Merge pull request #52 from svc-design/codex/render-openresty-configuration-templates

feat(openresty): template sites configs
This commit is contained in:
shenlan 2025-08-06 09:29:58 +08:00 committed by GitHub
commit a3743c1fc0
3 changed files with 167 additions and 59 deletions

View File

@ -25,12 +25,24 @@
state: present
update_cache: yes
- name: Ensure sites-available directory exists
file:
path: /usr/local/openresty/nginx/conf/sites-available
state: directory
- name: Deploy nginx configuration
template:
src: nginx.conf.j2
dest: /usr/local/openresty/nginx/conf/nginx.conf
notify: Restart OpenResty
- name: Deploy vhost configurations
template:
src: site.conf.j2
dest: "/usr/local/openresty/nginx/conf/sites-available/{{ item.name }}.conf"
loop: "{{ vhosts_openresty_vhosts | default([]) }}"
notify: Restart OpenResty
- name: Enable and start OpenResty
systemd:
name: openresty

View File

@ -1,62 +1,30 @@
worker_processes auto;
events { worker_connections 1024; }
worker_processes auto;
http {
lua_shared_dict limit_cache 10m;
{% for site in domain %}
server {
listen 80;
listen 443 ssl;
server_name {{ site.name }};
ssl_certificate {{ site.ssl_certificate }};
ssl_certificate_key {{ site.ssl_certificate_key }};
location /api/askai {
access_by_lua_block {
local redis = require "resty.redis"
local r = redis:new()
r:set_timeout(200)
-- 连接 Redis
local ok, err = r:connect("127.0.0.1", 6379)
if not ok then
ngx.log(ngx.ERR, "failed to connect to redis: ", err)
return ngx.exit(500)
end
-- 用户标识(优先 token 参数,否则用 IP
local user = ngx.var.arg_user or ngx.var.remote_addr
local today = os.date("%Y%m%d")
local user_key = "limit:user:" .. user .. ":" .. today
local global_key = "limit:global:" .. today
-- 用户限额 200
local current, err = r:incr(user_key)
if current == 1 then
r:expire(user_key, 86400)
end
if current > 200 then
ngx.status = 429
ngx.say("Too Many Requests: user limit reached")
return ngx.exit(429)
end
-- 全局限额 20000
local gcount, err = r:incr(global_key)
if gcount == 1 then
r:expire(global_key, 86400)
end
if gcount > 20000 then
ngx.status = 429
ngx.say("Too Many Requests: global limit reached")
return ngx.exit(429)
end
}
proxy_pass http://127.0.0.1:5000;
}
}
{% endfor %}
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
# 开启 Gzip (可选)
gzip on;
gzip_types text/plain text/css application/json application/javascript application/xml+rss;
# 定义日志格式(可选)
log_format main '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'$request_time';
# 全局访问日志
access_log /usr/local/openresty/nginx/logs/access.log main;
error_log /usr/local/openresty/nginx/logs/error.log warn;
# 引入 sites-available 下的配置
include /usr/local/openresty/nginx/conf/sites-available/*.conf;
}

View File

@ -0,0 +1,128 @@
lua_package_path "/usr/local/openresty/lualib/?.lua;;";
{% for sub in item.subdomains %}
{% if sub.type == 'artifact' %}
# {{ sub.server_name }} 文件下载服务
server {
listen 443 ssl http2;
server_name {{ sub.server_name }};
ssl_certificate {{ sub.ssl_certificate }};
ssl_certificate_key {{ sub.ssl_certificate_key }};
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
root {{ sub.root }};
index index.html;
autoindex on;
autoindex_exact_size off;
autoindex_localtime on;
location / {
add_header Accept-Ranges bytes;
try_files $uri $uri/ =404;
}
location ~* \.(dmg|zip|tar\.gz|deb|rpm|exe|pkg|AppImage|apk|ipa)$ {
expires 7d;
access_log off;
add_header Cache-Control "public";
add_header Accept-Ranges bytes;
try_files $uri =404;
}
location ~ /\. {
deny all;
}
}
{% else %}
# HTTP → HTTPS
server {
listen 80;
server_name {{ sub.server_name }};
return 301 https://{{ sub.server_name }}$request_uri;
}
# 主站服务
server {
listen 443 ssl http2;
server_name {{ sub.server_name }};
ssl_certificate {{ sub.ssl_certificate }};
ssl_certificate_key {{ sub.ssl_certificate_key }};
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
root {{ sub.root }};
index index.html;
{% if sub.askai_backend is defined %}
# /api/askai 限流:每用户每日 200 次
location = /api/askai {
access_by_lua_block {
local redis = require "resty.redis"
local r = redis:new()
r:set_timeout(200)
local ok, err = r:connect("127.0.0.1", 6379)
if not ok then
ngx.log(ngx.ERR, "failed to connect to redis: ", err)
return ngx.exit(500)
end
local user = ngx.var.arg_user or ngx.var.remote_addr
local today = os.date("%Y%m%d")
local user_key = "limit:user:" .. user .. ":" .. today
local current, err = r:incr(user_key)
if current == 1 then
r:expire(user_key, 86400)
end
if current > 200 then
ngx.status = 429
ngx.say("Too Many Requests: daily limit reached")
return ngx.exit(429)
end
}
proxy_pass {{ sub.askai_backend }};
proxy_http_version 1.1;
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;
}
{% endif %}
{% if sub.api_backend is defined %}
# 其他 API
location /api/ {
proxy_pass {{ sub.api_backend }};
proxy_http_version 1.1;
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;
}
{% endif %}
# SPA fallback
location / {
try_files $uri $uri/ /index.html;
}
# 静态资源缓存
location ~* \.(?:ico|css|js|gif|jpe?g|png|woff2?)$ {
expires 30d;
access_log off;
add_header Cache-Control "public";
}
# 隐藏 . 文件
location ~ /\. {
deny all;
}
}
{% endif %}
{% endfor %}