VayuPress Operations Runbook
Last reviewed: 2026-10-16, against VayuPress 3.18.7
Audience: Production operators, on-call maintainers
Everything here can also be seen from VayuOS: the system bar shows the mode and the world on every page, and System holds the state of the install, backups, storage and updates. This runbook is for the shell.
Quick Reference
# Service status, and its log
systemctl status vayupress
journalctl -u vayupress -n 100 --no-pager
# Health (local; most detail routes answer only locally or with the API key)
curl -s http://localhost:8080/health
curl -s http://localhost:8080/health/dependencies
# Restart, stop
sudo systemctl restart vayupress
sudo systemctl stop vayupress
What runs where
| Process | Listens on | User | Managed by |
|---|---|---|---|
| vayupress | 127.0.0.1:8080 (HTTP, behind nginx); 25, 587, 143, 993, 110, 995 (mail) | www-data |
systemd (vayupress.service) |
| nginx | 80, 443 | www-data |
systemd |
| tor (only with VayuTor on) | local control port | www-data, a child of vayupress |
vayupress itself |
| fail2ban | — | root | systemd |
| certbot | — | root | its systemd timer |
| Path | What |
|---|---|
/var/lib/vayupress |
Data: vayupress.db (+ -wal, -shm), media/, vayudata/mail, vayudata/pgp |
/var/cache/vayupress |
The page cache — safe to clear; it is rebuilt |
/etc/vayupress/env |
Configuration and secrets (API_KEY, DOMAIN, VAYUKEEP_TARGET …) |
/opt/vayupress |
The source and build; the binary is linked at /usr/local/bin/vayupress |
The firewall (ufw) allows 22, 80, 443 and the mail ports.
Health Endpoints
| Endpoint | What it reports |
|---|---|
GET /health, GET /health/live |
Liveness and the running version |
GET /health/ready |
Readiness: the database and workers are up |
GET /health/db |
The database |
GET /health/workers, GET /health/queue |
The write workers and the queue's depth |
GET /health/search |
VayuFind, the built-in search |
GET /health/storage |
Disk use of the data directory |
GET /health/migrations |
Applied migrations and their checksums |
GET /health/dependencies |
Everything above, together |
Runbooks
RB-01: The service does not start
- Read the log:
journalctl -u vayupress -n 50. migration driftmeans an applied migration's recorded checksum no longer matches the binary's. Do not restart it away: follow DR-03 in operations/disaster-recovery.md.database is lockedat start: another process holds it. Find it withpgrep -a vayupress; a leftover CLI run (vayupress backup,domains …) finishes on its own.required env not setnames the variable missing from/etc/vayupress/env;systemctl cat vayupressshows the unit reads it.- Ownership:
ls -la /var/lib/vayupress— the service runs aswww-dataand must own its data.
RB-02: Memory or disk growing
- Memory:
systemctl status vayupress(theMemory:line), andcurl -s http://localhost:8080/metrics | grep vayupress_memory_alloc_bytes. - The queue:
curl -s http://localhost:8080/health/queue. A backlog that does not drain points at the database (RB-05). - The WAL:
ls -lh /var/lib/vayupress/vayupress.db-wal. The server checkpoints on its own, more often under write load (vayupress_wal_adaptive_checkpoints_total); a WAL that keeps growing means a long read is holding it — usually a backup or an export in progress. - A memory figure that keeps climbing across hours is a defect: restart, and
report it with the
/metricsoutput from before the restart.
RB-03: Database corruption
Follow operations/wal-corruption-recovery.md.
RB-04: A TLS certificate expired
sudo certbot certificates— which one, and when.sudo certbot renew(add--force-renewalonly if a renewal is due and was refused), thensudo nginx -t && sudo systemctl reload nginx.- If the HTTP-01 challenge fails: port 80 must be open (
sudo ufw status) and the name must point at this server, with any CDN proxy off for it during the challenge.
VayuMail reloads its certificate from disk on its own; nothing needs a restart.
RB-05: Errors (5xx) rising
journalctl -u vayupress | grep '"level":"error"' | tail -20curl -s http://localhost:8080/health/dependenciesfor the failing part.- Database errors: RB-02 step 3, then RB-03.
- Search errors: rebuild the index — publishing is never blocked by it:
curl -X POST http://localhost:8080/os/api/search/reindex -H "X-API-Key: $API_KEY" - Pages slow or failing only when not yet cached: the console's Storage page shows the page cache and the warmer's progress.
RB-06: Disk space running low
df -h /var/lib/vayupress /var/cache/vayupresssudo du -sh /var/lib/vayupress/* /var/cache/vayupress | sort -rh- Rendered pages are disposable. VayuOS → System › Storage shows what they
and stale temporary files hold; Refresh every page redraws them and
removes the pages of posts that no longer exist. By hand, the page
directories (
/var/cache/vayupress/posts,home,tags) can be deleted; each page is drawn again when next asked for. Leave the rest of the cache directory: it holds the search index's snapshot and the sitemaps. - Media nothing uses is listed in the media library as unused; delete from there, so posts that do use a file keep it.
- Logs:
sudo logrotate -f /etc/logrotate.d/vayupress. - VayuKeep's target must be outside this disk, or a full disk takes the backups with it.
RB-07: Restore from a backup
Follow operations/backup-restore.md: verify the
archive, stop the service, vayupress restore, hand the directory back to
www-data, start.
RB-08: fail2ban blocking a legitimate visitor
The installer configures two jails on nginx's error log, nginx-http-auth and
nginx-limit-req (/etc/fail2ban/jail.d/vayupress.conf).
sudo fail2ban-client status nginx-limit-reqsudo fail2ban-client set nginx-limit-req unbanip <IP>- To never ban an address, add it to
ignoreipin/etc/fail2ban/jail.localandsudo fail2ban-client reload.
VayuShield's own jails are separate; VayuOS → Shield shows and releases them.
RB-09: Rotating the install's API key
The install key (API_KEY in /etc/vayupress/env) can do everything. Prefer
scoped keys for scripts and agents (VayuOS → API keys), which can
be rotated, paused or revoked without a restart. To rotate the install key:
NEW_KEY=$(openssl rand -hex 32)
sudo sed -i "s/^API_KEY=.*/API_KEY=${NEW_KEY}/" /etc/vayupress/env
sudo systemctl restart vayupress
curl -s -o /dev/null -w "%{http_code}\n" http://localhost:8080/metrics -H "X-API-Key: ${NEW_KEY}"
A key is sent as X-API-Key: <key> or Authorization: Bearer <key>.
RB-10: Analytics or the shield's record has gaps
Page views, events, reading engagement and the shield's events are written
in batches by bounded queues (docs/ANALYTICS.md, "When recording fails").
- System › Monitoring › Telemetry: each queue's waiting count against its cap, and what it dropped (full) and lost (refused) since boot, with the database's last refusal.
- Losses with a refusal named: the database is refusing writes. Check Write connection on the same page and RB-06; a held lock or a full disk is the usual cause. A refused batch is tried three times before it is lost.
- Drops without losses: more traffic than the queue's cap between flushes. Enforcement and pages are unaffected; only the record thins.
- The system mode reads read-only: the queues are holding, not losing. They write when the mode returns.
RB-11: The shield refuses a real reader
- Ask for the time and the page. The site's Security page, under Newest refusals, lists each with the request id its log line carries, and Why it was refused and Which gate acted name the rule or signal.
- A rule (
line Norsite line N): change it, or puttestin front to watch it without acting. A site's Security page replays the site's recorded views against the rules as typed, before saving. - The jail or reputation: release the address on VayuOS → Shield.
- A country rule: the country comes from the proxy's headers when trusted, or the embedded table; check what the request carried.
- To never challenge or refuse an address, add it to the allow list. An allow is never jailed.
RB-12: An account cannot sign in: "Too many failed sign-in attempts"
Five failures within 15 minutes on one account, from any address and any door, pause its sign-ins for 15 minutes, doubling with each pause to 24 hours. Its owner was mailed, with where the attempts came from.
- VayuOS → Shield, "Limits set elsewhere", lists the paused accounts and until when.
- If the attempts were the owner's (an old password in a phone's mail app
is the usual cause), fix that first, then Lift the account. Lifting
is recorded in the audit log (
account.unlock). - If they were not, leave the pause to run, and suggest a new password. The owner's sessions already signed in are unaffected.
Metrics
GET /metrics serves the Prometheus exposition format to a request carrying
the API key, or from the machine itself; anyone else gets a 404.
deploy/monitoring/ holds ready alerts and a Grafana
dashboard built on these names.
| Metric | Watch for | Runbook |
|---|---|---|
vayupress_http_request_duration_seconds |
p95 rising | RB-05 |
vayupress_memory_alloc_bytes |
climbing across hours | RB-02 |
vayupress_storage_used_bytes |
approaching the disk | RB-06 |
vayupress_migration_drift_detected_total |
any | RB-01 |
vayupress_queue_failed_total, vayupress_dead_letter_total |
rising | RB-05 |
vayupress_wal_checkpoint_duration_ms_total |
steps up | RB-02 |
vayupress_cache_hit_ratio |
falling | RB-05 step 5 |
vayupress_auth_lockouts_total |
rising | a sign-in attack; see VayuShield |
vayupress_workers_alive |
below the configured count | RB-01 |
What runs on its own
| When | What | Where |
|---|---|---|
| Adaptive: every 5 min while written to, up to 6 h when idle | A backup generation | VayuKeep (when a target is set) |
| Every 12 h | A restore drill of the newest generation | VayuKeep |
| Every 5 min | Listing cards built, then stale pages rebuilt, paced by load | The cache warmer |
| Daily | DNS and certificate re-check for every domain | vayupress-provision.timer |
| Twice a day | Certificate renewal | certbot's timer |
| Every start | Migrations applied and their checksums verified | internal/db |
Capacity
A single 8 GB RAM / 4 vCPU / 50 GB NVMe VPS runs everything; johal.in runs
234,727 posts, fourteen sites and the mail server on one Contabo VPS 10. The
binary is held under 45 MB gzipped (make check-size). Background work — backups, the
warmer, card building — asks the host pacer (internal/pace) before each step,
so it slows down while visitors need the machine.
Incident Classification
| Severity | Definition | Response Time | Escalation |
|---|---|---|---|
| P1 Critical | Site down, data loss, security breach | 15 min | BDFL + Security Lead |
| P2 High | Degraded performance, elevated errors | 1 hour | On-call maintainer |
| P3 Medium | Single feature broken, non-critical | 4 hours | Community Lead |
| P4 Low | Cosmetic, advisory | Next sprint | Regular backlog |
Security incidents: email security@vayupress.com immediately, and follow security/incident-response.md.
Emergency Contacts
| Role | |
|---|---|
| BDFL / Owner | admin@vayupress.com |
| Security Lead | security@vayupress.com |
| On-call (ops) | ops@vayupress.com |