# HTTP Upload (XEP-0363) on Prosody 0.11 — proven recipe (2026-08-28, ICQ/nixg.ru) ## Get the module — apt beats GitHub/hg - `prosody/prosody:latest` (0.11.9) ships NO mod_http_upload. - From some networks GitHub (codeload/raw) returns 404/rate-limit and hg.prosody.im misroutes — do not fight mirrors. - Reliable source on Ubuntu hosts: `sudo apt-get install -y prosody-modules` Module lands at `/usr/lib/prosody/modules/mod_http_upload/`. Copy into the compose-mounted dir: `cp -r /usr/lib/prosody/modules/mod_http_upload ./modules/` (compose mounts `./modules:/etc/prosody/modules`) ## Config — Component, NOT modules_enabled mod_http_upload registers as a COMPONENT. Adding it to `modules_enabled` errors out. ```lua Component "upload.nixg.ru" "http_upload" http_upload_file_size_limit = 10 * 1024 * 1024 -- hard cap = Prosody HTTP parser limit http_upload_expire_after = 7 * 24 * 60 * 60 http_upload_require_authentication = true http_upload_path = "/var/lib/prosody/http_upload" http_external_url = "https://upload.nixg.ru" -- public URL WITHOUT :5281 (Caddy proxies 443 → 5281) ``` - `http_upload_file_size_limit` above 10 MB is SILENTLY capped to 10485760 B with warning "exceeds HTTP parser limit on body size" — set it to 10 MB up front. ## TLS requirement — the gotcha The module refuses to start unless the HTTP endpoint is TLS: `Error initializing module 'http_upload': File upload MUST happen with TLS but it isn't enabled` Fix: enable Prosody's https port with a GLOBAL (not VirtualHost) ssl block: ```lua https_ports = { 5281 } https_interfaces = { "0.0.0.0" } ssl = { key = "/etc/prosody/certs/nixg.ru.key"; certificate = "/etc/prosody/certs/nixg.ru.crt"; } ``` One global `ssl` block also fixes the stock image's benign "No certificate present for https port 5281" bind error. ## Expose publicly (Caddy on vps02) DNS: `A upload.nixg.ru → ` (user action in the DNS panel). Caddyfile: ``` upload.nixg.ru { reverse_proxy 10.8.0.2:5281 { header_up Host {host} } } ``` Validate + reload: `docker exec caddy caddy validate --config /etc/caddy/Caddyfile` then `docker exec caddy caddy reload --config /etc/caddy/Caddyfile`. ## Verify - Prosody log: `upload.nixg.ru:http_upload info URL: - Ensure this can be reached by users` If the line shows `:5281` in the URL, http_external_url did not apply (restart needed). - From vps02 first: `nc -vz 10.8.0.2 5281` must be open before blaming Caddy. - End-to-end: upload a file via the web client; files land under `data/http_upload/` (monitored for expiry).