# Nginx

本頁說明 `config/nginx/nodejs.conf` 的路由區塊、快取設定、安全標頭，以及如何限制上傳與刪除的來源 IP。

## 路由區塊

| `location` | 上游 | 行為 |
|---|---|---|
| `~ /\.` | — | `deny all`，拒絕任何含 `/.` 的路徑（含 `.trash`） |
| `~* ^/c/img/` | `http://nodejs:8080` | 啟用 `proxy_cache`，逾時 120 秒 |
| `~* ^/upload/` | `http://nodejs:3000` | `proxy_no_cache 1`、`proxy_cache_bypass 1` |
| `~* ^/del/` | `http://nodejs:3000` | 不快取 |
| `/` | `http://nodejs:3000` | 不快取 |

## 快取設定

| 指令 | 值 |
|---|---|
| `proxy_cache_path` | `/var/cache/nginx/images`，`levels=1:2`，`keys_zone=images_cache:10m`，`max_size=2g`，`inactive=30d` |
| `proxy_cache_valid` | `200 302 301 304` 7 天，其他 1 分鐘 |
| `proxy_cache_use_stale` | `error timeout updating http_500 http_502 http_503 http_504` |
| `proxy_cache_lock`、`proxy_cache_revalidate`、`proxy_cache_background_update` | `on` |
| 回應標頭 | `X-Cache-Status`、`Cache-Control: public, max-age=604800`、`expires 7d` |
| gzip | `image/webp image/jpeg image/png image/svg+xml image/avif application/pdf`，等級 6，最小 1000 bytes |

```bash
# 檢查快取命中（HIT / MISS / EXPIRED）
curl -sI "http://localhost:8080/c/img/blog/a.jpg?w=800" | grep -i x-cache-status
```

## 安全設定

| 設定 | 值 |
|---|---|
| `server_tokens` | `off`，並以 `proxy_hide_header` 隱藏 `X-Powered-By` 等框架標頭 |
| HTTP 方法 | `GET HEAD POST DELETE PUT OPTIONS` 以外回 `444` |
| 上傳大小 | `client_max_body_size 100M` |
| `server` 層標頭 | `X-Content-Type-Options`、`X-Frame-Options`、`X-XSS-Protection`、`Referrer-Policy`、`Permissions-Policy`、`Content-Security-Policy` |

## 限制上傳與刪除的來源

`/upload/` 與 `/del/` 區塊內已預留註解，取消註解並改成自己的內網 IP：

```nginx
location ~* ^/upload/ {
    allow 10.0.0.0/8;
    deny all;

    proxy_pass http://nodejs:8080;
    # ...
}
```

修改後重新載入：

```bash
docker compose exec nginx nginx -s reload
```
