From bb77a762008be92a0f4e447c9834bb0afc8887c1 Mon Sep 17 00:00:00 2001 From: nineap Date: Sat, 11 Jul 2026 02:26:39 +0700 Subject: [PATCH] =?UTF-8?q?Fix:=20nginx-=D0=BA=D0=BE=D0=BD=D1=84=D0=B8?= =?UTF-8?q?=D0=B3=20=D0=B4=D0=BB=D1=8F=20cms.netrunner-vpn.com=20+=20?= =?UTF-8?q?=D0=B7=D0=B0=D0=B4=D0=B2=D0=BE=D0=B5=D0=BD=D0=BD=D1=8B=D0=B9=20?= =?UTF-8?q?/cms-api/api/api/=20=D0=BD=D0=B0=20=D0=BF=D1=80=D0=BE=D0=B4?= =?UTF-8?q?=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - cms.netrunner-vpn.com не имел своего vhost на новом проде после переезда CMS с французского сервера — падал 502 (уходил в чужой server_name). Добавлены cms-http.conf/cms-ssl.conf (Basic Auth + сертификат), deploy-nginx.yml теперь синкает и их. - landing-ssl.conf: /cms-api/ проксировал в /api/ одним location, из-за чего запросы PocketBase SDK (уже содержащие /api/ после /cms-api/) задваивались в /api/api/... и 404-ились. Добавлен точный /cms-api/api/ location + общий fallback с rewrite — как было руками пропатчено на старом сервере, но не попало в репозиторий. --- .gitea/workflows/deploy-nginx.yml | 25 ++++++++++++++++++++++--- nginx/cms-http.conf | 20 ++++++++++++++++++++ nginx/cms-ssl.conf | 31 +++++++++++++++++++++++++++++++ nginx/landing-ssl.conf | 24 ++++++++++++++++++++---- 4 files changed, 93 insertions(+), 7 deletions(-) create mode 100644 nginx/cms-http.conf create mode 100644 nginx/cms-ssl.conf diff --git a/.gitea/workflows/deploy-nginx.yml b/.gitea/workflows/deploy-nginx.yml index 1b49c18..eba64d3 100644 --- a/.gitea/workflows/deploy-nginx.yml +++ b/.gitea/workflows/deploy-nginx.yml @@ -10,7 +10,14 @@ name: Deploy Nginx # sudo apt-get install -y certbot # sudo certbot certonly --webroot -w /var/www/certbot \ # -d netrunner-vpn.com +# sudo certbot certonly --webroot -w /var/www/certbot \ +# -d cms.netrunner-vpn.com +# sudo htpasswd -c /etc/nginx/.htpasswd # спросит пароль # 3. Запустить эту джобу ещё раз — включит HTTPS. +# +# cms.netrunner-vpn.com — прямой доступ к PocketBase (см. nginx/cms-ssl.conf), +# отдельно от /cms-api/ на основном домене, которым в рантайме пользуется сам +# лендинг. on: workflow_dispatch: @@ -27,7 +34,7 @@ jobs: host: ${{ vars.VPS_IP }} username: root key: ${{ secrets.SSH_PRIVATE_KEY }} - source: "nginx/landing-http.conf,nginx/landing-ssl.conf" + source: "nginx/landing-http.conf,nginx/landing-ssl.conf,nginx/cms-http.conf,nginx/cms-ssl.conf" target: "/root/netrunner-frontend" strip_components: 0 @@ -50,19 +57,31 @@ jobs: cp /root/netrunner-frontend/nginx/landing-http.conf /etc/nginx/sites-available/landing-http.conf cp /root/netrunner-frontend/nginx/landing-ssl.conf /etc/nginx/sites-available/landing-ssl.conf + cp /root/netrunner-frontend/nginx/cms-http.conf /etc/nginx/sites-available/cms-http.conf + cp /root/netrunner-frontend/nginx/cms-ssl.conf /etc/nginx/sites-available/cms-ssl.conf ln -sf /etc/nginx/sites-available/landing-http.conf /etc/nginx/sites-enabled/landing-http.conf + ln -sf /etc/nginx/sites-available/cms-http.conf /etc/nginx/sites-enabled/cms-http.conf CERT=/etc/letsencrypt/live/netrunner-vpn.com/fullchain.pem if [ -f "$CERT" ]; then ln -sf /etc/nginx/sites-available/landing-ssl.conf /etc/nginx/sites-enabled/landing-ssl.conf - echo "🔒 Сертификат найден — HTTPS-конфиг включён." + echo "🔒 Сертификат (netrunner-vpn.com) найден — HTTPS-конфиг включён." else rm -f /etc/nginx/sites-enabled/landing-ssl.conf echo "⚠️ Сертификата ещё нет ($CERT) — HTTPS-конфиг НЕ включён." fi + CMS_CERT=/etc/letsencrypt/live/cms.netrunner-vpn.com/fullchain.pem + if [ -f "$CMS_CERT" ]; then + ln -sf /etc/nginx/sites-available/cms-ssl.conf /etc/nginx/sites-enabled/cms-ssl.conf + echo "🔒 Сертификат (cms.netrunner-vpn.com) найден — HTTPS-конфиг включён." + else + rm -f /etc/nginx/sites-enabled/cms-ssl.conf + echo "⚠️ Сертификата для cms.netrunner-vpn.com ещё нет ($CMS_CERT) — HTTPS-конфиг НЕ включён." + fi + nginx -t systemctl enable --now nginx systemctl reload nginx - echo "✅ nginx (netrunner-vpn.com) synchronized." + echo "✅ nginx (netrunner-vpn.com + cms.netrunner-vpn.com) synchronized." diff --git a/nginx/cms-http.conf b/nginx/cms-http.conf new file mode 100644 index 0000000..f14431c --- /dev/null +++ b/nginx/cms-http.conf @@ -0,0 +1,20 @@ +# Часть 1/2 — до выпуска сертификата отдаёт только ACME-челлендж и редиректит +# остальное на https. Тот же паттерн, что landing-http.conf/account-http.conf. +# +# cms.netrunner-vpn.com — прямой доступ к PocketBase (админка + /api), +# отдельно от /cms-api/ на основном домене (см. landing-ssl.conf), которым +# пользуется сам лендинг в рантайме. Этот поддомен — для ручного +# администрирования через дашборд PocketBase, поэтому под Basic Auth. +server { + listen 80; + listen [::]:80; + server_name cms.netrunner-vpn.com; + + location /.well-known/acme-challenge/ { + root /var/www/certbot; + } + + location / { + return 301 https://$host$request_uri; + } +} diff --git a/nginx/cms-ssl.conf b/nginx/cms-ssl.conf new file mode 100644 index 0000000..288a3d6 --- /dev/null +++ b/nginx/cms-ssl.conf @@ -0,0 +1,31 @@ +# Часть 2/2 — деплой включает этот файл ТОЛЬКО когда сертификат уже есть +# (см. deploy-nginx.yml). Basic Auth на дашборд ("/"), сам REST API ("/api/") +# открыт без него — так же, как было на старом (французском) origin-сервере, +# откуда сюда перенесены данные PocketBase. +server { + listen 443 ssl; + listen [::]:443 ssl; + http2 on; + server_name cms.netrunner-vpn.com; + + ssl_certificate /etc/letsencrypt/live/cms.netrunner-vpn.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/cms.netrunner-vpn.com/privkey.pem; + + location /api/ { + proxy_pass http://127.0.0.1:8090; + 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; + } + + location / { + auth_basic "Restricted"; + auth_basic_user_file /etc/nginx/.htpasswd; + proxy_pass http://127.0.0.1:8090; + 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; + } +} diff --git a/nginx/landing-ssl.conf b/nginx/landing-ssl.conf index b632a61..1cdb39d 100644 --- a/nginx/landing-ssl.conf +++ b/nginx/landing-ssl.conf @@ -10,9 +10,16 @@ # # Три бэкенда за одним доменом: # / -> сам лендинг (Next.js, :3000) -# /cms-api/* -> PocketBase (:8090) — префикс "/cms-api" меняется на -# родной для PocketBase "/api" (см. PB_PUBLIC_URL в -# docker-compose.yml) +# /cms-api/* -> PocketBase (:8090). PB_PUBLIC_URL в docker-compose.yml = +# ".../cms-api" — сам PocketBase JS SDK достраивает к нему +# свой нативный "/api/..." (records, files и т.д.), так что +# реальные запросы всегда выглядят как "/cms-api/api/...". +# Один location с proxy_pass .../api/ тут НЕ работает: nginx +# отрезает только совпавший префикс "/cms-api/" и приклеивает +# остаток к ".../api/", получая задвоенное ".../api/api/..." +# (404 у PocketBase). Поэтому ниже два location: точный +# "/cms-api/api/" — рабочий случай SDK, и общий "/cms-api/" +# с rewrite — просто на случай прямых ссылок без "/api/". # /api/* -> proxy-ws (:3001) — его собственные роуты уже объявлены # с префиксом /api (comments, speedtest), никакой замены # префикса не нужно, только вебсокет-апгрейд заголовки @@ -25,7 +32,7 @@ server { ssl_certificate /etc/letsencrypt/live/account.netrunner-vpn.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/account.netrunner-vpn.com/privkey.pem; - location /cms-api/ { + location /cms-api/api/ { proxy_pass http://127.0.0.1:8090/api/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; @@ -33,6 +40,15 @@ server { proxy_set_header X-Forwarded-Proto $scheme; } + location /cms-api/ { + rewrite ^/cms-api/(.*) /$1 break; + proxy_pass http://127.0.0.1:8090; + 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; + } + location /api/ { proxy_pass http://127.0.0.1:3001; proxy_set_header Host $host;