Rails 8 CI/CD: GitHub Actions & Kamal 2025

In my previous article, we explored deploying Rails 8 applications using Docker and Kamal. Deploying Rails 8 Applications: A Complete Guide with Docker, Kamal, and Cloudflare Sulman Baig ・ Jan 9 #rails #devops #docker #ruby 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. Why Add GitHub Actions to Our Deployment Stack? 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 Prerequisites Before we dive in, make sure you have: A Rails 8 application configured with Kamal (https://dev.to/sulmanweb/deploying-rails-8-applications-a-complete-guide-with-docker-kamal-and-cloudflare-3k) A GitHub repository for your application Access to your repository's settings to configure secrets Setting Up GitHub Actions Let's break down the process into manageable steps. 1. Creating the Workflow File 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 2. Setting Up Deployment Steps 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 3. Configuring SSH Access 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 }} 4. Running the Deployment 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 }} Setting Up GitHub Secrets 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! Understanding Environment Variables 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 Deployment Flow 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 Best Practices and Tips 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. Troubleshooting

Jan 20, 2025 - 07:11
 0
Rails 8 CI/CD: GitHub Actions & Kamal 2025

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.

Why Add GitHub Actions to Our Deployment Stack?

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

Prerequisites

Before we dive in, make sure you have:

Setting Up GitHub Actions

Let's break down the process into manageable steps.

1. Creating the Workflow File

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

2. Setting Up Deployment Steps

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

3. Configuring SSH Access

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 }}

4. Running the Deployment

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 }}

Setting Up GitHub Secrets

Security is paramount in automated deployments. Here's how to set up your secrets in GitHub:

  1. Navigate to your repository's Settings
  2. Select "Secrets and variables" → "Actions"
  3. Click "New repository secret"
  4. 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!

Understanding Environment Variables

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

Deployment Flow

When you push to main, here's what happens:

  1. GitHub Actions triggers the workflow
  2. The environment is prepared with Ruby and Docker
  3. SSH access is configured securely
  4. Kamal executes the deployment
  5. Your application is updated with zero downtime

Best Practices and Tips

Through my experience with this setup, I've learned some valuable lessons:

  1. Test Your Workflow: Use GitHub Actions' "workflow_dispatch" trigger to test manually before automating.
  2. Monitor Deployments: Watch your Actions tab for deployment logs.
  3. Secure Your Secrets: Regularly rotate your credentials and use strong passwords.
  4. Keep Dependencies Updated: Regularly update your GitHub Actions versions.

Troubleshooting Common Issues

If you encounter issues, check these common points:

  1. SSH Connection Failures

    • Verify your SSH private key format
    • Ensure the server IP in known_hosts is correct
  2. Docker Registry Issues

    • Confirm your registry credentials
    • Check Docker login status
  3. Environment Variables

    • Verify all secrets are properly set
    • Check for typos in secret names

Conclusion

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!

What's Your Reaction?

like

dislike

love

funny

angry

sad

wow