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_ADMIN to $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 remove usb-storage from the blacklist.

3) systemd/resolved/logind/journal: safer defaults and sane telemetry

  • systemdconf: no core dumps (DumpCore=no), CrashShell=no, conservative file/process limits in system.conf and user.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 0600 if 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) and RootDistanceMaxSec=1.
  • fstab: enforces nosuid,nodev,noexec where it belongs:
    • /boot and /home get nosuid,nodev (if present).
    • /var/log, /var/log/audit, /var/tmp add noexec (if present).
    • Add /run/shm and /dev/shm as tmpfs rw,noexec,nosuid,nodev; /proc as rw,nosuid,nodev,noexec,relatime,hidepid=2 (hide other users’ processes).
    • Switch /tmp to systemd tmp.mount (tmpfs).
  • aptget_noexec: adds Pre/Post-Invoke hooks so APT doesn’t choke on /tmp noexec.

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: sets sshd : ALL : ALLOW, ALL : LOCAL, 127.0.0.1 in /etc/hosts.allow, and ALL : ALL in /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: restricts su to sudo group (via pam_wheel), enforces use_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: deploys pwquality.conf with strong password policy and removes nullok from 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 (when Include is 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 VERBOSE and Banner /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 with inet_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 077 and 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: disables atd and limits cron/at to root only.
  • rhosts: removes hosts.equiv and any .rhosts.
  • rootaccess: tightens /etc/security/access.conf and /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., noexec on /tmp without 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-storage disabled 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)

  1. Phase 0 – Safety net: snapshot the VM/VPS and ensure provider console access.
  2. Phase 1 – Access & network: firewall, ssh[d]config, journalctl, postfix. Validate connectivity/logs.
  3. Phase 2 – Kernel/fstab/PAM: disablenet, disablefs, disablemod (with USB allowlist if needed), fstab, password/logindefs, limitsconf, sudo/cron.
  4. Phase 3 – Integrity: aide (baseline + timer), rkhunter.
  5. Phase 4 – Hygiene: package_remove, restrictcompilers, aptget_clean.
  6. 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

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.

Scroll to Top