A private, end-to-end encrypted file vault for Android - like Snapchat's "My Eyes Only", but for any file, any video length, on a server you own.
Vault is a native Android app (Kotlin + Jetpack Compose) for keeping photos, videos and any other file somewhere only you can open. Everything is encrypted on the phone before it's uploaded, so the server only ever stores scrambled data - it can't see file names, types or contents, and neither can anyone who gets hold of it. It can see how many files there are, roughly how big each one is and when it was added.
Vault talks to your own self-hosted Vault server over HTTPS. The server (Go, standard library only) and the Android app's source are both in this repository.
Choose a passkey
|
Argon2id stretches it into two keys
|
+-----------------------------+-----------------------------+
| |
Vault key (never leaves the phone) Login key (server keeps only a hash)
|
Every file gets its own random key
|
Sealed in 1 MiB chunks with AES-256-GCM -> names, types and thumbnails encrypted too
|
Uploaded to your server as unreadable blobs
The passkey can't be recovered or reset. If you forget it, your files are gone for good - that's the point.
- End-to-end encryption - your passkey and vault key never leave the phone
- Any file, any size - photos, videos of any length, documents, anything
- Add from anywhere - the + button offers "Photos and videos", which opens the usual Android chooser (your gallery, Google Photos, Files or any other app that can supply pictures), or "Any file" for documents. Sharing to Vault from another app works too
- Built-in viewer - photos and streaming video playback, with thumbnails; videos replay when they finish (toggle with the repeat button)
- Folders - starts with Photos, Videos and Documents; add or delete your own
- Offline mode - files added without a connection are kept encrypted on the phone and upload automatically later
- Resumable uploads - big files pick up where they left off if the connection drops
- Fingerprint unlock - optional, on top of the passkey
- Hidden in recent apps - the app switcher shows a blank screen, not your files
- Delete - remove files permanently from the vault
- Install the APK (see Download).
- Open Vault and enter your Vault server's address (
https://...). - The first time, switch on First-time setup, choose a passkey and paste the server's one-time setup token.
- On any other phone, enter the same server address and passkey.
Changing the server address later wipes that phone's offline copy and stored keys, because they belong to the old server.
Requires Android 9 or newer.
Grab the latest Vault-<version>.apk (about 10 MB) from the
Releases page, open it on your phone and allow installs from
your browser or file manager when Android asks.
To check the download, compare its SHA-256 with the one in that release's
notes, and the signing certificate with this one (apksigner verify --print-certs shows it):
Signing certificate: 5352d597c8b00e76f032df64c9f91f30965d4753156087c677d19b95af5bd017
Updates are signed with the same certificate, so they install over the top without losing anything.
The server stores only encrypted blobs, so a plain copy of its data folder is a full backup. With Docker:
echo "VAULT_SETUP_TOKEN=$(openssl rand -hex 32)" > .env && chmod 600 .env
mkdir -p data && sudo chown 65532:65532 data
docker compose up -d --buildThe container runs as user 65532, so the data folder must belong to it; a folder Docker creates on its own belongs to root and the server cannot start.
It listens on 127.0.0.1:8092. Put it behind HTTPS (a reverse proxy, or a
Cloudflare Tunnel pointing at http://localhost:8092) - the app only accepts
https:// addresses. The VAULT_SETUP_TOKEN is what you paste into the app's
first-time setup; it only works once.
Wrong passkeys are counted per visitor: five in a row pause logins from that
address, with the pause doubling up to 15 minutes, and 100 from anywhere pause
logins for everyone. Behind a Cloudflare Tunnel every visitor arrives from the
tunnel, so add VAULT_CLIENT_IP_HEADER=CF-Connecting-IP to .env to count
each real address. Only set it when the proxy is the one thing that can reach
the port, since the header is trusted as given.
Without Docker:
cd server
VAULT_DATA=./data VAULT_SETUP_TOKEN=<random> go run .If you use Cloudflare, keep upload chunks at 32 MiB or less - it rejects request bodies over 100 MB on free plans.
cd server && go build -o vault-server . && go test -race ./...
cd ../android
./gradlew :core:test # crypto + end-to-end tests against the real server
./gradlew :app:assembleRelease # app.vault.publicThe APK lands at android/app/build/outputs/apk/release/app-release.apk.
Requires JDK 17+ and the Android SDK. Release builds are signed with
~/.vault-release.jks when it exists (password in ~/.vault-release.pass);
without it the build still succeeds and produces an unsigned APK, so anyone
can build from source and sign with their own key.
Clone with git:
git clone https://github.com/drew-codes-things/Vault.gitOr with the GitHub CLI:
gh repo clone drew-codes-things/VaultAll rights reserved - free to download and use, but not to copy, modify or redistribute. See LICENSE.
Made by Drew