-
Notifications
You must be signed in to change notification settings - Fork 259
Deployment Guide
This guide covers how to setup the production environment for your BrowserCMS application. This setup should work for both:
- Apache (mod_rails) with Passenger
- Nginx with Passenger (though it's less well tested than Apache)
This guide is valid as of BrowserCMS 3.5.0.rc1.
In order for the CMS to send emails, you need to edit the following lines on production.rb:
# This should match the URL for your public CMS site.
config.cms.site_domain = "www.example.com"
# Configure your mail server host name
config.action_mailer.smtp_settings = {:address => 'mailserver.example.com', :domain => config.cms.site_domain}}
In order to make page caching work, you need to create two virtual hosts for your site. The desired endstate is to end up with two top level domains. For example, assuming our domain is example.com
, we want to have the following domains when we are done:
-
www.example.com
- The 'public' access to the site, which is uses page caching for speed. -
cms.example.com
- The 'admin' access to the site, which allow editors to make changes.
Its a good idea to set up a redirect from example.com
to www.example.com
for ease of access and SEO purposes. The main reason to use www.example.com
as the 'canonical' domain rather then dropping the www is due to some browsers (IE) having issues with cookies on example.com
being visible to cms.example.com
. Admin users will have hard to diagnose problems when they are logged in.
Some hosting setups may not like subdomains (or are harder to setup). You can run the CMS off a single domain by setting the following:
# In production.rb
config.cms.use_single_domain = true
This will disable all page caching though, which has performance implications.
Here is the sample configuration for Apache plus Passenger.
<VirtualHost *:80>
ServerName cms.mysite.com
DocumentRoot "/var/sites/mysite/public"
RailsEnv production
<directory "/var/sites/mysite/public">
Order allow,deny
Allow from all
</directory>
</VirtualHost>
<VirtualHost *:80>
ServerName mysite.com
DocumentRoot "/var/sites/mysite/public"
RailsEnv production
RewriteEngine On
# Uncomment for rewrite debugging
#RewriteLog /var/sites/mysite/log/rewrite.log
#RewriteLogLevel 9
#apache should serve cached pages
RewriteRule ^/$ /cache/index.html [QSA]
RewriteRule ^([^.]+)$ /cache/$1.html [QSA]
<directory "/var/sites/mysite/public">
Order allow,deny
Allow from all
</directory>
</VirtualHost>
Here is a sample configuration for Nginx.
server {
listen 80;
server_name cms.example.com
www.cms.example.com;
# remove 'www'
if ($host ~* ^www\.(.*)) {
set $remove_www $1;
rewrite ^(.*)$ http://$remove_www$1 permanent;
}
# point to public
root /home/example.com/www/public;
# if you use reverse proxy (in case of multiple rubies)
# point to your ip/port in location
# if you use only one ruby with passenger (for example REE) skip this location block
location / {
proxy_pass http://127.0.0.1:3001;
proxy_set_header Host $host;
}
# passenger related stuff
passenger_enabled on;
}
server {
listen 80;
server_name example.com
www.example.com;
# remove 'www'
if ($host ~* ^www\.(.*)) {
set $remove_www $1;
rewrite ^(.*)$ http://$remove_www$1 permanent;
}
# Cache Index HTML Files
if (-f $document_root/cache/$uri/index.html) {
rewrite (.*) /cache/$1/index.html break;
}
# Cache HTML Files
if (-f $document_root/cache/$uri.html) {
rewrite (.*) /cache/$1.html break;
}
# Cache Catch all
if (-f $document_root/cache/$uri) {
rewrite (.*) /cache/$1 break;
}
# point to public
root /home/example.com/www/public;
# if you use reverse proxy (in case of multiple rubies)
# point to your ip/port in location
# if you use only one ruby with passenger (for example REE) skip this location block
location / {
proxy_pass http://127.0.0.1:3001;
proxy_set_header Host $host;
}
# passenger related stuff
passenger_enabled on;
}
I believe there's a better way to do it. Main idea is to listen to domains and sub domains in one 'server' block, but if user comes from sub domain we should skip caching statements. Unfortunately nginx doesn't support multiple conditions neither nested "if's" to check whether request came from sub domain or not.
When you deploy your project to a remote server for the first time, you need to do migrate/populate the database on your production server. BrowserCMS provides a nice shortcut to setup your database in one go. After pushing your code's project, run:
rake db:install
Calling this task is essentially the same as calling rake db:create db:migrate db:seed
. Take note of the generated password for the cmsadmin user.
If you choose to copy a local database to your production server, make sure you change the default cmsadmin password to something non-guessable for security purposes.
If you plan to use Capistrano to deploy your sites, you will likely need to make some additional configuration changes.
The default location where files are stored is tmp/uploads, which means capistrano deployments will cause broken links after deploying. To fix this, you can reconfigure where files are stored to use a shared directory.
# In config/environments/production.rb
config.cms.attachments.storage_directory = File.join(Rails.root, 'uploads')
Then update config/deploy.rb (which Capistrano should generate) so that it creates an shared/uploads directory, and a symlink to it from within your project.
# In config/deploy.rb
task :link_shared_directories do
run "ln -s #{shared_path}/uploads #{release_path}/uploads"
end
after "deploy:update_code", :link_shared_directories
The binary data for uploaded files will be placed in shared/uploads and the CMS will serve the data from there.
For Rails 3/bundler, you need to tell capistrano to run bundle install after deployment. See "Bundler's Docs":http://gembundler.com/rationale.html and "this post":http://blog.josephholsten.com/2010/09/deploying-with-bundler-and-capistrano/ for some ideas into how to do that. The most common setup will be something like this though:
# In config/deploy.rb
require "bundler/capistrano
# This may not be necessary, depending on your server setup.
# To see other options, run cap --explain bundle:install
set :bundle_cmd, '/opt/ruby-ee/bin/bundle'