SafeLine/release/latest/setup.sh
2024-06-18 19:06:24 +08:00

348 lines
11 KiB
Bash
Executable file
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
echo "
____ __ _ _
/ ___| __ _ / _| ___ | | (_) _ __ ___
\___ \ / _\` | | |_ / _ \ | | | | | '_ \ / _ \\
___) | | (_| | | _| | __/ | |___ | | | | | | | __/
|____/ \__,_| |_| \___| |_____| |_| |_| |_| \___|
"
export STREAM=${STREAM:-0}
qrcode() {
echo "█████████████████████████████████████████"
echo "█████████████████████████████████████████"
echo "████ ▄▄▄▄▄ █▀ █▀▀██▀▄▀▀▄▀▄▀▄██ ▄▄▄▄▄ ████"
echo "████ █ █ █▀ ▄ █▀▄▄▀▀ ▄█▄ ▀█ █ █ ████"
echo "████ █▄▄▄█ █▀█ █▄█▄▀▀▄▀▄ ▀▀▄▄█ █▄▄▄█ ████"
echo "████▄▄▄▄▄▄▄█▄█▄█ █▄▀ █ ▀▄▀ █▄█▄▄▄▄▄▄▄████"
echo "████▄ ▄▄ █▄▄ ▄█▄▄▄▄▀▄▀▀▄██ ▄▄▀▄█▄▀ ▀████"
echo "████▄ ▄▀▄ ▄▀▄ ▀ ▄█▀ ▀▄ █▀▀ ▀█▀▄██▄▀▄█████"
echo "█████ ▀▄█ ▄ ▄▄▀▄▀▀█▄▀▄▄▀▄▀▄ ▄ ▀▄▄▄█▀▀████"
echo "████ █▀▄▀ ▄▀▄▄▀█▀ ▄▄ █▄█▀▀▄▀▀█▄█▄█▀▄█████"
echo "████ █ ▀ ▄▀▀ ██▄█▄▄▄▄▄▀▄▀▀▀▄▄▀█▄▀█ ▀████"
echo "████ █ ▀▄ ▄██▀▀ ▄█▀ ▀███▄ ▀▄▀▄▄ ▄▀▄█████"
echo "████▀▄▄█ ▄▀▄▀ ▄▀▀▀▄▀▄▀ ▄▀▄ ▄▀ ▄▀█ ▀████"
echo "████ █ █ █▄▀ █▄█▀ ▄▄███▀▀▀▄█▀▄ ▀ ▀▄█████"
echo "████▄███▄█▄▄▀▄ █▄█▄▄▄▄▀▀▄█▀▀ ▄▄▄ ▀█ ████"
echo "████ ▄▄▄▄▄ █▄▀█ ▄█▀▄ █▀█▄ ▀ █▄█ ▀▄▀████"
echo "████ █ █ █ █▄▀▀▀▄▄▄▀▀▀▀▀▀ ▄▄ ▀█ ████"
echo "████ █▄▄▄█ █ ▀█▀ ▄▄▄▄ ▀█ ▀▀▄▀ ▀▀ ▀██████"
echo "████▄▄▄▄▄▄▄█▄▄██▄█▄▄█▄██▄██▄▄█▄▄█▄█▄█████"
echo "█████████████████████████████████████████"
echo "█████████████████████████████████████████"
echo
echo "微信扫描上方二维码加入雷池项目讨论组"
}
confirm() {
echo -e -n "\033[34m[SafeLine] $* \033[1;36m(Y/n)\033[0m"
read -n 1 -s opt
[[ "$opt" == $'\n' ]] || echo
case "$opt" in
'y' | 'Y' ) return 0;;
'n' | 'N' ) return 1;;
*) confirm "$1";;
esac
}
info() {
echo -e "\033[37m[SafeLine] $*\033[0m"
}
warning() {
echo -e "\033[33m[SafeLine] $*\033[0m"
}
abort() {
qrcode
echo -e "\033[31m[SafeLine] $*\033[0m"
exit 1
}
command_exists() {
command -v "$1" 2>&1
}
check_container_health() {
local container_name=$1
local max_retry=30
local retry=0
local health_status="unhealthy"
info "Waiting for $container_name to be healthy"
while [[ "$health_status" == "unhealthy" && $retry -lt $max_retry ]]; do
health_status=$(docker inspect --format='{{.State.Health.Status}}' $container_name 2>/dev/null || info 'unhealthy')
sleep 5
retry=$((retry+1))
done
if [[ "$health_status" == "unhealthy" ]]; then
abort "Container $container_name is unhealthy"
fi
info "Container $container_name is healthy"
}
space_left() {
dir="$1"
while [ ! -d "$dir" ]; do
dir=`dirname "$dir"`;
done
echo `df -h "$dir" --output='avail' | tail -n 1`
}
local_ips() {
if [ -z `command_exists ip` ]; then
ip_cmd="ip addr show"
else
ip_cmd="ifconfig -a"
fi
echo $($ip_cmd | grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*' | awk '{print $2}')
}
get_average_delay() {
local source=$1
local total_delay=0
local iterations=3
for ((i = 0; i < iterations; i++)); do
# check timeout
if ! curl -o /dev/null -m 1 -s -w "%{http_code}\n" "$source" > /dev/null; then
delay=999
else
delay=$(curl -o /dev/null -s -w "%{time_total}\n" "$source")
fi
total_delay=$(awk "BEGIN {print $total_delay + $delay}")
done
average_delay=$(awk "BEGIN {print $total_delay / $iterations}")
echo "$average_delay"
}
install_docker() {
curl -fsSL "https://waf-ce.chaitin.cn/release/latest/get-docker.sh" -o get-docker.sh
sources=(
"https://mirrors.aliyun.com/docker-ce"
"https://mirrors.tencent.com/docker-ce"
"https://download.docker.com"
)
min_delay=${#sources[@]}
selected_source=""
for source in "${sources[@]}"; do
average_delay=$(get_average_delay "$source")
echo "source: $source, delay: $average_delay"
if (( $(awk 'BEGIN { print '"$average_delay"' < '"$min_delay"' }') )); then
min_delay=$average_delay
selected_source=$source
fi
done
echo "selected source: $selected_source"
export DOWNLOAD_URL="$selected_source"
bash get-docker.sh
start_docker
docker version > /dev/null 2>&1
if [ $? -ne "0" ]; then
echo "Docker 安装失败, 请检查网络连接或手动安装 Docker"
echo "参考文档: https://docs.docker.com/engine/install/"
abort "Docker 安装失败"
fi
info "Docker 安装成功"
}
start_docker() {
systemctl enable docker
systemctl daemon-reload
systemctl start docker
}
check_depend() {
# CPU ssse3 指令集检查
support_ssse3=1
lscpu | grep ssse3 > /dev/null 2>&1
if [ $? -ne "0" ]; then
echo "not found info in lscpu"
support_ssse3=0
fi
cat /proc/cpuinfo | grep ssse3 > /dev/null 2>&1
if [ $support_ssse3 -eq "0" -a $? -ne "0" ]; then
abort "雷池需要运行在支持 ssse3 指令集的 CPU 上,虚拟机请自行配置开启 CPU ssse3 指令集支持"
fi
if [ -z "$BASH" ]; then
abort "请用 bash 执行本脚本,请参考最新的官方技术文档 https://waf-ce.chaitin.cn/"
fi
if [ ! -t 0 ]; then
abort "STDIN 不是标准的输入设备,请参考最新的官方技术文档 https://waf-ce.chaitin.cn/"
fi
if [ "$EUID" -ne "0" ]; then
abort "请以 root 权限运行"
fi
if [ -z `command_exists docker` ]; then
warning "缺少 Docker 环境"
if confirm "是否需要自动安装 Docker"; then
install_docker
else
abort "中止安装"
fi
fi
info "发现 Docker 环境: '`command -v docker`'"
docker version > /dev/null 2>&1
if [ $? -ne "0" ]; then
abort "Docker 服务工作异常"
fi
compose_command="docker compose"
if $compose_command version; then
info "发现 Docker Compose Plugin"
else
warning "未发现 Docker Compose Plugin"
if confirm "是否需要自动安装 Docker Compose Plugin"; then
install_docker
if [ $? -ne "0" ]; then
abort "Docker Compose Plugin 安装失败"
fi
info "Docker Compose Plugin 安装完成"
else
abort "中止安装"
fi
fi
# check docker compose support -d
if ! $compose_command up -d --help > /dev/null 2>&1; then
warning "Docker Compose Plugin 不支持 '-d' 参数"
if confirm "是否需要自动升级 Docker Compose Plugin"; then
install_docker
if [ $? -ne "0" ]; then
abort "Docker Compose Plugin 升级失败"
fi
info "Docker Compose Plugin 升级完成"
else
abort "中止安装"
fi
fi
start_docker
info "安装环境确认正常"
}
trap 'onexit' INT
onexit() {
echo
abort "用户手动结束安装"
}
check_depend
docker network rm safeline-ce 2>/dev/null
ips=`local_ips`
subnets="172.22.222 169.254.222 192.168.222"
for subnet in $subnets; do
if [[ $ips != *$subnet* ]]; then
SUBNET_PREFIX=$subnet
break
fi
done
safeline_path='/data/safeline'
while true; do
echo -e -n "\033[34m[SafeLine] 雷池安装目录 (留空则为 '$safeline_path'): \033[0m"
read input_path
[[ -z "$input_path" ]] && input_path=$safeline_path
if [[ ! $input_path == /* ]]; then
warning "'$input_path' 不是合法的绝对路径"
continue
fi
if [ -f "$input_path" ] || [ -d "$input_path" ]; then
warning "'$input_path' 路径已经存在,请换一个"
continue
fi
safeline_path=$input_path
if confirm "目录 '$safeline_path' 当前剩余存储空间为 `space_left \"$safeline_path\"` ,雷池至少需要 5G是否确定"; then
break
fi
done
mkdir -p "$safeline_path"
if [ $? -ne "0" ]; then
abort "创建安装目录 '$safeline_path' 失败"
fi
info "创建安装目录 '$safeline_path' 成功"
cd "$safeline_path"
curl "https://waf-ce.chaitin.cn/release/latest/compose.yaml" -sSLk -o compose.yaml
curl "https://waf-ce.chaitin.cn/release/latest/reset_tengine.sh" -sSLk -o reset_tengine.sh
if [ $? -ne "0" ]; then
abort "下载 compose.yaml 脚本失败"
fi
info "下载 compose.yaml 脚本成功"
touch ".env"
if [ $? -ne "0" ]; then
abort "创建 .env 脚本失败"
fi
info "创建 .env 脚本成功"
echo "SAFELINE_DIR=$safeline_path" >> .env
if [ $STREAM -eq 1 ]; then
echo "IMAGE_TAG=latest-stream" >>".env"
else
echo "IMAGE_TAG=latest" >>".env"
fi
echo "MGT_PORT=9443" >> .env
echo "POSTGRES_PASSWORD=$(LC_ALL=C tr -dc A-Za-z0-9 </dev/urandom | head -c 32)" >> .env
echo "SUBNET_PREFIX=$SUBNET_PREFIX" >> .env
if [ -z "$CDN" ]; then
if ping -c 1 -W 1 docker.com > /dev/null 2>&1; then
CDN=0
else
CDN=1
echo "检测到你的网络环境不支持直接访问 Docker Hub 镜像将从华为云镜像仓库下载"
fi
fi
if [ $CDN -eq 0 ]; then
echo "IMAGE_PREFIX=chaitin" >>".env"
else
echo "IMAGE_PREFIX=swr.cn-east-3.myhuaweicloud.com/chaitin-safeline" >>".env"
fi
info "即将开始下载 Docker 镜像"
$compose_command up -d
if [ $? -ne "0" ]; then
abort "启动 Docker 容器失败"
fi
qrcode
check_container_health safeline-pg
check_container_health safeline-mgt
docker exec safeline-mgt /app/mgt-cli reset-admin --once
warning "雷池 WAF 社区版安装成功,请访问以下地址访问控制台"
warning "https://0.0.0.0:9443/"
for ip in $ips; do
warning https://$ip:9443/
done