A Matrix server can sit behind Cloudflare, but the setup depends on how clients and other homeservers discover it. Cloudflare’s standard HTTP proxy supports HTTPS on port 443; Synapse federation commonly defaults to port 8448, which is not in Cloudflare’s standard proxied-port list. A reliable arrangement is to expose Synapse through a reverse proxy on 443 and publish Matrix well-known records that direct clients and federation traffic to that hostname. Alternatively, keep federation on 8448 and make that DNS record DNS-only.
This guide uses Synapse, the official Matrix homeserver implementation, with the example Matrix IDs @alice:example.com and client endpoint matrix.example.com. Replace these names and addresses with your own. The instructions assume Synapse and an HTTPS reverse proxy are already installed. They do not apply unchanged to every homeserver implementation. Checked against current Cloudflare and Element Synapse documentation on October 6, 2026.
Choose the right network layout
Cloudflare’s orange-cloud proxy is an HTTP/HTTPS reverse proxy. It sits between clients and your origin for proxied web requests; it does not proxy every arbitrary TCP port. Its standard HTTPS ports include 443 and 8443, but not Synapse’s commonly used federation port 8448. See Cloudflare’s supported network ports and proxying limitations.
| Layout | Cloudflare DNS | Federation discovery | Use it when |
|---|
| Federation on HTTPS 443 | matrix.example.com proxied | example.com/.well-known/matrix/server points to matrix.example.com:443 | You want client and federation traffic to pass through the normal Cloudflare HTTP proxy. |
| Federation on 8448 | Client hostname proxied; federation hostname DNS-only | Advertise the server on port 8448, or use the appropriate delegation target | You want to retain Synapse’s default federation port and accept direct connections to the origin for federation. |
The first layout is used below. A proxied DNS record does not by itself configure Matrix discovery, reverse proxying, TLS, or firewall policy.
1. Decide the Matrix server name before configuring DNS
The Matrix server name is the part after the colon in a user ID. In this example it is example.com, so users have IDs such as @alice:example.com. The technical client hostname is matrix.example.com. This separation lets the domain used in user IDs stay stable while traffic is delegated to another hostname. If Synapse is already initialized, do not change server_name casually: it is part of user and room identity and changing it is a migration, not a proxy adjustment.
Plan to serve two small JSON discovery documents from the server name domain:
https://example.com/.well-known/matrix/client tells compatible clients to use https://matrix.example.com.https://example.com/.well-known/matrix/server tells other homeservers to reach federation at matrix.example.com:443.
The client document needs an Access-Control-Allow-Origin: * response header. The Synapse delegation guide includes examples of these records and their expected structure: Synapse federation delegation.
2. Create the Cloudflare DNS records
In Cloudflare DNS, create an A record named matrix that points to the public IPv4 address of the server. Add an AAAA record only if the origin has working IPv6 connectivity and a firewall configured for IPv6. Set the web hostname’s proxy status to Proxied (orange cloud). If the root domain also points to this server and will serve the well-known files, proxy its web record too.
Keep unrelated records, including mail records, at their appropriate DNS-only settings. MX and TXT records are not proxied. Cloudflare explains that a proxied A, AAAA, or CNAME record routes HTTP/HTTPS requests through Cloudflare, while DNS-only returns the origin address directly: Cloudflare proxy status behavior.
Allow inbound HTTPS from Cloudflare to the origin. For stronger protection, restrict the origin firewall to Cloudflare’s published IP ranges and keep those ranges updated. If the server’s IP was exposed before the zone became active, proxying DNS does not invalidate that old address; consider changing the origin IP after activation. Do not assume the orange cloud alone prevents direct-origin access.
3. Configure HTTPS between Cloudflare and the origin
In Cloudflare’s SSL/TLS settings, use Full (strict) when the origin presents a valid certificate for the hostname, such as a publicly trusted certificate or a Cloudflare Origin CA certificate. Full (strict) encrypts the Cloudflare-to-origin connection and validates the origin certificate; Flexible mode does not provide that same end-to-end TLS path. See Cloudflare’s Full (strict) documentation.
Install the certificate and private key on the reverse proxy, not necessarily in Synapse. The reverse proxy should listen on public port 443 and forward Matrix requests internally to Synapse’s HTTP listener, commonly port 8008. Do not expose the Synapse listener publicly if the reverse proxy is intended to be the only entry point.
4. Tell Synapse it is behind a trusted reverse proxy
In the relevant HTTP listener in homeserver.yaml, enable forwarded-header handling. A simplified example for a non-containerized server is:
listeners:
- port: 8008
type: http
tls: false
x_forwarded: true
bind_addresses: ['127.0.0.1']
resources:
- names: [client, federation]
compress: false
Merge these settings into the existing listener rather than replacing the whole configuration. Synapse’s maintained documentation recommends x_forwarded: true behind a reverse proxy and suggests binding to localhost when the proxy runs on the same host. For a container deployment, binding Synapse to the container’s loopback can prevent the host proxy from reaching it; use the container or service network address and firewall that path instead. Check the current Synapse reverse proxy guide before changing listener settings.
Forwarded headers are trustworthy only when Synapse accepts traffic from your controlled proxy. If Cloudflare is the only internet-facing route, prevent direct public access to the origin and configure the proxy to pass the correct client address. Nginx’s $remote_addr will otherwise be a Cloudflare address because Cloudflare connected to Nginx. Configure Nginx’s real-IP module to trust only Cloudflare’s published source ranges before using CF-Connecting-IP; never trust that header from arbitrary internet clients. Keep the Synapse admin API private unless you have a specific reason to expose it.
5. Route Matrix paths without rewriting them
Configure your reverse proxy to send both /_matrix and /_synapse/client to Synapse. Preserve the request URI exactly. Synapse federation request signatures can fail if a proxy decodes or normalizes encoded path segments.
Here is a compact Nginx example for matrix.example.com. It assumes your TLS certificate directives are already configured for this server block and that the reverse proxy and Synapse run on the same host:
server {
listen 443 ssl;
server_name matrix.example.com;
location ~ ^(/_matrix|/_synapse/client) {
proxy_pass http://127.0.0.1:8008;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $host;
proxy_http_version 1.1;
client_max_body_size 50M;
}
}
Do not add a URI suffix to this regex location’s proxy_pass. Synapse’s proxy documentation calls out URI canonicalization as a cause of federation signature errors. Also adjust client_max_body_size to match the Synapse upload limit and any Cloudflare plan limit that applies to your zone. The 50M value above is only an example, not a universal recommendation.
Cloudflare supports WebSockets on its plans, and Matrix clients may use long-lived connections. Confirm that your proxy permits the upgrade and that any WAF or rate-limit rules do not reject legitimate Matrix requests. Cloudflare’s WebSockets documentation describes its handling of upgraded connections.
6. Publish the well-known responses
Serve the following two responses from example.com over HTTPS. You can return them from your web server, a static host, or a separate virtual host. Keep the client and federation documents distinct:
GET /.well-known/matrix/client
HTTP/1.1 200 OK
Content-Type: application/json
Access-Control-Allow-Origin: *
{"m.homeserver":{"base_url":"https://matrix.example.com"}}
GET /.well-known/matrix/server
HTTP/1.1 200 OK
Content-Type: application/json
{"m.server":"matrix.example.com:443"}
Do not use a redirect to an unrelated host as a substitute without checking the Matrix discovery requirements and client behavior. Make sure the server-name host is covered by a valid HTTPS certificate and that Cloudflare does not cache stale discovery responses while you are changing them.
7. Keep API traffic dynamic and uploads within limits
Do not cache authenticated Matrix API responses. Add a Cloudflare Cache Rule to bypass caching for the Matrix API paths, including /_matrix/* and /_synapse/client/*, unless you have a carefully tested reason to handle a specific public response differently. Avoid broad WAF or bot rules that challenge or block federation endpoints; federation requests come from many independent homeservers. If a security rule is necessary, test it against client login, sync, media upload, and federation before enforcing it generally.
Uploads have several independent ceilings: the client, Cloudflare’s plan or zone upload setting, the reverse proxy’s body-size limit, and Synapse’s max_upload_size. A 413 error means one of those limits rejected the request. Cloudflare publishes plan-dependent upload limits and notes that these settings can be adjusted within the documented constraints: Cloudflare’s 413 troubleshooting page. Raise only the necessary limits, and test with a file smaller than the configured cap before increasing them further.
8. Verify client access, discovery, and federation
Run these checks from a machine outside your server’s network. Replace the example hostnames:
curl -i https://example.com/.well-known/matrix/client
curl -i https://example.com/.well-known/matrix/server
curl -i https://matrix.example.com/_matrix/client/versions
curl -i https://matrix.example.com/health
The first two requests should return HTTP 200, JSON content, and the expected values. The client document should include the CORS header. The client versions endpoint should return JSON from Synapse through Cloudflare. The Synapse health endpoint returns HTTP 200 when reached through a configured listener, but it is not a substitute for checking login or federation.
Then sign in with a Matrix client using an ID ending in :example.com, join a room hosted elsewhere, and confirm that messages and membership updates synchronize. Use a Matrix federation tester or a second homeserver to validate server discovery and federation. A successful request to /_matrix/client/versions proves only that the client-facing route works; it does not prove that federation discovery, signing, or outbound federation is correct.
What success looks like—and when to change the design
- Clients connect through Cloudflare: DNS resolves to Cloudflare addresses, HTTPS uses the intended certificate, and the Matrix client API returns a response.
- Discovery is correct: both well-known URLs return the right JSON and the client document passes cross-origin checks.
- Federation works: a remote server discovers your advertised endpoint and can exchange room state. If 443 delegation fails but direct 8448 works, inspect the well-known record, proxy path routing, and WAF rules.
- Uploads work at the expected size: test a representative upload. If small files succeed but larger files return 413, compare all four size limits rather than changing only Synapse.
- The origin is not an alternate public path: direct requests to the origin should be blocked or limited as designed. If they still reach the Matrix service, correct the firewall and trusted-proxy configuration.
Use DNS-only federation on port 8448 if your requirements or implementation cannot route federation on 443, but understand that this exposes the origin address and removes Cloudflare’s HTTP proxy protection for that hostname. Spectrum is another option for non-standard ports, subject to product availability and plan constraints. Cloudflare proxying also means TLS terminates at Cloudflare before a second TLS connection to your origin; Matrix end-to-end encryption protects encrypted message content, but it does not hide connection metadata or content that is not end-to-end encrypted from the services handling the HTTP request. Choose the topology based on your privacy, federation, and availability requirements, then retest after changes to DNS, certificates, Synapse, or Cloudflare rules.