A friendly guide to deploy a rails app using nginx (no docker needed)
Published: 2020-08-19 13:10:09

In past six years, I developed a huge skill set in ruby programming. Although it may seem a bit stupid, but after knowing such a great company like [GitHub](http://github.com) uses [Ruby on Rails](http://rubyonrails.org) as their backend framework and great FLOSS projects such as [Gitlab](http://gitlab.com) or [Mastodon](http://joinmastodon.org) are written in rails as well, you will find out it might be a smart choice. 

Although the whole process of building an app in rails is quiet easy and just needs a lot of search (or if you're like me, you can ask your questions in [rails subreddit](http://reddit.com/r/rails) and get help from a lot of great fellas there). Everything in Rails is pretty straight forward, except one things. __THE DEPLOYMENT__. It's really a hell of pain. But fortunately, I found a way which can work to some extent. 

## Gaining HTTPS access for your domain/subdomain 

In this tutorial, I will use [Ubuntu](http://ubuntu.com) and [Debian](http://debian.org) as an example. I'm sure the package names are mostly similar in other Linux distributions. In case of [FreeBSD](http://freebsd.org), I will give you the proper package name, do not worry. 

For having HTTPS on your domain, first you have to install `certbot`. As we're going to use nginx, this package will be enough : 

```
sudo apt install python-certbot-nginx
```
For FreeBSD, install `py37-certbot-nginx`. 

After certbot installation, you need to get certificates : 

```
sudo certbot --nginx -d example.com -d www.example.com 
```

_NOTE: Make sure that you set both root and www records on your DNS service provider._ 

Now, you have certificates! Let's deploy. 

## Installing ruby and rails 

Even on servers, I prefer [RVM](http://rvm.io). So, I skip the _installation_ part. 

## Deployment 

Are curious how I came up with this idea? It wasn't really easy though. One or two months ago, one of my friends at work just said _Mastodon has an LXC image available_. It made me a bit happy, 'cause I was thinking of my own instance of Mastodon. 

Two weeks ago, I made a simple rails app and wanted to deploy it. I took a look at docker and lxc images of other rails projects and understood nothing. But I knew that I have access to a server with Mastodon running. I still don't have my own instance, that server belongs to a friend of mine. I just connected to the server and found how it's deployed. So for deploying your app, follow the following instructions .

### Authenticity Token Problem

Open up your controllers and add this line to them :

```
skip_before_action :verify_authenticity_token
``` 

I'm not sure if this makes your app unsafe or not, and if adding it to the file `app/controllers/application_controller.rb` makes it global or not. Please let me know in the comments or where I shared the article with you. 

### Doing migrations and stuff 

I assume you know that you should do database migrations, asset compilations, etc. So I skip this part as well. 

### Running the app 

Fine, for running the app, I usually set `RAILS_ENV=production` in `.bashrc` or `.zshrc`, depending on the shell I use. After that, I open a `screen` session like this : 

```
screen -S rails-app-appname
```

then, I run my app : 

```
rails s -b 0.0.0.0
``` 

And by pressing `CTRL + A` then pressing `D`, I deatch from that session. I suggest this way for you as well. 

After running your app, just edit nginx configurations as following. 

First, open the configuration file : 

``` 
sudo vi /etc/nginx/sites-enabled/default
```

Then, look for your domain name (`certbot` adds your address to this configuration file). Under the server section which includes your domain name, just create this : 

```
   location @railsapp {
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto https;
        proxy_set_header Proxy "";
        proxy_pass_header Server;
        proxy_pass http://127.0.0.1:3000;
        proxy_buffering off;
        proxy_redirect off;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        tcp_nodelay on;
}

```

And then modify your root address to the `public` folder of your project. 

For example on one of my server, the default root is `/home/git/www` and I have changed that to `/home/my_user/rails_app/public` for that particular domain name. 

Then, make your root location like this : 

```
location / {
    try_files $uri @railsapp;
}
```

After that, do this : 

``` 
sudo systemctl reload nginx
sudo systemctl restart nginx
```

on FreeBSD (or Linux distributions without `systemd`) just do this : 

```
sudo service nginx restart
``` 

And happy using your app! 

## Why not docker? 

It's a personal preference I believe. I have a server with two gigabytes of RAM, and to my experience, these container solutions waste a lot of RAM. Also, for one who doesn't know how to work with docker (specially myself!) it will be really hard to get things work fine. Such as database connections, etc. 

In conclusion, if you have enough knowledge and resource, using docker might be even a better choice. But if you like the classic ways, I wrote this article for you. 

Happy coding :-)