Send files between your own devices. Encrypted before they leave.
No accounts. No cloud. No size limit. No public port.
Get started · Screenshots · What it does · FAQ · Security
Airlock runs on one of your own machines and lets your phone, laptop and desktop pass files to each other over Tailscale.
Your files are locked on the sending device before anything is uploaded. The server holds only scrambled data. It never gets the key, so it cannot read your files, their names, or even their thumbnails.
Note
Airlock works end to end today. It is a personal project, and Status is honest about which platforms have been tested on real hardware.
You need two things. Both are free and take a few minutes.
- Tailscale installed on at least two of your devices
- HTTPS turned on for your Tailscale network. One switch on the DNS page of your admin console
Why does it need HTTPS?
Browsers only allow encryption and offline features on a secure connection. Without a real certificate, Airlock cannot lock your files in the browser at all. Tailscale hands out certificates for free, and Airlock renews them for you.
1. Get Airlock. Download the file for your computer from Releases.
Which file do I download?
| Your computer | File |
|---|---|
| Windows | airlock_..._windows_amd64.exe |
| Mac (M1 or newer) | airlock_..._darwin_arm64 |
| Mac (Intel) | airlock_..._darwin_amd64 |
| Linux | airlock_..._linux_amd64 |
| Raspberry Pi, ARM server | airlock_..._linux_arm64 |
On Mac and Linux, make it runnable first:
chmod +x airlock_*2. Run it. Double click it, or from a terminal:
./airlockIt prints one line. That line is your address:
open https://your-computer.your-network.ts.net/ on any device on your tailnet
3. Open that address on your phone, your laptop, anywhere on your Tailscale network.
The first device picks a passphrase. Every other device enters the same one. That passphrase is what unlocks your files, and it never leaves your devices.
That's it. Drop in a file, pick a device, press Send.
Install it as an app
Airlock installs to your home screen or desktop and gets its own icon and window, like a normal app.
- iPhone / iPad: Share button, then Add to Home Screen
- Android: menu, then Install app
- Windows / Mac desktop: the install icon in the address bar (Chrome or Edge)
Where the browser offers it, an Install button also appears on the Send screen, which saves hunting through a menu that moves between browser releases.
Android does not show an install option? Chrome only offers PWA installation when Android's current Home app supports pinned shortcuts. In Settings → Apps → Default apps → Home app, select Pixel Launcher or another launcher that supports pinned shortcuts, then force-stop and reopen Chrome because Chrome caches this capability for the life of its process. If every PWA is missing its install option, the launcher is the likely cause rather than Airlock's manifest.
On iPhone and iPad, install it before entering your passphrase. A browser tab and an installed app keep separate data, so a passphrase typed in the tab will not be there in the app.
Send from the Windows right-click menu
Adds Send with Airlock to the right-click menu, with the Airlock icon.
Choosing it opens the app with that file staged and waiting for you to pick a
destination. It works for arbitrary extensions—including .mpp and files with
no extension—not just the concrete suffixes Chromium allows a PWA to declare.
Install Airlock as an app in Chrome or Edge first. The menu entry points at the launcher the browser creates when you install it, so there is nothing to point at until you have. Then, from the repository:
powershell -ExecutionPolicy Bypass -File .\deploy\windows\install-context-menu.ps1The installer normally identifies the app's address from the browser profile. If that profile is unavailable, provide it explicitly:
powershell -ExecutionPolicy Bypass -File .\deploy\windows\install-context-menu.ps1 -Origin https://your-airlock-host:8443Remove it the same way with uninstall-context-menu.ps1.
It needs no administrator. The installer writes one per-user registry key and
copies a small PowerShell handoff script under %LOCALAPPDATA%\Airlock\Shell.
The helper listens on a random 127.0.0.1 port, serves the selected file once
only to your Airlock origin, then exits. It never receives your passphrase and
never uploads; the file lands on the normal staging list, and the browser does
the existing encryption only after you press Send.
Chrome may ask once whether Airlock can access devices on the local network. Choose Allow. The handoff is loopback-only—it cannot accept a connection from another machine—and denying it prevents the right-clicked file from being added. Airlock offers Try again if the prompt was missed.
On Windows 11 the entry appears under Show more options, which is where classic menu entries live. Shift+F10 opens that menu directly.
There is no ready-made .reg file to double-click: both the browser launcher
path and the installed app identifier differ by profile, and the helper also
needs the matching Airlock origin.
It says the port is in use
Something else on that machine already uses port 443, often tailscale serve.
Pick another one:
./airlock --port 9443The startup line will show the new address. Nothing else changes.
A device cannot find the server
Almost always Tailscale DNS being switched off on that device.
- Phone or tablet: open the Tailscale app, Settings, turn on Use Tailscale DNS
- Computer: run
tailscale set --accept-dns=true
Typing the numeric address instead will not work. Airlock's certificate is issued for the name, so only the name connects.
If the name resolves but nothing loads, your Tailscale access rules may not allow that device. Check the ACLs in your admin console.
| Inbox | History |
|---|---|
![]() |
![]() |
| What has arrived and is waiting. Saving a file clears it from the list, and anything nobody collects clears itself. | What passed through, after the files themselves are gone. |
| 📁 Any size | 50 GB video? Fine. Nothing is held in memory. |
| 🔒 Private | Locked on your device. The server stores what it cannot read. |
| ⚡ Skips what it already has | Send the same file twice and the second one is instant. |
| ✏️ Sends only what changed | Edit part of a big file, resend, and only that part uploads. |
| 🔁 Survives a dropped connection | Picks up where it stopped, not from zero. |
| 📬 Waits for you | Files sit on your server until a device collects them, then clear themselves. |
| 🔔 Tells you | A notification when something arrives, even with the app closed. |
| 📱 Works everywhere | Installs as an app on phone, tablet and desktop. |
| Stops at 25 MB. | |
| Google Drive, Dropbox | Uploads your file to a company that can read it. |
| AirDrop | Apple devices only, same room. |
| A USB stick | A walk across the room, and never with your phone. |
| Taildrop | Genuinely good, and simpler. It has no inbox, no history, and both devices must be awake. Reach for it first for a quick one-off. |
Can the server read my files?
No. Your files are locked on the device sending them, before anything is uploaded, using a key made from your passphrase. That key is never sent anywhere.
The server only ever holds scrambled data. Filenames, sizes and thumbnails are locked too. This stays true even if the server is a rented VPS, and even if somebody steals its hard drive.
What if I forget my passphrase?
Your files cannot be recovered. There is no reset, because nobody holds a copy of your key, including you after you have forgotten it. That is the trade for the server never being able to read anything.
If it happens, delete Airlock's data folder and start again with a new passphrase.
How long does a file wait to be collected?
Ten minutes by default, then the server deletes it and the sender has to send it again. The point is that your own machine is not a place files pile up: it holds them only long enough to be picked up.
If your devices are not always to hand, give it longer:
./airlock --ttl-minutes 1440 # a dayA file that has been saved on a device leaves the queue immediately, without waiting for the timer.
Do I need to buy a server?
No. Any computer you already own works: a desktop, an old laptop, a Raspberry Pi. It just needs to be switched on when you want to send something.
A rented server only helps if none of your machines are reliably awake.
Does it work on iPhone and Android?
Yes, through the browser, and it installs to your home screen like an app.
For notifications while the app is closed, Chrome is the more reliable choice on Android. Firefox on Android only receives notifications while Firefox itself is running.
Open the Inbox and press Test notification to verify the subscription and Android delivery without waiting for a file. Swiping Airlock away normally still allows push; using Android's Force stop prevents notifications until the app is opened again.
Is my file safe if someone breaks into the server?
Your file contents are. An intruder gets scrambled data and cannot unlock any of it without your passphrase, which never reached that machine.
They would see device names, file sizes and timestamps, and they could delete things. Worth knowing.
Is it peer to peer?
Not any more. There was a direct device-to-device mode and it was removed after measuring it: it was about four times slower than going through the server, and it needed both devices awake at the same moment.
Tailscale already connects your devices directly. Everything Airlock sends is already locked before it leaves, so routing it through your own server costs nothing in privacy and is faster and far more reliable.
Can other people on my Tailscale network see my files?
They would need your passphrase to read anything. But on a shared network, lock it down properly:
./airlock --allow-users you@example.com --require-approvalNew devices then wait for approval from a device you have already approved.
Short version: your files are encrypted on your device with a key made from your passphrase. The server never sees that key.
| What | How |
|---|---|
| Not on the internet | Only reachable inside your Tailscale network |
| Only your devices | Tailscale proves who each device is |
| A lost phone | Revoke it instantly, no restart needed |
| The server, its disk, its backups | AES-256-GCM encryption |
| Filenames and thumbnails | Encrypted too, not plain text |
| Tampering | Every piece is verified before your file is rebuilt |
- Someone holding your unlocked phone. They have your files.
- A forgotten passphrase. Nothing can recover it.
- A server you do not control. It still learns who sent how much, and when.
Technical detail
Your passphrase becomes a key with PBKDF2-SHA256 at 600,000 iterations against a per-server salt, held in your browser's origin-private storage and never transmitted.
Files are split with content-defined chunking, so an edit does not shift every later boundary, which is what makes resending a changed file cheap. Each piece gets an id derived from its content and your key, so your own devices agree on ids without anyone else being able to confirm a guess about the contents.
Pieces are encrypted with AES-256-GCM. Filenames, sizes and thumbnails travel as separate encrypted records. Every piece is verified on the way back out, so a substituted or corrupted one fails loudly instead of producing a plausible wrong file.
Most people need none of these.
| Flag | Default | What it does |
|---|---|---|
--port |
443 |
Use a different port |
--data |
system folder | Where files are stored |
--ttl-minutes |
10 |
How long an uncollected file waits before the server deletes it |
--require-approval |
off | New devices must be approved first |
--allow-users |
you | Which Tailscale accounts may connect |
--version |
Print the version |
Keeping it running in the background
Linux (systemd). Airlock needs permission to fetch its certificate:
sudo tailscale set --operator=$USER# /etc/systemd/system/airlock.service
[Unit]
Description=Airlock
After=network-online.target tailscaled.service
Wants=network-online.target
[Service]
Type=simple
User=airlock
ExecStart=/usr/local/bin/airlock --data /var/lib/airlock
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.targetsudo systemctl enable --now airlockWindows. Create a scheduled task that runs at logon. Data is kept in
%LOCALAPPDATA%\Airlock.
Full instructions are in Set up a server. For a rented VPS with Docker, see the detailed guide.
Working: sending, receiving, notifications, saving, transfer history, thumbnails, device approval, skipping data you already have, resending only what changed, and resuming after a dropped connection.
Tested on real devices: Windows (Chrome, Edge, Firefox), Android (Chrome, Firefox), iPad, and a two-device network.
Not yet tested on hardware: iPhone, macOS Safari, Linux desktop.
Known limit: closing the tab mid-transfer restarts from the last confirmed piece rather than the exact byte.
Building and testing
go test ./... # server
node --test web/*.test.mjs # client, no dependencies to install
go build -o airlock . # the client is embedded, so this is the whole buildThe client is vanilla ES modules and plain CSS. No build step, no bundler, no
package.json, no framework, no CDN. Every CSS or JS edit needs go build to
take effect, because the client ships inside the binary.
CI runs the full suite on Linux, macOS and Windows for every push.
How a transfer works
Editable source: docs/assets/transfer-flow.excalidraw, or open it in Excalidraw.
- The file is split into pieces along its own content, so an edit does not move every later boundary.
- Each piece is fingerprinted using your key.
- The server is asked which fingerprints it already has. That one question is what makes deduplication, partial resends and resuming all work.
- Only the missing pieces are encrypted and uploaded.
- The encrypted name, size and thumbnail land last, and that is what triggers the notification.
Full detail is in the design spec.
Measured performance
| Phase | Throughput |
|---|---|
| Encryption | ~304 MB/s |
| Splitting | ~1.09 GB/s |
| Server storage | ~550 MB/s |
| Upload, end to end | 43 to 53 MB/s |
| Download, end to end | 66 to 109 MB/s |
| Rebuilding the file | ~104 MB/s |
Encryption is not the bottleneck, which is why there is no option to turn it off. Numbers are from one desktop (i9-14900K); phone measurements are still open. Method and caveats in docs/benchmarks.md.
MIT. Do what you like with it.
- Set up a server - the short version, for a machine you own
- Detailed deployment - a rented VPS, Docker, day-two operations
- Design spec - architecture and wire protocol
- Benchmarks - what was measured, and what is still open
- Enabling Tailscale HTTPS - the one prerequisite
- Taildrop - the simpler tool, already on your devices






