# Exercise 19 — Harden a container step by step # Baseline — works fine podman run -d --name insecure -p 8080:80 nginx:1.27 curl localhost:8080 podman rm -f insecure # Step 1: read-only filesystem podman run -d --name step1 -p 8080:80 --read-only nginx:1.27 podman logs step1 # → fails: mkdir /var/cache/nginx/client_temp: Read-only file system podman rm -f step1 podman run -d --name step1 -p 8080:80 \ --read-only \ --tmpfs /var/cache/nginx \ --tmpfs /var/run \ nginx:1.27 curl localhost:8080 podman rm -f step1 # Step 2: no-new-privileges podman run -d --name step2 -p 8080:80 \ --read-only \ --tmpfs /var/cache/nginx \ --tmpfs /var/run \ --security-opt no-new-privileges \ nginx:1.27 curl localhost:8080 podman rm -f step2 # Step 3: drop all capabilities podman run -d --name step3 -p 8080:80 \ --read-only \ --tmpfs /var/cache/nginx \ --tmpfs /var/run \ --security-opt no-new-privileges \ --cap-drop ALL \ nginx:1.27 podman logs step3 # → fails: bind() to 0.0.0.0:80 failed (13: Permission denied) podman rm -f step3 # Step 4: add back only what nginx needs podman run -d --name secure -p 8080:80 \ --read-only \ --tmpfs /var/cache/nginx \ --tmpfs /var/run \ --security-opt no-new-privileges \ --cap-drop ALL \ --cap-add CHOWN \ --cap-add SETUID \ --cap-add SETGID \ --cap-add NET_BIND_SERVICE \ nginx:1.27 curl localhost:8080 # → 200 OK # Inspect the final capability set podman inspect secure \ --format 'Add: {{.HostConfig.CapAdd}} Drop: {{.HostConfig.CapDrop}}' podman rm -f secure