AgentSkillsCN

kamal

使用 Kamal(Docker + SSH)部署 Rails 应用程序。当您需要:(1) 创建或修改 deploy.yml 配置文件;(2) 设置新的服务器部署环境;(3) 配置 kamal-proxy、SSL 或相关辅助工具;(4) 编写部署钩子;(5) 使用 1Password/Bitwarden/LastPass 管理敏感信息;(6) 排查部署过程中遇到的问题;(7) 配置多服务器或多目标部署方案时,本技能将助您事半功倍。

SKILL.md
--- frontmatter
name: kamal
description: "Deploy Rails applications with Kamal (Docker + SSH). Use when: (1) Creating or modifying deploy.yml configuration, (2) Setting up new server deployments, (3) Configuring kamal-proxy, SSL, or accessories, (4) Writing deployment hooks, (5) Managing secrets with 1Password/Bitwarden/LastPass, (6) Troubleshooting deployment issues, (7) Setting up multi-server or multi-destination deployments."

Kamal Deployment

Kamal deploys containerized applications via SSH. It builds Docker images, pushes to registries, and orchestrates zero-downtime deployments using kamal-proxy.

Quick Reference

bash
kamal init              # Create config/deploy.yml and .kamal/secrets
kamal setup             # First-time setup (bootstrap + deploy)
kamal deploy            # Deploy new version
kamal rollback VERSION  # Revert to specific version
kamal app logs -f       # Tail application logs
kamal console           # Rails console (via alias)

Configuration Workflow

  1. Initialize: kamal init creates config/deploy.yml and .kamal/secrets
  2. Configure: Edit deploy.yml with service, servers, registry, and env
  3. Secrets: Set up .kamal/secrets to fetch from password manager
  4. Deploy: Run kamal setup for first deployment, kamal deploy thereafter

Minimal deploy.yml

yaml
service: myapp
image: myuser/myapp

servers:
  web:
    - 192.168.0.1

registry:
  server: ghcr.io
  username: myuser
  password:
    - KAMAL_REGISTRY_PASSWORD

env:
  secret:
    - RAILS_MASTER_KEY
  clear:
    SOLID_QUEUE_IN_PUMA: true

volumes:
  - "myapp_storage:/rails/storage"

asset_path: /rails/public/assets

builder:
  arch: amd64

aliases:
  console: app exec --interactive --reuse "bin/rails console"
  shell: app exec --interactive --reuse "bash"
  logs: app logs -f

Secrets File (.kamal/secrets)

shell
# Fetch from 1Password
SECRETS=$(kamal secrets fetch --adapter 1password --account myaccount \
  --from Vault/Item KAMAL_REGISTRY_PASSWORD RAILS_MASTER_KEY)

KAMAL_REGISTRY_PASSWORD=$(kamal secrets extract KAMAL_REGISTRY_PASSWORD $SECRETS)
RAILS_MASTER_KEY=$(kamal secrets extract RAILS_MASTER_KEY $SECRETS)

# Or from environment
# KAMAL_REGISTRY_PASSWORD=$KAMAL_REGISTRY_PASSWORD

# Or from file
# RAILS_MASTER_KEY=$(cat config/master.key)

Key Configuration Sections

SectionPurposeReference
serversDeployment targets and rolesconfiguration.md
proxykamal-proxy settings (SSL, hosts, healthcheck)configuration.md
builderDocker build options (arch, remote, cache)configuration.md
envEnvironment variables (clear/secret)configuration.md
accessoriesAdditional services (db, redis)configuration.md

Destinations

Use destinations for staging/production environments:

bash
kamal deploy -d staging     # Uses config/deploy.staging.yml
kamal deploy -d production  # Uses config/deploy.production.yml

Destination configs merge with base deploy.yml. Secrets read from .kamal/secrets.<destination>.

Hooks

Place executable scripts in .kamal/hooks/ (no extension):

HookTrigger
pre-connectBefore SSH connections
pre-buildBefore Docker build
pre-deployBefore deployment starts
post-deployAfter successful deployment
pre-app-boot / post-app-bootAround container boot

Available environment variables: KAMAL_PERFORMER, KAMAL_VERSION, KAMAL_DESTINATION, KAMAL_RUNTIME, KAMAL_HOSTS

See hooks.md for examples.

Common Patterns

Single-Server Rails

yaml
service: myapp
image: myapp

servers:
  web:
    - 192.168.0.1

env:
  clear:
    SOLID_QUEUE_IN_PUMA: true  # Jobs in Puma process

volumes:
  - "myapp_storage:/rails/storage"

asset_path: /rails/public/assets

proxy:
  ssl: true
  host: myapp.example.com

Multi-Server with Separate Jobs

yaml
servers:
  web:
    hosts:
      - web-1
      - web-2
  jobs:
    hosts:
      - jobs-1
    cmd: bin/jobs

Database Accessory

yaml
accessories:
  db:
    image: postgres:16
    host: 192.168.0.2
    port: "127.0.0.1:5432:5432"
    env:
      secret:
        - POSTGRES_PASSWORD
    directories:
      - data:/var/lib/postgresql/data

Commands Reference

See commands.md for full CLI reference.

CommandPurpose
kamal app exec "cmd"Run command in container
kamal app logs -fTail logs
kamal proxy rebootRestart kamal-proxy
kamal rollbackRevert to previous version
kamal prune allClean old containers/images
kamal configShow resolved configuration
kamal lock statusCheck deployment lock

Troubleshooting

  • Health check failing: Check /up endpoint responds 200, verify proxy.healthcheck.path
  • SSL not working: Ensure port 443 open, host DNS resolves to server
  • Build slow: Use builder.remote for remote builds, or builder.cache for layer caching
  • Container not starting: Check kamal app logs, verify environment variables
  • Permission denied: Check SSH key, ensure user can run Docker

Reference Files