There is no good, free Google Drive sync client for Linux. The KDE Accounts integration barely works, GNOME Online Accounts only mounts files on demand (no offline access), and every other option is either paid (Insync), abandoned, or command-line only. We built Cloud Drive Sync to fix that — a native, open-source desktop app that just works, like what Dropbox and Google Drive offer on Windows and macOS but never bothered to ship for Linux.
It grew into a full multi-cloud sync platform supporting Google Drive, Dropbox, OneDrive, Nextcloud, and Box, running on Linux, macOS, and Windows — with Proton Drive planned for Q2 2026+.
If this project is useful to you, consider supporting it:
View as Mermaid
graph TB
subgraph UI["UI (Tauri + React)"]
direction TB
subgraph Frontend["React Frontend"]
StatusDashboard["Status Dashboard"]
Settings
ConflictDialog["Conflict Resolution"]
ActivityLog["Activity Log"]
AccountManager["Account Manager"]
end
Tray["System Tray Icon"]
RustBackend["Rust Backend\n(DaemonBridge)"]
Frontend --> RustBackend
end
subgraph Daemon["Daemon (Python 3.12)"]
direction TB
subgraph SyncEngine
Planner
Executor
ConflictResolver["Conflict Resolver"]
end
subgraph Providers["Provider Abstraction"]
GDrive["Google Drive"]
Dropbox["Dropbox"]
OneDrive["OneDrive"]
Nextcloud["Nextcloud"]
Box["Box"]
end
Watcher["Watcher\n(watchdog)"]
DB["SQLite DB\n(aiosqlite)"]
Watcher --> SyncEngine
SyncEngine --> DB
SyncEngine --> Providers
end
RustBackend <-->|"JSON-RPC 2.0\nUnix Socket"| SyncEngine
GDrive -->|"HTTPS"| GoogleAPI[("Google Drive\nAPI v3")]
Dropbox -->|"HTTPS"| DropboxAPI[("Dropbox\nAPI v2")]
OneDrive -->|"HTTPS"| GraphAPI[("Microsoft\nGraph API")]
Nextcloud -->|"WebDAV"| NextcloudAPI[("Nextcloud\nServer")]
Box -->|"HTTPS"| BoxAPI[("Box\nAPI v2")]
Cloud Drive Sync runs in two modes:
A native desktop app with system tray integration, built with Tauri + React. The UI launches a background daemon automatically.
- System tray icon with live status (idle, syncing, error, conflict)
- Visual management of accounts, sync folders, conflicts, and settings
- Desktop notifications for sync events
- Works on Linux (KDE, GNOME, etc.), macOS, and Windows
The daemon runs standalone — ideal for servers, NAS devices, and Docker containers. Three ways to manage it:
| Method | Description |
|---|---|
| CLI | cloud-drive-sync status, account add, pair list, etc. |
| Web UI | Browser-based dashboard at http://localhost:8080/ |
| REST API | curl http://localhost:8080/api/status — full HTTP API for automation |
The HTTP server (web UI + REST API) starts with --http-port 8080. Docker containers enable it by default.
Authentication in headless mode works without a local browser — the daemon prints an authorization URL to the console, and you complete sign-in on any device.
Pre-built packages are available from the latest release. Each package bundles both the desktop UI and the sync daemon — no separate install needed.
# Download and install
wget https://github.com/ciberkids/cloud-drive-sync/releases/latest/download/Cloud.Drive.Sync_0.1.0_amd64.deb
sudo dpkg -i Cloud.Drive.Sync_0.1.0_amd64.deb
sudo apt-get install -f # install any missing dependencies
# Enable the daemon to start on login
systemctl --user enable --now cloud-drive-sync-daemon
# Launch the UI
cloud-drive-sync-ui# Download and install
wget https://github.com/ciberkids/cloud-drive-sync/releases/latest/download/Cloud.Drive.Sync-0.1.0-1.x86_64.rpm
sudo rpm -U Cloud.Drive.Sync-0.1.0-1.x86_64.rpm
# Enable the daemon to start on login
systemctl --user enable --now cloud-drive-sync-daemon
# Launch the UI
cloud-drive-sync-uiNo installation required — download and run:
wget https://github.com/ciberkids/cloud-drive-sync/releases/latest/download/Cloud.Drive.Sync_0.1.0_amd64.AppImage
chmod +x Cloud.Drive.Sync_0.1.0_amd64.AppImage
./Cloud.Drive.Sync_0.1.0_amd64.AppImageThe AppImage bundles the daemon and will auto-start it when no running daemon is detected.
# Install from the release bundle
wget https://github.com/ciberkids/cloud-drive-sync/releases/latest/download/cloud-drive-sync.flatpak
flatpak install --user cloud-drive-sync.flatpak
# Run
flatpak run com.cloud_drive_sync.appFor servers or headless setups without a desktop UI:
# Download the standalone daemon binary
wget https://github.com/ciberkids/cloud-drive-sync/releases/latest/download/cloud-drive-sync-daemon
chmod +x cloud-drive-sync-daemon
sudo mv cloud-drive-sync-daemon /usr/local/bin/
# Start the daemon
cloud-drive-sync-daemon start --foreground
# Manage via CLI
cloud-drive-sync-daemon account add --provider gdrive
cloud-drive-sync-daemon pair add --local ~/Documents --remote root
cloud-drive-sync-daemon status# Run the daemon in a container
docker run -d --name cloud-drive-sync \
-p 8080:8080 \
-v cloud-drive-sync-config:/root/.config/cloud-drive-sync \
-v cloud-drive-sync-data:/root/.local/share/cloud-drive-sync \
-v ~/Documents:/data/Documents \
ghcr.io/ciberkids/cloud-drive-sync:latest
# Open http://localhost:8080/ for the web management UI, or use the REST API:
curl http://localhost:8080/api/status
curl http://localhost:8080/api/pairs
# Add a Google account (headless auth - prints URL, you enter the code)
docker exec -it cloud-drive-sync python -m cloud_drive_sync account add --provider gdrive --headless
# Check status
docker exec cloud-drive-sync python -m cloud_drive_sync status
# View logs
docker logs -f cloud-drive-syncOr with Docker Compose (see docker/docker-compose.yml):
cd docker
docker compose up -d
docker compose exec daemon python -m cloud_drive_sync account add --provider gdrive --headless# Download DMG from latest release
# Or via Homebrew (coming soon):
# brew install --cask cloud-drive-sync# Download installer from latest release
# Or via Scoop (coming soon):
# scoop install cloud-drive-syncAn interactive installer that detects your distro and downloads the right package:
curl -fsSL https://raw.githubusercontent.com/ciberkids/cloud-drive-sync/main/install.sh | bash- Multi-cloud support — Google Drive, Dropbox, OneDrive, Nextcloud, Box (Proton Drive coming soon)
- Bidirectional sync — uploads local changes and downloads remote changes automatically
- Cross-cloud sync — download from one provider and upload to another (see Cross-Cloud Sync)
- Google Docs conversion — exports Google Docs/Sheets/Slides to .docx/.xlsx/.pptx locally, re-uploads on edit
- Conflict resolution — three strategies: keep both copies, newest wins, or ask the user
- Real-time monitoring — local filesystem watcher (watchdog) + remote change polling
- Desktop notifications — native OS notifications for sync events, conflicts, and errors
- System tray — always-on tray icon with dynamic status indicators (idle, syncing, error, conflict)
- Headless CLI — full management via command line without the GUI
- Selective sync — per-pair ignore patterns and
.cloud-drive-sync-ignorefiles (gitignore-style) - Shared Drives — full support for Google Workspace Shared Drives (Team Drives)
- Multiple accounts — connect accounts from different providers, bind each sync pair to a specific account
- Hidden file filtering — exclude dotfiles and dot-directories from sync (configurable per pair)
- Multi-pair support — sync multiple local folders to different cloud locations
- Cross-platform — runs natively on Linux, macOS, and Windows
- Native desktop UI — Tauri + React app for configuration and monitoring
- Daemon architecture — runs as a background service (systemd on Linux, sidecar on macOS/Windows)
- XDG compliance — config, data, and runtime files follow the XDG Base Directory spec
- Encrypted credentials — OAuth2 tokens stored encrypted on disk (per-account)
- Demo mode — test the full UI and sync flow without any cloud account
| Provider | Status | Auth Method | Hash Algorithm | Notes |
|---|---|---|---|---|
| Google Drive | Available | OAuth 2.0 (browser) | MD5 | Shared Drives, Google Docs conversion |
| Dropbox | Optional dep | OAuth 2.0 PKCE | Content hash (SHA-256 blocks) | Path-based API, cursor-based changes |
| OneDrive | Optional dep | Azure AD (device code / browser) | QuickXorHash | Microsoft Graph API, delta sync |
| Nextcloud | Optional dep | App password | MD5 | Self-hosted, WebDAV, ETag polling |
| Box | Optional dep | OAuth 2.0 | SHA-1 | Chunked upload >50MB, Events API |
| Proton Drive | Planned Q2 2026+ | N/A | N/A | No public API yet |
Google Drive support is included by default. For other providers, install their optional dependencies:
# Individual providers
pip install cloud-drive-sync[dropbox]
pip install cloud-drive-sync[onedrive]
pip install cloud-drive-sync[nextcloud]
pip install cloud-drive-sync[box]
# All providers at once
pip install cloud-drive-sync[all-providers]Screenshots show the Tauri desktop application.
To add screenshots, place PNG files in
docs/screenshots/matching the filenames above.
# Clone and start everything in demo mode (no cloud account needed)
git clone https://github.com/ciberkids/cloud-drive-sync.git
cd cloud-drive-sync
./dev.sh # daemon only
./dev.sh --with-ui # daemon + Tauri UI- Python 3.12+
-
Node.js 18+ and npm
-
Rust toolchain — install via rustup
-
System libraries for Tauri:
Distro Packages Fedora webkit2gtk4.1-devel gtk3-devel libayatana-appindicator-gtk3-develUbuntu/Debian libwebkit2gtk-4.1-dev libgtk-3-dev libayatana-appindicator3-devArch webkit2gtk-4.1 gtk3 libayatana-appindicator
Each cloud provider requires its own credentials or app registration. Below are the setup instructions for each.
Works out of the box — OAuth client credentials are embedded in the app. Just click Add Account in the UI or run:
cloud-drive-sync-daemon account add --provider gdriveA browser window will open for Google sign-in. No setup required.
"This app isn't verified" warning: Since the app uses Google Drive's full access scope and hasn't been through Google's verification process, you'll see a warning screen. This is normal for open-source apps. To proceed:
- Click "Advanced" (bottom left)
- Click "Go to Cloud Drive Sync (unsafe)"
- Review the permissions and click "Allow"
Your data stays on your machine — the app syncs directly between your computer and Google Drive. See Google's explanation.
Power users: To use your own OAuth credentials, place a
client_secret.jsonin~/.config/cloud-drive-sync/or setCDS_GOOGLE_CLIENT_IDandCDS_GOOGLE_CLIENT_SECRETenvironment variables.
Dropbox uses OAuth 2.0 with PKCE — no client secret is required.
- Go to the Dropbox App Console
- Click Create app
- Choose Scoped access -> Full Dropbox (or App folder for limited access)
- Name your app (e.g.
cloud-drive-sync) - In the app settings, note the App key (you'll need it during auth)
- Under OAuth 2, add
http://localhostto redirect URIs - Under Permissions, enable:
files.metadata.read,files.metadata.write,files.content.read,files.content.write
When adding a Dropbox account via CLI (cloud-drive-sync account add --provider dropbox), you'll be prompted for the App key and directed to authorize in your browser.
OneDrive uses the Microsoft Graph API with Azure AD authentication.
- Go to the Azure Portal - App registrations
- Click New registration
- Name:
cloud-drive-sync, Supported account types: Personal Microsoft accounts + organizational - Redirect URI: Public client/native ->
http://localhost:8400 - Note the Application (client) ID
- Under API permissions, add:
Microsoft Graph->Files.ReadWrite.All,User.Read - Grant admin consent (or users will be prompted)
For headless setups, the device code flow is used — no browser needed on the server itself.
Nextcloud uses app passwords for authentication — no OAuth app registration needed.
- Log in to your Nextcloud instance
- Go to Settings -> Security -> Devices & sessions
- Enter a name (e.g.
cloud-drive-sync) and click Create new app password - Copy the generated password
When adding a Nextcloud account, you'll provide:
- Server URL: your Nextcloud instance (e.g.
https://cloud.example.com) - Username: your Nextcloud username
- App password: the generated password
cloud-drive-sync account add --provider nextcloud
# Enter server URL, username, and app password when promptedBox uses standard OAuth 2.0 with a client secret.
- Go to the Box Developer Console
- Click Create New App -> Custom App -> User Authentication (OAuth 2.0)
- Name your app (e.g.
cloud-drive-sync) - In the app configuration, note the Client ID and Client Secret
- Under OAuth 2.0 Redirect URI, add
http://localhost:8400 - Under Application Scopes, enable: Read/Write all files and folders
Set environment variables or provide credentials when prompted:
export BOX_CLIENT_ID="your_client_id"
export BOX_CLIENT_SECRET="your_client_secret"
cloud-drive-sync account add --provider boxCloud Drive Sync can be used to sync files between different cloud providers by setting up two sync pairs that point to the same local directory — one in download-only mode and another in upload-only mode.
Sync files from Google Drive to Dropbox automatically:
# 1. Add both accounts
cloud-drive-sync account add --provider gdrive
cloud-drive-sync account add --provider dropbox
# 2. Create a shared local directory
mkdir -p ~/cloud-bridge
# 3. Add a download-only pair from Google Drive
cloud-drive-sync pair add \
--local ~/cloud-bridge \
--remote root \
--account user@gmail.com \
--provider gdrive
# Set it to download-only (Google Drive -> local)
# Use the UI Settings or edit config.toml:
# sync_mode = "download_only"
# 4. Add an upload-only pair to Dropbox
cloud-drive-sync pair add \
--local ~/cloud-bridge \
--remote "" \
--account user@dropbox.com \
--provider dropbox
# Set it to upload-only (local -> Dropbox)
# sync_mode = "upload_only"Or via config.toml:
[[sync.pairs]]
local_path = "/home/user/cloud-bridge"
remote_folder_id = "root"
sync_mode = "download_only" # Google Drive -> local
account_id = "user@gmail.com"
provider = "gdrive"
[[sync.pairs]]
local_path = "/home/user/cloud-bridge"
remote_folder_id = ""
sync_mode = "upload_only" # local -> Dropbox
account_id = "user@dropbox.com"
provider = "dropbox"
[[accounts]]
email = "user@gmail.com"
provider = "gdrive"
[[accounts]]
email = "user@dropbox.com"
provider = "dropbox"The same pattern works for any combination:
| Source | Destination | Source sync_mode | Dest sync_mode |
|---|---|---|---|
| Google Drive | Dropbox | download_only |
upload_only |
| OneDrive | Nextcloud | download_only |
upload_only |
| Box | Google Drive | download_only |
upload_only |
| Any | Any | download_only |
upload_only |
For bidirectional cross-cloud sync (changes on either side are reflected on both), use two_way for both pairs. Be aware this may cause sync loops if both providers modify the same file simultaneously — the conflict resolver will handle these cases.
git clone https://github.com/ciberkids/cloud-drive-sync.git
cd cloud-drive-synccd daemon
# Create a virtual environment
python3 -m venv .venv
# Install the daemon (Google Drive only)
.venv/bin/pip install -e .
# Install with all cloud providers
.venv/bin/pip install -e ".[all-providers]"
# (Optional) Install dev/test dependencies too
.venv/bin/pip install -e ".[dev]"Verify the installation:
.venv/bin/python -m cloud_drive_sync --helpcd ui
# Install JavaScript dependencies
npm install
# (Optional) Verify Tauri compiles
npm run tauri buildThe compiled binary will be at ui/src-tauri/target/release/cloud-drive-sync-ui.
The daemon must be running before the UI can connect to it.
cd daemon
# Foreground (see logs in terminal)
.venv/bin/python -m cloud_drive_sync --log-level debug start --foreground
# Background (daemonize)
.venv/bin/python -m cloud_drive_sync start
# Check status
.venv/bin/python -m cloud_drive_sync status
# Stop
.venv/bin/python -m cloud_drive_sync stopOn first launch without existing credentials, the daemon starts and waits for authentication. Connect via the UI and click Add Account on the Account page, or use the CLI.
Manage everything from the command line without the GUI:
# Account management
cloud-drive-sync account add --provider gdrive
cloud-drive-sync account add --provider dropbox
cloud-drive-sync account list
cloud-drive-sync account remove user@gmail.com
# Sync pair management
cloud-drive-sync pair add --local ~/Documents --remote root --account user@gmail.com
cloud-drive-sync pair list
cloud-drive-sync pair remove 0
# Sync control
cloud-drive-sync sync # Trigger immediate sync (all pairs)
cloud-drive-sync sync --pair-id pair_0 # Sync specific pair
cloud-drive-sync pause
cloud-drive-sync resume
# Monitoring
cloud-drive-sync activity --limit 20
cloud-drive-sync conflicts
cloud-drive-sync resolve 1 keep_bothIn a separate terminal:
cd ui
# Development mode (hot-reload)
npm run tauri dev
# Or run a release build directly
./src-tauri/target/release/cloud-drive-sync-uiThe UI connects to the daemon via a Unix socket at $XDG_RUNTIME_DIR/cloud-drive-sync.sock (typically /run/user/1000/cloud-drive-sync.sock).
To start the daemon automatically on login:
# Install the service
mkdir -p ~/.config/systemd/user
cp installer/cloud-drive-sync-daemon.service ~/.config/systemd/user/
systemctl --user daemon-reload
systemctl --user enable --now cloud-drive-sync-daemon
# Check logs
journalctl --user -u cloud-drive-sync-daemon -f
# Uninstall
systemctl --user disable --now cloud-drive-sync-daemon
rm ~/.config/systemd/user/cloud-drive-sync-daemon.service
systemctl --user daemon-reloadNote: The systemd service expects the daemon binary at ~/.local/bin/cloud-drive-sync-daemon. You can create a wrapper script:
cat > ~/.local/bin/cloud-drive-sync-daemon << 'EOF'
#!/bin/sh
exec /path/to/cloud-drive-sync/daemon/.venv/bin/python -m cloud_drive_sync "$@"
EOF
chmod +x ~/.local/bin/cloud-drive-sync-daemonThe daemon reads ~/.config/cloud-drive-sync/config.toml (created automatically on first run):
[general]
log_level = "info"
[sync]
poll_interval = 30
conflict_strategy = "keep_both"
max_concurrent_transfers = 4
debounce_delay = 1.0
convert_google_docs = true
notify_sync_complete = true
notify_conflicts = true
notify_errors = true
[[sync.pairs]]
local_path = "/home/user/Documents"
remote_folder_id = "root"
enabled = true
sync_mode = "two_way"
ignore_hidden = true
ignore_patterns = ["*.tmp", "node_modules", "build/"]
account_id = "user@gmail.com"
provider = "gdrive"
[[accounts]]
email = "user@gmail.com"
display_name = "user@gmail.com"
provider = "gdrive"You can also configure sync pairs through the UI Settings page.
Exclude files and folders from sync using glob patterns. There are two ways to set them:
Per-pair config — add ignore_patterns to a sync pair in config.toml (or use the "Ignore Patterns" button in the UI Settings):
[[sync.pairs]]
local_path = "/home/user/Projects"
ignore_patterns = ["*.log", "node_modules", "dist/", "__pycache__"]Per-folder file — create a .cloud-drive-sync-ignore file in any synced folder root (gitignore-style, one pattern per line):
# Build artifacts
build/
dist/
*.o
# Logs
*.log
# IDE files
.idea/
.vscode/
Patterns from the config, the ignore file, and built-in defaults (.git, __pycache__, .DS_Store, etc.) are all merged together.
Add accounts from any supported provider via the UI Account Manager or CLI. Each sync pair can be bound to a specific account. On first upgrade from single-account to multi-account, existing Google credentials are automatically migrated.
Google Shared Drives (Team Drives) are automatically available. When browsing remote folders in the UI, Shared Drives appear as a separate section at the root level. All sync operations (upload, download, polling) work with Shared Drive files.
By default, Google Docs, Sheets, and Slides are exported to local .docx, .xlsx, and .pptx files respectively. When you edit the local file, it is re-uploaded with conversion back to the native format.
To disable this behavior:
[sync]
convert_google_docs = falseNative OS notifications are sent for sync events. Configure which notifications to show:
[sync]
notify_sync_complete = true # "Sync complete: X uploaded, Y downloaded"
notify_conflicts = true # "Conflict: filename.txt"
notify_errors = true # "Sync error: ..."See daemon/README.md for the full configuration reference.
cd daemon
# Run all tests
.venv/bin/pytest -v
# Run integration tests only (uses demo mode, no cloud credentials)
.venv/bin/pytest -v -m integrationcloud-drive-sync/
├── daemon/ # Python sync daemon
│ ├── src/cloud_drive_sync/ # Source code
│ │ ├── providers/ # Cloud provider implementations
│ │ │ ├── base.py # Abstract base classes
│ │ │ ├── registry.py # Provider registry
│ │ │ ├── gdrive/ # Google Drive
│ │ │ ├── dropbox/ # Dropbox
│ │ │ ├── onedrive/ # OneDrive
│ │ │ ├── nextcloud/ # Nextcloud
│ │ │ ├── box/ # Box
│ │ │ └── proton/ # Proton Drive (stub)
│ │ ├── sync/ # Planner, executor, engine
│ │ ├── drive/ # Legacy shims (re-exports from providers/gdrive/)
│ │ ├── ipc/ # JSON-RPC server + CLI client
│ │ ├── db/ # SQLite database
│ │ ├── local/ # File scanner, watcher, hasher
│ │ └── auth/ # Google OAuth (legacy, used by providers/gdrive/)
│ └── tests/ # pytest test suite (430+ tests)
├── ui/ # Tauri + React desktop UI
│ ├── src/ # React components
│ └── src-tauri/ # Rust backend
├── docs/ # Documentation
├── installer/ # systemd service, .desktop files, icons
├── Makefile # Build and dev commands
└── dev.sh # One-liner dev setup
- CLI Reference — complete command-line interface guide with examples
- Architecture — system design, sync algorithm, database schema
- API Reference — full IPC method documentation with examples
- Daemon — daemon CLI, config reference, demo mode
- UI — Tauri development and build instructions
- Contributing — dev setup, code style, PR process
MIT





