How CasaOS Gateway Service Manages Dynamic Route Creation

The CasaOS gateway service creates dynamic routes by exposing a Unix socket-based management API that allows the main process to register HTTP paths and backend targets at runtime using the CreateRoute method.

CasaOS utilizes a lightweight reverse-proxy architecture to expose microservices through a unified entry point. The gateway service, implemented as casaos-gateway.service, enables dynamic route creation by accepting runtime commands from the main application via the CasaOS-Common library. This design allows the platform to register API endpoints on-demand without requiring static configuration files or service restarts.

Gateway Client Architecture

The main CasaOS process communicates with the gateway through the external.ManagementService interface provided by the CasaOS-Common library. This interface abstracts the underlying Unix socket communication used to manipulate the proxy's routing table.

In service/service.go, the application obtains a management client during initialization:

// service/service.go – NewService
gatewayManagement, err := external.NewManagementService(RuntimePath)

The RuntimePath parameter typically points to /etc/casaos, where the gateway exposes a Unix socket for local management operations. This client instance is then exposed throughout the application via service.MyService.Gateway(), allowing components to modify routes dynamically.

Dynamic Route Registration Flow

When CasaOS starts, it establishes a dynamic routing table through a three-phase process involving listener creation, route definition, and registration.

Initializing the TCP Listener

The main process first creates a TCP listener on a random available port by binding to 0.0.0.0:0. The operating system assigns an unused port, which the application records to casaos.url for service discovery by other components.

Registering API Prefixes

After the listener is ready, the application iterates over a predefined slice of API paths—including /v1/sys, /v1/port, and route.V2APIPath—and registers each with the gateway. In main.go, the startup loop constructs a model.Route for each endpoint:

// main.go – startup loop
for _, apiPath := range routers {
    err = service.MyService.Gateway().CreateRoute(&model.Route{
        Path:   apiPath,
        Target: "http://" + listener.Addr().String(),
    })
    if err != nil { panic(err) }
}

The model.Route struct (defined in the CasaOS-Common model package) contains two critical fields:

  • Path: The frontend URL prefix (e.g., /v1/sys) that the gateway will expose
  • Target: The backend service address (e.g., http://127.0.0.1:8080) where requests are proxied

This registration happens immediately upon startup, ensuring the gateway's routing table reflects the current set of active APIs.

Runtime Port Configuration

CasaOS supports dynamic port changes without full service restarts. When a user specifies a custom HTTP port in the configuration, the main process invokes the ChangePort method:

// main.go – port-override logic
if config.ServerInfo.HttpPort != "" {
    changePort := model.ChangePortRequest{Port: config.ServerInfo.HttpPort}
    err := service.MyService.Gateway().ChangePort(&changePort)
    if err == nil { /* clear the config flag */ }
}

This operation rewrites the systemd socket unit used by casaos-gateway.service and triggers a reload, causing the proxy to listen on the new port while maintaining existing route registrations.

Managing Routes at Runtime

Beyond the initial registration, the CasaOS gateway service supports full lifecycle management of routes through the ManagementService interface.

Adding Custom Routes

To expose a new microservice at runtime, create a Route instance and call CreateRoute:

newRoute := &model.Route{
    Path:   "/v1/custom",
    Target: "http://127.0.0.1:9000",
}
if err := service.MyService.Gateway().CreateRoute(newRoute); err != nil {
    logger.Error("failed to add custom route", zap.Error(err))
}

Removing Routes

Routes can be deleted dynamically using the DeleteRoute method with the specific path prefix:

if err := service.MyService.Gateway().DeleteRoute("/v1/custom"); err != nil {
    logger.Error("failed to delete custom route", zap.Error(err))
}

Summary

  • CasaOS uses a dedicated casaos-gateway.service process as a reverse proxy, managed via the external.ManagementService interface from CasaOS-Common.
  • Route creation occurs in main.go through the CreateRoute method, which maps frontend paths (like /v1/sys) to backend TCP listeners discovered at runtime.
  • Dynamic ports are handled by ChangePort, which modifies systemd socket units without restarting the entire CasaOS application.
  • Lifecycle management includes DeleteRoute for removing endpoints and automatic cleanup when the gateway service stops via systemd.
  • Key source files include service/service.go for client initialization and main.go for the registration loop.

Frequently Asked Questions

What interface does CasaOS use to communicate with the gateway service?

CasaOS communicates with the gateway through the external.ManagementService interface defined in the CasaOS-Common library. This interface provides methods like CreateRoute, DeleteRoute, and ChangePort, which the main process uses to manipulate the gateway's routing table over a Unix socket connection.

How does CasaOS handle port changes without restarting?

When the HTTP port changes, CasaOS calls ChangePort with a model.ChangePortRequest containing the new port number. According to the implementation in main.go, this method updates the systemd socket unit file for casaos-gateway.service and reloads the systemd configuration, allowing the gateway to bind to the new port while maintaining existing dynamic routes.

Where are the dynamic routes stored in CasaOS?

Dynamic routes are stored in-memory within the gateway service process (casaos-gateway.service). They are not persisted to disk as static configuration files. Instead, the main CasaOS process recreates the routing table at startup by iterating through its API routers and calling CreateRoute for each endpoint, ensuring the gateway always reflects the current active services.

Can custom microservices register their own routes with the CasaOS gateway?

Yes, any component with access to the gateway client can register routes by calling CreateRoute with a model.Route struct containing the desired path and target URL. This allows third-party microservices or plugins to expose their APIs through the CasaOS gateway without modifying static nginx or Apache configuration files.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →