Files
FunConnect/install.sh

389 lines
13 KiB
Bash
Raw Normal View History

#!/bin/bash
#
# FunMC 一键部署脚本
# 用法: bash install.sh [ -force ]
# - 无参数: 更新安装保留数据库与现有配置server.env / relay.env / credentials.txt
# - -force: 强制覆盖安装,清空数据库并重写所有配置
#
set -e
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
NC='\033[0m'
# 配置
FUNMC_VERSION="0.1.0"
INSTALL_DIR="/opt/funmc"
CONFIG_DIR="/etc/funmc"
DATA_DIR="/var/lib/funmc"
LOG_DIR="/var/log/funmc"
echo -e "${CYAN}"
echo "╔═══════════════════════════════════════════════════════════╗"
echo "║ ║"
echo "║ FunMC 服务端一键部署脚本 v${FUNMC_VERSION}"
echo "║ ║"
echo "║ 魔幻方开发 ║"
echo "║ ║"
echo "╚═══════════════════════════════════════════════════════════╝"
echo -e "${NC}"
if [ "$FORCE_INSTALL" -eq 1 ]; then
echo -e "${YELLOW}运行模式: 强制覆盖安装(将清空数据库并重写配置)${NC}"
else
echo -e "${GREEN}运行模式: 更新安装(保留数据库与现有配置)${NC}"
fi
echo ""
# 检查 root 权限
if [ "$EUID" -ne 0 ]; then
echo -e "${RED}请使用 root 权限运行此脚本${NC}"
echo "sudo bash install.sh"
exit 1
fi
# 解析参数:-force 或 --force 为强制覆盖安装,否则为更新(不覆盖数据)
FORCE_INSTALL=0
for arg in "$@"; do
if [ "$arg" = "-force" ] || [ "$arg" = "--force" ]; then
FORCE_INSTALL=1
break
fi
done
# 检测系统
detect_os() {
if [ -f /etc/os-release ]; then
. /etc/os-release
OS=$ID
OS_VERSION=$VERSION_ID
else
echo -e "${RED}无法检测操作系统${NC}"
exit 1
fi
echo -e "${GREEN}检测到系统: $OS $OS_VERSION${NC}"
}
# 安装依赖
install_deps() {
echo -e "${YELLOW}[1/7] 安装系统依赖...${NC}"
case $OS in
ubuntu|debian)
apt-get update -qq
apt-get install -y -qq curl wget git build-essential pkg-config libssl-dev postgresql postgresql-contrib nginx certbot python3-certbot-nginx
;;
centos|rhel|fedora)
dnf install -y curl wget git gcc openssl-devel postgresql-server postgresql-contrib nginx certbot python3-certbot-nginx
postgresql-setup --initdb
;;
*)
echo -e "${RED}不支持的操作系统: $OS${NC}"
exit 1
;;
esac
echo -e "${GREEN}✓ 系统依赖安装完成${NC}"
}
# 安装 Rust
install_rust() {
echo -e "${YELLOW}[2/7] 安装 Rust...${NC}"
if command -v cargo &> /dev/null; then
echo -e "${GREEN}✓ Rust 已安装${NC}"
else
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
source $HOME/.cargo/env
echo -e "${GREEN}✓ Rust 安装完成${NC}"
fi
}
# 安装 Node.js
install_nodejs() {
echo -e "${YELLOW}[3/7] 安装 Node.js...${NC}"
if command -v node &> /dev/null; then
echo -e "${GREEN}✓ Node.js 已安装${NC}"
else
curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
apt-get install -y nodejs
echo -e "${GREEN}✓ Node.js 安装完成${NC}"
fi
}
# 配置数据库(-force 时强制删除并重建,否则仅确保库存在且不覆盖数据)
setup_database() {
echo -e "${YELLOW}[4/7] 配置数据库...${NC}"
systemctl enable postgresql
systemctl start postgresql
if [ "$FORCE_INSTALL" -eq 1 ]; then
# 强制断开对 funmc 库的所有连接,再删除库和用户
sudo -u postgres psql -d postgres -c "SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = 'funmc' AND pid <> pg_backend_pid();" 2>/dev/null || true
sudo -u postgres psql -d postgres -c "DROP DATABASE IF EXISTS funmc;" 2>/dev/null || true
sudo -u postgres psql -d postgres -c "DROP USER IF EXISTS funmc;" 2>/dev/null || true
sudo -u postgres psql -d postgres -c "CREATE USER funmc WITH PASSWORD '12345678';"
sudo -u postgres psql -d postgres -c "CREATE DATABASE funmc OWNER funmc;"
sudo -u postgres psql -d postgres -c "GRANT ALL PRIVILEGES ON DATABASE funmc TO funmc;"
echo -e "${GREEN}✓ 数据库已强制重建(密码 12345678${NC}"
else
# 更新模式:不删除,仅确保用户和库存在(若已存在则跳过)
sudo -u postgres psql -d postgres -c "CREATE USER funmc WITH PASSWORD '12345678';" 2>/dev/null || true
sudo -u postgres psql -d postgres -c "CREATE DATABASE funmc OWNER funmc;" 2>/dev/null || true
sudo -u postgres psql -d postgres -c "GRANT ALL PRIVILEGES ON DATABASE funmc TO funmc;" 2>/dev/null || true
echo -e "${GREEN}✓ 数据库检查完成(未覆盖现有数据)${NC}"
fi
# 配置 pg_hba.conf仅追加缺失项
PG_HBA=$(sudo -u postgres psql -t -c "SHOW hba_file;" | xargs)
if ! grep -q "funmc" "$PG_HBA"; then
echo "local funmc funmc md5" >> "$PG_HBA"
echo "host funmc funmc 127.0.0.1/32 md5" >> "$PG_HBA"
systemctl reload postgresql
fi
}
# 下载并编译 FunMC
build_funmc() {
echo -e "${YELLOW}[5/7] 编译 FunMC...${NC}"
# 创建目录(含客户端下载目录)
mkdir -p $INSTALL_DIR $INSTALL_DIR/downloads $CONFIG_DIR $DATA_DIR $LOG_DIR
# 克隆或更新代码
if [ -d "$INSTALL_DIR/src" ]; then
cd $INSTALL_DIR/src
git pull
else
2026-02-25 20:35:01 +08:00
git clone https://gt.funmc.cn/xiaobai/FunConnect.git $INSTALL_DIR/src
cd $INSTALL_DIR/src
fi
# 编译服务端
source $HOME/.cargo/env
cargo build --release -p funmc-server -p funmc-relay-server
2026-02-25 22:07:34 +08:00
# 复制二进制文件包名与二进制名不同server / relay-server
cp target/release/server $INSTALL_DIR/funmc-server
cp target/release/relay-server $INSTALL_DIR/funmc-relay-server
2026-02-25 22:13:29 +08:00
# 编译管理面板前端(使用官方 registry 避免镜像返回 HTML 导致 FETCH_ERROR
cd $INSTALL_DIR/src/admin-panel
2026-02-25 22:13:29 +08:00
npm install --registry https://registry.npmjs.org/
npm run build
cp -r dist $INSTALL_DIR/admin-panel
echo -e "${GREEN}✓ FunMC 编译完成${NC}"
}
# 配置服务(-force 时重写配置;否则若已有配置则保留仅做迁移与重启)
configure_services() {
echo -e "${YELLOW}[6/7] 配置服务...${NC}"
WROTE_CONFIG=0
if [ "$FORCE_INSTALL" -eq 1 ] || [ ! -f "$CONFIG_DIR/server.env" ]; then
# 强制安装或首次安装:生成新配置
WROTE_CONFIG=1
DB_PASSWORD="12345678"
JWT_SECRET=$(openssl rand -base64 48 | tr -dc 'a-zA-Z0-9' | head -c 48)
ADMIN_PASSWORD=$(openssl rand -base64 16 | tr -dc 'a-zA-Z0-9' | head -c 12)
SERVER_IP=$(curl -s ifconfig.me || curl -s ipinfo.io/ip || hostname -I | awk '{print $1}')
cat > $CONFIG_DIR/server.env << EOF
# FunMC 服务端配置
DATABASE_URL=postgres://funmc:${DB_PASSWORD}@localhost/funmc
JWT_SECRET=${JWT_SECRET}
BIND_ADDR=0.0.0.0:3000
QUIC_PORT=3001
RUST_LOG=info
# 服务器信息
SERVER_NAME=FunMC Server
SERVER_IP=${SERVER_IP}
SERVER_DOMAIN=
# 管理面板
ADMIN_ENABLED=true
ADMIN_USERNAME=admin
ADMIN_PASSWORD=${ADMIN_PASSWORD}
# 客户端下载
CLIENT_DOWNLOAD_ENABLED=true
CLIENT_VERSION=${FUNMC_VERSION}
DOWNLOADS_DIR=$INSTALL_DIR/downloads
EOF
cat > $CONFIG_DIR/relay.env << EOF
RELAY_PORT=7900
JWT_SECRET=${JWT_SECRET}
RUST_LOG=info
EOF
else
# 更新模式:保留现有配置,仅确保 DB_PASSWORD 等变量存在供后续迁移使用
DB_PASSWORD=$(grep DATABASE_URL "$CONFIG_DIR/server.env" 2>/dev/null | sed -n 's/.*:\/\/funmc:\([^@]*\)@.*/\1/p')
if [ -z "$DB_PASSWORD" ]; then
DB_PASSWORD="12345678"
fi
echo -e "${GREEN}✓ 保留现有配置(未覆盖 server.env / relay.env${NC}"
fi
# 创建 systemd 服务文件(始终更新以便安装路径等变更生效)
cat > /etc/systemd/system/funmc-server.service << EOF
[Unit]
Description=FunMC API Server
After=network.target postgresql.service
[Service]
Type=simple
User=root
WorkingDirectory=$INSTALL_DIR
EnvironmentFile=$CONFIG_DIR/server.env
ExecStart=$INSTALL_DIR/funmc-server
Restart=always
2026-02-26 20:49:56 +08:00
RestartSec=10
[Install]
WantedBy=multi-user.target
EOF
cat > /etc/systemd/system/funmc-relay.service << EOF
[Unit]
Description=FunMC Relay Server
After=network.target
[Service]
Type=simple
User=root
WorkingDirectory=$INSTALL_DIR
EnvironmentFile=$CONFIG_DIR/relay.env
ExecStart=$INSTALL_DIR/funmc-relay-server
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
# 安装 sqlx-cli若未安装并运行数据库迁移
export PATH="$HOME/.cargo/bin:$PATH"
if ! command -v sqlx &> /dev/null; then
cargo install sqlx-cli --no-default-features --features postgres
fi
cd $INSTALL_DIR/src/server
export DATABASE_URL="postgres://funmc:${DB_PASSWORD}@localhost/funmc"
sqlx migrate run
# 启动服务
systemctl daemon-reload
systemctl enable funmc-server funmc-relay
systemctl start funmc-server funmc-relay
echo -e "${GREEN}✓ 服务配置完成${NC}"
# 仅强制/首次安装时写入凭据文件,更新模式不覆盖
if [ "$WROTE_CONFIG" -eq 1 ]; then
cat > $CONFIG_DIR/credentials.txt << EOF
======================================
FunMC 服务端安装信息
======================================
服务器 IP: ${SERVER_IP}
API 地址: http://${SERVER_IP}:3000
管理面板: http://${SERVER_IP}:3000/admin
管理员账号: admin
管理员密码: ${ADMIN_PASSWORD}
数据库密码: ${DB_PASSWORD}
JWT 密钥: ${JWT_SECRET}
======================================
请妥善保管此文件!
======================================
EOF
chmod 600 $CONFIG_DIR/credentials.txt
fi
}
# 配置防火墙
configure_firewall() {
echo -e "${YELLOW}[7/7] 配置防火墙...${NC}"
if command -v ufw &> /dev/null; then
ufw allow 80/tcp
ufw allow 443/tcp
ufw allow 3000/tcp
ufw allow 7900/udp
ufw allow 7901/udp
echo -e "${GREEN}✓ UFW 防火墙配置完成${NC}"
elif command -v firewall-cmd &> /dev/null; then
firewall-cmd --permanent --add-port=80/tcp
firewall-cmd --permanent --add-port=443/tcp
firewall-cmd --permanent --add-port=3000/tcp
firewall-cmd --permanent --add-port=7900/udp
firewall-cmd --permanent --add-port=7901/udp
firewall-cmd --reload
echo -e "${GREEN}✓ firewalld 防火墙配置完成${NC}"
else
echo -e "${YELLOW}! 未检测到防火墙,请手动开放端口 80, 443, 3000, 7900, 7901${NC}"
fi
}
# 显示完成信息
show_completion() {
SERVER_IP=$(cat $CONFIG_DIR/server.env | grep SERVER_IP | cut -d= -f2)
ADMIN_PASSWORD=$(cat $CONFIG_DIR/server.env | grep ADMIN_PASSWORD | cut -d= -f2)
echo ""
echo -e "${CYAN}╔═══════════════════════════════════════════════════════════╗${NC}"
echo -e "${CYAN}║ ║${NC}"
echo -e "${CYAN}${GREEN}FunMC 安装完成!${CYAN}${NC}"
echo -e "${CYAN}║ ║${NC}"
echo -e "${CYAN}╚═══════════════════════════════════════════════════════════╝${NC}"
echo ""
echo -e "${GREEN}服务器信息:${NC}"
echo -e " API 地址: http://${SERVER_IP}:3000"
echo -e " 管理面板: http://${SERVER_IP}:3000/admin"
echo ""
echo -e "${GREEN}管理员登录:${NC}"
echo -e " 用户名: admin"
echo -e " 密码: ${ADMIN_PASSWORD}"
echo ""
echo -e "${GREEN}客户端下载:${NC}"
echo -e " http://${SERVER_IP}:3000/download"
echo ""
echo -e "${YELLOW}重要文件:${NC}"
echo -e " 配置文件: $CONFIG_DIR/server.env"
echo -e " 凭据信息: $CONFIG_DIR/credentials.txt"
echo -e " 日志文件: $LOG_DIR/"
echo ""
echo -e "${CYAN}服务管理命令:${NC}"
echo -e " 查看状态: systemctl status funmc-server"
echo -e " 重启服务: systemctl restart funmc-server"
echo -e " 查看日志: journalctl -u funmc-server -f"
echo ""
echo -e "${GREEN}魔幻方开发 - 让 Minecraft 联机变得简单${NC}"
}
# 主流程
main() {
detect_os
install_deps
install_rust
install_nodejs
setup_database
build_funmc
configure_services
configure_firewall
show_completion
}
# 运行
main "$@"