# How the CasaOS Storage Service Manages External Storage Mounts

> Discover how CasaOS storage service securely manages external storage mounts like SMB, NFS, and cloud drives using rclone and a local API for automatic boot mounting. Learn more!

- Repository: [IceWhale/CasaOS](https://github.com/IceWhaleTech/CasaOS)
- Tags: how-to-guide
- Published: 2026-06-28

---

**CasaOS abstracts external storage handling through a dedicated Storage Service that communicates with an embedded rclone instance via a local Unix-socket HTTP API, enabling automatic mounting of SMB, NFS, and cloud drives at boot.**

The CasaOS storage service provides a unified interface for integrating external storage devices and cloud remotes into the local filesystem. By leveraging rclone as the underlying engine and exposing a Go-based service layer, CasaOS treats SMB shares, NFS exports, and cloud storage providers as first-class citizens that persist across reboots. This article examines the source code implementation to explain how the CasaOS storage service manages external storage mounts through configuration, mounting, and reconciliation workflows.

## Architecture Overview

The storage subsystem consists of three primary layers. The **model layer** defines the `StorageA` struct in [`model/storage.go`](https://github.com/IceWhaleTech/CasaOS/blob/main/model/storage.go) to persist mount metadata. The **httper driver** in [`pkg/utils/httper/drive.go`](https://github.com/IceWhaleTech/CasaOS/blob/main/pkg/utils/httper/drive.go) handles low-level HTTP communication with rclone's Unix socket. Finally, the **service layer** in [`service/storage.go`](https://github.com/IceWhaleTech/CasaOS/blob/main/service/storage.go) orchestrates high-level operations like mounting and automatic reconciliation.

## How External Storage Mounts Work in CasaOS

### 1. Creating Remote Configurations

When a user adds a new external drive, the service constructs a key-value map describing the remote. The `CreateConfig` method in [`pkg/utils/httper/drive.go`](https://github.com/IceWhaleTech/CasaOS/blob/main/pkg/utils/httper/drive.go) (lines 13-30) translates this map into a JSON payload and posts it to rclone's `/config/create` endpoint.

This process stores credentials and connection parameters without exposing them to the host environment variables directly. The configuration persists in rclone's internal config database, keyed by a friendly name provided by the user.

### 2. Mounting External Drives

After configuration, the `MountStorage` method in [`service/storage.go`](https://github.com/IceWhaleTech/CasaOS/blob/main/service/storage.go) (lines 27-30) prepares the mount point using `file.IsNotExistMkDir` to create the directory if missing. It then invokes `httper.Mount`, which posts a form to rclone's `/mount/mount` endpoint with three critical parameters:

- **mount_point**: The local filesystem path
- **fs**: The remote identifier in rclone syntax (e.g., `my-remote:`)
- **options**: Mount flags including `AllowOther` and `CacheMode`

The implementation in [`pkg/utils/httper/drive.go`](https://github.com/IceWhaleTech/CasaOS/blob/main/pkg/utils/httper/drive.go) (lines 80-95) handles the HTTP POST via a Resty client bound to `/var/run/rclone/rclone.sock`.

### 3. Automatic Reconciliation at Startup

To ensure persistence across reboots, `CheckAndMountAll` in [`service/storage.go`](https://github.com/IceWhaleTech/CasaOS/blob/main/service/storage.go) (lines 66-99) implements a reconciliation loop. The method retrieves all remote names via `httper.GetAllConfigName`, then iterates through each configuration.

For every remote, it extracts the `mount_point` from `GetConfigByName` and checks active mounts using `GetStorages`. If a defined remote lacks an active mount, the service automatically invokes `MountStorage`. This guarantees that SMB shares, cloud drives, and NFS mounts become available immediately after CasaOS starts.

### 4. Unmounting and Cleanup

Removal operations follow the reverse path. `UnmountStorage` in [`service/storage.go`](https://github.com/IceWhaleTech/CasaOS/blob/main/service/storage.go) (lines 31-40) calls `httper.Unmount`, which posts to rclone's `/mount/unmount` endpoint (implemented in [`drive.go`](https://github.com/IceWhaleTech/CasaOS/blob/main/drive.go) lines 96-110). 

After a successful unmount, the service removes the empty mount-point directory from the local filesystem. This prevents stale directory accumulation while ensuring clean detachment of network storage.

## Data Model and HTTP Client

Each external storage entry is represented by the `StorageA` struct defined in [`model/storage.go`](https://github.com/IceWhaleTech/CasaOS/blob/main/model/storage.go) (lines 5-18). This structure tracks:

- **MountPath**: The local directory where the remote is attached
- **Driver**: The storage backend type (smb, nfs, onedrive, etc.)
- **Status**: Current operational state
- **Addition**: Driver-specific configuration data

All API communication occurs through a dedicated Resty client created by `NewRestyClient` in [`pkg/utils/httper/drive.go`](https://github.com/IceWhaleTech/CasaOS/blob/main/pkg/utils/httper/drive.go) (lines 47-61). This client binds exclusively to the Unix socket at `/var/run/rclone/rclone.sock`, ensuring the storage service never requires direct external network access. All rclone operations—configuration, mounting, and unmounting—flow through this private channel.

## Practical Implementation Examples

The following Go examples demonstrate the storage service API as implemented in the CasaOS codebase:

```go
// Example: add a new SMB share and mount it
func addAndMountSMB() error {
    // 1️⃣ Build the config map expected by rclone
    cfg := map[string]string{
        "type":          "smb",
        "host":          "192.168.1.100",
        "user":          "guest",
        "pass":          "password",
        "mount_point":   "/mnt/smb-share",
        "vendor":        "smb",
    }

    // 2️⃣ Store the config under a friendly name
    if err := MyService.Storage().CreateConfig(cfg, "my-smb", "smb"); err != nil {
        return err
    }

    // 3️⃣ Mount the newly created remote
    // The fs argument follows rclone syntax: "<remote_name>:" (note the trailing colon)
    return MyService.Storage().MountStorage(cfg["mount_point"], "my-smb:")
}

```

```go
// Example: ensure all defined remotes are mounted (called on startup)
func reconcileMounts() error {
    return MyService.Storage().CheckAndMountAll()
}

```

```go
// Example: unmount and clean up a specific mount point
func unmountShare(mp string) error {
    return MyService.Storage().UnmountStorage(mp)
}

```

## Summary

- **CasaOS manages external storage** through a Storage Service that wraps an embedded rclone instance communicating over a Unix socket at `/var/run/rclone/rclone.sock`.
- **Configuration persistence** occurs via `CreateConfig` in [`pkg/utils/httper/drive.go`](https://github.com/IceWhaleTech/CasaOS/blob/main/pkg/utils/httper/drive.go), which posts to rclone's `/config/create` endpoint.
- **Mount operations** are handled by `MountStorage` in [`service/storage.go`](https://github.com/IceWhaleTech/CasaOS/blob/main/service/storage.go), creating local directories and invoking rclone's `/mount/mount` API.
- **Automatic reconciliation** via `CheckAndMountAll` ensures all defined remotes mount automatically after system restarts.
- **Clean unmounting** removes both the rclone mount and the local directory through `UnmountStorage`.

## Frequently Asked Questions

### How does CasaOS handle external storage without direct network calls?

The storage service uses a dedicated Resty HTTP client bound to a local Unix socket at `/var/run/rclone/rclone.sock`. All communication with rclone—including configuration, mounting, and unmounting—traverses this private channel. The rclone process itself handles external network connectivity, while CasaOS remains isolated from direct remote storage protocols.

### What happens to external mounts when CasaOS restarts?

The `CheckAndMountAll` method in [`service/storage.go`](https://github.com/IceWhaleTech/CasaOS/blob/main/service/storage.go) (lines 66-99) executes during startup. It iterates through all stored configurations retrieved via `httper.GetAllConfigName`, verifies active mounts against the desired state, and automatically remounts any missing remotes. This reconciliation loop ensures SMB shares, cloud drives, and NFS exports persist across reboots without manual intervention.

### Which remote storage types does CasaOS support?

CasaOS supports any storage backend compatible with rclone, including SMB, NFS, OneDrive, Dropbox, Google Drive, and S3-compatible object storage. The `StorageA` model in [`model/storage.go`](https://github.com/IceWhaleTech/CasaOS/blob/main/model/storage.go) stores the driver type in the `Driver` field, while the `Addition` field accommodates driver-specific configuration parameters required by each backend.

### Where does CasaOS store external storage configuration?

Configuration data persists in two locations. The rclone-specific connection parameters (credentials, endpoints, options) are stored in rclone's internal configuration database via the `/config/create` API endpoint. The CasaOS-specific metadata—including mount points, status, and driver type—is stored in the CasaOS database via the `StorageA` struct defined in [`model/storage.go`](https://github.com/IceWhaleTech/CasaOS/blob/main/model/storage.go).