├── .editorconfig ├── .gitattributes ├── README.md ├── after-install-ubuntu.sh └── mounts ├── mnt-merged.mount ├── mnt-network-share.backup-backup.mount ├── mnt-network-share.downloads-downloads.mount └── mnt-network-share.medialibrary-medialibrary.mount /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: https://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | [*] 7 | indent_style = space 8 | indent_size = 2 9 | end_of_line = lf 10 | charset = utf-8 11 | trim_trailing_whitespace = true 12 | insert_final_newline = true 13 | 14 | [*.{json,jsonc}] 15 | indent_style = space 16 | indent_size = 2 17 | end_of_line = lf 18 | 19 | [*.md] 20 | indent_style = space 21 | indent_size = 4 22 | end_of_line = lf 23 | 24 | [*.sh] 25 | indent_style = space 26 | indent_size = 4 27 | end_of_line = lf 28 | switch_case_indent = true # like --case-indent 29 | 30 | [*.{yaml,yml}] 31 | indent_style = space 32 | indent_size = 2 33 | end_of_line = lf 34 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Set the default behavior, in case people don't have core.autocrlf set. 2 | * text=auto 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # after-install 2 | 3 | Scripts to automate common tasks after a fresh OS install 4 | -------------------------------------------------------------------------------- /after-install-ubuntu.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | IFS=$'\n\t' 4 | 5 | # System Information 6 | ARCH=$(uname -m) 7 | readonly ARCH 8 | export ARCH 9 | DPKG_ARCH=$(dpkg --print-architecture) 10 | readonly DPKG_ARCH 11 | export DPKG_ARCH 12 | ID=$(grep --color=never -Po '^ID=\K.*' /etc/os-release) 13 | readonly ID 14 | export ID 15 | VERSION_CODENAME=$(grep --color=never -Po '^VERSION_CODENAME=\K.*' /etc/os-release) 16 | readonly VERSION_CODENAME 17 | export VERSION_CODENAME 18 | 19 | # User/Group Information 20 | readonly DETECTED_PUID=${SUDO_UID:-$UID} 21 | export DETECTED_PUID 22 | DETECTED_UNAME=$(id -un "${DETECTED_PUID}" 2>/dev/null || true) 23 | readonly DETECTED_UNAME 24 | export DETECTED_UNAME 25 | DETECTED_PGID=$(id -g "${DETECTED_PUID}" 2>/dev/null || true) 26 | readonly DETECTED_PGID 27 | export DETECTED_PGID 28 | DETECTED_UGROUP=$(id -gn "${DETECTED_PUID}" 2>/dev/null || true) 29 | readonly DETECTED_UGROUP 30 | export DETECTED_UGROUP 31 | DETECTED_HOMEDIR=$(eval echo "~${DETECTED_UNAME}" 2>/dev/null || true) 32 | readonly DETECTED_HOMEDIR 33 | export DETECTED_HOMEDIR 34 | 35 | # Cleanup Function 36 | cleanup() { 37 | local -ri EXIT_CODE=$? 38 | 39 | exit ${EXIT_CODE} 40 | trap - ERR EXIT SIGABRT SIGALRM SIGHUP SIGINT SIGQUIT SIGTERM 41 | } 42 | trap 'cleanup' ERR EXIT SIGABRT SIGALRM SIGHUP SIGINT SIGQUIT SIGTERM 43 | 44 | # Check if running as root 45 | check_root() { 46 | if [[ ${DETECTED_PUID} == "0" ]] || [[ ${DETECTED_HOMEDIR} == "/root" ]]; then 47 | echo "Running as root is not supported. Please run as a standard user with sudo." 48 | exit 1 49 | fi 50 | } 51 | 52 | # Check if running with sudo 53 | check_sudo() { 54 | if [[ ${EUID} -eq 0 ]]; then 55 | echo "Running with sudo is not supported. Commands requiring sudo will prompt automatically when required." 56 | exit 1 57 | fi 58 | } 59 | 60 | # apt-get updates, installs, and cleanups 61 | package_management() { 62 | sudo apt-get -y update 63 | sudo apt-get -y install \ 64 | apt-transport-https \ 65 | ca-certificates \ 66 | curl \ 67 | fonts-powerline \ 68 | fuse \ 69 | git \ 70 | grep \ 71 | htop \ 72 | ncdu \ 73 | rsync \ 74 | sed \ 75 | smartmontools \ 76 | tmux 77 | sudo apt-get -y dist-upgrade 78 | sudo apt-get -y autoremove 79 | sudo apt-get -y autoclean 80 | } 81 | 82 | # Kernel modules for vpn 83 | kernel_modules() { 84 | echo "iptable_mangle" | sudo tee /etc/modules-load.d/iptable_mangle.conf 85 | echo "tun" | sudo tee /etc/modules-load.d/tun.conf 86 | } 87 | 88 | # https://github.com/trapexit/mergerfs/releases 89 | mergerfs_install() { 90 | local AVAILABLE_MERGERFS 91 | AVAILABLE_MERGERFS=$(curl -fsL "https://api.github.com/repos/trapexit/mergerfs/releases/latest" | grep -Po '"tag_name": "[Vv]?\K.*?(?=")') 92 | local MERGERFS_FILENAME="mergerfs_${AVAILABLE_MERGERFS}.${ID}-${VERSION_CODENAME}_${DPKG_ARCH}.deb" 93 | local MERGERFS_TMP 94 | MERGERFS_TMP=$(mktemp) 95 | curl -fsL "https://github.com/trapexit/mergerfs/releases/download/${AVAILABLE_MERGERFS}/${MERGERFS_FILENAME}" -o "${MERGERFS_TMP}" 96 | sudo dpkg -i "${MERGERFS_TMP}" 97 | rm -f "${MERGERFS_TMP}" || true 98 | } 99 | 100 | # https://help.ubuntu.com/community/StricterDefaults 101 | stricter_defaults() { 102 | # https://help.ubuntu.com/community/StricterDefaults#Shared_Memory 103 | if ! grep -q '/run/shm' /etc/fstab; then 104 | echo "none /run/shm tmpfs defaults,ro 0 0" | sudo tee -a /etc/fstab 105 | fi 106 | sudo mount -o remount /run/shm || true 107 | 108 | # https://help.ubuntu.com/community/StricterDefaults#Disable_Password_Authentication 109 | # only disable password authentication if an ssh key is found in the authorized_keys file 110 | # be sure to setup your ssh key before running this script 111 | # also be sure to use an ed25519 key (preferred) or an rsa key 112 | if grep -q -E '^(sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29t|ssh-ed25519 AAAAC3NzaC1lZDI1NTE5|ssh-rsa AAAAB3NzaC1yc2E)[0-9A-Za-z+/]+[=]{0,3}(\s.*)?$' "${DETECTED_HOMEDIR}/.ssh/authorized_keys"; then 113 | sudo sed -i -E 's/^#?PasswordAuthentication .*$/PasswordAuthentication no/g' /etc/ssh/sshd_config 114 | fi 115 | 116 | # https://help.ubuntu.com/community/StricterDefaults#SSH_Root_Login 117 | # this sets a value of prohibit-password rather than no 118 | # prohibit-password is the default value, but it is often changed to yes by distribution packages 119 | # prohibit-password allows logging in as root using a keypair, but not using a password 120 | sudo sed -i -E 's/^#?PermitRootLogin .*$/PermitRootLogin prohibit-password/g' /etc/ssh/sshd_config 121 | 122 | # restart ssh after all the changes above 123 | sudo systemctl restart ssh 124 | } 125 | 126 | # auto-tmux for SSH logins 127 | # https://github.com/spencertipping/bashrc-tmux 128 | tmux_auto() { 129 | if [[ ! -d "${DETECTED_HOMEDIR}/bashrc-tmux" ]]; then 130 | git clone https://github.com/spencertipping/bashrc-tmux.git "${DETECTED_HOMEDIR}/bashrc-tmux" 131 | else 132 | git -C "${DETECTED_HOMEDIR}/bashrc-tmux" pull 133 | git -C "${DETECTED_HOMEDIR}/bashrc-tmux" fetch --all --prune 134 | git -C "${DETECTED_HOMEDIR}/bashrc-tmux" reset --hard origin/master 135 | git -C "${DETECTED_HOMEDIR}/bashrc-tmux" pull 136 | fi 137 | if ! grep -q 'bashrc-tmux' "${DETECTED_HOMEDIR}/.bashrc"; then 138 | local BASHRC_TMP 139 | BASHRC_TMP=$(mktemp) 140 | cat <<-'EOF' | sed -E 's/^ *//' | cat - "${DETECTED_HOMEDIR}/.bashrc" >"${BASHRC_TMP}" 141 | [ -z "$PS1" ] && return # this still comes first 142 | source ~/bashrc-tmux/bashrc-tmux 143 | 144 | # rest of bashrc below... 145 | 146 | EOF 147 | mv "${BASHRC_TMP}" "${DETECTED_HOMEDIR}/.bashrc" 148 | rm -f "${BASHRC_TMP}" 149 | fi 150 | chown -R "${DETECTED_PUID}":"${DETECTED_PGID}" "${DETECTED_HOMEDIR}/bashrc-tmux" 151 | chown -R "${DETECTED_PUID}":"${DETECTED_PGID}" "${DETECTED_HOMEDIR}/.bashrc" 152 | } 153 | 154 | # tmux config 155 | # https://github.com/gpakosz/.tmux 156 | tmux_config() { 157 | if [[ ! -d "${DETECTED_HOMEDIR}/.tmux" ]]; then 158 | git clone https://github.com/gpakosz/.tmux.git "${DETECTED_HOMEDIR}/.tmux" 159 | else 160 | git -C "${DETECTED_HOMEDIR}/.tmux" pull 161 | git -C "${DETECTED_HOMEDIR}/.tmux" fetch --all --prune 162 | git -C "${DETECTED_HOMEDIR}/.tmux" reset --hard origin/master 163 | git -C "${DETECTED_HOMEDIR}/.tmux" pull 164 | fi 165 | 166 | ln -s -f "${DETECTED_HOMEDIR}/.tmux/.tmux.conf" "${DETECTED_HOMEDIR}/.tmux.conf" 167 | cp -n "${DETECTED_HOMEDIR}/.tmux/.tmux.conf.local" "${DETECTED_HOMEDIR}/.tmux.conf.local" 168 | sudo sed -i -E 's/^#?set -g mouse on$/set -g mouse on/g' "${DETECTED_HOMEDIR}/.tmux.conf.local" 169 | chown -R "${DETECTED_PUID}":"${DETECTED_PGID}" "${DETECTED_HOMEDIR}/.tmux" 170 | chown -R "${DETECTED_PUID}":"${DETECTED_PGID}" "${DETECTED_HOMEDIR}/.tmux.conf" 171 | chown -R "${DETECTED_PUID}":"${DETECTED_PGID}" "${DETECTED_HOMEDIR}/.tmux.conf.local" 172 | } 173 | 174 | # Main Function 175 | main() { 176 | # Terminal Check 177 | if [[ -t 1 ]]; then 178 | check_root 179 | check_sudo 180 | fi 181 | 182 | package_management 183 | kernel_modules 184 | tmux_config 185 | tmux_auto 186 | stricter_defaults 187 | mergerfs_install 188 | } 189 | main 190 | -------------------------------------------------------------------------------- /mounts/mnt-merged.mount: -------------------------------------------------------------------------------- 1 | # /etc/systemd/system/mnt-merged.mount 2 | [Unit] 3 | Description=MergerFS Mount 4 | 5 | [Mount] 6 | What=/mnt/local/disk.*=RW:/mnt/network/share.*=RW:/mnt/remote/rclone.*=NC 7 | Where=/mnt/merged 8 | Type=fuse.mergerfs 9 | Options=noauto,x-systemd.automount,category.create=mspmfs,minfreespace=0,allow_other,dropcacheonclose=true,security_capability=false,xattr=nosys,statfs_ignore=ro,use_ino,async_read=false,cache.files=auto-full 10 | 11 | [Install] 12 | WantedBy=default.target 13 | -------------------------------------------------------------------------------- /mounts/mnt-network-share.backup-backup.mount: -------------------------------------------------------------------------------- 1 | # /etc/systemd/system/mnt-network-share.backup-backup.mount 2 | [Unit] 3 | Description=NFS Mount backup 4 | After=network-online.target 5 | 6 | [Mount] 7 | What=192.168.1.22:/mnt/local/disk.backup/backup 8 | Where=/mnt/network/share.backup/backup 9 | Type=nfs 10 | Options=noauto,x-systemd.automount,x-systemd.device-timeout=30,_netdev 11 | TimeoutSec=30 12 | 13 | [Install] 14 | WantedBy=default.target 15 | -------------------------------------------------------------------------------- /mounts/mnt-network-share.downloads-downloads.mount: -------------------------------------------------------------------------------- 1 | # /etc/systemd/system/mnt-network-share.downloads-downloads.mount 2 | [Unit] 3 | Description=NFS Mount downloads 4 | After=network-online.target 5 | 6 | [Mount] 7 | What=192.168.1.21:/raid5store1/downloads 8 | Where=/mnt/network/share.downloads/downloads 9 | Type=nfs 10 | Options=noauto,x-systemd.automount,x-systemd.device-timeout=30,_netdev 11 | TimeoutSec=30 12 | 13 | [Install] 14 | WantedBy=default.target 15 | -------------------------------------------------------------------------------- /mounts/mnt-network-share.medialibrary-medialibrary.mount: -------------------------------------------------------------------------------- 1 | # /etc/systemd/system/mnt-network-share.medialibrary-medialibrary.mount 2 | [Unit] 3 | Description=NFS Mount medialibrary 4 | After=network-online.target 5 | 6 | [Mount] 7 | What=192.168.1.21:/raid5store1/medialibrary 8 | Where=/mnt/network/share.medialibrary/medialibrary 9 | Type=nfs 10 | Options=noauto,x-systemd.automount,x-systemd.device-timeout=30,_netdev 11 | TimeoutSec=30 12 | 13 | [Install] 14 | WantedBy=default.target 15 | --------------------------------------------------------------------------------