Troubleshooting

Fix a startup error, a backend that won't connect, a sign-in that does nothing or a lost admin account.

Updated 4 min read Edit on GitHub
On this page

Common problems and where to look. Logs are structured (Pino) and secret-redacted

  • docker compose logs app is your first stop for almost everything here.

The app won't start#

[env] Environment validation failed - a required variable is missing or malformed; the message lists each offending key. Check APP_URL (fully-qualified, no trailing slash), APP_SECRET_KEY/APP_ENCRYPTION_KEY (long enough, not placeholders), and DATABASE_URL. See Configuration.

OIDC_ENABLED=true but missing required keys - set all five: OIDC_PROVIDER_ID, OIDC_PROVIDER_NAME, OIDC_ISSUER_URL, OIDC_CLIENT_ID, OIDC_CLIENT_SECRET.

SMTP configuration is invalid / BOOTSTRAP_ADMIN_* must be set together - cross-field rules: SMTP_FROM is required with SMTP_HOST; SMTP_SECURE=true can't combine with SMTP_STARTTLS=required; SMTP_USERNAME/SMTP_PASSWORD are all-or-nothing; the two bootstrap-admin vars are all-or-nothing.

A migration failed - the boot aborts on purpose rather than running a half-migrated schema. The logs print the pending migrations and where it stopped. Fix the cause (often a DB permission or connectivity issue) and restart.

Build-time placeholder values detected at runtime - NEXT_PHASE is set in the runtime env, or the deploy didn't override the secrets. Generate real APP_SECRET_KEY/APP_ENCRYPTION_KEY and unset NEXT_PHASE.

I can't reach a PowerDNS backend#

  • URL rejected when adding it - the SSRF guard blocks private-network or http:// URLs by default in production. Set APP_PDNS_ALLOW_PRIVATE_NETWORKS=true and/or APP_PDNS_ALLOW_INSECURE_HTTP=true as needed (link-local / 169.254.169.254 is always blocked). See Backends.
  • Status shows "Not yet reached" / dashboard flags it stale - the app can't contact the API. Verify the base URL ends in /api/v1, the X-API-Key matches PowerDNS's api-key, and webserver-allow-from on PDNS permits the app's IP. Use the Test button for an immediate probe.
  • Reachable but no zones - confirm api=yes and that the API key has access to the server_id you configured (almost always localhost).

Zone or record edits fail on some backends but not others#

Symptom: the same edit succeeds when you retry it, then fails again later, seemingly at random. Usually a permission or read-only error surfaced from PowerDNS rather than from AuthAdmin.

Almost always a group where not every peer can actually accept writes. The peer-selection strategy rotates each request across the group's write targets, so a node that rejects writes takes roughly its share of your edits and the failures look intermittent.

The common shape is a hidden primary whose zones are Native, replicated to the public nameservers through the database rather than AXFR, where those public nodes run against a read-only database user. PowerDNS reports them as primary=no, secondary=no - indistinguishable from a standalone primary - so AuthAdmin can't detect the difference on its own.

Fix: open each node you only read from under Admin -> PowerDNS servers, tick Never write to this backend (read-only), and save. Writes then land only on the real write target, and the group re-labels itself Primary + secondaries. In provisioning YAML, set write_mode: read_only on the server row. See Backends -> Hidden primary.

Note this is unrelated to Use as the default backend, which only picks which backend serves a request that doesn't name one.

APP_URL's host doesn't match the URL you have in the address bar. The session and CSRF cookies are scoped to APP_URL's host, so the browser silently drops them on a mismatch and every login submit looks like it just reloads the page.

The login page renders an inline error when this happens. To fix it: set APP_URL to the exact scheme + host + port operators type in their browser (e.g. http://192.168.1.10:3000 if that's how you reach the LAN host, not the http://localhost:3000 from .env.example). Restart the app and reload the sign-in page.

OIDC sign-in problems#

  • redirect_uri mismatch at the IdP - register exactly <APP_URL>/api/auth/oidc/<slug>/callback. A wrong APP_URL is the usual cause.
  • "Sign-in refused: not authorized" - the email's domain isn't in the provider's allowed_email_domains (or OIDC_ALLOWED_EMAIL_DOMAINS), or the user is disabled.
  • "identity provider did not attest … verified" - the IdP didn't send email_verified: true. Fix it at the IdP, or (DB providers only) relax requireEmailVerified.
  • Groups don't map to roles - the env provider can't map groups; use a DB provider. Confirm the IdP emits the groups claim and claim_groups matches; the audit log records auth.group_sync.mapping_unresolved (provider slug in after.provider) for mappings whose role/team/server can't be resolved.
  • My env provider isn't on the login page - it only hides when a DB provider shares its slug (shadowing). See OIDC.

Email isn't being sent#

With SMTP_HOST unset, mail is skipped by design - verify-email, reset and email-change links won't go out. Verification and email-change links are recorded on their audit row (after.url, actions auth.email.verify.sent / auth.email.change.requested) for an operator to hand over out-of-band. The password-reset link is only printed once in the server log at warn level (never in the audit log), so docker compose logs app is where to find it; for a forgotten password the admin Reset password action on /admin/users/<id> is the supported alternative. Set the SMTP_* vars to enable delivery. If set but failing, check the logs for the SMTP error and confirm the encryption mode matches the port (465 implicit TLS vs 587 STARTTLS). See Configuration.

I'm locked out / lost the admin#

  • A failed-login lockout auto-clears after login_lockout_seconds (default 15 min).
  • If the Default sign-in method is an IdP that is sending you straight to a broken login, append ?force-local=1 to /login to get the local form back.
  • To re-bootstrap an admin, set BOOTSTRAP_ADMIN_EMAIL + BOOTSTRAP_ADMIN_PASSWORD and restart - the seed ensures that account exists (and won't clobber others).

Re-running provisioning#

Provisioning runs once (guarded by a provisioned_at settings row). To re-apply, delete that row and restart - see Provisioning → re-apply.

Still stuck?#

Open an issue with your logs (already secret-redacted) at github.com/PowerDNS-AuthAdmin/powerdns-authadmin/issues. For a suspected vulnerability, follow SECURITY.md instead.


← Docs index