posted by Ayush Newatia
31 July, 2026
In the final part of this series, we’ll build upon the setup created in Part 2a and close the loop by deploying code from our machine to the server.
Part 2a covered the setup to serve Ruby apps, but that app was created on the server itself. To deploy code, we need a way to copy our project files to the server and reload the server process for the changes to take effect. Ideally, we also want to ensure the new code starts up correctly and is healthy, before switching traffic over to it (sometimes known as blue-green deploys).
At the end of the post, I’ll introduce Mimas, which automates everything discussed in this post. Hence, this post is largely theory and doesn’t contain code examples for every step. Although, this knowledge will stand you in good stead if you choose to build your own deployment tooling.
Here are the steps required for zero-downtime blue-green deployments:
- Copy the code to the server.
- Start a new server process with the deployed code.
- Health-check the new process.
- Switch the reverse proxy to the new server’s Unix socket.
- Gracefully stop the old process without dropping requests.
Let’s take this step-by-step.
Copying code to the server
Heroku popularised the git push technique to copy code to a server. Personally I’m not a fan of this method when deploying code to a VPS, because it uses the server as a build server. git push will send your project as-is to the server, and any artifacts that require building, such as JavaScript assets, or an entire static site, will need to be done on the server.
This creates more moving parts as build dependencies such as Node need to be installed on the server. I prefer to build the site locally, or on a CI server, and push the built files to the hosting server. The most efficient way to do this is to create a GZIP archive of all required files, and then use SCP to copy that to the server.
Starting and health-checking new server process
After we have the GZIPped code on the server, we can extract it using the tar -xf command. To start the server process, we’ll create a new systemd service for the release. The way we set up the server in Part 1 means that this can be done without sudo privileges.
When the new systemd service has been created and started, we’ll make a curl request to the new Unix socket to ensure it is running.
Switching the reverse proxy and stopping the old service
When the new service has been health-checked, we can change the Caddyfile to point to the new Unix socket, and reload Caddy. Caddy does this seamlessly without downtime, and gracefully completes any requests in-flight.
And finally, we need to stop and remove the old service. Both Puma and Falcon stop gracefully without dropping requests when SIGTERM is sent to the process, so we won’t lose any requests here either.
And that’s it, our new code will be up and running!
Automation
Doing all the above steps manually is a recipe for disaster. With so many things going on, this needs to be automated for reliability. I’ve created a CLI tool called Mimas which automates everything I’ve covered in this blog series, and is optimised for single server Ruby deployments.
Introducing Mimas
My goal with Mimas was to create a single solution for end-to-end deployments, from securing the server, to configuring log rotation, and everything in between. These were my goals when building Mimas:
- Securing the server, including creating the required user acccounts.
- Installing and configuring Caddy.
- Installing prerequisite software including Ruby.
- Deploying multiple sites on a single server.
- Deployment of static sites as well as Ruby apps.
- Creating systemd services to automatically start and restart web services.
- Zero-downtime and blue-green deploys.
- Configure log rotation.
It’s still early days so there are likely to be issues. All my static sites (including the blog you’re reading) are now hosted on a VPS and deployed using Mimas. I’ve also created an official Bridgetown plugin for it, so you can deploy your Bridgetown static or hybrid apps to a VPS easily!
While it works well with static sites and simple Rack apps, Rails support is currently untested. I’m planning to migrate one of my Rails apps off Render, and onto a VPS, so I will release an official Rails plugin for Mimas in the coming weeks based off that work.
Mimas is written in Ruby and works by running Bash commands and scripts over SSH. There’s nothing fancy going on under the hood. The code should be fairly easy to follow, and the Readme describes how it all works.
Docker is far too heavy-handed for most projects, and PaaS providers can be quite expensive for small-scale and side projects. I hope that Mimas helps self-hosting become a bit more accessible as a free all-in-one solution.

Comments
Nothing yet. Say the first thing.
Sign in to join the conversation.