feat: 完成Rust User API完整开发
Some checks failed
Deploy to Production / Run Tests (push) Failing after 16m35s
Deploy to Production / Security Scan (push) Has been skipped
Deploy to Production / Build Docker Image (push) Has been skipped
Deploy to Production / Deploy to Staging (push) Has been skipped
Deploy to Production / Deploy to Production (push) Has been skipped
Deploy to Production / Notify Results (push) Successful in 31s
Some checks failed
Deploy to Production / Run Tests (push) Failing after 16m35s
Deploy to Production / Security Scan (push) Has been skipped
Deploy to Production / Build Docker Image (push) Has been skipped
Deploy to Production / Deploy to Staging (push) Has been skipped
Deploy to Production / Deploy to Production (push) Has been skipped
Deploy to Production / Notify Results (push) Successful in 31s
✨ 新功能: - SQLite数据库集成和持久化存储 - 数据库迁移系统和版本管理 - API分页功能和高效查询 - 用户搜索和过滤机制 - 完整的RBAC角色权限系统 - 结构化日志记录和系统监控 - API限流和多层安全防护 - Docker容器化和生产部署配置 🔒 安全特性: - JWT认证和授权 - 限流和防暴力破解 - 安全头和CORS配置 - 输入验证和XSS防护 - 审计日志和安全监控 📊 监控和运维: - Prometheus指标收集 - 健康检查和系统监控 - 自动化备份和恢复 - 完整的运维文档和脚本 - CI/CD流水线配置 🚀 部署支持: - 多环境Docker配置 - 生产环境部署指南 - 性能优化和安全加固 - 故障排除和应急响应 - 自动化运维脚本 📚 文档完善: - API使用文档 - 部署检查清单 - 运维操作手册 - 性能和安全指南 - 故障排除指南
This commit is contained in:
470
scripts/production-setup.sh
Executable file
470
scripts/production-setup.sh
Executable file
@@ -0,0 +1,470 @@
|
||||
#!/bin/bash
|
||||
|
||||
# 生产环境设置脚本
|
||||
# 用于初始化生产环境配置和部署
|
||||
|
||||
set -e
|
||||
|
||||
# 颜色定义
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# 日志函数
|
||||
log_info() {
|
||||
echo -e "${BLUE}[INFO]${NC} $1"
|
||||
}
|
||||
|
||||
log_success() {
|
||||
echo -e "${GREEN}[SUCCESS]${NC} $1"
|
||||
}
|
||||
|
||||
log_warning() {
|
||||
echo -e "${YELLOW}[WARNING]${NC} $1"
|
||||
}
|
||||
|
||||
log_error() {
|
||||
echo -e "${RED}[ERROR]${NC} $1"
|
||||
}
|
||||
|
||||
# 检查是否为root用户
|
||||
check_root() {
|
||||
if [[ $EUID -eq 0 ]]; then
|
||||
log_error "请不要以root用户运行此脚本"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# 检查系统要求
|
||||
check_system_requirements() {
|
||||
log_info "检查系统要求..."
|
||||
|
||||
# 检查Docker
|
||||
if ! command -v docker &> /dev/null; then
|
||||
log_error "Docker未安装,请先安装Docker"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 检查Docker Compose
|
||||
if ! command -v docker-compose &> /dev/null; then
|
||||
log_error "Docker Compose未安装,请先安装Docker Compose"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 检查系统资源
|
||||
TOTAL_MEM=$(free -m | awk 'NR==2{printf "%.0f", $2}')
|
||||
if [ "$TOTAL_MEM" -lt 1024 ]; then
|
||||
log_warning "系统内存少于1GB,可能影响性能"
|
||||
fi
|
||||
|
||||
DISK_SPACE=$(df -BG . | awk 'NR==2{print $4}' | sed 's/G//')
|
||||
if [ "$DISK_SPACE" -lt 10 ]; then
|
||||
log_warning "可用磁盘空间少于10GB,可能不足"
|
||||
fi
|
||||
|
||||
log_success "系统要求检查完成"
|
||||
}
|
||||
|
||||
# 创建目录结构
|
||||
create_directories() {
|
||||
log_info "创建目录结构..."
|
||||
|
||||
mkdir -p /opt/rust-api/{data,logs,backups,ssl,config}
|
||||
mkdir -p /opt/rust-api/nginx/{conf.d,ssl}
|
||||
mkdir -p /opt/rust-api/monitoring/{prometheus,grafana}
|
||||
|
||||
log_success "目录结构创建完成"
|
||||
}
|
||||
|
||||
# 设置文件权限
|
||||
setup_permissions() {
|
||||
log_info "设置文件权限..."
|
||||
|
||||
# 创建专用用户(如果不存在)
|
||||
if ! id "apiuser" &>/dev/null; then
|
||||
sudo useradd -r -s /bin/false -m -d /opt/rust-api apiuser
|
||||
log_success "创建用户 apiuser"
|
||||
fi
|
||||
|
||||
# 设置目录权限
|
||||
sudo chown -R apiuser:apiuser /opt/rust-api
|
||||
sudo chmod 750 /opt/rust-api
|
||||
sudo chmod 755 /opt/rust-api/{data,logs,backups}
|
||||
sudo chmod 700 /opt/rust-api/{ssl,config}
|
||||
|
||||
log_success "文件权限设置完成"
|
||||
}
|
||||
|
||||
# 生成SSL证书
|
||||
generate_ssl_certificate() {
|
||||
log_info "生成SSL证书..."
|
||||
|
||||
read -p "请输入域名 (例: example.com): " DOMAIN
|
||||
|
||||
if [ -z "$DOMAIN" ]; then
|
||||
log_warning "未输入域名,跳过SSL证书生成"
|
||||
return
|
||||
fi
|
||||
|
||||
# 检查是否已存在证书
|
||||
if [ -f "/opt/rust-api/ssl/cert.pem" ]; then
|
||||
log_warning "SSL证书已存在,跳过生成"
|
||||
return
|
||||
fi
|
||||
|
||||
# 生成自签名证书(生产环境建议使用Let's Encrypt)
|
||||
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
|
||||
-keyout /opt/rust-api/ssl/key.pem \
|
||||
-out /opt/rust-api/ssl/cert.pem \
|
||||
-subj "/C=CN/ST=State/L=City/O=Organization/CN=$DOMAIN"
|
||||
|
||||
sudo chown apiuser:apiuser /opt/rust-api/ssl/*.pem
|
||||
sudo chmod 600 /opt/rust-api/ssl/*.pem
|
||||
|
||||
log_success "SSL证书生成完成"
|
||||
log_info "生产环境建议使用Let's Encrypt证书"
|
||||
}
|
||||
|
||||
# 创建环境配置文件
|
||||
create_env_file() {
|
||||
log_info "创建环境配置文件..."
|
||||
|
||||
if [ -f ".env.production" ]; then
|
||||
log_warning ".env.production 已存在,跳过创建"
|
||||
return
|
||||
fi
|
||||
|
||||
# 复制模板文件
|
||||
cp config/production.env.template .env.production
|
||||
|
||||
# 生成随机JWT密钥
|
||||
JWT_SECRET=$(openssl rand -base64 32)
|
||||
sed -i "s/CHANGE_THIS_TO_A_SECURE_SECRET_KEY_AT_LEAST_32_CHARACTERS_LONG/$JWT_SECRET/" .env.production
|
||||
|
||||
log_success "环境配置文件创建完成"
|
||||
log_warning "请编辑 .env.production 文件,配置实际的生产环境参数"
|
||||
}
|
||||
|
||||
# 创建Nginx配置
|
||||
create_nginx_config() {
|
||||
log_info "创建Nginx配置..."
|
||||
|
||||
cat > /opt/rust-api/nginx/nginx.conf << 'EOF'
|
||||
events {
|
||||
worker_connections 1024;
|
||||
}
|
||||
|
||||
http {
|
||||
upstream rust_api {
|
||||
server rust-user-api:3000;
|
||||
}
|
||||
|
||||
# 限流配置
|
||||
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
|
||||
limit_conn_zone $binary_remote_addr zone=conn_limit_per_ip:10m;
|
||||
|
||||
# 日志格式
|
||||
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
||||
'$status $body_bytes_sent "$http_referer" '
|
||||
'"$http_user_agent" "$http_x_forwarded_for"';
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
server_name _;
|
||||
|
||||
# 重定向到HTTPS
|
||||
return 301 https://$server_name$request_uri;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
server_name _;
|
||||
|
||||
# SSL配置
|
||||
ssl_certificate /etc/nginx/ssl/cert.pem;
|
||||
ssl_certificate_key /etc/nginx/ssl/key.pem;
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512;
|
||||
ssl_prefer_server_ciphers off;
|
||||
|
||||
# 安全头
|
||||
add_header X-Frame-Options DENY;
|
||||
add_header X-Content-Type-Options nosniff;
|
||||
add_header X-XSS-Protection "1; mode=block";
|
||||
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";
|
||||
|
||||
# 限流
|
||||
limit_req zone=api burst=20 nodelay;
|
||||
limit_conn conn_limit_per_ip 10;
|
||||
|
||||
# API代理
|
||||
location /api/ {
|
||||
proxy_pass http://rust_api;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
|
||||
# 超时配置
|
||||
proxy_connect_timeout 30s;
|
||||
proxy_send_timeout 30s;
|
||||
proxy_read_timeout 30s;
|
||||
}
|
||||
|
||||
# 健康检查
|
||||
location /health {
|
||||
proxy_pass http://rust_api;
|
||||
access_log off;
|
||||
}
|
||||
|
||||
# 监控端点(限制访问)
|
||||
location /monitoring/ {
|
||||
allow 10.0.0.0/8;
|
||||
allow 172.16.0.0/12;
|
||||
allow 192.168.0.0/16;
|
||||
deny all;
|
||||
|
||||
proxy_pass http://rust_api;
|
||||
}
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
sudo chown apiuser:apiuser /opt/rust-api/nginx/nginx.conf
|
||||
log_success "Nginx配置创建完成"
|
||||
}
|
||||
|
||||
# 创建监控配置
|
||||
create_monitoring_config() {
|
||||
log_info "创建监控配置..."
|
||||
|
||||
# Prometheus配置
|
||||
cat > /opt/rust-api/monitoring/prometheus/prometheus.yml << 'EOF'
|
||||
global:
|
||||
scrape_interval: 15s
|
||||
|
||||
scrape_configs:
|
||||
- job_name: 'rust-user-api'
|
||||
static_configs:
|
||||
- targets: ['rust-user-api:3000']
|
||||
metrics_path: '/monitoring/metrics/prometheus'
|
||||
scrape_interval: 30s
|
||||
|
||||
- job_name: 'nginx'
|
||||
static_configs:
|
||||
- targets: ['nginx:9113']
|
||||
EOF
|
||||
|
||||
# Grafana配置
|
||||
mkdir -p /opt/rust-api/monitoring/grafana/dashboards
|
||||
cat > /opt/rust-api/monitoring/grafana/dashboard.json << 'EOF'
|
||||
{
|
||||
"dashboard": {
|
||||
"id": null,
|
||||
"title": "Rust User API Dashboard",
|
||||
"tags": ["rust", "api"],
|
||||
"timezone": "browser",
|
||||
"panels": [
|
||||
{
|
||||
"id": 1,
|
||||
"title": "Request Rate",
|
||||
"type": "graph",
|
||||
"targets": [
|
||||
{
|
||||
"expr": "rate(http_requests_total[5m])",
|
||||
"legendFormat": "Requests/sec"
|
||||
}
|
||||
],
|
||||
"yAxes": [
|
||||
{
|
||||
"label": "requests/sec"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"title": "Response Time",
|
||||
"type": "graph",
|
||||
"targets": [
|
||||
{
|
||||
"expr": "histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m]))",
|
||||
"legendFormat": "95th percentile"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"time": {
|
||||
"from": "now-1h",
|
||||
"to": "now"
|
||||
},
|
||||
"refresh": "30s"
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
sudo chown -R apiuser:apiuser /opt/rust-api/monitoring
|
||||
log_success "监控配置创建完成"
|
||||
}
|
||||
|
||||
# 创建备份脚本
|
||||
create_backup_script() {
|
||||
log_info "创建备份脚本..."
|
||||
|
||||
cat > /opt/rust-api/backup.sh << 'EOF'
|
||||
#!/bin/bash
|
||||
|
||||
# 数据库备份脚本
|
||||
|
||||
BACKUP_DIR="/opt/rust-api/backups"
|
||||
DATE=$(date +%Y%m%d-%H%M%S)
|
||||
RETENTION_DAYS=30
|
||||
|
||||
# 创建备份目录
|
||||
mkdir -p $BACKUP_DIR
|
||||
|
||||
# 备份数据库
|
||||
docker-compose exec -T rust-user-api \
|
||||
sqlite3 /app/data/production.db ".backup /app/data/backup-$DATE.db"
|
||||
|
||||
# 复制备份文件到主机
|
||||
docker cp rust-user-api-prod:/app/data/backup-$DATE.db $BACKUP_DIR/
|
||||
|
||||
# 压缩备份
|
||||
tar -czf "$BACKUP_DIR/api-backup-$DATE.tar.gz" \
|
||||
-C $BACKUP_DIR backup-$DATE.db
|
||||
|
||||
# 清理临时文件
|
||||
rm -f "$BACKUP_DIR/backup-$DATE.db"
|
||||
|
||||
# 清理旧备份
|
||||
find $BACKUP_DIR -name "api-backup-*.tar.gz" -mtime +$RETENTION_DAYS -delete
|
||||
|
||||
echo "备份完成: api-backup-$DATE.tar.gz"
|
||||
EOF
|
||||
|
||||
chmod +x /opt/rust-api/backup.sh
|
||||
sudo chown apiuser:apiuser /opt/rust-api/backup.sh
|
||||
|
||||
log_success "备份脚本创建完成"
|
||||
}
|
||||
|
||||
# 设置防火墙
|
||||
setup_firewall() {
|
||||
log_info "设置防火墙..."
|
||||
|
||||
if ! command -v ufw &> /dev/null; then
|
||||
log_warning "UFW未安装,跳过防火墙配置"
|
||||
return
|
||||
fi
|
||||
|
||||
read -p "是否配置防火墙? (y/N): " SETUP_FIREWALL
|
||||
if [[ ! "$SETUP_FIREWALL" =~ ^[Yy]$ ]]; then
|
||||
log_info "跳过防火墙配置"
|
||||
return
|
||||
fi
|
||||
|
||||
sudo ufw default deny incoming
|
||||
sudo ufw default allow outgoing
|
||||
sudo ufw allow ssh
|
||||
sudo ufw allow 80/tcp
|
||||
sudo ufw allow 443/tcp
|
||||
|
||||
read -p "是否启用防火墙? (y/N): " ENABLE_FIREWALL
|
||||
if [[ "$ENABLE_FIREWALL" =~ ^[Yy]$ ]]; then
|
||||
sudo ufw --force enable
|
||||
log_success "防火墙配置完成并已启用"
|
||||
else
|
||||
log_info "防火墙配置完成但未启用"
|
||||
fi
|
||||
}
|
||||
|
||||
# 创建systemd服务
|
||||
create_systemd_service() {
|
||||
log_info "创建systemd服务..."
|
||||
|
||||
cat > /tmp/rust-api.service << EOF
|
||||
[Unit]
|
||||
Description=Rust User API
|
||||
Requires=docker.service
|
||||
After=docker.service
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
RemainAfterExit=yes
|
||||
WorkingDirectory=/opt/rust-api
|
||||
ExecStart=/usr/bin/docker-compose -f docker-compose.prod.yml up -d
|
||||
ExecStop=/usr/bin/docker-compose -f docker-compose.prod.yml down
|
||||
TimeoutStartSec=0
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
|
||||
sudo mv /tmp/rust-api.service /etc/systemd/system/
|
||||
sudo systemctl daemon-reload
|
||||
|
||||
log_success "systemd服务创建完成"
|
||||
log_info "使用 'sudo systemctl enable rust-api' 启用自动启动"
|
||||
}
|
||||
|
||||
# 运行安全检查
|
||||
run_security_check() {
|
||||
log_info "运行安全检查..."
|
||||
|
||||
# 检查文件权限
|
||||
if [ "$(stat -c %a /opt/rust-api)" != "750" ]; then
|
||||
log_warning "目录权限不正确"
|
||||
fi
|
||||
|
||||
# 检查SSL证书
|
||||
if [ ! -f "/opt/rust-api/ssl/cert.pem" ]; then
|
||||
log_warning "SSL证书不存在"
|
||||
fi
|
||||
|
||||
# 检查环境文件权限
|
||||
if [ -f ".env.production" ] && [ "$(stat -c %a .env.production)" != "600" ]; then
|
||||
chmod 600 .env.production
|
||||
log_info "修正环境文件权限"
|
||||
fi
|
||||
|
||||
log_success "安全检查完成"
|
||||
}
|
||||
|
||||
# 主函数
|
||||
main() {
|
||||
echo "=========================================="
|
||||
echo " Rust User API 生产环境设置脚本"
|
||||
echo "=========================================="
|
||||
echo
|
||||
|
||||
check_root
|
||||
check_system_requirements
|
||||
create_directories
|
||||
setup_permissions
|
||||
generate_ssl_certificate
|
||||
create_env_file
|
||||
create_nginx_config
|
||||
create_monitoring_config
|
||||
create_backup_script
|
||||
setup_firewall
|
||||
create_systemd_service
|
||||
run_security_check
|
||||
|
||||
echo
|
||||
log_success "生产环境设置完成!"
|
||||
echo
|
||||
echo "下一步操作:"
|
||||
echo "1. 编辑 .env.production 文件,配置生产环境参数"
|
||||
echo "2. 复制项目文件到 /opt/rust-api/"
|
||||
echo "3. 运行 'docker-compose -f docker-compose.prod.yml up -d' 启动服务"
|
||||
echo "4. 使用 'sudo systemctl enable rust-api' 启用自动启动"
|
||||
echo "5. 配置域名DNS指向服务器IP"
|
||||
echo "6. 使用Let's Encrypt获取正式SSL证书"
|
||||
echo
|
||||
log_info "详细文档请参考 docs/production-deployment.md"
|
||||
}
|
||||
|
||||
# 运行主函数
|
||||
main "$@"
|
Reference in New Issue
Block a user