DEV Community

Cover image for Effortless Rails 7+ Deployment with Kamal Gem on DigitalOcean
Shah Zaib
Shah Zaib

Posted on

5

Effortless Rails 7+ Deployment with Kamal Gem on DigitalOcean

Deploying a Rails application can often be daunting, especially when aiming for a production-ready setup. This guide will walk you through deploying a Rails 7.1+ application using the Kamal gem on Digital Ocean. By the end of this post, you'll have your app live and running with minimal hassle.

Prerequisites

  • Basic knowledge of Ruby on Rails
  • A Rails 7.1+ application
  • A Digital Ocean account
  • Docker installed on your local machine

Step 1: Install Kamal Gem

First, let's install the Kamal gem. Add the gem to your Gemfile and run the bundle command:

bundle add kamal && bundle install
Enter fullscreen mode Exit fullscreen mode

Step 2: Initialize Kamal Configuration

Initialize Kamal configuration by running the following command:

kamal init
Enter fullscreen mode Exit fullscreen mode

This command will generate two crucial files: .env and config/deploy.yml.

Step 3: Configure .env File

Add the following environment variables to your .env file:

RAILS_MASTER_KEY=XXXXXXXXXX
KAMAL_REGISTRY_PASSWORD=XXXXXXXXX
Enter fullscreen mode Exit fullscreen mode
  • RAILS_MASTER_KEY: Your Rails master key.
  • KAMAL_REGISTRY_PASSWORD: Your Docker Registry password. To find it, go to hub.docker.com, log in, and create a new token under Account Settings > Security > New Access Token.

Step 4: Update deploy.yml

Purchase a VPS from Digital Ocean and add its IP to the relevant field in deploy.yml. Update the configuration according to your project credentials.

Example config/deploy.yml

# Name of your application. Used to uniquely configure containers.
service: myapp

# Docker image
image: username/myapp

# Main server configuration
servers:
  web:
    hosts:
      - 192.168.0.1
    labels:
      traefik.http.routers.messi-web.rule: Host(`intellecta.app`)
      traefik.http.routers.messi-web.tls: true
      traefik.http.routers.messi-web.entrypoints: websecure
      traefik.http.routers.messi-web.tls.certresolver: letsencrypt

  job:
    hosts:
      - 192.168.0.1
    cmd: bundle exec sidekiq -q high_priority -q default -q mailers
Enter fullscreen mode Exit fullscreen mode

Step 5: Registry Configuration

Configure your Docker registry credentials in deploy.yml:

# Credentials for your image host.
registry:
  # Specify the registry server if you're not using Docker Hub
  # server: registry.digitalocean.com / ghcr.io / ...
  username: shahzaib
  password:
    - KAMAL_REGISTRY_PASSWORD
Enter fullscreen mode Exit fullscreen mode

Step 6: Set Environment Variables

Define your environment variables in deploy.yml:

env:
  clear:
    HOSTNAME: 192.168.0.1
    DB_HOST: 192.168.0.1
    RAILS_SERVE_STATIC_FILES: true
    RAILS_LOG_TO_STDOUT: true
  secret:
    - KAMAL_REGISTRY_PASSWORD
    - RAILS_MASTER_KEY
    - POSTGRES_PASSWORD
    - REDIS_URL
Enter fullscreen mode Exit fullscreen mode

Step 7: Configure Accessories

Set up your accessory services like PostgreSQL and Redis:

accessories:
  db:
    image: postgres:16
    host: 192.168.0.1
    env:
      clear:
        POSTGRES_DB: "myapp_production"
      secret:
        - POSTGRES_PASSWORD
    directories:
      - data:/var/lib/postgresql/data
  redis:
    image: redis:7.0
    host: 192.168.0.1
    directories:
      - data:/data
Enter fullscreen mode Exit fullscreen mode

Rails Database Configuration

Update your Rails database configuration in config/database.yml:

production:
  <<: *default
  username: myapp
  password: <%= ENV["POSTGRES_PASSWORD"] %>
  database: myapp_production
  host: <%= ENV["DB_HOST"] %>
Enter fullscreen mode Exit fullscreen mode

Step 8: Configure Traefik

Traefik handles TLS termination, HTTPS redirect, and zero downtime deployments. Add the following configuration to deploy.yml:

traefik:
  options:
    publish:
      - "443:443"
    volume:
      - "/letsencrypt/acme.json:/letsencrypt/acme.json"
  args:
    entryPoints.web.address: ":80"
    entryPoints.websecure.address: ":443"
    entryPoints.web.http.redirections.entryPoint.to: websecure
    entryPoints.web.http.redirections.entryPoint.scheme: https
    entryPoints.web.http.redirections.entrypoint.permanent: true
    certificatesResolvers.letsencrypt.acme.email: "support@intellecta.app"
    certificatesResolvers.letsencrypt.acme.storage: "/letsencrypt/acme.json"
    certificatesResolvers.letsencrypt.acme.httpchallenge: true
    certificatesResolvers.letsencrypt.acme.httpchallenge.entrypoint: web
Enter fullscreen mode Exit fullscreen mode

Step 9: Deployment Commands

Run the following commands to set up and deploy your app:

kamal setup
kamal env push
Enter fullscreen mode Exit fullscreen mode

After 210 seconds, your app will be live. To deploy changes, use:

kamal deploy
Enter fullscreen mode Exit fullscreen mode

Step 10: Troubleshooting Logs

If there are issues, check the logs:

kamal traefik logs
kamal app logs 
Enter fullscreen mode Exit fullscreen mode

For live logs:

kamal app logs -f
Enter fullscreen mode Exit fullscreen mode

Step 11: Access Rails Console

Access the Rails console using:

kamal app exec -i "bin/rails c"
Enter fullscreen mode Exit fullscreen mode

Step 12: Access Bash on Server

Access bash on the server using:

kamal server exec --interactive "/bin/bash"
Enter fullscreen mode Exit fullscreen mode

Final config/deploy.yml

Here's the overall final look of your config/deploy.yml:

# Name of your application. Used to uniquely configure containers.
service: myapp

# Name of the container image.
image: username/myapp

# Deploy to these servers.
servers:
  web:
    hosts:
      - 192.168.0.1
    labels:
      traefik.http.routers.messi-web.rule: Host(`intellecta.app`)
      traefik.http.routers.messi-web.tls: true
      traefik.http.routers.messi-web.entrypoints: websecure
      traefik.http.routers.messi-web.tls.certresolver: letsencrypt

  job:
    hosts:
      - 192.168.0.1
    cmd: bundle exec sidekiq -q high_priority -q default -q mailers

# Credentials for your image host.
registry:
  # Specify the registry server, if you're not using Docker Hub
  # server: registry.digitalocean.com / ghcr.io / ...
  username: shahzaib
  password:
    - KAMAL_REGISTRY_PASSWORD

# Inject ENV variables into containers (secrets come from .env).
# Remember to run `kamal env push` after making changes!
env:
  clear:
    HOSTNAME: 192.168.0.1
    DB_HOST: 192.168.0.1
    RAILS_SERVE_STATIC_FILES: true
    RAILS_LOG_TO_STDOUT: true
  secret:
    - KAMAL_REGISTRY_PASSWORD
    - RAILS_MASTER_KEY
    - POSTGRES_PASSWORD
    - REDIS_URL

# Use accessory services (secrets come from .env).
accessories:
  db:
    image: postgres:16
    host: 192.168.0.1
    env:
      clear:
        POSTGRES_DB: "myapp_production"
      secret:
        - POSTGRES_PASSWORD
    directories:
      - data:/var/lib/postgresql/data
  redis:
    image: redis:7.0
    host: 192.168.0.1
    directories:
      - data:/data

traefik:
  options:
    publish:
      - "443:443"
    volume:
      - "/letsencrypt/acme.json:/letsencrypt/acme.json"
  args:
    entryPoints.web.address: ":80"
    entryPoints.websecure.address: ":443"
    entryPoints.web.http.redirections.entryPoint.to: websecure
    entryPoints.web.http.redirections.entryPoint.scheme: https
    entryPoints.web.http.redirections.entrypoint.permanent: true
    certificatesResolvers.letsencrypt.acme.email: "support@intellecta.app"
    certificatesResolvers.letsencrypt.acme.storage: "/letsencrypt/acme.json"
    certificatesResolvers.letsencrypt.acme.httpchallenge: true
    certificatesResolvers.letsencrypt.acme.httpchallenge.entrypoint: web
Enter fullscreen mode Exit fullscreen mode

By following these steps, you can easily deploy your Rails 7+ application using the

Kamal gem on Digital Ocean. This guide should help you set up a robust, production-ready environment with minimal effort. Happy deploying!

Heroku

This site is built on Heroku

Join the ranks of developers at Salesforce, Airbase, DEV, and more who deploy their mission critical applications on Heroku. Sign up today and launch your first app!

Get Started

Top comments (0)

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

👋 Kindness is contagious

Discover a treasure trove of wisdom within this insightful piece, highly respected in the nurturing DEV Community enviroment. Developers, whether novice or expert, are encouraged to participate and add to our shared knowledge basin.

A simple "thank you" can illuminate someone's day. Express your appreciation in the comments section!

On DEV, sharing ideas smoothens our journey and strengthens our community ties. Learn something useful? Offering a quick thanks to the author is deeply appreciated.

Okay