Kamal is built for Linux servers, so a Mac mini needs a few workarounds. It works because Kamal only needs SSH plus a working docker command on the target. Here’s the path:
1. Prepare the Mac mini
Docker via Colima, started at boot (from the previous answer):
brew install colima docker
brew services start colima
Make docker available to non-interactive SSH sessions. This is the most common failure. Kamal runs commands over SSH without loading your login profile, so Homebrew’s path is missing. On the mini, add to ~/.zshenv (not .zprofile):
export PATH="/opt/homebrew/bin:$PATH"
Verify from the MacBook:
ssh youruser@mac-mini.local docker ps
If that prints a container list (even empty), you’re set.
SSH keys (so Kamal can log in without a password):
ssh-copy-id youruser@mac-mini.local
2. Set up Kamal in your Rails app
Rails 8 already includes Kamal and a Dockerfile. Otherwise:
bundle add kamal
bundle exec kamal init
Make sure you have a production-ready Dockerfile (Rails 7.1+ generates one).
3. Configure config/deploy.yml
service: myapp
image: yourdockerhubuser/myapp
servers:
web:
- mac-mini.local # or the mini's IP
ssh:
user: youruser
proxy:
ssl: false # no Let's Encrypt on a LAN-only host
app_port: 80 # Rails 8 Dockerfile uses Thruster on 80; use 3000 for older Dockerfiles
registry:
username: yourdockerhubuser
password:
- KAMAL_REGISTRY_PASSWORD
builder:
arch: arm64 # the mini is Apple Silicon; use amd64 if it's an Intel mini
env:
secret:
- RAILS_MASTER_KEY
volumes:
- "myapp_storage:/rails/storage" # persists SQLite DB / uploads (Rails 8 default)
Notes:
- Registry: Kamal pushes the image to a registry and the mini pulls it. Docker Hub or GitHub Container Registry both work. Kamal 2 also supports a local registry (
registry: server: localhost:5555) if you don’t want an account. - Builder arch: If your MacBook is Apple Silicon too, builds are native and fast. If it’s Intel and the mini is ARM, Kamal will cross-build, which is slower.
4. Secrets
In .kamal/secrets:
KAMAL_REGISTRY_PASSWORD=$KAMAL_REGISTRY_PASSWORD
RAILS_MASTER_KEY=$(cat config/master.key)
Export your registry token in your shell first, or pull it from a password manager.
5. Adjust Rails for plain HTTP
Since there’s no SSL, in config/environments/production.rb set:
config.assume_ssl = false
config.force_ssl = false
Otherwise Rails redirects to HTTPS and you’ll get redirect loops or failed health checks.
6. Deploy
kamal setup # first time: bootstraps, boots kamal-proxy, builds, pushes, deploys
kamal deploy # subsequent deploys
Then open http://mac-mini.local in your browser.
Useful commands: kamal app logs -f, kamal app exec -i bash, kamal rollback <version>.
Gotchas
- Docker bootstrap:
kamal setuptries to install Docker if it isn’t found, and that only works on Linux. If the PATH fix above is in place, Kamal detects Docker and skips this. - Sleep: Keep the mini awake (Energy settings, “Wake for network access”), otherwise your app disappears.
- Colima resources: The default is 2 CPUs/2 GB RAM. For a Rails app plus a database you may want
colima start --cpu 4 --memory 6. - Ports 80/443: Colima forwards these, but if something else on the mini already uses port 80, kamal-proxy will fail to start.
- Reliability: Colima inside macOS is fine for a home setup, but it isn’t a typical production target. If you run into odd issues, a small Ubuntu VM on the mini (via UTM/Multipass) would be a closer match to what Kamal expects.
If you want to reach the app from outside your home, Tailscale (or Cloudflare Tunnel with a real domain for SSL) pairs well with this. Tell me whether your app uses SQLite or Postgres and I can add the database part to the config.
🤖 created with help of ai