Understanding the Connection Management Service Architecture in CasaOS

CasaOS implements a dedicated service-layer architecture for managing SMB connections, encapsulating database persistence, system-level mounting, and HTTP API concerns behind a clean ConnectionsService interface.

The connection management service architecture in CasaOS provides a robust, testable foundation for handling Samba shares. By isolating SMB operations into a distinct service layer, the codebase maintains separation between HTTP handlers, data persistence, and low-level filesystem mounts. This design leverages GORM for database operations and direct system calls for kernel-level SMB mounting.

Core Components of the Connection Management Service

The architecture consists of three primary components that work together to provide a complete SMB connection lifecycle management solution.

The ConnectionsService Interface

At the heart of the system lies the ConnectionsService interface defined in service/connections.go. This contract establishes the public API for all connection-related operations, ensuring that HTTP handlers remain decoupled from implementation details.

type ConnectionsService interface {
    GetConnectionsList() []model2.ConnectionsDBModel
    GetConnectionByHost(host string) []model2.ConnectionsDBModel
    GetConnectionByID(id string) model2.ConnectionsDBModel
    CreateConnection(*model2.ConnectionsDBModel)
    DeleteConnection(id string)
    UpdateConnection(*model2.ConnectionsDBModel)
    MountSmaba(username, host, directory, port, mountPoint, password string) error
    UnmountSmaba(mountPoint string) error
}

The interface exposes standard CRUD operations for connection metadata alongside specialized mount/unmount methods that handle kernel-level SMB filesystem operations.

The connectionsStruct Implementation

The concrete implementation, connectionsStruct, resides in the same file (service/connections.go) and holds a *gorm.DB reference for database operations. This struct implements all interface methods, bridging the gap between high-level service calls and low-level system execution.

For persistence operations, the implementation uses standard GORM patterns. For filesystem operations, it executes system calls using unix.Mount and mount.Unmount to expose remote SMB shares under /mnt/<host>/ directories. This encapsulation ensures that HTTP handlers never directly interact with the kernel or database driver.

The ConnectionsDBModel Persistence Layer

Connection metadata persists through the ConnectionsDBModel defined in service/model/o_connections.go. This GORM-mapped struct represents the database schema for the o_connections table:

type ConnectionsDBModel struct {
    ID          uint   `gorm:"column:id;primary_key"`
    Updated     int64  `gorm:"autoUpdateTime"`
    Created     int64  `gorm:"autoCreateTime"`
    Username    string
    Password    string
    Host        string
    Port        string
    Status      string
    Directories string // comma-separated list
    MountPoint  string // e.g. "/mnt/<host>"
}

The model serves as the single source of truth for connection configuration, storing credentials, host information, and mount point locations required for SMB operations.

Service Container Integration

The connection service wires into CasaOS's dependency injection container through service/service.go. The NewService function constructs a store struct that aggregates all sub-services, including the connection service instantiated via NewConnectionsService(db).

The container exposes the service through MyService.Connections(), making it available to any caller without requiring direct instantiation. This pattern follows the service-repository architecture, allowing HTTP handlers to access connection management through a standardized facade:

// Access pattern used throughout the application
service.MyService.Connections().GetConnectionsList()

HTTP Handler Integration and Workflow

The route/v1/samba.go file demonstrates how HTTP handlers leverage the connection management service architecture to orchestrate complex SMB workflows while maintaining clean separation of concerns.

Listing Connections

The handler retrieves all configured connections through the service interface, converting database models to API responses:

func GetSambaConnectionsList(ctx echo.Context) error {
    connections := service.MyService.Connections().GetConnectionsList()
    // ...convert to API model and return...
}

This approach keeps the HTTP layer agnostic to database query implementation details.

Creating SMB Connections

Creating a connection involves multiple coordinated steps through the service layer:

func PostSambaConnectionsCreate(ctx echo.Context) error {
    // Parse request → model.Connections
    dirs, err := samba.GetSambaSharesList(host, port, user, pass)
    
    // Build DB model
    conn := model2.ConnectionsDBModel{
        Username:    user,
        Password:    pass,
        Host:        host,
        Port:        port,
        Directories: strings.Join(dirs, ","),
        MountPoint:  "/mnt/" + host,
    }
    
    // Ensure mount root exists
    file.IsNotExistMkDir(conn.MountPoint)
    
    // Mount each discovered share
    for _, d := range dirs {
        mp := conn.MountPoint + "/" + d
        file.IsNotExistMkDir(mp)
        service.MyService.Connections().
            MountSmaba(user, host, d, port, mp, pass)
    }
    
    // Persist the connection record
    service.MyService.Connections().CreateConnection(&conn)
}

The handler orchestrates validation, share discovery, filesystem mounting, and persistence without directly managing database connections or kernel calls.

Deleting Connections

Deletion reverses the creation process by unmounting shares before removing database records:

func DeleteSambaConnections(ctx echo.Context) error {
    id := ctx.Param("id")
    conn := service.MyService.Connections().GetConnectionByID(id)
    
    shares, _ := samba.GetSambaSharesList(conn.Host, conn.Port, 
        conn.Username, conn.Password)
    
    for _, s := range shares {
        mountPath := "/mnt/" + conn.Host + "/" + s
        if service.IsMounted(mountPath) {
            service.MyService.Connections().UnmountSmaba(mountPath)
        }
    }
    
    // Clean up empty mount root
    if empty, _ := ioutil.ReadDir(conn.MountPoint); len(empty) == 0 {
        os.RemoveAll(conn.MountPoint)
    }
    
    service.MyService.Connections().DeleteConnection(id)
}

Dependency Flow and Architecture Pattern

The connection management service architecture in CasaOS follows a clear dependency hierarchy:


HTTP Handler (route/v1/samba.go)
        ↓
   MyService.Connections()  ←─── NewService (store) ──── DB (gorm)
        ↓
   connectionsStruct methods (CRUD + mount/unmount)
        ↓
   GORM → SQLite/PostgreSQL (persisted connections)
   unix/mount → kernel (SMB mounts)

This design implements the service-repository pattern, where HTTP handlers communicate through high-level service interfaces, the service manages repository access via GORM, and system-level actions remain encapsulated within the implementation. The architecture ensures that changes to database schema, ORM configuration, or mount implementation strategies do not cascade into HTTP handler code.

Summary

  • Interface-driven design: The ConnectionsService interface in service/connections.go decouples HTTP handlers from implementation details, enabling testable, maintainable code.
  • Three-layer architecture: The system separates concerns into interface definition (ConnectionsService), concrete implementation (connectionsStruct), and persistence model (ConnectionsDBModel).
  • Service container pattern: NewService in service/service.go wires the connection service into a central repository accessible via MyService.Connections().
  • System call encapsulation: Mount operations use unix.Mount and mount.Unmount internally while exposing simple method signatures to callers.
  • Complete lifecycle management: The architecture handles connection creation, persistence, mounting, unmounting, and deletion through a cohesive API.

Frequently Asked Questions

How does CasaOS persist SMB connection credentials?

CasaOS stores SMB connection credentials in a database table mapped to the ConnectionsDBModel struct in service/model/o_connections.go. The GORM ORM manages this persistence layer, storing username, password, host, port, and mount point information in the o_connections table. The connectionsStruct implementation in service/connections.go handles all database interactions through this model.

What happens when a user creates a new SMB connection in CasaOS?

When creating a connection, the system first validates the request and probes the remote host using samba.GetSambaSharesList to discover available shares. It then creates a ConnectionsDBModel record, establishes the mount point directory under /mnt/<host>/, iterates over discovered shares, and calls MountSmaba for each share via the connection service. Finally, it persists the configuration to the database using CreateConnection.

Why does CasaOS use a service interface for connection management?

The interface-based design allows CasaOS to separate HTTP route handlers from database and filesystem implementation details. This approach enables unit testing through mock implementations, supports future changes to the persistence layer or mount mechanisms without affecting API endpoints, and follows Go best practices for dependency injection. The ConnectionsService interface in service/connections.go defines this contract explicitly.

Where does CasaOS mount SMB shares on the filesystem?

According to the source code in service/connections.go and route/v1/samba.go, CasaOS mounts SMB shares under /mnt/<host>/ directories, where <host> represents the target server hostname. Individual shares mount as subdirectories within this path (e.g., /mnt/servername/sharename). The MountPoint field in ConnectionsDBModel tracks these locations for subsequent unmounting and cleanup operations.

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 →