Host Ruby on Rails app with Digital Ocean

Host Ruby on Rails app with Digital Ocean

Hey everyone, thanks for reading my article, I will show you how to deploy a Ruby on Rails app to Digital Ocean. I will also cover setting up nginx to make action cable work, setting up redis-server and enabling SSL connections to allow HTTPS links to work nicely!

The first thing you will need is a Ruby on Rails app, you should already have own ready to release to production if not you can create one with the rails new command.

rails new my-app -d postgresql -c tailwind         

I am using Postgresql because that is the library I usually use and its preinstalled with the Digital Ocean Rails 1 Click Installer!

Then you want to upload your code to Github or a similar service to store your code so we can download it on our Digital Ocean server.

Now that this is setup we need to create a new Digital Ocean droplet we will do this by using the Rails 1 Click Installer which already has Rails setup.

https://marketplace.digitalocean.com/apps/ruby-on-rails

Once you go to this page click on "Create Ruby on Rails Droplet"

this will bring you to the page where you can configure your new Droplet

1. Choose A Region

!tip - Try and choose a region that's close to where you and your users live so the latency is better

2. Choose a CPU option

this depends on your budget and how much resources your App needs but for a standard project any of the options will work! I usually choose the Premium Intel cheapest option for $8/month.

3. Create or choose an SSH key

you can create an SSH key with your computer so that you can SSH into the server from your computer

4. Create the Droplet

Wallah! Now we have created our first Digital Ocean droplet it should now bring you to your droplets page and you will see your droplet loading. It needs to setup the first time you create it. This usually only a minute.

Now that we have our droplet created lets enter into the machine either using the Web option ( which I use ) or directly SSH from your laptop using the private IP.

To use the web option click on the Droplet and then click on the "Access" tab

Now you should see an option for Launch Droplet Console. Click this and it will launch a session into the VM.

Now you should see a message like this

This will give you information on how the server is currently configured with file locations for Nginx logs, and the file that is used to manage your Rails server

/etc/systemd/system/rails.service

You can edit this file to choose which rails app is running as a system service

[Unit]
Description=ExampleApp
Requires=network.target

[Service]
Type=simple
User=rails
Group=rails
WorkingDirectory=/home/rails/example/
ExecStart=/bin/bash -lc 'bundle exec puma'
TimeoutSec=30s
RestartSec=30s
Restart=always

[Install]
WantedBy=multi-user.target        

By Default this is what your file will look like and its pointing to an example app We can check the status of this service by running

systemctl status rails.service

I got this message which means the app is running we can view it by going to the public IP Address of your Droplet which was in the message when you logged in to the droplet and also back on the web view

If we go to this right now we will see the example app

Lets turn this off so that we can start our server without any issues

systemctl stop rails.service        

So now lets add our app and make it work!To do this we first need to log into the 'rails account' in our server by typing

su - rails        

This will change the console name to something like rails@rubyonrails

and if you type ls you will see the only folder we have is example which is the default app.

Now we need to add our code by cloning it from github

git clone https://github.com/enochtamulonis/demo-app-yt        

Replace the url with your github repo

Now our app is downloaded to our machine we can cd into the app and start the server to test it out! make sure that the other server was turned off in the step above^^

bundle install # install the gems for our app
rails s        

If you need to install a custom ruby version its easy and RVM is already installed

for example if your app needs ruby 3.3.0 then run this

rvm install "ruby-3.3.0"        

Now we have our app installed and should be running correctly! we can view it by going to our ip address for example mine is https://137.184.44.103/

And we will see our app is live and working! TADA!!

If you see an error like this that the server already is running its because you need to stop the server from steps above

exit # go back to the main level of the vm
systemctl stop rails.service # stop the example rails server
su - rails # go back to the rails account        

Note that currently the server is still running in development mode to make it run in production mode we can set the RAILS_ENV environment variable we also need to pass a SECRET_KEY_BASE variable you would get this if you are using rails credentials its inside of your production or main credential file.

SECRET_KEY_BASE=1 RAILS_ENV=production rails s        

For my app I'm not using credentials but if you are then you also need to pass the RAILS_MASTER_KEY to decrypt the credentials file

SECRET_KEY_BASE=1 RAILS_MASTER_KEY=your-key-here RAILS_ENV=production rails s        

I did see an error because I'm using Tailwind it was excepting the files to be compiled

To fix this we just need to compile our assets so stop the server and run this

rails assets:precompile        

Then we can restart the server and see it is working and everything looks correct.

Now to setup our domain we need to first have a domain to use I'm using one from Godaddy

Then lets go to digital ocean and click the green "Create" button at the top right corner

Click on the "Domains/DNS" button then in "Enter your domain" field add your website for me I'm using blog-genius.com

Next you will setup your domains to route to your droplet by configuring the hostname we want to support two urls www.blog-genius.com and blog-genius.com without the WWW to do this we add two hostname records.

For the first one enter '@' and choose the droplet it should route to and press Create record

For the second route type in www and route it to the same droplet and press create record

Okay now we have our records configured on digital ocean now to set it up with Godaddy to reroute our domains to the server all we need to do is change the name servers for our domain on godaddy to do this go to your godaddy account

Click on products and then go to the domain you want to use and click DNS

Then go to the "Nameservers" tab and click "Change Nameservers" then click "I'll use my own nameservers" and in here you will add the 3 name servers for digital ocean


Boom! Now everything is set up and pretty soon we will be able to go and view our domain at www.blog-genius.com or blog-genius.com since we support both :))

We are able to access these pages with https:// but if it uses https:// then it will timeout and not work because we have not implemented SSL secure connections yet! Lets do this now

Lets add a custom server block with nginx first lets exit out of the rails user into our main VM section by typing so that our console says we are on the root account

root@rubyonrails

First we create a new directory for our nginx server block this should use our domain name for the folder name replace blog-genius with your domain name

sudo nano /etc/nginx/sites-available/blog-genius        

inside of here is where we are going to add our config for the app I will add a simple config which we will add more to after we generate the SSL crede

server {
    server_name blog-genius.com www.blog-genius.com;
    
    listen 80;
    listen [::]:80;

    location / {
        proxy_pass https://127.0.0.1:3000;
        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 $scheme;
    }

    location /cable {
      proxy_pass https://127.0.0.1:3000/cable;
      proxy_http_version 1.1;
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection "Upgrade";
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header Host $http_host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-Proto https;
      proxy_redirect off;
  } 
}        

This will match the domain and redirect all requests to our rails app running on port 3000

It also adds the code to make websockets connections work to /cable with our upcoming changes to SSL

Next, let’s enable the file by creating a link from it to the sites-enabled directory, which Nginx reads from during startup:

sudo ln -s /etc/nginx/sites-available/blog-genius /etc/nginx/sites-enabled/        

To avoid a possible hash bucket memory problem that can arise from adding additional server names, it is necessary to adjust a single value in the /etc/nginx/nginx.conf file. Open the file and uncomment this section

server_names_hash_bucket_size 64;

Now we can test to see if everything was okay and no syntax error

sudo nginx -t        

It should say test is successful now restart nginx to enable changes

sudo systemctl restart nginx        

Now we can test if this works by restarting the server lets edit the service file we mentioned earlier so that we can start the server service

vi /etc/systemd/system/rails.service        

WorkingDirectory=/home/rails/example/

To your apps folder name in the rails directory

WorkingDirectory=/home/rails/blog-genius/

You can also change the start command

ExecStart=/bin/bash -lc 'bundle exec puma'

to our command from earlier

ExecStart=/bin/bash -lc 'RAILS_ENV=production SECRET_KEY_BASE=1 rails s'

Now we need to reload the daemon and then we will be able to restart the service

systemctl daemon-reload
systemctl restart rails.service        

We can check if the service started successfully with

systemctl status rails.service        

It should say active and you can view the domain still. note that we still have not added SSL connections so HTTPS will not work yet only HTTP we have only added server blocks which will make it easier to configure NGINX with our certificate

First thing we need to do to setup our SSL certificate is install certbot

sudo apt install certbot python3-certbot-nginx        

Now were gonna obtain an SSL certificate using certbot like this

sudo certbot --nginx -d blog-genius.com -d www.blog-genius.com        

Now that this certificate is installed we can add it into our server block and finish up! It will add the needed SSL code to your server block for you

listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/blog-genius.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/blog-genius.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot        

Now lets test nginx for syntax errors

sudo nginx -t        

It should say test is successful now restart nginx to enable changes

sudo systemctl restart nginx        

Boom! TADA! You can now go and view your app with HTTPS enabled and see the security icon

Hope you enjoyed this article I know its a long one but It is very awesome to be able to deploy your Rails app for $8 nowadays and what you get is way better than anything Heroku! You can install anything on your VM like AI models and more!

要查看或添加评论,请登录

社区洞察

其他会员也浏览了