#!/bin/bash # # base-stack # https://git.stack-source.com/msb/base-stack # Copyright (c) 2022 Matthew Saunders Brown # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) # # this installer expects a clean Debian 12 install # require root if [ "${EUID}" -ne 0 ]; then echo "This script must be run as root." exit 1 fi # do some basic pre-install checks - these are *not* exhaustive os_id=`lsb_release -is` os_release=`lsb_release -rs` if [ $os_id != Debian ] || [ $os_release != 12 ]; then echo "This installer only runs on Debian 12 (Bookworm), bailing out." exit 1 fi if lsof /var/lib/dpkg/lock-frontend ; then echo "Could not get lock /var/lib/dpkg/lock-frontend" echo "See output above for info on what is holding the lock." echo "What for the command above to complete, then re-run this script." exit 1 fi # set webmaster email address, used below WEBMASTER=webmaster@`hostname -f` # set system variables if [[ ! -f /etc/sysctl.d/60-swappiness.conf ]]; then echo "vm.swappiness = 1" >> /etc/sysctl.d/60-swappiness.conf /sbin/sysctl --quiet --system fi # update system DEBIAN_FRONTEND=noninteractive apt-get -y update # update grub first, by itself, as it requires special overrides to run unattended DEBIAN_FRONTEND=noninteractive apt-get -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" install grub-common grub2-common DEBIAN_FRONTEND=noninteractive apt-get -y dist-upgrade # remove unwanted packages DEBIAN_FRONTEND=noninteractive apt-get -y purge snapd cryptsetup ufw iptables popularity-contest DEBIAN_FRONTEND=noninteractive apt-get -y autoremove systemctl daemon-reload # configure unattended upgrades with automatic reboots DEBIAN_FRONTEND=noninteractive apt-get -y install unattended-upgrades apt-listchanges sed -i 's|// "origin=Debian,codename=${distro_codename}-updates";| "origin=Debian,codename=${distro_codename}-updates";|g' /etc/apt/apt.conf.d/50unattended-upgrades # sed -i 's|// "origin=Debian,codename=${distro_codename}-proposed-updates";| "origin=Debian,codename=${distro_codename}-proposed-updates";|g' /etc/apt/apt.conf.d/50unattended-upgrades sed -i 's|//Unattended-Upgrade::Remove-Unused-Kernel-Packages "true";|Unattended-Upgrade::Remove-Unused-Kernel-Packages "true";|g' /etc/apt/apt.conf.d/50unattended-upgrades sed -i 's|//Unattended-Upgrade::Remove-Unused-Dependencies "false";|Unattended-Upgrade::Remove-Unused-Dependencies "true";|g' /etc/apt/apt.conf.d/50unattended-upgrades sed -i 's|//Unattended-Upgrade::Automatic-Reboot "false";|Unattended-Upgrade::Automatic-Reboot "true";|g' /etc/apt/apt.conf.d/50unattended-upgrades # between 1:00 and 1:55am REBOOT_TIME=01:$(printf "%02d" $((0 + RANDOM % 55))) sed -i "s|//Unattended-Upgrade::Automatic-Reboot-Time \"02:00\";|Unattended-Upgrade::Automatic-Reboot-Time \"$REBOOT_TIME\";|g" /etc/apt/apt.conf.d/50unattended-upgrades sed -i "s|//Unattended-Upgrade::Mail \"\";|Unattended-Upgrade::Mail \"$WEBMASTER\";|g" /etc/apt/apt.conf.d/50unattended-upgrades echo unattended-upgrades unattended-upgrades/enable_auto_updates boolean true | debconf-set-selections dpkg-reconfigure -f noninteractive unattended-upgrades # firewalld # without "--no-install-recommends" ipset and ipables are pulled in, and we don't need or want those DEBIAN_FRONTEND=noninteractive apt-get -y install firewalld --no-install-recommends firewall-cmd --set-default-zone=public # get public interface (e.g. eth0, enp0s10, etc.) then add it to the default (public) zone INTERFACE=$(ip route get 1.1.1.1 | sed -n 's/.*dev \([^\ ]*\).*/\1/p') firewall-cmd --permanent --zone=public --add-interface=$INTERFACE # ssh should already be enabled by default, just making sure firewall-cmd --permanent --zone=public --add-service=ssh # default firewalld public zone enables dhcpv6-client, we don't want that firewall-cmd --permanent --zone=public --remove-service=dhcpv6-client # blacklist - for local blacklisting firewall-cmd --permanent --new-ipset=blacklist --type=hash:net firewall-cmd --permanent --ipset=blacklist --set-short=Blacklist firewall-cmd --permanent --ipset=blacklist --set-description="Blacklist IP set for creating blacklists local to this server. Use firewall-blacklist-add.sh and firewall-blacklist-rem.sh to add/remove IPs to the blacklist." firewall-cmd --permanent --zone=drop --add-source=ipset:blacklist # fail2ban - fail2ban blocking firewall-cmd --permanent --new-ipset=fail2ban --type=hash:ip --option=timeout=90000 # 90000 timeout is 25 hours. Assumption is that 24 hours is the longest ban that fail2ban will implement, timeout is in place as a backup to remove out of date IPs firewall-cmd --permanent --ipset=fail2ban --set-short=Fail2Ban firewall-cmd --permanent --ipset=fail2ban --set-description="IP set for use by fail2ban. IPs in this set get added to the Drop zone." firewall-cmd --permanent --zone=drop --add-source=ipset:fail2ban systemctl restart firewalld # fail2ban DEBIAN_FRONTEND=noninteractive apt-get -y install fail2ban chmod 644 fail2ban/*.local chmod 644 fail2ban/*/*.conf cp -a fail2ban/* /etc/fail2ban/ echo "destemail = $WEBMASTER" >> /etc/fail2ban/jail.local echo "bantime = 24h" >> /etc/fail2ban/jail.d/defaults-debian.conf echo "maxretry = 3" >> /etc/fail2ban/jail.d/defaults-debian.conf echo "backend = systemd" >> /etc/fail2ban/jail.d/defaults-debian.conf systemctl enable fail2ban systemctl start fail2ban # adjust journald config to prevent /var/log/journal/... from using excessive disk space sed -i 's|.*SystemMaxUse=.*|SystemMaxUse=1G|g' /etc/systemd/journald.conf sed -i 's|.*RuntimeMaxUse=.*|RuntimeMaxUse=1G|g' /etc/systemd/journald.conf sed -i 's|.*SystemMaxFiles=.*|SystemMaxFiles=10|g' /etc/systemd/journald.conf sed -i 's|.*RuntimeMaxFiles=.*|RuntimeMaxFiles=10|g' /etc/systemd/journald.conf sed -i 's|.*MaxRetentionSec=.*|MaxRetentionSec=1week|g' /etc/systemd/journald.conf systemctl restart systemd-journald.service # adjust rsyslogd to log cron to it's own file, and to not include cron or mail in main syslog file # sed -i 's|^#cron\.\*|cron\.\*|' /etc/rsyslog.d/50-default.conf # sed -i 's|^\*\.\*;auth,authpriv\.none|\*\.\*;auth,authpriv\.none;mail\.none;cron\.none|' /etc/rsyslog.d/50-default.conf # systemctl restart rsyslog # install some handy extra packages DEBIAN_FRONTEND=noninteractive apt-get -y install curl exa gdu git isoquery net-tools pwgen sudo # exa is no longer maintained, eza is a fork that I expect/hope Debian will add to the next release # install chmod 750 sbin/* cp sbin/* /usr/local/sbin/ echo "" echo "Unattended upgrades & fail2ban are configured to send notifications to $WEBMASTER." echo "Update /etc/apt/apt.conf.d/50unattended-upgrades and /etc/fail2ban/jail.local to suit your needs." echo "NOTE: No mail server has been installed and emails won't send without one. See the README for more info."