summarylogtreecommitdiffstats
path: root/openjiuwen-web.nginx.conf
blob: 9e34051fc7af5fee0148ea9bfd634dada2714fa7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# /etc/nginx/sites-available/openjiuwen-web.conf
#
# OpenJiuwen Studio — nginx configuration sample.
#
# Enable:    sudo ln -s /etc/nginx/sites-available/openjiuwen-web.conf \
#                 /etc/nginx/sites-enabled/openjiuwen-web.conf
# Activate:  sudo nginx -t && sudo systemctl reload nginx
#
# This config serves the SPA from /usr/share/webapps/openjiuwen/ and
# proxies /api/* to the FastAPI backend (openjiuwen-server).

server {
    listen 8080;
    listen [::]:8080;
    server_name _;

    root /usr/share/webapps/openjiuwen;
    index index.html;

    # SPA fallback — React Router sends everything through index.html
    location / {
        try_files $uri $uri/ /index.html;
    }

    # Cache hashed Vite assets aggressively (their filenames include content hash)
    location ~* \.(?:js|css|woff2?|ttf|otf|eot|svg|png|jpe?g|gif|webp|ico)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
        access_log off;
    }

    # index.html must NOT be cached (it contains the hashed asset references)
    location = /index.html {
        add_header Cache-Control "no-cache, no-store, must-revalidate";
        expires 0;
    }

    # Proxy API + WebSocket to the backend (default uvicorn port 8186)
    location /api/ {
        proxy_pass http://127.0.0.1:8186/api/;
        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        "upgrade";
        proxy_read_timeout 300s;
        proxy_send_timeout 300s;
    }

    # Optional: gzip text assets (Vite already emits Brotli pre-compressed .br
    # files if you wire vite-plugin-compression; without them, gzip works)
    gzip on;
    gzip_vary on;
    gzip_min_length 1024;
    gzip_types text/plain text/css application/json application/javascript
               application/xml+rss application/atom+xml image/svg+xml;
}