A skinny but powerful, self-hosted file sync across your devices over a Tailscale tailnet.
Project description
SyncTwink
A skinny but powerful, self-hosted file sync across your devices over a Tailscale tailnet.
Two always-on servers (e.g. a Raspberry Pi and a Mac Mini) each expose the same folder over WebDAV for iOS Files and other clients, while Syncthing keeps the two copies replicated. Either server can go offline and your files stay reachable from the other.
Tailnet (WireGuard, end-to-end encrypted)
┌──────────────────────────────────────────────────┐
│ │
┌──┴──────────────┐ Syncthing replication ┌─────────┴───────┐
│ Raspberry Pi │ <───────────────────────> │ Mac Mini │
│ • Tailscale │ │ • Tailscale │
│ • WebDAV :8080 │ │ • WebDAV :8080 │
│ • Syncthing │ │ • Syncthing │
└──┬──────────────┘ └─────────┬───────┘
│ │
│ WebDAV over Tailscale (HTTP/HTTPS) │
└──────────────────────┬──────────────────────────────┘
│
┌─────────────┴─────────────┐
│ iPhone / iPad Files app │ ← connects to whichever
│ Mac / other devices │ server is reachable
└───────────────────────────┘
SyncTwink is the glue: a small Python package + CLI you install on each
server. It configures the WebDAV service (via WsgiDAV),
sets up the Syncthing shared folder, and optionally fronts WebDAV with HTTPS
using tailscale serve.
What it does
- WebDAV server backed by WsgiDAV + cheroot, serving one folder with per-user auth (basic + digest). Works with iOS Files, macOS Finder, and any WebDAV client.
- Syncthing replication between the two servers, configured for you via Syncthing's REST API (adds the folder, pairs peers, enables file versioning).
- Native services — installed as a
systemdunit on Linux or alaunchdagent/daemon on macOS, so WebDAV starts on boot and restarts on failure. - Tailscale-aware — reads your tailnet status to print the right connection URLs and can expose WebDAV over HTTPS with a valid MagicDNS cert.
SyncTwink assumes Tailscale is already installed and tailscale up has been
run on each machine. It does not manage the tailnet itself.
Quick start (run on each server)
# 1. Install the CLI (pick one)
pipx install synctwink
# or from source:
# pipx install git+https://github.com/jchaselubitz/synctwink.git
# pipx install . # from a git clone
# 2. Create a config (generates a WebDAV password for you)
sudo synctwink init --user jake --data-dir /srv/synctwink/data
# 3. Find this machine's Syncthing device id (after Syncthing has run once)
synctwink syncthing id
Put each server's device id into the other server's config under
syncthing.peers, then on both machines:
sudo synctwink install # installs deps, configures Syncthing, starts WebDAV
synctwink status # health check + connection URLs
See docs/INSTALL.md for the full walkthrough and
docs/IOS.md for connecting the iPhone Files app.
CLI
| Command | What it does |
|---|---|
synctwink init |
Write a config file (with a generated password). |
synctwink install |
Full setup: deps, Syncthing folder/peers, WebDAV service, HTTPS. |
synctwink serve |
Run the WebDAV server in the foreground (used by the service). |
synctwink status |
Show Tailscale / WebDAV / Syncthing health + URLs. |
synctwink info |
Print client connection details (for iOS Files etc.). |
synctwink syncthing id |
Print this node's Syncthing device id. |
synctwink syncthing pair <id> |
Add a peer and share the folder with it. |
synctwink syncthing configure |
Re-apply folder + peers from config. |
synctwink sync |
Wake Syncthing, pull/push now, re-quiet on battery (for laptops). |
synctwink pause / synctwink resume |
Stop / start peer syncing. |
synctwink service restart |
Restart the WebDAV service. |
synctwink uninstall |
Remove the WebDAV service and reset tailscale serve. |
For an often-offline laptop that wants offline files without burning
battery, see docs/LAPTOP.md: join it as a Syncthing peer,
pause on battery, and use synctwink sync to pull changes on demand.
Configuration
A single YAML file. Default location is /etc/synctwink/config.yaml (root) or
~/.config/synctwink/config.yaml. Override with --config or SYNCTWINK_CONFIG.
See synctwink/templates/config.example.yaml.
The config holds plaintext WebDAV passwords and is written 0600. Because all
traffic rides the encrypted tailnet, HTTP basic auth is safe here.
Requirements
- Python 3.9+
- Tailscale (installed +
tailscale upalready done) - Syncthing (auto-installed via
apt/dnf/pacman/brewif missing) - A Linux host with
systemd, or macOS withlaunchd
Architecture & design notes
See docs/ARCHITECTURE.md.
License
MIT — see LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file synctwink-0.1.0.tar.gz.
File metadata
- Download URL: synctwink-0.1.0.tar.gz
- Upload date:
- Size: 22.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cebb7150e857c0b51820fb69f0660446c065fd961806f09d6f9c5044fe8b5b1b
|
|
| MD5 |
a92f538bf76645f8534db81f1eb3bfdc
|
|
| BLAKE2b-256 |
cfbe9ba576d43f3bc62b7b172f2273ae545ab1c389c972c69e555bd951978461
|
Provenance
The following attestation bundles were made for synctwink-0.1.0.tar.gz:
Publisher:
publish-pypi.yml on jchaselubitz/SyncTwink
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
synctwink-0.1.0.tar.gz -
Subject digest:
cebb7150e857c0b51820fb69f0660446c065fd961806f09d6f9c5044fe8b5b1b - Sigstore transparency entry: 1702953877
- Sigstore integration time:
-
Permalink:
jchaselubitz/SyncTwink@0860a0367b367c962cbfca4b15c7b2d983223307 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/jchaselubitz
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@0860a0367b367c962cbfca4b15c7b2d983223307 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file synctwink-0.1.0-py3-none-any.whl.
File metadata
- Download URL: synctwink-0.1.0-py3-none-any.whl
- Upload date:
- Size: 25.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
379c9afbaf81f1a96358b0eb508c67968ecd1634d1ecfc808596437d6141dde7
|
|
| MD5 |
2fb60ffe3fda245acb6a29e113b11cca
|
|
| BLAKE2b-256 |
2767c5ce93a48780d02643b6ef7c37a3a04e6edd1349562648b7d1c0a90fb414
|
Provenance
The following attestation bundles were made for synctwink-0.1.0-py3-none-any.whl:
Publisher:
publish-pypi.yml on jchaselubitz/SyncTwink
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
synctwink-0.1.0-py3-none-any.whl -
Subject digest:
379c9afbaf81f1a96358b0eb508c67968ecd1634d1ecfc808596437d6141dde7 - Sigstore transparency entry: 1702954076
- Sigstore integration time:
-
Permalink:
jchaselubitz/SyncTwink@0860a0367b367c962cbfca4b15c7b2d983223307 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/jchaselubitz
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@0860a0367b367c962cbfca4b15c7b2d983223307 -
Trigger Event:
workflow_dispatch
-
Statement type: