Ollama Hardening

Tested on: Ubuntu 24.04 LTS, Ollama 0.30.9 (June 2026 stable line), NVIDIA driver 555-series with CUDA 12.x, Caddy 2.8 as the reverse proxy. The Ollama binary moves fast; verify the systemd unit and environment-variable names against the release you are installing. This guide assumes you have already worked through ubuntu-baseline or rhel-baseline and the ssh-hardening guide. Ollama is layered on top of a defensible host, not a fresh provider image. If the underlying box is not hardened, hardening the model server on top of it is theatre. ...

10 min

NIS2 Technical Readiness Checklist

Scope A technical self-assessment for entities in scope of the NIS2 Directive (Directive (EU) 2022/2555). Each item is a thing a sysadmin can verify on a host now — a command output, a config flag, a file’s contents, an external scan result — not a policy approval or a named role. This is the box-level companion to nis2-infrastructure. That guide explains why each Article 21(2) measure matters and how to implement it; this checklist is the “is it actually configured?” layer. ...

8 min

Nginx Rate Limiting — limit_req, limit_conn, and fail2ban

Tested on: Ubuntu 24.04 LTS, Nginx 1.26.x (nginx.org stable repository). All directives are core Nginx — no third-party modules required. Why this matters A web tier with no rate limiting fails in three predictable ways: Authentication brute force. A WordPress, application, or admin-panel login form with no rate cap is one credential-stuffing tool away from compromise. Signup / forgot-password abuse. Endpoints that send email, provision accounts, or issue tokens are expensive and attractive to spammers. Single-tenant noise becomes shared-tenant outage. One misbehaving client (or one bot) hammering an endpoint can starve FPM workers, application-server threads, and database connections. Rate limiting is not DDoS protection — that lives at the CDN / WAF layer if you need it. Nginx rate limiting is for the predictable, day-to-day class of behaviour: too many requests from too few sources to too few endpoints. Get this right and your origin survives even when something at the edge fails. ...

7 min

WordPress Hardening for Agencies

Tested on: WordPress 6.5.x on Ubuntu 24.04 LTS, Nginx 1.26.x, PHP-FPM 8.3, MariaDB 10.11. Most settings translate directly to Apache; Nginx-specific blocks are clearly marked. Why this matters WordPress powers a large share of the web, which makes it the most attacked CMS. Most WordPress incidents are not novel — they are one of: An out-of-date plugin with a known CVE, exploited within days of public disclosure. wp-login.php brute-force, succeeding because an admin reused a password leaked from elsewhere. Filesystem permissions that let the web server write to source files, so a single PHP RCE becomes persistent. A backup containing the entire database, stored unencrypted, exposed via a misconfigured S3 bucket. For an agency hosting multiple client sites, the blast radius compounds: one compromised site can pivot to siblings via shared filesystem, shared database server, or shared PHP-FPM pool. This guide gives you a baseline that addresses each of the above and isolates per-site risk. ...

8 min

Hardened RHEL / AlmaLinux VPS Baseline

Tested on: AlmaLinux 9.4 (kernel 5.14.x). The same steps apply to Rocky Linux 9 and Red Hat Enterprise Linux 9.x — all three share the same package set, service names, and SELinux profile. Why this matters A fresh RHEL-family cloud image differs from Ubuntu’s defaults in two important ways: SELinux is in enforcing mode by default — which is good, until an operator hits a denied syscall, panics, and runs setenforce 0. The baseline below assumes you’ll keep SELinux on and learn to tune it. The default firewall is firewalld, not ufw — same idea, different vocabulary. Internal-API hosts often ship with firewalld enabled but permissive; never trust the defaults without inspecting. Otherwise the threat model and the order of operations match the Ubuntu baseline: create a non-root user, harden SSH, enforce a host firewall, enable automatic security updates, turn on auditing, fix time. This guide is the RHEL-family-specific translation. ...

7 min

Hardened Ubuntu VPS Baseline

Tested on: Ubuntu 24.04 LTS (Noble Numbat), kernel 6.8.x, on a Hetzner Cloud CX22 instance. Steps are valid on any cloud VPS image of the same Ubuntu version. Why this matters A fresh Ubuntu cloud image is fine for a tutorial and unsuitable for production. Out of the box: The root account often accepts SSH key auth. No host firewall is enforced (the cloud provider’s network firewall is not a substitute, especially for internal traffic). Security updates apply only if you manually run apt upgrade. Time can drift by minutes, breaking TLS verification and log correlation. Audit logging is not enabled, so post-incident investigation depends on whatever syslog happens to have captured. This baseline closes those gaps in an opinionated order that minimises the window during which the server is reachable but not yet hardened. Before running step 1, pick your processors and decide your logging posture — some of the choices below depend on it. ...

6 min

Redis Hardening

Tested on: Ubuntu 24.04 LTS, Redis 7.2.x (from the official redis apt repository at packages.redis.io). Configuration paths use /etc/redis/redis.conf — RHEL-family installs use /etc/redis/redis.conf as well, so the file paths below are portable. Why this matters Almost every newsworthy Redis incident reduces to one of three failures: The server was bound to 0.0.0.0 “for testing” and reachable from the internet. There was no password (or the password was the example one from a tutorial). FLUSHALL, CONFIG, or DEBUG were left available, so a connected client could wipe data, exfiltrate keys, or write arbitrary files through CONFIG SET dir / BGSAVE. Redis is fast, in-memory, and trusts its clients by default. That trust is appropriate inside a private subnet with disciplined access controls. It is catastrophic everywhere else. This guide closes those three holes and adds the obvious next layer (TLS, resource limits, persistence safety). ...

6 min

SSH Hardening

Tested on: Ubuntu 24.04 LTS and AlmaLinux 9.4, OpenSSH 9.6 / 8.7 respectively. Configuration paths and directive names below are identical across both. Why this matters SSH is the front door to every server on this site. Three classes of failure account for almost every real-world SSH compromise: Password authentication accepting credentials harvested elsewhere. The root account directly logged into over SSH. A key from a former employee, contractor, or compromised workstation still present in ~/.ssh/authorized_keys six months later. This guide closes those holes and adds the minimum useful operational controls. It does not recommend changing the SSH port, fail2ban, or port-knocking as primary controls — those are noise reducers, not the security boundary. See “Gotchas” for why. ...

6 min

redis-check

What this script does redis-check is a read-only Bash + redis-cli script that reports on each recommendation from the Redis hardening guide: Network exposure (bind, protected-mode) Authentication (default user state, any ACL user with nopass) Dangerous-command accessibility (FLUSHALL, FLUSHDB, DEBUG, CONFIG, SHUTDOWN) TLS (tls-port vs cleartext port) Resource limits (maxmemory, maxmemory-policy, timeout) Persistence (appendonly) It uses only PING, INFO, CONFIG GET, ACL LIST, and COMMAND DOCS — no writes. If CONFIG has been renamed or disabled (recommended in the guide), the affected checks are skipped with a WARN rather than failing the whole run. ...

7 min

Nginx TLS Configuration — 2026 Baseline

Tested on: Ubuntu 24.04 LTS, Nginx 1.26.x (from nginx.org stable repository), Let’s Encrypt via certbot 2.x. The same config works on RHEL 9 / AlmaLinux 9 with path adjustments noted inline. Why this matters Most Nginx TLS configurations on the internet were copy-pasted from a tutorial written three to seven years ago. That means they typically have one or more of the following problems: TLS 1.0 and 1.1 still enabled “for compatibility” with browsers that no longer exist. A hand-rolled cipher list that excludes modern AEAD suites or includes long-deprecated ones (3DES, RC4, CBC-mode without AEAD). ssl_prefer_server_ciphers on — which was correct advice once but is now the wrong default for TLS 1.3. No OCSP stapling, so every visitor’s browser does a side-channel OCSP lookup to the CA on first connection. HSTS missing, or HSTS set without includeSubDomains on a domain that has subdomains people forgot about. HTTP-only Strict-Transport-Security header (it must be served over HTTPS to be honoured at all). This guide gives you a single, opinionated baseline that addresses all of the above. It targets the Mozilla “Intermediate” profile — broad client compatibility without enabling anything embarrassing. ...

5 min