This post explores how to deploy your first Solidus application ( the best eCommerce framework available in Ruby land) to DigitalOcean (one of the top Infrastructure as a service provider that puts the developers at the center). You will use the services provided by DigitalOcean, like Droplets and Managed Databases. This post is entry-level, you don’t need to be an experienced software developer to follow this. We are going to follow a step by step approach with lots of screenshots, and code snippets. So without further ado, let’s get started!
The first step is to create a Solidus application, to do that you can use the Solidus guide as reference.
If you prefer to just get started we have created a repository on Github ready to use, you can find it here.
On your local machine the application should look like this:
By the end of this post, you’ll be able to see this very same page online.
Now it’s time to prepare the deployment environment on DigitalOcean. DigitalOcean is an Infrastructure as a service provider, this means that you can rent the infrastructure we need for our application from DigitalOcean with just a click.
To be more specific we are going to need two main components for our application:
- A server to host our code.
- A database to keep our data safe.
DigitalOcean has two services that are perfect for our needs:
- Droplet: an easy, fast, and flexible compute unit. You can imagine this to be a small server that you can use as you want.
- Managed Databases: a worry-free database hosting. You can imagine this to be a database ready to use, you don’t have to worry about installation and maintenance.
Create the infrastructure
We are now going to create all the infrastructure we need on DigitalOcean.
First of all, you need to go to the DigitalOcean homepage and sign in, or sign up if you don’t already have an account.
Create the Database
Now that you are logged in, you are going to create the database.
We are doing this first because it’s your new database it’s going to take a while to become available, so we can work on other stuff while we wait for this to be ready.
From the homepage, you have to go to the
Databases section (arrow 1).
Databases sections, you need to click on
Create a Database Cluster
You can leave all the default values on the creation form, just scroll to the
bottom of the page and click on
Create a Database Cluster.
Note that DigitalOcean will create a default database inside your installation with a default admin user inside it. For this tutorial, we are going to use this database and user. In a real-world scenario I would suggest the creation of a custom database with its own admin user to improve the security of the system. You can do that through the database management UI.
Once created you will see the database management UI, you can skip the getting started section.
In the image, you can see the database management UI. Please note 2 things, pointed by the arrows in the image:
- Arrow 1: The credentials for your database, we are going to need them to configure our application.
- Arrow 2: At the moment your database can receive connections from all the internet, this is not ideal from a security point of view. We are going to fix this later.
Now your database is provisioning, while we wait for it to be ready we can create our server.
Small note on DigitalOcean Managed Databases
The service Managed Databases creates a cluster of databases for you. For this tutorial, you don’t need more than 1 database, but for a production application maybe you can consider creating a cluster with more than 1 database to be protected against outage, and to improve your disaster recovery capabilities.
You can read more about this on their documentation.
Create the Server
Now we are going to create our server, to do this you will use the DigitalOcean Droplet service.
From the homepage, you have to go to the
inside it click on the
Create Droplet button.
You can leave all the default values selected inside the form, you are going to use an Ubuntu image for the server. You need to add an ssh key during this process, the UI will guide you through the steps needed to do that.
Once created you will see the Droplet management UI.
Let’s secure our database access
Now that you have created the server we can secure our database. We want the database to accept connections only from your newly created Droplet.
You have to take note of your Droplet’s name, it will look
something like this
ubuntu-s-1vcpu-1gb-fra1-01, you can find this on
the Droplet management UI.
Now head back to the database management UI, from there:
- Click on
Settings. (Arrow 1)
Trusted sourcesput the name of your Droplet inside the autocomplete field. (Arrow 2)
- Click on
Save. (Arrow 3)
Now the only connections accepted by your database are the ones coming from your Droplet.
Configure the Droplet
Now that the infrastructure is up and running we have to install the application on the server.
Your Droplet is just a plain server running Ubuntu, to run your application on it you need to:
- Make sure that all the packages installed on the Droplet are updated.
- Install all the dependencies needed to run the application.
- Clone the application repo on the server.
- Configure the environment variables needed by the application.
- Setup the application’s server and database.
- And finally run the application.
It’s sound like a lot to do, but you’ll see that it’s easier that it looks like.
Login inside the Droplet
To work on the Droplet you need to connect to it, that’s exactly why you added an ssh key during the configuration.
To login inside the droplet you can run the following command:
ssh root@<YOUR DROPLET IP ADDRESS>
You can find your Droplet IP address on the Droplets management UI section of the DigitalOcean dashboard.
Updating Droplet packages
The Droplet is just a plain server with an Ubuntu distribution installed on it, to update all the packages on it you can launch the following command:
apt update && apt upgrade -y
This will make sure that the system is updated, keeping you server updated it’s a good practice, and can help your system to stay secure.
Install all the packages needed
You now have to install all the packages necessary to run Ruby and Ruby on Rails on the system.
There are quite a bit of packages needed, you can copy and paste the command below to install all of them:
apt-get install git-core zlib1g-dev build-essential libssl-dev libreadline-dev libyaml-dev libsqlite3-dev sqlite3 libxml2-dev libxslt1-dev libcurl4-openssl-dev software-properties-common libffi-dev imagemagick nodejs ruby npm ruby-dev libpq-dev -y && npm install -g yarn
gem install bundler rails
To check if everything is been installed correctly you can run the commands bellow, you should see a version number for every tool installed:
ruby -v bundle -v rails -v node -v yarn --version
Clone the application repository
Now you are ready to clone the application inside the server. If the repo is public you can clone it using HTTPS. If it’s private you have to generate an ssh key for the Droplet, and add it to GitHub (or the repository provider that you are using).
For a production application, I’ll suggest configuring a dedicated ssh key for your Droplet, and use it to clone the repository.
For example, if you are using our public repository you can run this command:
git clone https://github.com/nebulab/digitalocean-solidus-demo.git
Set the environment variables
We configured our example application to use environment variables to connect with the database, you can see the configuration on the repository.
As you can see from the configuration file we need to set 5 environment variables:
DATABASE_HOST DATABASE_PORT DATABASE_NAME DATABASE_USERNAME DATABASE_PASSWORD
Do you remember when earlier I talked about database credentials created by DigitalOcean? Now it’s time to use them.
You can add all the variables to our Droplet environment running the following command, remember to replace the placeholder with the information provided to you by DigitalOcean:
echo 'export DATABASE_HOST="<your_digitalocean_database_host>"' >> ~/.bashrc echo 'export DATABASE_PORT=<your_digitalocean_database_port>' >> ~/.bashrc echo 'export DATABASE_NAME="<your_digitalocean_database_database>"' >> ~/.bashrc echo 'export DATABASE_USERNAME="<your_digitalocean_database_username>"' >> ~/.bashrc echo 'export DATABASE_PASSWORD="<your_digitalocean_database_password>"' >> ~/.bashrc
You also have to set the variables to tell Ruby on Rails to treat this server as a production environment, and Puma to expose the application using the default HTTP port:
echo 'export RAILS_ENV="production"' >> ~/.bashrc echo 'export PORT=80' >> ~/.bashrc
After this we have to reload our
shell, you can logout and login again
inside the Droplet, or you can run:
To verify that the variables are set correctly run:
echo $DATABASE_HOST echo $DATABASE_PORT echo $DATABASE_NAME echo $DATABASE_USERNAME echo $DATABASE_PASSWORD
You should see all you database information.
Setup our application
We have almost done, now you have to go inside the directory where your repository is cloned.
From there you should install all the gems needed, to do that just run:
bundle && yarn install --check-files
This can take a while, you can go and grab yourself something to drink because you have done a lot of work and you deserve it.
Last, but not least, you have to compile the assets. To do that you can run the command:
bundle exec rake assets:clobber && bundle exec rake assets:precompile
Adding security and setting up the database
Our application needs a secret key to run. How to manage the secret key correctly, and secrets in general, is outside the scope of this article. You can find more on the official Ruby on Rails Guide.
To generate a secret key for your application you can run:
EDITOR="nano --wait" bin/rails credentials:edit
Now you need to load the database schema of the application, and setup the seed data inside it. To do that run the following command:
bundle exec rails db:schema:load db:seed
Don’t worry if it takes a while, you are loading a lot of data inside the database, and you are using the cheapest option offered by DigitalOcean it’s normal. Just relax and get ready for the last step.
Launch the application
Everything is finally ready, you can launch you application with the command:
bundle exec rails s
This will launch Puma, and expose your application to the internet. From the Droplet management UI copy your Droplet IP address, use your browser to navigate to it, and you should see your application up and running!
Road to production
Your application is finally online, congratulations! Take a moment to appreciate all the things you have done to accomplish this:
- You started from a local working application.
- Bootstrapped your server and database.
- Configured your server.
- Configured your app.
- Launched the app and made it available to the internet.
This is great, but it’s just a starting point. To be used in a real production environment our deployment needs some more work.
In the following sections we introduce the improvements needed to make our deployment production-ready.
Improving the Droplet configuration
If you want to use your Droplet for production you need to improve the configuration to make it secure and stable for a real-world scenario. You have to:
- Setup a firewall.
- Setup a reverse proxy, using tools like NGINX.
- Create a user for the deploy, instead of using the root user.
- Add SSL certificate to enable HTTPS for the application, using tools like Certbot.
- Isolate the installation of Ruby, and the bundle gems with tools like Rbenv
- Use a proper key to store the secrets.
- Set proper credentials for the Solidus store’s admin user.
Automate all the things
Doing all these installation steps by hand is boring, and error-prone. You can avoid it using a combination of tools to automate the creation, provisioning of the server, and deployment of your application.
One tool that you can look at for deploy automation is Capistrano, it’s quite popular inside the Ruby on Rails community.
You can integrate Capistrano with a CI/CD tool like CircleCI to enable the continuous deployment of your code.
With Terraform you can automate the creation of the infrastructure needed by your application, the Droplet and database. With Ansible you can automatically install all the packages you need on your Droplet.
Uploading files to an external storage
Right now the application is storing all the static files of the Solidus store on the local hard disk, this is not ideal because if the Droplet goes down you risk losing all the data.
To avoid this you can use external static file storage services, for example DigitalOcean provides Spaces an S3-compatible object storage with a built-in CDN that makes scaling easy, reliable, and affordable.
If you enjoyed this tutorial please share it with the world, if you want to know more leave a comment and start a conversation.