Skip to content

Reverse Proxy and TLS

Applies to: All subscriptions

Purpose

Configure the single public entry point correctly: terminate TLS, route requests to the right place, serve the application without breaking browser routing, and apply the security headers a customer's security review will look for.

Audience

Infrastructure engineers and system administrators. The security header and TLS sections are also read by security reviewers.

Prerequisites

Steps

1. Decide the routing

The proxy has exactly two jobs, and one fallback rule:

Request Destination
Paths beginning /api/ The application API, on its configured port
A path matching a real static file That file from the published build
Anything else The application's entry page, so the browser resolves the route

The third rule is not optional. Without it, refreshing an inner page or following a bookmark returns HTTP 404 — a fault that never appears during a click-through test and always appears on day one of user acceptance testing.

2. Terminate TLS

Setting Requirement
Minimum protocol version TLS 1.2, with TLS 1.3 preferred
Cipher suites Modern suites only; no legacy ciphers
Certificate Valid, trusted, covering every published hostname
Certificate chain Complete. An incomplete chain works in browsers and fails for the ERP calling in
HTTP to HTTPS redirect Enabled
Renewal Automated, with a named owner

Verify: The minimum TLS version above is a recommendation, not a stated platform requirement. Align it to the customer's own standard. Recorded as assumption E1 in the Assumptions Register.

The incomplete-chain failure is worth dwelling on: browsers usually repair a missing intermediate certificate automatically, so the application looks fine while every ERP integration fails TLS validation. Test with a tool that does not repair the chain, not with a browser.

3. Apply security headers

Header Purpose
Strict-Transport-Security Forces HTTPS on subsequent visits
X-Content-Type-Options: nosniff Prevents content-type guessing
X-Frame-Options or a frame-ancestors policy Prevents the application being framed
Referrer-Policy Limits referrer leakage
Content-Security-Policy Restricts what the page may load

The content-security policy needs specific care in a Complifly deployment: generated files are served from a different origin by design. If the policy does not allow that origin, downloads fail with no useful error. Enumerate the origins the application legitimately uses before writing the policy — see Domains and URLs.

4. Set timeouts and body limits

Setting Guidance
Proxy read timeout Longer than the slowest legitimate operation. Government calls and bulk operations are slower than an ordinary request
Request body limit Large enough for the biggest upload the business will attempt, and no larger
Header size limit Adequate for tokens, which can be sizeable
Keep-alive Enabled toward the API

A proxy timeout shorter than a legitimate government call produces an HTTP 504 while the operation actually completes at NIC. The user retries, and the retry is rejected as a duplicate. Size timeouts to the slow path, not the median.

5. Handle cross-origin requests deliberately

If the front end and API are served from the same origin, no cross-origin configuration is needed and none should be added. If they are on different hostnames, cross-origin access must be configured on the API for exactly those origins — never a wildcard.

6. Do not expose anything else

Only the proxy is reachable from outside. The API, worker, database and queue must not be. Verify this by attempting to reach them from outside the network, not by inspecting a configuration file.

Validation

Check Method Pass condition
HTTPS works Open the application URL Loads with a valid certificate and no warning
Redirect works Request the HTTP URL Redirects to HTTPS
Certificate chain complete Test with an external TLS checker, not a browser Full chain served
TLS version and ciphers External TLS checker Meets the agreed standard
API routing works Request the health path through the proxy HTTP 200
Static assets served Load the application Assets return HTTP 200
Deep link fallback works Open an inner page directly in a new tab, then refresh it Loads both times. HTTP 404 means the fallback rule is missing
Security headers present Inspect response headers All expected headers present
Downloads work Generate and download a document Downloads succeed. Failure here is usually the content-security policy
Long operations survive Perform a bulk operation at realistic size Completes without an HTTP 504
Upload size adequate Upload the largest file the business will use Accepted
Internal components not exposed Attempt to reach the API port, database port and queue port from outside All refused

Troubleshooting

Symptom Cause Action
HTTP 502 The proxy cannot reach the API Confirm the API is listening and the proxy target port matches. The application log will be silent
HTTP 504 on government operations Proxy timeout shorter than the operation Raise the read timeout. Note the operation may have succeeded at NIC — check before retrying, or the retry will be rejected as a duplicate
Works until refresh, then HTTP 404 Single-page-application fallback rule missing Add the fallback
Browsers fine, ERP integration fails TLS Incomplete certificate chain Serve the full chain. Browsers repair this; other clients do not
Downloads fail with no clear error Content-security policy blocks the download origin Allow that origin explicitly
Cross-origin errors in the browser console Front end and API on different origins without configuration Configure allowed origins on the API for exactly those hostnames
Large uploads rejected Body size limit too low Raise it to the largest legitimate file, and no further
Sign-in loops or fails after redirect Redirect URL not registered, or protocol mismatch between configuration and reality Register the exact URL including scheme and path
Site becomes unreachable overnight Certificate expired Automate renewal and monitor expiry. See Monthly Checks
Some users blocked, others fine Strict transport security cached against an old certificate or hostname Expected behaviour of the header; plan hostname changes carefully