Cubis Engineers

Operations and recovery

Observe server health, investigate failures in a reliable order, control logs, and restore from tested backups.

Cloud & infrastructureAdvancedUpdated Aug 13, 2026monitoringlogsincidentsbackupsrecovery

Operations is the practice of turning uncertain symptoms into evidence, containing impact, and leaving the system easier to understand next time.

The first five minutes

Terminal
date -Is; uptime
systemctl --failed
free -h
df -hT
sudo ss -tulpn
sudo journalctl -p warning --since '-15 min' --no-pager

Then narrow to the affected service:

Terminal
systemctl status cubis-api --no-pager
journalctl -u cubis-api --since '-15 min' --no-pager
curl -fsS -w '\n%{http_code} %{time_total}s\n' http://127.0.0.1:3000/health
sudo tail -n 100 /var/log/nginx/error.log
docker compose ps
docker compose logs --since=15m app

Before you restart anything

Record the time, commands, results, and changes. Read the error first. Clearing logs or repeatedly restarting a service can remove the information you need to find the cause.

Follow each signal

SignalAsk next
CPU saturatedWhich process? Is work expected? Is load runnable or I/O blocked?
Memory lowIs swap active? Is the kernel killing processes? Is usage growing?
Disk fullWhich filesystem and directory? Are deleted files still open?
502 from NginxIs the upstream listening? Is its health endpoint healthy?
TimeoutDNS, route, firewall, listener, application, or dependency latency?
Frequent restartWhat exit code and journal message preceded it?

Useful drill-down commands:

Terminal
ps -eo pid,ppid,user,%cpu,%mem,etime,cmd --sort=-%cpu | head
vmstat 1 5
sudo dmesg -T | tail -n 100
sudo journalctl -k | grep -i 'oom\|killed process'
sudo lsof +L1                     # deleted files still consuming disk
docker system df

Keep journals bounded

/etc/systemd/journald.conf.d/10-limits.conf
[Journal]
SystemMaxUse=1G
MaxRetentionSec=14day
Compress=yes
Terminal
sudo systemctl restart systemd-journald
journalctl --disk-usage
sudo logrotate --debug /etc/logrotate.conf

Tune retention to incident and compliance needs. Logs required for investigations should be shipped off-host; a failed or compromised server cannot be its only evidence store.

Back up state, not machines

Define the recoverable components:

  • database dumps or storage-native backups;
  • user uploads and other persistent volumes;
  • configuration represented as code;
  • encrypted secrets in an approved secrets system; and
  • the exact application image or release artifact.

Example PostgreSQL logical backup:

Terminal
install -d -m 700 /var/backups/cubis
sudo -u postgres pg_dump -Fc cubis > /var/backups/cubis/cubis-$(date +%F).dump
sha256sum /var/backups/cubis/*.dump > /var/backups/cubis/SHA256SUMS

Copy backups to a separate account or region, encrypt them, apply retention, and monitor the job. A local file on the same server is not disaster recovery.

Test the restore

At a regular cadence, restore into an isolated environment:

Start from empty infrastructure

Provision a fresh server or isolated database. Do not rely on undocumented remnants.

Fetch and verify backup integrity

Validate checksums and decryption before attempting restore.

Restore data and deploy the matching application

Record tool versions and duration; watch for schema incompatibility.

Run functional checks

Validate representative records, authentication, writes, uploads, and critical user journeys.

Record achieved RPO and RTO

Recovery point objective is tolerable data loss. Recovery time objective is tolerable outage. The test reveals whether you actually meet them.

Write down what happened

End the incident with a concise record: impact, start/end time, detection, timeline, contributing conditions, mitigations, recovery evidence, owner, and follow-up work. Separate learning from blame.

A backup is not enough Test the restore on a schedule. The test should show that the team can recover working data and service within the agreed recovery time.

On this page