HAProxy edge
On Docker Compose, every Canasta instance on a host is served through one front door: the HAProxy edge. It listens on the host's ports for all of the host's instances, terminates TLS, routes each request by its hostname and port to the right instance, throttles clients that send too many requests, and holds the certificates. Each instance's Caddy keeps serving its own wikis behind it, over plain HTTP on the host's private container network.
The edge applies to Docker Compose and Podman. On Kubernetes the ingress controller plays the same role; see Help:Networking and TLS.
Why an edge
- Many instances, one pair of ports. The edge routes each request by its hostname, so every instance on the host can serve its wikis at
https://<hostname>with no port. - Scraper throttling. The edge counts requests per client and answers
429 Too Many Requeststo a client that exceeds its limit, before the request reaches Caddy, Varnish or PHP. Requests that always reach PHP have a stricter limit and their own connection cap, so a crawler cannot use up the PHP pool that page views need. See Rate limits and connection caps. - Deny lists and CrowdSec. Addresses and User-Agents you list, and clients CrowdSec has banned, are refused with
403at the edge. See Deny lists and CrowdSec at the edge. - Client addresses. Behind a CDN, the edge recovers the visitor's address from the CDN's header, so rate limits and deny lists apply to each visitor. Under rootless Podman, the edge receives connections with the visitor's own address, which MediaWiki then records. See Behind a CDN and Container runtimes.
- Certificates. The edge obtains and renews Let's Encrypt certificates for every hostname behind it, by HTTP or DNS validation, or serves certificates from its own CA or ones you supply. See Certificates.
How it works
The edge is a Compose project of its own, canasta-edge, with two containers:
| Container | Role |
|---|---|
canasta-edge |
HAProxy. Listens on the instances' ports, terminates TLS, routes by hostname and port, applies rate limits, deny lists and CrowdSec bans. |
canasta-edge-acme |
acme.sh. Obtains and renews Let's Encrypt certificates and installs them in HAProxy without a reload. |
Every instance joins the canasta-edge network. Its Caddy is reachable there by the name caddy-<instance-id>, and publishes only random ports on the host's loopback address.
A request flows as follows:
- On an HTTP port (80 by default), the edge answers Let's Encrypt HTTP challenges, serves the instances that use plain HTTP on that port, and redirects everything else to HTTPS with a
301, to the instance's own HTTPS port if it has one. - On an HTTPS port (443 by default), the edge terminates TLS (TLS 1.2 or later, HTTP/2 and HTTP/1.1).
- The edge looks up the request's
Hostheader on that port. A request whose hostname no instance serves on that port,localhostand IP addresses included, goes to the instance whose wikis uselocalhostor an IP address on that port, if there is one, and otherwise gets404with the textNo site is served at this address. - The request goes to one of the instance's backends: media for its media hostnames, dynamic for requests that always reach PHP, and default for everything else (page views Varnish can serve from cache, static files).
- The backend applies the instance's CrowdSec bans, deny lists and rate limits, then passes the request to the instance's Caddy, which serves it through Varnish to MediaWiki.
The edge keeps routing the hostnames of an instance you stop. Its sites answer 503 with the text This site is not running. until you start it again.
The edge starts with the first instance on the host and stops when the last one is deleted. It comes back on its own after a reboot: Docker restarts it, and under rootless Podman its systemd units start HAProxy again.
New and existing instances
New instances
canasta create puts every Compose instance behind the edge. If the edge is not running yet, the instance's ports must be free: when anything listens on them, create stops and names it. Pass an env file that sets HTTP_PORT and HTTPS_PORT to use other ports; see Ports and plain HTTP.
Under rootless Podman, create also needs the operator's systemd user session; see Container runtimes.
Existing instances: the upgrade
canasta upgrade moves a host's existing Compose instances behind the edge before it upgrades them. Each instance keeps its hostnames, ports and certificates: the upgrade moves the Let's Encrypt certificates its Caddy holds into the edge, so no new certificates are requested. It then stops each instance's Caddy, starts the edge, and brings each Caddy back up behind it. The instances' sites are unavailable for a few seconds. An instance that was stopped joins the edge but stays stopped.
The upgrade moves a host's instances together or not at all. It refuses the host, upgrades none of its instances, and says why, when:
- the host's instances use both Docker and Podman;
- the CLI cannot write to an instance's directory;
- an instance runs under rootless Podman without the operator's systemd user session;
- a setting the edge needs is invalid, such as a non-numeric
CANASTA_EDGE_RATE_DYNAMICor a wiki URL whose port differs from the instance'sHTTPS_PORT; - two instances would clash at the edge: the same hostname on the same port, two instances reached by
localhostor an IP address on the same port, or a port that is one instance's HTTP port and another's HTTPS port.
Fix the cause and run the upgrade again.
Before moving an instance, the upgrade keeps a copy of its docker-compose.yml, .env and config/Caddyfile. If the move fails, it puts them back and brings the instance's Caddy back up on its own ports and certificates. The upgrade reports the failure with the edge's reason and does not upgrade that instance; run the upgrade again once the cause is fixed.
Ports and plain HTTP
By default an instance is served on ports 80 and 443. An instance can use other ports, and several instances can share them:
- Other ports.
HTTP_PORTandHTTPS_PORTin the instance's.envset the ports the edge serves it on, for example 8080 and 8443. Its wiki URLs carry the HTTPS port (example.com:8443). The edge listens on every port any instance uses, and redirects the instance's HTTP port to its HTTPS port. - Plain HTTP.
TLS_MODE=off(orcanasta create --skip-tls) serves the instance over plain HTTP on itsHTTP_PORT, with no certificate and no redirect, for use behind a proxy of your own that terminates TLS. Name that proxy inTRUSTED_PROXIES: the edge then takes the client address from it, keeps theX-Forwarded-Protoheader it sends, and applies per-client rate limits. Without it, the edge removesX-Forwarded-Proto, and applies no per-client rate limits, since every request would come from the proxy's address. - localhost and IP addresses. A wiki URL of
localhostor an IP address works behind the edge. The edge cannot tell such instances apart by name, so only one instance per port can use one; give others their own ports.
canasta config set -i <instance-id> HTTP_PORT=8080 HTTPS_PORT=8443
config set updates the port in the wiki URLs in config/wikis.yaml, MW_SITE_SERVER and MW_SITE_FQDN, and restarts the instance, which the edge then serves on the new ports. The same happens for the scheme when TLS_MODE changes to or from off.
Container runtimes
| Runtime | The edge |
|---|---|
| Docker | Publishes the instances' ports itself and receives each visitor's own address. |
| Rootless Podman | A systemd user socket unit, canasta-edge.socket, listens on the ports and hands them to HAProxy, which runs in the canasta-edge.service unit, so visitors' addresses reach MediaWiki and CrowdSec intact. This needs lingering enabled for the operator, which canasta install podman sets up; create and upgrade refuse an instance without it.
|
| Rootless Docker | The daemon's default port forwarding replaces every visitor's address with its own, so MediaWiki, CrowdSec and the edge cannot tell visitors apart. The edge applies no per-client rate limits to such an instance, and create, upgrade and doctor warn about it. Switch the daemon to an address-preserving port driver (RootlessKit's slirp4netns, or pasta with the implicit driver), then set CANASTA_EDGE_RATE_DYNAMIC and CANASTA_EDGE_RATE_DEFAULT to turn the limits on.
|
One edge serves a host in one runtime. create refuses an instance in one runtime on a host whose edge runs in the other, and the upgrade refuses a host whose instances use both.
Certificates
TLS_MODE selects how the edge gets each hostname's certificate. The edge holds the certificates; the instance's Caddy needs none. TLS_MODE=off serves the instance over plain HTTP, with no certificate.
TLS_MODE |
Certificate | Needs |
|---|---|---|
acme (default) |
Let's Encrypt, HTTP validation. HAProxy answers the challenge on port 80 itself. | Each hostname resolves to the host, and port 80 is reachable from the internet. |
acme-dns |
Let's Encrypt, DNS validation through the DNS provider's API. | ACME_DNS_PROVIDER (only cloudflare is supported, and is the default) and CLOUDFLARE_API_TOKEN. Port 80 need not be reachable for validation.
|
internal |
Signed by the edge's own CA. Never contacts Let's Encrypt. Browsers do not trust it. | Nothing. Suits a CDN in a mode that does not validate the origin certificate, and test hosts. |
custom |
The certificate and key you place in the instance's config/certs/, named by TLS_CERT and TLS_KEY (default origin.crt and origin.key). |
One certificate that covers every hostname of the instance, such as a CDN's origin certificate. |
Each instance chooses its own mode, so instances with different modes can share the edge.
- Before Let's Encrypt issues a certificate, and whenever issuance fails, the edge serves that hostname a certificate from its own CA. Issuance is retried at every start of an instance, and
canasta doctorreports a hostname still waiting for one. - Renewal runs in the
canasta-edge-acmecontainer, which installs a renewed certificate in HAProxy without a reload. - Staging certificates.
CANASTA_STAGING_CERTS=true(orcanasta create --staging-certs) gets the instance's certificates from Let's Encrypt's staging CA, as described in Staging certificates for testing. Switching between staging and production replaces the instance's certificates at the next start. - Changing the mode takes effect at the next start: certificates the edge no longer needs are removed, and new ones are obtained or created.
- The edge's CA certificate is
ca/ca.crtin the edge directory. Its certificates last 825 days. Import it into a browser or system trust store to trustinternalcertificates on machines you control. - A custom certificate is copied into the edge at every start, so a replaced file takes effect at the next
canasta restartorcanasta reconcile.
DNS validation
acme-dns proves control of a hostname by creating a DNS record through the provider's API, so it works when port 80 is not reachable from Let's Encrypt, for example behind a CDN that challenges automated clients. The keys:
| Key | Meaning |
|---|---|
ACME_DNS_PROVIDER |
The DNS provider. cloudflare (the default) is the only one supported.
|
CLOUDFLARE_API_TOKEN |
An API token that can edit the DNS records of the zone that holds the instance's hostnames. Stored as a secret. |
CLOUDFLARE_ZONE_ID |
The zone's ID. Optional for a single instance; required for every acme-dns instance when instances on one host use different tokens, since the edge then keeps each token with its own certificates.
|
A changed token takes effect at the instance's next start, for new certificates and renewals alike. Help:User journeys/Cloudflare in front of the edge walks through creating the token.
Behind a CDN
A CDN in front of the edge connects to it from the CDN's own addresses. To keep per-client rate limits, deny lists and CrowdSec working, tell the edge which CDN or proxy it is behind with TRUSTED_PROXIES:
| Value | The edge takes the client address from |
|---|---|
cloudflare |
CF-Connecting-IP, on connections from Cloudflare's published address ranges only.
|
imperva |
Incap-Client-IP, on connections from Imperva's published address ranges only.
|
| comma-separated CIDRs | The last X-Forwarded-For entry, on connections from the listed networks only.
|
Connections from anywhere else keep their own address, so a client that reaches the host directly cannot choose the address it is counted as. The setting applies to the instance's hostnames only; other instances on the host are unaffected. The edge refreshes the CDN's address ranges from the CDN at every start, keeps the last copy it fetched, and falls back to a list shipped with Canasta when it has none. The edge passes the recovered address on to Caddy and MediaWiki in X-Forwarded-For.
Origin TLS modes
When the CDN connects to the origin over HTTPS and validates the certificate (Cloudflare's Full (strict) mode, or the equivalent elsewhere), the edge must serve a publicly trusted certificate or the CDN's origin certificate:
TLS_MODE=acme-dnsobtains Let's Encrypt certificates without depending on the CDN to pass HTTP challenges through.TLS_MODE=acmeworks when the CDN passes/.well-known/acme-challenge/requests on port 80 through to the origin unchallenged.TLS_MODE=customserves an origin certificate the CDN issued.
When the CDN connects over HTTPS but does not validate the certificate (Cloudflare's Full mode), TLS_MODE=internal is enough.
When the CDN connects to the origin over plain HTTP (Cloudflare's Flexible mode), serve the instance over plain HTTP with TLS_MODE=off, and set TRUSTED_PROXIES so the edge trusts the CDN's addresses and its X-Forwarded-Proto header.
See Help:Using Canasta with Cloudflare for the Cloudflare settings.
Rate limits and connection caps
The edge sorts each request for a wiki hostname into one of two classes:
- Dynamic: requests that always reach PHP:
api.phpandrest.php, special pages, diffs and old revisions, any action other thanview, any method other thanGET, and requests from logged-in users (a session or token cookie, or anAuthorizationheader). - Default: everything else: page views that Varnish can answer from its cache, and static files.
For each class, the edge counts one client's requests over a 10-second window and answers 429 once the client exceeds the limit. Independently of these limits, a client that draws more than 50 error responses in 10 seconds, as a scanner probing for paths does, also gets 429. Each class also has a cap on the requests the edge passes to the instance at once; further requests wait in a queue for up to 30 seconds, and get 503 if they are still waiting then.
Requests for media hostnames are not rate-limited per client, since they never reach PHP, and have a connection cap of their own.
Requests from private and loopback addresses are not rate-limited per client: they come from the host itself, such as a wiki calling its own site, or from its local network. The edge applies no per-client rate limits where it cannot see visitors' addresses: an instance served over plain HTTP whose proxy is not named in TRUSTED_PROXIES, and an instance on rootless Docker unless you set the rate keys yourself. The connection caps still apply.
The limits are set per instance, in its .env:
| Key | Default | Meaning |
|---|---|---|
CANASTA_EDGE_RATE_DYNAMIC |
60 |
Dynamic requests one client may make in 10 seconds before the edge answers 429. 0 turns the limit off.
|
CANASTA_EDGE_RATE_DEFAULT |
300 |
Default requests one client may make in 10 seconds before the edge answers 429. 0 turns the limit off.
|
CANASTA_EDGE_DYNAMIC_MAXCONN |
60% of PM_MAX_CHILDREN, rounded up (15 with the default of 25) |
Dynamic requests the edge passes to the instance at once. Kept below the PHP pool size so that page views still find a free PHP worker. |
CANASTA_EDGE_DEFAULT_MAXCONN |
8 × PM_MAX_CHILDREN (200 with the default), or 2 × without Varnish |
Default requests the edge passes to the instance at once. |
CANASTA_EDGE_MEDIA_MAXCONN |
500 |
Requests for the instance's media hostnames the edge passes on at once. |
canasta config set -i <instance-id> CANASTA_EDGE_RATE_DYNAMIC=120
A limit counts per client address, so the visitors behind one shared address (an office or campus network, or a CDN without TRUSTED_PROXIES) share one allowance. Raise the limits for an instance whose editors work from one network, or whose CDN is not configured. A value that is not a number is refused when the instance next starts, with a message naming the key.
Deny lists
Two optional files in an instance's config/ directory list clients the edge refuses with 403 on all the instance's hostnames, media hostnames included:
| File | One entry per line |
|---|---|
config/edge-deny-cidrs.list |
An IPv4 or IPv6 address or CIDR range. |
config/edge-deny-user-agents.list |
Text that, found anywhere in a request's User-Agent, refuses it. Matching ignores case.
|
Blank lines and lines starting with # are ignored. For example:
# config/edge-deny-cidrs.list
192.0.2.0/24
2001:db8::/32
# config/edge-deny-user-agents.list
GPTBot
Bytespider
An entry that is not an address or range, or a User-Agent line with a control character, is refused with a message naming the file and line. The lists apply when the client address is the visitor's, which behind a CDN requires TRUSTED_PROXIES. Both files are in config/, so backups and gitops carry them.
CrowdSec at the edge
When CrowdSec is enabled on an instance, the instance also runs a CrowdSec bouncer for the edge, crowdsec-spoa, enrolled with that instance's CrowdSec. The edge asks it about every request for the instance's hostnames, before deny lists and rate limits, and refuses a banned client with a plain 403, so banned clients never count against a limit or reach Caddy. If the bouncer does not answer in time, the edge lets the request through, and Caddy's own CrowdSec bouncer still refuses banned clients.
Each instance has its own bouncer and its own decisions; a ban on one instance does not apply to the others on the host. The bouncer is enrolled automatically when CrowdSec is enabled; canasta crowdsec status lists it as canasta-edge, next to Caddy's canasta-caddy.
Per-instance HAProxy directives
config/haproxy-backend.cfg holds HAProxy directives for the instance's backends at the edge. Canasta creates it with only comments and never overwrites it. Each line that is not blank or a comment is added to every one of the instance's backends (dynamic, default and media), after Canasta's own CrowdSec, deny-list, rate-limit and not-running rules:
http-request deny if { path_beg /private }
http-request deny if { path_beg /wiki/Special:UserLogin } !{ src 192.0.2.0/24 }
timeout server 300s
Only backend directives belong here; see the HAProxy 3.2 configuration manual. A line that starts a new section (frontend, backend, global, defaults and the like) is refused, since it would end the instance's backend and capture the rest of the generated configuration.
Before installing any change, the edge checks the whole generated configuration with haproxy -c. A configuration HAProxy would not load is refused with HAProxy's message, and the edge keeps serving the previous one.
Extra sites in Caddyfile.global
Site blocks in an instance's config/Caddyfile.global (a www redirect, say) are served behind the edge too. The edge routes each site address that is a plain hostname to the instance and gets it a certificate under the instance's TLS_MODE, and Caddy serves the block over plain HTTP. For example, this block needs nothing else behind the edge:
www.example.com {
redir https://example.com{uri} permanent
}
A site address the edge cannot route by hostname is reported when the instance starts, and is not reachable from outside the host:
- an address with a placeholder, such as
{$WWW_HOST} - a wildcard, such as
*.example.com - a port other than 80 or 443, such as
example.com:8080 localhostor an IP address
Global options blocks and snippet definitions ((name) { ... }) are not site blocks and are left alone. A global options block's settings merge with the ones Canasta generates; for example, a servers block that sets timeouts is combined with Canasta's servers block for the trusted proxies.
Media hostnames
Hostnames declared in an instance's config/media-hosts.yaml, which serve uploads from object storage, are routed and given certificates like wiki hostnames. They use their own backend, with the connection cap CANASTA_EDGE_MEDIA_MAXCONN, no per-client rate limit, and the instance's CrowdSec bans and deny lists.
Hostnames across instances
On each port, a hostname (wiki, media, or Caddyfile.global site) can belong to one instance on the host. A hostname two instances claim on the same port is refused when the second one starts, with a message naming both.
IPv6
When the host has IPv6, the edge listens on IPv6 as well as IPv4, and its container network gets an IPv6 subnet (fd63:616e:6173:7461::/64), so connections from IPv6 visitors arrive with their own addresses. Rate limits, CrowdSec and IPv6 deny-list entries then apply to each IPv6 visitor. Publish AAAA records for the hostnames only on hosts with IPv6.
The network keeps the IPv6 setting it was created with while instances are behind the edge. If the host gains or loses IPv6 later, each start reports it, and the network is created with the new setting once no instance is behind the edge any more, for example after the last instance on the host is deleted.
Applying changes
The edge's configuration is generated from the instances behind it each time one of them starts. A change to any of these takes effect at the instance's next canasta restart or canasta reconcile:
HTTP_PORT,HTTPS_PORT, theCANASTA_EDGE_*keys,TLS_MODE,TRUSTED_PROXIES, and the DNS validation keysconfig/haproxy-backend.cfgand the deny lists- hostnames in
config/wikis.yaml,config/media-hosts.yamland site blocks inconfig/Caddyfile.global
canasta reconcile applies the change without stopping the instance, and the edge reloads without dropping connections. canasta config set and config unset restart the instance unless you pass --no-restart.
If the edge refuses the new configuration, restart and reconcile still bring the instance up, served by the edge's previous configuration, then fail with the reason: "The HAProxy edge keeps its previous configuration until this is fixed; run 'canasta restart' again afterwards." If the edge itself is not running, there is no previous configuration to fall back on, and the command fails before starting the instance.
canasta reconcile -i <instance-id>
Commands for several instances on one host may run at the same time; they take turns updating the edge.
Where the edge lives
The edge's files are in the edge directory under the operator's Canasta configuration directory on the instance's host: /etc/canasta/edge when canasta runs as root, otherwise ~/.config/canasta/edge (or $CANASTA_CONFIG_DIR/edge when that variable is set).
| Path | Contents |
|---|---|
docker-compose.yml |
The edge's Compose project. |
members.yaml |
The instances that joined the edge, so a stopped instance keeps its route. |
conf/ |
The configuration mounted into HAProxy: haproxy.cfg, crt-list, hosts.map, the address and User-Agent lists, and one CrowdSec spoe-<instance-id>.cfg per instance with CrowdSec.
|
conf/certs/ |
One certificate file per hostname (one per instance for custom).
|
ca/ |
The edge's CA, which signs internal certificates and the placeholder certificates served until Let's Encrypt issues.
|
acme/ |
acme.sh's Let's Encrypt account, certificates and renewal state. |
Under rootless Podman, the operator's ~/.config/systemd/user/ also holds canasta-edge.socket and canasta-edge.service, which run HAProxy; canasta-edge-acme stays in the Compose project.
Each instance also has a generated docker-compose.edge.yml in its directory, which attaches its Caddy to the edge's network and, with CrowdSec, adds its edge bouncer. Gitops ignores it.
Do not edit these files. Everything in them is generated from the instances and is overwritten at the next start; put changes in the instance's .env, config/haproxy-backend.cfg or deny lists instead. The edge directory is not part of any instance's backup: an instance restored on another host gets that host's edge, which obtains its certificates again.
Checking status
canasta doctor -i <instance-id> includes an HAProxy edge section:
HAProxy edge (mywiki): edge: running (Up 3 days) member: yes CrowdSec bouncer: running (Up 3 days) acme.sh: running (Up 3 days) wiki.example.com: Let's Encrypt production, renews 2026-12-01T00:00:00Z
It warns when the edge, acme.sh or the CrowdSec bouncer is not running, when the instance is missing from the edge's members, for each hostname still served a certificate from the edge's CA, and when the edge cannot see visitors' addresses (rootless Docker, or plain HTTP behind a proxy TRUSTED_PROXIES does not name). The Origin TLS section checks the certificate the edge actually serves on the instance's HTTPS port.
The edge's request log is the container log:
docker logs --tail 50 canasta-edge
Under Podman, use podman logs, or journalctl --user -u canasta-edge.service for the unit.
Caddy behind the edge
An instance's Caddy serves its sites over plain HTTP on the edge's network and holds no certificates. It trusts the X-Forwarded-For header only from the edge's private network, so MediaWiki records the visitor's address. config/Caddyfile.site applies as before, so redirects, headers and User-Agent blocks there keep working. CrowdSec's Caddy bouncer keeps running too, behind the edge's.
Troubleshooting
| Symptom | Cause and fix |
|---|---|
No site is served at this address. (404) |
No instance serves the hostname on that port. Check the URL in config/wikis.yaml and the instance's HTTP_PORT and HTTPS_PORT.
|
This site is not running. (503) |
The instance is stopped, or its Caddy is not running. canasta start -i <instance-id>.
|
429 Too Many Requests for real users |
Several users share one address, or a CDN is not named in TRUSTED_PROXIES. See Rate limits and connection caps.
|
Browser rejects the certificate; canasta doctor says the edge serves its own CA's certificate |
Let's Encrypt has not issued one. For acme, check that the hostname resolves to this host and that port 80 reaches it from the internet; the start that tried reports Let's Encrypt's reason. For acme-dns, check the token's permissions. Then canasta restart.
|
"Ports ... must be free for the HAProxy edge" (create) or "The HAProxy edge needs ports ..., but something is already listening on them" (start) |
Another web server holds one of the ports. Stop it, or give the instance other ports with HTTP_PORT and HTTPS_PORT.
|
| "The rendered edge configuration is invalid" | A line in config/haproxy-backend.cfg is not valid HAProxy. Fix it and run canasta restart.
|
| "Instances 'a' and 'b' both serve example.com on port 443" | Two instances claim one hostname on one port. Remove it from one of them, or give one of them other ports. |
| "Instances 'a' and 'b' are both reached by localhost or an IP address on port ..." | Give one of them its own HTTP_PORT and HTTPS_PORT.
|
| "Port ... is both an HTTP port and an HTTPS port of the edge's instances" | One instance's HTTP_PORT is another's HTTPS_PORT. Change one of them.
|
| "use acme-dns with different Cloudflare tokens" | Set CLOUDFLARE_ZONE_ID on each of those instances.
|
A Caddyfile.global site is reported as one the edge cannot route |
See Extra sites in Caddyfile.global. Replace the placeholder, wildcard or port with plain hostnames. |
| The upgrade reports "not upgrading <host>: its instances use both Docker and Podman" | One edge serves a host in one runtime. Move one runtime's instances to another host, or onto the same runtime. |
The upgrade or create reports that rootless Podman needs the operator's systemd user session |
Enable lingering for the operator (canasta install podman does), then run the command again.
|
| The upgrade reports "moving <instance> behind the HAProxy edge on <host> failed" | The instance is back on its own Caddy and was not upgraded. Fix the reason the message gives (often config/haproxy-backend.cfg), then run the upgrade again.
|
See also
- Help:Networking and TLS: the request path on each orchestrator.
- Help:Using Canasta with Cloudflare: Cloudflare SSL/TLS modes and the real client IP.
- Help:User journeys/Cloudflare in front of the edge: a worked example with DNS validation.
- Help:User journeys/Combatting bots and scrapers: the other layers of crawler defense.
- Help:CrowdSec: behavioral blocking.
- Help:Upgrading: what the upgrade changes.