Playbook / updated 28 Sep 2026

Got hacked: single Docker host

Got hacked: single Docker host

For one Linux box running Docker Compose stacks. Budget: one evening to contain, one weekend to rebuild. The rule that matters most: you rebuild, you don't clean. Once someone had root or the Docker socket, you can't prove the box is clean.

Signs you're here

  • CPU or GPU pinned at 100% with nothing of yours running (miners love homelab GPUs).
  • Containers you didn't create, often alpine, ubuntu, or random names, sometimes --privileged.
  • New SSH keys in authorized_keys, new users, new cron entries.
  • Outbound traffic to mining pools or odd IPs. Your ISP or a Shadowserver report emails you.
  • Your Ollama / GPU box suddenly slow and your power bill up.

1. Contain (tonight, 15 minutes)

Cut it off from the internet, but don't power it off yet. Running processes are evidence.

# Pull the WAN side: unplug the uplink, or block the host at the router.
# If you only have SSH access, block everything except your own IP first:
sudo iptables -I INPUT -s <your-ip> -j ACCEPT
sudo iptables -I OUTPUT -d <your-ip> -j ACCEPT
sudo iptables -A INPUT -j DROP
sudo iptables -A OUTPUT -j DROP
  • Kill tunnels and port-forwards: stop cloudflared, remove router forwards to this box.
  • From a different, clean device, change passwords that were stored on or typed into this box.

2. Capture (30 minutes, before you change anything else)

Save this to a USB stick or another machine, not the compromised disk.

OUT=/mnt/usb/incident-$(date +%F); mkdir -p "$OUT"
docker ps -a --no-trunc              > "$OUT/containers.txt"
docker images --no-trunc             > "$OUT/images.txt"
for c in $(docker ps -aq); do docker inspect "$c"; done > "$OUT/inspect.json"
for c in $(docker ps -aq); do echo "== $c"; docker diff "$c"; done > "$OUT/diffs.txt"
docker events --since 72h --until 0s > "$OUT/docker-events.txt"
ps auxf                               > "$OUT/ps.txt"
sudo ss -tupan                        > "$OUT/sockets.txt"
sudo crontab -l; ls -la /etc/cron.* > "$OUT/cron.txt" 2>&1
sudo cat /root/.ssh/authorized_keys /home/*/.ssh/authorized_keys > "$OUT/ssh-keys.txt" 2>&1
sudo journalctl --since "-7 days" > "$OUT/journal.txt"
sudo last -Faiw                       > "$OUT/logins.txt"

Export any suspicious container for later inspection:

docker export <container> | gzip > "$OUT/<container>.tar.gz"

3. Find the way in (1 hour)

You need this answer, or the rebuilt box gets owned the same way. Check, in order:

Suspect Look for
Docker API on TCP -H tcp:// in /etc/docker/daemon.json or a systemd override; port 2375 in sockets.txt
docker.sock mounted into a web-facing container "/var/run/docker.sock" in inspect.json
Exposed admin/AI port Any 0.0.0.0 bind in sockets.txt for 3000, 8080, 9000, 9090, 11434, 4000
Tunnel with no Access policy Hostnames in your cloudflared config; open each in a private window
Weak SSH Password auth on, root login on, unknown IPs in logins.txt
Vulnerable app Versions in images.txt against the relevant cards in risks/

4. Rebuild (weekend)

  1. Wipe and reinstall the OS. Don't reuse the old root disk.
  2. Rotate every secret that lived on the box: .env files, API keys (OpenAI, Anthropic, Cloudflare), tunnel token, database passwords, SSH keys, and Tailscale auth keys.

  3. Restore data from backups taken before the first sign of trouble. Restore config by re-reading it, not copying it blindly; attackers leave things in compose files and cron.

  4. Pull fresh images by digest or pinned tag. Don't reuse local images from the old box.

  5. Close the hole you found in step 3 before the box goes back online.

5. Afterwards

  • Check other machines on the same LAN for the same SSH keys, cron entries, or container names.
  • Check your email and accounts at https://haveibeenpwned.com/ if credentials were on the box.
  • Set up an alert for new containers or high CPU. Uptime Kuma or a Grafana alert is enough.
  • Write down what happened. If it's something others will hit, it's a labsec card.

Sources

  • NIST SP 800-61 Rev. 3, incident response recommendations: https://csrc.nist.gov/pubs/sp/800/61/r3/final
  • docker diff: https://docs.docker.com/reference/cli/docker/container/diff/
  • docker export: https://docs.docker.com/reference/cli/docker/container/export/
  • docker events: https://docs.docker.com/reference/cli/docker/system/events/