Files
dezky/docs/TROUBLESHOOTING.md
T
Ronni Baslund 22b2583f0b chore(services): rename services/provisioning -> services/platform-api
O.0 prep from OPERATOR-PLAN.md. Mechanical refactor before adding partner
management and operator-specific endpoints. The service now owns more than
just provisioning orchestration (it'll soon own partners, tenant lifecycle
actions, multi-audience JWT validation), so the name 'platform-api' reflects
its scope better.

What changed:
- Directory: services/provisioning/ -> services/platform-api/
- Package: @dezky/provisioning -> @dezky/platform-api
- Docker: container_name dezky-provisioning -> dezky-platform-api;
  compose service key 'provisioning' -> 'platform-api'; volume
  provisioning_node_modules -> platform_api_node_modules
- Portal: PROVISIONING_INTERNAL_URL env var -> PLATFORM_API_INTERNAL_URL,
  default URL http://provisioning:3001 -> http://platform-api:3001 in all
  three proxy routes (me.get.ts, tenants/index.post.ts, tenants/[slug]/
  reconcile.post.ts), plus NUXT_API_BASE updated
- Health endpoint service identifier and main.ts log lines updated to
  'dezky-platform-api'
- Docs swept: README, CLAUDE.md, SERVICES.md, AUTHENTIK-SETUP.md,
  NEXT-STEPS.md, TROUBLESHOOTING.md, OPERATOR-PLAN.md, traefik/dynamic.yml

What deliberately stays:
- Internal module names ProvisioningService / ProvisioningModule (those
  describe an orchestration sub-concern, not the service's purpose)
- Tenant.provisioningStatus / provisioningErrors field names (state
  per integration, not service name)
- File services/platform-api/src/tenants/provisioning.service.ts
- 'Hetzner provisioning' references in production-prep docs (infrastructure
  provisioning, unrelated)

Verified end-to-end after rename: /api/me returns 200 with profile + 2
tenants + subscription, /api/tenants/dezky/reconcile returns 200 with
Authentik integration still ok.

OPERATOR-PLAN.md O.0 checkboxes ticked.
2026-05-24 00:35:01 +02:00

6.6 KiB

Troubleshooting

Common issues and fixes when running the Dezky local development stack.

TLS / Certificate issues

Browser shows "Not Secure" or certificate warning

mkcert root CA isn't trusted in your browser yet.

mkcert -install

Then fully restart your browser (quit, not just close window).

Certificate not loading in Traefik

Verify the cert files exist:

ls -la infrastructure/docker-compose/certs/
# Should show:
#   dezky.local.pem
#   dezky.local-key.pem

If they're named differently (e.g. _wildcard.dezky.local+1.pem), rename them:

cd infrastructure/docker-compose/certs/
mv _wildcard.dezky.local+*.pem dezky.local.pem
mv _wildcard.dezky.local+*-key.pem dezky.local-key.pem

Then restart Traefik:

docker compose restart traefik

Service-to-service TLS errors

Inside Docker, services talk via internal hostnames (e.g. authentik-server:9000), not auth.dezky.local. Internal traffic uses HTTP, not HTTPS. Only Traefik handles TLS termination.

If a service config has https://authentik-server, change it to http://authentik-server.


Container startup issues

Authentik fails to start

Most common cause: PostgreSQL not ready yet, or password mismatch.

# Check postgres is healthy
docker compose ps postgres
# Should show "healthy" in STATUS

# Check Authentik DB user exists
docker compose exec postgres psql -U postgres -c "\du"
# Should list "authentik" as a user

# Check Authentik logs
docker compose logs authentik-server | tail -50

If password is wrong, reset and re-bootstrap:

./scripts/reset.sh
./scripts/bootstrap.sh

Port 25 conflict (Stalwart fails to bind)

macOS often has Postfix running by default:

sudo launchctl unload /System/Library/LaunchDaemons/org.postfix.master.plist 2>/dev/null || true
sudo launchctl stop org.postfix.master 2>/dev/null || true

Or just disable the SMTP port mapping in docker-compose.yml for local dev:

stalwart:
  # ports:
  #   - "25:25"   # comment out if conflicting

Port 80/443 conflict (Traefik fails to bind)

Another service is using those ports.

# Find what's using port 80
sudo lsof -nP -i:80 -sTCP:LISTEN

Common culprits: nginx, apache, Caddy, other Docker stacks. Stop them or change Traefik to use 8080/8443.

OCIS crashes on first start

OCIS needs to initialize before running. The compose file does this via:

command: ["-c", "ocis init --insecure true || true && ocis server"]

If init fails:

# Manually init
docker compose run --rm ocis ocis init --insecure true

# Then start
docker compose up -d ocis

DNS / hostname issues

app.dezky.local doesn't resolve

Check /etc/hosts:

grep dezky.local /etc/hosts

Should see entries pointing 127.0.0.1 to all hostnames. If missing, run:

./scripts/bootstrap.sh   # Will offer to add them

Or manually:

echo "127.0.0.1  dezky.local app.dezky.local auth.dezky.local mail.dezky.local files.dezky.local office.dezky.local meet.dezky.local chat.dezky.local traefik.dezky.local" | sudo tee -a /etc/hosts

Browser DNS cache holding old entry

Clear browser cache, or test from terminal:

ping app.dezky.local
# Should return 127.0.0.1

If terminal resolves but browser doesn't:

  • Chrome: chrome://net-internals/#dns → Clear host cache
  • Firefox: about:networking#dns → Clear DNS cache

Authentik OIDC integration issues

"Invalid issuer URL"

The iss claim in the JWT must match exactly what the consuming service expects.

# In docker-compose.yml for OCIS:
OCIS_OIDC_ISSUER: https://auth.dezky.local/application/o/ocis/

The trailing slash matters. Authentik issues with trailing slash by default.

Verify the actual issuer:

curl -s https://auth.dezky.local/application/o/ocis/.well-known/openid-configuration | jq .issuer

"redirect_uri not allowed"

The OAuth provider in Authentik must list every redirect URI the client might use.

For OCIS:

https://files.dezky.local/
https://files.dezky.local/oidc-callback

Add both. Patterns matter — exact match.

Login loop (redirects forever)

Usually caused by:

  1. Time mismatch between container and host. Check docker compose exec ocis date matches host clock.
  2. Cookie domain mismatch. Cookies set for .dezky.local should work across subdomains.

Hot reload not working

Nuxt portal doesn't rebuild on file changes

The volume mount works on macOS but file watching needs explicit polling:

Add to apps/portal/nuxt.config.ts:

export default defineNuxtConfig({
  vite: {
    server: {
      watch: {
        usePolling: true,
        interval: 1000,
      },
    },
  },
})

NestJS platform-api doesn't restart

Same issue. The start:dev command uses nodemon under the hood. Make sure your package.json has:

{
  "scripts": {
    "start:dev": "nest start --watch"
  }
}

Data and reset issues

Want to keep data but restart services

docker compose restart [service-name]

Want to reset just one service

docker compose stop authentik-server authentik-worker
docker volume rm dezky_authentik_media dezky_authentik_certs
docker compose up -d authentik-server authentik-worker

Full reset (nuclear option)

./scripts/reset.sh
./scripts/bootstrap.sh

Performance issues

Stack is using too much RAM

Check usage:

docker stats --no-stream

Top RAM consumers are usually:

  • Zulip (4-6 GB) — disabled in main compose
  • Jitsi (2-4 GB) — disabled in main compose
  • Authentik server + worker (~1 GB each)
  • OCIS (~1 GB)
  • Collabora (1-2 GB if active document open)

For low-memory machines, disable services you're not using:

docker compose stop collabora  # Save ~1 GB
docker compose stop ocis       # Save ~1 GB if not testing files

macOS Docker is slow

OrbStack is significantly faster than Docker Desktop on macOS:

brew install --cask orbstack

Or in Docker Desktop, enable VirtioFS for bind mount performance.


Logs and debugging

See logs from one service

docker compose logs -f authentik-server

See logs from multiple services

docker compose logs -f authentik-server authentik-worker postgres

Inspect a container

docker compose exec authentik-server sh
# or
docker compose exec postgres psql -U postgres

See what's running

docker compose ps

Network debugging — can services reach each other?

docker compose exec ocis ping -c 3 authentik-server
docker compose exec ocis curl -v http://authentik-server:9000/-/health/ready/