35+ Years Experience Netherlands Based ⚡ Fast Response Times Ruby on Rails Experts AI-Powered Development Fixed Pricing Available Senior Architects Dutch & English 35+ Years Experience Netherlands Based ⚡ Fast Response Times Ruby on Rails Experts AI-Powered Development Fixed Pricing Available Senior Architects Dutch & English
Rails 8 deployen met Kamal 2: Een complete productie-setup vanaf nul

Rails 8 deployen met Kamal 2: Een complete productie-setup vanaf nul

TTB Software
rails, devops
Stap-voor-stap handleiding voor het deployen van Rails 8 met Kamal 2. Server setup, Docker-configuratie, SSL, database migraties en de valkuilen die we in productie tegenkwamen.

Kamal 2 is de standaard deployment-tool in Rails 8 en vervangt de oude Capistrano-workflow waar de meeste van ons mee zijn opgegroeid. Na het migreren van drie productie-apps van Capistrano naar Kamal in de afgelopen maanden, is hier de complete handleiding — inclusief de onderdelen die de documentatie overslaat.

Wat Kamal 2 precies doet

Kamal gebruikt Docker-containers die via SSH worden gedeployd. Geen Kubernetes. Geen managed container service. Je wijst het naar een server, het bouwt je Docker-image, pusht het naar een registry, pullt het op de server en wisselt verkeer via Kamal Proxy (dat Traefik uit Kamal 1 vervangt).

Het mentale model: Capistrano deployde code naar een server en herstartte processen. Kamal deployt containers naar een server en wisselt verkeer. De server heeft geen Ruby, Node of andere dependencies nodig — alleen Docker.

Vereisten

Je hebt nodig:

  • Een server met Ubuntu 22.04+ en SSH-toegang (een VPS van €10/maand werkt prima)
  • Een Docker Hub-account (of een andere container registry)
  • Rails 8.0+ met Docker-ondersteuning (nieuwe apps hebben dit automatisch; bestaande apps hebben een Dockerfile nodig)
  • Ruby 3.3+ lokaal

Bij een bestaande Rails 7-app, draai rails app:update na het upgraden naar Rails 8. Dit genereert de Dockerfile, .dockerignore en config/deploy.yml die je nodig hebt.

Stap 1: Installeer Kamal

gem install kamal

Rails 8-apps hebben het al in de Gemfile staan. Controleer met:

kamal version
# => 2.4.0

Stap 2: Configureer deploy.yml

De gegenereerde config/deploy.yml heeft echte waarden nodig. Hier is een uitgeklede productie-configuratie:

service: myapp

image: yourdockerhub/myapp

servers:
  web:
    hosts:
      - 203.0.113.42
    options:
      memory: 512m

proxy:
  ssl: true
  host: myapp.com

registry:
  username: yourdockerhub
  password:
    - KAMAL_REGISTRY_PASSWORD

env:
  clear:
    RAILS_LOG_TO_STDOUT: "1"
    RAILS_SERVE_STATIC_FILES: "1"
  secret:
    - RAILS_MASTER_KEY
    - DATABASE_URL

builder:
  arch: amd64

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

Een paar dingen die de docs onvoldoende benadrukken:

Geheugenlimieten zijn belangrijk. Zonder memory: 512m kan een enkel request dat veel geheugen alloceert al je VPS-RAM opeten, waarna de OOM-killer je container (en soms de database) afschiet. Stel dit in op basis van het daadwerkelijke geheugenprofiel van je app — check wat je GC-getunede Rails-proces werkelijk gebruikt.

Bind Postgres aan localhost. De 127.0.0.1:5432:5432 mapping houdt je database van het publieke internet af. Ik heb Kamal-tutorials gezien die de database-poort blootstellen zonder dit — dat is vragen om problemen op een €10 VPS zonder firewall.

Builder arch moet overeenkomen met je server. Als je ontwikkelt op Apple Silicon maar deployt naar een AMD64-server, stel dan arch: amd64 in. Zonder dit bouwt Kamal een ARM-image dat direct crasht op de server met een cryptische exec format error.

Stap 3: Secrets instellen

Maak een .kamal/secrets-bestand aan (niet committen naar git):

KAMAL_REGISTRY_PASSWORD=your_docker_hub_token
RAILS_MASTER_KEY=inhoud_van_config_master.key
DATABASE_URL=postgresql://myapp:geheimwachtwoord@myapp-db:5432/myapp_production
POSTGRES_PASSWORD=geheimwachtwoord

Kamal leest dit bestand automatisch tijdens deployment. Voor teamomgevingen kun je secrets ophalen uit 1Password, AWS SSM of elk commando dat KEY=VALUE-paren uitvoert.

Stap 4: Server voorbereiden

kamal server bootstrap

Dit SSHt naar je server(s) en installeert Docker. Op een verse Ubuntu VPS duurt het ongeveer 60 seconden.

Stel daarna de database-accessoire in:

kamal accessory boot db

Stap 5: Deploy

kamal deploy

De eerste deploy duurt 3-5 minuten (Docker-image bouwen, pushen, pullen op de server). Volgende deploys zijn sneller dankzij Docker layer caching — meestal 60-90 seconden als alleen je applicatiecode is gewijzigd.

Wat er gebeurt tijdens kamal deploy:

  1. Bouwt het Docker-image lokaal (of op een remote builder)
  2. Pusht het image naar je registry
  3. Pullt het image op elke server
  4. Draait kamal deploy hooks (indien geconfigureerd)
  5. Start de nieuwe container
  6. Kamal Proxy health-checkt de nieuwe container
  7. Wisselt verkeer van oude naar nieuwe container
  8. Stopt de oude container

De verkeerswisseling is de grote verbetering ten opzichte van Capistrano. Er is geen moment waarop je app down is tijdens deployment.

Stap 6: Database-migraties

Kamal draait migraties niet automatisch. De aanbevolen aanpak:

kamal app exec --primary "bin/rails db:migrate"
kamal deploy

Dit geeft je de kans om te verifiëren dat de migratie is geslaagd voordat je verkeer wisselt. Voor zero-downtime migraties is dit de veiligste aanpak — draai je backward-compatible migratie, controleer het resultaat en deploy dan de code die ervan afhankelijk is.

Stap 7: SSL met Kamal Proxy

SSL-setup is automatisch:

proxy:
  ssl: true
  host: myapp.com

Kamal Proxy gebruikt Let’s Encrypt om certificaten te provisioneren en te vernieuwen. Wijs het DNS A-record van je domein naar het IP van je server, deploy, en SSL werkt. Geen certbot-configuratie, geen cron-jobs voor vernieuwing.

Let op: het eerste request na deployment kan traag zijn (2-3 seconden) omdat Kamal Proxy het certificaat on-demand provisioneert.

De valkuilen

Na een paar maanden Kamal 2 in productie, zijn dit de problemen die daadwerkelijk opdoken:

Docker-image groei. De standaard Rails 8 Dockerfile gebruikt multi-stage builds, maar je image kan alsnog opblazen als je niet oplet. Check met docker images — als je app-image groter is dan 500MB, kijk wat er wordt gekopieerd. Veelvoorkomende boosdoeners: node_modules in de finale stage, testbestanden, development gems. Een goed geoptimaliseerd Rails 8-image is 200-350MB.

Log-rotatie. Kamal stelt geen log-rotatie in. Docker’s standaard logging driver bewaart alles in JSON-bestanden die onbeperkt groeien. Voeg dit toe aan je deploy config:

servers:
  web:
    hosts:
      - 203.0.113.42
    options:
      log-opt: max-size=50m
      log-opt: max-file=3

Health check-fouten bij traag opstartende apps. Kamal Proxy checkt standaard /up. Als je Rails-app meer dan 7 seconden nodig heeft om op te starten, faalt de health check en wordt de deploy teruggedraaid. Verhoog de timeout:

proxy:
  healthcheck:
    interval: 3
    timeout: 30

Monitoring en onderhoud

Handige commando’s na deployment:

# Bekijk logs
kamal app logs -f

# Open een Rails console
kamal app exec -i "bin/rails console"

# Bekijk containerstatus
kamal details

# Rollback naar vorige versie
kamal rollback

Kamal vs. Capistrano: wanneer overstappen

Stap over naar Kamal als:

  • Je zero-downtime deploys wilt zonder Puma phased restarts te configureren
  • Je nieuwe servers opzet en geen Ruby/Node-installaties wilt beheren
  • Je een enkele tool wilt voor proxy, SSL en deployment
  • Je een nieuwe Rails 8-app start (Kamal is de standaard — gebruik het gewoon)

Blijf bij Capistrano als:

  • Je team het door en door kent en je deploy-pipeline solide is
  • Je complexe multi-stage deploy-workflows hebt die afhankelijk zijn van Capistrano’s taaksysteem
  • Je nog niet klaar bent om je app te containerizen

FAQ

Hoeveel kost een Kamal-deployment?

De tool zelf is gratis en open source. Je kosten zijn de VPS (€5-20/maand voor een kleine app) en de Docker registry (Docker Hub’s gratis tier geeft je één privé-repo, genoeg voor een enkele app). Geen managed Kubernetes-cluster, geen container orchestration-dienst.

Kan ik naar meerdere servers deployen met Kamal 2?

Ja. Voeg meer hosts toe onder de web-key in deploy.yml. Kamal deployt parallel naar alle servers. Je hebt een load balancer voor ze nodig (een simpele Nginx of HAProxy, of de load balancer van je cloudprovider).

Hoe ga ik om met background jobs in Kamal?

Definieer een aparte serverrol voor je background job processor:

servers:
  web:
    hosts:
      - 203.0.113.42
  worker:
    hosts:
      - 203.0.113.42
    cmd: bundle exec sidekiq

Solid Queue-gebruikers kunnen het in hetzelfde proces als Puma draaien — geen aparte worker-container nodig.

Wat gebeurt er als een deploy faalt?

Kamal Proxy blijft verkeer naar de oude container sturen. De nieuwe container faalt zijn health check en wordt gestopt. Je app blijft draaien op de vorige versie. Draai kamal rollback om op te ruimen, los het probleem op en deploy opnieuw.

Kan ik van Capistrano naar Kamal migreren zonder downtime?

Ja, maar reken op 5-10 minuten setup. De basisaanpak: stel Kamal in gericht op dezelfde server, deploy je app naast de Capistrano-versie op een andere poort, verifieer dat het werkt, en wijs dan je DNS of reverse proxy naar de Kamal-container. Zodra verkeer via Kamal loopt, kun je de Capistrano-setup ontmantelen.

T

About the Author

Roger Heykoop is een senior Ruby on Rails ontwikkelaar met 19+ jaar Rails ervaring en 35+ jaar ervaring in softwareontwikkeling. Hij is gespecialiseerd in Rails modernisering, performance optimalisatie, en AI-ondersteunde ontwikkeling.

Get in Touch

Share this article

Need Expert Rails Development?

Let's discuss how we can help you build or modernize your Rails application with 19+ years of expertise

Schedule a Free Consultation