Host Ruby on Rails app with Digital Ocean
Enoch Tamulonis
Senior Software Engineer Ruby on Rails, Javascript & Open Source experience
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.
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!