When something's wrong¶
Organised by what you're seeing. You can't SSH into your box — it's firewalled to
web traffic only — so every tool here is a CLI command or the dashboard. That sounds
limiting and mostly isn't: allocus logs reaches the container logs, and allocus
status reaches the meters.
The three commands worth learning first¶
allocus deploy --wait # block until the box says healthy, or name what failed
allocus logs # this repo's app, last 200 lines from the container
allocus status # is the box alive, and how loaded is it
--wait is the important one. Without it, allocus deploy returns as soon as the
deploy is queued, so a build that pushed fine but an app that won't start looks
identical to success. With it, you get the reason.
The deploy failed¶
Run it again with --wait and read the message. It comes from your box, not from the
control plane, so it's about your app rather than about Allocus.
"…did not become healthy in time" — your containers started but the healthcheck never passed within two minutes. Almost always one of:
- the app is bound to
127.0.0.1instead of0.0.0.0(see below), - it's waiting on a database that isn't up yet — declare the dependency:
depends_on: {db: {condition: service_healthy}}, - it genuinely takes longer than two minutes to boot, which usually means a migration running at startup. Move it to a one-shot migrate service instead.
allocus logs right after a failed deploy is the fastest next step — the containers
are left running, so the logs are there.
"docker compose pull failed" — the box couldn't fetch your image. If the build
and push succeeded locally this is nearly always a transient registry error; retry.
"docker compose up failed" — a problem in the generated compose file, usually a
volume or a port. allocus render prints exactly what your box was handed, which is
faster than guessing.
The build failed before any of that¶
Then it's a local Docker problem and nothing has left your machine. allocus deploy
checks up front that Docker is installed, Buildx is present and the daemon is running,
so a clear message there means exactly what it says. Note that images are always
cross-built for linux/amd64 — a Dockerfile that only works on arm64 (a base image
with no amd64 tag, say) fails here even though it builds fine locally with docker
build.
A successful deploy is not proof your app works
The health gate only checks what it can see. A container that exits counts as a
failed deploy — unless the service asked to run to completion with restart: "no",
which is how a one-shot migration job is meant to end. What no gate can spot without
help is an app that stays up while serving errors. Add a HEALTHCHECK to your
Dockerfile and the gate starts earning its keep:
The URL loads nothing, or a 502¶
The deploy worked and https://<app>.<you>.allocus.dev doesn't. In order of how often
it's the cause:
- The app is listening on
127.0.0.1. Inside a container that means "reachable only from inside this container", so Traefik gets a connection refused → 502. Bind0.0.0.0. This is the single most common one, and frameworks default to localhost in development mode. - The port doesn't match. The
portinallocus.yamlmust be the port your process actually listens on. If you moved it, both have to move. - The container isn't running.
allocus logswill show you the crash. - You're expecting a path that isn't routed. In a stack, exactly one public
service may omit
path:; that one catches everything unmatched. If every public service has apath:, anything outside those prefixes is a genuine 404 — see multiple public endpoints. strip_pathis the wrong way round. A backend onpath: /apireceives/api/usersby default. If it serves/users, setstrip_path: true. Getting this backwards gives 404s from your app rather than from Traefik.
The certificate is wrong, or the browser complains¶
Your box holds one wildcard certificate for *.<you>.allocus.dev, and a wildcard
covers exactly one level. So:
myapp.you.allocus.dev— covered, works from the first deploy.api.myapp.you.allocus.dev— not covered, and can't be. Route by path instead of by sub-subdomain.
On a brand-new box the certificate is issued during provisioning, before you can deploy anything, so there's no first-deploy wait to sit through. If TLS is broken on a box that used to work, that's an Allocus problem rather than yours — email the contact address and say which box.
An app keeps restarting for no reason¶
This is what running out of memory looks like, and it's the most common surprise on a small box. Two different limits can bite:
The box ran out. When a Linux machine exhausts its memory, the kernel kills the
process using the most of it — which is usually an unrelated app, so the symptom lands
somewhere confusing. Check the memory meter on your dashboard or in allocus status.
If it sits near the top, that's your answer: size up, or run fewer
things.
One service hit its own limit. Each service in a stack gets a per-service memory
cap, and the default is deliberately small (256M) so one app can't wedge the whole
box. That is fine for a small web process and far too little for Postgres, a JVM, or
anything doing server-side rendering. Raise it for the services that need it:
allocus render prints the effective limits, so you can check rather than assume.
A container killed for exceeding its own limit dies abruptly with no error in your
app's logs — an unexplained restart loop with nothing logged is the signature.
Everything is slow¶
Look at allocus status. Sustained CPU at 100% means requests are queueing; brief
spikes during a deploy are normal and not worth acting on. There is no throttling and
no quota involved — your box is simply doing more than it can. Box
sizes covers reading the meters and what a resize costs.
The box says stale or offline¶
Health comes from a heartbeat your box sends every few seconds. stale means it's
gone quiet, offline that it's been quiet a while.
Your running apps keep serving traffic regardless — Traefik and your containers
are self-contained on the box and don't need the control plane. What you lose while a
box is quiet is the management channel: deploys queue instead of running, and logs
gets no answer. If it doesn't come back within a few minutes, that's ours to fix.
The same is true in reverse: if the control plane is down, your apps carry on serving and you simply can't deploy until it's back.
Disk is filling up¶
You don't need to prune anything — the box clears out container images older than a week, every week, on its own, and container logs are capped at 10 MB × 3 files each, so a chatty app can't fill the disk.
Which means disk pressure on Allocus is almost always your data: a Postgres volume, uploaded files, something accumulating in a named volume. Disk is a flat 20 GB on every plan and sizing up does not change it — block volumes can grow but cannot shrink, so a per-plan disk would make every downgrade destructive.
The lever you do have is removing an app you no longer want, which deletes its volumes along with it:
allocus apps # what's actually on the box
allocus remove old-experiment # takes the volumes too
allocus remove blog --keep-data # …unless you say otherwise
If 20 GB genuinely isn't enough for your data, Allocus is the wrong shape for that app right now. Point it at a managed database off the box.
I need to see what's really happening¶
The box is firewalled, so this works by asking the box's agent to run docker compose
logs and send the output back. It arrives within a few seconds. Note the round trip:
that output passes through the control plane's database on the way to you, so anything
your app prints ends up there too — see Your data.
There is no exec, no shell, and no way to attach to a running container. If you need
to poke at something interactively, the intended loop is docker compose up on your
laptop with the same compose file allocus render prints.
Nothing here matches¶
Email the support address at the foot of allocus.dev. A person answers — the same person who runs the service. Include the app name and roughly when it happened; that's enough to find it.
If a provisioning or resize step failed, the dashboard tells you it failed and offers a Retry; the underlying error is recorded on our side, so mentioning the time is genuinely all we need from you.