How CasaOS Implements the Shares Service for File Sharing
CasaOS implements its shares service using a database-backed Gorm model that synchronizes Samba configuration files and automatically restarts the SMB daemon when shares are created, modified, or deleted.
The CasaOS project provides a dedicated shares service that bridges the gap between database records and Samba-based file sharing. This service manages the complete lifecycle of file shares, from persistence in SQLite to runtime configuration in the Samba daemon. The implementation centers on two primary files: service/shares.go for business logic and service/model/o_shares.go for data modeling.
Architecture of the Shares Service
The shares service follows a database-driven configuration pattern where share definitions live in an SQLite database while Samba consumes generated configuration files.
Database Model and Persistence
At the core of the system is the SharesDBModel struct defined in service/model/o_shares.go. This Gorm model represents the o_shares table and stores essential share metadata including the ID, filesystem path, anonymity flag, and timestamps. When the service initializes via NewSharesService(db *gorm.DB), it receives a *gorm.DB handle that enables all subsequent database operations.
Samba Configuration Generation
The service maintains two key files on the host filesystem:
/etc/samba/smb.casa.conf– The generated include file containing individual share stanzas/etc/samba/smb.conf– The main Samba configuration that imports the CasaOS-specific include
The UpdateConfigFile method reads all rows from the o_shares table and translates each into a Samba share stanza. For example, a share named "myshare" at path /mnt/data becomes a configuration block like [myshare] with the path directive set accordingly.
Core Implementation Files
The shares service implementation spans several critical files within the CasaOS repository:
service/shares.go– Implements theSharesServiceinterface with CRUD operations and Samba configuration managementservice/model/o_shares.go– Defines theSharesDBModelstruct and database schema for theo_sharestablepkg/utils/file– Provides utility functions for file operations includingWriteToPathand existence checkspkg/utils/command– Wraps shell command execution for restarting services
CRUD Operations and Samba Synchronization
Every mutating operation follows a consistent pattern: update the database, regenerate the configuration, and restart the Samba daemon.
Creating a Share
When CreateShare receives a SharesDBModel, it first inserts the record into the database using db.Create. Immediately after persistence, it triggers InitSambaConfig to ensure the base /etc/samba/smb.conf contains the CasaOS header and the include=/etc/samba/smb.casa.conf directive. Finally, UpdateConfigFile rebuilds the include file with all existing shares and executes the restart command via command.OnlyExec("source "+config.AppInfo.ShellPath+"/helper.sh ;RestartSMBD").
Deleting and Querying Shares
The service provides several query methods:
GetSharesList()– Retrieves all share records from the databaseGetSharesByPath(path)– Finds shares matching a specific filesystem pathGetSharesByName(name)– Locates shares by their configured name
Deletion methods include DeleteShare (by ID) and DeleteShareByPath (removing all shares under a directory tree). Both operations follow the same synchronization pattern: modify the database, regenerate smb.casa.conf, and restart Samba.
Working with the Shares Service
Below is a practical example demonstrating how to interact with the shares service in a CasaOS environment:
// Assume `db` is an opened *gorm.DB (CasaOS bootstraps this already)
sharesSvc := service.NewSharesService(db)
// 1. Create a new share
newShare := model.SharesDBModel{
Anonymous: false,
Path: "/mnt/usbdrive/shared",
Name: "myshare",
}
sharesSvc.CreateShare(newShare)
// 2. List all shares
allShares := sharesSvc.GetSharesList()
for _, s := range allShares {
fmt.Printf("Share ID=%d, Path=%s, Anonymous=%t\n", s.ID, s.Path, s.Anonymous)
}
// 3. Find a share by its underlying filesystem path
matches := sharesSvc.GetSharesByPath("/mnt/usbdrive/shared")
if len(matches) > 0 {
fmt.Println("Found share:", matches[0].Name)
}
// 4. Delete a share by its database ID (stringified uint)
sharesSvc.DeleteShare(fmt.Sprintf("%d", newShare.ID))
// 5. Delete all shares that reside under a given directory tree
sharesSvc.DeleteShareByPath("/mnt/usbdrive/")
These calls automatically keep the Samba configuration file in sync, requiring no additional system commands from the caller.
Summary
- CasaOS manages Samba shares through a database-backed service defined in
service/shares.goandservice/model/o_shares.go. - The
SharesDBModelstruct persists share metadata to an SQLite database via Gorm. UpdateConfigFilegenerates/etc/samba/smb.casa.confby translating database rows into Samba configuration stanzas.InitSambaConfigensures the main/etc/samba/smb.confincludes the CasaOS-generated file and applies global settings.- Every CRUD operation triggers an automatic Samba daemon restart via the
RestartSMBDhelper command.
Frequently Asked Questions
How does CasaOS store share definitions?
CasaOS stores share definitions in an SQLite database using the o_shares table, mapped by the SharesDBModel struct in service/model/o_shares.go. This table tracks the share path, name, anonymity settings, and timestamps.
What happens when a new share is created in CasaOS?
When CreateShare is called, the service inserts the record into the database, ensures the base Samba configuration exists via InitSambaConfig, regenerates the include file through UpdateConfigFile, and executes the RestartSMBD command to apply changes immediately.
Where does CasaOS write the Samba configuration files?
CasaOS writes share-specific configuration to /etc/samba/smb.casa.conf and ensures the main /etc/samba/smb.conf contains an include directive pointing to this file. The service also applies CasaOS-specific global settings to the main configuration if they are not already present.
Can external applications use the CasaOS shares service?
Yes, external applications or plugins can import the service package and call NewSharesService(db) to obtain a service instance. They can then use methods like CreateShare, DeleteShare, and GetSharesList to manage shares, with all Samba configuration updates handled automatically by the service.
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 →