2 releases
| 0.1.1 | Mar 20, 2026 |
|---|---|
| 0.1.0 | Mar 20, 2026 |
#1530 in Filesystem
155KB
3K
SLoC
dps — Debian Profile Sync
Keep your shell config, dotfiles, and editor settings identical across every Debian machine you own — automatically, in real time, over any network.
dps spins up a lightweight Proxmox LXC container that acts as the central sync hub. Every machine runs the dps-daemon in the background; it watches for local file changes and pushes them to the container, and periodically pulls changes made from other machines. A system-tray GUI (dps-gui) gives you live status at a glance.
Features
- One-command setup — interactive wizard creates the LXC container, injects your SSH key, and optionally joins Tailscale
- Real-time push — inotify watcher debounces changes and rsyncs instantly
- Periodic pull — background poller keeps you in sync when you return to a machine
- Tailscale integration — sync works from any network without opening firewall ports
- Machine-specific file filtering — built-in patterns skip hostname files, dconf, pulse TDB, recently-used lists, etc.
.syncignoresupport — per-directory exclusion rules (gitignore syntax)- System-tray GUI — egui app connects to the daemon over a Unix socket
- systemd user service — daemon starts at login, restarts on failure
Requirements
| Requirement | Notes |
|---|---|
| Proxmox VE 7+ | Any node with LXC support |
| Debian/Ubuntu client machines | rsync and ssh must be in PATH |
| Rust 1.75+ | Only needed to build from source |
| GTK3 + libayatana-appindicator3 | Only for the GUI binary |
Install GUI system deps on Debian/Ubuntu:
sudo apt install libgtk-3-dev libayatana-appindicator3-dev
Installation
From crates.io (CLI + daemon only)
cargo install dps
From source (all binaries including GUI)
git clone https://github.com/dfrederick15/dps
cd dps
cargo build --release # CLI + daemon
cargo build --release --features gui # + tray GUI
install -Dm755 target/release/dps ~/.local/bin/dps
install -Dm755 target/release/dps-daemon ~/.local/bin/dps-daemon
install -Dm755 target/release/dps-gui ~/.local/bin/dps-gui # if built
Quick Start
# 1. Run the interactive setup wizard — creates config + provisions the container
dps setup
# 2. Enable the background daemon
mkdir -p ~/.config/systemd/user
cp systemd/dps-daemon.service ~/.config/systemd/user/
systemctl --user enable --now dps-daemon
# 3. On every other machine: install dps, copy your config, enable the daemon
# (no `dps setup` needed — the container already exists)
# 4. Manual sync
dps push # push local → container
dps pull # pull container → local
# 5. Or watch continuously
dps watch
Setup Wizard
Running dps setup with no config file launches a step-by-step wizard:
╔══════════════════════════════════════╗
║ dps — first-time setup ║
╚══════════════════════════════════════╝
── Proxmox Connection ───────────────────────────────────────────────
Host (IP or hostname): 192.168.1.10
Port [8006]:
Node name [pve]:
Verify SSL certificate [y/N]:
── Authentication ────────────────────────────────────────────────────
Type (token/password) [token]:
User [root@pam]:
Token name [dps]:
Token value: ****
── LXC Container ─────────────────────────────────────────────────────
VMID [200]:
Hostname [dps-sync]:
...
── Profile Sync ──────────────────────────────────────────────────────
Local path [1/?]: ~/.bashrc
Remote path [.bashrc]:
...
── Tailscale (optional) ──────────────────────────────────────────────
Enable Tailscale integration [y/N]:
The wizard saves ~/.config/dps/config.toml and immediately provisions the container.
CLI Reference
dps setup First-time setup (wizard + container provisioning)
dps push [--dry-run] Push local files → container
dps pull [--dry-run] Pull container → local files
dps check Report machine-specific files that would be skipped
dps watch Real-time push watcher + periodic pull poller
dps status Show container and sync status
dps start Start the LXC container
dps stop Stop the LXC container
dps destroy Destroy the LXC container (requires --yes)
dps tailscale status Show Tailscale status inside the container
dps tailscale reauth <key> Re-authenticate Tailscale with a new auth key
Configuration
Config lives at ~/.config/dps/config.toml. A full annotated example is at config.example.toml.
Minimal example (API token auth)
[proxmox]
host = "192.168.1.10"
node = "pve"
[proxmox.auth]
type = "token"
user = "root@pam"
token_name = "dps"
token_value = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
[container]
vmid = 200
hostname = "dps-sync"
template = "local:vztmpl/debian-12-standard_12.7-1_amd64.tar.zst"
storage = "local-lvm"
disk_size = "8G"
root_password = "change-me"
[container.network]
bridge = "vmbr0"
ip = "dhcp"
[sync]
[[sync.paths]]
local = "~/.bashrc"
remote = ".bashrc"
[[sync.paths]]
local = "~/.gitconfig"
remote = ".gitconfig"
Tailscale
[tailscale]
auth_key = "tskey-auth-..."
prefer_tailscale_ip = true
When prefer_tailscale_ip = true, all push/pull transfers use the Tailscale IP (stored automatically after dps setup), so sync works from any network.
Daemon
[daemon]
auto_start_container = true
auto_watch = true
watch_direction = "both" # "push", "pull", or "both"
debounce_ms = 500
poll_secs = 30
Background Daemon
The daemon maintains the watcher processes and exposes a Unix socket at $XDG_RUNTIME_DIR/dps.sock for the CLI and GUI to connect to.
# Install and enable
mkdir -p ~/.config/systemd/user
cp systemd/dps-daemon.service ~/.config/systemd/user/
systemctl --user daemon-reload
systemctl --user enable --now dps-daemon
# Logs
journalctl --user -u dps-daemon -f
System-Tray GUI
Build and install (requires GTK3 + libayatana-appindicator3):
cargo build --release --features gui
install -Dm755 target/release/dps-gui ~/.local/bin/dps-gui
cp autostart/dps-gui.desktop ~/.config/autostart/ # auto-start on login
The tray icon turns green when connected to the daemon. Left-click toggles the control window; right-click shows the menu.
Ignoring Files
.syncignore
Create a .syncignore file inside any synced directory to exclude files from that directory (gitignore syntax):
*.log
.env
secrets/
Global ignore
Add patterns to ~/.config/dps/syncignore to exclude files across all paths.
Built-in machine-specific patterns
dps automatically skips files that contain your hostname or machine-id, plus a built-in list of known machine-specific paths:
.cache/
monitors.xml
recently-used.xbel
pulse/*.tdb
tracker/
dconf/
Run dps check to see which files in your sync paths would be flagged.
License
MIT
Dependencies
~16–68MB
~1M SLoC