Deploying Rails 7 to Linode with Dokku
In this article, I will go through the steps to launch a Rails 7 app using Linode and Dokku. This should be the exact same process for other providers such as Digital Ocean or Vultr (and more not named). I chose Linode because it is super easy to setup an account and the pricing is the best I have seen for the particular server setup I like to run.
First, get a Linode Account
Super easy to get an account. They also have Google auth which I prefer. At the time of this writing, they are offering a $100 credit too. Click here to visit Linode.
Create a Linode
It should go without saying, that Linode calls their server stack instances as Linodes. In the case of Digital Ocean, you would create a Droplet. For my specific case and this tutorial, I am using Linode's Nanode 1 GB plan which is $5 a month.
Point Your Domain Name to the New Server
You will get an ip address once your server is provisioned and running. You will need to create an A record in your DNS entry that points to your server's IP address. See below where I have my A record pointed to my server IP. I also have the CNAME record for "www" pointed to the main domain.
Set up the Server
Open your terminal and SSH into the server
# terminal $ ssh [email protected]<server ip from linode>
Now, get the latest version of Dokku on the server:
# terminal # for debian systems, installs Dokku via apt-get wget https://raw.githubusercontent.com/dokku/dokku/v0.28.1/bootstrap.sh; sudo DOKKU_TAG=v0.28.1 bash bootstrap.sh
This is the latest version as of the time of this writing. Be sure to check here to see if there is a newer version.
Follow the instructions provided after install to make dokku an admin with rights to your ssh keys.
Set up Swapfile, if needed
Depending on the size of your cloud server, you may want to create a swapfile to handle the deployments better and not run out of resources. When using the smallest droplet on Digital Ocean, I would always use this tactic. With Linode, their smallest instance already has a swapfile attached. In the case you need to make one, follow the instructions below.
# SSH terminal to Linode server sudo fallocate -l 4G /swapfile sudo chmod 600 /swapfile sudo mkswap /swapfile sudo swapon /swapfile sudo sh -c 'echo "/swapfile none swap sw 0 0" >> /etc/fstab'
Add App to Dokku
Be sure to replace myapp with your app name
# SSH terminal to droplet server dokku apps:create myapp
Add Heroku buildpacks to avoid setting up any dependencies manually.
#SSH terminal to Linode server dokku buildpacks:add myapp https://github.com/heroku/heroku-buildpack-ruby.git # Add this if you plan on using Active Storage dokku buildpacks:add myapp https://github.com/heroku/heroku-buildpack-activestorage-preview # Add this if you plan on using Node JS dokku buildpacks:add myapp https://github.com/heroku/heroku-buildpack-nodejs.git
Set up ENV variables on the server:
# SSH terminal to Linode server dokku config:set myapp RAILS_ENV=production dokku config:set myapp RAILS_MASTER_KEY=<master_key_from_app>
Your master key will be located in a file called "master.key" in your app's config folder.
Get Postgres up and running:
# SSH terminal to Linode server dokku plugin:install https://github.com/dokku/dokku-postgres.git dokku postgres:create myapp_db
Link Postgres DB to app:
# SSH terminal to Linode server dokku postgres:link myapp_db myapp
Add Procfile to Your App
You need to add a "Procfile" to the root of your app directory. It must be spelled as Procfile with the capitalization on the P. Add the following to your Procfile declarations:
# Procfile # this tells the app upon deployment to run Puma to serve the app web: bundle exec puma -C config/puma.rb # add this line to automatically run migrations upon each deployment release: bundle exec rails db:migrate
Add Domain(s) and SSL
Now, add domain(s) to your app.
#SSH to Linode server dokku domains:add myapp example.com dokku domains:add myapp www.example.com # If it were subdomain dokku domains:add myapp myapp.example.com dokku domains:add myapp www.mayapp.example.com
Acquire SSL Encryption and Certificate.
# SSH to Linode server dokku plugin:install https://github.com/dokku/dokku-letsencrypt.git dokku config:set --no-restart myapp DOKKU_LETSENCRYPT_EMAIL=[email protected] dokku letsencrypt:enable myapp # Add cron job so certificate automatically renews dokku letsencrypt:cron-job --add myapp
Definitely add the cron job. Let's Encrypt's certificates are only valid for 3 months, so you will want to have the cron job handle getting the new one automatically to keep your domain from experiencing any disruptions.
Deploy Your App
Almost ready to roll. Now, we just need to add a remote repository.
# Terminal within your app folder git remote add dokku [email protected]_ADDRESS:myapp
With this setup, it is using the IP Address. If you domain is resolving already and correctly, you could use "myapp.com:myapp" for example. But for now, I will just stick with the IP address.
Deploy app just like you would on Heroku but with Dokku:
# Terminal within your app folder git push dokku master
Dokku runs one instance of web process by default. You can up that by using this command.
# SSH to Linode server dokku ps:scale myapp web=2
App Changes and Future Deployments
You should be good to go and if you enabled swap, your experience should be as smooth as using Heroku, just as mine has been.
Going forward, after you commit changes in git inside your app, all you should need to do is to run the "git push dokku master" command and your site will deploy the latest version.