Reverse proxy

Publish AnsibleForms behind Nginx, Traefik or Apache, at the root or under a subpath

  1. When to use one
  2. The settings that matter
  3. Serving under a subpath
  4. Timeouts, uploads and live output
  5. Client addresses
  6. Examples

When to use one

AnsibleForms serves the interface, REST API and Swagger on one port; a reverse proxy in front of it lets you:

  • serve it on port 443 with a certificate managed by your existing tooling (ACME, a corporate CA)
  • share one host name with other applications, by publishing AnsibleForms under a subpath
  • keep the application port and the database off the public network

A proxy is optional: the application can serve HTTPS itself, see HTTPS.


The settings that matter

Only a few settings affect how AnsibleForms behaves behind a proxy:

Setting Behind a proxy
PORT The port the proxy forwards to, 8000 by default. The docker-compose project sets it to 443.
HTTPS 0 when the proxy terminates TLS and reaches the application over a private network, 1 to encrypt that hop as well.
BASE_URL The subpath, for example /ansibleforms. Leave it at / when the application has a host name of its own.
API_BODY_LIMIT_MB Largest JSON request the application accepts, 50 MB by default. The proxy must allow at least this.
UPLOAD_MAX_GB Largest file a form upload field accepts, 10 GB by default. The proxy must allow it too, or uploads fail there.
Public Root Url Under Settings: the address users reach, subpath included. It builds the links in notification emails.

For Entra ID or OIDC, register the public address as redirect URI, with the BASE_URL subpath if set.


Serving under a subpath

BASE_URL mounts the whole application under the subpath; the proxy must forward the path unchanged. With BASE_URL=/ansibleforms:

  • the interface, /api/v2/... and the Swagger interface are all served under /ansibleforms/
  • the <base href> of the interface is rewritten at startup, so assets and API calls resolve under the subpath
  • a request for / or for /ansibleforms (no trailing slash) is redirected to /ansibleforms/

Keep the prefix: no StripPrefix in Traefik, no URI on proxy_pass in Nginx, as the application expects it.

The Status page shows the base URL in force.


Timeouts, uploads and live output

Job output and job status reach the browser by polling: there are no WebSockets or server-sent events to configure. A job launch returns as soon as the job is created, so a long playbook does not hold a request open.

The requests that can take long are:

  • backup and restore from the Backups page, which wait for the dump or restore command to finish, up to BACKUP_COMMAND_TIMEOUT_SECONDS (3600 by default)
  • large uploads through a file field, which stream the whole file in one request
  • chat messages, when the chat assistant is enabled, which wait for the model provider to answer

Proxies often time out after 60 seconds and cap request bodies (Nginx accepts 1 MB by default). Raise both for the AnsibleForms routes, as in the examples below.


Client addresses

AnsibleForms does not read X-Forwarded-For. Behind a proxy, the IP address in the audit trail and in the log is the address of the proxy, so correlate with the proxy’s access log when you need the client address.


Examples

Each example publishes AnsibleForms at https://forms.example.com/ansibleforms/, with TLS terminated by the proxy and the application running with HTTPS=0, PORT=8000 and BASE_URL=/ansibleforms:

proxy_pass names no URI, so Nginx forwards the path as it came in, prefix included:

server {
    listen 443 ssl;
    server_name forms.example.com;

    ssl_certificate     /etc/nginx/certs/forms.example.com.crt;
    ssl_certificate_key /etc/nginx/certs/forms.example.com.key;

    location /ansibleforms/ {
        proxy_pass         http://10.0.0.20:8000;
        proxy_set_header   Host $host;
        proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header   X-Forwarded-Proto $scheme;

        client_max_body_size    10g;    # UPLOAD_MAX_GB
        proxy_request_buffering off;    # stream uploads instead of spooling them first
        proxy_read_timeout      3600s;  # BACKUP_COMMAND_TIMEOUT_SECONDS
        proxy_send_timeout      3600s;
    }
}

Without a subpath, use location / and leave BASE_URL unset.

To keep the hop between proxy and application encrypted, run the application with HTTPS=1, point the proxy at https://, and give the application a certificate the proxy trusts, see HTTPS.