The Personal Cloud
Replace Dropbox / Google Drive / iCloud.
Replace Dropbox / Google Drive / iCloud with three nodes you already own: a VPS for availability, a desktop for the bulk of your files, and a phone for automatic photo upload. Encrypted before it leaves any of them.
What you'll end up with: a vault called
Photosreplicated across three nodes (RF = 2 reliable + 1 mobile seeder), auto-syncing your phone's camera roll, browsable from any device's web UI.
Prerequisites
- Any small VPS β 1 vCPU, 1 GB RAM, 25 GB disk is enough for ~20 GB of replicated photos.
- Your usual desktop / laptop (Linux, macOS, or Windows).
- An Android phone with the MeshHold APK installed. iOS is not supported yet.
- A domain pointing at the VPS β optional, but it gives you free Let's Encrypt TLS.
1. Install the first node (VPS)
Start with the VPS β it's the only node guaranteed to be online, so it's our bootstrap peer.
# Ubuntu / Debian
ssh root@vps.example.com
wget https://meshhold.dev/dl/linux/meshhold-amd64.deb
apt-get install -y ./meshhold-amd64.deb
# Set a password for the web UI (daemon stays running)
sudo -u meshhold meshhold set-password -c /etc/meshhold/config.yaml
Prefer Docker? Same binary, no apt step, no system user. Works the same on any host with Docker installed:
bash curl -fsSL https://meshhold.dev/dl/docker/meshhold-amd64.tar.gz \ | gunzip | docker load docker volume create meshhold-data docker run -d --name meshhold --restart unless-stopped \ -p 7777:7777 -p 8080:8080 \ -v meshhold-data:/var/lib/meshhold \ -e MESHHOLD_PASSWORD=changeme \ meshhold:latest-amd64The image is distroless static and runs as uid 65532. The
meshhold-datanamed volume picks that ownership up automatically; a host-path bind-mount needschown 65532:65532first.
Open https://vps.example.com:8080/ and accept the self-signed cert (or
configure api.tls.acme_domain in config.yaml for Let's Encrypt). The
Setup Wizard greets you with three choices:
- Create new network β pick this on the first node; it mints a fresh swarm-key.
- Join existing β for nodes #2, #3, β¦
- Continue offline β for trying it out on a laptop with no peers yet.
2. Create a vault
In the web UI, click Vaults β New. Pick:
- Name:
Photos - Type:
storage - Key: any strong passphrase β write it down, this is the encryption key.
- Replication factor:
2(we want two reliable copies).
RF counts only reliable nodes. Your phone defaults to
reliable=false, so it seeds blocks but doesn't count toward the factor. That's the point β phones come and go; reliable nodes stay.
3. Pair your desktop
On the VPS, hit Network β Add peer and copy the invite QR or the
host:port string. On the desktop:
# Install the desktop binary (Linux example β Windows uses the MSI).
sudo apt-get install -y ./meshhold-amd64.deb
systemctl start meshhold
# Open https://localhost:8080/, pick "Join existing", paste the invite.
Within ~20 seconds the desktop appears in the VPS's Network page.
Open Vaults, you'll see Photos listed β click it and add the same
passphrase.
4. Pair your phone
- Install the APK and open the app.
- Tap Scan invite, point it at the QR from the VPS.
- Open Vaults β Photos, enter the passphrase.
- Toggle Camera-roll auto-upload. New photos appear on the other nodes in seconds.
5. Set replication and walk away
The defaults are already sane, but you can tune them on the VPS:
vaults:
- vault_id: "..."
name: "Photos"
key: "your-passphrase"
storage_path: "/var/lib/meshhold/photos"
full_sync: true # keep a full copy on the VPS
replication_factor: 2
type: "storage"
Restart the daemon. The VPS will pull and decrypt every block; the desktop already has a local copy of files it created; the phone keeps the encrypted ciphertext but can decrypt anything you scroll to.
Troubleshooting
Nodes don't see each other
- Check the swarm-key matches on both β
meshhold keygenoutput, exactly. - Open
0.0.0.0:7777in the VPS firewall. - On the second node, paste the VPS's public address into
bootstrap_peers.
Phone keeps going offline
Battery optimisation. In Android settings, mark MeshHold as unrestricted β and enable UnifiedPush in Profile so wake-ups still reach you when the foreground service is paused.
RF stuck at 1
Open the vault's Health panel. If only one reliable node is online,
RF can't climb. Bring up the second reliable node, or temporarily mark
a third as reliable: true in its config.
Next up
Add a chat vault for your household (see The Secure Comms Hub),
or expose Photos over S3 to back up your Immich instance (see
The S3-compatible Backend).