核心 · Key Idea
In one line: 80 % of breaches come from default configs + weak passwords + missing patches. This is the minimum security checklist for every production server and container — not advanced offensive/defensive work; just don't fail at easy stuff.
Server minimum checklist#
- SSH pubkey-onlyDisable PasswordAuthentication, ban root login, change port if you wish.
- Auto security updatesunattended-upgrades / dnf-automatic — at least security patches.
- Minimal firewallDefault-deny inbound; allow only what's needed (22 / 80 / 443). ufw / nftables / cloud SG.
- fail2banBan brute-force IPs (SSH / nginx).
- Dedicated service usersNo root for services; add systemd sandbox fields.
- Centralized logs + alertsEven if the host is tampered, external evidence remains.
- Backups + drillsSee the previous article.
Container minimum checklist#
# Dockerfile
USER 1000
COPY --chown=1000:1000 app /app# K8s securityContext
securityContext:
runAsNonRoot: true
runAsUser: 1000
readOnlyRootFilesystem: true
allowPrivilegeEscalation: false
capabilities:
drop: ["ALL"]
seccompProfile: { type: RuntimeDefault }Pair with:
- Image scanning (Trivy / Grype): CI blocks high-severity CVEs.
- Signing + SBOM (cosign + syft): reject untrusted images.
- NetworkPolicy: default deny-all, allowlist explicitly.
- Resource limits: CPU/Mem/PID caps so one Pod can't take the node down.
- PSA / Kyverno / OPA Gatekeeper (PSP replacements): policy enforcement.
Analogy#
打个比方 · Analogy
A default server install is a new house with no locks and no security — burglars are the default outcome. This checklist is a lock + camera + gas alarm + fire extinguisher.
Key concepts#
Least privilegeLeast Privilege
Processes / users / IAM roles get exactly what they need — nothing more.
Defense in depthDefense in Depth
Network + host + app + monitoring layers — **no single failure is fatal**.
Zero TrustZero Trust
Don't trust the internal network. Verify identity + policy on every access.
Secrets hygieneSecrets Hygiene
No hardcoding, regular rotation, short-lived credentials.
WAFWeb Application Firewall
Cloudflare / nginx + ModSecurity — blocks SQL injection / XSS.
Practical notes#
- Never expose DB / Redis to the public internet — private subnet + SG + strong passwords.
- Disable password login > strong password — weak-password dictionaries are attack #1.
- Inside containers: read-only root filesystem + non-root user + minimal capabilities.
- K8s: enable audit log — sensitive operations (exec / port-forward) have a paper trail.
- Don't put secrets in git — CI uses env vars; runtime uses Vault / SOPS / cloud KMS / external-secrets.
- Dependency manifest + auto-scan: dependabot / renovate + trivy image scan.
- Drills: simulate "this host is compromised" periodically — verify IAM / firewall / app layers detect and contain in time.
- Retain logs 90+ days — for forensic analysis.
Common mistakes#
chmod 777to solve problems — equivalent to removing the lock.sudo NOPASSWD ALLin production — one phished engineer = whole cluster compromised.- Service binds 0.0.0.0 but no firewall — add the firewall or bind 127.0.0.1 + reverse proxy.
- Mounting Docker socket into a container — escape = host root.
- Default ServiceAccount auto-mounted in K8s — set
automountServiceAccountToken: false. - CI runner executes public PR code — code injection grabs internal secrets.
Easy confusions#
Availability
Whether the service runs well.
Measured by SLA / SLO.
Measured by SLA / SLO.
Security
Whether **adversaries** can break it.
Few observable metrics — relies on **process + drills**.
Few observable metrics — relies on **process + drills**.