Published

Last modified by Eleni Cojocariu on 2026/08/18 11:56

Show last authors
1 Review of [[HTTP Reverse Proxy for XWiki>>doc:documentation.xs.admin.installation.http-reverse-proxy.WebHome]] and of the three pages under [[Apache Server Key Configurations>>doc:documentation.xs.admin.installation.http-reverse-proxy.apache-key-configurations.WebHome]], against the Documentation Guide, the Apache HTTP Server documentation and the XWiki sources. Five pages, none created, none deleted, none renamed.
2
3 == Configurations that do not work as documented ==
4
5 * **##ProxyPassReverse## was given a ##nocanon## argument it does not accept**, on both OS pages. Its syntax is ##ProxyPassReverse [path] url [interpolate]## and ##nocanon## is a ##ProxyPass## option. Apache never says so — any third keyword written there is silently ignored, verified on 2.4.58 — so the block did work, while the page told the reader something false about what it does; the same mistake on ##ProxyPass## itself does fail ##configtest##.
6 * **The ##xwiki.home## example was not a valid ##xwiki.home##.** The HTTPS page gave {{code language="none"}}xwiki.home=https://localhost/xwiki{{/code}}, but the property is a //server// URL: ##xwiki.cfg## documents it as "schema, domain and (optional) port, and the trailing /", ##XWikiServletURLFactory.getServerURL## returns "the url of the server EG: http:~/~/www.xwiki.org/", and the context path is appended separately. It becomes {{code language="none"}}xwiki.home=https://wiki.example.com/{{/code}}.
7 * **The Reference table misspelled ##Require all granted## as ##Required all granted##**, contradicting the very configuration it is the reference for.
8 * **The Linux page's result step told the reader to open {{code language="none"}}https://localhost{{/code}}**, although the ##VirtualHost## it had just pasted is ##*:80## with no ##SSLEngine##. The Windows page had the same step written correctly.
9 * **Moving the proxy directives to the port ##443## block silently dropped four of them.** The HTTPS page says to move the Proxy Rules across, then shows a block without ##AllowEncodedSlashes NoDecode##, ##nocanon##, ##upgrade=websocket##, the ##<Location>## grant or ##RedirectMatch##, so page names containing an encoded slash answer ##404##, realtime editing does not connect, and the root URL stops redirecting. It now shows the complete block.
10 * **Three rows of the Reference table did not render as the directives they document.** ##RewriteCond %{HTTPS}!=on## lost the space between its two arguments; the two ##RewriteRule## rows had their // eaten by an unmatched italic span, so the live page reads ##^/?(.*)https:%{SERVER_NAME}/$1##; and the three ##ProxyPass##/##ProxyPassReverse## rows put a URL inside ##~#~#…~#~###, which the autolinker breaks — one of them ends in a stray ##~#~#~#~###. Every directive is in a code macro now.//
11 * **Two ##ProxyPass## rows for the same path** were documented as separate configuration lines, which cannot both apply; both child pages in fact use the single combined line. **A ##ws:~/~/## ##RewriteRule## row** documented the deprecated ##mod_proxy_wstunnel## approach that no example uses, with no ##RewriteCond %{HTTP:Upgrade}##, so applied as written it would route every request into a WebSocket tunnel. Both are replaced by one row for ##upgrade=websocket##, whose Apache 2.4.47 requirement was stated nowhere.
12 * Smaller ones: **##httpd.exe -k restart## used to start a service that had never been started**; the Linux page enabling ##rewrite##, which its configuration does not use, while the HTTPS page that does need it never mentions it; the Windows prose and code block disagreeing on how many modules to uncomment; "listents", "requeststo"; and the Installation hub linked from Related under the title of a different page ("Installation Methods" is a separate page that also exists).
13
14 == Guideline work ==
15
16 * **Two pages were typed against their content.** The Apache directive table is stored as ##type=explanation## while its identically-shaped NginX twin is ##reference## — it becomes **##reference##**, its noun-phrase title already fitting. "More Configurations for the Apache HTTP Proxy Server" is also ##explanation##, but it is two configuration blocks to paste plus "modify and add in the file" and "test and restart Apache" — it becomes a **##howto##** titled **"Configure HTTPS for the Apache HTTP Proxy Server"**, with the three link labels pointing at it updated to match. Its **page name is left as ##configurations##**: renaming is a move rather than an edit, and it is listed as a follow-up below, where the backlink survey that makes it safe is recorded.
17 * **The hub routed past all three of its own children.** It linked two grandchildren and one great-grandchild, so ##apache-key-configurations##, ##nginx-key-configurations## and ##ssh-tunneling## were reachable only through the automatic "More" table. That matters here because two other pages route //into// this hub as a step — [[Configure XWiki in Docker Behind a Reverse Proxy>>doc:documentation.xs.admin.installation.methods.install-xwiki-docker.configuration.reverse-proxy.WebHome]] and [[HTTPS for XWiki in Docker>>doc:documentation.xs.admin.installation.methods.install-xwiki-docker.configuration.https.WebHome]]. All three children are now named and linked with one orienting clause each.
18 * **Three FAQ answers were duplicated verbatim.** "How can I check if Apache is running locally?" and the ##SSL## modules answer were byte-identical on the Linux and Windows pages; the custom-domain answer was byte-identical on those two //and// on [[Set up NginX Proxy Server>>doc:documentation.xs.admin.installation.http-reverse-proxy.nginx-key-configurations.configure-nginx-server-linux.WebHome]]. The two Apache-wide answers move to the Apache Reference page, which both OS pages now link from their intro, and each OS page keeps only what is specific to its OS.
19 * **The Apache ##related## field linked one of its own children**, which the not-children rule forbids; the content routes there instead. **Both OS pages had no intro paragraph**, opening straight on the numbered list. **The Windows page nested its list four levels deep.** **The directive table mixed two ##VirtualHost## blocks** with no way to tell which row belonged where — it is now three tables under level-2 headings, one per block: the proxy directives, the ##HTTPS## ones and the port ##80## redirect. **18 links pointed at the //French// Apache documentation**, plus one pinned to ##docs/2.4##. Non-breaking spaces, trailing whitespace and an unclosed parenthesis are gone.
20 * **Three ##WIP## banners are removed**, one of which showed readers an author's note: "WIP-not sure how much a Windows version of the tutorial is needed". That question is real and is raised below rather than left in the page.
21
22 == What was added ==
23
24 * **A PlantUML diagram on the hub** — reader, proxy, Servlet Container and XWiki, with the ports and the forwarded headers on the edges. It is the one visual this subtree can have: every page is a config-file procedure, so there is no UI to screenshot.
25 * **What actually changes once XWiki is behind a proxy**, which the hub never said: XWiki reads ##Forwarded##, ##X-Forwarded-Proto##, ##X-Forwarded-Host## and ##X-Forwarded-For## itself and builds its links from them, so the proxy has to send them //and// drop the ones the client sent; trusting them in the container is worth doing for the container's own view of the request; and ##xwiki.home## has to hold the public base address for the URLs built outside a request. Each is a clause plus a link, not an explanation.
26 * **The two failure modes readers hit**, as FAQ entries on the Apache Reference page: ##404## through the proxy while port ##8080## works, and realtime editing not connecting. **Obtaining the certificate** is now the first step of the HTTPS procedure, and the ##/.well-known## exemption says //why// it exists — it is where an ACME client answers the renewal challenge. **A FAQ entry names the Red Hat differences**, since the Linux page is written entirely in Debian terms under the title "on a Linux OS".
27
28 == Corrections from a technical review of this change ==
29
30 The five file changes were then re-tested against a real Apache HTTP Server 2.4.58 and a live XWiki 18.4.3 proxied through it: every proposed block through ##configtest##, and the interesting ones served for real. Seven items came out of that and are all applied above. Nothing was wrong in what this change had already fixed on the two OS configurations — those were proxied end to end and behave as documented.
31
32 * **The port ##80## redirect this change introduced broke page names containing a slash.** Replacing the body of that block dropped ##AllowEncodedSlashes NoDecode## from it, and the rule carried no ##NE## flag. Served for real, {{code language="none"}}/xwiki/bin/view/Main/A%2FB{{/code}} answered ##404## instead of redirecting; with the directive back but no ##NE##, it redirected to a double-encoded ##%252F##, that is to a different page. Both are fixed and the rule is now ##[R=301,L,NE]## rather than a ##302##.
33 * **Nothing stopped a reader from forging the forwarded headers.** XWiki reads the //first// value of ##X-Forwarded-Host##, ##X-Forwarded-Proto## and ##Forwarded## while ##mod_proxy_http## appends its own value //last//, so through the configuration these pages documented, a request carrying {{code language="none"}}X-Forwarded-Host: evil.example.com{{/code}} made the wiki hand back ##https:~/~/evil.example.com/…## as its absolute URL. All three procedures now open their proxy block with ##RequestHeader unset## for those three headers, the Reference table documents them, and the two plain-##HTTP## pages consequently enable ##mod_headers##. The platform side of this — first value rather than last, and no trusted-proxy count — is worth an issue of its own and is listed below.
34 * **"The Servlet Container has to trust the headers, otherwise links stay ##http##" is not what happens.** With no container-side proxy configuration at all, the proxied REST answer already gives an ##https## absolute URL: XWiki reads the headers itself, deliberately — ##HttpServletUtils.appendScheme##, whose javadoc ends "One less thing to configure". A container valve is now //recommended//, for the container's own view of the request (its ##getScheme##, its access log), rather than presented as what makes links correct; and the "why are links still http" answer names the real causes — ##mod_headers## not enabled, or ##xwiki.home##/##xwiki.url.protocol## pinned to ##http##.
35 * **The Reference table filed the three ##Rewrite## rows under the port ##443## block**, where ##RewriteCond %{HTTPS}!=on## can never match, so a reader following the table gets a dead rule and no redirect. They are a table of their own now, under a heading saying they belong to the port ##80## block — and that condition is gone, being unreachable in a block that only ever serves port ##80##.
36 * **The Red Hat answer pointed at an httpd that cannot parse the block it recommends reusing**: RHEL 8 ships 2.4.37, where ##upgrade=websocket## fails ##configtest## outright. It now says to drop the option there and tunnel realtime editing with ##mod_proxy_wstunnel## instead.
37 * Smaller ones: the ##.## in the ##RewriteCond## that exempts ##/.well-known## was unescaped; the Windows ##ServerName## step said to uncomment a line that in the shipped ##httpd.conf## reads ###ServerName www.example.com:80##, so it has to be changed as well as uncommented; and the hub diagram showed XWiki redirecting to ##localhost:8080## for ##ProxyPassReverse## to rewrite, which with the recommended ##ProxyPreserveHost On## never happens — XWiki's own redirects are relative, and ##ProxyPassReverse## is a safety net rather than the mechanism drawn. That diagram also turned out not to render at all: its line breaks reached PlantUML as real newlines, which end the statement. It is corrected and rendered offline.
38 * Two FAQ entries were added for reports this tree answered nowhere: Apache's 60 s ##ProxyTimeout##, which turns a large XAR import or attachment upload into a ##504## while the container is still working, and ##Strict-Transport-Security## once ##HTTPS## is in place.
39
40 == Deliberately left alone ==
41
42 Both OS pages **stay ##type=tutorial##**: by the letter of Diataxis they are How-tos, but their sibling ##set-nginx## is also a Tutorial, and retyping two of three would make the subtree inconsistent to fix a classification it has already settled. **##highlights## stays empty** on both hubs (three children each, and the content does the routing). **Technical ID stays empty** on all five — these are installation pages, not extension documentation. **##nocanon## is kept alongside ##AllowEncodedSlashes NoDecode##**: they cover Apache's own canonicalisation and its handling of ##%2F##, and XWiki needs both. **The tables are not wrapped in ##figure##/##figureCaption##** although the guide asks for it, because no page in the tree does and doing it on one page would look accidental — worth raising for the tree as a whole. No number, path or directive value was changed other than the ones listed above.
43
44 == Follow-ups, not in this change ==
45
46 * **Rename ##configurations## to ##configure-https##, then pin the three Apache children** in the order Linux, Windows, HTTPS — the new title otherwise sorts to the front of an alphabetical tree, ahead of the pages it depends on. A walk of all 705 documentation pages found **exactly four** references to that page, all of them on pages in this Change Request, so the move needs no repointing beyond it.
47 * **Decide whether the Windows tutorial is wanted**, per the banner removed above. It has been corrected on the assumption that it stays; it is linked from six pages, so dropping it would go through the page-deletion procedure.
48 * **##set-nginx## hard-codes ##proxy_set_header X-Forwarded-Proto http##**, so an NginX instance terminating TLS tells XWiki the request arrived over plain HTTP — the exact bug the Tomcat proxy-headers page exists to prevent. The idiomatic value is ##$scheme##, which the Docker reverse-proxy page already uses. The same page also carries the third copy of the custom-domain answer, and it is an **Apache** answer on an NginX page: it says to replace ##ServerName localhost##, a directive NginX does not have.
49 * **The two header findings above apply outside the pages of this change**, which is why they are not fixed here: ##set-nginx## sets no ##proxy_set_header## for the client-sent headers either, and both it and [[Configure Tomcat to Find Proxy Headers>>doc:documentation.xs.admin.installation.methods.install-xwiki-war.configure-servlet-container.configure-tomcat.find-proxy-headers.WebHome]] carry the "the container has to trust the headers or links stay ##http##" framing. Widening this change or opening a second one is a call for the reviewer.
50 * **A platform issue for the header handling itself**: ##HttpServletUtils.getFirstHeaderValue## takes the //first// value of ##X-Forwarded-*## while a proxy appends its own value last, and there is no trusted-proxy count — ##getClientIP## carries a ##TODO## saying exactly that for ##X-Forwarded-For##. Documentation can only tell administrators to strip the headers at the proxy, which is what it now does.
51 * **##ssh-tunneling##** opens a (((
52 ## group in its first FAQ answer and closes it at the end of the second, so the two answers render inside one box; and it describes a two-hop path in prose where a diagram would carry it.##
53 )))

Get Connected