download/panel/install.sh
耗子 550c34fc0a
Some checks failed
Generate Checksums / checksums (push) Has been cancelled
fix: lint
2025-03-20 23:14:48 +08:00

424 lines
19 KiB (Stored with Git LFS)
Bash
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/bin/bash
export PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:$PATH
: '
Copyright (C) 2022 - now HaoZi Technology Co., Ltd.
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 <https://www.gnu.org/licenses/>.
'
source <(curl -f -s --connect-timeout 10 --retry 3 https://dl.cdn.haozi.net/panel/public.sh)
if [ $? -ne 0 ]; then
echo "下载 public.sh 失败,请检查网络或稍后重试。"
echo "Download public.sh failed, please check the network or try again later."
exit 1
fi
LOGO="+----------------------------------------------------\n| 耗子面板安装脚本\n| Rat Panel install script\n+----------------------------------------------------\n| Copyright © 2022-"$(date +%Y)" 耗子科技 All rights reserved.\n+----------------------------------------------------"
current_path=$(pwd)
ssh_port=$(cat /etc/ssh/sshd_config | grep 'Port ' | awk '{print $2}')
in_china=$(curl --retry 2 -m 10 -L https://www.qualcomm.cn/cdn-cgi/trace 2>/dev/null | grep -qx 'loc=CN' && echo "true" || echo "false")
# 检查系统
Prepare_System() {
if [ $(whoami) != "root" ]; then
error "请使用root用户运行安装命令(Please run the installation command using the root user)"
fi
if [ ${OS} == "unknown" ]; then
error "系统不支持安装面板(The system does not support installing the panel)"
fi
if [ ${ARCH} != "x86_64" ] && [ ${ARCH} != "aarch64" ]; then
error "系统架构不支持安装面板(The system architecture does not support installing the panel)"
fi
if [ ${ARCH} == "x86_64" ]; then
if [ "$(cat /proc/cpuinfo | grep -c ssse3)" -lt "1" ]; then
error "CPU至少需支持x86-64-v2指令集(CPU must support at least the x86-64-v2 instruction set)"
fi
fi
kernel_version=$(uname -r | awk -F '.' '{print $1}')
if [ "${kernel_version}" -lt "4" ]; then
error "系统内核版本太低请升级到4.x以上版本(The system kernel version is too low, please upgrade to version 4.x or above)"
fi
is_64bit=$(getconf LONG_BIT)
if [ "${is_64bit}" != '64' ]; then
error "请更换64位系统安装面板(Please switch to a 64-bit system to install the panel)"
fi
if [ -f "${setup_path}/panel/web" ]; then
error "面板已安装,无需重复安装(Panel is already installed, no need to install again)"
fi
if ! id -u "www" >/dev/null 2>&1; then
groupadd www
useradd -s /sbin/nologin -g www www
fi
if [ ! -d ${setup_path} ]; then
mkdir ${setup_path}
fi
timedatectl set-timezone Asia/Shanghai
[ -s /etc/selinux/config ] && sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config
setenforce 0 >/dev/null 2>&1
ulimit -n 1048576
echo 2147483584 >/proc/sys/fs/file-max
soft_nofile_check=$(cat /etc/security/limits.conf | grep '^* soft nofile .*$')
hard_nofile_check=$(cat /etc/security/limits.conf | grep '^* hard nofile .*$')
soft_nproc_check=$(cat /etc/security/limits.conf | grep '^* soft nproc .*$')
hard_nproc_check=$(cat /etc/security/limits.conf | grep '^* hard nproc .*$')
fs_file_max_check=$(cat /etc/sysctl.conf | grep '^fs.file-max.*$')
if [ "${soft_nofile_check}" == "" ]; then
echo "* soft nofile 1048576" >>/etc/security/limits.conf
fi
if [ "${hard_nofile_check}" == "" ]; then
echo "* hard nofile 1048576" >>/etc/security/limits.conf
fi
if [ "${soft_nproc_check}" == "" ]; then
echo "* soft nproc 1048576" >>/etc/security/limits.conf
fi
if [ "${hard_nproc_check}" == "" ]; then
echo "* hard nproc 1048576" >>/etc/security/limits.conf
fi
if [ "${fs_file_max_check}" == "" ]; then
echo fs.file-max = 2147483584 >>/etc/sysctl.conf
fi
# 自动开启 BBR
# 清理旧配置,防止干扰
sed -i '/net.core.default_qdisc/d' /etc/sysctl.conf
sed -i '/net.ipv4.tcp_congestion_control/d' /etc/sysctl.conf
bbr_support_check=$(ls -l /lib/modules/*/kernel/net/ipv4 | grep -c tcp_bbr)
bbr_open_check=$(sysctl net.ipv4.tcp_congestion_control | grep -c bbr)
if [ "${bbr_support_check}" != "0" ] && [ "${bbr_open_check}" == "0" ]; then
qdisc=$(sysctl net.core.default_qdisc | awk '{print $3}')
# cake 是 fq_codel 的升级版,优先使用
if cat /boot/config-$(uname -r) | grep CONFIG_NET_SCH_CAKE | grep -q "="; then
qdisc="cake"
elif cat /boot/config-$(uname -r) | grep CONFIG_NET_SCH_FQ_CODEL | grep -q "="; then
qdisc="fq_codel"
elif cat /boot/config-$(uname -r) | grep CONFIG_NET_SCH_FQ_PIE | grep -q "="; then
qdisc="fq_pie"
elif cat /boot/config-$(uname -r) | grep CONFIG_NET_SCH_FQ | grep -q "="; then
qdisc="fq"
fi
echo "net.core.default_qdisc=${qdisc}" >>/etc/sysctl.conf
echo "net.ipv4.tcp_congestion_control=bbr" >>/etc/sysctl.conf
fi
# nf_conntrack 相关参数调优
# 这个配置非常重要,默认值很容易出现 nf_conntrack: table full, dropping packet 丢包问题
sed -i '/nf_conntrack_max/d' /etc/sysctl.conf
sed -i '/nf_conntrack_buckets/d' /etc/sysctl.conf
if [ ${MEM} -lt 2100 ]; then
echo "net.netfilter.nf_conntrack_max=262144" >>/etc/sysctl.conf
echo "net.netfilter.nf_conntrack_buckets=65536" >>/etc/sysctl.conf
elif [ ${MEM} -lt 4100 ]; then
echo "net.netfilter.nf_conntrack_max=655360" >>/etc/sysctl.conf
echo "net.netfilter.nf_conntrack_buckets=163840" >>/etc/sysctl.conf
elif [ ${MEM} -lt 8200 ]; then
echo "net.netfilter.nf_conntrack_max=1048576" >>/etc/sysctl.conf
echo "net.netfilter.nf_conntrack_buckets=262144" >>/etc/sysctl.conf
else
echo "net.netfilter.nf_conntrack_max=1503232" >>/etc/sysctl.conf
echo "net.netfilter.nf_conntrack_buckets=375808" >>/etc/sysctl.conf
fi
sysctl -p
if [ ${OS} == "rhel" ]; then
if ${in_china}; then
sed -e 's|^mirrorlist=|#mirrorlist=|g' \
-e 's|^#baseurl=http://dl.rockylinux.org/$contentdir|baseurl=https://mirrors.tencent.com/rocky|g' \
-e 's|^# baseurl=http://dl.rockylinux.org/$contentdir|baseurl=https://mirrors.tencent.com/rocky|g' \
-i.bak \
/etc/yum.repos.d/[Rr]ocky*.repo >/dev/null 2>&1
sed -e 's|^mirrorlist=|#mirrorlist=|g' \
-e 's|^#baseurl=https://repo.almalinux.org|baseurl=https://mirrors.tencent.com|g' \
-e 's|^# baseurl=https://repo.almalinux.org|baseurl=https://mirrors.tencent.com|g' \
-i.bak \
/etc/yum.repos.d/[Aa]lmalinux*.repo >/dev/null 2>&1
sed -e 's|^mirrorlist=|#mirrorlist=|g' \
-e 's|^#baseurl=http://mirror.centos.org/$contentdir|baseurl=https://mirrors.tencent.com/centos-stream|g' \
-e 's|^# baseurl=http://mirror.centos.org/$contentdir|baseurl=https://mirrors.tencent.com/centos-stream|g' \
-i.bak \
/etc/yum.repos.d/[Cc]ent*.repo >/dev/null 2>&1
fi
dnf makecache -y
dnf install dnf-plugins-core -y
dnf config-manager --set-enabled epel
if ${in_china}; then
sed -i 's|^#baseurl=https://download.example/pub|baseurl=https://mirrors.tencent.com|' /etc/yum.repos.d/epel* >/dev/null 2>&1
sed -i 's|^# baseurl=https://download.example/pub|baseurl=https://mirrors.tencent.com|' /etc/yum.repos.d/epel* >/dev/null 2>&1
sed -i 's|^metalink|#metalink|' /etc/yum.repos.d/epel* >/dev/null 2>&1
dnf makecache -y
fi
# EL 9
dnf config-manager --set-enabled crb
dnf install epel-release epel-next-release -y
# 部分系统可能没有这两个包,需要手动安装
# 对于 openEuler 这种大改的系统,下载会 404这没有影响
if [ "$?" != "0" ]; then
if ${in_china}; then
dnf install -y https://mirrors.tencent.com/epel/epel-release-latest-$(rpm -E %{rhel}).noarch.rpm
dnf install -y https://mirrors.tencent.com/epel/epel-next-release-latest-$(rpm -E %{rhel}).noarch.rpm
else
dnf install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-$(rpm -E %{rhel}).noarch.rpm
dnf install -y https://dl.fedoraproject.org/pub/epel/epel-next-release-latest-$(rpm -E %{rhel}).noarch.rpm
fi
fi
# Rocky Linux
/usr/bin/crb enable >/dev/null 2>&1
# openEuler
if [ -f /etc/openEuler-release ]; then
# 清理旧配置
grep -rl '^baseurl=https://repo.oepkgs.net' /etc/yum.repos.d/ | xargs -I {} rm -f {}
dnf config-manager --add-repo https://repo.oepkgs.net/openeuler/rpm/$(awk '{print $1"-"$3"-"$4}' /etc/openEuler-release | sed 's/[()]//g')/extras/$(uname -m)/
oe_version=$(awk '{print $3}' /etc/openEuler-release | cut -d '.' -f 1)
case ${oe_version} in
22)
dnf config-manager --add-repo https://repo.oepkgs.net/openeuler/rpm/$(awk '{print $1"-"$3"-"$4}' /etc/openEuler-release | sed 's/[()]//g')/extras/$(uname -m)/
dnf config-manager --add-repo https://repo.oepkgs.net/openeuler/rpm/$(awk '{print $1"-"$3"-"$4}' /etc/openEuler-release | sed 's/[()]//g')/compatible/f33/$(uname -m)/
;;
24)
# openEuler 24 目前没有 p7zip-plugins等他们自己修复
error "openEuler 24 暂不支持安装面板(Panel installation is not supported on openEuler 24)"
;;
*)
error "不支持的 openEuler 版本(Unsupported openEuler version)"
;;
esac
# 禁用gpcheck这仓库缺签名
grep -rl '^baseurl=https://repo.oepkgs.net' /etc/yum.repos.d/ | xargs -I {} sh -c 'echo "gpgcheck=0" >> "{}"'
fi
dnf makecache -y
dnf install -y bash curl wget zip unzip tar p7zip p7zip-plugins git jq git-core dos2unix make sudo
elif [ ${OS} == "debian" ] || [ ${OS} == "ubuntu" ]; then
if ${in_china}; then
# Debian
sed -i 's/deb.debian.org/mirrors.tencent.com/g' /etc/apt/sources.list >/dev/null 2>&1
sed -i 's/deb.debian.org/mirrors.tencent.com/g' /etc/apt/sources.list.d/debian.sources >/dev/null 2>&1
sed -i -e 's|security.debian.org/\? |security.debian.org/debian-security |g' \
-e 's|security.debian.org|mirrors.tencent.com|g' \
-e 's|deb.debian.org/debian-security|mirrors.tencent.com/debian-security|g' \
/etc/apt/sources.list >/dev/null 2>&1
# Ubuntu
sed -i 's@//.*archive.ubuntu.com@//mirrors.tencent.com@g' /etc/apt/sources.list >/dev/null 2>&1
sed -i 's@//.*archive.ubuntu.com@//mirrors.tencent.com@g' /etc/apt/sources.list.d/ubuntu.sources >/dev/null 2>&1
sed -i 's/security.ubuntu.com/mirrors.tencent.com/g' /etc/apt/sources.list >/dev/null 2>&1
sed -i 's/security.ubuntu.com/mirrors.tencent.com/g' /etc/apt/sources.list.d/ubuntu.sources >/dev/null 2>&1
fi
apt-get update -y
apt-get install -y bash curl wget zip unzip tar p7zip p7zip-full git jq git dos2unix make sudo
fi
if [ "$?" != "0" ]; then
error "安装面板依赖软件失败(Installation of panel dependency software failed)"
fi
}
# 自动 swap
Auto_Swap() {
# 判断是否有swap
if [ "${SWAP}" -gt 1 ]; then
return
fi
# 内存 >= 4G 不设置swap
if [ "${MEM}" -ge 3900 ]; then
return
fi
# 设置swap
swap_file="${setup_path}/swap"
btrfs_check=$(df -T ${setup_path} | awk '{print $2}' | tail -n 1)
if [ "${btrfs_check}" == "btrfs" ]; then
btrfs filesystem mkswap_file --size 2G --uuid clear ${swap_file}
else
dd if=/dev/zero of=$swap_file bs=8M count=256
fi
chmod 600 $swap_file
mkswap -f $swap_file
swapon $swap_file
echo "$swap_file swap swap defaults 0 0" >>/etc/fstab
mount -a
if [ "$?" != "0" ]; then
error "/etc/fstab 文件配置有误,请检查排除后重试,问题解决前勿重启系统(There is an error in the /etc/fstab file configuration, please check and try again after excluding, do not restart the system until the problem is resolved)"
fi
}
# 初始化面板
Init_Panel() {
systemctl stop panel >/dev/null 2>&1
systemctl disable panel >/dev/null 2>&1
rm -f /etc/systemd/system/panel.service
rm -rf ${setup_path}/panel
mkdir ${setup_path}/server
mkdir ${setup_path}/server/cron
mkdir ${setup_path}/server/cron/logs
chmod -R 755 ${setup_path}/server
mkdir ${setup_path}/panel
# 下载面板zip包并解压
version=$(curl -fsLm 10 --retry 3 "https://panel.haozi.net/api/version/latest")
if [ ${ARCH} == "x86_64" ]; then
panel_url=$(echo "$version" | jq -r '.data.downloads[] | select(.arch == "amd64") | .url')
panel_checksum=$(echo "$version" | jq -r '.data.downloads[] | select(.arch == "amd64") | .checksum')
elif [ ${ARCH} == "aarch64" ]; then
panel_url=$(echo "$version" | jq -r '.data.downloads[] | select(.arch == "arm64") | .url')
panel_checksum=$(echo "$version" | jq -r '.data.downloads[] | select(.arch == "arm64") | .checksum')
fi
if [ "$?" != "0" ] || [ "${panel_url}" == "" ] || [ "${panel_checksum}" == "" ]; then
error "获取面板下载链接失败(Failed to get the panel download url)"
fi
panel_name=$(echo "$panel_url" | awk -F '/' '{print $NF}')
wget --retry-connrefused --retry-on-host-error --retry-on-http-error=429,500,502,503,504 -t 10 -T 120 -O ${setup_path}/panel/${panel_name} "${panel_url}"
wget --retry-connrefused --retry-on-host-error --retry-on-http-error=429,500,502,503,504 -t 10 -T 120 -O ${setup_path}/panel/${panel_name}.sha256 "${panel_checksum}"
cd ${setup_path}/panel
if ! sha256sum --status -c ${panel_name}.sha256 --ignore-missing; then
error "面板压缩包校验失败(The panel zip package verification failed)"
fi
unzip -o ${panel_name}
if [ "$?" != "0" ]; then
error "解压面板失败(Failed to unzip the panel)"
fi
rm -f ${panel_name}
rm -f ${panel_name}.sha256
mkdir -p /usr/local/etc/panel
mv -f config.example.yml /usr/local/etc/panel/config.yml
sed -i "s|/www|${setup_path}|g" /usr/local/etc/panel/config.yml
chmod 600 /usr/local/etc/panel/config.yml
# 设置面板
chmod -R 700 ${setup_path}/panel
mv -f ${setup_path}/panel/cli /usr/local/sbin/panel-cli
# 防火墙放行
if [ ${OS} == "rhel" ]; then
dnf install firewalld -y
elif [ ${OS} == "debian" ] || [ ${OS} == "ubuntu" ]; then
ufw disable >/dev/null 2>&1
systemctl stop ufw >/dev/null 2>&1
systemctl disable ufw >/dev/null 2>&1
apt-get purge --auto-remove ufw -y
apt-get install firewalld -y
fi
systemctl enable --now firewalld
firewall-cmd --set-default-zone=public >/dev/null 2>&1
firewall-cmd --permanent --zone=public --add-port=22/tcp >/dev/null 2>&1
firewall-cmd --permanent --zone=public --add-port=80/tcp >/dev/null 2>&1
firewall-cmd --permanent --zone=public --add-port=443/tcp >/dev/null 2>&1
firewall-cmd --permanent --zone=public --add-port=443/udp >/dev/null 2>&1
firewall-cmd --permanent --zone=public --add-port=8888/tcp >/dev/null 2>&1
firewall-cmd --permanent --zone=public --add-port=${ssh_port}/tcp >/dev/null 2>&1
firewall-cmd --reload
if [ "$?" != "0" ]; then
error "防火墙端口放行失败(Failed to add firewall port)"
fi
# 写入服务文件
wget --retry-connrefused --retry-on-host-error --retry-on-http-error=429,500,502,503,504 -t 10 -T 120 -O /etc/systemd/system/panel.service ${download_url}/panel.service
sed -i "s|/www|${setup_path}|g" /etc/systemd/system/panel.service
chmod 644 /etc/systemd/system/panel.service
systemctl daemon-reload
panel-cli init
panel-cli sync
systemctl enable --now panel.service
if [ "$?" != "0" ]; then
error "面板启动失败(Failed to start the panel)"
fi
}
# 自动标记已存在的应用
Auto_Mark_Installed() {
# docker
docker_Flag=0
if [ -x "$(command -v docker)" ]; then
systemctl enable --now docker
docker_Flag=1
docker_version=$(docker -v | awk '{print $3}' | cut -d ',' -f 1)
panel-cli app write docker stable ${docker_version}
fi
# podman
if [ -x "$(command -v podman)" ] && [ "${docker_Flag}" == "0" ]; then
systemctl enable --now podman
systemctl enable --now podman.socket
systemctl enable --now podman-restart
podman_version=$(podman -v | awk '{print $3}')
panel-cli app write podman stable ${podman_version}
fi
# fail2ban
if [ -x "$(command -v fail2ban-server)" ]; then
systemctl enable --now fail2ban
fail2ban_version=$(fail2ban-server -V)
panel-cli app write fail2ban stable ${fail2ban_version}
fi
}
clear
echo -e $LOGO
# 设置安装目录
while true; do
read -p "请输入安装目录(默认/www(Enter the installation directory (default /www)): " setup_path
setup_path=${setup_path:-/www}
# 检查目录是否是绝对路径
if [ "${setup_path:0:1}" != "/" ]; then
echo "请输入绝对路径(Please enter an absolute path)"
else
break
fi
done
# 安装确认
read -p "面板将安装至 ${setup_path} 目录,请输入 y 并回车以开始安装 (Enter 'y' to start installation): " install
if [ "$install" != 'y' ]; then
echo "输入不正确,已退出安装。"
echo "Incorrect input, installation has been exited."
exit
fi
clear
echo -e $LOGO
echo "安装面板依赖软件(如报错请检查软件源是否正常)"
echo "Installing panel dependency software (if error, please check the software source)"
echo -e $HR
sleep 1s
Prepare_System
Auto_Swap
echo -e $LOGO
echo "安装面板运行环境(视网络情况可能需要较长时间)"
echo "Installing the panel running environment (may take a long time depending on the network)"
echo -e $HR
sleep 1s
Init_Panel
Auto_Mark_Installed
clear
echo -e $LOGO
echo '面板安装成功!'
echo -e $HR
panel-cli info
cd ${current_path}
rm -f install.sh