
Gemma-3-12B-IT WebUI多租户教程Nginx反向代理JWT身份验证接入方案1. 项目背景与需求如果你已经成功部署了Gemma-3-12B-IT的WebUI可能会遇到一个很实际的问题怎么让团队里的其他同事也能安全地使用这个强大的AI助手直接开放端口显然不安全每个人单独部署一套又太浪费资源。这就是多租户接入要解决的问题。简单来说就是让一个Gemma-3服务能够安全、可控地服务多个用户。今天我要分享的方案就是用Nginx做反向代理加上JWT身份验证帮你搭建一个既安全又好用的多租户访问入口。这个方案有几个实实在在的好处安全性提升不再是裸奔的Web服务有了身份验证的门槛访问可控可以管理谁能访问、什么时候访问资源复用一套硬件服务整个团队成本更低维护简单所有用户都走同一个入口升级维护一次搞定2. 方案架构与核心组件2.1 整体架构设计先来看看我们搭建的系统长什么样用户浏览器 │ ▼ Nginx反向代理 (端口80/443) │ ┌─ JWT验证模块 │ └─ 路由转发 ▼ Gemma-3-12B-IT WebUI (端口7860)整个流程是这样的用户访问你的服务器地址Nginx拦截请求检查有没有有效的JWT令牌如果有合法令牌Nginx把请求转发给后端的Gemma-3服务如果没有令牌或令牌无效Nginx直接返回401错误2.2 核心组件介绍Nginx反向代理作用作为流量入口处理所有HTTP请求好处性能好、配置灵活、支持负载均衡我们的用法主要用它做身份验证和请求转发JWT身份验证JWT是什么JSON Web Token一种安全的身份验证方式怎么工作用户登录后获得一个加密的令牌每次请求都带上这个令牌优点无状态、可自包含、安全性好Gemma-3-12B-IT WebUI就是我们原来的服务运行在7860端口的聊天界面不需要修改我们的方案在前端做验证后端服务完全不用动3. 环境准备与安装3.1 检查现有环境首先确认你的Gemma-3服务已经正常运行# 检查服务状态 /root/gemma-3-webui/manage.sh status # 如果没运行先启动 /root/gemma-3-webui/manage.sh start # 测试访问 curl http://localhost:7860应该能看到正常的响应说明Gemma-3服务是好的。3.2 安装Nginx如果你的服务器还没有Nginx需要先安装# Ubuntu/Debian系统 sudo apt update sudo apt install nginx -y # CentOS/RHEL系统 sudo yum install epel-release -y sudo yum install nginx -y # 启动Nginx sudo systemctl start nginx sudo systemctl enable nginx # 检查状态 sudo systemctl status nginx安装完成后在浏览器访问你的服务器IP应该能看到Nginx的欢迎页面。3.3 安装JWT相关工具我们需要一个简单的JWT生成和验证服务。这里用Python写一个因为比较灵活# 创建JWT服务目录 mkdir -p /opt/jwt-auth cd /opt/jwt-auth # 创建虚拟环境 python3 -m venv venv source venv/bin/activate # 安装依赖 pip install pyjwt flask4. JWT身份验证服务搭建4.1 创建JWT服务代码在/opt/jwt-auth目录下创建app.pyfrom flask import Flask, request, jsonify import jwt import datetime from functools import wraps app Flask(__name__) # 配置信息 - 生产环境请使用更复杂的密钥 SECRET_KEY your-super-secret-key-change-this-in-production TOKEN_EXPIRE_HOURS 24 # 用户数据库简化版实际应该用数据库 USERS { admin: admin123, user1: password1, user2: password2 } def token_required(f): JWT验证装饰器 wraps(f) def decorated(*args, **kwargs): token request.headers.get(Authorization) if not token: return jsonify({error: Token is missing}), 401 try: # 去掉Bearer前缀 if token.startswith(Bearer ): token token[7:] # 验证令牌 data jwt.decode(token, SECRET_KEY, algorithms[HS256]) request.user data[username] except jwt.ExpiredSignatureError: return jsonify({error: Token has expired}), 401 except jwt.InvalidTokenError: return jsonify({error: Invalid token}), 401 return f(*args, **kwargs) return decorated app.route(/api/login, methods[POST]) def login(): 用户登录获取JWT令牌 data request.json username data.get(username) password data.get(password) if not username or not password: return jsonify({error: Username and password required}), 400 # 验证用户简化版 if username not in USERS or USERS[username] ! password: return jsonify({error: Invalid credentials}), 401 # 生成JWT令牌 token jwt.encode({ username: username, exp: datetime.datetime.utcnow() datetime.timedelta(hoursTOKEN_EXPIRE_HOURS) }, SECRET_KEY, algorithmHS256) return jsonify({ token: token, expires_in: TOKEN_EXPIRE_HOURS * 3600, username: username }) app.route(/api/verify, methods[GET]) token_required def verify_token(): 验证令牌有效性 return jsonify({ valid: True, username: request.user }) app.route(/api/users, methods[GET]) token_required def list_users(): 列出所有用户需要管理员权限 if request.user ! admin: return jsonify({error: Permission denied}), 403 return jsonify({ users: list(USERS.keys()), count: len(USERS) }) if __name__ __main__: app.run(host0.0.0.0, port5000, debugFalse)4.2 创建启动脚本创建/opt/jwt-auth/run.sh#!/bin/bash cd /opt/jwt-auth source venv/bin/activate nohup python app.py jwt-auth.log 21 echo $! jwt-auth.pid echo JWT Auth服务已启动PID: $(cat jwt-auth.pid)给脚本执行权限chmod x /opt/jwt-auth/run.sh4.3 启动JWT服务cd /opt/jwt-auth ./run.sh # 检查是否运行 ps aux | grep app.py curl http://localhost:5000/api/verify应该能看到{error:Token is missing}的响应说明服务正常运行。5. Nginx配置与反向代理设置5.1 配置Nginx反向代理现在来配置Nginx让它做两件事验证JWT令牌把合法请求转发给Gemma-3编辑Nginx配置文件sudo nano /etc/nginx/sites-available/gemma-proxy添加以下配置# Gemma-3多租户代理配置 server { listen 80; server_name your-server-domain.com; # 改成你的域名或IP # 静态文件缓存设置 location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ { expires 1y; add_header Cache-Control public, immutable; } # JWT验证接口 - 允许直接访问 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; # CORS设置 add_header Access-Control-Allow-Origin * always; add_header Access-Control-Allow-Methods GET, POST, OPTIONS always; add_header Access-Control-Allow-Headers DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization always; if ($request_method OPTIONS) { add_header Access-Control-Allow-Origin *; add_header Access-Control-Allow-Methods GET, POST, OPTIONS; add_header Access-Control-Allow-Headers DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization; add_header Access-Control-Max-Age 1728000; add_header Content-Type text/plain; charsetutf-8; add_header Content-Length 0; return 204; } } # 登录页面 - 不需要验证 location /login { alias /var/www/html/login; index index.html; } # Gemma-3 WebUI - 需要JWT验证 location / { # JWT验证 auth_request /validate; auth_request_set $auth_status $upstream_status; # 如果验证失败跳转到登录页 error_page 401 error401; # 代理到Gemma-3服务 proxy_pass http://127.0.0.1:7860; # WebSocket支持如果Gemma-3使用 proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection upgrade; # 传递必要的头信息 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 300s; proxy_send_timeout 300s; proxy_read_timeout 300s; } # JWT验证内部接口 location /validate { internal; proxy_pass http://127.0.0.1:5000/api/verify; proxy_pass_request_body off; proxy_set_header Content-Length ; proxy_set_header X-Original-URI $request_uri; proxy_set_header Authorization $http_authorization; } # 401错误处理 location error401 { return 302 /login; } # 健康检查 location /health { access_log off; return 200 healthy\n; add_header Content-Type text/plain; } }5.2 创建登录页面创建登录页面目录和文件sudo mkdir -p /var/www/html/login sudo nano /var/www/html/login/index.html添加简单的登录页面!DOCTYPE html html langzh-CN head meta charsetUTF-8 meta nameviewport contentwidthdevice-width, initial-scale1.0 titleGemma-3 登录/title style body { font-family: Arial, sans-serif; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); height: 100vh; display: flex; justify-content: center; align-items: center; margin: 0; } .login-container { background: white; padding: 40px; border-radius: 10px; box-shadow: 0 10px 40px rgba(0,0,0,0.1); width: 300px; } h2 { text-align: center; color: #333; margin-bottom: 30px; } .form-group { margin-bottom: 20px; } label { display: block; margin-bottom: 5px; color: #666; font-size: 14px; } input { width: 100%; padding: 10px; border: 1px solid #ddd; border-radius: 5px; font-size: 14px; box-sizing: border-box; } button { width: 100%; padding: 12px; background: #667eea; color: white; border: none; border-radius: 5px; font-size: 16px; cursor: pointer; transition: background 0.3s; } button:hover { background: #5a67d8; } .error { color: #e53e3e; font-size: 14px; margin-top: 10px; display: none; } .success { color: #38a169; font-size: 14px; margin-top: 10px; display: none; } /style /head body div classlogin-container h2Gemma-3 身份验证/h2 div classform-group label forusername用户名/label input typetext idusername placeholder输入用户名 /div div classform-group label forpassword密码/label input typepassword idpassword placeholder输入密码 /div button onclicklogin()登录/button div iderror classerror/div div idsuccess classsuccess/div /div script async function login() { const username document.getElementById(username).value; const password document.getElementById(password).value; const errorDiv document.getElementById(error); const successDiv document.getElementById(success); // 清空提示 errorDiv.style.display none; successDiv.style.display none; if (!username || !password) { errorDiv.textContent 请输入用户名和密码; errorDiv.style.display block; return; } try { const response await fetch(/api/login, { method: POST, headers: { Content-Type: application/json }, body: JSON.stringify({ username, password }) }); const data await response.json(); if (response.ok) { // 保存token到localStorage localStorage.setItem(gemma_token, data.token); localStorage.setItem(gemma_user, data.username); successDiv.textContent 登录成功正在跳转...; successDiv.style.display block; // 3秒后跳转到主页面 setTimeout(() { window.location.href /; }, 2000); } else { errorDiv.textContent data.error || 登录失败; errorDiv.style.display block; } } catch (error) { errorDiv.textContent 网络错误请稍后重试; errorDiv.style.display block; } } // 回车键登录 document.getElementById(password).addEventListener(keypress, function(e) { if (e.key Enter) { login(); } }); /script /body /html5.3 启用Nginx配置# 创建符号链接 sudo ln -s /etc/nginx/sites-available/gemma-proxy /etc/nginx/sites-enabled/ # 删除默认配置如果有 sudo rm /etc/nginx/sites-enabled/default # 测试配置 sudo nginx -t # 重启Nginx sudo systemctl restart nginx6. 客户端接入与使用6.1 创建客户端脚本为了让用户更方便地使用我们可以创建一个简单的客户端脚本。创建/var/www/html/login/gemma-client.js// Gemma-3客户端脚本 class GemmaClient { constructor() { this.token localStorage.getItem(gemma_token); this.username localStorage.getItem(gemma_user); this.init(); } init() { // 检查token if (!this.token) { this.redirectToLogin(); return; } // 验证token this.validateToken(); // 拦截所有请求添加Authorization头 this.interceptRequests(); } async validateToken() { try { const response await fetch(/api/verify, { headers: { Authorization: Bearer ${this.token} } }); if (!response.ok) { throw new Error(Token invalid); } } catch (error) { console.warn(Token验证失败:, error); this.redirectToLogin(); } } interceptRequests() { const originalFetch window.fetch; window.fetch async function(...args) { const [resource, config {}] args; // 如果是API请求添加token if (typeof resource string !resource.startsWith(/api/)) { config.headers { ...config.headers, Authorization: Bearer ${localStorage.getItem(gemma_token)} }; } return originalFetch(resource, config); }; // 处理XMLHttpRequest const originalOpen XMLHttpRequest.prototype.open; XMLHttpRequest.prototype.open function(...args) { originalOpen.apply(this, args); const originalSetRequestHeader this.setRequestHeader; this.setRequestHeader function(header, value) { if (header.toLowerCase() authorization !value) { value Bearer ${localStorage.getItem(gemma_token)}; } originalSetRequestHeader.call(this, header, value); }; }; } redirectToLogin() { localStorage.removeItem(gemma_token); localStorage.removeItem(gemma_user); window.location.href /login; } logout() { localStorage.removeItem(gemma_token); localStorage.removeItem(gemma_user); this.redirectToLogin(); } // 获取用户信息 async getUserInfo() { try { const response await fetch(/api/verify, { headers: { Authorization: Bearer ${this.token} } }); if (response.ok) { return await response.json(); } return null; } catch (error) { console.error(获取用户信息失败:, error); return null; } } } // 自动初始化 document.addEventListener(DOMContentLoaded, () { window.gemmaClient new GemmaClient(); // 添加登出按钮如果页面有id为logout-btn的元素 const logoutBtn document.getElementById(logout-btn); if (logoutBtn) { logoutBtn.addEventListener(click, () { window.gemmaClient.logout(); }); } // 显示当前用户 const userSpan document.getElementById(current-user); if (userSpan window.gemmaClient.username) { userSpan.textContent window.gemmaClient.username; } });6.2 用户使用流程现在用户的使用流程变得非常简单访问网站用户打开浏览器访问你的服务器地址跳转登录自动跳转到登录页面输入凭证输入用户名和密码比如user1/password1获得访问权登录成功后自动跳转到Gemma-3聊天界面正常使用像之前一样使用所有功能整个过程对用户来说是透明的他们只需要登录一次就可以正常使用了。6.3 测试完整流程我们来测试一下整个流程是否正常# 1. 测试JWT服务 curl -X POST http://localhost:5000/api/login \ -H Content-Type: application/json \ -d {username:user1,password:password1} # 应该返回类似 # {token:eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...,expires_in:86400,username:user1} # 2. 测试Nginx代理未登录 curl http://your-server-ip/ # 应该返回302重定向到/login # 3. 测试登录页面 curl http://your-server-ip/login # 应该返回登录页面的HTML # 4. 测试健康检查 curl http://your-server-ip/health # 应该返回healthy7. 高级功能与优化7.1 添加用户管理界面我们可以创建一个简单的用户管理界面方便管理员操作。创建/opt/jwt-auth/admin.html!DOCTYPE html html head title用户管理/title style body { font-family: Arial; padding: 20px; } .container { max-width: 800px; margin: 0 auto; } table { width: 100%; border-collapse: collapse; margin-top: 20px; } th, td { border: 1px solid #ddd; padding: 10px; text-align: left; } th { background: #f5f5f5; } .btn { padding: 8px 16px; margin: 5px; cursor: pointer; } .add-user { background: #4CAF50; color: white; border: none; } .logout { background: #f44336; color: white; border: none; } /style /head body div classcontainer h1用户管理/h1 button classbtn logout onclicklogout()退出登录/button button classbtn add-user onclickshowAddForm()添加用户/button div idaddForm styledisplay:none; margin:20px 0; padding:20px; border:1px solid #ddd; h3添加新用户/h3 input typetext idnewUsername placeholder用户名 input typepassword idnewPassword placeholder密码 button onclickaddUser()添加/button button onclickhideAddForm()取消/button /div table iduserTable thead tr th用户名/th th操作/th /tr /thead tbody/tbody /table /div script let token localStorage.getItem(gemma_token); if (!token) { alert(请先登录); window.location.href /login; } // 加载用户列表 async function loadUsers() { try { const response await fetch(/api/users, { headers: { Authorization: Bearer ${token} } }); if (response.status 403) { alert(需要管理员权限); return; } if (!response.ok) { throw new Error(加载失败); } const data await response.json(); renderUsers(data.users); } catch (error) { console.error(加载用户失败:, error); } } function renderUsers(users) { const tbody document.querySelector(#userTable tbody); tbody.innerHTML ; users.forEach(user { const tr document.createElement(tr); tr.innerHTML td${user}/td td button onclickresetPassword(${user})重置密码/button ${user ! admin ? button onclickdeleteUser(${user})删除/button : } /td ; tbody.appendChild(tr); }); } function showAddForm() { document.getElementById(addForm).style.display block; } function hideAddForm() { document.getElementById(addForm).style.display none; } async function addUser() { const username document.getElementById(newUsername).value; const password document.getElementById(newPassword).value; if (!username || !password) { alert(请输入用户名和密码); return; } // 这里需要实现添加用户的API alert(添加用户功能需要后端支持); // 实际实现时需要调用后端API添加用户 } function logout() { localStorage.removeItem(gemma_token); localStorage.removeItem(gemma_user); window.location.href /login; } // 页面加载时获取用户列表 loadUsers(); /script /body /html7.2 配置Nginx访问控制我们可以进一步细化访问控制比如限制访问频率、设置访问时间等。修改Nginx配置# 在server块内添加 # 限制请求频率 limit_req_zone $binary_remote_addr zonegemma_limit:10m rate10r/s; # 在location /块内添加 limit_req zonegemma_limit burst20 nodelay; # 限制连接数 limit_conn_zone $binary_remote_addr zoneaddr:10m; location / { limit_conn addr 5; # 每个IP最多5个连接 # ... 其他配置不变 } # 设置访问时间限制示例只允许工作时间访问 location / { # 周一到周五9点到18点允许访问 if ($time_local ~ ^(Mon|Tue|Wed|Thu|Fri)) { set $worktime 1; } if ($time_hour 9) { set $worktime ${worktime}0; } if ($time_hour 18) { set $worktime ${worktime}0; } if ($worktime 10) { return 403 服务只在工作日9:00-18:00开放; } # ... 其他配置不变 }7.3 添加监控和日志为了更好地了解使用情况我们可以添加访问日志# 在http块内添加日志格式 log_format gemma_log $remote_addr - $remote_user [$time_local] $request $status $body_bytes_sent $http_referer $http_user_agent $http_authorization; # 在server块内指定日志文件 access_log /var/log/nginx/gemma-access.log gemma_log; error_log /var/log/nginx/gemma-error.log;创建日志分析脚本/opt/jwt-auth/analyze_logs.sh#!/bin/bash LOG_FILE/var/log/nginx/gemma-access.log echo Gemma-3访问统计 echo 统计时间: $(date) echo # 总访问量 echo 1. 总访问次数: grep -c POST /api/login $LOG_FILE | awk {print 登录请求: $1 次} grep -c GET / $LOG_FILE | awk {print 主页访问: $1 次} echo echo 2. 最近24小时活跃用户: grep GET / $LOG_FILE | grep -o Bearer [^]* | cut -d -f2 | \ sort | uniq -c | sort -rn | head -10 | \ awk {print $2: $1 次} echo echo 3. 请求时间分布: awk {print substr($4,14,2)} $LOG_FILE | sort | uniq -c | \ awk {printf %2s时: %4d次\n, $2, $1} echo echo 4. 错误统计: grep -c 401 $LOG_FILE | awk {print 401未授权: $1 次} grep -c 403 $LOG_FILE | awk {print 403禁止访问: $1 次} grep -c 500 $LOG_FILE | awk {print 500服务器错误: $1 次}8. 安全加固与最佳实践8.1 安全配置建议1. 使用HTTPS# 使用Lets Encrypt获取免费SSL证书 sudo apt install certbot python3-certbot-nginx sudo certbot --nginx -d your-domain.com # 自动续期 sudo certbot renew --dry-run2. 强化JWT安全# 在生产环境中使用更强的密钥 import os SECRET_KEY os.environ.get(JWT_SECRET_KEY, os.urandom(32).hex()) # 添加更多验证 def token_required(f): wraps(f) def decorated(*args, **kwargs): token request.headers.get(Authorization) if not token: return jsonify({error: Token is missing}), 401 # 检查token格式 if not token.startswith(Bearer ): return jsonify({error: Invalid token format}), 401 token token[7:] # 检查token长度 if len(token) 50: return jsonify({error: Token too short}), 401 try: data jwt.decode(token, SECRET_KEY, algorithms[HS256]) # 检查过期时间 if datetime.datetime.utcnow() datetime.datetime.fromtimestamp(data[exp]): return jsonify({error: Token expired}), 401 # 检查用户是否存在 if data[username] not in USERS: return jsonify({error: User not found}), 401 request.user data[username] except jwt.ExpiredSignatureError: return jsonify({error: Token has expired}), 401 except jwt.InvalidTokenError: return jsonify({error: Invalid token}), 401 return f(*args, **kwargs) return decorated3. 添加速率限制from flask_limiter import Limiter from flask_limiter.util import get_remote_address limiter Limiter( appapp, key_funcget_remote_address, default_limits[100 per day, 10 per hour] ) app.route(/api/login, methods[POST]) limiter.limit(5 per minute) # 登录接口限制 def login(): # ... 原有代码8.2 数据库集成可选对于正式环境建议使用数据库存储用户信息。这里以SQLite为例import sqlite3 from werkzeug.security import generate_password_hash, check_password_hash def init_db(): conn sqlite3.connect(/opt/jwt-auth/users.db) c conn.cursor() c.execute( CREATE TABLE IF NOT EXISTS users ( id INTEGER PRIMARY KEY AUTOINCREMENT, username TEXT UNIQUE NOT NULL, password_hash TEXT NOT NULL, email TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, last_login TIMESTAMP, is_active BOOLEAN DEFAULT 1 ) ) # 创建初始管理员用户 admin_hash generate_password_hash(admin123) c.execute(INSERT OR IGNORE INTO users (username, password_hash) VALUES (?, ?), (admin, admin_hash)) conn.commit() conn.close() # 修改登录验证 def verify_user(username, password): conn sqlite3.connect(/opt/jwt-auth/users.db) c conn.cursor() c.execute(SELECT password_hash FROM users WHERE username ? AND is_active 1, (username,)) result c.fetchone() conn.close() if result and check_password_hash(result[0], password): return True return False9. 故障排查与维护9.1 常见问题解决问题1无法访问登录页面# 检查Nginx配置 sudo nginx -t # 检查Nginx状态 sudo systemctl status nginx # 检查端口监听 sudo netstat -tlnp | grep :80 # 查看错误日志 sudo tail -f /var/log/nginx/error.log问题2登录成功但无法访问Gemma-3# 检查Gemma-3服务 /root/gemma-3-webui/manage.sh status # 检查JWT服务 ps aux | grep app.py # 测试JWT验证 curl -H Authorization: Bearer YOUR_TOKEN http://localhost/api/verify # 查看Nginx访问日志 sudo tail -f /var/log/nginx/gemma-access.log问题3性能问题# 查看系统资源 top htop # 查看Gemma-3内存使用 ps aux | grep gemma | grep -v grep # 优化Nginx配置 # 调整worker_processes为CPU核心数 # 调整worker_connections9.2 日常维护命令创建维护脚本/opt/jwt-auth/maintenance.sh#!/bin/bash case $1 in status) echo 服务状态 echo 1. Nginx: sudo systemctl status nginx --no-pager | grep Active echo echo 2. JWT Auth: if [ -f /opt/jwt-auth/jwt-auth.pid ]; then pid$(cat /opt/jwt-auth/jwt-auth.pid) if ps -p $pid /dev/null; then echo 运行中 (PID: $pid) else echo 未运行 fi else echo 未运行 fi echo echo 3. Gemma-3: /root/gemma-3-webui/manage.sh status ;; restart) echo 重启所有服务... sudo systemctl restart nginx cd /opt/jwt-auth ./run.sh /root/gemma-3-webui/manage.sh restart echo 服务重启完成 ;; logs) echo 最近日志 echo 1. Nginx错误日志: sudo tail -20 /var/log/nginx/error.log echo echo 2. Nginx访问日志: sudo tail -20 /var/log/nginx/gemma-access.log echo echo 3. JWT服务日志: tail -20 /opt/jwt-auth/jwt-auth.log echo echo 4. Gemma-3日志: /root/gemma-3-webui/manage.sh logs | tail -20 ;; backup) echo 备份配置... backup_dir/opt/backup/$(date %Y%m%d_%H%M%S) mkdir -p $backup_dir # 备份Nginx配置 sudo cp -r /etc/nginx/sites-available/ $backup_dir/ sudo cp -r /etc/nginx/sites-enabled/ $backup_dir/ # 备份JWT服务 cp -r /opt/jwt-auth/*.py $backup_dir/ cp -r /opt/jwt-auth/*.sh $backup_dir/ # 备份用户数据 if [ -f /opt/jwt-auth/users.db ]; then cp /opt/jwt-auth/users.db $backup_dir/ fi echo 备份完成: $backup_dir ;; *) echo 用法: $0 {status|restart|logs|backup} exit 1 ;; esac10. 总结通过这个Nginx反向代理JWT身份验证的方案我们成功实现了Gemma-3-12B-IT WebUI的多租户安全接入。现在你的团队可以安全、可控地共享这个强大的AI助手了。主要成果安全访问控制只有授权用户才能使用Gemma-3用户管理可以方便地添加、管理用户访问监控能够查看使用情况和统计信息无缝体验用户只需要登录一次后续使用无感易于维护所有配置集中管理升级维护方便后续优化建议集成LDAP或OAuth对接现有用户系统添加使用配额限制防止资源滥用实现更细粒度的权限控制如只读、读写权限添加操作审计日志满足合规要求考虑负载均衡支持更多并发用户这个方案不仅适用于Gemma-3任何需要多用户安全访问的Web服务都可以参考这个架构。希望这个教程能帮助你更好地管理和使用AI资源获取更多AI镜像想探索更多AI镜像和应用场景访问 CSDN星图镜像广场提供丰富的预置镜像覆盖大模型推理、图像生成、视频生成、模型微调等多个领域支持一键部署。