888 lines
25 KiB
Bash
888 lines
25 KiB
Bash
#!/usr/bin/env bash
|
|
#########################################################
|
|
# Function :Initial Server Setup for Debian Server #
|
|
# Platform :Debian 11, 12 or 13 #
|
|
# Version :2.1 #
|
|
# Date :26-08-2025 #
|
|
# Author :Xiufeng Guo #
|
|
# Contact :i@m.ac #
|
|
# Company :Show Corporation #
|
|
# Usage :curl -sSL ba.sh/debian | bash #
|
|
#########################################################
|
|
|
|
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
|
export PATH
|
|
|
|
set -euo pipefail
|
|
IFS=$'\n\t'
|
|
|
|
# Global variables with environment variable override support
|
|
SSH_KEYS_URL="${SSH_KEYS_URL:-https://git.m.ac/showfom/bash/raw/branch/main/authorized_keys}"
|
|
SSH_KEYS_RETRY_COUNT="${SSH_KEYS_RETRY_COUNT:-3}"
|
|
SSH_KEYS_RETRY_DELAY="${SSH_KEYS_RETRY_DELAY:-5}"
|
|
APT_MIRROR_URL="${APT_MIRROR_URL:-https://mirror-cdn.xtom.com}"
|
|
|
|
# Global codename variable (will be set by check_debian_version)
|
|
CODENAME=""
|
|
|
|
#current_dir=$(cd -P -- "$(dirname -- "$0")" && pwd -P)
|
|
|
|
# Check system requirements, if it's not Debian 11, 12 or 13, exit
|
|
function check_debian_version() {
|
|
if [[ -f /etc/os-release ]]; then
|
|
source /etc/os-release
|
|
if [[ "$ID" == "debian" && ( "$VERSION_CODENAME" == "bullseye" || "$VERSION_CODENAME" == "bookworm" || "$VERSION_CODENAME" == "trixie" ) ]]; then
|
|
echo "Running on supported Debian version: $PRETTY_NAME"
|
|
# Set global codename variable
|
|
CODENAME="$VERSION_CODENAME"
|
|
else
|
|
echo "Unsupported Debian version: $PRETTY_NAME"
|
|
exit 1
|
|
fi
|
|
else
|
|
echo "/etc/os-release file not found. Cannot determine OS version."
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
check_debian_version
|
|
|
|
# Check if user is root, if not, exit
|
|
function check_root() {
|
|
if [ "$(id -u)" != "0" ]; then
|
|
printf "\E[0;31;40m"
|
|
echo "### This script must be run as root. Exiting... ###"
|
|
printf "\E[0m"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
check_root
|
|
|
|
function change_apt_sources() {
|
|
printf "\E[0;35;40m"
|
|
echo '### Remove all apt sources files ###'
|
|
printf "\E[0m"
|
|
|
|
# If /etc/apt/sources.list exists, then backup it
|
|
if [ -f /etc/apt/sources.list ]; then
|
|
cp /etc/apt/sources.list /etc/apt/sources.list.$(date +"%Y%m%d_%H%M%S").bak
|
|
fi
|
|
|
|
# If /etc/apt/sources.list.d exists, then backup it
|
|
if [ -d /etc/apt/sources.list.d ] && [ "$(ls -A /etc/apt/sources.list.d 2>/dev/null)" ]; then
|
|
cp -r /etc/apt/sources.list.d /etc/apt/sources.list.d.$(date +"%Y%m%d_%H%M%S").bak
|
|
fi
|
|
|
|
printf "\E[0;35;40m"
|
|
echo '### Update system, install apt-transport-https and ca-certificates ###'
|
|
printf "\E[0m"
|
|
apt update
|
|
apt install apt-transport-https ca-certificates lsb-release -y
|
|
|
|
printf "\E[0;35;40m"
|
|
echo '### Replace the default sources.list with the new one ###'
|
|
printf "\E[0m"
|
|
|
|
case "$CODENAME" in
|
|
"bullseye")
|
|
cat > /etc/apt/sources.list << EOF
|
|
deb $APT_MIRROR_URL/debian $CODENAME main contrib non-free
|
|
|
|
deb $APT_MIRROR_URL/debian-security $CODENAME-security main contrib non-free
|
|
|
|
deb $APT_MIRROR_URL/debian $CODENAME-updates main contrib non-free
|
|
EOF
|
|
# Delete all sources.list.d files for bullseye
|
|
rm -rf /etc/apt/sources.list.d/*
|
|
;;
|
|
|
|
"bookworm"|"trixie")
|
|
# Clear existing sources.list
|
|
if [ -f /etc/apt/sources.list ]; then
|
|
cat /dev/null > /etc/apt/sources.list
|
|
fi
|
|
|
|
# Create new sources files
|
|
rm -rf /etc/apt/sources.list.d/*
|
|
cat > /etc/apt/sources.list.d/debian.sources << EOF
|
|
Types: deb
|
|
URIs: $APT_MIRROR_URL/debian
|
|
Suites: $CODENAME $CODENAME-updates $CODENAME-backports
|
|
Components: main contrib non-free non-free-firmware
|
|
Signed-By: /usr/share/keyrings/debian-archive-keyring.pgp
|
|
|
|
Types: deb
|
|
URIs: $APT_MIRROR_URL/debian-security
|
|
Suites: $CODENAME-security
|
|
Components: main contrib non-free non-free-firmware
|
|
Signed-By: /usr/share/keyrings/debian-archive-keyring.pgp
|
|
EOF
|
|
;;
|
|
|
|
*)
|
|
printf "\E[0;31;40m"
|
|
echo "### This script is only for Debian 11 (bullseye), 12 (bookworm) or 13 (trixie). Current: $CODENAME ###"
|
|
printf "\E[0m"
|
|
exit 1
|
|
;;
|
|
esac
|
|
|
|
printf "\E[0;35;40m"
|
|
echo '### Updating system... ###'
|
|
printf "\E[0m"
|
|
apt update
|
|
|
|
printf "\E[0;33;40m"
|
|
echo "### apt sources replaced ###"
|
|
printf "\E[0m"
|
|
}
|
|
|
|
function install_packages() {
|
|
printf "\E[0;35;40m"
|
|
echo '### Install the necessary packages ###'
|
|
printf "\E[0m"
|
|
apt install -y \
|
|
vim nano cron sudo \
|
|
net-tools dnsutils mtr-tiny traceroute \
|
|
wget curl host \
|
|
unzip rsync \
|
|
bash-completion git whois rsyslog \
|
|
fail2ban iptables haveged gnupg vnstat lrzsz jq \
|
|
unattended-upgrades apt-listchanges \
|
|
htop iftop p7zip-full zstd systemd-timesyncd \
|
|
bat python3-systemd byobu screen extrepo \
|
|
netcat-openbsd telnet rclone libpam-systemd
|
|
printf "\E[0;35;40m"
|
|
echo '### Updating system... ###'
|
|
printf "\E[0m"
|
|
apt update
|
|
apt upgrade -y
|
|
apt full-upgrade -y
|
|
apt autoclean
|
|
apt autoremove -y
|
|
printf "\E[0;33;40m"
|
|
echo "### System upgraded ###"
|
|
printf "\E[0m"
|
|
}
|
|
|
|
function change_timezone() {
|
|
printf "\E[0;35;40m"
|
|
echo '### Change timezone to UTC and environment variables to en_US.UTF-8 ###'
|
|
printf "\E[0m"
|
|
rm -rf /etc/localtime
|
|
ln -s /usr/share/zoneinfo/UTC /etc/localtime
|
|
|
|
cat > /etc/locale.conf << EOF
|
|
LANG=en_US.UTF-8
|
|
LC_TIME=en_US.UTF-8
|
|
LANGUAGE=en_US.UTF-8
|
|
EOF
|
|
|
|
cat > /etc/default/locale << EOF
|
|
LANG=en_US.UTF-8
|
|
LC_TIME=en_US.UTF-8
|
|
LANGUAGE=en_US.UTF-8
|
|
EOF
|
|
|
|
locale-gen en_US.UTF-8
|
|
update-locale LANG=en_US.UTF-8 LC_TIME=en_US.UTF-8 LANGUAGE=en_US.UTF-8
|
|
printf "\E[0;33;40m"
|
|
echo "### Timezone changed to UTC ###"
|
|
printf "\E[0m"
|
|
}
|
|
|
|
function add_ssh_keys(){
|
|
printf "\E[0;35;40m"
|
|
echo '### Add SSH keys... ###'
|
|
printf "\E[0m"
|
|
|
|
# Create .ssh directory
|
|
mkdir -p ~/.ssh
|
|
|
|
# Backup existing authorized_keys file (if exists)
|
|
if [ -f /root/.ssh/authorized_keys ]; then
|
|
cp /root/.ssh/authorized_keys "/root/.ssh/authorized_keys.$(date +%Y%m%d_%H%M%S).bak"
|
|
printf "\E[0;33;40m"
|
|
echo "### Backed up existing authorized_keys ###"
|
|
printf "\E[0m"
|
|
fi
|
|
|
|
# Download SSH keys with retry mechanism
|
|
local retry_count=0
|
|
local download_success=false
|
|
|
|
while [ $retry_count -lt $SSH_KEYS_RETRY_COUNT ]; do
|
|
printf "\E[0;35;40m"
|
|
echo "### Downloading SSH keys from $SSH_KEYS_URL (attempt $((retry_count + 1))/$SSH_KEYS_RETRY_COUNT)... ###"
|
|
printf "\E[0m"
|
|
|
|
if curl -sSL "$SSH_KEYS_URL" -o /root/.ssh/authorized_keys.tmp; then
|
|
# Verify downloaded file is not empty
|
|
if [ -s /root/.ssh/authorized_keys.tmp ]; then
|
|
# Verify file contains valid SSH key format
|
|
if grep -qE "^(ssh-rsa|ssh-ed25519|ecdsa-sha2-nistp256|ecdsa-sha2-nistp384|ecdsa-sha2-nistp521|ssh-dss)" /root/.ssh/authorized_keys.tmp; then
|
|
mv /root/.ssh/authorized_keys.tmp /root/.ssh/authorized_keys
|
|
download_success=true
|
|
break
|
|
else
|
|
printf "\E[0;31;40m"
|
|
echo "### Downloaded file doesn't contain valid SSH keys ###"
|
|
printf "\E[0m"
|
|
fi
|
|
else
|
|
printf "\E[0;31;40m"
|
|
echo "### Downloaded file is empty ###"
|
|
printf "\E[0m"
|
|
fi
|
|
else
|
|
printf "\E[0;31;40m"
|
|
echo "### Failed to download SSH keys ###"
|
|
printf "\E[0m"
|
|
fi
|
|
|
|
# Clean up temporary file
|
|
rm -f /root/.ssh/authorized_keys.tmp
|
|
|
|
retry_count=$((retry_count + 1))
|
|
if [ $retry_count -lt $SSH_KEYS_RETRY_COUNT ]; then
|
|
printf "\E[0;33;40m"
|
|
echo "### Retrying in $SSH_KEYS_RETRY_DELAY seconds... ###"
|
|
printf "\E[0m"
|
|
sleep $SSH_KEYS_RETRY_DELAY
|
|
fi
|
|
done
|
|
|
|
if [ "$download_success" = true ]; then
|
|
# Set correct permissions
|
|
chmod 700 ~/.ssh
|
|
chmod 600 ~/.ssh/authorized_keys
|
|
|
|
# Verify final authorized_keys file
|
|
if [ -f /root/.ssh/authorized_keys ] && [ -s /root/.ssh/authorized_keys ]; then
|
|
local key_count=$(grep -cE "^(ssh-rsa|ssh-ed25519|ecdsa-sha2-nistp256|ecdsa-sha2-nistp384|ecdsa-sha2-nistp521|ssh-dss)" /root/.ssh/authorized_keys || true)
|
|
printf "\E[0;32;40m"
|
|
echo "### SSH keys added successfully ($key_count keys found) ###"
|
|
printf "\E[0m"
|
|
return 0
|
|
else
|
|
printf "\E[0;31;40m"
|
|
echo "### ERROR: authorized_keys file is invalid ###"
|
|
printf "\E[0m"
|
|
return 1
|
|
fi
|
|
else
|
|
printf "\E[0;31;40m"
|
|
echo "### ERROR: Failed to download SSH keys after $SSH_KEYS_RETRY_COUNT attempts ###"
|
|
echo "### No SSH keys were added. You may need to manually add SSH keys later. ###"
|
|
printf "\E[0m"
|
|
|
|
# If backup files exist, remind user they can restore
|
|
if [ -f /root/.ssh/authorized_keys.*.bak ]; then
|
|
printf "\E[0;33;40m"
|
|
echo "### Note: Backup files exist in /root/.ssh/ ###"
|
|
printf "\E[0m"
|
|
fi
|
|
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
function disable_ssh_password() {
|
|
printf "\E[0;35;40m"
|
|
echo '### Disable SSH password ###'
|
|
printf "\E[0m"
|
|
|
|
cat > /etc/ssh/sshd_config.d/disable_password.conf << EOF
|
|
PermitRootLogin prohibit-password
|
|
PasswordAuthentication no
|
|
EOF
|
|
cat > /etc/ssh/sshd_config.d/hide_debian_banner.conf << EOF
|
|
DebianBanner no
|
|
EOF
|
|
cat > /etc/ssh/sshd_config.d/enable_rsa_keys.conf << EOF
|
|
HostKeyAlgorithms +ssh-rsa
|
|
PubkeyAcceptedKeyTypes +ssh-rsa
|
|
EOF
|
|
|
|
printf "\E[0;33;40m"
|
|
echo "### SSH password disabled ###"
|
|
printf "\E[0m"
|
|
}
|
|
|
|
function custom_fail2ban() {
|
|
printf "\E[0;35;40m"
|
|
echo '### Custom Fail2ban ###'
|
|
printf "\E[0m"
|
|
cat > /etc/fail2ban/jail.d/bantime.conf << EOF
|
|
[DEFAULT]
|
|
bantime = 1h
|
|
EOF
|
|
# If you still needs iptables
|
|
# cat > /etc/fail2ban/jail.d/sshd.conf << EOF
|
|
#[sshd]
|
|
#banaction = iptables-multiport
|
|
#banaction_allports = iptables-allports
|
|
#EOF
|
|
printf "\E[0;33;40m"
|
|
echo "### Custom Fail2ban configuration added ###"
|
|
printf "\E[0m"
|
|
}
|
|
|
|
function custom_bashrc() {
|
|
printf "\E[0;35;40m"
|
|
echo '### Custom .bashrc ###'
|
|
printf "\E[0m"
|
|
cp -r /root/.bashrc /root/.bashrc.$(date +"%Y_%m_%d_%I_%M_%p").bak
|
|
cat > ~/.bashrc << EOF
|
|
if [ -z "\$PS1" ]; then
|
|
return
|
|
fi
|
|
|
|
# Custom alias
|
|
alias ls='ls --color=auto'
|
|
alias ll='ls --color=auto -alFh'
|
|
alias l='ls -A'
|
|
alias mtr='mtr --aslookup --show-ips'
|
|
PS1='\[\033[01;31m\]\u\[\033[01;33m\]@\[\033[01;36m\]\h \[\033[01;33m\]\w \[\033[01;35m\]\\$ \[\033[00m\]'
|
|
|
|
# If this is an xterm set the title to user@host:dir
|
|
case "\$TERM" in
|
|
xterm*|rxvt*)
|
|
PS1="\[\e]0;\${debian_chroot:+(\$debian_chroot)}\u@\h: \w\a\]\$PS1"
|
|
;;
|
|
*)
|
|
;;
|
|
esac
|
|
EOF
|
|
printf "\E[0;33;40m"
|
|
echo "### Custom .bashrc added ###"
|
|
printf "\E[0m"
|
|
}
|
|
|
|
function custom_vimrc() {
|
|
printf "\E[0;35;40m"
|
|
echo '### Custom .vimrc ###'
|
|
printf "\E[0m"
|
|
cat > ~/.vimrc << EOF
|
|
set nopaste
|
|
syntax on
|
|
set nu
|
|
set tabstop=4
|
|
set shiftwidth=4
|
|
set softtabstop=4
|
|
set expandtab
|
|
EOF
|
|
printf "\E[0;33;40m"
|
|
echo "### Custom .vimrc added ###"
|
|
printf "\E[0m"
|
|
}
|
|
|
|
function custom_rc() {
|
|
printf "\E[0;35;40m"
|
|
echo '### Custom .inputrc ###'
|
|
printf "\E[0m"
|
|
cat > ~/.inputrc << EOF
|
|
set enable-bracketed-paste off
|
|
EOF
|
|
printf "\E[0;33;40m"
|
|
echo "### Custom .inputrc added ###"
|
|
printf "\E[0m"
|
|
# echo '### Custom .curlrc ###'
|
|
# printf "\E[0m"
|
|
# cat > ~/.curlrc << EOF
|
|
#ipv4
|
|
#EOF
|
|
# printf "\E[0;33;40m"
|
|
# echo "### Custom .curlrc added ###"
|
|
# printf "\E[0m"
|
|
}
|
|
|
|
function custom_sysctl() {
|
|
printf "\E[0;35;40m"
|
|
echo '### Custom sysctl.conf ###'
|
|
printf "\E[0m"
|
|
|
|
# Check if /etc/sysctl.d exists
|
|
if [ ! -d /etc/sysctl.d ]; then
|
|
printf "\E[0;33;40m"
|
|
echo "### WARNING: /etc/sysctl.d does not exist ###"
|
|
echo "### Skipping sysctl configuration... ###"
|
|
printf "\E[0m"
|
|
return 0
|
|
fi
|
|
|
|
# Modern system - use /etc/sysctl.d/
|
|
cat > /etc/sysctl.d/local.conf << EOF
|
|
net.ipv4.ip_forward = 1
|
|
net.ipv4.conf.all.proxy_arp = 0
|
|
net.ipv6.conf.all.forwarding = 1
|
|
net.ipv6.conf.all.autoconf = 0
|
|
net.ipv6.conf.default.autoconf = 0
|
|
net.ipv6.conf.all.accept_ra = 0
|
|
net.ipv6.conf.default.accept_ra = 0
|
|
net.ipv6.conf.default.accept_dad = 0
|
|
net.ipv6.conf.all.accept_dad = 0
|
|
net.core.rmem_default = 1212992
|
|
net.ipv4.neigh.default.gc_interval = 3600
|
|
net.ipv4.neigh.default.gc_stale_time = 3600
|
|
net.ipv4.neigh.default.gc_thresh1 = 2048
|
|
net.ipv4.neigh.default.gc_thresh2 = 4096
|
|
net.ipv4.neigh.default.gc_thresh3 = 8192
|
|
net.ipv6.neigh.default.base_reachable_time_ms = 3600
|
|
net.core.wmem_max = 134217728
|
|
net.core.rmem_max = 134217728
|
|
net.ipv4.tcp_rmem = 10240 87380 134217728
|
|
net.ipv4.tcp_wmem = 10240 87380 134217728
|
|
net.ipv4.tcp_slow_start_after_idle = 0
|
|
fs.inotify.max_user_watches = 819200
|
|
net.ipv4.tcp_max_syn_backlog = 32768
|
|
net.core.somaxconn = 2048
|
|
net.core.netdev_max_backlog = 32768
|
|
vm.vfs_cache_pressure = 100
|
|
vm.dirty_background_bytes = 52428800
|
|
net.core.default_qdisc = fq
|
|
net.ipv4.tcp_congestion_control = bbr
|
|
net.ipv6.route.max_size = 1048576
|
|
fs.file-max = 1000000
|
|
vm.swappiness = 10
|
|
vm.dirty_ratio = 60
|
|
vm.dirty_background_ratio = 2
|
|
net.ipv6.ip6frag_high_thresh = 4194304
|
|
net.ipv6.ip6frag_low_thresh = 3145728
|
|
net.ipv4.ipfrag_high_thresh = 4194304
|
|
net.ipv4.ipfrag_low_thresh = 3145728
|
|
net.ipv4.ping_group_range = 0 2147483647
|
|
EOF
|
|
|
|
# Apply sysctl settings
|
|
sysctl -p /etc/sysctl.d/local.conf
|
|
|
|
# If /etc/sysctl.conf exists, backup and replace with guide comment
|
|
if [ -f /etc/sysctl.conf ]; then
|
|
cp /etc/sysctl.conf /etc/sysctl.conf.$(date +"%Y%m%d_%H%M%S").bak
|
|
cat > /etc/sysctl.conf << EOF
|
|
#
|
|
# /etc/sysctl.conf - Configuration file for setting system variables
|
|
#
|
|
# NOTE: This file has been deprecated in favor of /etc/sysctl.d/
|
|
# Please add or modify system settings in /etc/sysctl.d/local.conf
|
|
#
|
|
# Custom configurations are now located at: /etc/sysctl.d/local.conf
|
|
#
|
|
EOF
|
|
fi
|
|
|
|
# Verify if the settings were applied successfully
|
|
local file_max=$(sysctl -n fs.file-max)
|
|
if [ "$file_max" = "1000000" ]; then
|
|
printf "\E[0;32;40m"
|
|
echo "### Custom sysctl settings added successfully (fs.file-max=$file_max) ###"
|
|
printf "\E[0m"
|
|
else
|
|
printf "\E[0;31;40m"
|
|
echo "### ERROR: Failed to apply sysctl settings (fs.file-max=$file_max, expected 1000000) ###"
|
|
printf "\E[0m"
|
|
return 1
|
|
fi
|
|
|
|
echo "### Adjust system file limits ###"
|
|
|
|
cat > /etc/security/limits.d/nofile.conf << EOF
|
|
root soft nofile 65536
|
|
root hard nofile 1048576
|
|
* soft nofile 65536
|
|
* hard nofile 1048576
|
|
EOF
|
|
|
|
mkdir -p /etc/systemd/system.conf.d
|
|
|
|
cat > /etc/systemd/system.conf.d/limits.conf << EOF
|
|
[Manager]
|
|
DefaultLimitNOFILE=65536
|
|
EOF
|
|
|
|
systemctl daemon-reexec
|
|
|
|
echo "### Adjust system file limits done ###"
|
|
}
|
|
|
|
# Helper function to add repository sources
|
|
function add_repo_source() {
|
|
local repo_name="$1"
|
|
local key_url="$2"
|
|
local key_file="$3"
|
|
local repo_url="$4"
|
|
local components="$5"
|
|
local suite="${6:-$CODENAME}"
|
|
|
|
# Download GPG key - try direct download first, then dearmor if needed
|
|
printf "\E[0;35;40m"
|
|
echo "### Downloading GPG key for $repo_name... ###"
|
|
printf "\E[0m"
|
|
|
|
# Download to temporary file first
|
|
local temp_key_file="/tmp/$(basename "$key_file").tmp.$$"
|
|
if curl -sSL "$key_url" -o "$temp_key_file"; then
|
|
# Check if file starts with ASCII armored header
|
|
if head -n 1 "$temp_key_file" | grep -q "^-----BEGIN PGP"; then
|
|
# ASCII armored format, need to dearmor
|
|
if gpg --dearmor < "$temp_key_file" > "$key_file" 2>/dev/null; then
|
|
rm "$temp_key_file"
|
|
else
|
|
printf "\E[0;31;40m"
|
|
echo "### ERROR: Failed to dearmor GPG key for $repo_name ###"
|
|
printf "\E[0m"
|
|
rm -f "$temp_key_file"
|
|
return 1
|
|
fi
|
|
else
|
|
# Binary format, use directly
|
|
mv "$temp_key_file" "$key_file"
|
|
fi
|
|
else
|
|
printf "\E[0;31;40m"
|
|
echo "### ERROR: Failed to download GPG key for $repo_name ###"
|
|
printf "\E[0m"
|
|
rm -f "$temp_key_file"
|
|
return 1
|
|
fi
|
|
|
|
# Create repository source based on Debian version
|
|
if [ "$CODENAME" = "bookworm" ] || [ "$CODENAME" = "trixie" ]; then
|
|
# Use new DEB822 format for Debian 12 and 13
|
|
cat > "/etc/apt/sources.list.d/${repo_name}.sources" << EOF
|
|
Types: deb
|
|
URIs: $repo_url
|
|
Suites: $suite
|
|
Components: $components
|
|
Signed-By: $key_file
|
|
EOF
|
|
else
|
|
# Use traditional format for Debian 11
|
|
echo "deb [arch=$(dpkg --print-architecture) signed-by=$key_file] $repo_url $suite $components" > "/etc/apt/sources.list.d/${repo_name}.list"
|
|
fi
|
|
}
|
|
|
|
function add_nginx_repo() {
|
|
printf "\E[0;35;40m"
|
|
echo '### Add n.wtf Nginx repo ###'
|
|
printf "\E[0m"
|
|
|
|
add_repo_source "n.wtf" \
|
|
"https://n.wtf/public.key" \
|
|
"/usr/share/keyrings/n.wtf.gpg" \
|
|
"https://mirror-cdn.xtom.com/sb/nginx" \
|
|
"main"
|
|
|
|
printf "\E[0;33;40m"
|
|
echo "### n.wtf Nginx repo added ###"
|
|
printf "\E[0m"
|
|
}
|
|
|
|
function add_caddy_repo() {
|
|
printf "\E[0;35;40m"
|
|
echo '### Add Caddy repo ###'
|
|
printf "\E[0m"
|
|
|
|
add_repo_source "caddy" \
|
|
"https://dl.cloudsmith.io/public/caddy/stable/gpg.key" \
|
|
"/usr/share/keyrings/caddy.gpg" \
|
|
"https://dl.cloudsmith.io/public/caddy/stable/deb/debian" \
|
|
"main" \
|
|
"any-version"
|
|
|
|
add_repo_source "xcaddy" \
|
|
"https://dl.cloudsmith.io/public/caddy/xcaddy/gpg.key" \
|
|
"/usr/share/keyrings/xcaddy.gpg" \
|
|
"https://dl.cloudsmith.io/public/caddy/xcaddy/deb/debian" \
|
|
"main" \
|
|
"any-version"
|
|
|
|
printf "\E[0;33;40m"
|
|
echo "### Caddy repo added ###"
|
|
printf "\E[0m"
|
|
}
|
|
|
|
function add_docker_repo() {
|
|
printf "\E[0;35;40m"
|
|
echo '### Add Docker CE repo ###'
|
|
printf "\E[0m"
|
|
|
|
add_repo_source "docker" \
|
|
"https://download.docker.com/linux/debian/gpg" \
|
|
"/usr/share/keyrings/docker-ce.gpg" \
|
|
"https://download.docker.com/linux/debian" \
|
|
"stable"
|
|
|
|
printf "\E[0;33;40m"
|
|
echo "### Docker CE repo added ###"
|
|
printf "\E[0m"
|
|
}
|
|
|
|
function add_php_repo() {
|
|
printf "\E[0;35;40m"
|
|
echo '### Add Sury PHP repo ###'
|
|
printf "\E[0m"
|
|
|
|
add_repo_source "php" \
|
|
"https://packages.sury.org/php/apt.gpg" \
|
|
"/usr/share/keyrings/deb.sury.org-php.gpg" \
|
|
"https://mirror-cdn.xtom.com/sury/php" \
|
|
"main"
|
|
|
|
printf "\E[0;33;40m"
|
|
echo "### Sury PHP repo added ###"
|
|
printf "\E[0m"
|
|
}
|
|
|
|
function add_mariadb_repo() {
|
|
printf "\E[0;35;40m"
|
|
echo '### Add MariaDB repo ###'
|
|
printf "\E[0m"
|
|
|
|
add_repo_source "mariadb" \
|
|
"https://supplychain.mariadb.com/MariaDB-Server-GPG-KEY" \
|
|
"/usr/share/keyrings/mariadb.gpg" \
|
|
"https://mirror-cdn.xtom.com/mariadb/repo/11.8/debian" \
|
|
"main"
|
|
|
|
printf "\E[0;33;40m"
|
|
echo "### MariaDB repo added ###"
|
|
printf "\E[0m"
|
|
}
|
|
|
|
function add_postgresql_repo() {
|
|
printf "\E[0;35;40m"
|
|
echo '### Add PostgreSQL repo ###'
|
|
printf "\E[0m"
|
|
|
|
add_repo_source "postgresql" \
|
|
"https://www.postgresql.org/media/keys/ACCC4CF8.asc" \
|
|
"/usr/share/keyrings/postgresql.gpg" \
|
|
"http://apt.postgresql.org/pub/repos/apt" \
|
|
"main" \
|
|
"${CODENAME}-pgdg"
|
|
|
|
printf "\E[0;33;40m"
|
|
echo "### PostgreSQL repo added ###"
|
|
printf "\E[0m"
|
|
}
|
|
|
|
function add_tor_repo() {
|
|
printf "\E[0;35;40m"
|
|
echo '### Add Tor repo ###'
|
|
printf "\E[0m"
|
|
|
|
add_repo_source "tor" \
|
|
"https://deb.torproject.org/torproject.org/A3C4F0F979CAA22CDBA8F512EE8CBC9E886DDD89.asc" \
|
|
"/usr/share/keyrings/tor.gpg" \
|
|
"https://deb.torproject.org/torproject.org" \
|
|
"main"
|
|
|
|
printf "\E[0;33;40m"
|
|
echo "### Tor repo added ###"
|
|
printf "\E[0m"
|
|
}
|
|
|
|
function add_redis_repo() {
|
|
printf "\E[0;35;40m"
|
|
echo '### Add Redis repo ###'
|
|
printf "\E[0m"
|
|
|
|
add_repo_source "redis" \
|
|
"https://packages.redis.io/gpg" \
|
|
"/usr/share/keyrings/redis.gpg" \
|
|
"https://packages.redis.io/deb" \
|
|
"main"
|
|
|
|
printf "\E[0;33;40m"
|
|
echo "### Redis repo added ###"
|
|
printf "\E[0m"
|
|
}
|
|
|
|
function add_unattended_upgrades() {
|
|
printf "\E[0;35;40m"
|
|
echo '### Enable Unattended Upgrades ###'
|
|
printf "\E[0m"
|
|
cp -r /etc/apt/apt.conf.d/50unattended-upgrades /etc/apt/apt.conf.d/50unattended-upgrades.$(date +"%Y_%m_%d_%I_%M_%p").bak
|
|
cat > /etc/apt/apt.conf.d/50unattended-upgrades << EOF
|
|
APT::Periodic::Update-Package-Lists "1";
|
|
APT::Periodic::Unattended-Upgrade "1";
|
|
APT::Periodic::Verbose "1";
|
|
APT::Periodic::AutocleanInterval "7";
|
|
|
|
Unattended-Upgrade::Mail "root";
|
|
|
|
Unattended-Upgrade::Origins-Pattern {
|
|
"origin=Debian,codename=\${distro_codename},label=Debian-Security";
|
|
"origin=Debian,codename=\${distro_codename}-security,label=Debian-Security";
|
|
};
|
|
|
|
Unattended-Upgrade::Package-Blacklist {
|
|
};
|
|
|
|
Unattended-Upgrade::Automatic-Reboot "false";
|
|
EOF
|
|
printf "\E[0;33;40m"
|
|
echo "### Unattended Upgrades enabled ###"
|
|
printf "\E[0m"
|
|
}
|
|
|
|
function add_acme_sh() {
|
|
printf "\E[0;35;40m"
|
|
echo '### Install acme.sh ###'
|
|
printf "\E[0m"
|
|
curl -sSL https://get.acme.sh | bash
|
|
/root/.acme.sh/acme.sh --upgrade --auto-upgrade
|
|
/root/.acme.sh/acme.sh --set-default-ca --server letsencrypt
|
|
printf "\E[0;33;40m"
|
|
echo "### acme.sh installation done ###"
|
|
printf "\E[0m"
|
|
}
|
|
|
|
function add_anubis() {
|
|
printf "\E[0;35;40m"
|
|
echo '### Install Anubis ###'
|
|
printf "\E[0m"
|
|
VERSION=$(curl -s https://api.github.com/repos/TecharoHQ/anubis/releases/latest | grep tag_name | cut -d '"' -f 4 | sed 's/^v//') && echo "Latest Anubis version is v${VERSION}"
|
|
wget -O /tmp/anubis.deb https://github.com/TecharoHQ/anubis/releases/download/v${VERSION}/anubis_${VERSION}_$(dpkg --print-architecture).deb
|
|
dpkg -i /tmp/anubis.deb
|
|
rm /tmp/anubis.deb
|
|
printf "\E[0;33;40m"
|
|
echo "### Anubis installation done ###"
|
|
printf "\E[0m"
|
|
}
|
|
|
|
function add_update_sh() {
|
|
printf "\E[0;35;40m"
|
|
echo '### Add update.sh ###'
|
|
printf "\E[0m"
|
|
cat > /root/update.sh << EOF
|
|
#!/usr/bin/env bash
|
|
apt update
|
|
apt upgrade -y
|
|
apt full-upgrade -y
|
|
apt autoclean
|
|
apt autoremove -y
|
|
EOF
|
|
chmod +x /root/update.sh
|
|
/root/update.sh
|
|
printf "\E[0;33;40m"
|
|
echo "### update.sh added ###"
|
|
printf "\E[0m"
|
|
}
|
|
|
|
# Check if dialog is installed, if not, install it
|
|
function check_dialog() {
|
|
if ! command -v dialog &> /dev/null; then
|
|
echo "dialog is not installed. Installing it now..."
|
|
apt update && apt install dialog -y
|
|
fi
|
|
}
|
|
|
|
check_dialog
|
|
|
|
# Dialog box begins here
|
|
cmd=(dialog --title "Debian Server Initial Setup" --separate-output --checklist "Select options:" 22 76 16)
|
|
options=(1 "Install Packages" on # any option can be set to default to "on"
|
|
2 "Change APT Sources" on
|
|
3 "Change Timezone" on
|
|
4 "Add SSH Keys" on
|
|
5 "Disable SSH Password" on
|
|
6 "Custom Fail2ban" on
|
|
7 "Custom .bashrc" on
|
|
8 "Custom .vimrc" on
|
|
9 "Custom run commands" on
|
|
10 "Custom sysctl and system file limitation" on
|
|
11 "Enable Unattended Upgrades" on
|
|
12 "Add n.wtf Nginx Repo" on
|
|
13 "Add Caddy Repo" off
|
|
14 "Add Docker CE Repo" off
|
|
15 "Add Sury PHP Repo" off
|
|
16 "Add MariaDB Repo" off
|
|
17 "Add PostgreSQL Repo" off
|
|
18 "Add Tor Project Repo" off
|
|
19 "Add Redis Repo" off
|
|
20 "Install Anubis" off
|
|
97 "Install acme.sh" off
|
|
99 "Add update.sh" on)
|
|
choices=$("${cmd[@]}" "${options[@]}" 2>&1 >/dev/tty)
|
|
clear
|
|
for choice in $choices
|
|
do
|
|
case $choice in
|
|
1)
|
|
install_packages
|
|
;;
|
|
2)
|
|
change_apt_sources
|
|
;;
|
|
3)
|
|
change_timezone
|
|
;;
|
|
4)
|
|
add_ssh_keys
|
|
;;
|
|
5)
|
|
disable_ssh_password
|
|
;;
|
|
6)
|
|
custom_fail2ban
|
|
;;
|
|
7)
|
|
custom_bashrc
|
|
;;
|
|
8)
|
|
custom_vimrc
|
|
;;
|
|
9)
|
|
custom_rc
|
|
;;
|
|
10)
|
|
custom_sysctl
|
|
;;
|
|
11)
|
|
add_unattended_upgrades
|
|
;;
|
|
12)
|
|
add_nginx_repo
|
|
;;
|
|
13)
|
|
add_caddy_repo
|
|
;;
|
|
14)
|
|
add_docker_repo
|
|
;;
|
|
15)
|
|
add_php_repo
|
|
;;
|
|
16)
|
|
add_mariadb_repo
|
|
;;
|
|
17)
|
|
add_postgresql_repo
|
|
;;
|
|
18)
|
|
add_tor_repo
|
|
;;
|
|
19)
|
|
add_redis_repo
|
|
;;
|
|
20)
|
|
add_anubis
|
|
;;
|
|
97)
|
|
add_acme_sh
|
|
;;
|
|
99)
|
|
add_update_sh
|
|
;;
|
|
esac
|
|
done
|
|
|
|
printf "\E[0;36;40m"
|
|
echo '### Server Initial Setup Completed. ###'
|
|
echo 'Have a nice day.'
|
|
echo 'You may need to reboot your system to take affect.'
|
|
printf "\E[0m" |