#!/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 "$@"