Answers · Deploying

How do I see production logs for a deployed Rails app?

Run kamal app logs --follow to stream, or kamal app logs --lines 200 --grep Error to search what already happened. Rails 8 logs one line per request in production, so the useful move is filtering by request id and following that one request through the job and mailer lines it produced.

The commands worth memorizing

bin/kamal app logs --follow
bin/kamal app logs --lines 500 --grep "Completed 500"
bin/kamal app logs --lines 500 --grep "<request-id>"

The third one is the one that turns a wall of text into a story. Every log line in production carries the request id, so grepping it gives you the request, the SQL it ran, the job it enqueued and the mail it sent, in order.

Find the request id from the outside

curl -sI https://yourdomain.com/up | grep -i x-request-id

Rails echoes the id in a response header, so a user who can reproduce a problem can hand you the id from their browser's network tab and you can pull exactly their request.

Logs are not a monitoring system

Container logs rotate and are lost when the container is replaced, which happens on every deploy. For anything you need after the fact, send it somewhere durable. One Shot has an error reporter seam at app/adapters/error_reporter.rb that follows the same adapter and fake pattern as the rest of the kit: it no-ops without credentials and reports to a real service with them. That is where an exception tracker plugs in, not into a log grep.

Turn down the noise before you need it

Production defaults to :info, which includes every request. The level is set in config/environments/production.rb. If the log is unreadable, that is usually assets or health checks rather than your app. The health check route is declared at the top of config/routes.rb and is hit every few seconds by design, so filtering it out is the first thing worth doing:

bin/kamal app logs --lines 500 | grep -v "/up"

When the container will not start at all

kamal app logs reads a running container. If the deploy failed on the health check, the container already exited, and the same command still shows its final output. That is where the boot error is, and it is almost always a secret that did not arrive. See First Deploy Checklist.

Related questions

How do I deploy a Rails 8 app without Heroku?

Use Kamal, which ships with Rails 8. You give it a server over SSH and a container registry in config/deploy.yml, run kamal setup once, and kamal deploy after that. It builds an image, pushes it, and swaps containers with no downtime. A $5 VPS replaces the PaaS.

How do I deploy a Rails app from GitHub Actions?

Run kamal deploy as a workflow step. Kamal needs three things in the runner: an SSH key that can reach the server, registry credentials, and RAILS_MASTER_KEY. All three go in as repository secrets and are read by .kamal/secrets. Gate the deploy job behind the test job so a red build never ships.

How do I fix no space left on device on a deploy server?

Old container images are the cause, not your app. Every deploy pushes a new image and the server keeps the old ones. Run docker image prune -a -f to reclaim the space, then check with df -h. On a 25GB VPS this usually returns several gigabytes, and it is worth doing before you are locked out rather than after.