Skip to content
All docs

Docs

Observability

Logs, metrics history, Prometheus, terminal, the service event timeline, alerts, uptime, and incidents.

Live surfaces

  • WebSocket log streaming and deployment logs, with level badges, filtering and download
  • Web terminal (xterm) into running containers
  • CPU / memory / network / block metrics sampled every 30 seconds, kept for 48 hours by default (NIXPLOY_METRICS_RETENTION_HOURS, up to 720)
  • Replica breakdown and a 24h uptime chip
  • A single push stream per tab updates deployment status, queue depth and service-status corrections, so dashboard screens carry no polling of their own

Prometheus

GET /api/metrics serves the calling API key's organization as Prometheus text exposition. A scrape is a read, so a read-only key is enough, and the same rate limits, key scopes and organization binding apply as everywhere else.

sh
curl -H "x-api-key: $NIXPLOY_API_KEY" https://panel.example.com/api/metrics
  • Series: service CPU, memory and memory limit, service status, deployments by status, uptime probe state, and this process's queue depth
  • Numbers come from the existing metrics store, so scraping faster than the 30-second sampler just sees the same point twice
  • Services with no sample yet emit no CPU/memory series; the status gauge is always emitted, so status == 0 is the honest “it is down” signal
  • One organization per key — there is deliberately no instance-wide dump that would expose every tenant's names

Service event timeline

Runtime → Events on every service page answers the question a Swarm panel usually cannot: why did it restart? One list of what happened to the service, newest first, filterable by failures, deploys or changes.

  • Task started, task failed and killed rows, with the exit code and the daemon's own error string
  • Status drift the reconciler had to correct — something changed the service outside Nixploy
  • Every deployment transition, and the rollback or config change that came just before it
  • Who changed what: settings, environment variables, source, build type, start and stop all carry the actor
  • Deploys, rollbacks and kills are drawn on the metrics charts too, so a spike and its cause sit next to each other
  • Read it from a terminal with nixploy events list <serviceId>, or over REST

Exit 137 is reported as a kill, not asserted as an out-of-memory: Swarm's task API carries no OOMKilled flag, and a stop that timed out produces the same code. The row says both causes and keeps the exit code — a panel that guessed here would be wrong often enough to matter.

Deploy Copilot reads the last events before a failure as context, so “explain this failed deploy” can see the out-of-memory kill four minutes earlier instead of guessing from the build log alone.

Alerts & incidents

  • Per-service and host threshold alert rules
  • Uptime probes with flip notifications
  • Expiry warnings for uploaded TLS certificates, from 21 days out
  • Incident timeline on the Monitoring page — acknowledge records who is looking at it and leaves the incident open; resolve closes it with an optional note
  • Proposed remediations: a service that fails three tasks in ten minutes gets an incident carrying a suggested rollback — to the previous pinned image, or a compose stack's earlier snapshot — that waits for a person to apply or dismiss it. Nothing runs on its own, an out-of-memory loop is told to raise its limit rather than roll back, and one proposal per service per hour keeps it quiet
  • Public status page at /status/<token>: chosen probes, their state, 90-day uptime and recent incident titles, on an unauthenticated link you can rotate or take offline
  • Fleet overview across local and remote servers

What the status page exposes is deliberately small: the probe's host, its state, an uptime percentage and incident titles. No service ids, project names, probe paths, error strings or acknowledger identities. The page is noindex and rate-limited per IP.

Platform self-alerts

Organization thresholds watch tenant services; platform self-alerts watch the box the panel runs on, so an operator learns about a full disk from Slack instead of from a failed deploy. A check runs every five minutes.

  • Host disk above 85% (warning) or 95% (critical) on the filesystem holding the config dir
  • The oldest deployment still queued for more than 30 minutes
  • An ACME certificate expiring in under 14 days, or already expired
  • Traefik or Postgres below their desired replicas
  • No successful instance backup in NIXPLOY_INSTANCE_BACKUP_ALERT_DAYS days (default 8, 0 disables)

They go to notification channels that have the “Nixploy restarted” toggle on and belong to an organization with an instance-admin member — a tenant org that enables the toggle never sees platform internals. One notification per alert per 24 hours, also surfaced on GET /api/ready and on Monitoring → Fleet.

Panel logs

  • docker service logs -f nixploy — one line per event, prefixed with the subsystem in brackets ([deploy], [status-reconciler], [metrics-history], [platform-alerts], …)
  • LOG_LEVEL is debug | info | warn | error; LOG_FORMAT=json emits one JSON object per line for Loki, Elastic or Datadog
  • All three platform services rotate their json-file logs (10 MB × 3), so an unbounded log cannot fill a small host
  • Build logs are not process logs: each deployment writes its own file under the config dir, streamed live to the UI and pruned after 30 days
  • Secrets never reach the log — a line that contains a credential is a bug worth reporting

Runtime log history

The live log tab ends with the container. Runtime log history keeps what services printed: the worker collects docker logs every 30 s into hour files under the config directory (gzipped once the hour closes), with Docker's own timestamps and a level classified on the server. Every service page has Runtime → History, the Monitoring page has a Logs section across every service you can see, the CLI has nixploy logs search and MCP has get_runtime_logs.

  • Query grammar: terms (all must match), "phrases", -excludes, level:error,warn, container:web, /regex/ (≤ 200 characters, quantified groups refused).
  • Bounded: 2 000 lines per container per pass with an explicit marker line when more was dropped; a read stops after 500 000 lines or four seconds and says so.
  • Retention per service, instance-wide: NIXPLOY_RUNTIME_LOG_RETENTION_DAYS (7) and NIXPLOY_RUNTIME_LOG_MAX_MB_PER_SERVICE (256); NIXPLOY_RUNTIME_LOGS=0 turns the harvester off.

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.