Not affiliated with IceWhale. An independent, community-maintained distribution of CasaOS, not produced or endorsed by Shanghai IceWhale Technology Limited. CASAOS is their trademark, used here only to say what this is a release of. The original project is IceWhaleTech/CasaOS; report problems with this distribution at ReCasaOS/CasaOS/issues.
The gateway is the only CasaOS service bound to a public port. Every other component — the system API, app management, user accounts, the message bus, local storage — listens on loopback and registers a path prefix here; the gateway forwards each request to whichever service claimed the longest matching prefix. It also serves the dashboard's files.
This repository is part of ReCasaOS, a maintained release of the project after upstream IceWhaleTech/CasaOS-Gateway stopped shipping in 2025. It descends from alvins82's fork, whose Ubuntu 26 fix to the setup script is still in here.
Three listeners, from one process:
- The public port — the proxy itself, plus
GET /ping. Paths are matched longest first, so a route on/v1/appsis not swallowed by one on/v1.X-Forwarded-ForandX-Real-IPare rewritten before forwarding, so a service behind the gateway sees the address the connection actually came from rather than one a client claimed. - The management API, on
127.0.0.1at a port the kernel assigns.GETandPOST /v1/gateway/routeslist and register routes;GETandPUT /v1/gateway/portread and change the public port. All four need either a person's CasaOS JWT or, from loopback,Authorization: Internal <secret>, where the secret is the one the gateway writes to/var/run/casaos/internal.secret(root only, mode 0600) at every start. Coming from loopback is not enough on its own: any local process can do that. The address is written to/var/run/casaos/management.url, which is how the other services find it, and the port endpoint is also proxied on the public port under/v1/gateway/port. - The static server, on
127.0.0.1at another assigned port, serving the dashboard from the directory given by-w, which the shipped systemd unit leaves at its default of/var/lib/casaos/www, and registered as the route/. Its address goes to/var/run/casaos/static.url.
Changing the port opens the new listener, waits for it to answer /ping, and stops the old one a second later so requests already in flight still get a response. Registered routes are kept in /var/run/casaos/routes.json.
Components are not installed individually. The installer places all of them:
curl -fsSL https://github.com/ReCasaOS/CasaOS-Install/releases/latest/download/install.sh | sudo bashCasaOS-Install describes what a release contains and how it is built.
/etc/casaos/gateway.ini, written from the sample on first start if it does not exist:
[common]
runtimepath=/var/run/casaos
[gateway]
port=
address=
tlscert=
tlskey=
httpsport=port is the public port. Left empty, the service takes the first free port from 80–89, then 8080–8089, and writes its choice back to this file; changing the port from the dashboard rewrites it too.
address is the interface that port binds to. Empty, the default, binds every interface as dual-stack [::]. Set it to one address to keep the dashboard off an untrusted network without a firewall rule. The management and static listeners stay on 127.0.0.1 either way.
tlscert and tlskey are a certificate and private key you supply. With both set the gateway serves HTTPS, with neither it serves plain HTTP. Half a pair falls back to HTTP rather than leaving a box unreachable through the only thing that serves its UI.
The file is looked for in the working directory, then ./conf, then $CASAOS_CONFIG_PATH if it is set, then /etc/casaos. Logs are written to /var/log/casaos/gateway.log.
A service behind this gateway should bind loopback only — 127.0.0.1, or ::1 — since the gateway is the part meant to be reachable.
- HTTPS without configuring anything (v0.4.27). When no certificate is supplied, the gateway makes one for itself on first start (
/var/lib/casaos/tls/gateway.crt, ten years, this box's hostname and the loopback addresses) and serves the same routes over HTTPS onhttpsport, 443 unless the configuration says otherwise, beside the plain port. Self-signed, so the browser warns once; the plain port is still there, andhttpsport=0turns the second one off. A port somebody else holds is logged and skipped. The dashboard was readable on the wire and denied the browser APIs that need a secure context, the clipboard first among them. - TLS with an administrator-supplied certificate, the
tlscertandtlskeykeys above. The key pair is parsed before the listener is swapped, so a bad certificate fails the reload with an error instead of killing the serving goroutine once the old listener is already gone. There is no ACME and no self-signed generation: automatic issuance needs port 80 reachable from the internet or registrar credentials, which belongs in a reverse proxy. This covers the bring-your-own-certificate half of CasaOS #1074. - The secret of this boot (v0.4.26). The gateway writes a random secret to the runtime path at every start, readable by root only, before it writes its management address; every service asks for it on loopback instead of trusting the interface, since a container on the host network or any local account reaches the same addresses. The management API, which asked for a token from the network and nothing from loopback, takes the same rule: the secret, or a person's token.
address=, binding the public port to one interface (v0.4.41). Both bind sites were hard-wired to every interface before. The idea comes from CasaOS-Gateway #56, rewritten smaller: no state plumbing, and nogateway.urlfile, which nothing ever read and which the code had never written.- A health check that works. Every branch of it was inverted: it reported success without looking at the status code, reported failure when the status was 200 OK, and dereferenced a nil response on the unreachable path, so a service that was not up yet panicked the gateway instead of being retried — and the retry loop never retried anything. It now lives in
pkg/, with a test. - A release pipeline that can run here. Upstream's workflow called an IceWhale reusable workflow needing Aliyun credentials and published to the
IceWhaleTechorganisation, so a fork could never cut a release. It is a self-contained job now: it runs the tests, cross-builds static binaries for amd64, arm64 and arm/v7, and publishes the tarballs with thechecksums.txtthe installer verifies against. - No geo-IP at install time.
build/scripts/migration/script.dran__get_download_domainat top level, curlingipconfig.io/countryand thenifconfig.io/country_codeto pick a download mirror by country.install.shruns every script in that directory on every install and every upgrade, so both services were contacted each time, before the script had even decided whether a migration was due — which, on anything but a pre-0.4 box, it never is. The migration tools now come from GitHub unconditionally, and the domain is a constant: it is not an environment knob either, because what it points at is downloaded and run as root without verification. - Ubuntu 26 setup, inherited from alvins82. The setup script picks its per-distribution script by walking a candidate list —
ID/VERSION_CODENAME, thenID, then each entry ofID_LIKE— and says which OS it could not place when none of them exists, in place of nestedpushdfallbacks that did not resolve on Ubuntu 26. - Its own module path. The Go module is
github.com/ReCasaOS/CasaOS-Gatewayand it builds againstgithub.com/ReCasaOS/CasaOS-Common v0.4.22, so log lines, stack traces andgo version -mon the shipped binary name this fork instead of the upstream that stopped shipping.
Go, as declared in go.mod. Build, vet and test:
go build ./...
go vet ./...
go test ./...Running the binary from a checkout needs a gateway.ini it can find and a writable runtimepath; go test covers the config loading, the TLS configuration, the health check, the management routes and route persistence without either.
Apache License 2.0 — see LICENSE, kept as upstream shipped it. It is the stock Apache text: neither the licence file nor any source file carries a copyright line, and none has been added here.
CasaOS and this gateway are the work of IceWhale and its contributors; the Ubuntu 26 setup fallback is alvins82's. CasaOS is a mark of IceWhale, used here to say what this is a release of and nothing more.