#!/bin/bash # _____ _ _ # | __|___ ___ ___ _| |___ _____| |_ ___ ___ ___ # | __| _| -_| -_| . | . | | . | . | | -_| # |__| |_| |___|___|___|___|_|_|_|___|___|_|_|___| # # Freedom in the Cloud # # Setup functions # # License # ======= # # Copyright (C) 2014-2018 Bob Mottram # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . if [ ! "$PROJECT_NAME" ]; then PROJECT_NAME='freedombone' fi if [ ! "$LOCAL_NAME" ]; then LOCAL_NAME=${PROJECT_NAME} fi DEFAULT_DOMAIN_NAME= DEFAULT_DOMAIN_CODE= MY_USERNAME= if [ ! "$SYSTEM_TYPE" ]; then SYSTEM_TYPE="full" fi # An optional configuration file which overrides some of these variables if [ ! "$CONFIGURATION_FILE" ]; then CONFIGURATION_FILE="$HOME/${PROJECT_NAME}.cfg" fi # Directory where source code is downloaded and compiled INSTALL_DIR=$HOME/build # device name for an attached usb drive USB_DRIVE=/dev/sda1 # Location where the USB drive is mounted to USB_MOUNT=/mnt/usb # Number of days to keep backups for BACKUP_MAX_DAYS=30 # file containing a list of remote locations to backup to # Format: [username@friendsdomain//home/username] [ssh_password] # With the only space character being between the server and the password FRIENDS_SERVERS_LIST="/home/$MY_USERNAME/backup.list" export DEBIAN_FRONTEND=noninteractive # used to limit CPU usage CPULIMIT='/usr/bin/cpulimit -l 20 -e' # command to create a git repository CREATE_GIT_PROJECT_COMMAND='create-project' # File which keeps track of what has already been installed COMPLETION_FILE=$HOME/${PROJECT_NAME}-completed.txt # log file where details of remote backups are stored REMOTE_BACKUPS_LOG=/var/log/remotebackups.log # message if something fails to install CHECK_MESSAGE="Check your internet connection, /etc/network/interfaces and /etc/resolvconf/resolv.conf.d/head, then delete $COMPLETION_FILE, run 'rm -fR /var/lib/apt/lists/* && apt-get update --fix-missing' and run this script again. If hash sum mismatches persist then try setting $DEBIAN_REPO to a different mirror and also change /etc/apt/sources.list." # Default diffie-hellman key length in bits DH_KEYLENGTH=2048 function support_256_colours { if ! grep 'xterm-256color' /etc/skel/.profile; then echo '' >> /etc/skel/.profile echo 'export TERM=xterm-256color' >> /etc/skel/.profile fi if ! grep 'xterm-256color' /home/$MY_USERNAME/.profile; then echo '' >> /home/$MY_USERNAME/.profile echo 'export TERM=xterm-256color' >> /home/$MY_USERNAME/.profile chown $MY_USERNAME:$MY_USERNAME /home/$MY_USERNAME/.profile fi } function detect_usb_drive { # sets to the highest available drive letter # which is likely to be the last drive connected read_config_param USB_DRIVE partition_number='1' #if [[ "$1" == "nopath" ]]; then # partition_number='' #fi if [ -b /dev/sda${partition_number} ]; then USB_DRIVE=/dev/sda${partition_number} fi if [ -b /dev/sdb${partition_number} ]; then USB_DRIVE=/dev/sdb${partition_number} fi if [ -b /dev/sdc${partition_number} ]; then USB_DRIVE=/dev/sdc${partition_number} fi if [ -b /dev/sdd${partition_number} ]; then USB_DRIVE=/dev/sdd${partition_number} fi if [ -b /dev/sde${partition_number} ]; then USB_DRIVE=/dev/sde${partition_number} fi if [ -b /dev/sdf${partition_number} ]; then USB_DRIVE=/dev/sdf${partition_number} fi if [ -b /dev/sdg${partition_number} ]; then USB_DRIVE=/dev/sdg${partition_number} fi if [ -b /dev/sdh${partition_number} ]; then USB_DRIVE=/dev/sdh${partition_number} fi write_config_param USB_DRIVE "$USB_DRIVE" } function separate_tmp_filesystem { tmp_filesystem_size_mb=$1 if [ ! -d /tmp ]; then mkdir -p /tmp fi if ! grep -q '/tmp' /etc/fstab; then mount -t tmpfs -o size="${tmp_filesystem_size_mb}m" tmpfs /tmp echo "tmpfs /tmp tmpfs nodev,nosuid,noexec,nodiratime,size=${tmp_filesystem_size_mb}M 0 0" >> /etc/fstab fi } function proc_filesystem_settings { if ! grep -q "proc proc defaults,nodev,nosuid " /etc/fstab; then sed -i 's|proc /proc proc defaults |proc /proc proc defaults,nodev,nosuid |g' /etc/fstab fi } function remove_bluetooth { bluetooth_changed= bnep_exists=$(lsmod | grep bnep) if [[ "$bnep_exists" == "bnep"* ]]; then rmmod -f bnep bluetooth_changed=1 fi bluetooth_exists=$(lsmod | grep bluetooth) if [[ "$bluetooth_exists" == "bluetooth"* ]]; then rmmod -f bluetooth bluetooth_changed=1 fi if [ -f /etc/default/bluetooth ]; then if grep -q "BLUETOOTH_ENABLED=" /etc/default/bluetooth; then sed -i 's|BLUETOOTH_ENABLED=.*|BLUETOOTH_ENABLED=0|g' /etc/default/bluetooth else echo "BLUETOOTH_ENABLED=0" >> /etc/default/bluetooth fi bluetooth_changed=1 fi if ! grep -q 'blacklist bnep' /etc/modprobe.d/bluetooth.conf; then echo 'blacklist bnep' >> /etc/modprobe.d/bluetooth.conf bluetooth_changed=1 fi if ! grep -q 'blacklist btusb' /etc/modprobe.d/bluetooth.conf; then echo 'blacklist btusb' >> /etc/modprobe.d/bluetooth.conf bluetooth_changed=1 fi if ! grep -q 'blacklist bluetooth' /etc/modprobe.d/bluetooth.conf; then echo 'blacklist bluetooth' >> /etc/modprobe.d/bluetooth.conf bluetooth_changed=1 fi if [ $bluetooth_changed ]; then update-initramfs -u -k "$(uname -r)" -v update-rc.d bluetooth remove fi } function running_as_root { if [[ $EUID != 0 ]] ; then echo "0" else echo "1" fi } function reset_usb_devices { for xhci in /sys/bus/pci/drivers/?hci-pci ; do if ! cd "$xhci" ; then return fi echo "Resetting devices from $xhci..." for i in ????:??:??.? ; do echo -n "$i" > unbind echo -n "$i" > bind done done udevadm control --reload-rules } function install_backports_kernel { # install backports kernel if possible architecture_type=$(uname -a) if [[ "$architecture_type" == *"amd64"* ]]; then package_installed=$(dpkg-query -W -f='${Package}\n' linux-image-amd64 2>/dev/null) if [ ! "$package_installed" ]; then apt-get -yq install linux-image-amd64 fi fi } function save_rsys_header { { echo ""; echo "#################"; echo "#### MODULES ####"; echo "#################"; echo ''; echo 'module(load="imuxsock")'; echo 'module(load="imklog")'; echo ''; echo '###########################'; echo '#### GLOBAL DIRECTIVES ####'; echo '###########################'; echo ''; echo "\$ActionFileDefaultTemplate RSYSLOG_TraditionalFileFormat"; echo ''; echo "\$FileOwner root"; echo "\$FileGroup adm"; echo "\$FileCreateMode 0640"; echo "\$DirCreateMode 0755"; echo "\$Umask 0022"; echo ''; echo "\$WorkDirectory /var/spool/rsyslog"; echo ''; echo "\$IncludeConfig /etc/rsyslog.d/*.conf"; echo ''; echo '###############'; echo '#### RULES ####'; echo '###############'; echo ''; } > /etc/rsyslog.conf } function turn_off_rsys_logging { save_rsys_header echo '*.* ~' >> /etc/rsyslog.conf rm -rf /var/log/wtmp* rm -rf /var/log/debug* rm -rf /var/log/cron.* rm -rf /var/log/auth.* rm -rf /var/log/mail.* rm -rf /var/log/daemon.* rm -rf /var/log/user.* rm -rf /var/log/messages* rm -rf /var/log/syslog* rm -rf /var/log/alternatives* rm -rf /var/log/faillog rm -rf /var/log/kern.log* } function initial_setup { if [[ $(is_completed "${FUNCNAME[0]}") == "1" ]]; then return fi apt-get -yq remove --purge apache2-bin* apt-get -yq dist-upgrade apt-get -yq install ca-certificates apt-get -yq install apt-utils apt-get -yq install cryptsetup libgfshare-bin duplicity sshpass wget avahi-daemon apt-get -yq install avahi-utils avahi-discover connect-proxy openssh-server apt-get -yq install sudo git dialog build-essential avahi-daemon avahi-utils apt-get -yq install avahi-discover iptables dnsutils net-tools apt-get -yq install network-manager iputils-ping libnss-mdns libnss-myhostname apt-get -yq install libnss-gw-name nano man ntp locales locales-all debconf apt-get -yq install wireless-tools wpasupplicant usbutils zsh cpulimit screen apt-get -yq install pinentry-curses eatmydata iotop bc hostapd # With some VMs, the hardware cycles counter is emulated and deterministic, # and thus predictible, so havege should not be used if [[ $ARCHITECTURE != 'qemu'* ]]; then apt-get -yq install haveged fi if [[ $ARCHITECTURE == 'qemu'* || $ARCHITECTURE == 'amd64' || $ARCHITECTURE == 'x86_64' || $ARCHITECTURE == 'i686' || $ARCHITECTURE == 'i386' ]]; then apt-get -yq install grub2 lvm2 fi if [ ! -d "$INSTALL_DIR" ]; then mkdir -p "$INSTALL_DIR" fi mark_completed "${FUNCNAME[0]}" } function turn_off_magic_sysrq { if grep -q 'kernel.sysrq = 0' /etc/sysctl.conf; then return fi if grep -q 'kernel.sysrq' /etc/sysctl.conf; then sed -i 's|#kernel.sysrq.*|kernel.sysrq = 0|g' /etc/sysctl.conf sed -i 's|kernel.sysrq.*|kernel.sysrq = 0|g' /etc/sysctl.conf else echo 'kernel.sysrq = 0' >> /etc/sysctl.conf fi } function setup_grub { if [[ $ARCHITECTURE == 'qemu'* || $ARCHITECTURE == 'amd64' || $ARCHITECTURE == 'x86_64' || $ARCHITECTURE == 'i686' || $ARCHITECTURE == 'i386' ]]; then if ! grep -q 'ifnames=0' /etc/default/grub; then sed -i 's|GRUB_CMDLINE_LINUX_DEFAULT=.*|GRUB_CMDLINE_LINUX_DEFAULT="quiet ifnames=0 slub_debug=FZP slab_nomerge page_poison=1 panic=0"|g' /etc/default/grub update-grub fi fi } function admin_user_sudo { # shellcheck disable=SC2154 if ! grep -q "$MY_USERNAME ALL=(ALL) ALL" "$rootdir/etc/sudoers"; then echo "$MY_USERNAME ALL=(ALL) ALL" >> "$rootdir/etc/sudoers" fi } function search_for_attached_usb_drive { # If a USB drive is attached then search for email, # gpg, ssh keys and emacs configuration if [[ $(is_completed "${FUNCNAME[0]}") == "1" ]]; then return fi detect_usb_drive if [ -b $USB_DRIVE ]; then if [ ! -d $USB_MOUNT ]; then echo $'Mounting USB drive' mkdir $USB_MOUNT mount $USB_DRIVE $USB_MOUNT fi if [ -d $USB_MOUNT/.gnupg ]; then echo $'Importing GPG keyring' cp -r $USB_MOUNT/.gnupg /home/$MY_USERNAME chown -R $MY_USERNAME:$MY_USERNAME /home/$MY_USERNAME/.gnupg if [ ! -f /home/$MY_USERNAME/.gnupg/secring.gpg ]; then echo $'GPG files did not copy' exit 73529 fi fi if [ -f $USB_MOUNT/private_key.gpg ]; then echo $'GPG private key found on USB drive' MY_GPG_PRIVATE_KEY="$USB_MOUNT/private_key.gpg" fi if [ -f $USB_MOUNT/public_key.gpg ]; then echo $'GPG public key found on USB drive' MY_GPG_PUBLIC_KEY="$USB_MOUNT/public_key.gpg" fi if [ -f $USB_MOUNT/letsencrypt ]; then echo $'Copying letsencrypt keys"' cp -r $USB_MOUNT/letsencrypt /etc fi if [ -d $USB_MOUNT/.ssh ]; then echo $'Importing ssh keys' cp -r $USB_MOUNT/.ssh /home/$MY_USERNAME chown -R $MY_USERNAME:$MY_USERNAME /home/$MY_USERNAME/.ssh # for security delete the ssh keys from the usb drive if [ ! -f /home/$MY_USERNAME/.ssh/id_rsa ]; then echo $'ssh files did not copy' exit 8 fi fi if [ -f $USB_MOUNT/.emacs ]; then echo $'Importing .emacs file' cp -f $USB_MOUNT/.emacs /home/$MY_USERNAME/.emacs chown $MY_USERNAME:$MY_USERNAME /home/$MY_USERNAME/.emacs fi if [ -d $USB_MOUNT/.emacs.d ]; then echo $'Importing .emacs.d directory' cp -r $USB_MOUNT/.emacs.d /home/$MY_USERNAME chown -R $MY_USERNAME:$MY_USERNAME /home/$MY_USERNAME/.emacs.d fi if [ -d $USB_MOUNT/ssl ]; then echo $'Importing SSL certificates' cp -r $USB_MOUNT/ssl/* /etc/ssl chmod 640 /etc/ssl/certs/* chmod 400 /etc/ssl/private/* # change ownership of some certificates if [ -d /etc/prosody ]; then chown prosody:prosody /etc/ssl/private/xmpp.* chown prosody:prosody /etc/ssl/certs/xmpp.* fi if [ -d /etc/dovecot ]; then chown root:dovecot /etc/ssl/certs/dovecot.* chown root:dovecot /etc/ssl/private/dovecot.* fi if [ -f /etc/ssl/private/exim.key ]; then cp /etc/ssl/private/exim.key /etc/exim4 cp /etc/ssl/certs/exim.crt /etc/exim4 cp /etc/ssl/certs/exim.dhparam /etc/exim4 chown root:Debian-exim /etc/exim4/exim.key /etc/exim4/exim.crt /etc/exim4/exim.dhparam chmod 640 /etc/exim4/exim.key /etc/exim4/exim.crt /etc/exim4/exim.dhparam fi fi if [ -d $USB_MOUNT/personal ]; then echo $'Importing personal directory' cp -r $USB_MOUNT/personal /home/$MY_USERNAME chown -R $MY_USERNAME:$MY_USERNAME /home/$MY_USERNAME/personal fi else if [ -d $USB_MOUNT ]; then umount $USB_MOUNT rm -rf $USB_MOUNT fi echo $'No USB drive attached' fi mark_completed "${FUNCNAME[0]}" } function mark_admin_user_account { set_completion_param "Admin user" "$MY_USERNAME" } function remove_instructions_from_motd { if grep -q "## " /etc/motd; then sed -i '/## /d' /etc/motd fi } function remove_default_user { # make sure you don't use the default user account if [[ $MY_USERNAME == "debian" ]]; then echo 'Do not use the default debian user account. Create a different user with: adduser [username]' exit 68 fi # remove the default debian user to prevent it from becoming an attack vector if [ -d /home/debian ]; then userdel -r debian echo 'Default debian user account removed' fi } function create_completion_file { if [ ! -f "$COMPLETION_FILE" ]; then touch "$COMPLETION_FILE" fi } function remove_management_engine_interface { # see https://www.kernel.org/doc/Documentation/misc-devices/mei/mei.txt # Disabling this interface doesn't cure the problems of ME, but it # might stop an adversary in control of AMT from using the command # interface to control the operating system. if [ -f /dev/mei0 ]; then rmmod mei_me rmmod mei0 fi blacklist_changed= if [ ! -f /etc/modprobe.d/blacklist.conf ]; then touch /etc/modprobe.d/blacklist.conf blacklist_changed=1 fi if ! grep -q "blacklist mei" /etc/modprobe.d/blacklist.conf; then echo "blacklist mei" >> /etc/modprobe.d/blacklist.conf blacklist_changed=1 fi if ! grep -q "blacklist mei_me" /etc/modprobe.d/blacklist.conf; then echo "blacklist mei_me" >> /etc/modprobe.d/blacklist.conf blacklist_changed=1 fi if [ $blacklist_changed ]; then depmod -ae -E update-initramfs -u fi } function set_login_umask { logindefs_umask=$(grep UMASK /etc/login.defs | grep -v '#') if [[ "$logindefs_umask" != *'077' ]]; then sed -i 's|UMASK\t.*|UMASK\t\t077|g' /etc/login.defs fi } function disable_deferred_execution { systemctl stop atd systemctl disable atd } function set_shadow_permissions { chown root:root /etc/shadow chmod 0000 /etc/shadow chown root:root /etc/gshadow chmod 0000 /etc/gshadow } function set_max_login_tries { max_tries=$1 if ! grep -q ' deny=' /etc/pam.d/common-auth; then sed -i "/pam_deny.so/a auth required\\t\\t\\tpam_tally.so onerr=fail no_lock_time per_user deny=$max_tries" /etc/pam.d/common-auth else if ! grep -q " deny=$max_tries" /etc/pam.d/common-auth; then sed -i "s| deny=.*| deny=$max_tries|g" /etc/pam.d/common-auth fi fi if ! grep -q 'pam_tally.so' /etc/pam.d/common-account; then sed -i '/pam_deny.so/a account required\t\t\tpam_tally.so' /etc/pam.d/common-account fi } function limit_user_logins { # overall max logins if ! grep -q '\* hard maxsyslogins' /etc/security/limits.conf; then echo '* hard maxsyslogins 10' >> /etc/security/limits.conf else if ! grep -q '\* hard maxsyslogins 10' /etc/security/limits.conf; then sed -i 's|hard maxsyslogins.*|hard maxsyslogins 10|g' /etc/security/limits.conf fi fi # Max logins for each user if ! grep -q '\* hard maxlogins' /etc/security/limits.conf; then echo '* hard maxlogins 2' >> /etc/security/limits.conf else if ! grep -q '\* hard maxlogins 2' /etc/security/limits.conf; then sed -i 's|hard maxlogins.*|hard maxlogins 2|g' /etc/security/limits.conf fi fi } function remove_serial_logins { if grep -q 'ttyS' /etc/securetty; then cp /etc/securetty /etc/securetty_old sed -i '/ttyS/d' /etc/securetty fi } function set_sticky_bits { world_writable=$(find / -xdev -type d -perm -002 \! -perm -1000) for w in $world_writable; do echo "Setting sticky bit on $w" chmod +t "$w" done } function disable_ctrl_alt_del { ctrl_alt_del=$(ls -l /etc/systemd/system/ctrl-alt-del.target) if [[ "$ctrl_alt_del" != *'/dev/null' ]]; then ln -sf /dev/null /etc/systemd/system/ctrl-alt-del.target fi } function lockdown_permissions { if [ -d /root/.npm ]; then chmod -R 700 /root/.npm fi # All commands owned by root if [ -d /root/.cache/yarn ]; then rm -rf /root/.cache/yarn fi if [ -d /usr/local/share/.cache/yarn ]; then rm -rf /usr/local/share/.cache/yarn fi if [ -f /usr/lib/ssl/certs/ssl-cert-snakeoil.pem ]; then chown root:root /usr/lib/ssl/certs/ssl-cert-snake* fi if [ -d /bin ]; then chown root:root /bin/* fi if [ -d /usr/bin ]; then chown root:root /usr/bin/* fi if [ -d /usr/local/bin ]; then chown root:root /usr/local/bin/* fi if [ -d /sbin ]; then chown root:root /sbin/* fi if [ -d /usr/sbin ]; then chown root:root /usr/sbin/* fi if [ -d /usr/local/sbin ]; then chown root:root /usr/local/sbin/* fi if [ -d /usr/share/${PROJECT_NAME} ]; then chown -R root:root /usr/share/${PROJECT_NAME} chmod -R +r /usr/share/${PROJECT_NAME} fi # All libraries owned by root if [ -d /lib ]; then chown -R root:root /lib/* fi if [ -d /lib64 ]; then chown -R root:root /lib64/* fi if [ -d /usr/lib ]; then chown -R root:root /usr/lib/* if [ -d /usr/lib/node_modules ]; then chmod -R 750 /usr/lib/node_modules/* fi if [ -d /usr/lib/prosody ]; then chown -R prosody:prosody /usr/lib/prosody fi fi if [ -d /usr/lib64 ]; then chown -R root:root /usr/lib64/* fi # sudo permissions chmod 4755 /usr/bin/sudo chmod 4755 /usr/lib/sudo/sudoers.so chown root:root /etc/sudoers # permissions on email commands if [ -f /usr/bin/procmail ]; then chmod 6755 /usr/bin/procmail fi if [ -f /usr/sbin/exim ]; then chmod u+s /usr/sbin/exim fi if [ -f /usr/sbin/exim4 ]; then chmod u+s /usr/sbin/exim4 fi set_sticky_bits # Create some directories to correspond with users in passwords file if [ ! -d /var/spool/lpd ]; then mkdir /var/spool/lpd fi if [ ! -d /var/spool/news ]; then mkdir /var/spool/news fi if [ ! -d /var/spool/uucp ]; then mkdir /var/spool/uucp fi if [ ! -d /var/list ]; then mkdir /var/list fi if [ ! -d /var/lib/gnats ]; then mkdir /var/lib/gnats fi if [ ! -d /var/lib/saned ]; then mkdir /var/lib/saned fi if [ -d /etc/prosody ]; then chown -R prosody /etc/prosody chmod -R 700 /etc/prosody/conf.d fi if [ -d /var/lib/prosody ]; then chown -R prosody /var/lib/prosody fi if [ -d /etc/letsencrypt ]; then chmod -R 600 /etc/letsencrypt chmod -R g=rX /etc/letsencrypt chown -R root:ssl-cert /etc/letsencrypt fi chown -f root:root /etc/motd /etc/issue* chmod -f 0444 /etc/motd /etc/issue* } function disable_core_dumps { if ! grep -q '\* hard core' /etc/security/limits.conf; then echo '* hard core 0' >> /etc/security/limits.conf else if ! grep -q '\* hard core 0' /etc/security/limits.conf; then sed -i 's|hard core.*|hard core 0|g' /etc/security/limits.conf fi fi } function dummy_nologin_command { if [ ! -f /sbin/nologin ]; then echo '#!/bin/bash' > /sbin/nologin chmod +x /sbin/nologin fi } function disable_null_passwords { if grep -q ' nullok_secure' /etc/pam.d/common-auth; then sed -i 's| nullok_secure||g' /etc/pam.d/common-auth fi } function create_usb_canary { if [[ $SYSTEM_TYPE == "mesh"* ]]; then return fi if [[ $(is_completed "${FUNCNAME[0]}") == "1" ]]; then return fi echo "ACTION==\"add\", KERNEL==\"sd*[!0-9]\", RUN+=\"/usr/local/bin/${PROJECT_NAME}-usb-canary\"" > /etc/udev/rules.d/00-usb-canary.rules udevadm control --reload-rules mark_completed "${FUNCNAME[0]}" } function setup_firewall { function_check create_completion_file create_completion_file function_check configure_firewall configure_firewall function_check block_firefox_telemetry block_firefox_telemetry function_check configure_firewall_ping configure_firewall_ping function_check firewall_handle_port_scans firewall_handle_port_scans function_check firewall_drop_telnet firewall_drop_telnet function_check firewall_drop_spoofed_packets firewall_drop_spoofed_packets function_check firewall_rate_limits firewall_rate_limits function_check configure_firewall_for_dns configure_firewall_for_dns function_check configure_firewall_for_avahi configure_firewall_for_avahi function_check global_rate_limit global_rate_limit function_check firewall_block_bad_ip_ranges firewall_block_bad_ip_ranges } function setup_powerline { if [ -f ~/${PROJECT_NAME}/src/${PROJECT_NAME}-powerline ]; then if [ ! -f ~/.powerline.bash ]; then cp ~/${PROJECT_NAME}/src/${PROJECT_NAME}-powerline ~/.powerline.bash else HASH1=$(sha256sum ~/${PROJECT_NAME}/src/${PROJECT_NAME}-powerline | awk -F ' ' '{print $1}') HASH2=$(sha256sum ~/.powerline.bash | awk -F ' ' '{print $1}') if [[ "$HASH1" != "$HASH2" ]]; then cp ~/${PROJECT_NAME}/src/${PROJECT_NAME}-powerline ~/.powerline.bash fi fi if [ ! -f /etc/skel/.powerline.bash ]; then cp ~/${PROJECT_NAME}/src/${PROJECT_NAME}-powerline /etc/skel/.powerline.bash else HASH1=$(sha256sum ~/${PROJECT_NAME}/src/${PROJECT_NAME}-powerline | awk -F ' ' '{print $1}') HASH2=$(sha256sum /etc/skel/.powerline.bash | awk -F ' ' '{print $1}') if [[ "$HASH1" != "$HASH2" ]]; then cp ~/${PROJECT_NAME}/src/${PROJECT_NAME}-powerline /etc/skel/.powerline.bash fi fi else if [ -f /home/${MY_USERNAME}/${PROJECT_NAME}/src/${PROJECT_NAME}-powerline ]; then if [ ! -f ~/.powerline.bash ]; then cp /home/${MY_USERNAME}/${PROJECT_NAME}/src/${PROJECT_NAME}-powerline ~/.powerline.bash else HASH1=$(sha256sum /home/${MY_USERNAME}/${PROJECT_NAME}/src/${PROJECT_NAME}-powerline | awk -F ' ' '{print $1}') HASH2=$(sha256sum ~/.powerline.bash | awk -F ' ' '{print $1}') if [[ "$HASH1" != "$HASH2" ]]; then cp /home/${MY_USERNAME}/${PROJECT_NAME}/src/${PROJECT_NAME}-powerline ~/.powerline.bash fi fi if [ ! -f /etc/skel/.powerline.bash ]; then cp /home/${MY_USERNAME}/${PROJECT_NAME}/src/${PROJECT_NAME}-powerline /etc/skel/.powerline.bash else HASH1=$(sha256sum /home/${MY_USERNAME}/${PROJECT_NAME}/src/${PROJECT_NAME}-powerline | awk -F ' ' '{print $1}') HASH2=$(sha256sum /etc/skel/.powerline.bash | awk -F ' ' '{print $1}') if [[ "$HASH1" != "$HASH2" ]]; then cp /home/${MY_USERNAME}/${PROJECT_NAME}/src/${PROJECT_NAME}-powerline /etc/skel/.powerline.bash fi fi fi fi if ! grep -q "powerline" ~/.bashrc; then if [ -f ~/.powerline.bash ]; then echo 'source ~/.powerline.bash' >> ~/.bashrc fi fi if ! grep -q "powerline" /etc/skel/.bashrc; then if [ -f /etc/skel/.powerline.bash ]; then echo 'source ~/.powerline.bash' >> /etc/skel/.bashrc fi fi } function congestion_control { # see /proc/sys/net/ipv4/tcp_congestion_control if [ ! -f /etc/sysctl.d/10-custom-kernel-bbr.conf ]; then echo 'net.core.default_qdisc=fq' > /etc/sysctl.d/10-custom-kernel-bbr.conf echo 'net.ipv4.tcp_congestion_control=bbr' >> /etc/sysctl.d/10-custom-kernel-bbr.conf sysctl --system fi } function install_shellcheck { # Used by the tests command apt-get -yq install shellcheck } function microsd_card_optimisations { # These values can improve performance on microSD cards apt-get -yq install hdparm printf '#!/bin/bash\n' > /usr/bin/enable_optimisations if [ -f /sys/devices/virtual/bdi/179:0/read_ahead_kb ]; then echo -n '4096' > /sys/devices/virtual/bdi/179:0/read_ahead_kb echo "echo -n '4096' > /sys/devices/virtual/bdi/179:0/read_ahead_kb" >> /usr/bin/enable_optimisations fi if [ -f /proc/sys/vm/dirty_expire_centisecs ]; then echo -n '100' > /proc/sys/vm/dirty_expire_centisecs echo "echo -n '100' > /proc/sys/vm/dirty_expire_centisecs" >> /usr/bin/enable_optimisations fi if [ -f /proc/sys/vm/dirty_writeback_centisecs ]; then echo -n '100' > /proc/sys/vm/dirty_writeback_centisecs echo "echo -n '100' > /proc/sys/vm/dirty_writeback_centisecs" >> /usr/bin/enable_optimisations fi chmod +x /usr/bin/enable_optimisations { echo '[Unit]'; echo "Description=${PROJECT_NAME} optimisations"; echo 'After=syslog.target'; echo 'After=network.target'; echo 'After=remote-fs.target'; echo ''; echo '[Service]'; echo 'Type=simple'; echo 'User=root'; echo 'Group=root'; echo 'WorkingDirectory=/root'; echo 'ExecStart=/usr/bin/enable_optimisations'; echo ''; echo '[Install]'; echo 'WantedBy=multi-user.target'; } > /etc/systemd/system/optimisations.service systemctl enable optimisations } function setup_utils { read_config_param "PROJECT_REPO" write_config_param "PROJECT_REPO" "$PROJECT_REPO" function_check remove_management_engine_interface remove_management_engine_interface function_check support_256_colours support_256_colours function_check congestion_control congestion_control function_check enable_predictable_device_names enable_predictable_device_names function_check turn_off_magic_sysrq turn_off_magic_sysrq function_check separate_tmp_filesystem separate_tmp_filesystem 150 function_check microsd_card_optimisations microsd_card_optimisations function_check proc_filesystem_settings proc_filesystem_settings function_check optimise_filesystem optimise_filesystem function_check disable_null_passwords disable_null_passwords function_check disable_ctrl_alt_del disable_ctrl_alt_del function_check dummy_nologin_command dummy_nologin_command function_check disable_core_dumps disable_core_dumps function_check remove_serial_logins remove_serial_logins function_check set_max_login_tries set_max_login_tries 10 function_check set_shadow_permissions set_shadow_permissions function_check remove_bluetooth remove_bluetooth function_check set_login_umask set_login_umask function_check disable_deferred_execution disable_deferred_execution function_check turn_off_rsys_logging turn_off_rsys_logging function_check install_backports_kernel install_backports_kernel function_check create_completion_file create_completion_file function_check read_configuration read_configuration function_check check_system_type check_system_type function_check set_default_onion_domains set_default_onion_domains function_check locale_setup locale_setup function_check parse_args parse_args function_check check_domains check_domains function_check install_static_network install_static_network function_check remove_default_user remove_default_user function_check setup_firewall setup_firewall function_check create_repo_sources create_repo_sources function_check configure_dns configure_dns function_check initial_setup initial_setup function_check setup_grub setup_grub function_check install_tor install_tor function_check check_tor_health check_tor_health function_check install_command_line_browser install_command_line_browser function_check enable_ssh_via_onion enable_ssh_via_onion function_check check_date check_date function_check install_dynamicdns install_dynamicdns function_check randomize_cron randomize_cron function_check create_freedns_updater create_freedns_updater function_check mark_admin_user_account mark_admin_user_account function_check enforce_good_passwords enforce_good_passwords function_check change_login_message change_login_message function_check enable_zram enable_zram function_check random_number_generator random_number_generator function_check set_your_domain_name set_your_domain_name function_check configure_internet_protocol configure_internet_protocol function_check create_git_project create_git_project function_check setup_wifi setup_wifi function_check configure_ssh configure_ssh function_check configure_ssh_onion configure_ssh_onion function_check allow_ssh_to_onion_address allow_ssh_to_onion_address function_check remove_instructions_from_motd remove_instructions_from_motd function_check check_hwrng check_hwrng function_check search_for_attached_usb_drive search_for_attached_usb_drive function_check regenerate_ssh_keys regenerate_ssh_keys function_check create_upgrade_script create_upgrade_script function_check letsencrypt_renewals letsencrypt_renewals function_check install_watchdog_script install_watchdog_script function_check install_avahi install_avahi function_check keep_avahi_running keep_avahi_running function_check create_avahi_onion_domains create_avahi_onion_domains #function_check install_atheros_wifi #install_atheros_wifi function_check route_outgoing_traffic_through_tor route_outgoing_traffic_through_tor function_check upgrade_golang upgrade_golang function_check install_tomb install_tomb function_check admin_user_sudo admin_user_sudo function_check limit_user_logins limit_user_logins function_check schedule_stig_tests schedule_stig_tests function_check create_usb_canary create_usb_canary function_check setup_powerline setup_powerline function_check install_shellcheck install_shellcheck } function setup_email { function_check create_completion_file create_completion_file function_check install_email install_email function_check remove_ip_addresses_from_email_logs remove_ip_addresses_from_email_logs function_check create_procmail create_procmail function_check handle_admin_emails handle_admin_emails function_check spam_filtering spam_filtering function_check configure_imap configure_imap #function_check configure_imap_client_certs #configure_imap_client_certs function_check configure_gpg configure_gpg function_check refresh_gpg_keys refresh_gpg_keys function_check configure_backup_key configure_backup_key #function_check install_monkeysphere #install_monkeysphere function_check email_client email_client function_check encrypt_incoming_email encrypt_incoming_email function_check encrypt_outgoing_email encrypt_outgoing_email function_check email_archiving email_archiving function_check email_from_address email_from_address function_check create_public_mailing_list #create_public_mailing_list #function check create_private_mailing_list #create_private_mailing_list function_check encrypt_all_email encrypt_all_email function_check import_email import_email } function setup_web { function_check create_completion_file create_completion_file function_check install_web_server install_web_server function_check install_web_server_access_control install_web_server_access_control function_check install_web_local_user_interface install_web_local_user_interface } function upgrade_apps { function_check create_completion_file create_completion_file APPS_COMPLETED=() FILES="/usr/share/${PROJECT_NAME}/apps/${PROJECT_NAME}-app-*" # for all the app scripts for filename in $FILES do app_name=$(echo "${filename}" | awk -F '-app-' '{print $2}') # shellcheck disable=SC2068 if ! item_in_array "${app_name}" ${APPS_COMPLETED[@]}; then function_check app_is_installed if [[ "$(app_is_installed "$app_name")" == "1" ]]; then echo '' echo '' echo $"Upgrading $app_name" app_load_variables "${app_name}" APPS_COMPLETED+=("${app_name}") function_check "upgrade_${app_name}" "upgrade_${app_name}" fi fi done } function setup_apps { is_interactive=$1 function_check create_completion_file create_completion_file function_check detect_installable_apps detect_installable_apps function_check choose_apps_for_variant choose_apps_for_variant "$SYSTEM_TYPE" echo $"System variant: $SYSTEM_TYPE" #echo $'The following apps have been selected' #echo '' #function_check list_chosen_apps #list_chosen_apps #echo '' function_check upgrade_apps upgrade_apps if [[ $is_interactive == "noninteractive" || $is_interactive == "headless" ]]; then function_check install_apps install_apps if [ ! "$APP_INSTALLED_SUCCESS" ]; then echo $'One or more apps failed to install' fi fi } function combine_all_scripts { combined_filename=$1 # initial variables cp "$PROJECT_INSTALL_DIR/${PROJECT_NAME}-vars" "$combined_filename" # utilities UTILS_FILES="/usr/share/${PROJECT_NAME}/utils/${PROJECT_NAME}-utils-*" for f in $UTILS_FILES do # this removes the first line, which is #!/bin/bash tail -n +2 "$f" >> "$combined_filename" done # base system BASE_SYSTEM_FILES="/usr/share/${PROJECT_NAME}/base/${PROJECT_NAME}-base-*" for f in $BASE_SYSTEM_FILES do tail -n +2 "$f" >> "$combined_filename" done # apps APP_FILES="/usr/share/${PROJECT_NAME}/apps/${PROJECT_NAME}-app-*" for f in $APP_FILES do tail -n +2 "$f" >> "$combined_filename" done } function check_ram_availability { minimum_ram_MB="$1" minimum_ram_bytes=$((minimum_ram_MB * 1024)) ram_available=$(grep MemTotal /proc/meminfo | awk '{print $2}') if [ "$ram_available" -lt "$minimum_ram_bytes" ]; then echo $"Need at least ${minimum_ram_MB}MB RAM to install this app" exit 783524 fi } # NOTE: deliberately no exit 0