From acbdcd4efec4b3973ac0b122b4a9504c65cc06ea Mon Sep 17 00:00:00 2001 From: shenlan Date: Tue, 19 Aug 2025 12:47:17 +0800 Subject: [PATCH] refactor: split OpenResty vhost templates --- playbooks/deploy_openresty_vhosts.yml | 44 +++---- .../roles/vhosts/OpenResty/tasks/main.yml | 7 +- .../OpenResty/templates/artifact.conf.j2 | 35 +++++ .../OpenResty/templates/homepage.conf.j2 | 78 +++++++++++ .../vhosts/OpenResty/templates/panel.conf.j2 | 1 + .../vhosts/OpenResty/templates/site.conf.j2 | 124 ------------------ 6 files changed, 135 insertions(+), 154 deletions(-) create mode 100644 playbooks/roles/vhosts/OpenResty/templates/artifact.conf.j2 create mode 100644 playbooks/roles/vhosts/OpenResty/templates/homepage.conf.j2 create mode 100644 playbooks/roles/vhosts/OpenResty/templates/panel.conf.j2 delete mode 100644 playbooks/roles/vhosts/OpenResty/templates/site.conf.j2 diff --git a/playbooks/deploy_openresty_vhosts.yml b/playbooks/deploy_openresty_vhosts.yml index 3b4a76e..981f755 100644 --- a/playbooks/deploy_openresty_vhosts.yml +++ b/playbooks/deploy_openresty_vhosts.yml @@ -2,25 +2,21 @@ hosts: cn-homepage.svc.plus become: true vars: - domain: + vhosts: - name: cn-homepage.svc.plus + domain: + - www.svc.plus + - cn-homepage.svc.plus ssl_certificate: /etc/ssl/svc.plus.pem ssl_certificate_key: /etc/ssl/svc.plus.rsa.key + type: homepage - name: cn-artifact.svc.plus + domain: + - artifact.svc.plus + - cn-artifact.svc.plus ssl_certificate: /etc/ssl/svc.plus.pem ssl_certificate_key: /etc/ssl/svc.plus.rsa.key - - name: www.svc.plus - template: geo_redirect.conf.j2 - cn_target: cn-homepage.svc.plus - global_target: global-homepage.svc.plus - ssl_certificate: /etc/ssl/svc.plus.pem - ssl_certificate_key: /etc/ssl/svc.plus.rsa.key - - name: artifact.svc.plus - template: geo_redirect.conf.j2 - cn_target: cn-artifact.svc.plus - global_target: global-artifact.svc.plus - ssl_certificate: /etc/ssl/svc.plus.pem - ssl_certificate_key: /etc/ssl/svc.plus.rsa.key + type: artifact roles: - roles/vhosts/common/ - roles/vhosts/OpenResty/ @@ -28,25 +24,21 @@ hosts: global-homepage.svc.plus become: true vars: - domain: + vhosts: - name: global-homepage.svc.plus + domain: + - www.svc.plus + - global-homepage.svc.plus ssl_certificate: /etc/ssl/svc.plus.pem ssl_certificate_key: /etc/ssl/svc.plus.rsa.key + type: homepage - name: global-artifact.svc.plus + domain: + - artifact.svc.plus + - cn-artifact.svc.plus ssl_certificate: /etc/ssl/svc.plus.pem ssl_certificate_key: /etc/ssl/svc.plus.rsa.key - - name: www.svc.plus - template: geo_redirect.conf.j2 - cn_target: cn-homepage.svc.plus - global_target: global-homepage.svc.plus - ssl_certificate: /etc/ssl/svc.plus.pem - ssl_certificate_key: /etc/ssl/svc.plus.rsa.key - - name: artifact.svc.plus - template: geo_redirect.conf.j2 - cn_target: cn-artifact.svc.plus - global_target: global-artifact.svc.plus - ssl_certificate: /etc/ssl/svc.plus.pem - ssl_certificate_key: /etc/ssl/svc.plus.rsa.key + type: artifact roles: - roles/vhosts/common/ - roles/vhosts/OpenResty/ diff --git a/playbooks/roles/vhosts/OpenResty/tasks/main.yml b/playbooks/roles/vhosts/OpenResty/tasks/main.yml index aede025..40c6b76 100644 --- a/playbooks/roles/vhosts/OpenResty/tasks/main.yml +++ b/playbooks/roles/vhosts/OpenResty/tasks/main.yml @@ -65,11 +65,10 @@ - name: Deploy vhost configurations template: - # Use item.template if provided; - # otherwise default to the unified site template - src: "{{ item.template | default('site.conf.j2') }}" + # Use item.template if provided; otherwise select by vhost type + src: "{{ item.template | default(item.type ~ '.conf.j2') }}" dest: "/usr/local/openresty/nginx/conf/sites-available/{{ item.name }}.conf" - loop: "{{ domain | default([]) }}" + loop: "{{ vhosts | default([]) }}" notify: Restart OpenResty - name: Enable and start OpenResty diff --git a/playbooks/roles/vhosts/OpenResty/templates/artifact.conf.j2 b/playbooks/roles/vhosts/OpenResty/templates/artifact.conf.j2 new file mode 100644 index 0000000..435197b --- /dev/null +++ b/playbooks/roles/vhosts/OpenResty/templates/artifact.conf.j2 @@ -0,0 +1,35 @@ +server { + listen 443 ssl; + server_name {{ item.domain | join(' ') }}; + + ssl_certificate {{ item.ssl_certificate }}; + ssl_certificate_key {{ item.ssl_certificate_key }}; + ssl_protocols TLSv1.2 TLSv1.3; + ssl_ciphers HIGH:!aNULL:!MD5; + + root /data/update-server; + index index.html; + + 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; + } +} + +server { + listen 80; + server_name {{ item.domain | join(' ') }}; + return 301 https://$host$request_uri; +} diff --git a/playbooks/roles/vhosts/OpenResty/templates/homepage.conf.j2 b/playbooks/roles/vhosts/OpenResty/templates/homepage.conf.j2 new file mode 100644 index 0000000..30a6dbb --- /dev/null +++ b/playbooks/roles/vhosts/OpenResty/templates/homepage.conf.j2 @@ -0,0 +1,78 @@ +server { + listen 80; + server_name {{ item.domain | join(' ') }}; + return 301 https://$host$request_uri; +} + +server { + listen 443 ssl; + server_name {{ item.domain | join(' ') }}; + + ssl_certificate {{ item.ssl_certificate }}; + ssl_certificate_key {{ item.ssl_certificate_key }}; + ssl_protocols TLSv1.2 TLSv1.3; + ssl_ciphers HIGH:!aNULL:!MD5; + + root /var/www/XControl/ui/homepage/out; + index index.html; + + # /api/ 路径反向代理,不跳转 + location /api/ { + proxy_pass http://127.0.0.1:8080; + 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; + } + + # /api/askai 接口限流(基于 IP 或 user 参数) + 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, "Redis connect error: ", 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 key = "limit:user:" .. user .. ":" .. today + + local count, err = r:incr(key) + if count == 1 then r:expire(key, 86400) end + if count > 200 then + ngx.status = 429 + ngx.say("Too Many Requests: daily limit reached") + return ngx.exit(429) + end + } + + proxy_pass http://127.0.0.1:8080; + 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; + } + + # 页面请求:默认静态页面 + HTML5 history 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"; + } + + # 拒绝访问隐藏文件(如 .env) + location ~ /\. { + deny all; + } +} diff --git a/playbooks/roles/vhosts/OpenResty/templates/panel.conf.j2 b/playbooks/roles/vhosts/OpenResty/templates/panel.conf.j2 new file mode 100644 index 0000000..a813a2f --- /dev/null +++ b/playbooks/roles/vhosts/OpenResty/templates/panel.conf.j2 @@ -0,0 +1 @@ +# TODO: implement panel vhost template diff --git a/playbooks/roles/vhosts/OpenResty/templates/site.conf.j2 b/playbooks/roles/vhosts/OpenResty/templates/site.conf.j2 deleted file mode 100644 index c56910d..0000000 --- a/playbooks/roles/vhosts/OpenResty/templates/site.conf.j2 +++ /dev/null @@ -1,124 +0,0 @@ -{% if 'artifact' in item.name %} -{% set name = 'artifact.svc.plus' if 'artifact' in item.name else item.name %} -# {{ name }} 文件下载服务 -server { - listen 443 ssl http2; - server_name {{ name }}; - - ssl_certificate {{ item.ssl_certificate }}; - ssl_certificate_key {{ item.ssl_certificate_key }}; - ssl_protocols TLSv1.2 TLSv1.3; - ssl_ciphers HIGH:!aNULL:!MD5; - - root /data/update-server; - 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 %} -{% set name = item.name %} -lua_package_path "/usr/local/openresty/lualib/?.lua;;"; - -# HTTP → HTTPS -server { - listen 80; - server_name {{ name }}; - return 301 https://{{ name }}$request_uri; -} - -# 主站服务 -server { - listen 443 ssl http2; - server_name {{ name }}; - - ssl_certificate {{ item.ssl_certificate }}; - ssl_certificate_key {{ item.ssl_certificate_key }}; - ssl_protocols TLSv1.2 TLSv1.3; - ssl_ciphers HIGH:!aNULL:!MD5; - - root /var/www/XControl/ui/homepage/out; - index index.html; - - # /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 http://127.0.0.1:8080; - 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; - } - - # 其他 API - location /api/ { - proxy_pass http://127.0.0.1:8080; - 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; - } - - # 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 %}