#!/bin/bash
# ============= 自动后台运行检测 =============
if [[ "$1" != "background" ]]; then
echo "首次运行,将在后台继续执行..."
nohup $0 background > /var/log/ai-gateway-install.log 2>&1 &
echo "安装日志已记录到 /var/log/ai-gateway-install.log"
echo "你可以安全地关闭 SSH 连接"
exit 0
fi
# ============= 配置变量 =============
DOMAIN="vps2.zxm20.top"
ADMIN_KEY="admin_$(openssl rand -hex 8)"
ENCRYPTION_KEY="encrypt_$(openssl rand -hex 8)"
DB_PASSWORD="dbpass_$(openssl rand -hex 8)"
INSTALL_DIR="/var/www/ai-gateway"
# ============= 创建日志目录 =============
mkdir -p /var/log/
exec > >(tee -a /var/log/ai-gateway-install.log) 2>&1
# ============= 1. 检查是否为 root =============
if [ "$EUID" -ne 0 ]; then
echo "请以 root 权限运行此脚本"
exit 1
fi
# ============= 2. 安装系统依赖 =============
echo "安装系统依赖..."
apt update && apt upgrade -y
apt install -y git python3 python3-pip python3-venv nginx postgresql postgresql-contrib redis-server certbot curl build-essential net-tools
# ============= 3. 安装 Node.js =============
echo "安装 Node.js..."
curl -fsSL https://deb.nodesource.com/setup_18.x | bash -
apt install -y nodejs
# ============= 4. 创建项目目录 =============
echo "创建项目目录..."
mkdir -p $INSTALL_DIR/{backend,frontend,admin,ssl}
chown -R $USER:$USER $INSTALL_DIR
cd $INSTALL_DIR
# ============= 5. 生成后端代码 =============
cat > backend/app.py <<'EOL'
import os
import logging
import random
import time
import ssl
import psycopg2
import redis
import requests
from flask import Flask, request, jsonify
from flask_cors import CORS
from functools import wraps
from cryptography.fernet import Fernet
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization
import base64
import json
from datetime import datetime, timedelta, timezone
import psutil
import traceback
# 日志配置
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logger = logging.getLogger('AI-Gateway')
app = Flask(__name__)
CORS(app)
# 环境变量
DB_HOST = os.getenv('DB_HOST', 'localhost')
DB_PORT = os.getenv('DB_PORT', '5432')
DB_NAME = os.getenv('DB_NAME', 'ai_gateway')
DB_USER = os.getenv('DB_USER', 'ai_gateway')
DB_PASSWORD = os.getenv('DB_PASSWORD', 'your_db_password')
REDIS_URL = os.getenv('REDIS_URL', 'redis://localhost:6379/0')
ADMIN_KEY = os.getenv('ADMIN_KEY', 'your_admin_key')
ENCRYPTION_KEY = os.getenv('ENCRYPTION_KEY', 'your_encryption_key')
DOMAIN = os.getenv('DOMAIN', 'your-domain.com')
# 数据库连接池
db_pool = psycopg2.pool.ThreadedConnectionPool(1, 10,
host=DB_HOST,
port=DB_PORT,
database=DB_NAME,
user=DB_USER,
password=DB_PASSWORD
)
# Redis连接池
redis_client = redis.Redis.from_url(REDIS_URL)
def get_db():
if 'db' not in g:
g.db = db_pool.getconn()
return g.db
@app.teardown_appcontext
def close_db(e=None):
db = g.pop('db', None)
if db is not None:
db_pool.putconn(db)
# 加密工具
def get_cipher_suite():
salt = b'salt_'
kdf = PBKDF2HMAC(algorithm=hashes.SHA256(), length=32, salt=salt, iterations=100000, backend=default_backend())
key = base64.urlsafe_b64encode(kdf.derive(ENCRYPTION_KEY.encode()))
return Fernet(key)
def encrypt_data(data):
return get_cipher_suite().encrypt(data.encode()).decode()
def decrypt_data(encrypted_data):
return get_cipher_suite().decrypt(encrypted_data.encode()).decode()
# 管理员认证装饰器
def admin_required(f):
@wraps(f)
def decorated_function(*args, **kwargs):
auth_header = request.headers.get('Authorization')
if not auth_header or not auth_header.startswith('Bearer '):
return jsonify({"error": "未提供认证信息"}), 401
token = auth_header.split(' ')[1]
if token != ADMIN_KEY:
return jsonify({"error": "无效的管理员密钥"}), 403
return f(*args, **kwargs)
return decorated_function
# 获取 API 密钥
def get_api_key(service_name):
cache_key = f"api_key:{service_name}"
cached_key = redis_client.get(cache_key)
if cached_key:
return cached_key.decode()
db = get_db()
cur = db.cursor()
cur.execute("SELECT id, api_key FROM api_keys WHERE service_name = %s AND is_active = TRUE", (service_name,))
keys = cur.fetchall()
cur.close()
if not keys:
raise Exception(f"没有可用的{service_name} API密钥")
key_id, api_key = random.choice(keys)
try:
decrypted_key = decrypt_data(api_key)
except:
decrypted_key = api_key
redis_client.setex(cache_key, 3600, decrypted_key)
return decrypted_key
# 调用AI服务
def call_ai_service(service_name, query, history=None):
api_key = get_api_key(service_name)
if service_name == 'openai':
return call_openai(api_key, query, history)
elif service_name == 'deepseek':
return call_deepseek(api_key, query, history)
elif service_name == 'doubao':
return call_doubao(api_key, query, history)
elif service_name == 'claude':
return call_claude(api_key, query, history)
elif service_name == 'llama':
return call_llama(api_key, query, history)
else:
raise Exception(f"不支持的服务: {service_name}")
# 具体服务调用实现...
# (此处省略具体服务实现,保持完整脚本结构)
# 用户查询接口
@app.route('/api/query', methods=['POST'])
def handle_query():
data = request.json
service_name = data.get('service')
query = data.get('query')
history = data.get('history', [])
if not service_name or not query:
return jsonify({"error": "无效的请求参数"}), 400
start_time = time.time()
client_ip = request.remote_addr
status = 'success'
error_message = None
try:
response = call_ai_service(service_name, query, history)
elapsed = time.time() - start_time
log_usage(service_name, query, response, elapsed, client_ip, status, error_message)
return jsonify({
"success": True,
"service": service_name,
"response": response,
"time": elapsed
})
except Exception as e:
status = 'error'
error_message = str(e)
elapsed = time.time() - start_time
logger.error(f"AI调用失败: {str(e)}\n{traceback.format_exc()}")
log_usage(service_name, query, None, elapsed, client_ip, status, error_message)
return jsonify({"error": str(e)}), 500
# 其他路由...
# (省略其余路由)
if __name__ == '__main__':
try:
ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
ssl_context.load_cert_chain('ssl/cert.pem', 'ssl/key.pem')
app.run(host='0.0.0.0', port=5000, ssl_context=ssl_context, threaded=True, debug=False)
except Exception as e:
logger.error(f"启动失败: {str(e)}")
exit(1)
EOL
# ============= 6. 创建数据库初始化脚本 =============
cat > backend/sql/init.sql <<'EOL'
CREATE TABLE services (
id SERIAL PRIMARY KEY,
name VARCHAR(50) NOT NULL UNIQUE,
display_name VARCHAR(100) NOT NULL,
description TEXT,
endpoint VARCHAR(255),
model VARCHAR(100),
is_available BOOLEAN DEFAULT TRUE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE api_keys (
id SERIAL PRIMARY KEY,
service_name VARCHAR(50) NOT NULL REFERENCES services(name),
api_key TEXT NOT NULL,
is_active BOOLEAN DEFAULT TRUE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 初始化服务
INSERT INTO services (name, display_name, description, endpoint, model) VALUES
('openai', 'OpenAI', 'OpenAI的GPT系列模型', 'https://api.openai.com/v1/chat/completions', 'gpt-3.5-turbo'),
('deepseek', 'DeepSeek', '深度求索的大模型服务', 'https://api.deepseek.com/v1/chat/completions', 'deepseek-chat'),
('doubao', '豆包', '字节跳动的豆包大模型', 'https://dubao.baidu.com/api/v1/chat', 'Doubao-Pro'),
('claude', 'Claude', 'Anthropic的安全对齐模型', 'https://api.anthropic.com/v1/messages', 'claude-3-opus'),
('llama', 'Llama', 'Meta的开源大语言模型', 'https://api.replicate.com/v1/predictions', 'llama-2-70b-chat');
EOL
# ============= 7. 创建前端页面 =============
cat > frontend/index.html <<'EOL'
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>AI服务聚合平台</title>
</head>
<body>
<h1>欢迎使用 AI 服务聚合平台</h1>
<p>访问地址: https://vps2.zxm20.top</p>
</body>
</html>
EOL
# ============= 8. 申请SSL证书 =============
echo "申请SSL证书..."
certbot certonly --standalone -d $DOMAIN --non-interactive --agree-tos -m admin@$DOMAIN --no-eff-email || true
cp /etc/letsencrypt/live/$DOMAIN/fullchain.pem ssl/cert.pem
cp /etc/letsencrypt/live/$DOMAIN/privkey.pem ssl/key.pem
# ============= 9. 设置 PostgreSQL =============
echo "设置 PostgreSQL..."
sudo -u postgres psql -c "CREATE USER ai_gateway WITH PASSWORD '$DB_PASSWORD';"
sudo -u postgres psql -c "CREATE DATABASE ai_gateway;"
sudo -u postgres psql -c "GRANT ALL PRIVILEGES ON DATABASE ai_gateway TO ai_gateway;"
# ============= 10. 初始化数据库 =============
sudo -u postgres psql -d ai_gateway -f backend/sql/init.sql
# ============= 11. 设置后端环境变量 =============
cd backend
python3 -m venv venv
source venv/bin/activate
pip install cryptography flask flask-cors requests psycopg2-binary redis gunicorn
cat > .env <<EOF
ADMIN_KEY=$ADMIN_KEY
ENCRYPTION_KEY=$ENCRYPTION_KEY
DB_HOST=localhost
DB_PORT=5432
DB_NAME=ai_gateway
DB_USER=ai_gateway
DB_PASSWORD=$DB_PASSWORD
REDIS_URL=redis://localhost:6379/0
DOMAIN=$DOMAIN
EOF
# ============= 12. 创建 Gunicorn 服务 =============
cat > /etc/systemd/system/ai-gateway.service <<'EOF'
[Unit]
Description=AI Gateway Backend
After=network.target
[Service]
User=$USER
Group=$USER
WorkingDirectory=/var/www/ai-gateway/backend
Environment="PATH=/var/www/ai-gateway/backend/venv/bin"
ExecStart=/var/www/ai-gateway/backend/venv/bin/gunicorn -w 4 -b 127.0.0.1:5000 app:app
Restart=always
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable ai-gateway
systemctl start ai-gateway
# ============= 13. 配置 Nginx =============
cat > /etc/nginx/sites-available/ai-gateway <<'EOL'
server {
listen 80;
server_name vps2.zxm20.top;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name vps2.zxm20.top;
ssl_certificate /var/www/ai-gateway/ssl/cert.pem;
ssl_certificate_key /var/www/ai-gateway/ssl/key.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers EECDH+AESGCM:EDH+AESGCM;
ssl_prefer_server_ciphers on;
location / {
root /var/www/html;
index index.html;
try_files $uri $uri/ =404;
}
location /api {
proxy_pass http://127.0.0.1:5000;
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;
}
}
EOL
ln -s /etc/nginx/sites-available/ai-gateway /etc/nginx/sites-enabled/
rm /etc/nginx/sites-enabled/default
nginx -t && systemctl restart nginx
# ============= 14. 配置防火墙 =============
ufw allow OpenSSH
ufw allow 'Nginx Full'
ufw --force enable
# ============= 15. 输出部署信息 =============
echo "✅ 部署完成!"
echo "管理员密钥: $ADMIN_KEY"
echo "数据库密码: $DB_PASSWORD"
echo "访问地址: https://vps2.zxm20.top"
echo "日志文件: /var/log/ai-gateway-install.log"
改成OpenRouter的免费ai,记住要真的调用
最新发布