Commissioning the git proxy on the portable stack
Status
Accepted. The state described here is the running one.
Context
The package runs on a portable server: Apache with PHP as a module, not IIS and not FastCGI. The git proxy is the only part of the package that does not run through doku.php but through an endpoint of its own, with PATH_INFO after the file name. Precisely those two properties — the separate endpoint and the portable stack — collided in two places during commissioning.
The plugin ships a web.config. It is pure IIS and has no effect on this stack; its three concerns had to be demonstrated or replaced one by one.
Mechanism
AcceptPathInfo per file instead of globally. The portable Apache sets AcceptPathInfo off globally in server/conf/httpd.conf. It therefore answers every request of the form …/git.php/code/{project}/{repo}/info/refs with 404 before PHP starts — the proxy never sees the request. An .htaccess in the plugin directory switches the option on for git.php alone:
<Files "git.php"> AcceptPathInfo On </Files>
The global default stays untouched, because it is right for the rest of the wiki.
The other two concerns of the web.config were already met and were demonstrated rather than rebuilt: mod_deflate is not loaded, so there is no gzip to corrupt a packfile, and LimitRequestBody is unset. Because PHP runs as a module, the Authorization header also reaches PHP without extra configuration — under FastCGI that would have needed a rule of its own.
curl was installed afterwards. The transport to Azure DevOps and the whole REST path run through curl; without the extension the connector reports itself inactive, the repository browser does not load and the proxy fails. The portable server did not ship it. ext/php_curl.dll was added along with the runtime dependencies libssh2.dll and nghttp2.dll from the official package php-8.2.13-Win32-vs16-x64.zip; extension=curl is set in server/php/php.ini.
Paths verified after commissioning. The list is evidence, not a promise of function:
| Path | State |
|---|---|
git clone, fetch and push through the proxy | works; a counter-check straight against Azure DevOps confirms the pushed branch |
| permission check per identity | signed-in non-administrator at tier readonly: read 200, write 403 |
| repository browser including folder loading | works |
{{source>ado:…}} inline on a project page | works |
{{source>ado:…}} in the drawer, on selecting a file | works |
| section editing of a page carrying rendered Markdown | works; each edit touches only its own section |
Consequences
- Do not remove the
.htaccessfrom the plugin directory. It looks redundant because aweb.configsits beside it; without it the proxy answers 404 on this stack, and the failure does not look like a server configuration problem. - Do not switch
AcceptPathInfoon globally to achieve the same thing. The per-file option is the narrower solution. - A PHP update must carry curl with it. The extension has to match the exact server build: same minor version, same thread safety and same compiler. A reliable test is comparing the checksum of
php8ts.dllfrom the package with the one on the server. - If the stack moves to FastCGI, re-check the
Authorizationheader; today's assumption holds only for PHP as a module. max_execution_timeis 30 seconds. Harmless for the repository sizes tested, the next limit for very large ones.
Related topics
- Technical reference – actions and entry points
- Concepts – mounts, visibility tier and limits
- Clone a mounted repository – the git proxy from the user's side
- Diagnostics: git clone answers 404 – the symptom this note explains