Skip to content
peakpg edited this page May 18, 2012 · 10 revisions

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 for BrowserCMS 3.5.0.rc1.

Configure the Production Environment

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}}

Setting Up Virtual Hosts

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.

Why not drop the www?

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. This creates issues with logins.

What if I want a single domain?

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.

h3. Apache Configuration

Here is the sample configuration for Apache plus Passenger.



  ServerName cms.mysite.com
  DocumentRoot "/var/sites/mysite/public"
  RailsEnv production
  
    Order allow,deny
    Allow from all
  



  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]
  
  
    Order allow,deny
    Allow from all
  

h3. Nginx

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.

h2. Using Capistrano to Deploy

If you plan to use Capistrano to deploy your sites, you will likely need to make some additional configuration changes.

h3. File Upload location

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
app.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.

h3. Configuring bundler

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'

h2. Setting up production database

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 @db:create, db:migrate@ and @db:seed@. Take note of the generated password for the cmsadmin user.

h3. Warning: Copying a local database

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.

Clone this wiki locally