--- name: deployment-kamal description: This skill should be used when the user asks about deploying Rails applications, Kamal deployment, Docker containers, production configuration, environment variables, secrets management, CI/CD pipelines, server provisioning, zero-downtime deploys, Kamal Proxy, Thruster, or infrastructure setup. Also use when discussing production optimization, deployment strategies, or hosting options. Examples: Context: User wants to deploy their Rails 8 app user: "How do I deploy my Rails app to production?" assistant: "Rails 8 includes Kamal for deployment. Let me show you the setup." This relates to Kamal deployment workflow and configuration. Context: User asks about zero-downtime deploys user: "How can I deploy without taking my app offline?" assistant: "Kamal provides zero-downtime deploys by default. Let me explain how it works." This involves Kamal's rolling deployment strategy. Context: User needs environment-specific configuration user: "How do I configure different settings for staging vs production?" assistant: "I'll show you Rails environment configuration and Kamal deployment targets." This relates to Rails environments and Kamal configuration. --- # Deployment & Infrastructure: Kamal and Rails 8 ## Overview Rails 8 ships with **Kamal 2** for zero-downtime deployments to any Linux server. Kamal eliminates PaaS lock-in and Kubernetes complexity, giving you full control with simple tools. **Kamal philosophy:** - Deploy to any server (VPS, cloud, on-premise) - Docker-based containers - Zero-downtime deploys - No vendor lock-in - Simple configuration - One command to deploy Rails 8 also includes: - **Thruster**: Rust-based proxy for asset serving and compression - **Kamal Proxy**: Traffic routing and SSL termination - **Dockerfile**: Production-ready container configuration ## Kamal Basics ### What Kamal Does Kamal turns a fresh Linux server into a production Rails host with a single command: ```bash kamal setup ``` This: 1. Installs Docker 2. Configures the server 3. Pulls your application image 4. Starts containers 5. Configures proxy 6. Sets up SSL (via Let's Encrypt) Subsequent deploys are just: ```bash kamal deploy ``` ### Zero-Downtime Deploys Kamal performs rolling deploys: 1. Builds new Docker image 2. Pushes to registry 3. Pulls image on servers 4. Starts new containers 5. Waits for health check 6. Shifts traffic to new containers 7. Stops old containers Users never see downtime. ### Configuration Kamal is configured in `config/deploy.yml`: ```yaml service: myapp image: username/myapp servers: web: hosts: - 192.168.1.1 - 192.168.1.2 proxy: ssl: true host: myapp.com registry: username: username password: - KAMAL_REGISTRY_PASSWORD env: secret: - RAILS_MASTER_KEY healthcheck: path: /up interval: 10s ``` ## Kamal 2 Features ### Kamal Proxy Rails 8 includes Kamal Proxy (replaces Traefik): - Simpler configuration - Better performance - Integrated health checks - Automatic SSL via Let's Encrypt - Traffic routing - Request buffering ### Registry-Free Deploys (Rails 8.1+) Kamal 2.8+ supports local registry for simple deploys: ```yaml # config/deploy.yml registry: local: true # No Docker Hub/GHCR needed ``` Perfect for getting started. Use remote registry for larger deployments. ### Accessories Deploy supporting services alongside your app: ```yaml accessories: db: image: postgres:16 host: 192.168.1.1 env: POSTGRES_PASSWORD: secret volumes: - /var/lib/postgresql/data:/var/lib/postgresql/data redis: image: redis:7 host: 192.168.1.1 ``` ## Rails 8 Dockerfile Generated Dockerfile is production-ready: ```dockerfile FROM ruby:3.2-slim # Install dependencies RUN apt-get update && apt-get install -y \ build-essential \ postgresql-client \ && rm -rf /var/lib/apt/lists/* # Install gems COPY Gemfile* ./ RUN bundle install # Copy application COPY . . # Precompile assets RUN bundle exec rails assets:precompile # Start Thruster CMD ["bin/thruster", "bin/rails", "server"] ``` ## Thruster Rust-based proxy that sits in front of Puma: **Features:** - X-Sendfile acceleration (serve files efficiently) - Asset caching (immutable assets cached forever) - Compression (gzip/brotli) - HTTP/2 support **Configuration:** ```bash # bin/thruster thruster \ --http-port=80 \ --https-port=443 \ --storage-path=/var/thruster \ bin/rails server ``` Thruster handles all the performance optimizations you'd normally configure in Nginx. ## Environment Configuration ### Rails Environments Rails has three default environments: - **development**: Local development (verbose logs, code reloading) - **test**: Running tests (separate database, fixtures) - **production**: Live application (caching, optimized, secure) Configure in `config/environments/`: ```ruby # config/environments/production.rb Rails.application.configure do config.cache_classes = true config.eager_load = true config.consider_all_requests_local = false config.public_file_server.enabled = true config.assets.compile = false config.assets.digest = true config.log_level = :info config.force_ssl = true end ``` ### Secrets and Credentials Rails 8 uses encrypted credentials: ```bash # Edit credentials rails credentials:edit # Edit environment-specific credentials rails credentials:edit --environment production ``` ```yaml # config/credentials/production.yml.enc secret_key_base: abc123... database: password: dbpass aws: access_key_id: AKIAIOSFODNN7EXAMPLE secret_access_key: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY ``` Access in code: ```ruby Rails.application.credentials.aws[:access_key_id] Rails.application.credentials.database[:password] ``` Kamal can fetch secrets from credentials: ```bash # .kamal/secrets KAMAL_REGISTRY_PASSWORD=$(rails credentials:fetch kamal.registry_password) ``` See `references/kamal-setup.md` for complete deployment guide. ## CI/CD with Rails 8 ### Local CI (Rails 8.1+) > **Note**: This feature is available in Rails 8.1+. Verify your Rails version > supports `config/ci.rb` before using. Rails 8.1 includes built-in CI configuration: ```ruby # config/ci.rb CI.run do step "Setup", "bin/setup --skip-server" step "Style: Ruby", "bin/rubocop" step "Security: Gem audit", "bin/bundler-audit" step "Tests: Rails", "bin/rails test" if success? step "Signoff: All systems go", "gh signoff" else failure "CI failed. Fix issues and try again." end end ``` Run locally: ```bash bin/ci ``` Perfect for fast feedback without cloud CI. ### GitHub Actions ```yaml # .github/workflows/ci.yml name: CI on: [push, pull_request] jobs: test: runs-on: ubuntu-latest services: postgres: image: postgres:16 env: POSTGRES_PASSWORD: postgres steps: - uses: actions/checkout@v3 - uses: ruby/setup-ruby@v1 with: bundler-cache: true - run: bin/rails db:setup - run: bin/rails test - run: bin/rails test:system deploy: needs: test if: github.ref == 'refs/heads/main' runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: webfactory/ssh-agent@v0.8.0 with: ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }} - run: gem install kamal - run: kamal deploy ``` ## Production Best Practices 1. **Use production environment** with proper config 2. **Enable SSL/TLS** (force_ssl = true) 3. **Set SECRET_KEY_BASE** via credentials 4. **Use environment variables** for secrets 5. **Enable caching** (Solid Cache in Rails 8) 6. **Configure logging** appropriately 7. **Set up monitoring** (error tracking, metrics) 8. **Use CDN** for assets 9. **Configure database** connection pooling 10. **Set up backups** (database, credentials) See `references/production-checklist.md` for complete checklist. ## Further Reading For deeper exploration: - **`references/kamal-setup.md`**: Complete Kamal deployment guide - **`references/production-checklist.md`**: Production readiness checklist For code examples: - **`examples/basic-config.yml`**: Minimal single-server setup - **`examples/registry-free-config.yml`**: No Docker Hub needed (Kamal 2.8+) - **`examples/multi-server-config.yml`**: Multiple web servers with workers - **`examples/with-accessories-config.yml`**: PostgreSQL and Redis setup - **`examples/staging-production-config.yml`**: Environment-specific deploys - **`examples/custom-healthcheck-config.yml`**: Detailed health checks - **`examples/advanced-services-config.yml`**: Resource limits and scaling - **`examples/deployment-hooks.sh`**: Pre/post deploy automation ## Summary Rails 8 deployment provides: - **Kamal 2**: Zero-downtime deploys to any server - **Thruster**: Performance proxy - **Kamal Proxy**: Traffic routing - **Dockerfile**: Production-ready containers - **Credentials**: Encrypted secrets - **Local CI**: Fast feedback - **Self-hosting**: No vendor lock-in Master Kamal and deploy with confidence to any infrastructure.