Compare commits

..

4 Commits

Author SHA1 Message Date
xkrrudah 9029cf09e1 Merge pull request '[MR]Modified upstreams.map' (#4) from develop into main
Deploy Main / deploy-main (push) Successful in 8s
Reviewed-on: 07_web/error-page#4
2026-08-18 14:06:21 +09:00
xkrrudah 97bec6a651 Merge pull request '[MR]Modified upstreams.map' (#3) from develop into main
Deploy Main / deploy-main (push) Successful in 7s
Reviewed-on: 07_web/error-page#3
2026-08-15 21:15:41 +09:00
xkrrudah b603bfd608 Merge pull request '[MR]Modified distribution/upstreams' (#2) from develop into main
Deploy Main / deploy-main (push) Successful in 9s
Reviewed-on: 07_web/error-page#2
2026-08-15 20:02:22 +09:00
xkrrudah a5ee8ce5c5 Merge pull request '[MR]Added distribution' (#1) from develop into main
Deploy Main / deploy-main (push) Successful in 9s
Reviewed-on: 07_web/error-page#1
2026-08-15 19:58:58 +09:00
7 changed files with 37 additions and 54 deletions
+1 -2
View File
@@ -7,7 +7,7 @@ on:
workflow_dispatch: workflow_dispatch:
env: env:
DEPLOY_DIR: /volume1/09_container_manager/14_gateway DEPLOY_DIR: /volume1/09_container_manager/14_error-page
jobs: jobs:
deploy-main: deploy-main:
@@ -25,7 +25,6 @@ jobs:
cp docker-compose.yml "$DEPLOY_DIR/docker-compose.yml" cp docker-compose.yml "$DEPLOY_DIR/docker-compose.yml"
cp nginx.conf "$DEPLOY_DIR/nginx.conf" cp nginx.conf "$DEPLOY_DIR/nginx.conf"
cp upstreams.map "$DEPLOY_DIR/upstreams.map" cp upstreams.map "$DEPLOY_DIR/upstreams.map"
cp proxy_to_app.conf "$DEPLOY_DIR/proxy_to_app.conf"
cp html/index.html "$DEPLOY_DIR/html/index.html" cp html/index.html "$DEPLOY_DIR/html/index.html"
rm -f "$DEPLOY_DIR/html/preview.html" rm -f "$DEPLOY_DIR/html/preview.html"
+8 -9
View File
@@ -1,28 +1,28 @@
# gateway # error-page
`*.takits.me`가 컨테이너 다운(502/503/504)이거나 앱이 404/500을 줄 때, DSM 기본 에러창 대신 쓰는 공통 nginx 게이트웨이입니다. `*.takits.me`가 컨테이너 다운으로 502/503/504가 날 때, DSM 기본 에러창 대신 쓰는 공통 nginx.
DSM 리버스 프록시가 **앱 포트에 직접** 붙으면, 그 포트가 닫혀 있을 때 나스가 에러 페이지를 그립니다. 이 컨테이너는 항상 `127.0.0.1:4098`에서 떠 있고, `Host`로 실제 앱에 넘긴 뒤 업스트림이 죽었을 때만 공통 페이지를 보여 줍니다. DSM 리버스 프록시가 **앱 포트에 직접** 붙으면, 그 포트가 닫혀 있을 때 나스가 에러 페이지를 그립니다. 이 컨테이너는 항상 `127.0.0.1:4098`에서 떠 있고, `Host`로 실제 앱에 넘긴 뒤 업스트림이 죽었을 때만 공통 페이지를 보여 줍니다.
``` ```
브라우저 → DSM RP (HTTPS) → 127.0.0.1:4098 (gateway) 브라우저 → DSM RP (HTTPS) → 127.0.0.1:4098 (error-page)
└─ Host가 takits.me 이면 127.0.0.1:4889 └─ Host가 takits.me 이면 127.0.0.1:4889
``` ```
페이지 404/500과 게이트웨이 502/503/504는 공통 화면을 씁니다. `/api/` 404만 JSON 그대로 둡니다. 앱의 404/500은 가로채지 않습니다.
## 배포 ## 배포
`develop`에서 작업한 뒤 `main`에 머지하면 Gitea Actions가 아래 경로로 파일을 동기화하고 컨테이너를 재생성합니다. `develop`에서 작업한 뒤 `main`에 머지하면 Gitea Actions가 아래 경로로 파일을 동기화하고 컨테이너를 재생성합니다.
```text ```text
/volume1/09_container_manager/14_gateway /volume1/09_container_manager/14_error-page
``` ```
수동 실행: 수동 실행:
```bash ```bash
cd /volume1/09_container_manager/14_gateway cd /volume1/09_container_manager/14_error-page
docker compose up -d docker compose up -d
``` ```
@@ -47,7 +47,7 @@ curl -sI -H "Host: unknown.takits.me" http://127.0.0.1:4098/
한 줄 추가 후: 한 줄 추가 후:
```bash ```bash
docker exec gateway nginx -s reload docker exec error-page nginx -s reload
``` ```
와일드카드 `*.takits.me` → `127.0.0.1:4098` 한 규칙으로 모아도 됩니다. 맵에 없는 호스트는 공통 에러 페이지가 뜹니다. 와일드카드 `*.takits.me` → `127.0.0.1:4098` 한 규칙으로 모아도 됩니다. 맵에 없는 호스트는 공통 에러 페이지가 뜹니다.
@@ -57,6 +57,5 @@ docker exec gateway nginx -s reload
| 파일 | 역할 | | 파일 | 역할 |
|------|------| |------|------|
| `upstreams.map` | 호스트별 앱 포트 | | `upstreams.map` | 호스트별 앱 포트 |
| `html/index.html` | 404/500/502/503/504 페이지 | | `html/index.html` | 502/503/504 페이지 |
| `proxy_to_app.conf` | 앱으로 넘기는 프록시 설정 |
| `nginx.conf` | 프록시 + 에러 가로채기 | | `nginx.conf` | 프록시 + 에러 가로채기 |
+3 -4
View File
@@ -1,9 +1,9 @@
name: gateway name: error-page
services: services:
gateway: error-page:
image: nginx:alpine image: nginx:alpine
container_name: gateway container_name: error-page
restart: unless-stopped restart: unless-stopped
# Reach 127.0.0.1-bound app ports on the NAS (DSM reverse proxy style). # Reach 127.0.0.1-bound app ports on the NAS (DSM reverse proxy style).
network_mode: host network_mode: host
@@ -12,7 +12,6 @@ services:
volumes: volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro - ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./upstreams.map:/etc/nginx/upstreams.map:ro - ./upstreams.map:/etc/nginx/upstreams.map:ro
- ./proxy_to_app.conf:/etc/nginx/proxy_to_app.conf:ro
- ./html:/usr/share/nginx/html:ro - ./html:/usr/share/nginx/html:ro
healthcheck: healthcheck:
test: ["CMD", "wget", "-qO-", "http://127.0.0.1:4098/healthz"] test: ["CMD", "wget", "-qO-", "http://127.0.0.1:4098/healthz"]
+4 -1
View File
@@ -105,7 +105,10 @@
<p class="code">__STATUS__</p> <p class="code">__STATUS__</p>
<h1 class="title">__ERROR_TITLE__</h1> <h1 class="title">__ERROR_TITLE__</h1>
<p class="message">__ERROR_MESSAGE__</p> <p class="message">
We're working to resolve the issue.<br />
Please try again shortly.
</p>
</main> </main>
<footer>© 2026 takitsme. All rights reserved.</footer> <footer>© 2026 takitsme. All rights reserved.</footer>
</body> </body>
+19 -18
View File
@@ -20,18 +20,11 @@ http {
map $status $error_title { map $status $error_title {
default "Service Unavailable"; default "Service Unavailable";
404 "Not Found";
500 "Internal Server Error";
502 "Bad Gateway"; 502 "Bad Gateway";
503 "Service Unavailable"; 503 "Service Unavailable";
504 "Gateway Timeout"; 504 "Gateway Timeout";
} }
map $status $error_message {
default "We're working to resolve the issue.<br />Please try again shortly.";
404 "The page you're looking for could not be found.";
}
include /etc/nginx/upstreams.map; include /etc/nginx/upstreams.map;
server { server {
@@ -40,8 +33,6 @@ http {
root /usr/share/nginx/html; root /usr/share/nginx/html;
absolute_redirect off; absolute_redirect off;
client_max_body_size 5g;
proxy_request_buffering off;
location = /healthz { location = /healthz {
access_log off; access_log off;
@@ -49,29 +40,39 @@ http {
return 200 "ok\n"; return 200 "ok\n";
} }
error_page 404 500 502 503 504 /__error/index.html; error_page 502 503 504 /__error/index.html;
location = /__error/index.html { location = /__error/index.html {
internal; internal;
alias /usr/share/nginx/html/index.html;
sub_filter_once off; sub_filter_once off;
sub_filter_types text/html; sub_filter_types text/html;
sub_filter "__STATUS__" $status; sub_filter "__STATUS__" $status;
sub_filter "__ERROR_TITLE__" $error_title; sub_filter "__ERROR_TITLE__" $error_title;
sub_filter "__ERROR_MESSAGE__" $error_message;
sub_filter "__HOST__" $host; sub_filter "__HOST__" $host;
add_header Cache-Control "no-store" always; add_header Cache-Control "no-store" always;
add_header X-Content-Type-Options "nosniff" always; add_header X-Content-Type-Options "nosniff" always;
} }
# API 404 stays with the app so JSON clients keep working. location / {
location /api/ { if ($app_port = 0) {
error_page 500 502 503 504 /__error/index.html; return 502;
include /etc/nginx/proxy_to_app.conf;
} }
location / { proxy_pass http://127.0.0.1:$app_port;
include /etc/nginx/proxy_to_app.conf; 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;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_connect_timeout 3s;
proxy_send_timeout 3600s;
proxy_read_timeout 3600s;
# Only replace DSM-style "upstream down" pages. App 404/500 stay as-is.
proxy_intercept_errors on;
} }
} }
} }
-18
View File
@@ -1,18 +0,0 @@
if ($app_port = 0) {
return 502;
}
proxy_pass http://127.0.0.1:$app_port;
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;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_connect_timeout 3s;
proxy_send_timeout 3600s;
proxy_read_timeout 3600s;
proxy_intercept_errors on;
+1 -1
View File
@@ -1,7 +1,7 @@
# Host → published port on the NAS (the destination already used in DSM reverse proxy). # Host → published port on the NAS (the destination already used in DSM reverse proxy).
# 0 = unknown host → custom error page. # 0 = unknown host → custom error page.
# #
# After adding a line, reload: docker exec gateway nginx -s reload # After adding a line, reload: docker exec error-page nginx -s reload
# Then point that host's DSM reverse proxy to 127.0.0.1:4098 (not the app port). # Then point that host's DSM reverse proxy to 127.0.0.1:4098 (not the app port).
map $host $app_port { map $host $app_port {