2022-11-17 09:47:11 -08:00
#!/bin/bash
#
# base-stack
# https://git.stack-source.com/msb/base-stack
# Copyright (c) 2022 Matthew Saunders Brown <matthewsaundersbrown@gmail.com>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
#
# this installer expects a clean Ubuntu 20.04 install
# require root
if [ " ${ EUID } " -ne 0 ] ; then
2024-03-14 15:22:09 -07:00
echo "This script must be run as root."
2022-11-17 09:47:11 -08:00
exit 1
fi
# do some basic pre-install checks - these are *not* exhaustive
2024-06-14 10:54:49 -07:00
# check for Ubuntu 22.04 (jammy) or Debian 12 (bookworm)
os_codename = ` lsb_release -cs`
if [ $os_codename != jammy ] && [ $os_codename != bookworm ] ; then
echo "This installer only runs on Ubuntu 22.04 (jammy) or Debian 12 (Bookworm), bailing out."
2024-03-14 15:22:09 -07:00
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."
2022-11-17 09:47:11 -08:00
exit 1
fi
# set webmaster email address, used below
2024-03-26 13:43:03 -07:00
WEBMASTER = webmaster@` hostname -f`
2022-11-17 09:47:11 -08:00
2024-03-05 12:14:57 -08:00
# if policy-rc.d is installed configure it to allow all packages to automatically start/restart/stop after install/upgrade/uninstall
if [ [ -f /usr/sbin/policy-rc.d ] ] ; then
echo -e '#!/bin/sh\nexit 0' > /usr/sbin/policy-rc.d
fi
2024-02-21 14:41:04 -08:00
# set needrestart to list only, which is also default for unattended upgrades
2022-11-17 09:47:11 -08:00
if [ [ -f /etc/needrestart/needrestart.conf ] ] ; then
2024-02-21 14:41:04 -08:00
sed -i "s|^#\$nrconf{restart} = 'i';|\$nrconf{restart} = 'l';|g" /etc/needrestart/needrestart.conf
# 'l' = list only, change to 'a' for automatic restart or 'i' for interactive
2022-11-17 12:46:53 -08:00
# disable kernelhints (no warnings about currently running kernel version)
echo '$nrconf{kernelhints} = 0;' > /etc/needrestart/conf.d/kernelhints.conf
2022-11-17 09:47:11 -08:00
fi
2023-03-03 10:40:49 -08:00
# set system variables
2024-06-14 10:54:49 -07:00
if [ [ ! -f /etc/sysctl.d/60-swappiness.conf ] ] ; then
echo "vm.swappiness = 1" >> /etc/sysctl.d/60-swappiness.conf
/sbin/sysctl --quiet --system
fi
2022-11-17 09:47:11 -08:00
# 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 grub-pc grub-pc-bin
DEBIAN_FRONTEND = noninteractive apt-get -y dist-upgrade
# remove unwanted packages
2024-06-14 10:54:49 -07:00
DEBIAN_FRONTEND = noninteractive apt-get -y purge snapd ufw iptables landscape-common popularity-contest
2022-11-17 10:44:10 -08:00
DEBIAN_FRONTEND = noninteractive apt-get -y autoremove
2022-11-17 10:53:45 -08:00
systemctl daemon-reload
2022-11-17 09:47:11 -08:00
# disable motd
2024-06-14 10:54:49 -07:00
if [ [ -f /etc/default/motd-news ] ] ; then
sed -i 's|ENABLED=1|ENABLED=0|g' /etc/default/motd-news
fi
if [ [ -f /etc/update-motd.d/10-help-text ] ] ; then
chmod 644 /etc/update-motd.d/10-help-text
fi
2022-11-17 13:17:25 -08:00
# disable apt news
2024-06-14 10:54:49 -07:00
if [ [ -x /usr/bin/pro ] ] ; then
/usr/bin/pro config set apt_news = false
fi
2022-11-17 09:47:11 -08:00
# configure unattended upgrades with automatic reboots
2024-06-14 10:54:49 -07:00
DEBIAN_FRONTEND = noninteractive apt-get -y install unattended-upgrades apt-listchanges
# /etc/apt/apt.conf.d/10periodic is part of update-notifier-common, on Ubuntu only
if [ [ -f /etc/apt/apt.conf.d/10periodic ] ] ; thenl
sed -i 's|^APT::Periodic::Update-Package-Lists.*|APT::Periodic::Update-Package-Lists "1";|g' /etc/apt/apt.conf.d/10periodic
sed -i 's|^APT::Periodic::Download-Upgradeable-Packages.*|APT::Periodic::Download-Upgradeable-Packages "1";|g' /etc/apt/apt.conf.d/10periodic
sed -i 's|^APT::Periodic::AutocleanInterval.*|APT::Periodic::AutocleanInterval "7";|g' /etc/apt/apt.conf.d/10periodic
fi
2022-11-17 09:47:11 -08:00
sed -i 's|^APT::Periodic::Update-Package-Lists.*|APT::Periodic::Update-Package-Lists "1";|g' /etc/apt/apt.conf.d/20auto-upgrades
sed -i 's|^APT::Periodic::Unattended-Upgrade.*|APT::Periodic::Unattended-Upgrade "1";|g' /etc/apt/apt.conf.d/20auto-upgrades
sed -i 's|// "${distro_id}:${distro_codename}-updates";| "${distro_id}:${distro_codename}-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
# 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
2023-03-18 16:38:57 -07:00
INTERFACE = $( ip route get 1.1.1.1 | sed -n 's/.*dev \([^\ ]*\).*/\1/p' )
2022-11-17 09:47:11 -08:00
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
2023-03-07 13:28:06 -08:00
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."
2022-11-17 09:47:11 -08:00
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
2022-11-17 10:44:10 -08:00
chmod 644 fail2ban/*.local
chmod 644 fail2ban/*/*.conf
2022-11-17 09:47:11 -08:00
cp -a fail2ban/* /etc/fail2ban/
2022-12-07 10:29:49 -08:00
echo " destemail = $WEBMASTER " >> /etc/fail2ban/jail.local
2022-12-16 11:22:06 -08:00
echo "bantime = 24h" >> /etc/fail2ban/jail.d/defaults-debian.conf
echo "maxretry = 3" >> /etc/fail2ban/jail.d/defaults-debian.conf
2024-06-14 16:03:53 -07:00
if [ $os_codename = jammy ] ; then
echo "backend = auto" >> /etc/fail2ban/jail.d/defaults-debian.conf
echo "logpath = /var/log/auth.log tail" >> /etc/fail2ban/jail.d/defaults-debian.conf
elif [ $os_codename = bookworm ] ; then
echo "backend = systemd" >> /etc/fail2ban/jail.d/defaults-debian.conf
fi
2022-11-17 09:47:11 -08:00
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
2024-06-14 10:54:49 -07:00
# adjust rsyslogd to log cron to it's own file, and to not include cron or mail in main syslog file (Ubuntu only, not on Debian 12+)
if [ [ -f /etc/rsyslog.d/50-default.conf ] ] ; then
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
fi
2024-02-21 14:41:37 -08:00
2022-11-17 09:47:11 -08:00
# install some handy extra packages
2024-06-14 10:54:49 -07:00
DEBIAN_FRONTEND = noninteractive apt-get -y install gdu exa pwgen net-tools curl sudo
# exa will be changed to eza in future releases
2022-11-17 09:47:11 -08:00
# install
chmod 750 sbin/*
cp sbin/* /usr/local/sbin/
echo ""
2022-12-07 10:29:49 -08:00
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."
2024-03-14 15:22:09 -07:00
echo "NOTE: No mail server has been installed and emails won't send without one. See the README for more info."