Self-hosted file ghosting for Android + Raspberry Pi — or any home server on your network.
Free phone storage without handing your files to a third-party cloud.
ShadowFS moves inactive files from your Android phone to your own Raspberry Pi — or any home server connected to your network (an old PC, a NAS, a mini PC: anything that runs Linux) — then restores them when you need them. Think storage optimization like iCloud, but self-hosted, local-first, and protected by mutual TLS.
Core safety rule: ShadowFS ghosts a local file only after the Raspberry Pi has received it, verified it with SHA-256, stored it, and sent a final ACK.
| Own your storage | Free phone space | Verified transfers | Built for real devices |
|---|---|---|---|
| Files stay on your Raspberry Pi or home server, not a subscription cloud. | Cold photos, videos, PDFs and archives become lightweight ghosts. | Uploads and restores are checksum-gated before local files are changed. | Foreground service, QR pairing, Tailscale-friendly networking and recovery paths. |
- Detects large inactive files on Android.
- Uploads originals to a daemon on your Raspberry Pi or home server over TCP + TLS 1.3 + mTLS.
- Verifies file integrity with SHA-256.
- Replaces local files with tiny ghost markers or previews only after server ACK.
- Restores files on demand, using temporary downloads until verification passes.
- Keeps each paired device isolated under its own storage namespace.
- Defends against sync loops from Google Photos, OneDrive, Amazon Photos and similar backup apps.
Default ports:
| Port | Purpose |
|---|---|
4243/tcp |
Android client protocol over TLS + mTLS |
4244/tcp |
temporary HTTP pairing endpoint for QR setup |
Interrupted transfers are designed to be recoverable:
- uploads use
.partfiles on the Raspberry Pi; - downloads use
.shadowdl.tmpfiles on Android; - incomplete bytes are never published as final files.
ShadowFS is in field testing. The architecture is usable, but it is not yet a polished consumer product and should not be treated as the only copy of important data.
Recommended use today:
- test upload, restore and delete flows before trusting a folder;
- keep a separate backup for critical data;
- avoid mixing ShadowFS and aggressive cloud-sync tools on the same directory unless that directory is protected;
- validate real-device behavior with TEST_CHECKLIST.md.
.
├── shadow_client/ Android app, Kotlin + Gradle
├── shadow_daemon/ Raspberry Pi daemon, Go + SQLite
├── sito/ project website + localized docs (EN·IT·DE·ES·FR)
├── docs/assets/ README images and diagrams
├── USER_MANUAL.md end-user setup and usage guide
├── DEPLOY_GUIDE.md deployment guide for Android + Raspberry Pi
├── TEST_CHECKLIST.md real-device validation checklist
└── ANDROID_APP_AUDIT.md Android implementation audit notes
The daemon is a single static Go binary: it runs the same on a Raspberry Pi, an old laptop, a NAS or any x86/ARM Linux box plugged into your home network.
git clone https://github.com/robycinix/ShadowFS.git
cd ShadowFS/shadow_daemon
sudo chmod +x install_raspberry.sh
sudo ./install_raspberry.shThe installer builds the daemon, creates /opt/shadowfs and
/storage/shadow_root, generates mTLS certificates, installs a systemd
service and prints pairing information.
systemctl status shadowfs
journalctl -fu shadowfs- Open
shadow_client/in Android Studio. - Let Gradle sync.
- Connect a real Android device.
- Run the debug build.
- Pair the app with the Raspberry Pi by QR code or manual certificate import.
Manual build:
cd shadow_client
.\gradlew.bat assembleDebugShadowFS works best when Android can reach the Raspberry Pi through a private network such as Tailscale.
curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up
tailscale ip -4Use the Raspberry Pi Tailscale IP in the Android app, or include it when regenerating certificates:
sudo ./shadowdaemon --generate-certs \
--server-ip="$(tailscale ip -4),$(hostname -I | awk '{print $1}')"ShadowFS assumes the Raspberry Pi and Android device are controlled by the same person or household.
- A private CA is generated locally.
- The daemon requires a valid client certificate.
- The Android app validates the daemon certificate.
- Each paired device gets an isolated storage namespace.
- Pairing tokens are short-lived and one-time use.
- Generated certificates, private keys, databases, logs and storage roots are ignored by git.
Run daemon checks:
cd shadow_daemon
go test ./...
go vet ./...Build the Android client:
cd shadow_client
.\gradlew.bat assembleDebugGitHub Actions runs Go checks and an Android debug build on pushes and pull
requests to main.
- User Manual
- Deployment Guide
- Real-Device Test Checklist
- Security Policy
- Contributing Guide
- Changelog
- Localized guides — English, Italiano, Deutsch, Español, Français — in
sito/docs/
- TCP + TLS + mTLS Android protocol
- QR-code pairing
- Resumable uploads
- Resumable downloads
- Per-device storage isolation
- Manual restore list
- Anti-loop handling for cloud backup apps
- Signed release builds
- Automated Android instrumentation tests
- Formal protocol schema (Protobuf or similar)
- Optional QUIC transport after the TCP path is fully validated
- Incremental backup or block-level dedupe
Issues, bug reports and focused pull requests are welcome. Please read CONTRIBUTING.md before opening a PR. This project handles local files, so data-loss safety matters more than cosmetic speed.
ShadowFS is provided as is, without warranties of any kind. The project is designed to reduce risk by verifying transfers before changing local files, but it cannot guarantee protection from hardware failure, misconfiguration, accidental deletion, filesystem corruption, interrupted deployments, cloud-sync conflicts, or any other condition outside the software's control.
Use ShadowFS first with non-critical files, validate upload and restore flows on your own devices, and always keep a separate backup of important data. By using the software, you accept responsibility for how it is configured and for the files you choose to manage with it.
MIT. See LICENSE.
