Table of Contents
Overview
The main differences between Capistrano and Kamal are:
- Capistrano is a traditional server-based deployment tool that uses SSH and file system deployment.
- Kamal is a container-based deployment tool that uses Docker and container orchestration.
Capistrano Architecture
Local Machine (Client) ←→ Remote Server (Target)
↓
Capistrano Tasks
↓
SSH Connection
↓
Remote Commands Execution
↓
File System Deployment
Key Components:
- Capfile (entry point)
- config/deploy.rb (main configuration)
- config/deploy/environment.rb (environment-specific)
- SSH key authentication
- Server file system management
Kamal Architecture
Local Machine ←→ Container Registry ←→ VPS Server
↓ ↓ ↓
Kamal CLI ←→ Docker Images ←→ Docker Containers
↓ ↓ ↓
Deploy Commands ←→ Image Build ←→ Application Running
Key Components:
- config/deploy.yml (single configuration file)
- Dockerfile (container definition)
- Container registry (Docker Hub, GitHub Container Registry)
- Traefik (reverse proxy and load balancer)
Setup Process
Capistrano Setup
1. Add Gems to Gemfile
# Gemfile
group :development do
gem 'capistrano', '~> 3.17'
gem 'capistrano-rails', '~> 1.6'
gem 'capistrano-rbenv', '~> 2.2'
gem 'capistrano3-puma', '~> 5.2'
gem 'capistrano-postgresql', '~> 7.0'
end
2. Install Capistrano
bundle install
bundle exec cap install
This command will create all the necessary configuration files and directory structure
├── Capfile
├── config
│ ├── deploy
│ │ ├── production.rb
│ │ └── staging.rb
│ └── deploy.rb
└── lib
└── capistrano
└── tasks
3. Server Preparation
# On VPS server
sudo adduser deploy
sudo usermod -aG sudo deploy
sudo mkdir -p /var/www/meditation
sudo chown deploy:deploy /var/www/meditation
# Install required software
sudo apt update
sudo apt install nginx postgresql redis-server
Kamal Setup
1. Add Kamal Gem
# Gemfile
gem "kamal", require: false
2. Initialize Kamal
bundle install
kamal init
This command will create config/deploy.yml - a configuration yml file for container deployment.
3. Create Dockerfile
Otherwise, you need to create Dockerfile to build image for this project.
Workflow Comparison
Capistrano Workflow
Deployment Process
# 1. Check deployment prerequisites
cap production deploy:check
# 2. Deploy application
cap production deploy
Internal Steps:
- deploy:starting - Initialize deployment
- deploy:updating - Update code from Git
- deploy:reverting - Rollback if needed
- deploy:publishing - Publish application
- deploy:finishing - Complete deployment
File System Structure
/var/www/meditation/
├── current/ # Symlink to latest release
├── releases/ # All deployed versions
│ ├── 20231201120000/
│ ├── 20231201130000/
│ └── 20231201140000/
├── shared/ # Shared files between releases
│ ├── log/
│ ├── tmp/
│ ├── public/
│ └── config/
└── repo/ # Git repository
Kamal Workflow
Deployment Process
# 1. Build and push Docker image
docker build -t your-registry/meditation:latest .
docker push your-registry/meditation:latest
# 2. Deploy application
kamal deploy
Internal Steps:
- Image Pull - Pull latest image from registry
- Container Stop - Stop current container
- Container Start - Start new container
- Health Check - Verify application health
- Traefik Update - Update routing configuration
Container Structure
Docker Containers:
├── meditation-app # Rails application
├── postgres # Database
├── redis # Cache/Queue
└── traefik # Reverse proxy
Configuration Examples
Kamal is easier to configure compared with Capistrano. With Kamal, you need a Dockerfile and one YAML file to define services. With Capistrano, you need to install and configure for each service on the server, for example, puma, nginx, ...
Capistrano Configuration
This is config from my old project, use for deploying on Linode VPS
Capfile
# Load DSL and set up stages
require "capistrano/setup"
# Include default deployment tasks
require "capistrano/deploy"
require "capistrano/secrets_yml"
require "capistrano/scm/git"
install_plugin Capistrano::SCM::Git
# Include tasks from other gems included in your Gemfile
# require "capistrano/rvm"
require "capistrano/rbenv"
require "capistrano/bundler"
require "capistrano/rails/assets"
require "capistrano/rails/migrations"
require 'capistrano/puma'
install_plugin Capistrano::Puma # Default puma tasks
install_plugin Capistrano::Puma::Systemd
# require "capistrano/passenger"
# Load custom tasks from `lib/capistrano/tasks` if you have any defined
Dir.glob("lib/capistrano/tasks/*.rake").each { |r| import r }
config/deploy.rb
# config valid for current version and patch releases of Capistrano
lock "~> 3.17.2"
set :application, "hotwire_way"
set :repo_url, "git@github.com:hungle00/hotwire-way.git"
set :rbenv_type, :user
set :rbenv_ruby, '3.0.0'
# Default branch is :master
# ask :branch, `git rev-parse --abbrev-ref HEAD`.chomp
set :branch, :develop
# Default deploy_to directory is /var/www/my_app_name
set :deploy_to, "/home/ubuntu/#{fetch :application}"
set :puma_bind, "unix://#{shared_path}/tmp/sockets/puma.sock"
set :puma_state, "#{shared_path}/tmp/pids/puma.state"
set :puma_pid, "#{shared_path}/tmp/pids/puma.pid"
set :puma_access_log, "#{release_path}/log/puma.error.log"
set :puma_error_log, "#{release_path}/log/puma.access.log"
set :puma_systemctl_user, :system
set :puma_preload_app, true
set :puma_worker_timeout, nil
set :puma_init_active_record, true # Change to false when not using ActiveRecord
# Default value for :format is :airbrussh.
# set :format, :airbrussh
# You can configure the Airbrussh format using :format_options.
# These are the defaults.
# set :format_options, command_output: true, log_file: "log/capistrano.log", color: :auto, truncate: :auto
# Default value for :pty is false
# set :pty, true
# Default value for :linked_files is []
# append :linked_files, "config/database.yml", 'config/master.key'
append :linked_files, 'config/credentials/production.key'
# Default value for linked_dirs is []
append :linked_dirs, "log", "tmp/pids", "tmp/cache", "tmp/sockets", "tmp/webpacker", "public/system", "vendor", "storage"
Environment Configuration
# config/deploy/production.rb
server 'your-vps-ip', user: 'deploy', roles: %w{app db web}
set :branch, 'main'
set :rails_env, 'production'
set :default_env, {
'RAILS_ENV' => 'production',
'DATABASE_URL' => 'postgresql://user:pass@localhost/meditation_production'
}
Configuration for puma and nginx
See here
https://github.com/hungle00/hotwire-way/blob/develop/puma_nginx.md
Kamal Configuration
Main Configuration
# config/deploy.yml
service: meditation
image: your-registry/meditation
registry:
username: your-username
password:
- KAMAL_REGISTRY_PASSWORD
servers:
web:
hosts:
- your-vps-ip
labels:
traefik.http.routers.meditation.rule: Host(`your-domain.com`)
traefik.http.routers.meditation.tls: "true"
env:
RAILS_ENV: production
DATABASE_URL: postgresql://user:pass@host/db
REDIS_URL: redis://host:6379/1
volumes:
- "/var/lib/meditation/storage:/app/storage"
- "/var/lib/meditation/logs:/app/log"
accessories:
db:
image: postgres:15
host: your-vps-ip
port: 5432
env:
POSTGRES_DB: meditation_production
POSTGRES_USER: meditation
POSTGRES_PASSWORD: your-password
volumes:
- "/var/lib/meditation/postgres:/var/lib/postgresql/data"
redis:
image: redis:7-alpine
host: your-vps-ip
port: 6379
volumes:
- "/var/lib/meditation/redis:/data"
Deployment Process
Capistrano Deployment
Pre-deployment Checks
# Check deployment prerequisites
cap production deploy:check
Deployment Commands
# Full deployment
cap production deploy
# Deploy with specific branch
cap production deploy BRANCH=feature/new-feature
# Deploy with custom environment
cap production deploy RAILS_ENV=staging
Deployment Steps
-
Bundle Install
bundle install --path vendor/bundle --without development test
-
Database Migration
RAILS_ENV=production bundle exec rake db:migrate
-
Asset Precompilation
RAILS_ENV=production bundle exec rake assets:precompile
-
Symlink Update
rm /var/www/meditation/current
ln -s /var/www/meditation/releases/20231201140000 /var/www/meditation/current
-
Application Restart
sudo systemctl restart puma_meditation
Kamal Deployment
Pre-deployment Checks
# Check configuration
kamal config
# Validate deployment
kamal deploy --dry-run
Deployment Commands
# Build and deploy
kamal deploy
# Deploy specific version
kamal deploy v1.2.3
# Deploy with custom environment
kamal deploy --env production
Deployment Steps
-
Image Build
docker build -t your-registry/meditation:latest .
-
Image Push
docker push your-registry/meditation:latest
-
Container Deployment
# Pull new image
docker pull your-registry/meditation:latest
# Stop old container
docker stop meditation-app
# Start new container
docker run -d --name meditation-app-new your-registry/meditation:latest
-
Traefik Update
# Update routing to new container
docker exec traefik traefik config
Monitoring & Logging
Capistrano Monitoring
Log Management
# Application logs
tail -f /var/www/meditation/current/log/production.log
# Puma logs
sudo journalctl -u puma_meditation -f
# Nginx logs
sudo tail -f /var/log/nginx/access.log
sudo tail -f /var/log/nginx/error.log
Health Checks
# Check application status
curl -f http://your-domain.com/health
# Check Puma status
sudo systemctl status puma_meditation
# Check database connection
RAILS_ENV=production bundle exec rails console
Kamal Monitoring
Container Logs
# View all logs
kamal logs
# View specific service logs
kamal logs web
# Follow logs in real-time
kamal logs -f
# View container logs directly
docker logs meditation-app
Health Monitoring
# Check service status
kamal status
# Check container health
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
# Check resource usage
kamal exec web top
Conclusion
Kamal represents the future of Rails deployment with its modern approach. The main pros of Kamal over Capistrano are:
- Modern Container-based: Kamal uses Docker instead of direct server management, making it easier to scale and maintain.
- Automatic Zero-downtime: Kamal has built-in zero-downtime deployment, while Capistrano requires complex manual configuration.
- Quick Setup: Kamal is easier to learn and requires less time to set up.
- Rails-focused Design: Kamal is specifically designed for Rails with built-in monitoring, health checks, and secrets management.
Table of Contents
Overview
The main differences between Capistrano and Kamal are:
Capistrano Architecture
Key Components:
Kamal Architecture
Key Components:
Setup Process
Capistrano Setup
1. Add Gems to Gemfile
2. Install Capistrano
bundle install bundle exec cap installThis command will create all the necessary configuration files and directory structure
3. Server Preparation
Kamal Setup
1. Add Kamal Gem
2. Initialize Kamal
This command will create
config/deploy.yml- a configuration yml file for container deployment.3. Create Dockerfile
Otherwise, you need to create Dockerfile to build image for this project.
Workflow Comparison
Capistrano Workflow
Deployment Process
Internal Steps:
File System Structure
Kamal Workflow
Deployment Process
Internal Steps:
Container Structure
Configuration Examples
Kamal is easier to configure compared with Capistrano. With Kamal, you need a Dockerfile and one YAML file to define services. With Capistrano, you need to install and configure for each service on the server, for example, puma, nginx, ...
Capistrano Configuration
This is config from my old project, use for deploying on Linode VPS
Capfile
config/deploy.rb
Environment Configuration
Configuration for puma and nginx
See here
https://github.com/hungle00/hotwire-way/blob/develop/puma_nginx.md
Kamal Configuration
Main Configuration
Deployment Process
Capistrano Deployment
Pre-deployment Checks
# Check deployment prerequisites cap production deploy:checkDeployment Commands
Deployment Steps
Bundle Install
bundle install --path vendor/bundle --without development testDatabase Migration
RAILS_ENV=production bundle exec rake db:migrateAsset Precompilation
RAILS_ENV=production bundle exec rake assets:precompileSymlink Update
Application Restart
Kamal Deployment
Pre-deployment Checks
Deployment Commands
Deployment Steps
Image Build
docker build -t your-registry/meditation:latest .Image Push
Container Deployment
Traefik Update
Monitoring & Logging
Capistrano Monitoring
Log Management
Health Checks
Kamal Monitoring
Container Logs
Health Monitoring
Conclusion
Kamal represents the future of Rails deployment with its modern approach. The main pros of Kamal over Capistrano are: