NginX Server Key Configurations
Reference
NginX forwards requests to XWiki with the proxy_pass directive of its proxy module. The directives below are the ones a wiki needs; Configure NginX Server as a Proxy on a Linux OS and Configure NginX Server as a Proxy on a Windows OS assemble them into a complete server block, and Configure HTTPS for the NginX HTTP Proxy Server adds the HTTPS ones. The Apache Server Key Configurations page documents the equivalent Apache HTTP Server directives.
Server Block Directives
These go in the server block that serves the wiki.
| Directive | What it does |
|---|---|
| listen 80 | The port this server block answers on, 80 being the default for plain HTTP. See listen. |
| server_name localhost | The host name this block answers for. Set it to the wiki's public domain, for example server_name wiki.example.com;. A request whose Host header matches no server_name reaches the server's default site instead, which is what answers with NginX's welcome page. See server_name. |
access_log /var/log/nginx/xwiki-access.log; and error_log /var/log/nginx/xwiki-error.log; | Optional per-wiki log files, so that proxy problems can be told apart from the rest of the server's traffic. See access_log. |
| client_max_body_size 0 | Removes the limit on the size of a request body, 1m by default, which otherwise makes NginX answer 413 for an attachment upload or a XAR import larger than that. See client_max_body_size. |
location = / { return 301 /xwiki/; } | Redirects the root URL to the wiki, so that http://localhost reaches XWiki without /xwiki being typed. The trailing slash matters: without it XWiki answers a second redirect to add it. See return. |
location /xwiki { ... } | Matches every request whose path starts with /xwiki and applies the proxy directives below. See location. |
Proxy Directives
These go inside the location /xwiki block, except the map, which belongs at http level.
| Directive | What it does |
|---|---|
proxy_pass http://localhost:8080; | Forwards the request to the Servlet Container. It is deliberately given no path: with one, for example proxy_pass http://localhost:8080/xwiki;, NginX forwards the normalized path instead of the original one, so a page name containing an encoded slash (%2F), which XWiki page names can, silently reaches a different page. See proxy_pass. |
| proxy_set_header Host $http_host | Passes the client's Host header on, so that XWiki builds URLs for the public domain rather than for localhost. It has to be $http_host, the header as the reader sent it, and not $host, which NginX strips the port from: on a proxy listening anywhere other than 80 or 443, $host makes the wiki emit its own address without the port, and the redirects it answers with lead nowhere. See proxy_set_header. |
| proxy_set_header X-Real-IP $remote_addr | Sends the address NginX sees the request coming from, which a Servlet Container can be configured to log instead of the proxy's own address. |
| proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for | Appends that address to the X-Forwarded-For chain, so a request that already crossed another proxy keeps its history. NginX does not check what the client put in that chain and XWiki reads its first value, so it is not evidence of who sent the request; where this proxy is the only one in front of the wiki, send $remote_addr instead. |
| proxy_set_header X-Forwarded-Proto $scheme | Tells XWiki which protocol the reader used. It has to be the $scheme variable and not a hard-coded http: with the latter a wiki served over HTTPS reports plain HTTP, and XWiki builds every link with it. |
| proxy_set_header X-Forwarded-Host $http_host | Replaces the X-Forwarded-Host header a client may have sent with the real one, port included. NginX passes headers it does not set through untouched, and XWiki reads this one before anything else to build its URLs, so without this line a reader can choose the host of every link the wiki emits. |
proxy_set_header Forwarded ""; | Drops the Forwarded header for the same reason: an empty value makes NginX send nothing at all, and it is the standard header XWiki looks at first. |
| proxy_http_version 1.1 | Uses HTTP/1.1 towards the container, which the WebSocket upgrade needs. See proxy_http_version. |
map $http_upgrade $connection_upgrade { default upgrade; "" ""; } with proxy_set_header Upgrade $http_upgrade and proxy_set_header Connection $connection_upgrade | Tunnels the WebSocket connections that realtime editing uses. The map belongs at http level, outside the server block, and is what keeps Connection: upgrade for the handshakes only: hard-coded, that header goes out on every request, including the ones upgrading nothing, and it rules out the connection reuse an upstream block declaring keepalive would otherwise bring. See map. |
| proxy_redirect off | Leaves the Location header of the container's redirects alone, which is what is wanted here: Host is forwarded unchanged, so XWiki already redirects to the public address. See proxy_redirect. |
HTTPS Directives
These are added to the port 443 block, on top of the proxy directives above.
| Directive | What it does |
|---|---|
listen 443 ssl; | Opens the block that handles HTTPS requests and turns TLS on for it. The block carries the same proxy directives as the port 80 one, X-Forwarded-Proto included: it is written $scheme, so it reports https here with nothing else to change. See listen. |
| ssl_certificate /etc/ssl/certs/wiki.example.com.crt | The certificate presented to browsers during the TLS handshake. NginX reads no separate chain file: an intermediate certificate goes in this same file, after the wiki's own. See ssl_certificate. |
| ssl_certificate_key /etc/ssl/private/wiki.example.com.key | The private key matching that certificate. See ssl_certificate_key. |
Redirection Directives
These make up the port 80 block once HTTPS serves the wiki: its body is replaced by them, so that a plain HTTP request is redirected instead of proxied.
| Directive | What it does |
|---|---|
location ^~ /.well-known/acme-challenge/ { root /var/www/html; } | Keeps the path an ACME client such as certbot answers the certificate challenge on reachable over plain HTTP, so that automatic renewal keeps working. The ^## prefix is what makes NginX stop at this location instead of also trying the regular-expression ones the block may hold. See location. |
return 301 https://$host$request_uri; | Redirects everything else to the HTTPS address of the same URL. It is $host here and not the $http_host the proxy directives use, because $host carries no port and the redirect must not put the port of the plain HTTP listener into an https:// address. $request_uri is the request as it arrived, so the %2F an XWiki page name can contain crosses the redirect still encoded. See return. |
FAQ
How can I check whether NginX is running?
Open http://localhost in a browser, or run curl http://localhost: NginX's own welcome page means the server is running but is not forwarding to XWiki yet.
Why does a page whose name contains a slash open a different page?
Because proxy_pass was given a path. NginX then forwards the normalized request path, which decodes the %2F an XWiki page name can contain, so a link to a page named A/B opens the page A.B instead. Write proxy_pass http://localhost:8080; without the /xwiki suffix, and NginX passes the original path on unchanged.
Why does the wiki answer 404 through the proxy while port 8080 still works?
The proxied path does not match the wiki's context path: the location block has to use the same /xwiki prefix as the Servlet Container.
Why does realtime editing not work through the proxy?
Its WebSocket connection is not being tunnelled: the location block needs proxy_http_version 1.1 together with the Upgrade and Connection headers above.
Why does importing a large XAR or uploading a large attachment fail?
Two different limits. A 413 answer is NginX's client_max_body_size, 1m by default, which the block above sets to 0. A 504 after about a minute is proxy_read_timeout, 60s by default, expiring while the container is still working; raise it for the wiki, for example proxy_read_timeout 600s;.
More
To find more about the current topic, you can search or use the table below and filter the columns to narrow your choices.