mirror of
https://github.com/xkatld/lxdapi-web-server.git
synced 2026-05-31 08:17:21 +08:00
513 lines
17 KiB
Bash
513 lines
17 KiB
Bash
#!/bin/bash
|
||
|
||
cd /root >/dev/null 2>&1
|
||
|
||
RED='\033[0;31m'
|
||
GREEN='\033[0;32m'
|
||
YELLOW='\033[1;33m'
|
||
BLUE='\033[0;34m'
|
||
NC='\033[0m'
|
||
|
||
REGEX=("debian|astra" "ubuntu")
|
||
RELEASE=("Debian" "Ubuntu")
|
||
CMD=("$(grep -i pretty_name /etc/os-release 2>/dev/null | cut -d \" -f2)" "$(lsb_release -sd 2>/dev/null)")
|
||
SYS="${CMD[0]}"
|
||
[[ -n $SYS ]] || exit 1
|
||
|
||
for ((int = 0; int < ${#REGEX[@]}; int++)); do
|
||
if [[ $(echo "$SYS" | tr '[:upper:]' '[:lower:]') =~ ${REGEX[int]} ]]; then
|
||
SYSTEM="${RELEASE[int]}"
|
||
[[ -n $SYSTEM ]] && break
|
||
fi
|
||
done
|
||
|
||
if [[ "$SYSTEM" != "Debian" && "$SYSTEM" != "Ubuntu" ]]; then
|
||
echo -e "${RED}[ERR]${NC} 此脚本仅支持 Debian 和 Ubuntu 系统"
|
||
exit 1
|
||
fi
|
||
|
||
log() { echo -e "$1"; }
|
||
ok() { log "${GREEN}[OK]${NC} $1"; }
|
||
info() { log "${BLUE}[INFO]${NC} $1"; }
|
||
warn() { log "${YELLOW}[WARN]${NC} $1"; }
|
||
err() { log "${RED}[ERR]${NC} $1"; exit 1; }
|
||
|
||
reading() { read -rp "$(echo -e "${GREEN}$1${NC}")" "$2"; }
|
||
|
||
install_package() {
|
||
package_name=$1
|
||
if dpkg -l 2>/dev/null | grep -q "^ii.*$package_name"; then
|
||
ok "$package_name 已安装"
|
||
else
|
||
apt-get install -y $package_name >/dev/null 2>&1
|
||
if [ $? -ne 0 ]; then
|
||
apt-get install -y $package_name --fix-missing >/dev/null 2>&1
|
||
fi
|
||
if dpkg -l 2>/dev/null | grep -q "^ii.*$package_name"; then
|
||
ok "$package_name 已安装"
|
||
else
|
||
warn "$package_name 安装失败"
|
||
fi
|
||
fi
|
||
}
|
||
|
||
install_base_packages() {
|
||
info "更新软件包列表..."
|
||
apt-get update >/dev/null 2>&1
|
||
apt-get autoremove -y >/dev/null 2>&1
|
||
|
||
info "安装基础软件包..."
|
||
DEBIAN_FRONTEND=noninteractive apt-get install -y unzip e2fsprogs bc nftables fdisk parted iptables-persistent nginx >/dev/null 2>&1
|
||
ok "软件包安装完成"
|
||
|
||
systemctl enable nftables >/dev/null 2>&1
|
||
systemctl start nftables >/dev/null 2>&1
|
||
ok "nftables 已启动"
|
||
|
||
if command -v lxc &>/dev/null && lxc network show lxdbr0 &>/dev/null; then
|
||
systemctl reload snap.lxd.daemon 2>/dev/null
|
||
sleep 3
|
||
lxc network set lxdbr0 ipv4.nat true 2>/dev/null
|
||
lxc network set lxdbr0 ipv6.nat true 2>/dev/null
|
||
ok "LXD NAT 规则已重建"
|
||
fi
|
||
|
||
systemctl enable nginx >/dev/null 2>&1
|
||
systemctl start nginx >/dev/null 2>&1
|
||
ok "nginx 已启动"
|
||
}
|
||
|
||
deploy_lxdapi() {
|
||
info "检测系统架构..."
|
||
sys_arch=$(uname -m)
|
||
case $sys_arch in
|
||
x86_64)
|
||
arch="amd64"
|
||
ok "检测到架构: x86_64"
|
||
;;
|
||
aarch64|arm64)
|
||
arch="arm64"
|
||
ok "检测到架构: $sys_arch"
|
||
;;
|
||
*)
|
||
err "不支持的架构: $sys_arch"
|
||
;;
|
||
esac
|
||
|
||
while true; do
|
||
reading "请选择下载源 github/gitee [github]:" download_source
|
||
download_source=${download_source:-github}
|
||
if [[ "$download_source" =~ ^(github|gitee)$ ]]; then
|
||
break
|
||
else
|
||
warn "请输入 github 或 gitee"
|
||
fi
|
||
done
|
||
|
||
if [[ "$download_source" == "github" ]]; then
|
||
latest_tag=$(curl -s https://api.github.com/repos/xkatld/lxdapi-web-server/releases/latest | grep '"tag_name"' | sed -n 's/.*"tag_name": *"\([^"]*\)".*/\1/p')
|
||
base_url="https://github.com/xkatld/lxdapi-web-server/releases/download"
|
||
else
|
||
latest_tag=$(curl -s https://gitee.com/api/v5/repos/xkatld/lxdapi-web-server/releases/latest | grep '"tag_name"' | sed -n 's/.*"tag_name": *"\([^"]*\)".*/\1/p')
|
||
base_url="https://gitee.com/xkatld/lxdapi-web-server/releases/download"
|
||
fi
|
||
|
||
if [ -z "$latest_tag" ]; then
|
||
err "无法获取最新版本信息"
|
||
fi
|
||
|
||
info "最新版本: $latest_tag"
|
||
reading "请输入安装版本 [$latest_tag]:" install_version
|
||
install_version=${install_version:-$latest_tag}
|
||
ok "安装版本: $install_version"
|
||
|
||
download_url="${base_url}/${install_version}/lxdapi-linux-${arch}.tar.gz"
|
||
|
||
info "下载 lxdapi..."
|
||
info "下载地址: $download_url"
|
||
|
||
temp_file=$(mktemp)
|
||
if wget -q --show-progress -O "$temp_file" "$download_url" 2>&1; then
|
||
ok "下载完成"
|
||
else
|
||
rm -f "$temp_file"
|
||
err "下载失败"
|
||
fi
|
||
|
||
info "解压到 /opt/lxdapi..."
|
||
mkdir -p /opt/lxdapi
|
||
tar -xzf "$temp_file" -C /opt/lxdapi --strip-components=1
|
||
rm -f "$temp_file"
|
||
}
|
||
|
||
configure_lxdapi() {
|
||
info "配置 lxdapi..."
|
||
|
||
config_file="/opt/lxdapi/configs/config.yaml"
|
||
|
||
if [ ! -f "$config_file" ]; then
|
||
err "配置文件不存在: $config_file"
|
||
fi
|
||
|
||
reading "请输入服务端口 [8443]:" server_port
|
||
server_port=${server_port:-8443}
|
||
|
||
reading "请输入API密钥 [随机生成]:" api_hash
|
||
if [ -z "$api_hash" ]; then
|
||
api_hash=$(openssl rand -hex 16)
|
||
ok "API密钥已生成: $api_hash"
|
||
fi
|
||
|
||
reading "请输入管理员用户名 [admin]:" admin_user
|
||
admin_user=${admin_user:-admin}
|
||
|
||
reading "请输入管理员密码 [随机生成]:" admin_pass
|
||
if [ -z "$admin_pass" ]; then
|
||
admin_pass=$(openssl rand -hex 8)
|
||
ok "管理员密码已生成: $admin_pass"
|
||
fi
|
||
|
||
session_secret=$(openssl rand -hex 16)
|
||
|
||
reading "请输入流量采集间隔秒数 [20]:" traffic_interval
|
||
traffic_interval=${traffic_interval:-20}
|
||
|
||
reading "请输入流量批量更新数量 [10]:" traffic_batch_size
|
||
traffic_batch_size=${traffic_batch_size:-10}
|
||
|
||
reading "请输入任务自动清理天数 [7]:" auto_cleanup_days
|
||
auto_cleanup_days=${auto_cleanup_days:-7}
|
||
|
||
while true; do
|
||
reading "请选择任务队列后端 memory/redis [memory]:" task_backend
|
||
task_backend=${task_backend:-memory}
|
||
if [[ "$task_backend" =~ ^(memory|redis)$ ]]; then
|
||
break
|
||
else
|
||
warn "请输入 memory 或 redis"
|
||
fi
|
||
done
|
||
|
||
if [[ "$task_backend" == "redis" ]]; then
|
||
while true; do
|
||
reading "使用本地安装还是远程配置?local/remote [local]:" redis_location
|
||
redis_location=${redis_location:-local}
|
||
if [[ "$redis_location" =~ ^(local|remote)$ ]]; then
|
||
break
|
||
else
|
||
warn "请输入 local 或 remote"
|
||
fi
|
||
done
|
||
|
||
if [[ "$redis_location" == "local" ]]; then
|
||
info "安装 Redis..."
|
||
apt-get install -y redis-server >/dev/null 2>&1
|
||
systemctl start redis-server
|
||
systemctl enable redis-server
|
||
|
||
redis_host="localhost"
|
||
redis_port="6379"
|
||
redis_password=""
|
||
redis_db="0"
|
||
ok "Redis 已安装"
|
||
else
|
||
reading "请输入 Redis 主机地址:" redis_host
|
||
reading "请输入 Redis 端口 [6379]:" redis_port
|
||
redis_port=${redis_port:-6379}
|
||
reading "请输入 Redis 密码 [留空表示无密码]:" redis_password
|
||
reading "请输入 Redis 数据库编号 [0]:" redis_db
|
||
redis_db=${redis_db:-0}
|
||
fi
|
||
else
|
||
redis_host="localhost"
|
||
redis_port="6379"
|
||
redis_password=""
|
||
redis_db="0"
|
||
fi
|
||
|
||
while true; do
|
||
reading "请选择数据库类型 sqlite/mysql/postgres [sqlite]:" db_type
|
||
db_type=${db_type:-sqlite}
|
||
if [[ "$db_type" =~ ^(sqlite|mysql|postgres)$ ]]; then
|
||
break
|
||
else
|
||
warn "请输入 sqlite、mysql 或 postgres"
|
||
fi
|
||
done
|
||
|
||
if [[ "$db_type" == "mysql" ]]; then
|
||
while true; do
|
||
reading "使用本地安装还是远程配置?local/remote [local]:" mysql_location
|
||
mysql_location=${mysql_location:-local}
|
||
if [[ "$mysql_location" =~ ^(local|remote)$ ]]; then
|
||
break
|
||
else
|
||
warn "请输入 local 或 remote"
|
||
fi
|
||
done
|
||
|
||
if [[ "$mysql_location" == "local" ]]; then
|
||
info "安装 MariaDB..."
|
||
apt-get install -y mariadb-server >/dev/null 2>&1
|
||
systemctl start mariadb
|
||
systemctl enable mariadb
|
||
|
||
mysql_host="localhost"
|
||
mysql_port="3306"
|
||
mysql_user="lxdapi"
|
||
mysql_password=$(openssl rand -hex 8)
|
||
mysql_database="lxdapi"
|
||
|
||
info "创建数据库和用户..."
|
||
mysql -u root << EOF
|
||
CREATE DATABASE IF NOT EXISTS ${mysql_database};
|
||
CREATE USER IF NOT EXISTS '${mysql_user}'@'localhost' IDENTIFIED BY '${mysql_password}';
|
||
GRANT ALL PRIVILEGES ON ${mysql_database}.* TO '${mysql_user}'@'localhost';
|
||
FLUSH PRIVILEGES;
|
||
EOF
|
||
ok "MariaDB 数据库已创建"
|
||
ok "用户: $mysql_user"
|
||
ok "密码: $mysql_password"
|
||
else
|
||
reading "请输入 MySQL 主机地址:" mysql_host
|
||
reading "请输入 MySQL 端口 [3306]:" mysql_port
|
||
mysql_port=${mysql_port:-3306}
|
||
reading "请输入 MySQL 用户名:" mysql_user
|
||
reading "请输入 MySQL 密码:" mysql_password
|
||
reading "请输入 MySQL 数据库名:" mysql_database
|
||
fi
|
||
|
||
elif [[ "$db_type" == "postgres" ]]; then
|
||
while true; do
|
||
reading "使用本地安装还是远程配置?local/remote [local]:" postgres_location
|
||
postgres_location=${postgres_location:-local}
|
||
if [[ "$postgres_location" =~ ^(local|remote)$ ]]; then
|
||
break
|
||
else
|
||
warn "请输入 local 或 remote"
|
||
fi
|
||
done
|
||
|
||
if [[ "$postgres_location" == "local" ]]; then
|
||
info "安装 PostgreSQL..."
|
||
apt-get install -y postgresql >/dev/null 2>&1
|
||
systemctl start postgresql
|
||
systemctl enable postgresql
|
||
|
||
postgres_host="localhost"
|
||
postgres_port="5432"
|
||
postgres_user="lxdapi"
|
||
postgres_password=$(openssl rand -hex 8)
|
||
postgres_database="lxdapi"
|
||
postgres_sslmode="disable"
|
||
|
||
info "创建数据库和用户..."
|
||
sudo -u postgres psql << EOF
|
||
CREATE DATABASE ${postgres_database};
|
||
CREATE USER ${postgres_user} WITH PASSWORD '${postgres_password}';
|
||
GRANT ALL PRIVILEGES ON DATABASE ${postgres_database} TO ${postgres_user};
|
||
EOF
|
||
ok "PostgreSQL 数据库已创建"
|
||
ok "用户: $postgres_user"
|
||
ok "密码: $postgres_password"
|
||
else
|
||
reading "请输入 PostgreSQL 主机地址:" postgres_host
|
||
reading "请输入 PostgreSQL 端口 [5432]:" postgres_port
|
||
postgres_port=${postgres_port:-5432}
|
||
reading "请输入 PostgreSQL 用户名:" postgres_user
|
||
reading "请输入 PostgreSQL 密码:" postgres_password
|
||
reading "请输入 PostgreSQL 数据库名:" postgres_database
|
||
reading "请输入 PostgreSQL SSL模式 [disable]:" postgres_sslmode
|
||
postgres_sslmode=${postgres_sslmode:-disable}
|
||
fi
|
||
fi
|
||
|
||
info "写入配置文件..."
|
||
sed -i "s|__SERVER_PORT__|$server_port|g" "$config_file"
|
||
sed -i "s|__API_HASH__|$api_hash|g" "$config_file"
|
||
sed -i "s|__ADMIN_USER__|$admin_user|g" "$config_file"
|
||
sed -i "s|__ADMIN_PASS__|$admin_pass|g" "$config_file"
|
||
sed -i "s|__SESSION_SECRET__|$session_secret|g" "$config_file"
|
||
sed -i "s|__TRAFFIC_INTERVAL__|$traffic_interval|g" "$config_file"
|
||
sed -i "s|__TRAFFIC_BATCH_SIZE__|$traffic_batch_size|g" "$config_file"
|
||
sed -i "s|__AUTO_CLEANUP_DAYS__|$auto_cleanup_days|g" "$config_file"
|
||
sed -i "s|__TASK_BACKEND__|$task_backend|g" "$config_file"
|
||
sed -i "s|__REDIS_HOST__|$redis_host|g" "$config_file"
|
||
sed -i "s|__REDIS_PORT__|$redis_port|g" "$config_file"
|
||
sed -i "s|__REDIS_PASSWORD__|$redis_password|g" "$config_file"
|
||
sed -i "s|__REDIS_DB__|$redis_db|g" "$config_file"
|
||
sed -i "s|__DB_TYPE__|$db_type|g" "$config_file"
|
||
|
||
if [[ "$db_type" == "mysql" ]]; then
|
||
sed -i "s|__MYSQL_HOST__|$mysql_host|g" "$config_file"
|
||
sed -i "s|__MYSQL_PORT__|$mysql_port|g" "$config_file"
|
||
sed -i "s|__MYSQL_USER__|$mysql_user|g" "$config_file"
|
||
sed -i "s|__MYSQL_PASSWORD__|$mysql_password|g" "$config_file"
|
||
sed -i "s|__MYSQL_DATABASE__|$mysql_database|g" "$config_file"
|
||
else
|
||
sed -i "s|__MYSQL_HOST__|localhost|g" "$config_file"
|
||
sed -i "s|__MYSQL_PORT__|3306|g" "$config_file"
|
||
sed -i "s|__MYSQL_USER__|root|g" "$config_file"
|
||
sed -i "s|__MYSQL_PASSWORD__||g" "$config_file"
|
||
sed -i "s|__MYSQL_DATABASE__|lxdapi|g" "$config_file"
|
||
fi
|
||
|
||
if [[ "$db_type" == "postgres" ]]; then
|
||
sed -i "s|__POSTGRES_HOST__|$postgres_host|g" "$config_file"
|
||
sed -i "s|__POSTGRES_PORT__|$postgres_port|g" "$config_file"
|
||
sed -i "s|__POSTGRES_USER__|$postgres_user|g" "$config_file"
|
||
sed -i "s|__POSTGRES_PASSWORD__|$postgres_password|g" "$config_file"
|
||
sed -i "s|__POSTGRES_DATABASE__|$postgres_database|g" "$config_file"
|
||
sed -i "s|__POSTGRES_SSLMODE__|$postgres_sslmode|g" "$config_file"
|
||
else
|
||
sed -i "s|__POSTGRES_HOST__|localhost|g" "$config_file"
|
||
sed -i "s|__POSTGRES_PORT__|5432|g" "$config_file"
|
||
sed -i "s|__POSTGRES_USER__|postgres|g" "$config_file"
|
||
sed -i "s|__POSTGRES_PASSWORD__||g" "$config_file"
|
||
sed -i "s|__POSTGRES_DATABASE__|lxdapi|g" "$config_file"
|
||
sed -i "s|__POSTGRES_SSLMODE__|disable|g" "$config_file"
|
||
fi
|
||
|
||
ok "配置文件已更新"
|
||
}
|
||
|
||
setup_lxdapi_service() {
|
||
info "配置 lxdapi 系统服务..."
|
||
|
||
config_file="/opt/lxdapi/configs/config.yaml"
|
||
if [ ! -f "$config_file" ]; then
|
||
err "配置文件不存在: $config_file"
|
||
fi
|
||
|
||
if grep -q "__SERVER_PORT__" "$config_file"; then
|
||
err "配置文件未完成配置"
|
||
fi
|
||
|
||
sys_arch=$(uname -m)
|
||
case $sys_arch in
|
||
x86_64)
|
||
exec_bin="/opt/lxdapi/lxdapi-amd64"
|
||
;;
|
||
aarch64|arm64)
|
||
exec_bin="/opt/lxdapi/lxdapi-arm64"
|
||
;;
|
||
*)
|
||
err "不支持的架构: $sys_arch"
|
||
;;
|
||
esac
|
||
|
||
service_file="/etc/systemd/system/lxdapi.service"
|
||
|
||
cat > "$service_file" << EOF
|
||
[Unit]
|
||
Description=LXD API Server
|
||
After=network.target lxd.service
|
||
Wants=lxd.service
|
||
|
||
[Service]
|
||
Type=simple
|
||
User=root
|
||
WorkingDirectory=/opt/lxdapi
|
||
Environment="PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin"
|
||
ExecStart=$exec_bin
|
||
Restart=always
|
||
RestartSec=5
|
||
StandardOutput=journal
|
||
StandardError=journal
|
||
|
||
[Install]
|
||
WantedBy=multi-user.target
|
||
EOF
|
||
|
||
ok "服务文件已创建: $service_file"
|
||
|
||
systemctl daemon-reload
|
||
systemctl enable lxdapi
|
||
systemctl start lxdapi
|
||
|
||
info "等待服务启动..."
|
||
for i in {1..10}; do
|
||
printf "\r[%-10s] %d/10s" "$(printf '#%.0s' $(seq 1 $i))" "$i"
|
||
sleep 1
|
||
done
|
||
echo
|
||
|
||
if systemctl is-active --quiet lxdapi; then
|
||
ok "lxdapi 服务已启动"
|
||
else
|
||
warn "lxdapi 服务启动失败"
|
||
journalctl -u lxdapi -n 20 --no-pager
|
||
fi
|
||
}
|
||
|
||
main() {
|
||
echo
|
||
echo "========================================"
|
||
echo " LXDAPI 安装脚本"
|
||
echo " by Github-xkatld"
|
||
echo "========================================"
|
||
echo
|
||
|
||
echo "======== 步骤 1/5: 基础软件包安装 ========"
|
||
reading "是否安装基础软件包?(y/n) [y]:" step1_confirm
|
||
step1_confirm=${step1_confirm:-y}
|
||
if [[ "$step1_confirm" =~ ^[yY]$ ]]; then
|
||
install_base_packages
|
||
ok "基础软件包安装完成"
|
||
else
|
||
info "已跳过基础软件包安装"
|
||
fi
|
||
echo
|
||
|
||
echo "======== 步骤 2/5: 下载 ========"
|
||
reading "是否下载 lxdapi?(y/n) [y]:" step2_confirm
|
||
step2_confirm=${step2_confirm:-y}
|
||
if [[ "$step2_confirm" =~ ^[yY]$ ]]; then
|
||
deploy_lxdapi
|
||
ok "下载完成"
|
||
else
|
||
info "已跳过下载"
|
||
fi
|
||
echo
|
||
|
||
echo "======== 步骤 3/5: 配置 ========"
|
||
reading "是否配置 lxdapi?(y/n) [y]:" step3_confirm
|
||
step3_confirm=${step3_confirm:-y}
|
||
if [[ "$step3_confirm" =~ ^[yY]$ ]]; then
|
||
configure_lxdapi
|
||
ok "配置完成"
|
||
else
|
||
info "已跳过配置"
|
||
fi
|
||
echo
|
||
|
||
echo "======== 步骤 4/5: 启动服务 ========"
|
||
reading "是否启动 lxdapi 服务?(y/n) [y]:" step4_confirm
|
||
step4_confirm=${step4_confirm:-y}
|
||
if [[ "$step4_confirm" =~ ^[yY]$ ]]; then
|
||
setup_lxdapi_service
|
||
ok "服务已启动"
|
||
else
|
||
info "已跳过服务启动"
|
||
fi
|
||
echo
|
||
|
||
echo "======== 步骤 5/5: 完成 ========"
|
||
echo
|
||
echo "========================================"
|
||
echo " LXDAPI 安装完成"
|
||
echo "========================================"
|
||
echo
|
||
info "服务端口: $server_port"
|
||
info "API密钥: $api_hash"
|
||
info "管理员用户: $admin_user"
|
||
info "管理员密码: $admin_pass"
|
||
info "数据库类型: $db_type"
|
||
info "任务队列: $task_backend"
|
||
info "流量采集间隔: ${traffic_interval}s"
|
||
echo
|
||
systemctl status lxdapi --no-pager | head -5
|
||
}
|
||
|
||
main
|