前提条件
Debian13(其他系统参考本文可能存在兼容性问题)
Node.js 20+(重要!低版本会导致 oxc-parser 错误)
PostgreSQL数据库(根据自身环境选择部署方式)
Redis数据库(可选,暂不推荐,可能存在兼容性问题)
PostgreSQL配置
- 终端手动安装
sudo apt update
sudo apt install postgresql postgresql-contrib
sudo systemctl status postgresql
sudo -i -u postgres
createuser --interactive
createuser --createdb --no-superuser --no-createrole hubdb
psql
ALTER USER hubdb WITH PASSWORD 'your_secure_password';
\q
createdb --owner=hubdb hubdb
psql -d hubdb -U hubdb
\conninfo
\q
- 1Panel安装




配置NPM
apt install npm
克隆仓库
git clone https://github.com/laoshuikaixue/VoiceHub.git
cd VoiceHub
npm install
配置环境变量
- 手动配置
cp .env.example .env
JWT_SECRET 应该是一个至少 32 个字符的强随机字符串。您可以使用在线工具生成,或者运行以下命令
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
编辑 .env 文件,配置必需的环境变量:
# 数据库连接地址(必填)
DATABASE_URL="postgresql://username:password@host:port/database?sslmode=require"
# JWT 认证密钥(必填)
JWT_SECRET="your-very-secure-jwt-secret-key"
# 应用运行环境(可选)
NODE_ENV=development
- 交互式配置
cat > /root/configure-env.sh << 'EOF'
#!/bin/bash
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
echo -e "${BLUE}========================================${NC}"
echo -e "${GREEN}VoiceHub 环境变量配置脚本${NC}"
echo -e "${BLUE}========================================${NC}"
# 进入项目目录
cd /root/VoiceHub 2>/dev/null || {
echo -e "${RED}❌ 无法进入 /root/VoiceHub 目录${NC}"
exit 1
}
# 检查 .env.example 是否存在
if [ ! -f ".env.example" ]; then
echo -e "${RED}❌ 找不到 .env.example 文件${NC}"
exit 1
fi
# 复制 .env.example 到 .env
echo -e "${YELLOW}📋 复制 .env.example 到 .env...${NC}"
cp .env.example .env
echo -e "${GREEN}✅ 已创建 .env 文件${NC}"
echo -e "${BLUE}========================================${NC}"
echo -e "${YELLOW}请按照提示配置环境变量:${NC}"
echo -e "${BLUE}========================================${NC}"
# 数据库配置
echo -e "\n${GREEN}📦 数据库配置(必填)${NC}"
echo -e "${BLUE}格式: postgresql://用户名:密码@主机:端口/数据库名?sslmode=require${NC}"
echo -e "${BLUE}示例: postgresql://myuser:mypassword@localhost:5432/voicehub?sslmode=require${NC}"
read -p "请输入数据库主机 (默认: localhost): " DB_HOST
DB_HOST=${DB_HOST:-localhost}
read -p "请输入数据库端口 (默认: 5432): " DB_PORT
DB_PORT=${DB_PORT:-5432}
read -p "请输入数据库名 (默认: voicehub): " DB_NAME
DB_NAME=${DB_NAME:-voicehub}
read -p "请输入数据库用户名: " DB_USER
while [ -z "$DB_USER" ]; do
echo -e "${RED}❌ 用户名不能为空${NC}"
read -p "请输入数据库用户名: " DB_USER
done
read -s -p "请输入数据库密码: " DB_PASS
echo ""
while [ -z "$DB_PASS" ]; do
echo -e "${RED}❌ 密码不能为空${NC}"
read -s -p "请输入数据库密码: " DB_PASS
echo ""
done
# 生成数据库 URL
DATABASE_URL="postgresql://${DB_USER}:${DB_PASS}@${DB_HOST}:${DB_PORT}/${DB_NAME}?sslmode=require"
# JWT 配置
echo -e "\n${GREEN}🔑 JWT 配置(必填)${NC}"
echo -e "${BLUE}建议使用强随机字符串,至少32位${NC}"
read -p "是否自动生成强 JWT 密钥?(y/n, 默认: y): " AUTO_JWT
AUTO_JWT=${AUTO_JWT:-y}
if [[ $AUTO_JWT == "y" || $AUTO_JWT == "Y" ]]; then
# 生成随机 JWT 密钥
JWT_SECRET=$(openssl rand -hex 32)
echo -e "${GREEN}✅ 已自动生成 JWT 密钥${NC}"
else
read -p "请输入 JWT 密钥: " JWT_SECRET
while [ -z "$JWT_SECRET" ]; do
echo -e "${RED}❌ JWT 密钥不能为空${NC}"
read -p "请输入 JWT 密钥: " JWT_SECRET
done
fi
# 应用环境配置
echo -e "\n${GREEN}⚙️ 应用环境配置${NC}"
echo "1) development (开发环境)"
echo "2) production (生产环境)"
read -p "请选择 (默认: 1): " NODE_ENV_CHOICE
if [[ $NODE_ENV_CHOICE == "2" ]]; then
NODE_ENV="production"
else
NODE_ENV="development"
fi
# Redis 配置
echo -e "\n${GREEN}📀 Redis 配置(可选)${NC}"
echo -e "${YELLOW}注意:Redis 暂不推荐使用,可能存在潜在问题${NC}"
read -p "是否配置 Redis?(y/n, 默认: n): " USE_REDIS
if [[ $USE_REDIS == "y" || $USE_REDIS == "Y" ]]; then
read -p "请输入 Redis 主机 (默认: localhost): " REDIS_HOST
REDIS_HOST=${REDIS_HOST:-localhost}
read -p "请输入 Redis 端口 (默认: 6379): " REDIS_PORT
REDIS_PORT=${REDIS_PORT:-6379}
read -p "请输入 Redis 用户名 (默认: default): " REDIS_USER
REDIS_USER=${REDIS_USER:-default}
read -s -p "请输入 Redis 密码: " REDIS_PASS
echo ""
REDIS_URL="redis://${REDIS_USER}:${REDIS_PASS}@${REDIS_HOST}:${REDIS_PORT}"
else
REDIS_URL=""
fi
# OAuth 配置
echo -e "\n${GREEN}🔐 OAuth 配置(可选)${NC}"
read -p "是否配置 OAuth?(y/n, 默认: n): " USE_OAUTH
if [[ $USE_OAUTH == "y" || $USE_OAUTH == "Y" ]]; then
# OAuth 回调地址
echo -e "\n${YELLOW}OAuth 回调配置${NC}"
read -p "请输入 OAuth 回调地址 (默认: http://localhost:3000/api/auth): " OAUTH_REDIRECT_URI
OAUTH_REDIRECT_URI=${OAUTH_REDIRECT_URI:-"http://localhost:3000/api/auth"}
# OAuth state 密钥
read -p "是否自动生成 OAuth state 密钥?(y/n, 默认: y): " AUTO_OAUTH_STATE
AUTO_OAUTH_STATE=${AUTO_OAUTH_STATE:-y}
if [[ $AUTO_OAUTH_STATE == "y" || $AUTO_OAUTH_STATE == "Y" ]]; then
OAUTH_STATE_SECRET=$(openssl rand -hex 32)
echo -e "${GREEN}✅ 已自动生成 OAuth state 密钥${NC}"
else
read -p "请输入 OAuth state 密钥: " OAUTH_STATE_SECRET
fi
# GitHub OAuth
echo -e "\n${YELLOW}GitHub OAuth(可选)${NC}"
read -p "请输入 GitHub Client ID (留空跳过): " GITHUB_CLIENT_ID
if [ ! -z "$GITHUB_CLIENT_ID" ]; then
read -p "请输入 GitHub Client Secret: " GITHUB_CLIENT_SECRET
fi
# Google OAuth
echo -e "\n${YELLOW}Google OAuth(可选)${NC}"
read -p "请输入 Google Client ID (留空跳过): " GOOGLE_CLIENT_ID
if [ ! -z "$GOOGLE_CLIENT_ID" ]; then
read -p "请输入 Google Client Secret: " GOOGLE_CLIENT_SECRET
fi
# Casdoor OAuth
echo -e "\n${YELLOW}Casdoor OAuth(可选)${NC}"
read -p "请输入 Casdoor Client ID (留空跳过): " CASDOOR_CLIENT_ID
if [ ! -z "$CASDOOR_CLIENT_ID" ]; then
read -p "请输入 Casdoor Client Secret: " CASDOOR_CLIENT_SECRET
read -p "请输入 Casdoor Endpoint: " CASDOOR_ENDPOINT
fi
else
OAUTH_REDIRECT_URI="http://localhost:3000/api/auth"
OAUTH_STATE_SECRET=""
GITHUB_CLIENT_ID=""
GITHUB_CLIENT_SECRET=""
GOOGLE_CLIENT_ID=""
GOOGLE_CLIENT_SECRET=""
CASDOOR_CLIENT_ID=""
CASDOOR_CLIENT_SECRET=""
CASDOOR_ENDPOINT=""
fi
# 写入 .env 文件
echo -e "\n${YELLOW}📝 正在写入 .env 文件...${NC}"
cat > .env << EOL
# 数据库连接地址(必填)
# 格式:postgresql://用户名:密码@主机:端口/数据库名?sslmode=require
# 示例:postgresql://myuser:mypassword@localhost:5432/voicehub?sslmode=require
DATABASE_URL="${DATABASE_URL}"
# JWT 认证密钥(必填)
# 请使用强随机字符串,建议至少 32 位
JWT_SECRET="${JWT_SECRET}"
# 应用运行环境(可选)
# development: 开发环境
# production: 生产环境
NODE_ENV=${NODE_ENV}
# Redis 缓存服务(可选,暂不推荐)
# 如果设置了 REDIS_URL,系统将自动启用 Redis 缓存功能
# 格式:redis://用户名:密码@主机:端口
EOL
if [ -z "$REDIS_URL" ]; then
echo "# REDIS_URL=\"redis://default:password@host:port\"" >> .env
else
echo "REDIS_URL=\"${REDIS_URL}\"" >> .env
fi
cat >> .env << EOL
# OAuth 配置(可选)
# 启用相应的 OAuth 提供商需要填写对应的 Client ID 和 Client Secret
# OAuth 回调地址(必填,如果启用 OAuth)
# 注意:[provider] 是占位符,实际使用时需要根据具体情况填写
# 通常需要配置基础的回调域名,例如:https://your-domain.com
OAUTH_REDIRECT_URI="${OAUTH_REDIRECT_URI}"
# 用于加密 OAuth state 的密钥(必填,如果启用 OAuth)
EOL
if [ -z "$OAUTH_STATE_SECRET" ]; then
echo "# OAUTH_STATE_SECRET=your-secure-random-string-for-oauth-state" >> .env
else
echo "OAUTH_STATE_SECRET=${OAUTH_STATE_SECRET}" >> .env
fi
cat >> .env << EOL
# GitHub OAuth
GITHUB_CLIENT_ID="${GITHUB_CLIENT_ID}"
GITHUB_CLIENT_SECRET="${GITHUB_CLIENT_SECRET}"
# Casdoor OAuth
CASDOOR_CLIENT_ID="${CASDOOR_CLIENT_ID}"
CASDOOR_CLIENT_SECRET="${CASDOOR_CLIENT_SECRET}"
CASDOOR_ENDPOINT="${CASDOOR_ENDPOINT}"
# Google OAuth
GOOGLE_CLIENT_ID="${GOOGLE_CLIENT_ID}"
GOOGLE_CLIENT_SECRET="${GOOGLE_CLIENT_SECRET}"
EOL
# 显示配置结果
echo -e "${BLUE}========================================${NC}"
echo -e "${GREEN}✅ .env 文件配置完成!${NC}"
echo -e "${BLUE}========================================${NC}"
echo -e "${YELLOW}配置文件位置: ${NC}$(pwd)/.env"
echo -e "${YELLOW}数据库连接: ${NC}${DATABASE_URL}"
echo -e "${YELLOW}JWT 密钥: ${NC}${JWT_SECRET}"
echo -e "${YELLOW}运行环境: ${NC}${NODE_ENV}"
if [ ! -z "$REDIS_URL" ]; then
echo -e "${YELLOW}Redis: ${NC}已配置"
fi
echo -e "${BLUE}========================================${NC}"
echo -e "${GREEN}🎉 配置完成!现在可以运行以下命令:${NC}"
echo -e " ${YELLOW}npm run db:generate${NC} # 生成数据库 schema"
echo -e " ${YELLOW}npm run db:migrate${NC} # 执行数据库迁移"
echo -e " ${YELLOW}npm run create-admin${NC} # 创建管理员账户"
echo -e " ${YELLOW}npm run dev${NC} # 启动开发服务器"
echo -e " ${YELLOW}npm run build${NC} # 构建生产版本"
echo -e " ${YELLOW}npm start${NC} # 运行生产版本"
echo -e "${BLUE}========================================${NC}"
EOF
# 添加执行权限
chmod +x /root/configure-env.sh
echo -e "${GREEN}✅ 脚本已创建:/root/configure-env.sh${NC}"
echo -e "${YELLOW}运行命令:sudo /root/configure-env.sh${NC}"
sudo /root/configure-env.sh
测试运行
npm run deploy
npm run dev
npm run build
npm start
PM2持久化
npm install -g pm2
pm2 --version
cd /root/VoiceHub
pm2 start .output/server/index.mjs --name voicehub
如果上面的执行失败那么试试带参数启动
DATABASE_URL="your-database-url" \
JWT_SECRET="your-jwt" \
HOST="0.0.0.0" \
PORT="3000" \
pm2 start .output/server/index.mjs --name voicehub
反向代理
- Candy部署
cat > /root/install-caddy.sh << 'EOF'
#!/bin/bash
# Caddy 交互式安装脚本 - 自动反代 + SSL 申请与续签
# 适用于 VoiceHub 或其他 Node.js 应用
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# 显示欢迎信息
clear
echo -e "${BLUE}========================================${NC}"
echo -e "${GREEN} Caddy 反向代理 + SSL 自动安装脚本 ${NC}"
echo -e "${BLUE}========================================${NC}"
echo -e "${YELLOW}本脚本将:${NC}"
echo -e " 1. 安装 Caddy Web 服务器"
echo -e " 2. 配置反向代理到你的应用"
echo -e " 3. 自动申请 Let's Encrypt SSL 证书"
echo -e " 4. 设置证书自动续签"
echo -e "${BLUE}========================================${NC}"
echo ""
# 检查是否以 root 运行
if [ "$EUID" -ne 0 ]; then
echo -e "${RED}❌ 请以 root 权限运行此脚本${NC}"
echo -e " sudo $0"
exit 1
fi
# 检查 curl 是否安装
if ! command -v curl &> /dev/null; then
echo -e "${YELLOW}📦 安装 curl...${NC}"
apt update && apt install -y curl
fi
# 交互式配置
echo -e "${GREEN}📝 请配置以下信息:${NC}"
echo ""
# 输入域名
read -p "请输入你的域名 (例如: voicehub.example.com): " DOMAIN
while [ -z "$DOMAIN" ]; do
echo -e "${RED}❌ 域名不能为空${NC}"
read -p "请输入你的域名: " DOMAIN
done
# 输入邮箱(用于 SSL 通知)
read -p "请输入你的邮箱 (用于 SSL 证书通知): " EMAIL
while [ -z "$EMAIL" ]; do
echo -e "${RED}❌ 邮箱不能为空${NC}"
read -p "请输入你的邮箱: " EMAIL
done
# 输入后端服务地址
echo -e "${YELLOW}📡 后端服务配置${NC}"
echo -e " VoiceHub 默认运行在 ${BLUE}localhost:3000${NC}"
read -p "请输入后端服务地址 (默认: localhost:3000): " BACKEND
BACKEND=${BACKEND:-localhost:3000}
# 确认配置
echo ""
echo -e "${BLUE}========================================${NC}"
echo -e "${GREEN}配置确认:${NC}"
echo -e " 域名: ${YELLOW}$DOMAIN${NC}"
echo -e " 邮箱: ${YELLOW}$EMAIL${NC}"
echo -e " 后端: ${YELLOW}$BACKEND${NC}"
echo -e "${BLUE}========================================${NC}"
echo ""
read -p "确认以上配置?(y/n): " CONFIRM
if [[ ! "$CONFIRM" =~ ^[Yy]$ ]]; then
echo -e "${RED}❌ 安装已取消${NC}"
exit 1
fi
# 开始安装
echo ""
echo -e "${GREEN}🚀 开始安装 Caddy...${NC}"
# 安装 Caddy(官方源)
echo -e "${YELLOW}📦 添加 Caddy 官方仓库...${NC}"
apt update
apt install -y debian-keyring debian-archive-keyring apt-transport-https
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | tee /etc/apt/sources.list.d/caddy-stable.list
apt update
apt install -y caddy
# 检查安装结果
if ! command -v caddy &> /dev/null; then
echo -e "${RED}❌ Caddy 安装失败${NC}"
exit 1
fi
echo -e "${GREEN}✅ Caddy 安装成功!版本: $(caddy version)${NC}"
# 创建 Caddyfile 配置
echo -e "${YELLOW}📝 创建 Caddyfile 配置...${NC}"
# 备份原配置
if [ -f /etc/caddy/Caddyfile ]; then
cp /etc/caddy/Caddyfile /etc/caddy/Caddyfile.backup.$(date +%Y%m%d%H%M%S)
echo -e "${YELLOW}已备份原配置${NC}"
fi
# 写入新配置
cat > /etc/caddy/Caddyfile << CONF
# VoiceHub 反向代理配置
# 由安装脚本自动生成于 $(date)
${DOMAIN} {
# 日志配置
log {
output file /var/log/caddy/${DOMAIN}.log
level INFO
}
# 反向代理到后端服务
reverse_proxy ${BACKEND} {
# 转发原始 Host 头
header_up Host {host}
# 转发真实 IP
header_up X-Real-IP {remote}
header_up X-Forwarded-For {remote}
header_up X-Forwarded-Proto {scheme}
}
# 安全头配置
header {
X-Content-Type-Options nosniff
X-Frame-Options DENY
X-XSS-Protection "1; mode=block"
Referrer-Policy strict-origin-when-cross-origin
}
# 启用压缩
encode gzip zstd
}
# HTTP 重定向到 HTTPS(默认已启用)
CONF
echo -e "${GREEN}✅ Caddyfile 配置完成${NC}"
# 设置权限
chown -R caddy:caddy /var/log/caddy 2>/dev/null || mkdir -p /var/log/caddy && chown caddy:caddy /var/log/caddy
# 测试配置
echo -e "${YELLOW}🔍 测试 Caddy 配置...${NC}"
caddy validate --config /etc/caddy/Caddyfile
if [ $? -ne 0 ]; then
echo -e "${RED}❌ Caddy 配置测试失败${NC}"
exit 1
fi
echo -e "${GREEN}✅ 配置测试通过${NC}"
# 重启 Caddy
echo -e "${YELLOW}🔄 重启 Caddy 服务...${NC}"
systemctl restart caddy
# 检查服务状态
if systemctl is-active --quiet caddy; then
echo -e "${GREEN}✅ Caddy 服务已启动${NC}"
else
echo -e "${RED}❌ Caddy 服务启动失败,查看日志: journalctl -u caddy -f${NC}"
exit 1
fi
# 设置开机自启
systemctl enable caddy
echo -e "${GREEN}✅ 已设置开机自启${NC}"
# 验证 SSL 证书申请
echo ""
echo -e "${YELLOW}⏳ 等待 SSL 证书申请(可能需要几秒钟)...${NC}"
sleep 5
# 检查证书是否成功
CERT_FILE="/var/lib/caddy/.local/share/caddy/certificates/acme-v02.api.letsencrypt.org-directory/${DOMAIN}/${DOMAIN}.crt"
if [ -f "$CERT_FILE" ]; then
echo -e "${GREEN}✅ SSL 证书申请成功!${NC}"
# 显示证书过期时间
openssl x509 -in "$CERT_FILE" -noout -enddate | cut -d= -f2
else
echo -e "${YELLOW}⚠️ 证书申请中,请稍后检查:${NC}"
echo -e " journalctl -u caddy -f | grep -i 'cert'"
fi
# 设置自动续签(Caddy 默认自动处理)
echo -e "${GREEN}✅ 自动续签已内置,无需额外配置${NC}"
# 防火墙配置
echo ""
echo -e "${YELLOW}🔥 配置防火墙...${NC}"
if command -v ufw &> /dev/null; then
ufw allow 80/tcp comment 'Caddy HTTP'
ufw allow 443/tcp comment 'Caddy HTTPS'
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 --reload
echo -e "${GREEN}✅ FirewallD 规则已添加${NC}"
else
echo -e "${YELLOW}⚠️ 未检测到防火墙工具,请手动开放 80 和 443 端口${NC}"
fi
# 显示完成信息
echo ""
echo -e "${BLUE}========================================${NC}"
echo -e "${GREEN}🎉 Caddy 安装配置完成!${NC}"
echo -e "${BLUE}========================================${NC}"
echo -e " 域名: ${YELLOW}https://${DOMAIN}${NC}"
echo -e " 后端: ${YELLOW}${BACKEND}${NC}"
echo -e ""
echo -e "${YELLOW}📋 常用命令:${NC}"
echo -e " 查看状态: ${GREEN}systemctl status caddy${NC}"
echo -e " 查看日志: ${GREEN}journalctl -u caddy -f${NC}"
echo -e " 编辑配置: ${GREEN}vim /etc/caddy/Caddyfile${NC}"
echo -e " 重载配置: ${GREEN}systemctl reload caddy${NC}"
echo -e " 重启服务: ${GREEN}systemctl restart caddy${NC}"
echo -e ""
echo -e "${YELLOW}📝 证书信息:${NC}"
echo -e " 证书路径: ${GREEN}/var/lib/caddy/.local/share/caddy/certificates/acme-v02.api.letsencrypt.org-directory/${DOMAIN}/${NC}"
echo -e " 自动续签: ${GREEN}Caddy 内置,无需手动干预${NC}"
echo -e ""
echo -e "${YELLOW}🌐 测试访问:${NC}"
echo -e " ${GREEN}curl -I https://${DOMAIN}${NC}"
echo -e "${BLUE}========================================${NC}"
echo ""
echo -e "${GREEN}🔔 请确保你的域名 ${DOMAIN} 已解析到本服务器 IP!${NC}"
echo -e "${YELLOW}如果尚未解析,请先配置 DNS 记录${NC}"
EOF
# 添加执行权限
chmod +x /root/install-caddy.sh
echo -e "${GREEN}✅ 脚本已创建:/root/install-caddy.sh${NC}"
echo -e "${YELLOW}运行命令:sudo /root/install-caddy.sh${NC}"
sudo /root/install-caddy.sh
- 1Panel部署









- 直接接入CDN加速

开机自启动
pm2 startup
pm2 save
pm2 resurrect
systemctl status pm2-root
软件更新
pm2 list
pm2 stop voicehub
pm2 list
cd /root
mv VoiceHub VoiceHub_backup_$(date +%Y%m%d)
git clone https://github.com/laoshuikaixue/VoiceHub.git
cd VoiceHub
cp /root/VoiceHub_backup_$(date +%Y%m%d)/.env ./
npm install
npm run build
pm2 start .output/server/index.mjs --name voicehub
pm2 status
pm2 logs voicehub --lines 20
本文系作者 @
雨落祈星台
原创发布在 雨落Droplogue ,未经许可,禁止转载。
评论