image::logo/horizontal.png[Ubuntu Hardening]
= Hardening Ubuntu. Systemd edition.

:icons: font

A quick way to make a Ubuntu server a bit more secure.

NOTE: Read the code and do not run this script without first testing in a
non-operational environment. The code is *not* idempotent and no longer actively maintained.
If you want to harden your Ubuntu system in a more idempotent and maintainable way
use the https://github.com/konstruktoid/ansible-collection-hardening[Ansible collection] instead.

Use the newly installed and configured system as a reference,
or golden, image. Use that image as a baseline installation media and ensure
that any future installation comply with benchmarks and policies using a
configuration management tool, e.g https://www.ansible.com/[Ansible] or
https://puppet.com/[Puppet].

Tested on `Ubuntu 22.04 (Jammy Jellyfish)` and `Ubuntu 24.04 (Noble Numbat)`.

If you're interested in testing your host settings, you'll find the
link:README.adoc#tests[instructions here].

NOTE: There is a https://slsa.dev/[SLSA] artifact present under the
https://github.com/konstruktoid/hardening/actions/workflows/slsa.yml[slsa workflow]
for file checksum verification.

== Ansible playbook

An Ansible playbook is available in the https://github.com/konstruktoid/ansible-role-hardening[konstruktoid/ansible-role-hardening]
repository.

== Howto

. Start the server installation.
. Pick language and keyboard layout.
. Select "Ubuntu Server (minimized)".
. Configure network connections.
. Partition the system, see below for recommendations.
. Do not install the OpenSSH server, "Featured Server Snaps", or any other packages.
. Finish the installation and reboot.
. Log in.
. If wanted, set a Grub2 password with `grub-mkpasswd-pbkdf2`. See https://help.ubuntu.com/community/Grub2/Passwords[https://help.ubuntu.com/community/Grub2/Passwords]
for more information.
. Install necessary packages: `sudo apt-get -y install git net-tools procps --no-install-recommends`.
. Download the script: `git clone https://github.com/konstruktoid/hardening.git`.
. Change the configuration options in the `ubuntu.cfg` file. Make sure to update the CHANGEME variable otherwise the script will fail.
. Run the script: `sudo bash ubuntu.sh`.
. Reboot.

=== Recommended partitions and options

[source,shell]
----
/boot (rw)
/home (rw,nosuid,nodev)
/var/log (rw,nosuid,nodev,noexec)
/var/log/audit (rw,nosuid,nodev,noexec)
/var/tmp (rw,nosuid,nodev,noexec)
----

Note that `/tmp` will be added automatically by the script.

== Configuration options

[source,shell]
----
FW_ADMIN='127.0.0.1' // <1>
SSH_GRPS='sudo' // <2>
SSH_PORT='22' // <3>
SYSCTL_CONF='./misc/sysctl.conf' // <4>
AUDITD_MODE='1' // <5>
AUDITD_RULES='./misc/audit-base.rules ./misc/audit-aggressive.rules ./misc/audit-docker.rules' // <6>
LOGROTATE_CONF='./misc/logrotate.conf' // <7>
NTPSERVERPOOL='0.ubuntu.pool.ntp.org 1.ubuntu.pool.ntp.org 2.ubuntu.pool.ntp.org 3.ubuntu.pool.ntp.org pool.ntp.org' // <8>
TIMEDATECTL='' // <9>
VERBOSE='N' // <10>
AUTOFILL='N' // <11>
ADMINEMAIL="root@localhost" // <12>
KEEP_SNAPD='Y' // <13>
CHANGEME='' // <14>

# Configuration files // <15>
ADDUSER='/etc/adduser.conf'
AUDITDCONF='/etc/audit/auditd.conf'
AUDITRULES='/etc/audit/rules.d/hardening.rules'
COMMONPASSWD='/etc/pam.d/common-password'
COMMONACCOUNT='/etc/pam.d/common-account'
COMMONAUTH='/etc/pam.d/common-auth'
COREDUMPCONF='/etc/systemd/coredump.conf'
DEFAULTGRUB='/etc/default/grub.d'
DISABLEFS='/etc/modprobe.d/disablefs.conf'
DISABLEMOD='/etc/modprobe.d/disablemod.conf'
DISABLENET='/etc/modprobe.d/disablenet.conf'
FAILLOCKCONF='/etc/security/faillock.conf'
JOURNALDCONF='/etc/systemd/journald.conf'
LIMITSCONF='/etc/security/limits.conf'
LOGINDCONF='/etc/systemd/logind.conf'
LOGINDEFS='/etc/login.defs'
LOGROTATE='/etc/logrotate.conf'
PAMLOGIN='/etc/pam.d/login'
PSADCONF='/etc/psad/psad.conf'
PSADDL='/etc/psad/auto_dl'
RESOLVEDCONF='/etc/systemd/resolved.conf'
RKHUNTERCONF='/etc/default/rkhunter'
RSYSLOGCONF='/etc/rsyslog.conf'
SECURITYACCESS='/etc/security/access.conf'
SSHFILE='/etc/ssh/ssh_config'
SSHDFILE='/etc/ssh/sshd_config'
SYSCTL='/etc/sysctl.conf'
SYSTEMCONF='/etc/systemd/system.conf'
TIMESYNCD='/etc/systemd/timesyncd.conf'
UFWDEFAULT='/etc/default/ufw'
USERADD='/etc/default/useradd'
USERCONF='/etc/systemd/user.conf'

----
<1> The IP addresses that will be able to connect with SSH, separated by spaces.
<2> Which group the users have to be member of in order to acess via SSH, separated by spaces.
<3> Configure SSH port.
<4> Stricter sysctl settings.
<5> Auditd failure mode. 0=silent 1=printk 2=panic.
<6> Auditd rules.
<7> Logrotate settings.
<8> NTP server pool.
<9> Add a specific time zone or use the system default by leaving it empty.
<10> If you want all the details or not.
<11> Let the script guess the `FW_ADMIN` and `SSH_GRPS` settings.
<12> Add a valid email address, so PSAD can send notifications.
<13> If `'Y'` then the `snapd` package will be held to prevent removal.
<14> Add something just to verify that you actually glanced the code.
<15> Default configuration file locations.

== Functions

=== Function list in execution order

Note that all functions has the `f_` prefix in the code.

==== `pre`

Sets `apt` flags and performs basic permission check.

The `pre` function is located in link:scripts/pre[./scripts/pre].

==== `kernel`

Sets https://github.com/jeffmurphy/NetPass/blob/master/doc/netfilter_conntrack_perf.txt#L175[/sys/module/nf_conntrack/parameters/hashsize]
to 1048576 if `hashsize` exists and is writable.

Sets https://man7.org/linux/man-pages/man7/kernel_lockdown.7.html[/sys/kernel/security/lockdown]
to `confidentiality` if `lockdown` exists and is writable.

The `kernel` function is located in link:scripts/kernel[./scripts/kernel].

==== `firewall`

Configures https://help.ubuntu.com/community/UFW[UFW] if installed.

Allows connections from the adresses in `$FW_ADMIN` to the `$SSH_PORT`.

Sets logging and `IPT_SYSCTL=/etc/sysctl.conf`.

The `firewall` function is located in link:scripts/ufw[./scripts/ufw].

==== `disablenet`

Disables the `dccp`, `sctp`, `rds` and `tipc` kernel modules.

The `disablenet` function is located in link:scripts/disablenet[./scripts/disablenet].

==== `disablefs`

Disables the `cramfs` `freevxfs` `jffs2` `ksmbd` `hfs` `hfsplus` `udf` kernel
modules.

The `disablefs` function is located in link:scripts/disablefs[./scripts/disablefs].

==== `disablemod`

Disables the `bluetooth`, `bnep`, `btusb`, `cpia2`, `firewire-core`, `floppy`,
`n_hdlc`, `net-pf-31`, `pcspkr`, `soundcore`, `thunderbolt`, `usb-midi`,
`usb-storage`, `uvcvideo`, `v4l2_common` kernel modules.

Note that disabling the `usb-storage` module will disable any usage of USB
storage devices, if such devices are needed `USBGuard` should be configured
accordingly and `usb-storage` removed from the `disablemod` function.

The `disablemod` function is located in link:scripts/disablemod[./scripts/disablemod].

==== `systemdconf`

Sets `CrashShell=no`, `DefaultLimitCORE=0`, `DefaultLimitNOFILE=1024`,
`DefaultLimitNPROC=1024`, `DumpCore=no` in `$SYSTEMCONF`
and `$USERCONF`.

The `systemdconf` function is located in link:scripts/systemdconf[./scripts/systemdconf].

==== `resolvedconf`

Sets `DNS=$dnslist`, `DNSOverTLS=opportunistic`, `DNSSEC=allow-downgrade`, `FallbackDNS=1.0.0.1`
in `$RESOLVEDCONF`, where `$dnslist` is an array with the nameservers present
in `/etc/resolv.conf`.

The `resolvedconf` function is located in link:scripts/resolvedconf[./scripts/resolvedconf].

==== `logindconf`

Sets `IdleAction=lock`, `IdleActionSec=15min`, `KillExcludeUsers=root`,
`KillUserProcesses=1`, `RemoveIPC=yes` in `$LOGINDCONF`.

The `logindconf` function is located in link:scripts/logindconf[./scripts/logindconf].

==== `journalctl`

Copies link:misc/logrotate.conf[./misc/logrotate.conf] to `$LOGROTATE`.

Sets `Compress=yes`, `ForwardToSyslog=yes`, `Storage=persistent` in
`$JOURNALDCONF`.

Sets `$FileCreateMode 0600/` in `$RSYSLOGCONF`.
if `RSYSLOGCONF` is writable.

The `journalctl` function is located in link:scripts/journalctl[./scripts/journalctl].

==== `timesyncd`

Sets `NTP=${SERVERARRAY}`, `FallbackNTP=${FALLBACKARRAY}`, `RootDistanceMaxSec=1`
in `$TIMESYNCD` where the arrays are up to four time servers with < 50ms
latency.

The `timesyncd` function is located in link:scripts/timesyncd[./scripts/timesyncd].

==== `fstab`

Configures the `/boot` and `/home` partitions with `defaults,nosuid,nodev` if
they are available in `/etc/fstab`.

Configures the `/var/log`, `/var/log/audit` and `/var/tmp` partitions with
`defaults,nosuid,nodev,noexec` if they are available in `/etc/fstab`.

Adds `/run/shm tmpfs rw,noexec,nosuid,nodev`,
`/dev/shm tmpfs rw,noexec,nosuid,nodev` and
`/proc proc rw,nosuid,nodev,noexec,relatime,hidepid=2` to `/etc/fstab` if
the partition isn't present in `/etc/fstab`.

Removes any floppy drivers from `/etc/fstab`.

Copies ./config/tmp.mount[./config/tmp.mount] to
`/etc/systemd/system/tmp.mount`, removes `/tmp` from `/etc/fstab`
and enables the tmpfs `/tmp` mount instead.

The `/proc` `hidepid` option is described in https://www.kernel.org/doc/html/latest/filesystems/proc.html#mount-options[https://www.kernel.org/doc/html/latest/filesystems/proc.html#mount-options].

The `fstab` function is located in link:scripts/fstab[./scripts/fstab].

==== `prelink`

Reverts binaries and libraries to their original content before they were
prelinked and uninstalls `prelink`.

The `prelink` function is located in link:scripts/prelink[./scripts/prelink].

==== `aptget_configure`

Sets `apt` options `Acquire::http::AllowRedirect "false";`, `APT::Get::AllowUnauthenticated "false";`,
`APT::Periodic::AutocleanInterval "7";`,
`APT::Install-Recommends "false";`, `APT::Get::AutomaticRemove "true";`,
`APT::Install-Suggests "false";`, `Acquire::AllowDowngradeToInsecureRepositories "false";`,
`Acquire::AllowInsecureRepositories "false";`, `APT::Sandbox::Seccomp "1";`

See https://manpages.ubuntu.com/manpages/jammy/man5/apt.conf.5.html[https://manpages.ubuntu.com/manpages/jammy/man5/apt.conf.5.html].

The `aptget_configure` function is located in link:scripts/aptget[./scripts/aptget].

==== `aptget`

Upgrades installed packages.

The `aptget` function is located in link:scripts/aptget[./scripts/aptget].

==== `hosts`

Sets `sshd : ALL : ALLOW`, `ALL: LOCAL, 127.0.0.1` in `/etc/hosts.allow` and
`ALL: ALL` in `/etc/hosts.deny`.

See https://manpages.ubuntu.com/manpages/jammy/man5/hosts_access.5.html[https://manpages.ubuntu.com/manpages/jammy/man5/hosts_access.5.html]
for the format of host access control files.

The `hosts` function is located in link:scripts/hosts[./scripts/hosts].

==== `issue`

Writes a notice regarding authorized use only to `/etc/issue`, `/etc/issue.net`
and `/etc/motd`.

Removes the executable flag from every file in `/etc/update-motd.d/`.

The `issue` function is located in link:scripts/issue[./scripts/issue].

==== `sudo`

Restricts `su` access to members of the `sudo` group using
https://manpages.ubuntu.com/manpages/jammy/man8/pam_wheel.8.html[pam_wheel].

Sets `!pwfeedback`, `!visiblepw`, `logfile=/var/log/sudo.log`, `passwd_timeout=1`,
`timestamp_timeout=5`, `use_pty` https://manpages.ubuntu.com/manpages/jammy/man5/sudoers.5.html[sudo options].

The `sudo` function is located in link:scripts/sudo[./scripts/sudo].

==== `logindefs`

Writes `LOG_OK_LOGINS yes`, `UMASK 077`, `PASS_MIN_DAYS 1`, `PASS_MAX_DAYS 60`,
`DEFAULT_HOME no`, `ENCRYPT_METHOD SHA512`, `USERGROUPS_ENAB no`,
`SHA_CRYPT_MIN_ROUNDS 10000`, `SHA_CRYPT_MAX_ROUNDS 65536` to
https://manpages.ubuntu.com/manpages/jammy/man5/login.defs.5.html[$LOGINDEFS]

The `logindefs` function is located in link:scripts/logindefs[./scripts/logindefs].

==== `sysctl`

Copies link:misc/sysctl.conf[./misc/sysctl.conf] to `$SYSCTL`.

For an explanation of the options set, see
https://www.kernel.org/doc/html/latest/admin-guide/sysctl/[https://www.kernel.org/doc/html/latest/admin-guide/sysctl/].

The `sysctl` function is located in link:scripts/sysctl[./scripts/sysctl].

==== `limitsconf`

Sets `hard maxlogins 10`, `hard core 0`, `soft nproc 512`, `hard nproc 1024` in
https://manpages.ubuntu.com/manpages/jammy/en/man5/limits.conf.5.html[$LIMITSCONF]

The `limitsconf` function is located in link:scripts/limits[./scripts/limits].

==== `adduser`

Sets `DIR_MODE=0750`,`DSHELL=/bin/false`, and `USERGROUPS=yes` in `$ADDUSER`.

Sets `INACTIVE=30` and `SHELL=/bin/false` in `$USERADD`.

The `adduser` function is located in link:scripts/adduser[./scripts/adduser].

==== `rootaccess`

Writes `+:root:127.0.0.1/'` to `$SECURITYACCESS` and `console` to
`/etc/securetty`.

Masks https://freedesktop.org/wiki/Software/systemd/Debugging/[debug-shell].

The `rootaccess` function is located in link:scripts/rootaccess[./scripts/rootaccess].

==== `package_install`

Installs `acct`, `aide-common`, `cracklib-runtime`, `debsums`, `gnupg2`,
`haveged`, `libpam-pwquality`, `libpam-tmpdir`, `needrestart`, `openssh-server`,
`postfix`, `psad`, `rkhunter`, `sysstat`, `systemd-coredump`, `tcpd`,
`update-notifier-common`, `vlock`.

The `package_install` function is located in link:scripts/packages[./scripts/packages].

==== `psad`

Installs and configures https://cipherdyne.org/psad/[PSAD]

The `psad` function is located in link:scripts/psad[./scripts/psad].

==== `coredump`

Writes `Storage=none` and `ProcessSizeMax=0` to `$COREDUMPCONF`.

The `coredump` function is located in link:scripts/coredump[./scripts/coredump].

==== `usbguard`

Installs and configures https://usbguard.github.io/[USBGuard].

The `usbguard` function is located in link:scripts/usbguard[./scripts/usbguard].

==== `postfix`

Installs `postfix` and sets `disable_vrfy_command=yes`,
`inet_interfaces=loopback-only`,
`smtpd_banner="\$myhostname`,
`smtpd_client_restrictions=permit_mynetworks,reject` using https://manpages.ubuntu.com/manpages/jammy/en/man1/postconf.1.html[postconf].

The `postfix` function is located in link:scripts/postfix[./scripts/postfix].

==== `apport`

Disables
https://manpages.ubuntu.com/manpages/jammy/man1/apport-cli.1.html[apport],
https://github.com/Ubuntu/ubuntu-report[ubuntu-report] and
https://manpages.ubuntu.com/manpages/jammy/en/man8/popularity-contest.8.html[popularity-contest].

The `apport` function is located in link:scripts/apport[./scripts/apport].

==== `motdnews`

Disables `apt_news` and https://ubuntu.com/legal/motd[motd-news].

The `motdnews` function is located in link:scripts/motdnews[./scripts/motdnews].

==== `rkhunter`

Sets `CRON_DAILY_RUN="yes"`, `APT_AUTOGEN="yes"` in `$RKHUNTERCONF`.

The `rkhunter` function is located in link:scripts/rkhunter[./scripts/rkhunter].

==== `sshconfig`

Sets `HashKnownHosts yes`, `Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes256-ctr`
and `MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-sha2-512,hmac-sha2-256`
in `$SSHFILE`.

The `sshconfig` function is located in link:scripts/sshdconfig[./scripts/sshdconfig].

==== `sshdconfig`

Configures the `OpenSSH` daemon. The configuration changes will be placed in
the directory defined by the `Include` option if present, otherwise
https://manpages.ubuntu.com/manpages/jammy/en/man5/sshd_config.5.html[$SSHDFILE]
will be modified.

By default `/etc/ssh/sshd_config.d/hardening.conf` will contain the following:

[source,shell]
----
AcceptEnv LANG LC_*
AllowAgentForwarding no
AllowGroups sudo
AllowTcpForwarding no
Banner /etc/issue.net
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes256-ctr
ClientAliveCountMax 3
ClientAliveInterval 200
Compression no
GSSAPIAuthentication no
HostbasedAuthentication no
IgnoreUserKnownHosts yes
KbdInteractiveAuthentication no
KerberosAuthentication no
KexAlgorithms curve25519-sha256@libssh.org,ecdh-sha2-nistp521,ecdh-sha2-nistp384,ecdh-sha2-nistp256,diffie-hellman-group-exchange-sha256
LogLevel VERBOSE
LoginGraceTime 20
Macs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-sha2-512,hmac-sha2-256
MaxAuthTries 3
MaxSessions 3
MaxStartups 10:30:60
PasswordAuthentication no
PermitEmptyPasswords no
PermitRootLogin no
PermitUserEnvironment no
Port 22
PrintLastLog yes
PrintMotd no
RekeyLimit 512M 1h
StrictModes yes
TCPKeepAlive no
UseDNS no
UsePAM yes
X11Forwarding no
----

The `sshdconfig` function is located in link:scripts/sshdconfig[./scripts/sshdconfig].

==== `password`

Copies ./config/pwquality.conf[./config/pwquality.conf] to `/etc/security/pwquality.conf`,

Removes `nullok` from https://manpages.ubuntu.com/manpages/jammy/man5/pam.conf.5.html[PAM]
`$COMMONAUTH`.

Configures https://manpages.ubuntu.com/manpages/jammy/en/man8/faillock.8.html[faillock]
or https://manpages.ubuntu.com/manpages/jammy/man8/pam_tally2.8.html[pam_tally2]
depending on which is installed.

Adds a link:misc/passwords.list[password list] to https://manpages.ubuntu.com/manpages/jammy/man8/update-cracklib.8.html[cracklib].

The `password` function is located in link:scripts/password[./scripts/password].

==== `cron`

Disables https://manpages.ubuntu.com/manpages/jammy/en/man8/atd.8.html[atd]
and only allow root to use https://manpages.ubuntu.com/manpages/jammy/en/man1/at.1.html[at]
or https://manpages.ubuntu.com/manpages/jammy/en/man8/cron.8.html[cron].

The `cron` function is located in link:scripts/cron[./scripts/cron].

==== `ctrlaltdel`

Masks https://manpages.ubuntu.com/manpages/jammy/man1/systemd.1.html#signals[ctrl-alt-del.target].

The `ctrlaltdel` function is located in link:scripts/ctraltdel[./scripts/ctraltdel].

==== `auditd`

Configures https://manpages.ubuntu.com/manpages/jammy/en/man8/auditd.8.html[auditd].

See link:misc/audit-base.rules[./misc/audit-base.rules],
link:misc/audit-aggressive.rules[./misc/audit-aggressive.rules] and link:misc/audit-docker.rules[./misc/audit-docker.rules]
for the rules used.

The `auditd` function is located in link:scripts/auditd[./scripts/auditd].

==== `aide`

Excludes `/var/lib/lxcfs/cgroup` and `/var/lib/docker` from https://manpages.ubuntu.com/manpages/jammy/en/man1/aide.1.html[AIDE].

The `aide` function is located in link:scripts/aide[./scripts/aide].

==== `rhosts`

Removes any existing `hosts.equiv` or `.rhosts` files.

The `rhosts` function is located in link:scripts/rhosts[./scripts/rhosts].

==== `users`

Removes the `games`, `gnats`, `irc`, `list`, `news`, `sync`, `uucp` users.

The `users` function is located in link:scripts/users[./scripts/users].

==== `lockroot`

Locks root account

The `lockroot` function is located in link:scripts/lockroot[./scripts/lockroot].

==== `package_remove`

Removes the `apport*`, `autofs`, `avahi*`, `beep`, `git`, `pastebinit`,
`popularity-contest`, `rsh*`, `rsync`, `talk*`, `telnet*`, `tftp*`, `whoopsie`,
`xinetd`, `yp-tools`, `ypbind` packages.

The `package_remove` function is located in link:scripts/packages[./scripts/packages].

==== `suid`

Ensures the executables in link:misc/suid.list[./misc/suid.list] don't have suid
bits set.

The `suid` function is located in link:scripts/suid[./scripts/suid].

==== `restrictcompilers`

Changes mode to `0750` on any installed compilers.

The `restrictcompilers` function is located in link:scripts/compilers[./scripts/compilers].

==== `umask`

Sets the default https://manpages.ubuntu.com/manpages/jammy/man2/umask.2.html[umask] to `077`

The `umask` function is located in link:scripts/umask[./scripts/umask].

==== `path`

Copies ./config/initpath.sh[./config/initpath.sh] to `/etc/profile.d/initpath.sh`
and sets `PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin`
for the `root` user and `PATH=/usr/local/bin:/usr/sbin:/usr/bin:/bin:/snap/bin`
for everyone else.

The `path` function is located in link:scripts/path[./scripts/path].

==== `aa_enforce`

Enforces available https://manpages.ubuntu.com/manpages/jammy/en/man7/apparmor.7.html[apparmor]
profiles.

The `aa_enforce` function is located in link:scripts/apparmor[./scripts/apparmor].

==== `aide_post`

Creates a new AIDE database.

The `aide_post` function is located in link:scripts/aide[./scripts/aide].

==== `aide_timer`

Copies a systemd AIDE check service and timer to /etc/systemd/system/.

The `aide_timer` function is located in link:scripts/aide[./scripts/aide].

==== `aptget_noexec`

Adds a `DPkg::Pre-Invoke` and `DPkg::Post-Invoke` to ensure package updates
don't fail on a `noexec` `/tmp` partition.

The `aptget_noexec` function is located in link:scripts/aptget[./scripts/aptget].

==== `aptget_clean`

Runs https://manpages.ubuntu.com/manpages/jammy/en/man8/apt-get.8.html[apt-get] `clean` and `autoremove`.

The `aptget_clean` function is located in link:scripts/aptget[./scripts/aptget].

==== `systemddelta`

Runs https://manpages.ubuntu.com/manpages/jammy/man1/systemd-delta.1.html[systemd-delta] if running in verbose mode.

The `systemddelta` function is located in link:scripts/systemddelta[./scripts/systemddelta].

==== `post`

Ensures https://manpages.ubuntu.com/manpages/jammy/man1/fwupdmgr.1.html[fwupdmgr]
and https://packages.ubuntu.com/jammy/secureboot-db[secureboot-db] is installed
and GRUB is updated.

The `post` function is located in link:scripts/post[./scripts/post].

==== `checkreboot`

Checks if a reboot is required.

The `checkreboot` function is located in link:scripts/reboot[./scripts/reboot].

== Tests
There are approximately 760 https://github.com/bats-core/bats-core[Bats tests]
for most of the above settings available in the link:tests/[tests directory].

[source,shell]
----
sudo apt-get -y install bats
git clone https://github.com/konstruktoid/hardening.git
cd hardening/tests/
sudo bats .
----

=== Test automation using Vagrant
Running `bash ./runTests.sh` will use https://www.vagrantup.com/[Vagrant] to run
all above tests, https://github.com/CISOfy/Lynis[Lynis] and
https://www.open-scap.org/[OpenSCAP] with a
https://www.cisecurity.org/benchmark/ubuntu_linux[CIS Ubuntu benchmark] on all
supported Ubuntu versions.

The script will generate a file named `TESTRESULTS.adoc` and CIS report in
HTML-format.

=== Testing a host
Running `bash ./runHostTests.sh`, located in the link:tests/[tests directory],
will generate a `TESTRESULTS-<HOSTNAME>.adoc` report.

Running `bash ./runHostTestsCsv.sh`, located in the link:tests/[tests directory],
will generate a `TESTRESULTS-<HOSTNAME>.csv` report.


== Recommended reading
https://public.cyber.mil/stigs/downloads/?_dl_facet_stigs=operating-systems%2Cunix-linux[Canonical Ubuntu 20.04 LTS STIG - Ver 1, Rel 3] +
https://www.cisecurity.org/benchmark/distribution_independent_linux/[CIS Distribution Independent Linux Benchmark] +
https://www.cisecurity.org/benchmark/ubuntu_linux/[CIS Ubuntu Linux Benchmark] +
https://www.ncsc.gov.uk/collection/end-user-device-security/platform-specific-guidance/ubuntu-18-04-lts[EUD Security Guidance: Ubuntu 18.04 LTS] +
https://wiki.ubuntu.com/Security/Features +
https://help.ubuntu.com/community/StricterDefaults +

== Contributing
Do you want to contribute? That's great! Contributions are always welcome,
no matter how large or small. If you found something odd, feel free to
https://github.com/konstruktoid/hardening/issues/[submit a new issue],
improve the code by https://github.com/konstruktoid/hardening/pulls[creating a pull request],
or by https://github.com/sponsors/konstruktoid[sponsoring this project].

Logo by https://github.com/reallinfo[reallinfo].
