How ZeroTier Network Integration Works in CasaOS: Architecture and API Deep Dive
CasaOS integrates ZeroTier by wrapping the local daemon's HTTP API in Go helper functions (ZTGet, ZTPost), exposing network status through a structured v2 REST endpoint, and providing a legacy v1 proxy for raw daemon passthrough, all while auto-configuring the CasaOS virtual network on startup.
CasaOS embeds ZeroTier support to enable seamless virtual LAN creation without manual CLI configuration. The integration leverages the ZeroTier One daemon's local HTTP API, consuming token files for authentication and dynamic port discovery. By examining the source code in route/v2/zerotier.go and pkg/utils/httper, you can see exactly how the home-server platform bridges containers and hosts across NAT boundaries.
The ZeroTier HTTP Client Layer
The foundation of CasaOS's ZeroTier support lies in thin HTTP wrappers that handle authentication and request signing. These helpers isolate the rest of the codebase from the daemon's local API mechanics.
Authentication and Port Discovery
Before making any requests, CasaOS locates the running ZeroTier daemon by reading two files from /var/lib/zerotier-one/:
zerotier-one.port– contains the TCP port number the daemon is listening on (typically9993).authtoken.secret– contains the ephemeral authentication token required for theX-ZT1-AUTHheader.
These values are loaded at runtime and injected into every request to ensure only the local CasaOS process can command the daemon.
Core Helper Functions
The utility functions live in pkg/utils/httper/zerotier.go and pkg/utils/httper/httper.go:
ZTGet(path string) ([]byte, error)constructs aGETrequest tohttp://127.0.0.1:<port><path>, adds theX-ZT1-AUTHheader, and returns the raw response body.ZTPost(path string, body string) ([]byte, error)performs the same setup but sends aPOSTrequest with the provided JSON payload.ZeroTierGet(url string, head map[string]string)is a generic variant used for remote controller endpoints, returning both the response body and HTTP status code.
These functions abstract the low-level details of the ZeroTier API, allowing higher-level business logic to focus on network management rather than HTTP boilerplate.
Querying Network Status via the v2 API
The modern REST interface is implemented in route/v2/zerotier.go, specifically within the GetZerotierInfo handler. This endpoint drives the CasaOS dashboard's network status widget.
The GetZerotierInfo Handler
When the UI requests GET /api/v2/zerotier/info, the handler executes the following flow:
- Calls
httper.ZTGet("/controller/network")to list all networks managed by the local daemon. - Iterates through the network array using
gjsonfor efficient JSON parsing. - Identifies the CasaOS-specific network by matching
common.RANW_NAMEagainst thenamefield. - Fetches detailed network configuration via
ZTGet("/controller/network/" + networkID).
func (s *CasaOS) GetZerotierInfo(ctx echo.Context) error {
info := codegen.GetZTInfoOK{}
respBody, err := httper.ZTGet("/controller/network")
// ... error handling ...
networkNames := gjson.ParseBytes(respBody).Array()
for _, v := range networkNames {
res, err := httper.ZTGet("/controller/network/" + v.Str)
name := gjson.GetBytes(res, "name").Str
if name == common.RANW_NAME {
via := gjson.GetBytes(res, "routes.0.via").Str
info.Id = utils.Ptr(gjson.GetBytes(res, "id").Str)
info.Name = &name
if len(via) == 0 {
info.Status = utils.Ptr("online")
} else {
info.Status = utils.Ptr("offline")
}
break
}
}
return ctx.JSON(http.StatusOK, info)
}
Determining Online/Offline Status
CasaOS infers connectivity by inspecting the routes.0.via field in the network configuration. An empty via value indicates the network is operating in pure Layer-2 mode (or has no upstream gateway), which the codebase interprets as online. A populated via field triggers an offline status, signaling that traffic is being routed through a gateway that may be unreachable.
Legacy Proxy and Network Management
For backward compatibility and raw daemon access, route/v1/zerotier.go implements a transparent proxy and automated network provisioning.
Full Daemon Passthrough via ZerotierProxy
The ZerotierProxy function allows arbitrary ZeroTier API calls by forwarding any request matching /v1/zt/* directly to the local daemon:
func ZerotierProxy(ctx echo.Context) error {
port, err := ioutil.ReadFile("/var/lib/zerotier-one/zerotier-one.port")
path := strings.TrimPrefix(r.URL.Path, "/v1/zt")
targetURL := fmt.Sprintf("http://localhost:%s%s", strings.TrimSpace(string(port)), path)
req, err := http.NewRequest(r.Method, targetURL, r.Body)
authToken, _ := ioutil.ReadFile("/var/lib/zerotier-one/authtoken.secret")
req.Header.Set("X-ZT1-AUTH", strings.TrimSpace(string(authToken)))
resp, err := client.Do(req)
// ... copy headers and write response ...
return nil
}
This enables debugging tools and advanced users to interact with the full ZeroTier controller API through CasaOS's authenticated session.
Automated Network Provisioning
During system initialization, CasaOS ensures the host is joined to the correct virtual network. Functions like CheckNetwork, CreateNet, and JoinAndUpdateNet (all in route/v1/zerotier.go) automate this process:
CheckNetworkverifies if a network matchingcommon.RANW_NAMEexists by querying/controller/network.CreateNetgenerates a new network with a unique CIDR pool if none is found.JoinAndUpdateNetauthorizes the local node's ZeroTier address and assigns a static IP address within the network segment.
All these operations rely on the ZTGet and ZTPost helpers, maintaining clean separation between the HTTP transport and business logic.
Architectural Flow Summary
| Layer | Responsibility | Key Source File |
|---|---|---|
| HTTP Client | Handles auth tokens, port discovery, and raw GET/POST to daemon | pkg/utils/httper/zerotier.go |
| v2 API | Structured JSON responses for UI consumption; network status detection | route/v2/zerotier.go |
| v1 Proxy | Raw passthrough for debugging; full daemon API exposure | route/v1/zerotier.go |
| Auto-Setup | Boot-time network creation and host authorization | route/v1/zerotier.go (network management functions) |
Summary
- CasaOS communicates with the local ZeroTier daemon via authenticated HTTP requests to
127.0.0.1, using token files from/var/lib/zerotier-one/for security. - The
GetZerotierInfohandler inroute/v2/zerotier.goprovides a curated view of network health, determining online status by inspecting theroutes.0.viafield. - A legacy
ZerotierProxyinroute/v1/zerotier.goenables full API passthrough, while helper functions likeZTGetandZTPostkeep the codebase DRY. - Background tasks automatically provision the CasaOS-named network and authorize the host on first boot, ensuring zero-config networking out of the box.
Frequently Asked Questions
How does CasaOS authenticate with the ZeroTier daemon?
CasaOS reads the authtoken.secret file from /var/lib/zerotier-one/ and injects its contents into the X-ZT1-AUTH header for every request. It also reads zerotier-one.port to determine the correct TCP port, ensuring it can locate the daemon even if running on a non-standard port.
What is the difference between the v1 and v2 ZeroTier endpoints?
The v2 endpoint (/api/v2/zerotier/info) is a curated API that returns filtered, JSON-structured data about the CasaOS-specific network, including a simplified online/offline status. The v1 endpoint (/v1/zt/*) acts as a transparent proxy, forwarding raw requests directly to the local ZeroTier daemon for advanced administrative tasks.
How does CasaOS determine if the ZeroTier network is online?
The system queries the network configuration via /controller/network/{id} and inspects the routes.0.via field using gjson. If the via field is empty, the network is marked as online; if it contains a gateway address, the status is reported as offline.
Can I use the CasaOS API to manage arbitrary ZeroTier networks?
Yes. While the v2 API only exposes the CasaOS-specific network (identified by common.RANW_NAME), you can use the v1 proxy endpoint (/v1/zt/) to send arbitrary commands to the local daemon. This allows you to create, join, or modify any network ID permitted by your ZeroTier controller, provided the request includes valid CasaOS authentication cookies or tokens.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →