You’ve just setup your production server, but still haven’t deployed your app? Then this the right place for you. You are going to learn how to deploy your app to remote server, deal with some config files, create staging environment and setup monitoring tools.
Capistrano is an excellent tool to automate your deployment process using Rake DSL. It allows you to deploy applications using various source control management systems like Git, run migrations on remote server, restart application and many more.
Let’s start with creating Rails application:
rvm-capistrano (for RVM integration) and
pg gems(for Postgres database) to your Gemfile:
1 2 3 4
NOTE: When writing this article, the current Capistrano version was 2.15.5 which I believe is buggy as I had some problems with authentication while deploying. If you have the same problem, use 2.15.3 version instead.
You should also uncomment this line:
And run bundle install.
Is my app secure?
Well, it depends. If you are the only person working on it, then you are safe. But if you aren’t, then your session secret is available to other people, which makes your app vulnerable to carefully crafted attacks and you should exclude it from your code repository. Initialize git repository in your application:
And add to your
.gitignore file the following line:
Database and staging environment config
Now, edit database configuration file (
config/database.yml), so it looks similar to this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
There is one extra thing in this config: the staging environment. We are going to use pre-production environment for testing purposes. If you want to share the same database between production and staging, then leave this config as it is.
You should also exclude
database.yml from your code repository, not only for keeping your passwords secret, but also to prevent overriding local configuration when fetching code from repository - add to
Staging environment should be close to production as much as possible, so copy the production.rb file and rename it to staging.rb:
To create configuration files, run
It will create two files:
Capfile. Start with editing
Capfile and uncomment this line:
Next, open the
deploy.rb remove the default content, copy & paste the script below and adjust it according to the comments.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
deploy directory in
config directory and add
staging.rb files there. You have to specify paths, where the production and staging app instance will be deployed. Let’s edit the
That’s a basic configuration that should be sufficient in most cases. But Capistrano is a really sophisticated tool, you can specify diffrent servers for staging and production environment, diffrent git branches, diffrent repositories and many more. Just specify different settings in
staging.rb if you need to.
Before deploying your app, you have to setup git repository. We will create just an empty repo in
/home/deploy/repos directory on remote server:
Keeping the Git repositories on deploy user might not be the best idea, especially when you want to give other people access to the repo, but it sufficient for demonstration purposes. In other cases, you should rather create seperate git user with a limited shell (git-shell) or use some sophisticated tools like Gitolite if you need to.
Now we can commit all changes and deploy our application:
1 2 3 4
You are ready to deploy our application, but before that you need to setup databases and http server configuration. If you have any problem, check this one out (remember about specifying appropriate rails_env). Firstly, let the Capistrano deal with creating all the neccessary directories in both staging and production environments:
Then check if directory permissions, utilities and other dependencies are correct:
In both cases you should have output ending with: You appear to have all necessary dependencies installed.
The last thing before deployment: we haven’t included
database.yml files in repo, so we have to copy them on remote server:
1 2 3 4 5
And you can deploy your application. Instead of
cap deploy, use
cap deploy:cold and
cap production deploy:cold - it will deploy the app, run all migrations and run deploy start instead of
Done! You have just deployed your application. Next time use cap deploy or
cap deploy:migrations to run migrations.
Monitoring with Monit
How do you know if everything is running correctly after deployment? Well, you don’t know, unless you install a monitoring tool. Monit is a great and easy to configure utility for managing and monitoring processes. Let’s start with installing Monit on remote server (I use CentOS Linux, there are some differences between distros, so the location of the files might be diffrent, e.g. on Debian, the configuration file is in
and edit the configuration file:
Read carefully all the comments to get familiar with Monit. Then specify your configuration, e.g.:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
There are a lot of available Monit recipies, e.g. here, so it is quite easy to setup. When you finish, restart Monit:
Or if you haven’t started it yet:
To check status of processes being monitored, run:
You don’t have to ssh on your server everytime you want to check the status, Monit comes with a very nice web interface. Here is a simple Nginx configuration, so that you will be able to access Monit via your-ip:1111/monit address:
1 2 3 4 5 6 7 8 9 10
Use password and username specified in Monit configuration.
After some time your Rails app logs and especially Nginx logs might be really large, so it is a good idea to somehow manage them. Fortunately, you can use system-built utility called Logrotate. Just open
/etc/logrotate.conf and paste the configuration below (remember about changing path to your application):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
Here is the options explanation:
- daily - rotate the logs every day
- rotate 30 - rotate logs 30 times, after that delete the oldest
- missingok - ignore if the file doesn’t exist
- compress - compress logs with gzip
- notifempty - leave file if the logs are empty
- delaycompress - postpone compression of the file to the next cycle
- sharedscripts - tell only once that the logs have been rotated, not several times for every group
- copytruncate - copy the log file and and truncate the original one
- postrotate [ ! -f /var/run/nginx.pid ] || kill -USR1 `cat /var/run/nginx.pid` endscript - tell Nginx that the logs have been rotated and use the new ones.
And that’s is it! Cron by default runs logrotate every day.