How FlClash Implements WebDAV Synchronization for Backup and Restore
FlClash stores user configurations, profiles, scripts, and the SQLite database in a single ZIP archive, uploading it to a configured WebDAV endpoint for backup and downloading it to restore local state.
FlClash is an open-source proxy client built with Flutter that provides cross-platform support for managing clash configurations. To prevent data loss and enable cross-device synchronization, the application implements a robust WebDAV synchronization mechanism that packages all user data into a portable archive format. This implementation leverages Riverpod for state management and the webdav_client package for remote file operations.
WebDAV Configuration Flow
Setting Up Credentials
The configuration interface is handled by WebDAVFormDialog located in lib/views/backup_and_restore.dart. When users press the Bind button on the Backup & Restore screen, this dialog collects four essential parameters: server URL, username, password, and an optional remote filename. These values are encapsulated in a DAVProps object (defined in lib/models/common.dart) and persisted through the davSettingProvider Riverpod notifier found in lib/providers/generated/config.g.dart.
ref.read(davSettingProvider.notifier).value = DAVProps(
uri: 'https://example.com/webdav',
user: 'myUser',
password: 'myPassword',
fileName: 'myBackup.zip', // optional; defaults to 'backup.zip'
);
Connectivity Verification
Once the provider updates, the application instantiates a DAVClient (wrapper in lib/common/dav_client.dart) and invokes client.ping() to verify server accessibility. The UI renders a status indicator—green for successful connection, red for failure—based on this handshake before enabling backup or restore operations.
Backup Implementation
Creating the Archive
The backup process begins in lib/providers/action.dart where BackupAction.backup() orchestrates data collection. This method serializes the current Config object to JSON, enumerates active profile and script filenames, and delegates archive creation to backupTask() in lib/common/task.dart. The task executes on a background isolate to prevent UI blocking.
The resulting ZIP file (stored at tempZipFilePath) contains four critical components:
config.json– Serialized application state and UI preferencesbackup.db– Copy of the SQLite database containing runtime data*.yamlfiles – Active proxy configuration profiles*.jsfiles – User-defined JavaScript scripts for rule processing
Uploading to WebDAV
After local archive creation, the system calls DAVClient.backup(localFilePath) from lib/common/dav_client.dart. This method first ensures the remote directory structure exists by creating /FlClash on the server root, then uploads the ZIP file to <root>/<fileName> using the webdav_client package's write operations.
// Create the ZIP archive
final zipPath = await ref.read(backupActionProvider.notifier).backup();
// Upload to configured WebDAV endpoint
await _client!.backup(zipPath);
Restore Implementation
Downloading the Archive
Restoration starts when the user selects their preferred scope—either profiles-only or full data restoration—via _handleRestoreOnWebDAV() in the backup UI. The _restoreOnWebDAV() method triggers DAVClient.restore(), which downloads the remote ZIP into the local backup location specified by appPath.backupFilePath.
// Download remote archive to local storage
await _client?.restore();
Applying the Restore
Once downloaded, BackupAction.restore(option) invokes restoreTask() from lib/common/task.dart. This task performs a destructive recovery sequence: it extracts the ZIP to a temporary restore directory, reconstructs the SQLite database from the embedded backup.db file, copies profile and script files back to their permanent directories, and rehydrates the in-memory configuration state including the WebDAV configuration itself.
// Unpack and restore all data
await ref.read(backupActionProvider.notifier).restore(RestoreOption.all);
Summary
- FlClash WebDAV synchronization packages all user data—configs, profiles, scripts, and database—into a single ZIP archive for atomic backup operations.
- Configuration persists through Riverpod's
davSettingProviderusing theDAVPropsmodel, with connectivity validated viaDAVClient.ping(). - The
backupTask()function inlib/common/task.darthandles compression on a background isolate, whileDAVClientmanages remote file I/O. - Restoration supports granular options (
RestoreOption.profilesorRestoreOption.all) and rebuilds the entire application state from the downloaded archive.
Frequently Asked Questions
What data does FlClash include in the WebDAV backup archive?
The backup archive contains config.json (application settings), backup.db (SQLite database copy), all active *.yaml profile files, and all *.js script files. This comprehensive packaging ensures that restoring on a new device recreates the exact same environment, including proxy rules and UI preferences.
How does FlClash handle WebDAV authentication?
FlClash stores WebDAV credentials (URI, username, password) in a DAVProps object managed by the davSettingProvider Riverpod notifier. The DAVClient class in lib/common/dav_client.dart initializes the underlying webdav_client package with these credentials, supporting standard HTTP Basic Authentication for secure server access.
Can I restore only specific profiles without affecting other settings?
Yes. The restore workflow in lib/views/backup_and_restore.dart presents a dialog allowing users to choose between RestoreOption.profiles (proxy configurations only) or RestoreOption.all (complete state including database and scripts). This granularity prevents overwriting current application settings when you only need to update proxy rules.
Where does FlClash store the remote backup files on the WebDAV server?
By default, FlClash creates a root directory named /FlClash on the remote server and stores the backup as backup.zip within that folder. Users can customize the filename through the fileName property in DAVProps, though the /FlClash directory structure remains constant as implemented in DAVClient.backup().
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 →