bash/debian.sh
2024-10-31 02:24:31 +09:00

596 lines
20 KiB
Bash

#!/bin/bash
#########################################################
# Function :Initial Server Setup for Debian Server #
# Platform :Debian 11, 12 or 13 #
# Version :1.7 #
# Date :31-10-2024 #
# Author :Xiufeng Guo #
# Contact :i@m.ac #
# Company :Show Corporation #
# Usage :curl -sL 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'
#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"
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 -r /etc/apt/sources.list /etc/apt/sources.list.$(date +"%Y_%m_%d_%I_%M_%p").bak
fi
# if /etc/apt/sources.list.d exists, then backup it
if [ -d /etc/apt/sources.list.d ]; then
cp -r /etc/apt/sources.list.d /etc/apt/sources.list.d.$(date +"%Y_%m_%d_%I_%M_%p").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"
codename=$(lsb_release -sc)
# If codename = bullseye, use it's sources.list
if [ "$codename" == "bullseye" ]; then
cat > /etc/apt/sources.list << EOF
deb https://mirror-cdn.xtom.com/debian/ $codename main contrib non-free
#deb-src https://mirror-cdn.xtom.com/debian/ $codename main contrib non-free
deb https://mirror-cdn.xtom.com/debian-security/ $codename-security main contrib non-free
#deb-src https://mirror-cdn.xtom.com/debian-security/ $codename-security main contrib non-free
deb https://mirror-cdn.xtom.com/debian/ $codename-updates main contrib non-free
#deb-src https://mirror-cdn.xtom.com/debian/ $codename-updates main contrib non-free
deb https://mirror-cdn.xtom.com/debian/ $codename-backports main contrib non-free
EOF
# If codename = bookworm, use the new sources.list
elif [ "$codename" == "bookworm" ]; then
cat > /etc/apt/sources.list << EOF
deb https://mirror-cdn.xtom.com/debian/ $codename main contrib non-free non-free-firmware
#deb-src https://mirror-cdn.xtom.com/debian/ $codename main contrib non-free non-free-firmware
deb https://mirror-cdn.xtom.com/debian-security/ $codename-security main contrib non-free non-free-firmware
#deb-src https://mirror-cdn.xtom.com/debian-security/ $codename-security main contrib non-free non-free-firmware
deb https://mirror-cdn.xtom.com/debian/ $codename-updates main contrib non-free non-free-firmware
#deb-src https://mirror-cdn.xtom.com/debian/ $codename-updates main contrib non-free non-free-firmware
deb https://mirror-cdn.xtom.com/debian/ $codename-backports main contrib non-free non-free-firmware
EOF
# If codename = trixie, use the new sources.list
elif [ "$codename" == "trixie" ]; then
cat > /etc/apt/sources.list << EOF
deb https://mirror-cdn.xtom.com/debian/ $codename main contrib non-free non-free-firmware
#deb-src https://mirror-cdn.xtom.com/debian/ $codename main contrib non-free non-free-firmware
deb https://mirror-cdn.xtom.com/debian-security/ $codename-security main contrib non-free non-free-firmware
#deb-src https://mirror-cdn.xtom.com/debian-security/ $codename-security main contrib non-free non-free-firmware
deb https://mirror-cdn.xtom.com/debian/ $codename-updates main contrib non-free non-free-firmware
#deb-src https://mirror-cdn.xtom.com/debian/ $codename-updates main contrib non-free non-free-firmware
deb https://mirror-cdn.xtom.com/debian/ $codename-backports main contrib non-free non-free-firmware
EOF
# If codename = others, then exit
else
printf "\E[0;31;40m"
echo "### This script is only for Debian 11, 12 or 13. Exiting... ###"
printf "\E[0m"
exit 1
fi
# Delete all sources.list.d files
rm -rf /etc/apt/sources.list.d/*
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
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
localectl set-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"
mkdir -p /root/.ssh
cat > /root/.ssh/authorized_keys << EOF
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPn3FvKyi2pvUCU943a1FPUKV+rOElgPoOcxORGnEmdS p@m.ac-mobile
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINeLww3zlRtaZ5vSxMRKoUC8s2r3+wEirzGt0bFMCD1R p@m.ac-x1
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHAj4nbOal5A6nPPBFdjLG5a7JjW/BC6jif1yY1rbQS+ y@m.ac-2022
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINQvrfn3+7e/qLYFkHt7Jmo+e+7QdD8vD/ECh3PC/gR6 i@m.ac-ed25519
ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAgEAlfvpoVibfQ36GwMjJt2PIF77Dup8T9/3frJwVBC33zSwHJiihfPZlfKiUfiOUP1io1kBs3fMhq1r+x708ilxKn/3NxtYFmUWTKpqQq6+t5KBAY+0Cy+WHnJlslg8M0/npf7mDr5HJf09eTn+krSGCUTo+Gd38P9aNp1WamMa6pIRQ27mWMSECDkB93LpPVI4p9t00Z8ArNS6DOaTRcW9+/VJ0S+wYKnTmGz9bvsliHIK1fSBCMtPH0ApZtsQSHmsjh75ACv6qbU2R9d0ur3OA5u3wtFXuCIIzZANJIfQP8ehXnNjmakJTbNtGjye9hErKuaBwy42Ekgw5gRiHRuxvdPM5P5fSy01+jPQb3JqaEQOtrlTaVyjja0Y8+MSA8LqGvgul8FsQ5fRafJo0D+ep2SblrYUCc1mTwWx5+Z7pgaW04dXeVVXXGJVkGvfcE74rOBqfgHe/FAsbW+9rVueDiwuXnkivz/Yeqp2uAQxAqJerpZUPx9mE7ouSTipBT8e2R7zXm65cfhmrHmrrzEo8kJfcxBj9ozzpj2S4RsTm2DvYo05tbzaSo/gC1pv4QIwFhPfz8IvmPOjNI2xdYhMLCZGAf4Rl2g8PCE8lgXTjOFxIUb11H2N1OJgPoXiiAGFBPhdQZardE+fIfjWlh0wW9yCtTk7CojT0l1DPR8F9PE= i@m.ac-rsa-4096
EOF
chmod 700 /root/.ssh
chmod 600 /root/.ssh/authorized_keys
printf "\E[0;33;40m"
echo "### SSH keys added ###"
printf "\E[0m"
}
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
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 > /root/.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 > /root/.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_inputrc() {
printf "\E[0;35;40m"
echo '### Custom .inputrc ###'
printf "\E[0m"
cat > /root/.inputrc << EOF
set enable-bracketed-paste off
EOF
printf "\E[0;33;40m"
echo "### Custom .inputrc added ###"
printf "\E[0m"
}
function custom_sysctl() {
printf "\E[0;35;40m"
echo '### Custom sysctl.conf ###'
printf "\E[0m"
cp -r /etc/sysctl.conf /etc/sysctl.conf.$(date +"%Y_%m_%d_%I_%M_%p").bak
cat /dev/null > /etc/sysctl.conf
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
sysctl -p
printf "\E[0;33;40m"
echo "### Custom sysctl.conf added ###"
printf "\E[0m"
}
function add_nginx_repo() {
printf "\E[0;35;40m"
echo '### Add n.wtf Nginx repo ###'
printf "\E[0m"
curl -sS https://n.wtf/public.key | gpg --dearmor > /usr/share/keyrings/n.wtf.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/n.wtf.gpg] https://mirror-cdn.xtom.com/sb/nginx/ $(lsb_release -sc) main" > /etc/apt/sources.list.d/n.wtf.list
printf "\E[0;33;40m"
echo "### n.wtf Nginx repo added ###"
printf "\E[0m"
}
function add_docker_repo() {
printf "\E[0;35;40m"
echo '### Add Docker CE repo ###'
printf "\E[0m"
curl -sS https://download.docker.com/linux/debian/gpg | gpg --dearmor > /usr/share/keyrings/docker-ce.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-ce.gpg] https://download.docker.com/linux/debian $(lsb_release -sc) stable" > /etc/apt/sources.list.d/docker.list
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"
wget -O /usr/share/keyrings/deb.sury.org-php.gpg https://packages.sury.org/php/apt.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/deb.sury.org-php.gpg] https://mirror-cdn.xtom.com/sury/php/ $(lsb_release -sc) main" > /etc/apt/sources.list.d/php.list
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"
curl -sSL https://mariadb.org/mariadb_release_signing_key.asc | gpg --dearmor > /usr/share/keyrings/mariadb.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/mariadb.gpg] https://mirror-cdn.xtom.com/mariadb/repo/11.4/debian $(lsb_release -sc) main" > /etc/apt/sources.list.d/mariadb.list
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"
curl -sSL https://www.postgresql.org/media/keys/ACCC4CF8.asc | gpg --dearmor > /usr/share/keyrings/postgresql.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/postgresql.gpg] http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/postgresql.list
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"
wget -O /usr/share/keyrings/tor.gpg https://deb.torproject.org/torproject.org/A3C4F0F979CAA22CDBA8F512EE8CBC9E886DDD89.asc
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/tor.gpg] https://deb.torproject.org/torproject.org $(lsb_release -sc) main" > /etc/apt/sources.list.d/tor.list
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"
curl -sSL https://packages.redis.io/gpg | gpg --dearmor > /usr/share/keyrings/redis.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/redis.gpg] https://packages.redis.io/deb $(lsb_release -sc) main" > /etc/apt/sources.list.d/redis.list
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 -sS https://get.acme.sh | bash -s email=i@m.ac
/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_rclone() {
printf "\E[0;35;40m"
echo '### Install Rclone ###'
printf "\E[0m"
VERSION=$(curl -s https://api.github.com/repos/rclone/rclone/releases/latest | grep tag_name | cut -d '"' -f 4) && echo "Latest rclone version is $VERSION"
wget -O /tmp/rclone.deb https://github.com/rclone/rclone/releases/download/$VERSION/rclone-$VERSION-linux-$(dpkg --print-architecture).deb
dpkg -i /tmp/rclone.deb
rm /tmp/rclone.deb
printf "\E[0;33;40m"
echo "### Rclone 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
#!/bin/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 .inputrc" on
10 "Custom sysctl" on
11 "Enable Unattended Upgrades" on
12 "Add n.wtf Nginx Repo" on
13 "Add Docker CE Repo" off
14 "Add Sury PHP Repo" off
15 "Add MariaDB Repo" off
16 "Add PostgreSQL Repo" off
17 "Add Tor Project Repo" off
18 "Add Redis Repo" off
19 "Install acme.sh" off
20 "Install Rclone" off
21 "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_inputrc
;;
10)
custom_sysctl
;;
11)
add_unattended_upgrades
;;
12)
add_nginx_repo
;;
13)
add_docker_repo
;;
14)
add_php_repo
;;
15)
add_mariadb_repo
;;
16)
add_postgresql_repo
;;
17)
add_tor_repo
;;
18)
add_redis_repo
;;
19)
add_acme_sh
;;
20)
add_rclone
;;
21)
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"