How to Secure a VPS That Runs Docker Containers
SSH hardening, a default-deny firewall, and the fix for the problem that catches almost everyone — Docker publishing container ports straight past UFW into the public internet.
The distribution most guides assume, with the details they leave out.
Ubuntu LTS is the default assumption in most server documentation, which makes it the pragmatic choice even where a technical argument favours something else. Five years of security maintenance and a package for nearly everything is a reasonable trade.
Reach for the LTS release for anything that will still be running next year. Reach for an interim release only when you need a kernel or a package version the LTS does not have, and accept a nine-month support window if you do.
The 24.04 release changed two things that quietly break older instructions.
SSH is socket-activated, so the listening port is owned by ssh.socket and
editing Port in sshd_config no longer does what tutorials say. And the
logging story has moved toward journald, so guides that assume
/var/log/auth.log exists — fail2ban’s default jail among them — need
adjusting.
Beyond that, most Ubuntu-specific trouble is resource limits. File descriptor
ceilings inherited from a systemd unit rather than your login shell. inotify
watcher limits that dev servers and log shippers exhaust. Values set with
sysctl -w that vanish on reboot because they were never written to
/etc/sysctl.d/.
Unattended upgrades are worth enabling on every host and worth configuring
deliberately: security pocket on, automatic reboot off unless a reboot at 06:00
is genuinely acceptable, and /var/run/reboot-required watched from wherever
you watch things.
Articles here state which release they were verified on, because the answer has changed more between 22.04 and 24.04 than the version numbers suggest.
Start here
SSH hardening, a default-deny firewall, and the fix for the problem that catches almost everyone — Docker publishing container ports straight past UFW into the public internet.
A reading order that builds Ubuntu knowledge in the sequence it is actually needed.
SSH hardening, a default-deny firewall, and the fix for the problem that catches almost everyone — Docker publishing container ports straight past UFW into the public internet.
A production n8n install on Ubuntu 24.04 using Docker Compose, PostgreSQL and Caddy for automatic TLS — with the encryption key, webhook URL and backup steps most quickstarts leave out.
Failure modes that come up repeatedly with Ubuntu, and where each one is solved.
Diagnose which file descriptor limit you actually hit — container, daemon or kernel — then raise it properly, and work out whether the real problem is a leak rather than a limit.
SSH hardening, a default-deny firewall, and the fix for the problem that catches almost everyone — Docker publishing container ports straight past UFW into the public internet.
A production n8n install on Ubuntu 24.04 using Docker Compose, PostgreSQL and Caddy for automatic TLS — with the encryption key, webhook URL and backup steps most quickstarts leave out.
SSH hardening, a default-deny firewall, and the fix for the problem that catches almost everyone — Docker publishing container ports straight past UFW into the public internet.
A production n8n install on Ubuntu 24.04 using Docker Compose, PostgreSQL and Caddy for automatic TLS — with the encryption key, webhook URL and backup steps most quickstarts leave out.
Diagnose which file descriptor limit you actually hit — container, daemon or kernel — then raise it properly, and work out whether the real problem is a leak rather than a limit.
LTS. Five years of standard security maintenance, and every piece of third-party documentation is written against it. Interim releases are supported for nine months, which is a short upgrade treadmill for a server.
No. It lags upstream and does not track the Compose v2 plugin the way Docker's own apt repository does. Add Docker's repository instead.
The file `/var/run/reboot-required` exists when one does, and `/var/run/reboot-required.pkgs` lists why. Check it from monitoring rather than by logging in.