Runbook: the keferboeck-ltd droplet
The host for every Keferboeck Ltd app (and the GrowCentric sites, documented in their own knowledge base).
- Host:
keferboeck-ltd,161.35.42.199, DigitalOcean, London (lon1) - Model: multi-app Docker host managed with Kamal, fronted by kamal-proxy on 80/443 (TLS via Let's Encrypt). DNS is on DigitalOcean nameservers pointing straight at the droplet.
- Apps (containers):
keferboeck-web(keferboeck.com),portal-web(hub.keferboeck.com), the demo shopshampers-web,joinery-web,marlowfinch-web,wagwhisker-web,flugschule-web(each on<name>.keferboeck.com), and the GrowCentric pair (growcentric-web,growcentric-app-web), plus per-app Postgres and Redis accessories. - Deploy: from each app repo,
kamal deploy(build + push + boot). Env/secrets come from each repo's.kamal/files; the marketing site builds a standalone Next.js image.
Email (Mailjet)
All droplet apps and the uptime monitor send through one Mailjet key (prefix 453c, the
Keferboeck account). Verified sender domain is keferboeck.com (wildcard). Note:
noreply@growcentric.ai is not active on that account, so growcentric app email must send
from a keferboeck.com address or the growcentric.ai domain must be verified in Mailjet.
Uptime monitoring
- Location:
/opt/uptime-monitor/on the droplet. Hourly cron at:17. - Checks six sites (growcentric.ai, app.growcentric.ai, keferboeck.com, hampers/joinery/hub
.keferboeck.com). Healthy = HTTP 200-399. On failure it emails
georg@keferboeck.comvia Mailjet and repeats hourly until recovery. check.sh testsends a confirmation email.urls.txtis the monitored list.
Common tasks
# tail a running app's logs
kamal app logs -f # from the app repo
# reboot an app with fresh env (no rebuild)
kamal app boot # add -d staging for staging destinations
# see what the proxy is routing
ssh root@161.35.42.199 'docker exec kamal-proxy kamal-proxy list'
Shop-specific tasks
# from a shop directory (hampers/, joinery/, marlowfinch/, wagwhisker/, flugschule/)
kamal deploy # release that shop only
kamal app logs -f # tail it
kamal app exec 'bin/rails runner "Rails.cache.clear"' # bust fragment caches after copy changes
# demo data
kamal app exec 'bin/rails demo:reset_catalogue' # manual reset (nightly at 04:15 anyway)
kamal app exec 'bin/rails demo:image_brief' # regenerate the photography brief
Fragment caching
Product pages cache aggressively keyed on product and pricing, not template content.
Copy or locale changes need a Rails.cache.clear per shop after deploy, or they will
look unreleased.