Skip to content

Nginx 完整配置参考 ​

生成日期:2026-09-16
用途:客户现场入口 Nginx。location 按产品统一模板 locations-ruoyi-office.inc 裁剪:根路径进管理端,不含文档站 / CI / 天气网关 / 体验包。Windows 路径见 Windows 部署。

各手册里的「最小配置」只保证能打开 /web 并登录。下面是与演示站同一套路径约定的完整 server 块。

落地前必改 ​

  1. server_name 改成现场域名或入口 IP。
  2. 所有 proxy_pass 里的 127.0.0.1:48080:宿主机 Nginx 保持本机;Compose 内改 yudao-server:48080;微服务改 gateway-server:48080。不要剥掉 /admin-api、/app-api 前缀。
  3. 模板里静态目录是容器路径 /usr/share/nginx/html/...。宿主机 Nginx 改成 /data/nginx/html/...;宝塔常见 /www/wwwroot/ruoyi-office/web/。
  4. 未部署的能力整段删除(/mall、/goview、积木、OnlyOffice、LiveKit)。
  5. 积木必须同时保留 /web/jmreport + /jmreport、/web/drag + /drag。生产包 VITE_BASE_URL=/web,iframe 第一跳是 /web/jmreport/list;设计器内部资源走根路径 /jmreport/。只留其中一对,iframe 会变成管理端首页或 JS 404。
  6. 改完 nginx -t && nginx -s reload。已有 default.conf 同时听 80 时先关掉。

$connection_upgrade 必须写在 http { } 里(与 server 平级),OnlyOffice / LiveKit 的 WebSocket 要用。积木 / WebSocket location 必须与 location /web 平级,不要嵌进 /web { }。

路径一览 ​

浏览器路径作用是否必配
/302 到 /web/必配
/webPC 管理端静态(Vben)必配
/admin-api管理端 API必配
/infra/ws、/web/infra/ws实时消息 WebSocket必配
/app、/app-apiUniApp H5 + 移动端 API有移动端时必配
/mall商城 H5(history 路由,接口走 /app-api)合同含商城时
/goviewGoView 大屏合同含大屏时
/web/jmreport、/web/drag 与 /jmreport、/drag积木报表 / 仪表盘(两套前缀都要)用报表时
/onlyoffice/、/cache/、/coauthoring/OnlyOffice合同含在线编辑时
/livekit/IM 音视频信令启用通话时
/healthNginx 探活建议

OnlyOffice 同 Compose 网络用服务名 onlyoffice-documentserver。LiveKit 媒体口 7881/7882(TCP/UDP)不走 Nginx,需对客户端放行。

http 级(与 server 平级) ​

nginx
map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}

完整配置(HTTP) ​

放到 /data/nginx/conf/conf.d/ruoyi-office.conf(或宝塔 vhost/nginx/)。80 / 443 可把下面 server 内 location 抽成 .inc,两边 include,与演示站 ruoyi-office.conf 同一做法。

nginx
server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name _;   # 改成现场域名或入口 IP

    charset utf-8;
    # 合同模板、附件经 /admin-api/infra/file/upload 走后端;默认 1m 会被 Nginx 直接断开
    client_max_body_size 100m;
    access_log /var/log/nginx/ruoyi-office-access.log;
    error_log /var/log/nginx/ruoyi-office-error.log;

    gzip on;
    gzip_vary on;
    gzip_min_length 1024;
    gzip_comp_level 6;
    gzip_types text/plain text/css text/xml text/javascript
               application/json application/javascript application/xml+rss
               application/x-javascript image/svg+xml;
    gzip_static on;

    location ~ /\. {
        deny all;
        access_log off;
        log_not_found off;
    }

    # Let's Encrypt HTTP-01(certbot webroot 时保留)
    location ^~ /.well-known/acme-challenge/ {
        root /usr/share/nginx/html/acme;
        default_type text/plain;
    }

    location = / {
        return 302 /web/;
    }

    # 企业云盘独立编辑页:旧入口 window.open("/oa/cloud/file-editor?...") 会打到站点根。
    # 生产为 hash 路由 + /web 子路径。Location 中 # 必须用引号。
    location = /oa/cloud/file-editor {
        return 302 "/web/#/oa/cloud/file-editor$is_args$args";
    }

    # ========================================
    # Vben Admin(/web 子路径)
    # ========================================
    location /web {
        alias /usr/share/nginx/html/web;
        index index.html;
        # 使用 alias 时,try_files 的路径相对 alias 目录
        try_files $uri $uri/ /web/index.html;
    }

    location ~* ^/web/(.+)\.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2|ttf|eot|map)$ {
        root /usr/share/nginx/html;
        expires 30d;
        add_header Cache-Control "public, immutable";
        access_log off;
    }

    location ~ ^/web/\. {
        deny all;
        access_log off;
        log_not_found off;
    }

    # ========================================
    # WebSocket
    # ========================================
    # 后端实际路径为 /infra/ws。
    # /web/infra/ws 兼容旧版前端错误拼接,避免被 /web 静态站拦截。
    location ^~ /infra/ws {
        proxy_pass http://127.0.0.1:48080/infra/ws;
        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_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_read_timeout 3600s;
        proxy_send_timeout 3600s;
        proxy_buffering off;
    }

    location ^~ /web/infra/ws {
        proxy_pass http://127.0.0.1:48080/infra/ws;
        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_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_read_timeout 3600s;
        proxy_send_timeout 3600s;
        proxy_buffering off;
    }

    # ========================================
    # UniApp H5(/app)
    # ========================================
    location /app {
        alias /usr/share/nginx/html/app;
        index index.html;
        try_files $uri $uri/ /app/index.html;
    }

    location ~* ^/app/(.+)\.(jpg|jpeg|png|gif|ico|css|js|mjs|svg|woff|woff2|ttf|eot|map|json|mp3|mp4|webm|ogg|wav|flac|aac)$ {
        root /usr/share/nginx/html;
        expires 30d;
        add_header Cache-Control "public, immutable";
        access_log off;
    }

    location ~ ^/app/\. {
        deny all;
        access_log off;
        log_not_found off;
    }

    # ========================================
    # 商城 H5(/mall,未部署可整段删除)
    # ========================================
    # 商城为 history 路由;接口前缀 /app-api(见下方)。
    location /mall {
        alias /usr/share/nginx/html/mall;
        index index.html;
        try_files $uri $uri/ /mall/index.html;
    }

    location ~* ^/mall/(.+)\.(jpg|jpeg|png|gif|ico|css|js|mjs|svg|woff|woff2|ttf|eot|map|json|mp3|mp4|webm|ogg|wav|flac|aac)$ {
        root /usr/share/nginx/html;
        expires 30d;
        add_header Cache-Control "public, immutable";
        access_log off;
    }

    location ~ ^/mall/\. {
        deny all;
        access_log off;
        log_not_found off;
    }

    # ========================================
    # GoView(/goview,未部署可整段删除)
    # ========================================
    location /goview {
        alias /usr/share/nginx/html/goview;
        index index.html;
        try_files $uri $uri/ /goview/index.html;
    }

    location ~* ^/goview/(.+)\.(jpg|jpeg|png|gif|ico|css|js|mjs|svg|woff|woff2|ttf|eot|map|json|mp3|mp4|webm|ogg|wav|flac|aac)$ {
        root /usr/share/nginx/html;
        expires 30d;
        add_header Cache-Control "public, immutable";
        access_log off;
    }

    location ~ ^/goview/\. {
        deny all;
        access_log off;
        log_not_found off;
    }

    # ========================================
    # 积木报表(后端 iframe)
    # ========================================
    # 必须同时代理 /web/jmreport(当前前端 VITE_BASE_URL=/web)和 /jmreport(设计器内部资源)。
    # 缺 /web/jmreport 时,/web 的 try_files 把 /web/jmreport/list 回成 index.html,iframe 里是管理端首页。
    location /web/jmreport {
        proxy_pass http://127.0.0.1:48080/jmreport;
        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 /web/drag {
        proxy_pass http://127.0.0.1:48080/drag;
        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 /jmreport {
        proxy_pass http://127.0.0.1:48080/jmreport;
        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 /drag {
        proxy_pass http://127.0.0.1:48080/drag;
        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;
    }

    # ========================================
    # OnlyOffice(未采购可整段删除)
    # ========================================
    # Compose 同网络把 127.0.0.1:8081 换成 onlyoffice-documentserver。
    # X-Forwarded-Host 必须带 /onlyoffice 后缀,否则 DS 下发根路径 /cache,被 SPA 接走。
    # Connection 走 map:非 WebSocket 不能写死 upgrade。
    location /onlyoffice/ {
        proxy_pass http://127.0.0.1:8081/;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        proxy_set_header Host $http_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 X-Forwarded-Host $http_host/onlyoffice;
        proxy_connect_timeout 300s;
        proxy_send_timeout 300s;
        proxy_read_timeout 300s;
        client_max_body_size 100m;
        proxy_buffering off;
    }

    location /cache/ {
        proxy_pass http://127.0.0.1:8081/cache/;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        proxy_set_header Host $http_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_connect_timeout 300s;
        proxy_send_timeout 300s;
        proxy_read_timeout 300s;
        client_max_body_size 100m;
        proxy_buffering off;
    }

    location /coauthoring/ {
        proxy_pass http://127.0.0.1:8081/coauthoring/;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        proxy_set_header Host $http_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_connect_timeout 300s;
        proxy_send_timeout 300s;
        proxy_read_timeout 300s;
        proxy_buffering off;
    }

    # ========================================
    # LiveKit 信令(未启用可整段删除)
    # ========================================
    # 浏览器 / App:wss://<入口>/livekit ;媒体 UDP/TCP 不走 Nginx
    location ^~ /livekit/ {
        proxy_pass http://127.0.0.1:7880/;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        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_read_timeout 3600s;
        proxy_send_timeout 3600s;
        proxy_buffering off;
    }

    location = /livekit {
        return 301 /livekit/;
    }

    # ========================================
    # 后端 API(不要剥掉前缀)
    # ========================================
    location /admin-api {
        proxy_pass http://127.0.0.1:48080/admin-api;
        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_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_connect_timeout 60s;
        proxy_send_timeout 300s;
        proxy_read_timeout 300s;
        client_max_body_size 100m;
        proxy_request_buffering off;
        proxy_buffer_size 64k;
        proxy_buffers 4 64k;
        proxy_busy_buffers_size 128k;
    }

    location /app-api {
        proxy_pass http://127.0.0.1:48080/app-api;
        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_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_connect_timeout 60s;
        proxy_send_timeout 300s;
        proxy_read_timeout 300s;
        client_max_body_size 100m;
        proxy_request_buffering off;
        proxy_buffer_size 64k;
        proxy_buffers 4 64k;
        proxy_busy_buffers_size 128k;
    }

    location /health {
        access_log off;
        return 200 "healthy\n";
        add_header Content-Type text/plain;
    }

    error_page 500 502 503 504 /50x.html;
    location = /50x.html {
        root /usr/share/nginx/html;
    }
}
bash
sudo nginx -t && sudo nginx -s reload
# Docker 内的 Nginx:
# sudo docker exec nginx nginx -t && sudo docker exec nginx nginx -s reload

宝塔若在「伪静态」里又写了 try_files ... /index.html,会把 /web/jmreport 打回首页。伪静态不要覆盖积木这两个前缀。

HTTPS ​

证书放到约定目录后,再加一个 listen 443 ssl 的 server,location 与上面完全相同。推荐抽 .inc 后 80 / 443 各 include 一次。

nginx
server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name oa.example.com;

    ssl_certificate     /data/nginx/ssl/oa.example.com/fullchain.pem;
    ssl_certificate_key /data/nginx/ssl/oa.example.com/privkey.pem;
    ssl_protocols       TLSv1.2 TLSv1.3;
    ssl_session_cache   shared:SSL:10m;
    ssl_session_timeout 1d;

    include /etc/nginx/conf.d/locations-ruoyi-office.inc;
}

Nginx 1.25.1+ 也可写成 listen 443 ssl; + http2 on;。

切 HTTPS 后同步改:文件配置「自定义域名」、OnlyOffice server-url、UniApp 绝对 URL、LiveKit livekit-url(wss://<入口>/livekit)。见 域名、存储与 OnlyOffice。

形态差异 ​

形态proxy_pass 上游静态目录
宿主机 Nginx + JARhttp://127.0.0.1:48080/data/nginx/html/...
Compose 内 Nginxhttp://yudao-server:48080容器 /usr/share/nginx/html/...
微服务http://gateway-server:48080同上;不要剥掉 /admin-api
宝塔http://127.0.0.1:48080/www/wwwroot/ruoyi-office/web/ 等
Windowshttp://127.0.0.1:48080C:/ruoyi-office/app/web/,见 Windows 部署

OnlyOffice 与后端必须在同一入口域名下;X-Forwarded-Host 带 /onlyoffice 后缀,并反代 /cache/、/coauthoring/。排障见 域名、存储与 OnlyOffice。

LiveKit:yudao.im.rtc.livekit-url 填 wss://<入口>/livekit;livekit-api-url 填服务端直连(如 http://127.0.0.1:7880)。

验证 ​

检查项命令 / 地址预期
语法nginx -tsyntax is ok
根路径浏览器打开 http://<入口>/跳到 /web/ 登录页
API登录,网络面板 /admin-api 无 502进入首页
上传管理端传 >1MB 附件成功;失败先看 client_max_body_size
WebSocket登录后消息/待办能实时刷新无一直 404 的 /infra/ws
积木报表(若有)curl -sI http://<入口>/web/jmreport/list不是管理端 index.html;nginx -T 同时有 /web/jmreport 和 /jmreport
OnlyOffice(若有)打开一份 docx不报 Editor.bin / 扩展名不匹配
LiveKit(若有)curl -sI http://<入口>/livekit/200;通话能进房

首次登录验收仍按对应部署手册勾选,然后进入 上线文档。

联系我们

获取报价、演示和二开方案

微信咨询二维码

微信咨询

17156169080

添加时备注「RuoYi Office」

在线体验商业版