Rails CI/CD with Dokku & GitHub Actions


As developers, we're always looking for ways to streamline our deployment process while maintaining security and reliability. Today, I'm excited to share my experience setting up an automated deployment pipeline for a Rails application using Dokku and GitHub Actions. This setup has transformed our deployment process from a manual, error-prone task into a smooth, automated workflow.
The Challenge
Managing production deployments can be tricky. You want something robust like Heroku but with more control over your infrastructure. Enter Dokku - a lightweight, open-source Platform as a Service (PaaS) that gives you Heroku-like features on your own server.
Prerequisites
Before we dive in, make sure you have:
A Dokku server set up and running
%[https://sulmanweb.com/rails-8-production-dokku-deployment-guide]
An existing Rails application deployed to the server
Administrative access to both the server and your GitHub repository
Setting Up Secure Deployment Keys
The first step in our automation journey is setting up secure SSH keys for deployment. This is crucial for allowing GitHub Actions to securely communicate with our Dokku server.
# On your production server
ssh-keygen -t ed25519 -f dokku
This command generates two files:
dokku
- Your private key (keep this secret!)dokku.pub
- Your public key (safe to share)
Next, we need to configure Dokku and the server to trust these keys:
# Add the key to Dokku
echo "YOUR_PUBLIC_KEY_CONTENT" | dokku ssh-keys:add github
# Add to authorized keys for additional security
echo "YOUR_PUBLIC_KEY_CONTENT" >> ~/.ssh/authorized_keys
GitHub Repository Configuration
With our keys in place, we need to store the private key securely in GitHub. Here's how:
Navigate to your repository's Settings → Secrets and variables → Actions
Create a new secret named
PRODUCTION_DOKKU_SSH_PRIVATE_KEY
Paste your private key content
This secret will be securely encrypted and only accessible during the deployment process.
The Magic: GitHub Actions Workflow
Now for the exciting part - setting up our automated deployment pipeline. Create or modify .github/workflows/ci.yml
:
deploy_production:
needs: [ test ]
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
runs-on: ubuntu-24.04
steps:
- name: Cloning repo
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Push to dokku
uses: dokku/github-action@master
with:
branch: 'main'
trace: '1'
git_push_flags: '--force'
git_remote_url: 'ssh://dokku@SERVER_IP:22/APP_NAME_IN_DOKKU'
ssh_private_key: ${{ secrets.PRODUCTION_DOKKU_SSH_PRIVATE_KEY }}
Let's break down what's happening here:
Workflow Triggers
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
This condition ensures deployments only happen when code is pushed to the main branch - perfect for a trunk-based development workflow.
Job Dependencies
needs: [ test ]
By specifying needs: [ test ]
, we ensure our tests pass before any deployment occurs. This is crucial for maintaining code quality!
Deployment Configuration
The dokku/github-action@master
action handles the heavy lifting:
branch: 'main'
- Specifies which branch to deploytrace: '1'
- Enables detailed logging for troubleshootinggit_push_flags: '--force'
- Ensures clean deploymentsgit_remote_url
- Connects to your Dokku serverssh_private_key
- Securely authenticates using our previously configured key
The Deployment Process
With everything set up, deploying is as simple as:
git push origin main
This triggers the following sequence:
Your code is pushed to GitHub
GitHub Actions detects the push to main
The test suite runs
If tests pass, the deployment job begins
Your code is securely deployed to the Dokku server
Personal Insights and Tips
Through implementing this setup, I've learned some valuable lessons:
Security First: Always use dedicated deployment keys and never store sensitive information in your repository.
Test Dependencies: Make deployment dependent on test success to prevent broken code from reaching production.
Logging Matters: The
trace: '1'
option has saved hours of debugging by providing detailed deployment logs.
Looking Forward
This setup has dramatically improved our deployment workflow, but there's always room for enhancement. Future improvements might include:
Adding staging environment deployments
Implementing automatic database backups pre-deployment
Setting up deployment notifications in Slack
Remember, the goal of automation isn't just to save time - it's to build confidence in your deployment process and free up mental energy for solving more interesting problems.
Have you implemented a similar setup? I'd love to hear about your experiences and any improvements you've made to this workflow!
Happy deployments!
Subscribe to my newsletter
Read articles from Sulman Baig directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Sulman Baig
Sulman Baig
Senior Software Engineer with 11 years of expertise in Ruby on Rails and Vue.js, specializing in health, e-commerce, staffing, and transport. Experienced in software development and version analysis.