# How CasaOS Gateway Service Manages Dynamic Route Creation

> Discover how CasaOS gateway service dynamically creates routes using a Unix socket API for runtime registration of HTTP paths and backend targets. Learn about the CreateRoute method.

- Repository: [IceWhale/CasaOS](https://github.com/IceWhaleTech/CasaOS)
- Tags: internals
- Published: 2026-06-27

---

**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`](https://github.com/IceWhaleTech/CasaOS/blob/main/service/service.go), the application obtains a management client during initialization:

```go
// 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`](https://github.com/IceWhaleTech/CasaOS/blob/main/main.go), the startup loop constructs a `model.Route` for each endpoint:

```go
// 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:

```go
// 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`:

```go
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:

```go
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`](https://github.com/IceWhaleTech/CasaOS/blob/main/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`](https://github.com/IceWhaleTech/CasaOS/blob/main/service/service.go) for client initialization and [`main.go`](https://github.com/IceWhaleTech/CasaOS/blob/main/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`](https://github.com/IceWhaleTech/CasaOS/blob/main/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.