Series
The way I see it
9 articles in reading order.
-
A hardened Dockerfile for a web app
Build in stages so no compiler ships to production, run as a user with no powers, and strip out everything an attacker could use. The Dockerfile I reach for on web projects.
-
A hardened compose file for a web app
Freeze the filesystem, drop every Linux privilege, keep the secret out of docker inspect, and publish no ports at all. The other half of running a container safely.
-
CI that builds, gates, and publishes your image
A pipeline that lints, tests, scans and ships the image on every push, plus the monthly rebuild that stops a pinned base from rotting in silence.
-
Your CI shouldn't be your formatter
A pre-commit hook that formats your code before it reaches the pipeline. No husky, no lint-staged, fifteen lines of shell.
-
Deploying without an SSH key in CI
A pull-based deploy: CI signs a webhook, an agent on the server pulls the new image and redeploys. Plus the 401 that was never about the signature.
-
Git: commits, branches, and .gitignore
Why git add . is a trap, what a commit stores, and why a deleted secret is still in your history. The local half of Git, before any remote.
-
Processes, signals, and PID 1
Why a long job ignores your Ctrl-C, and the handler that fixes it. Signals, the child processes a script leaves running, and the init that inherits them.
-
The shell & Bash
The same backup script, grown from four lines that look fine to one you can trust to fail without eating your last good backup. Quoting, exit codes, set -euo pipefail and traps, with the reason behind each line.
-
Users, groups, and permissions
From the universal chmod -R 777 to a directory only the service can touch. Ownership as a number, the rwx bits, and the setgid, sticky and setuid bits the hardened container leans on.