The Secure Way
Hardening guides, the secure way
We know why you're here. The docs said it would just work. Pull up a chair.
Step-by-step guides to setting up infrastructure securely: post-quantum TLS, WAFs, DNSSEC, service meshes, Kubernetes, secrets, identity, supply chain, detection and Linux hosts. Each guide shows the secure configuration, what the official docs leave out, how to prove it works, and the mistakes people make.
150 guides in 13 categories
Start herePost-quantum TLS at NIST level 5ML-KEM-1024, the standard name for Kyber-1024: what it is, how it compares to X25519MLKEM768, and how to prove what a server negotiates.
- Post-quantum and TLSML-KEM key exchange, TLS 1.3 done properly, and proving what your server actually negotiates.10 guides
- Edge and WAFWeb application firewalls that block instead of log, rate limits, blocklists and the edge in front of your app.12 guides
- DNS and DNSSECSigned zones, key rollovers that do not take your domain down, hidden primaries and zone transfers.14 guides
- Service meshmTLS between services that is really on, traffic permissions that deny, and gateways into the mesh.10 guides
- Kubernetes networking with CiliumDefault-deny network policy, transparent encryption and egress control with Cilium and Hubble.11 guides
- Nodes and clustersTalos Linux, Kubernetes API hardening, service account tokens, RBAC and the cloud underneath.14 guides
- Sandboxing untrusted codegVisor, pods with no network, and running other people's code without handing them your cluster.8 guides
- Secrets and PKIOpenBao, External Secrets, internal certificate authorities and keeping secrets off the command line.10 guides
- Identity and accessSelf-hosted identity with Zitadel, private access with Headscale, break-glass and offboarding.9 guides
- Build and supply chainKaniko, Chainguard and Wolfi images, vendoring, signing with cosign and admission that refuses the unsigned.20 guides
- Runtime detection and observabilityTetragon, alerting as code, multi-tenant logs and knowing when a sensor goes quiet.11 guides
- DatabasesPostgres with TLS that verifies, backups you can restore, least-privilege roles and row-level security.4 guides
- Linux hostsSSH, sudo, firewalls, mount options, updates and the host basics every engineer should get right.17 guides
Post-quantum and TLS
- Checking a server's TLS key exchange, the secure waySee which key exchange a TLS server really agrees to, hybrid ML-KEM, MLKEM1024 or classical X25519, with OpenSSL 3.5 and curl, and read the output right.
- CNSA 2.0 for web servers, the secure wayConfigure a CNSA 2.0 TLS endpoint on nginx with OpenSSL 3.5 or on Envoy: TLS 1.3, ML-KEM-1024 only, AES-256-GCM, P-384 signatures, and proof of each.
- ECDSA P-384 certificates with cert-manager, the secure wayIssue ECDSA P-384 certificates with cert-manager instead of the RSA-2048 default: the Certificate fields, key rotation, the Let's Encrypt chain, and checks.
- Finding classical key exchange in your estate, the secure wayInventory which TLS and SSH endpoints still use classical key exchange: a read-only script, how to read its output, and how to rank what to fix first.
- ML-DSA certificates: what is ready, the secure wayWhat works with ML-DSA certificates today: private PKI with OpenSSL 3.5 end to end, no publicly trusted ML-DSA certificates, and the Merkle Tree plan.
- ML-KEM-1024 on Envoy Gateway, the secure wayTurn on ML-KEM-1024 and hybrid ML-KEM at an Envoy Gateway edge with one ClientTrafficPolicy, keep browsers working, and prove the negotiated group.
- Post-quantum mTLS in a Kuma mesh, the secure wayMake Kuma sidecar-to-sidecar mTLS use ML-KEM-1024: MeshTLS for TLS 1.3, a MeshProxyPatch on both inbound and outbound, and counters that prove it.
- Post-quantum SSH with mlkem768x25519, the secure wayMake every SSH connection use mlkem768x25519-sha256: check what your servers negotiate, restrict KexAlgorithms to hybrids, and see what a refused client prints.
- Post-quantum TLS in nginx and HAProxy with OpenSSL 3.5, the secure wayEnable ML-KEM in nginx and HAProxy on OpenSSL 3.5: hybrid by default, MLKEM1024 when offered, and the group-tuple syntax that decides which one wins.
- TLS 1.3 only at the edge, the secure wayRefuse TLS 1.2 at an Envoy or Envoy Gateway edge, know which clients that cuts off, and why cipher_suites cannot restrict TLS 1.3 ciphers in Envoy.
Edge and WAF
- Coraza WAF with OWASP CRS v4 on Envoy Gateway, the secure wayRun the Coraza WAF with OWASP CRS v4 in Envoy Gateway: an EnvoyExtensionPolicy pinned by digest, fail-closed, blocking mode, and proof it blocks attacks.
- Fail-closed WASM filters pinned by digest, the secure wayLoad Envoy Wasm filters, such as a WAF, pinned by sha256 and failing closed: what Envoy and Envoy Gateway do when the module changes, and why fail-open is dangerous.
- IP blocklists with Envoy Gateway SecurityPolicy, the secure wayBlock IP ranges at Envoy Gateway with a SecurityPolicy that really matches the client: the right numTrustedHops, the XFF trap, and tested proof of each case.
- Multi-region edge PoPs on Kubernetes, the secure wayRun edge points of presence as small Kubernetes clusters with Envoy Gateway: identical policy from Git, per-PoP certificates, health-checked DNS, and no shared keys.
- OWASP CRS paranoia levels and false positives, the secure wayRaise OWASP CRS paranoia levels without blocking real users: detection paranoia level first, then narrow rule exclusions by path, parameter and rule ID.
- Protecting an identity-provider admin console at the edge, the secure wayKeep an identity provider's admin console off the internet while login stays public: Envoy Gateway route split, allowlist, and tests against path tricks.
- Rate limiting login endpoints on Envoy Gateway, the secure wayRate limit a login endpoint on Envoy Gateway so a query string or a trailing slash cannot skip it: a dedicated route, a per-IP global limit, a local backstop.
- Real client IPs with Proxy Protocol v2, the secure wayPass real client IPs from a TCP load balancer to Envoy with PROXY protocol v2, and stop anyone who reaches Envoy directly from forging their address.
- Upstream TLS from the edge with a pinned CA, the secure wayEncrypt and authenticate the edge-to-backend hop: BackendTLSPolicy with your own CA and hostname, why Envoy without a trusted CA verifies nothing, and tests.
- WAF audit logs without leaking credentials, the secure wayStop Coraza and ModSecurity audit logs from storing bearer tokens, cookies and passwords: which audit parts leak, safer parts, and redaction for matched data.
- WAF auto-ban across edge PoPs, the secure wayTurn WAF blocks into a shared, expiring IP ban list for every Envoy Gateway edge PoP, without banning your load balancer, yourself, or routes by accident.
- WAF rules for AI-agent credential and dev-server probes, the secure wayBlock probes for .env files, cloud keys, AI coding-agent configs and Vite dev-server paths like /@fs/ at the edge, with two tested Coraza rules on top of CRS.
DNS and DNSSEC
- Building your own GeoIP CDN, the secure wayBuild a GeoIP CDN with a hidden DNSSEC signer and Knot edges that hold only the ZSK: signed geo answers, daily re-signing, and PoP failover in one edit.
- CAA records bound to your ACME account, the secure wayLimit who can get certificates for your domain: CAA with accounturi and validationmethods, no wildcards by default, DNSSEC-signed, and a per-subdomain override.
- DNS rate limiting and cookies in Knot, the secure wayStop Knot DNS from acting as a reflection amplifier: mod-rrl with slip, mod-cookies loaded first so real clients pass, and one cookie secret across anycast.
- DS records and delegation at the registrar, the secure wayThe DS record is the one DNSSEC step you cannot do on your own server. Get it right at the registrar, check it from the parent, and remove it before you unsign.
- Emergency DNSSEC key revocation, the secure wayWhat to do in Knot DNS when a ZSK or KSK leaks: swap the ZSK in minutes, replace the KSK in the right order with the registrar, and why panic deletion fails.
- GeoDNS with Knot and DNSSEC, the secure wayServe location-based answers from Knot DNS mod-geoip with valid DNSSEC signatures: manual keys, a reload after each ZSK change, and a test from every region.
- Knot DNS automatic DNSSEC signing, the secure wayTurn on DNSSEC in Knot DNS 3.5 with automatic keys, NSEC3 set per RFC 9276, a guarded KASP database and a validated chain, plus the DS step Knot waits on.
- Knot DNSSEC key rollover, the secure wayRoll ZSKs and KSKs in Knot DNS without going bogus: lifetimes, TTL timing, a parent DS check, the registrar step, and the timeout that quietly breaks the chain.
- Monitoring DNSSEC signature expiry, the secure wayCatch expiring RRSIGs before resolvers do: check every authoritative server directly, set thresholds from your refresh window, and size SOA expire to match.
- Offline KSK with Knot, the secure wayKeep the DNSSEC KSK off your Knot DNS servers: the KSR and SKR ceremony, keytag split, an air-gapped signer, and the SKR expiry that turns a zone bogus.
- PowerDNS hidden primary with Knot secondaries, the secure wayRun PowerDNS as a hidden, signing primary behind Knot DNS secondaries: a private transfer network, TSIG on every transfer, SOA-EDIT, and validation on the edge.
- Split-horizon DNS for private services with CoreDNS, the secure wayGive internal clients private answers and everyone else public ones with the CoreDNS view plugin, without leaking private names or shadowing the internal view.
- TSIG for zone transfers and key rotation, the secure wayProtect AXFR, IXFR and NOTIFY with TSIG in Knot DNS: hmac-sha256, address plus key ACLs, versioned key names, and a key rotation with no failed transfers.
- Zone files in git, reconciled to PowerDNS, the secure wayKeep DNS zones in git and make PowerDNS match them: validate before apply, detect drift from API edits, keep serials moving forward, and lock the API down.
Service mesh
- Cilium with a sidecar mesh (Kuma, Istio, Linkerd) without losing mTLS, the secure wayCilium's socket load balancing can make Kuma or Istio sidecars send plaintext. Set socketLB.hostNamespaceOnly, fail closed, and prove traffic is encrypted.
- Default-deny MeshTrafficPermission, the secure wayMake Kuma deny service-to-service traffic by default with MeshTrafficPermission: strict mTLS, a mesh-wide deny, per-service allows, shadow deny, and RBAC.
- Envoy Gateway as a delegated mesh gateway, the secure wayPut Envoy Gateway in front of a Kuma mesh as a delegated gateway without plaintext hops: routingType Service, sidecar on proxy pods only, and permissions.
- Internal tools behind a Kuma gateway, the secure wayPublish Grafana, Argo CD and other internal tools through a Kuma built-in gateway without exposing them: private Service, TLS per host, SSO and permissions.
- Kuma certificate rotation and CA choices, the secure wayPick a Kuma mesh CA you can defend: builtin vs provided with an offline root, explicit workload certificate lifetimes, CA expiry you plan for, and checks.
- Kuma multi-zone mTLS with a builtin CA, the secure wayEnable Kuma mTLS across zones with the builtin CA: permissions first, strict TLS 1.3, short certificates, a locked-down CA key, and proof that it holds.
- Mesh sidecars inside gVisor, the secure wayRun Kuma or Istio sidecars in gVisor pods without losing traffic interception: a dedicated runsc handler with raw sockets, capabilities dropped, and wire proof.
- Mesh telemetry over OTLP, the secure waySend Kuma mesh metrics, traces and access logs over OTLP without leaking tokens or letting pods redirect them: node-local collector, env mode Disabled, mTLS out.
- Retries and non-idempotent requests in a mesh, the secure wayStop service mesh retries from duplicating POSTs and payments: what Kuma and Istio retry by default, a safe mesh-wide policy, and per-service retries for reads.
- Securing Kuma zone-to-global traffic, the secure waySecure the Kuma KDS link between zone and global control planes: your own CA, verified TLS, no skipVerify, source-restricted port 5685, and checks that prove it.
Kubernetes networking with Cilium
- API server and webhook traffic under default deny, the secure wayKeep the Kubernetes API server and admission webhooks working under Cilium default deny: kube-apiserver entity, webhook ingress, and failurePolicy traps.
- Blocking the cloud metadata endpoint from pods, the secure wayStop Kubernetes pods from reading 169.254.169.254: a Cilium deny policy that cannot be overridden, the hostNetwork gap, IMDSv2 hop limits, and a test.
- Cilium kube-proxy replacement, the secure wayReplace kube-proxy with Cilium without widening exposure: NodePorts on the private NIC only, source ranges on every service type, no kube-proxy leftovers.
- Cilium L2 announcements in a cloud VPC, the secure wayCilium L2 announcements answer ARP for service IPs. In a cloud VPC that rarely works, and making it work weakens anti-spoofing. Limit it where you use it.
- Cilium policy audit mode to enforcement, the secure wayRoll out Cilium network policies with Policy Audit Mode without switching off every policy in the cluster: per-endpoint audit, AUDIT verdicts, exit criteria.
- Cilium WireGuard transparent encryption, the secure wayTurn on Cilium WireGuard encryption so pod traffic between nodes is never sent in clear: node encryption, strict mode, the gaps it leaves, and how to check.
- Cilium with minimal capabilities on Talos, the secure wayRun Cilium on Talos Linux with the smallest privilege set: no SYS_MODULE, no privileged or nsenter init containers, KubePrism, and no exec into the agent.
- Default-deny network policies generated from Hubble flows, the secure wayBuild Kubernetes default-deny network policies from real Hubble flows: collect enough traffic, reduce it to edges, write narrow Cilium policies, and verify.
- Egress isolation for CI build pods, the secure wayIsolate Kubernetes CI build pods with Cilium: egressDeny for the API server, nodes, metadata and private ranges, plus an FQDN allowlist for builds.
- FQDN egress allowlists with the Cilium DNS proxy, the secure wayWrite Cilium toFQDNs egress allowlists that hold: restrict what pods may resolve, not only where they connect, and block internal ranges an FQDN may resolve to.
- Hubble for network forensics, the secure wayUse Cilium Hubble as network evidence: export flows before the ring buffer forgets, keep the right fields, redact secrets, lock the API, and query offline.
Nodes and clusters
- Cloud firewalls by tag, the secure wayDigitalOcean cloud firewalls follow tags, so one missing or misspelled tag leaves a Droplet with no firewall at all. Design tag-based rules and audit coverage.
- Disk encryption on Talos with LUKS2 and TPM, the secure wayTalos encrypts STATE and EPHEMERAL with LUKS2, but a TPM key without SecureBoot, a static key on STATE, or a patch on a used disk protects little. Do it right.
- etcd on cloud VMs, the secure wayetcd on cloud VMs: mTLS for clients and peers on the private network only, timings that survive slow cloud disks, a dedicated volume, and snapshots encrypted.
- Kubernetes and Talos API access over a tailnet, the secure wayTake the Kubernetes API and the Talos API off the internet: join Talos nodes to a tailnet, firewall 6443 and 50000 to it, and let tailnet grants decide who connects.
- Kubernetes audit policy, the secure wayA Kubernetes audit policy that records who did what without copying Secrets and tokens into the log: rule order, levels per resource, and a Talos patch.
- Pod Security Admission levels in practice, the secure wayPod Security Admission accepts a bad Deployment and silently blocks its pods. Pin versions, pair enforce with warn and audit, avoid exemptions, pass restricted.
- RBAC least privilege with resourceNames, the secure wayRBAC resourceNames can limit a role to one Secret, but not for create, deletecollection or plain list. Scope reads and patches by name; police create by policy.
- Self-managed Pulumi state, the secure waySelf-managed Pulumi state keeps every non-secret value in plain text, in history and backups too. Mark secrets, use a real key provider, and lock down the bucket.
- ServiceAccount token hardening, the secure wayEvery pod gets an API token by default, and the API server quietly makes it valid for a year. Turn off automount, use short projected tokens, drop legacy ones.
- Talos Linux hardening, the secure wayTalos ships a hardened kernel, but its host firewall defaults to accept and admin credentials never expire. Close apid, scope talosconfig, and verify it.
- Talos machine configs in git with age, the secure wayTalos machine configs hold your cluster CA keys. Commit only patches and a sops+age encrypted secrets bundle, regenerate configs on demand, and block plaintext.
- Talos on DigitalOcean without losing kernel hardening, the secure wayOn DigitalOcean, Talos boots with GRUB and takes its kernel command line from the installer image. Keep KSPP args, and keep your machine config out of user data.
- Talos upgrades that keep your hardening, the secure wayA Talos upgrade can drop your extensions and kernel args, and it never adds the new security defaults. Pin the installer, snapshot the node, then diff it.
- VPC segmentation for untrusted CI, the secure wayCI runners execute code from pull requests and dependencies. Give them their own VPC, deny egress to your networks, block the metadata service, and prove it.
Sandboxing untrusted code
- Detecting and stopping sandbox abuse, the secure waySandboxes get abused for mining, scanning and probing your cluster. Alert on Hubble drop and egress metrics and CPU at limit, keep evidence, then cut access.
- Exec-only access to sandboxes, the secure wayLet users into their own sandbox pod with kubectl exec and nothing else: per-pod RBAC, create-only exec, no port-forward or nodes/proxy, and an audit trail.
- Giving learners root in a sandbox safely, the secure wayHands-on labs need root, and learners will try everything with it. Contain root with gVisor or user namespaces, isolate learners, cap resources, and set a deadline.
- gVisor for untrusted workloads on Kubernetes, the secure wayA gVisor RuntimeClass protects only pods that name it; the rest silently run on runc. Pin sandbox nodes, require the class by policy, prove each pod is sandboxed.
- Logging sandbox egress with Hubble, the secure wayHubble shows sandbox egress live, then forgets it within minutes. Export sandbox egress flows with DNS names to a file and ship them off the node for review.
- One pod per code execution, the secure wayA code-execution feature is a remote shell with a nice API. Run every execution in a fresh sandboxed pod, and pin what the service may create by admission policy.
- Pods with no network at all, the secure wayA deny-all NetworkPolicy does nothing if your CNI ignores it, and it may spare open connections. Cut pod networking with Cilium deny rules or gVisor, then test it.
- Running untrusted repositories in an isolated job, the secure wayBuilding or testing a stranger's repository runs their code with your job's rights. Use one sandboxed Job per run: no credentials, one allowed host, hard limits.
Secrets and PKI
- An offline internal CA with cert-manager, the secure wayKeep the root CA key offline and give cert-manager only a one-year intermediate with pathlen:0 and name constraints, so a stolen key cannot sign anything else.
- External Secrets Operator with OpenBao, the secure wayRun External Secrets Operator against OpenBao with namespaced SecretStores, per-team ServiceAccounts, audience-bound tokens, a pinned CA and no cluster stores.
- Let's Encrypt DNS-01 over RFC 2136 and TSIG, the secure wayGive cert-manager a TSIG key that can only write TXT records in a delegated ACME zone, never your main zone. BIND update-policy, CNAME delegation, real tests.
- Never put a secret on the command line, the secure wayCommand-line arguments are readable by every user on the host and land in shell history. See the leak in ps and /proc, then pass secrets by file, fd or stdin.
- OpenBao hardening, the secure wayHarden an OpenBao server: no swap, TLS 1.3, declarative audit devices, self-init with no root token left behind, and HMAC'd audit logs, shown with real output.
- OpenBao Kubernetes auth across clusters, the secure wayLet pods in several Kubernetes clusters log in to one OpenBao without sharing trust: one mount per cluster, audience-bound tokens, exact subjects, short TTLs.
- OpenBao policies as code with drift detection, the secure wayKeep OpenBao ACL policies in git, apply them from CI, and catch hand edits with a read-only drift check that fails the pipeline. Tested script included.
- OpenBao transit auto-unseal, the secure waySet up OpenBao transit auto-unseal with an orphan periodic token, a two-path policy and TLS, and see what happens when the transit server is sealed or revoked.
- Operator secret stores with pass and an offline copy, the secure wayShare operator secrets in a team with pass: per-person GPG keys, a signed recipient list, re-encryption and rotation when someone leaves, and an offline copy.
- Signing keys no cluster can read, the secure wayKeep cosign signing keys in OpenBao transit, non-exportable, and give CI a 15-minute token that can sign with one key and nothing else. Tested with cosign v3.
Identity and access
- A userspace Tailscale subnet router on Kubernetes, the secure wayRun a Tailscale subnet router in Kubernetes as non-root with no capabilities, an exact auto-approved route, per-service grants and a Role for its own state.
- Admin tools reachable only on a tailnet, the secure wayBind admin tools to loopback, publish them with tailscale serve, and grant one group one port. Tested end to end: ops gets in, dev and the LAN are refused.
- An insider kill switch, the secure wayCut a person out of OpenBao and the tailnet in seconds: disable the entity so every token dies, expire their devices, and verify. Deleting the login is not enough.
- Break-glass accounts, the secure wayDesign break-glass access that needs two parties, lives offline, alerts on use and is revoked after, shown end to end with OpenBao recovery shares and audit logs.
- Developer onboarding and offboarding, the secure wayGrant developer access through groups and single-use keys, and remove it with an inventory, expired devices and deleted accounts. Tested with Headscale.
- Forcing MFA in Zitadel, the secure wayForce MFA in Zitadel for every user, including those from external IdPs, and catch organizations that quietly override it. Real API output from Zitadel v4.
- Headscale with OIDC and deny-by-default ACLs, the secure wayRun Headscale with OIDC restricted to your domain and group, PKCE, expiring nodes, and a deny-by-default policy whose tests fail any change that opens more.
- Staff and customers in separate Zitadel organizations, the secure wayKeep Zitadel instance administrators in their own organization, away from customer orgs whose admins can reset their passwords. Real API output from Zitadel v4.
- Zitadel on Kubernetes, the secure wayDeploy Zitadel with Helm without the default admin password, a masterkey in values, plaintext to the pod or a 2029 admin key in a Secret. Tested and validated.
Build and supply chain
- Argo CD hardening, the secure wayHarden Argo CD: disable the admin user, empty the default project, scope AppProjects to one repo and namespace, and write RBAC where a team can sync but not delete.
- Builds with no internet access, the secure waySplit builds into a fetch stage that locks and verifies inputs and a build stage with no internet route. Tested with pip wheels, Go vendoring and kaniko.
- Chainguard and Wolfi base images, the secure wayUse Chainguard images and Wolfi well: pin the free latest tag by digest, verify its signature, build in -dev, ship without a shell, read scans honestly.
- Containing a root Kaniko build, the secure wayKaniko needs root inside its container. How to drop it to five capabilities, cut its network and credentials, and keep a hostile Dockerfile off your nodes.
- Digest pinning in GitOps, the secure wayPin every image in your GitOps repository by sha256 digest with kustomize, keep the tag for humans, and fail CI when any rendered manifest has an unpinned image.
- Forgejo Actions runner isolation, the secure wayIsolate Forgejo Actions runners: no host label, no Docker socket in jobs, dropped capabilities and limits, one runner per trust level on its own VM.
- Git forge disaster recovery, the secure wayBack up a self-hosted Forgejo so you can really restore it: verified git bundles off the server, encrypted snapshots with the secrets, and restore drills.
- GitOps without circular dependencies, the secure wayYour GitOps tool deploys the Git server it reads from? Break the loops between Argo CD, the forge, the registry, secrets and SSO so a dead cluster can come back.
- Kaniko: building images without Docker, the secure wayBuild container images in CI with kaniko instead of the Docker socket: the maintained fork, a digest-pinned executor, reproducible builds, no push in PRs.
- Mirroring base images with a scan and a signature, the secure wayMirror upstream container images only after the upstream signature verifies and a grype scan passes; copy by digest and sign the mirrored digest.
- Offline cosign signing, the secure waySign release files and container images with a cosign key pair and no internet, no Fulcio and no Rekor, using cosign v3 signing configs, and verify them offline.
- Promotion workflows where CI can only write digests, the secure wayLet CI promote releases through GitOps without write access to anything else: digest-only commits, a required check that proves it, and staging before prod.
- Registry tags that never move, the secure wayMake container image tags immutable: what OCI registries promise, how Harbor, ECR and zot enforce it, and a tested zot policy where CI can push but never overwrite.
- Rolling out the Sigstore policy-controller, the secure wayEnforce signed images on Kubernetes with the Sigstore policy-controller without breaking the cluster: opt-in namespaces, warn mode, then enforce and deny.
- SAST and secret scanning in CI, the secure wayRun gitleaks over every commit, not just the working tree, and semgrep with your own rules as blocking CI checks, offline and with redacted findings.
- SBOMs and attestations with Syft and cosign, the secure wayGenerate an SBOM with Syft from the exact image digest, attach it as a signed in-toto attestation with cosign, and verify signer and content before you trust it.
- Self-hosting Forgejo, the secure wayHarden a self-hosted Forgejo: no open registration, login required, 2FA for all, no git hooks, SSRF limits on migrations and webhooks, and a locked-down container.
- Vendored Go modules and hashed Python requirements, the secure wayVendor Go modules and lock Python requirements with hashes so builds use only reviewed bytes, and add the CI check go build skips: re-vendor and diff.
- Vendoring CI actions at pinned SHAs, the secure wayStop running other people's latest code in CI: vendor Forgejo and GitHub actions into your own forge at a reviewed commit, pin full SHAs, and fail CI on any tag.
- Wolfi's split packages and the mistakes they cause, the secure wayOn Wolfi, apk add gnupg installs no gpg at all. How split packages work, how to find the package that ships a command, and how to keep images small and working.
Runtime detection and observability
- Alerting when a sensor goes quiet, the secure wayAlert when a security sensor stops reporting: a target that is down, a target that vanished, an agent that is up but silent, and a host far quieter than its peers.
- Detecting sign-in brute force from logs, the secure wayThree LogQL detections for SSH sign-in attacks (brute force, password spraying, and a success after failures) as Loki ruler alerts, tested on synthetic logs.
- Kubescape CIS, NSA and MITRE scans, the secure wayScan Kubernetes manifests with Kubescape against the NSA and MITRE frameworks in CI, gate merges on a compliance threshold, and run CIS checks on the cluster.
- Loki multi-tenancy, the secure wayRun Loki with auth_enabled and put an authenticating gateway in front that sets X-Scope-OrgID itself, because Loki trusts whatever header it receives. Tested.
- Multi-tenant OTLP ingest with Alloy, the secure wayAccept OTLP logs from several tenants with Grafana Alloy: TLS, one credential set per tenant, and a tenant ID set by the pipeline instead of the client. Tested.
- Security alerting as code in Grafana, the secure wayProvision Grafana security alert rules, contact points and routing from files in git, so nobody can quietly edit or delete a detection in the UI. Tested end to end.
- Tetragon egress monitoring for CI, the secure waySee every outbound connection a CI build pod makes, and which process made it, with a namespaced Tetragon tcp_connect policy; kill unexpected egress.
- Tetragon runtime detection on Talos, the secure wayInstall Tetragon on Talos Linux with the tracing mount it needs, keep host and kube-system events in the export, redact secrets, and keep gRPC off the network.
- Tetragon: catching privilege escalation, the secure wayDetect privilege escalation inside Kubernetes pods with Tetragon: setuid calls to root and new credentials from commit_creds, plus Sigkill enforcement.
- Tetragon: credential file reads, the secure wayDetect reads of /etc/shadow, SSH keys and Kubernetes service account tokens with a Tetragon policy on security_file_permission, filtered in the kernel.
- Tetragon: kernel module and BPF loads, the secure wayDetect kernel module loads, automatic module requests and BPF program loads with Tetragon policies, the moves rootkits and eBPF-based malware make to hide on a node.
Databases
- CloudNativePG backups to object storage, the secure wayBack up CloudNativePG to S3-compatible storage with the Barman Cloud Plugin: a bucket-scoped key, verified TLS, encryption at rest, retention, and restore tests.
- CloudNativePG TLS and pg_hba, the secure wayCloudNativePG's default pg_hba rule accepts plaintext passwords over TCP. Add hostnossl reject, allow the app only over TLS, and use your own server CA.
- Least-privilege Postgres roles for an app, the secure wayGive an application its own Postgres login that can read and write rows but not drop tables, change the schema or run programs, with default privileges. Tested.
- Testing row-level security in CI, the secure wayTest Postgres row-level security like any other code: a small suite that runs as the app's login, checks tenant isolation, views and new tables, and fails the build.
Linux hosts
- Auditing a host after a break-in, the secure wayWhat to check on a Linux host you think is compromised: UID 0 accounts, SSH keys, cron, setuid files, changed package files and disguised listeners.
- Container hosts: rootless containers, the secure wayRun containers without root on the host: rootless Podman with subordinate UID ranges, user namespaces, and why the docker group is root. Tested with a real UID map.
- Finding and removing setuid binaries, the secure wayList every setuid, setgid and file-capability binary on a Linux host, remove the ones you do not need, and keep them removed after upgrades with dpkg-statoverride.
- Hunting secrets on a host, the secure wayFind the passwords, tokens and private keys lying around a Linux host: .env files, shell history, process environments, Docker configs and git history. Tested.
- Kernel sysctl hardening, the secure wayA commented sysctl.d file that hides kernel pointers, limits BPF, ptrace and perf for users, and blocks redirects, plus the ip_forward ordering trap. Tested.
- Linux users, groups and file permissions, the secure wayShare files between Linux users without chmod 777: a group-owned setgid directory, the sticky bit, one ACL for a service, and an audit for world-writable files.
- Log review with journalctl, the secure wayReview Linux logs with journalctl: persistent storage, auth and priority filters, trusted fields that expose fake entries, access control, and log sealing.
- Mount options: noexec, nosuid, nodev, the secure wayMount /tmp, /var/tmp, /dev/shm and /home with noexec, nosuid and nodev, and learn what each option stops and what it does not. Tested with findmnt and real escapes.
- nftables default-drop firewall, the secure wayA default-drop nftables ruleset for a Linux server: established traffic, ICMP, SSH from admin networks only, one public port. Tested with real probes.
- Package repository keys and version locks, the secure wayAdd third-party apt repositories with a Signed-By key scoped to that repo, pin what they may install, and lock versions with apt-mark hold or dnf versionlock.
- Scoped sudo rules, the secure wayWrite sudoers rules that give exact commands, not root: no wildcards in arguments, sudoedit for files, NOEXEC as a backstop. Tested with sudo -l and escapes.
- Secure shell scripts, the secure wayWrite Bash scripts that fail safely: set -Eeuo pipefail, quoted variables, ${var:?} before rm, mktemp, globs instead of ls, input checks, and ShellCheck in CI.
- SSH server hardening, the secure wayHarden sshd_config with a drop-in file: keys only, no root login, one allowed group, no forwarding. Proven with sshd -T, including the first-value-wins trap.
- systemd service sandboxing, the secure waySandbox a systemd service with DynamicUser, ProtectSystem=strict, no capabilities and a syscall filter, and gate it in CI with systemd-analyze security --offline.
- Time sync and why security needs it, the secure wayWhy TLS, Kerberos, TOTP and log timelines break when clocks drift, and how to run chrony with NTS-authenticated servers and minsources. Tested with chronyc.
- umask and login.defs, the secure waySet UMASK 027 and HOME_MODE 0700 in login.defs, enable pam_umask so logins use it, and set UMask= for services. Tested on Debian 12 with real file modes.
- Unattended security upgrades, the secure wayInstall security updates automatically with unattended-upgrades on Debian and Ubuntu and dnf-automatic on RHEL and Rocky, with reboots handled. Tested with dry runs.