In the age of “boot & breach”—spin up a VM in minutes, see it scanned 10 seconds later—your security baseline can’t be a wish list in a wiki. It needs order, repeatability, and sane minimums that don’t negotiate with operational reality. That’s where konstruktoid/hardening fits. The public repository automates Ubuntu hardening (systemd edition) in a strict execution order, with functions that touch kernel, network, systemd/resolved/logind/journal, fstab, SSH, logging, password policy, USB, AppArmor, packages, AIDE/Rkhunter, and more. The goal: leave a server coherent and defensible without forcing admins to stitch together dozens of disparate guides.
The philosophy is “conservative but conscious.” Every control is documented, functions run in a defined sequence, and the script warns where a change has operational impact (e.g., disabling usb-storage will block thumb drives unless you allowlisted devices with USBGuard). It’s not a CIS/ISO replacement; it is a reliable accelerator for Linux/Ubuntu teams to enforce a consistent baseline in minutes—and repeat it with the same recipe across estates.
What it actually does (and why execution order matters)
The script chains functions with the f_ prefix in execution order. The order isn’t cosmetic: it prevents a change from breaking another and reduces mid-flight surprises. A sysadmin-focused recap:
1) Preflight & hardened APT
pre: sets APT flags and performs a basic permission check.aptget_configure: forbids insecure/downgraded repos, disables Recommends/Suggests by default, enables APT seccomp sandbox, sets Autoclean to 7 days and automatic autoremove.aptget: upgrades installed packages after APT has been hardened.
Why it matters: If APT breaks on noexec or pulls from insecure repos, everything after is on thin ice.
2) Firewall & kernel: reduce surface, increase control
firewall: if UFW is installed, configures policy/logging and allows SSH from$FW_ADMINto$SSH_PORT.disablenet: disables rarely used network modules (dccp, sctp, rds, tipc).disablefs: disables filesystems that don’t belong on most servers (cramfs, freevxfs, jffs2, ksmbd, hfs/hfsplus, udf).disablemod: disables potentially risky or unnecessary modules (bluetooth, firewire, pcspkr, uvcvideo, usb-storage, etc.). Heads-up: if you need USB storage, plan to configure USBGuard later and removeusb-storagefrom the blacklist.
3) systemd/resolved/logind/journal: safer defaults and sane telemetry
systemdconf: no core dumps (DumpCore=no),CrashShell=no, conservative file/process limits insystem.confanduser.conf.resolvedconf: configures systemd-resolved with DNS learned from/etc/resolv.conf, DoT in opportunistic mode, DNSSEC as allow-downgrade, and FallbackDNS of 1.0.0.1.logindconf: locks inactive sessions after 15 minutes (IdleAction=lock), kills user processes at logout, clears IPC.journalctl: makes the journal persistent and compressed, forwards to rsyslog, and tightens$FileCreateMode 0600if rsyslog is writable.
Why it matters: less noise and fewer accidental leaks; when something breaks, logs survive reboots and have the right permissions.
4) Time & secure fstab (without breaking APT)
timesyncd: sets NTP servers (up to 4, < 50 ms latency) andRootDistanceMaxSec=1.fstab: enforcesnosuid,nodev,noexecwhere it belongs:/bootand/homegetnosuid,nodev(if present)./var/log,/var/log/audit,/var/tmpaddnoexec(if present).- Add
/run/shmand/dev/shmastmpfs rw,noexec,nosuid,nodev;/procasrw,nosuid,nodev,noexec,relatime,hidepid=2(hide other users’ processes). - Switch
/tmpto systemdtmp.mount(tmpfs).
aptget_noexec: adds Pre/Post-Invoke hooks so APT doesn’t choke on/tmpnoexec.
Why it matters: aggressive fstab without killing dpkg. This is a frequent foot-gun neatly defused.
5) Legal banners, tcp_wrappers and base hygiene
hosts: setssshd : ALL : ALLOW,ALL : LOCAL, 127.0.0.1in/etc/hosts.allow, andALL : ALLin/etc/hosts.deny.issue: writes authorized-use banners to/etc/issue,/etc/issue.net,/etc/motd; removes the executable bit on/etc/update-motd.d/*.
6) Users, PAM, and passwords
sudo: restrictssutosudogroup (viapam_wheel), enforcesuse_pty, logs to/var/log/sudo.log, and uses short passwd/timestamp timeouts.logindefs:UMASK 077,PASS_MIN_DAYS 1,PASS_MAX_DAYS 60, SHA512 with 10K–65K rounds.limitsconf: caps sessions, core, and nproc.adduser/useradd:DIR_MODE=0750,DSHELL=/bin/false,INACTIVE=30.password: deployspwquality.confwith strong password policy and removesnullokfrom PAM (no empty passwords).users: removes obsolete system users (games, gnats, irc, list, news, sync, uucp).lockroot: locks the root account.
7) “Modern & strict” SSH with Include support
sshconfig/sshdconfig: writes to/etc/ssh/sshd_config.d/hardening.conf(whenIncludeis present) with:PasswordAuthentication no,PermitRootLogin no,AllowGroups sudo,Port 22(adjustable).AllowTcpForwarding no,AllowAgentForwarding no,X11Forwarding no,Compression no.- Modern Ciphers/KEX/MACs (Curve25519, chacha20, GCM, SHA2).
LoginGraceTime 20,MaxAuthTries 3,MaxSessions 3,ClientAliveInterval 200/CountMax 3.LogLevel VERBOSEandBanner /etc/issue.net.
Why it matters: uses sshd_config.d/ when available to avoid clobbering existing overrides and simplify maintenance.
8) Integrity, rootkits, and system mail
aide+aide_post+aide_timer: excludes Docker/LXCFS, builds a baseline, and schedules systemd timer checks.rkhunter: enables daily cron and autogeneration.postfix: installs and configures withinet_interfaces=loopback-only,disable_vrfy_command, a minimal banner, and basic client restrictions—ready for local alerting.
9) Core dumps, USB, and AppArmor
coredump: disables storing & sizing of core dumps.usbguard: installs and enforces a USB allowlist.aa_enforce: switches all available AppArmor profiles to enforce.
10) PATH, umask, and package hygiene
path/umask:umask 077and secure PATH (different for root vs users).package_install: security tooling: acct, aide, cracklib, debsums, haveged, pam-pwquality, pam-tmpdir, needrestart, openssh, postfix, psad, rkhunter, sysstat, tcpd, vlock, etc.package_remove: removes distractions and legacy services (apport, autofs, avahi, telnet/tftp/rsh, whoopsie, xinetd, yp*,** even rsync if not used).restrictcompilers: sets compilers to 0750 to prevent unprivileged abuse.
11) Cron/at, rhosts, console access
cron: disablesatdand limits cron/at to root only.rhosts: removeshosts.equivand any.rhosts.rootaccess: tightens/etc/security/access.confand/etc/securetty.
12) Finishing moves: APT cleanup, systemd deltas, reboot flag
aptget_clean: clean/autoremove.systemddelta,post,checkreboot: housekeeping & reboot hint.
Why Ubuntu admins and platform teams are picking it up
- Consistency: the blocks don’t fight each other and the order avoids classic foot-guns (e.g.,
noexecon/tmpwithout dpkg fixes). - Quick win: you can push a high-value baseline in 20–30 minutes and extend later.
- Visibility: leaves authorized-use banners, persistent journal, rsyslog with strict umasks, and local alerting via postfix.
- Real-world security: no core dumps, no weak passwords, SSH reduced to essentials, legacy modules gone, AppArmor in enforce, USB under control.
For estate-level rollouts, you can wrap it in Ansible/Terraform and run it idempotently, with variables for $FW_ADMIN, $SSH_PORT, allowlists, and service specifics.
Caveats and “don’t surprise yourself” limits
usb-storagedisabled will break all USB mass storage not explicitly allowed by USBGuard. If you rely on external drives for backups, plan the policy./tmp noexec+ build pipelines or container tooling can clash if your workflows drop binaries in/tmp. The script covers APT; validate your pipelines.- Package removals: if you need rsync or inetd-style services, adjust before running.
- SSH posture: very strict by default; pair it with proper key distribution/groups and an out-of-band console.
- AppArmor enforce: some less common apps may require profile tuning.
Good practice: take a snapshot, test on staging, roll out in phases, and watch journal/auth logs plus AIDE/Rkhunter post-boot.
Suggested phased adoption (Ubuntu 22.04/24.04)
- Phase 0 – Safety net: snapshot the VM/VPS and ensure provider console access.
- Phase 1 – Access & network:
firewall,ssh[d]config,journalctl,postfix. Validate connectivity/logs. - Phase 2 – Kernel/fstab/PAM:
disablenet,disablefs,disablemod(with USB allowlist if needed),fstab,password/logindefs,limitsconf,sudo/cron. - Phase 3 – Integrity:
aide(baseline + timer),rkhunter. - Phase 4 – Hygiene:
package_remove,restrictcompilers,aptget_clean. - Phase 5 – Audit: optional Lynis run, performance smoke tests, and functional checks.
Typical effort: 30–90 minutes depending on customization.
Bottom line
konstruktoid/hardening has carved out a real niche: automate the Ubuntu systemd security baseline with order, warnings, and battle-tested defaults. For sysadmins and platform teams who can’t spend “a day and a half” hand-hardening every host, this script turns “we should harden” into done: reduced attack surface, better logs, coherent SSH, enforced password policy, scheduled integrity checks, and a stable foundation for compliance frameworks (CIS, SIEM, audits) to build on.
It’s not the last word in security—nor does it claim to be—but it moves any Ubuntu host light-years beyond a vanilla image exposed to the internet. And that, today, makes all the difference.
FAQs
Will it break my production servers if I run it “as is”?
It’s generally safe, but there are sensitive changes: noexec on /tmp, disabling usb-storage, removing legacy packages (e.g., rsync if you need it), enforcing AppArmor, strict SSH. Take a snapshot, test in staging, adjust variables (admin IPs, SSH port, allowlists), and roll out in phases.
How does this compare to running CIS Benchmarks?
CIS is a compliance standard; this script is an operational implant: ordered, pragmatic, and quick to apply. In regulated environments, use it as a starting point and then map to CIS Benchmarks (CIS-CAT) to close compliance gaps.
Can I pick and choose functions?
Yes. Each f_* function is documented, and the repository lists the recommended order. You can comment or invoke selectively, preserving relative sequence (e.g., apply aptget_noexec before fstab tightening). That said, the most robust outcome comes from running the full flow and customizing allowlists.
How do I integrate it with Ansible or Terraform at scale?
Wrap it as an Ansible role or cloud-init step. Expose variables ($FW_ADMIN, $SSH_PORT, USB/DNS/NTP allowlists), add tags by phase (firewall/ssh, fstab/PAM, integrity, cleanup), and wire handlers for sshd/rsyslog/systemd reloads. Validate with Molecule/Inspec or your preferred test harness.
Sources
- konstruktoid/hardening – Hardening Ubuntu. Systemd edition (function list, order, and parameters)
https://github.com/konstruktoid/hardening
This report relies solely on the repository’s documentation (function descriptions and effects). Review the README and config/ files, and test on staging/snapshots before applying to critical systems.

