Skip to content
All docs

Docs

Troubleshooting

Symptom-keyed runbook for the panel, Traefik, deployments and restores.

Start with the readiness endpoint — it names the failing check before you read a single log line.

sh
1curl -sk https://<panel-host>/api/ready | jq 2docker service logs --tail 100 nixploy

Install

  • Ports 80/443 in use — `ss -ltnp | grep -E ':(80|443)\s'`, then stop nginx/Apache/Caddy. Re-runs are fine: nixploy-traefik is allowed to hold its own ports.
  • Rootless Docker — `docker info` listing `rootless` under SecurityOptions. There is no workaround; install Docker Engine as root.
  • Setup URL shows a private IP, or sign-in says "Invalid origin" — BETTER_AUTH_URL must be exactly the origin you browse to. Re-run with NIXPLOY_DOMAIN=… or NIXPLOY_PUBLIC_IP=….

Updates

  • Rolled back — `docker service ps nixploy --no-trunc` names the failed task; restore the pre-update dump from /etc/nixploy/backups if a migration half-applied.
  • /api/ready says migrations "behind" — the migration step did not finish (Postgres not up yet, or a full disk). Fix the cause, then `docker service update --force nixploy`.
  • Deployments show "Interrupted" — only the jobs that were actually building are lost: the queue lives in Postgres, so anything still queued is claimed again on the next boot. Redeploy the interrupted services. A split-worker install avoids it entirely, because rolling the panel does not touch the builder.
  • Refusing to downgrade — migrations are forward-only. Restore the pre-update dump taken before the version you are leaving, then re-run with the downgrade guard disabled.

TLS and domains

  • A domain with HTTPS off still redirects — an install from before v0.2.0 still has the entrypoint redirect in traefik.yml. Re-run update.sh; it removes the block and restarts the proxy.
  • Stuck on the self-signed certificate — check the ACME email (not nixploy@localhost), the DNS A record, and that port 80 is reachable from the internet.
  • Let's Encrypt rate limits — 5 failed validations per hostname per hour. Fix DNS first, then attach the domain; retrying faster makes it worse.
  • acme.json must be mode 600 — a restore with a permissive umask is the usual way it breaks.
  • Traefik 404s a running service — a service joins the shared network only while it has a domain. Re-save the domain to reconcile it.
  • Editing traefik.yml by hand changes nothing until the proxy restarts: Traefik reads its static config once at start. Only the dynamic directory hot-reloads.

Networking and deployments

  • App cannot reach another service by name — since v0.2.0 each environment has its own overlay, so a service resolves only services of its own environment.
  • ping inside a container fails — NET_RAW is dropped from tenant containers. Uptime Kuma ICMP monitors will not work; use HTTP or TCP monitors.
  • Swarm tasks stay Pending — `docker service ps <appName> --no-trunc` prints the reason: insufficient resources, a stale placement pin, or a pruned image.
  • A service suddenly has CPU/memory limits — org quotas are now applied as per-service resource limits when the service sets none (1024 shares = 1 CPU).
  • Compose validation rejects a file that used to work — the deny-list grew (cgroup_parent, unbounded tmpfs, foreign log drivers, global mode, manager placement). The error names the key.
  • A managed server answers "unreachable over SSH" — the circuit breaker opened after repeated connection failures. The message says when Nixploy retries; Test connection closes it immediately.

Disk

sh
1df -h /etc/nixploy && docker system df 2docker image prune -f && docker builder prune -af

Never run `docker image prune -a` on a Nixploy host: a stopped application has no container, so "all unused" pruning deletes the only copy of its locally built image. Set NIXPLOY_DOCKER_CLEANUP_CRON for a safe weekly prune, and watch the disk platform alert (85% warning, 95% critical).

Restores

  • A restore fails with "relation already exists" — the dump predates --clean --if-exists. Drop and recreate the database, or re-dump.
  • Everything decrypts to garbage — ENCRYPTION_KEY does not match the one that wrote the data. It lives in /etc/nixploy/.env, which is deliberately excluded from backups: keep your own copy.
  • Rehearse before you need it: tools/dr-restore-test.sh restores into a throwaway Postgres container and can boot the panel against it.

Also see the repository guides under docs/ · REST API reference

Rent the box. Keep the rest.

One command, three services, and the first account is yours.