1+ #! /bin/bash
2+
3+ # --- 配置 ---
4+ NGINX_SITES_AVAILABLE=" /etc/nginx/sites-available"
5+ NGINX_SITES_ENABLED=" /etc/nginx/sites-enabled"
6+ TARGET_API_URL=" https://generativelanguage.googleapis.com/v1beta/models/"
7+
8+ # --- 颜色定义 ---
9+ GREEN=' \033[0;32m'
10+ YELLOW=' \033[1;33m'
11+ RED=' \033[0;31m'
12+ NC=' \033[0m' # No Color
13+
14+ # --- 辅助函数 ---
15+ function print_info {
16+ echo -e " ${GREEN} [信息] $1 ${NC} "
17+ }
18+
19+ function print_warning {
20+ echo -e " ${YELLOW} [警告] $1 ${NC} "
21+ }
22+
23+ function print_error {
24+ echo -e " ${RED} [错误] $1 ${NC} "
25+ }
26+
27+ function check_root {
28+ if [[ $EUID -ne 0 ]]; then
29+ print_error " 此脚本需要以 root 权限运行。请使用 'sudo ./setup_gemini_proxy.sh' 运行。"
30+ exit 1
31+ fi
32+ }
33+
34+ function check_nginx {
35+ if ! command -v nginx & > /dev/null; then
36+ print_error " 未找到 Nginx。请先安装 Nginx (例如: 'sudo apt update && sudo apt install nginx' 或 'sudo yum install nginx')。"
37+ exit 1
38+ fi
39+ print_info " 检测到 Nginx 已安装。"
40+ }
41+
42+ # --- 主逻辑 ---
43+ clear
44+ print_info " 欢迎使用 Google Gemini API Nginx 反向代理配置脚本"
45+ print_warning " --------------------------------------------------"
46+ print_warning " 重要提示:"
47+ print_warning " 1. API Key 安全: 强烈建议让客户端在请求时提供 API Key (通过 Header 或 URL 参数)。"
48+ print_warning " 脚本生成的配置默认不包含 API Key,您需要在客户端请求中添加它。"
49+ print_warning " 如果您选择在 Nginx 配置中添加 Key (不推荐),请务必保护好配置文件的安全。"
50+ print_warning " 2. HTTPS: 强烈建议为您的代理启用 HTTPS,以保护通信安全。"
51+ print_warning " --------------------------------------------------"
52+ echo
53+
54+ # 1. 检查权限和 Nginx
55+ check_root
56+ check_nginx
57+ echo
58+
59+ # 2. 获取用户输入
60+ read -p " 请输入您的服务器域名或公共 IP 地址: " server_name
61+ while [[ -z " $server_name " ]]; do
62+ print_warning " 服务器域名或 IP 地址不能为空。"
63+ read -p " 请输入您的服务器域名或公共 IP 地址: " server_name
64+ done
65+
66+ read -p " 请输入您希望在服务器上访问 Gemini 的路径前缀 (必须以 / 开头和结尾, 例如 /gemini/): " proxy_location
67+ # 验证路径格式
68+ while ! [[ " $proxy_location " =~ ^/.* \/ $ ]]; do
69+ print_warning " 路径前缀格式无效。必须以 / 开头和结尾 (例如 /gemini/ )。"
70+ read -p " 请重新输入路径前缀: " proxy_location
71+ done
72+
73+ config_file_name=" gemini-proxy-${server_name// ./ _} .conf" # 基于域名/IP生成文件名
74+ config_file_path=" ${NGINX_SITES_AVAILABLE} /${config_file_name} "
75+ link_path=" ${NGINX_SITES_ENABLED} /${config_file_name} "
76+
77+ read -p " 是否需要配置 HTTPS (需要您准备好 SSL 证书)? (y/n, 默认 n): " use_https
78+ use_https=$( echo " $use_https " | tr ' [:upper:]' ' [:lower:]' ) # 转小写
79+
80+ ssl_cert_path=" "
81+ ssl_key_path=" "
82+ listen_directive=" listen 80;"
83+ ssl_config_block=" "
84+
85+ if [[ " $use_https " == " y" ]]; then
86+ listen_directive=" listen 443 ssl http2;"
87+ print_info " 已选择启用 HTTPS。"
88+ while [[ -z " $ssl_cert_path " ]]; do
89+ read -p " 请输入 SSL 证书文件的完整路径 (例如 /etc/letsencrypt/live/yourdomain.com/fullchain.pem): " ssl_cert_path
90+ if [[ -z " $ssl_cert_path " ]]; then
91+ print_warning " 证书路径不能为空。"
92+ # 可选:添加文件存在性检查
93+ # elif [[ ! -f "$ssl_cert_path" ]]; then
94+ # print_warning "找不到证书文件: $ssl_cert_path"
95+ # ssl_cert_path=""
96+ fi
97+ done
98+ while [[ -z " $ssl_key_path " ]]; do
99+ read -p " 请输入 SSL 私钥文件的完整路径 (例如 /etc/letsencrypt/live/yourdomain.com/privkey.pem): " ssl_key_path
100+ if [[ -z " $ssl_key_path " ]]; then
101+ print_warning " 私钥路径不能为空。"
102+ # 可选:添加文件存在性检查
103+ # elif [[ ! -f "$ssl_key_path" ]]; then
104+ # print_warning "找不到私钥文件: $ssl_key_path"
105+ # ssl_key_path=""
106+ fi
107+ done
108+
109+ # 构建 SSL 配置块
110+ ssl_config_block=$( cat << EOF
111+ # --- SSL 配置 ---
112+ ssl_certificate $ssl_cert_path ;
113+ ssl_certificate_key $ssl_key_path ;
114+
115+ # 推荐的 SSL 参数 (如果使用 Let's Encrypt, 可以包含它们的推荐配置)
116+ # include /etc/letsencrypt/options-ssl-nginx.conf; # 取消注释并确保此文件存在
117+ # ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # 取消注释并确保此文件存在
118+
119+ # 较强的加密套件和协议 (可以根据需要调整)
120+ ssl_protocols TLSv1.2 TLSv1.3;
121+ ssl_prefer_server_ciphers off;
122+ ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
123+ EOF
124+ )
125+ print_info " HTTPS 配置准备就绪。"
126+ else
127+ print_info " 已选择使用 HTTP (不推荐用于生产环境)。"
128+ fi
129+ echo
130+
131+ # 3. 生成 Nginx 配置内容
132+ print_info " 正在生成 Nginx 配置文件..."
133+
134+ # 使用 heredoc 创建配置文件内容
135+ nginx_config=$( cat << EOF
136+ server {
137+ $listen_directive
138+ server_name $server_name ;
139+
140+ $ssl_config_block
141+
142+ # 可选:设置更大的 client_max_body_size 以允许更大的请求体
143+ # client_max_body_size 10M;
144+
145+ # --- Gemini API 反向代理配置 ---
146+ location $proxy_location {
147+ # 代理目标地址 (末尾的 / 很重要)
148+ proxy_pass $TARGET_API_URL ;
149+
150+ # 设置必要的请求头
151+ proxy_set_header Host generativelanguage.googleapis.com;
152+ proxy_set_header X-Real-IP \$ remote_addr;
153+ proxy_set_header X-Forwarded-For \$ proxy_add_x_forwarded_for;
154+ proxy_set_header X-Forwarded-Proto \$ scheme;
155+ proxy_set_header Accept-Encoding ""; # 防止 Nginx 压缩与后端冲突
156+
157+ # SSL 相关配置 (与 HTTPS 后端通信)
158+ proxy_ssl_server_name on; # 必须开启,以支持 SNI
159+ # proxy_ssl_verify on; # 建议开启后端 SSL 证书验证 (可能需要配置 proxy_ssl_trusted_certificate)
160+ # proxy_ssl_trusted_certificate /etc/ssl/certs/ca-certificates.crt; # 根据系统调整路径
161+
162+ # 超时设置 (根据需要调整)
163+ # proxy_connect_timeout 60s;
164+ # proxy_send_timeout 60s;
165+ # proxy_read_timeout 60s;
166+
167+ # 处理流式响应 (如果 Gemini API 使用流式输出)
168+ proxy_buffering off; # 对于 SSE (Server-Sent Events) 可能需要关闭缓冲
169+ proxy_cache off; # 通常 API 代理不需要缓存
170+ proxy_http_version 1.1; # 建议使用 HTTP/1.1 与后端通信
171+ proxy_set_header Connection ""; # 清除 Connection 头
172+
173+ # --- API Key 处理 ---
174+ # !! 推荐方式:客户端提供 API Key !!
175+ # Nginx 默认会转发客户端的请求头 (如 x-goog-api-key) 和 URL 参数 (?key=...)
176+ # 客户端调用示例 (Header):
177+ # curl -H "x-goog-api-key: YOUR_API_KEY" ... http(s)://$server_name ${proxy_location} gemini-pro:generateContent
178+ # 客户端调用示例 (URL 参数):
179+ # curl ... "http(s)://$server_name ${proxy_location} gemini-pro:generateContent?key=YOUR_API_KEY"
180+
181+ # --- 不推荐:在 Nginx 中添加 API Key (有安全风险) ---
182+ # 如果您执意如此,并了解风险,可以取消注释下面这行,并替换 Key
183+ # proxy_set_header x-goog-api-key YOUR_ACTUAL_GEMINI_API_KEY;
184+ # 注意:请务必保护好此 Nginx 配置文件的访问权限!
185+ }
186+
187+ # 可选:根路径处理
188+ location / {
189+ # 可以返回一个简单的文本或 404
190+ return 403 "Forbidden";
191+ # 或者指向一个静态页面
192+ # root /var/www/html;
193+ # index index.html index.htm;
194+ }
195+
196+ # 日志文件路径
197+ access_log /var/log/nginx/${config_file_name} .access.log;
198+ error_log /var/log/nginx/${config_file_name} .error.log;
199+ }
200+ EOF
201+ )
202+
203+ # 4. 写入配置文件
204+ print_info " 正在将配置写入到: $config_file_path "
205+ echo " $nginx_config " > " $config_file_path "
206+ if [[ $? -ne 0 ]]; then
207+ print_error " 写入配置文件失败!请检查权限或磁盘空间。"
208+ exit 1
209+ fi
210+ print_info " 配置文件已成功创建。"
211+ echo
212+
213+ # 5. 创建符号链接
214+ print_info " 正在启用配置 (创建符号链接)..."
215+ # 使用 -f 强制覆盖可能存在的旧链接
216+ ln -sf " $config_file_path " " $link_path "
217+ if [[ $? -ne 0 ]]; then
218+ print_error " 创建符号链接失败!"
219+ exit 1
220+ fi
221+ print_info " 配置已启用: $link_path -> $config_file_path "
222+ echo
223+
224+ # 6. 完成与后续步骤
225+ print_info " --------------------------------------------------"
226+ print_info " 配置完成!"
227+ print_info " --------------------------------------------------"
228+ echo -e " ${YELLOW} 下一步操作:${NC} "
229+ echo -e " 1. ${GREEN} 测试 Nginx 配置语法:${NC} "
230+ echo -e " sudo nginx -t"
231+ echo
232+ echo -e " 2. ${GREEN} 如果测试成功 (显示 'syntax is ok' 和 'test is successful'),重新加载 Nginx 服务:${NC} "
233+ echo -e " sudo systemctl reload nginx"
234+ echo
235+ echo -e " 3. ${GREEN} 使用您的反向代理:${NC} "
236+ echo -e " 现在您可以通过以下 URL 访问 Gemini API (请将 'gemini-pro:generateContent' 替换为实际的模型和方法):"
237+ if [[ " $use_https " == " y" ]]; then
238+ echo -e " ${YELLOW} POST https://$server_name ${proxy_location} gemini-pro:generateContent${NC} "
239+ else
240+ echo -e " ${YELLOW} POST http://$server_name ${proxy_location} gemini-pro:generateContent${NC} "
241+ fi
242+ echo -e " ${YELLOW} 重要:${NC} 请确保在您的客户端请求中包含 Google API Key,通过 HTTP Header ('x-goog-api-key: YOUR_API_KEY') 或 URL 参数 ('?key=YOUR_API_KEY')。"
243+ echo
244+ print_warning " 请再次确认您的防火墙设置,确保端口 80 (HTTP) 和/或 443 (HTTPS) 已对外部开放。"
245+ print_info " 脚本执行完毕。"
246+
247+ exit 0
0 commit comments