How to add a Rails application to an nginx server

by Jason Swett,

This is part 3 of my series on how to deploy a Ruby on Rails application to AWS. If you found this page via search, I recommend starting from the beginning.

Overview of this step

In this step we’re going to clone our Rails application, make sure the server’s Ruby version matches the application’s Ruby version, and install the application’s dependencies.

1. Clone the application

For the rest of this tutorial I’m going to use a certain Rails application of mine called hello_world. Its repo is public, so feel free to use my app instead of yours for practice if you want.

cd /var/www
sudo git clone https://github.com/jasonswett/hello_world
cd hello_world

2. Install the right version of Ruby

When we set up nginx and Passenger in the previous step, we configured the server with Ruby 2.5.

Unfortunately, my hello_world application uses Ruby 2.6.5, so Ruby 2.5 isn’t going to work. We could have configured Ruby 2.6.5 from the start but I didn’t want to add more steps and make things more confusing.

We could install Ruby any way we want but I’m going to use RVM.

sudo apt-get update
sudo apt install -y gnupg2
gpg2 --keyserver hkp://pool.sks-keyservers.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB
curl -L get.rvm.io | bash -s stable
source ~/.rvm/scripts/rvm
rvm install 2.6.5

3. Configure nginx to use the new Ruby version

Now we need to get the path of the Ruby we just installed.

passenger-config about ruby-command

Copy and paste the Ruby path (for me it was /home/ubuntu/.rvm/gems/ruby-2.6.5/wrappers/ruby) into /etc/nginx/sites-enabled/default.

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

Here’s what my full /etc/nginx/sites-enabled/default looks like for reference.

server {
        listen 80 default_server;
        listen [::]:80 default_server;
        
        root /var/www/hello_world/public;
        
        index index.html index.htm index.nginx-debian.html;
        
        server_name _;
        
        passenger_enabled on;
        passenger_ruby /home/ubuntu/.rvm/gems/ruby-2.6.5/wrappers/ruby;
}

4. Bundle install

Before we can serve our Rails app we need to install its dependencies using bundle install. Before we can do that we need to install Bundler.

sudo gem install bundler

Also, I’m using PostgreSQL, and in order to successfully install the pg gem, I need to have libpq-dev installed.

sudo apt-get install -y libpq-dev

Now we can bundle install.

bundle install

5. Set proper permissions

In order to do its business, the nginx user, www-data, needs to have ownership of our project directory.

sudo chown -R www-data:www-data .

6. Verify that this step worked

Lastly, we’ll verify that everything we’ve done so far has worked.

The app can’t be served yet because we haven’t yet done all the necessary steps, so we can’t verify the success of this step by checking to see if the app can be served. All we can do is check to see that the error message we get when we try to serve the app is the error message we expect.

Let’s tail the nginx log file so we can see whatever errors that come across.

sudo tail -f /var/log/nginx/error.log

Now visit your EC2 instance’s URL in the browser. What will almost certainly happen is you’ll get some sort of error. Below is the expected error.

Error: The application encountered the following error: Missing `secret_key_base` for 'production' environment

If you see the above error regarding secret_key_base, you’re all set for this step. If you get a different error, there’s a problem.

Now we can move onto the next step, setting up Rails secrets.

16 thoughts on “How to add a Rails application to an nginx server

  1. Alberto

    I followed the steps and I managed to run bundle install without problems, but there are no errors on /var/log/nginx/error.log and the nginx page is still displayed. Nginx and passenger are working but It looks like the rails application is not running.

    Reply
    1. Jason Swett Post author

      The next thing I would check in that case is whether the `root` directive in `/etc/nginx/sites-enabled/default` matches where your Rails application is located on the server’s filesystem.

      Reply
  2. Andrew

    Hey Jason,

    I’m on my third attempt (having to start over from Part 1) and finally think I’m good through this Part 3, but now like some of the other commenters I have no errors when tailing the nginx log file.

    When checking my /etc/nginx/sites-enabled/default I’m seeing
    root /var/www/html;

    I’m not sure where to check to see where my Rails application is located on the server’s filesystem. How can I see this?

    Should I update my /etc/nginx/sites-enabled/default to
    root /var/www/my_app/public;
    ?

    Really appreciate you putting together this guide. Thanks in advance for your help!

    Reply
    1. Jason Swett Post author

      Regarding where your Rails application is, you can see that in step one I CD’d into `/var/www` and then cloned my `hello_world` project. So in my case my project is located at `/var/www/hello_world`. If you followed that step then that’s where your Rails app should be too.

      And yes, if you’re using your own app and not my `hello_world` app, then you should change `/var/www/hello_world/public` to `/var/www/my_app/public` where `my_app` is of course whatever your app is called.

      Reply
  3. Matthew Sells

    Hello Jason –

    Great article! This has been immensely helpful in setting up a server. I’m attempting to set up a new instance of an application from Heroku on AWS. I was able to get everything set up and running, connection to the DB, etc. However, I’m experiencing the following issue:

    Originally when I was accessing the public DNS or just the IP of the EC2 instance I would get a Passenger error because of the secret key not being found (as expected). After that was fixed I received another error because I was missing some ENV variables (also expected).

    The good thing is that adding the env variables fixed those errors. However, after I did that when I attempt to reach the site it stalls on a blank screen and eventually times out. I’m confident the settings were originally working because I was seeing the “welcome to nginx” page originally, then received the errors when I switched the root url to my Rails application’s public folder.

    I’ve traced /var/log/nginx/error.log and /var/log/nginx/access.log when hitting the endpoint but am not receiving any logs. Do you have any recommendations for debugging this? I’m new to nginx and passenger. Thank you very much for any suggestions!

    Reply
    1. Jason Swett Post author

      Thanks! If you’re not seeing anything in the nginx logs then I don’t know whether requests are actually making it to nginx in the first place. So I’d try to answer that question: is traffic making it to nginx or not?

      If I were you I’d switch from testing via the browser to testing via cURL. The reason is that sometimes it’s unclear in the browser whether the request being sent is HTTP or HTTPS, and that can make a big difference.

      I would also use an open port checker (e.g. https://www.yougetsignal.com/tools/open-ports/) to see if ports 80 and 443 are open.

      Lastly, I have a hunch about Rails’ `force_ssl` setting. I vaguely remember having a problem with that myself at one point, with symptoms similar to yours. If you have that set to true, try setting it to false.

      Reply
  4. Joe

    For the posters who are seeing the nginx server still running after making changes: Try rebooting your EC2 instance. There’s probably a quicker way to do this, but rebooting the EC2 instance allowed my rails server to boot properly(well…get the error described) and get rid of the nginx screen.

    Reply
  5. steven aguilar

    Hey Jason, thanks for this amazing article. I noticed when I check the error logs the following

    Error: The application encountered the following error: bootsnap doesn’t have permi
    ssion to write cache entries in ‘/var/www/wsbapp/code/tmp/cache/bootsnap-compile-cache’ (or, less li
    kely, doesn’t have permission to read ‘/var/www/wsbapp/code/app/controllers/spacs_controller.rb’) (B
    ootsnap::CompileCache::PermissionError)

    It seems theres no permission to access the Cache. when I check I see www-data is the user and group owner of the application. I tried telling Passanger to run with
    passenger_user www-data
    passenger_group www-data
    so all permissions are provided but this stills doesn’t solve the problem. when you run the command sudo chown -R www-data:www-data .
    you didn’t need to tell passenger anything about how to run so I’m curious as to why this didn’t work for me. Any idea on which direction I can go to fix this?

    Reply
    1. Jason Swett Post author

      Thanks! There are two things I might try:
      rm -rf /var/www/wsbapp/code/tmp

      And if that doesn’t work, I might try this:
      chmod 755 /var/www/wsbapp/code/tmp

      Reply
  6. steven aguilar

    Jason, another question. I get the following error

    chdir(“/tmp/passenger.U8dWSAn”) failed: No such file or directory (errno=2)2021/01/15 22:22:14 [error] 20504#20504: *5 open() “/var/www/html/top-stocks” failed (2: No such file or directory), client: 186.83.232.237, server: _, request: “GET /top-stocks HTTP/1.1”, host: “ec2-xxxxxx-53.compute-1.amazonaws.com”

    I’m deploying an RAILS API only, so when I ls in public, all I have is csv files.
    Is there anything I need to do?

    Reply
  7. Aiden

    Hello,
    I am trying to follow this article and deploy my own code from a private github repository.
    The issue that I am having is that sudo is using the wrong generated ssh key. I dont want to change the permissions of the folder, and I cant seem to be able to add a key to /root/.ssh/

    Do you have any idea what I should do?
    Thanks in advance

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *