Rails 8 CI/CD: GitHub Actions & Kamal 2025

Senior Software Engineer with 12 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.
Search for a command to run...

Senior Software Engineer with 12 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.
No comments yet. Be the first to comment.
This comprehensive series will equip readers with practical knowledge and skills in deploying Rails applications using Kamal, Dokku, and other relevant tools.
Introduction When I first started deploying Rails applications, the process felt overwhelming. Today, I'm excited to share a complete guide that transforms this complexity into a straightforward process. Let's dive into deploying a Rails 8 app using ...
Motivation After building several Shopify embedded apps, I've learned valuable lessons about what works (and what definitely doesn't) in the embedded app environment. Today, I'm sharing these insights to help you avoid common pitfalls and build bette...

As a developer working with Shopify's ecosystem, I recently built a multi-tenant SaaS application that synchronizes customer data between Shopify stores and external services. In this article, I'll share my experience and technical insights into crea...

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 an...

The Challenge: Modernizing Rails Deployment When I recently needed to deploy my Rails 8 application with multiple databases, I faced a common dilemma: choosing between expensive managed solutions and complex self-managed servers. My requirements were...

The Cost-Benefit Realization As a Rails developer who recently migrated from Heroku to Dokku, I want to share my journey and the surprising benefits I discovered. This transition wasn't just about cost savings—it opened up new possibilities for my de...

In my previous article, we explored deploying Rails 8 applications using Docker and Kamal.
Today, I'm excited to share how we can take this deployment process to the next level by automating it with GitHub Actions. This automation will make our deployments more consistent, reduce human error, and save valuable development time.
When I first started using Kamal for deployments, I found myself repeatedly running the same commands. While Kamal made the process straightforward, I knew we could make it even better. GitHub Actions provides the perfect solution by:
Automating deployments on code pushes to main
Ensuring consistent deployment environments
Managing secrets securely
Providing detailed deployment logs and history
Before we dive in, make sure you have:
A Rails 8 application configured with Kamal (https://sulmanweb.com/deploy-rails-8-docker-kamal-production-guide)
A GitHub repository for your application
Access to your repository's settings to configure secrets
Let's break down the process into manageable steps.
First, create a new file at .github/workflows/deploy.yml. This is where our deployment magic will happen.
name: Deploy to Production
on:
push:
branches:
- main
permissions:
contents: read
packages: write
id-token: write
jobs:
deploy:
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
runs-on: ubuntu-24.04
env:
DOCKER_BUILDKIT: 1
RAILS_ENV: production
BUNDLE_WITHOUT: "development test"
BUNDLE_WITH: tools
Let's examine each step of our deployment process:
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: .ruby-version
bundler-cache: true
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
These initial steps prepare our deployment environment:
checkout clones our repository
setup-ruby configures Ruby using our project's .ruby-version
setup-buildx enables Docker's advanced build capabilities
The SSH setup is crucial for secure server access:
- name: Set up SSH
run: |
mkdir -p ~/.ssh
echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
eval $(ssh-agent -s)
ssh-add ~/.ssh/id_rsa
ssh-keyscan xx.xx.xx.xx >> ~/.ssh/known_hosts
env:
SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
Finally, we execute Kamal:
- name: Deploy with Kamal
run: bin/kamal deploy
env:
RAILS_MASTER_KEY: ${{ secrets.RAILS_MASTER_KEY }}
KAMAL_REGISTRY_PASSWORD: ${{ secrets.KAMAL_REGISTRY_PASSWORD }}
POSTGRES_PASSWORD: ${{ secrets.POSTGRES_PASSWORD }}
POSTGRES_PASS: ${{ secrets.POSTGRES_PASSWORD }}
Security is paramount in automated deployments. Here's how to set up your secrets in GitHub:
Navigate to your repository's Settings
Select "Secrets and variables" → "Actions"
Click "New repository secret"
Add the following secrets:
SSH_PRIVATE_KEY: Your server's SSH private key
RAILS_MASTER_KEY: Your Rails master key
KAMAL_REGISTRY_PASSWORD: Docker registry password
POSTGRES_PASSWORD: Database password
Pro tip: Generate strong passwords for these secrets using a password manager!
Our workflow uses several environment variables:
DOCKER_BUILDKIT: 1: Enables Docker's modern build system
RAILS_ENV: production: Sets Rails environment
BUNDLE_WITHOUT: Optimizes gem installation
BUNDLE_WITH: tools: Ensures deployment tools are available
When you push to main, here's what happens:
GitHub Actions triggers the workflow
The environment is prepared with Ruby and Docker
SSH access is configured securely
Kamal executes the deployment
Your application is updated with zero downtime
Through my experience with this setup, I've learned some valuable lessons:
Test Your Workflow: Use GitHub Actions' "workflow_dispatch" trigger to test manually before automating.
Monitor Deployments: Watch your Actions tab for deployment logs.
Secure Your Secrets: Regularly rotate your credentials and use strong passwords.
Keep Dependencies Updated: Regularly update your GitHub Actions versions.
If you encounter issues, check these common points:
SSH Connection Failures
Verify your SSH private key format
Ensure the server IP in known_hosts is correct
Docker Registry Issues
Confirm your registry credentials
Check Docker login status
Environment Variables
Verify all secrets are properly set
Check for typos in secret names
Automating deployments with GitHub Actions and Kamal has transformed our deployment process from a manual task to a streamlined, automated workflow. Not only does this save time, but it also provides consistency and reliability in our deployments.
Remember, automation is about finding the right balance between convenience and control. With this setup, we maintain full control over our deployment process while enjoying the benefits of automation.
What's your experience with automated deployments? I'd love to hear your thoughts and experiences in the comments below! 🚀
Happy Coding!