What the FUTO Notes sync server can see
From what it stores, the FUTO Notes sync server cannot read your notes, their titles, or their folder names. It does see the shape of your activity, and because it receives your sync password every time a device signs in, whoever controls the running server can decrypt everything. The self-hosted design assumes that person is you.
This page separates those cases. For the cryptography itself, see how the encryption works.
What the server never sees
- Note text, titles, filenames, folder names, tags, and links.
- Image contents, and which objects are images rather than notes (though size is a hint).
- The vault key, unless someone uses your password to unwrap it.
Every note and image is encrypted on the device, with its path inside the ciphertext, before upload.
What the server always sees
The server stores sync coordination data in plain form in its database, where anyone who can read that database can see it:
- How many objects your vault holds, including deleted ones.
- The exact size of each blob. It is the size of the note’s path plus its content plus 33 bytes, with no padding, so the server knows roughly how long each note is.
- When each object was created and last changed, and the order of every change in the vault.
- How many times each object has been changed, from its version number.
- Which objects were deleted, and when. A deletion is a plaintext flag on the object.
- Old versions, still encrypted. When a note changes or is deleted, the server keeps the previous blob for 365 days so devices can use it for merges. The deleted object itself stays in the database as a marker.
- The wrapped vault key, with its salt and PBKDF2 parameters.
- Sessions: a SHA-256 hash of each session token and its expiry time.
- Network details: the IP address of each connection, and when a device holds its live-update stream open. The server does not write an access log or store IP addresses, but a reverse proxy in front of it may.
Renaming or moving a note shows up only as objects being changed, created, or deleted. The server never learns the old or new name.
Who can learn what
Someone with a copy of the data directory
Someone with a copy of the server’s data directory gets all the metadata above, but cannot read your notes without the sync password. That covers a stolen disk, a leaked backup, or anyone who can read the files.
They can try to guess the password offline: each guess costs one PBKDF2-HMAC-SHA256 run at 100,000 iterations, and a right guess is confirmed by the wrapped key’s GCM tag. A long random password makes this impractical. A short or reused one does not.
Someone who also has the server’s .env
With the server’s .env and the data directory, someone can decrypt everything, including the retained old versions, because the installer writes the sync password into .env in plain text by default. By default .env and the data directory sit side by side in the install directory, so a copy of the whole install directory is a copy of everything.
If .env holds a scrypt hash in FUTO_NOTES_PASSWORD_HASH instead, the hash is one more offline guessing target, but it does not reveal the password directly.
Whoever runs the server
Whoever controls the server process, or the TLS proxy in front of it, can read the sync password, and with it unwrap the vault key and read every note, current and retained. The sync password is also the login password. The app sends it in the body of POST /api/auth/password/login when it first connects, whenever a session expires (sessions last seven days), and each time the iOS or Android app starts. The server code does not store or log it.
This is why the encryption is not a defense against a server you don’t trust. On a self-hosted server, that operator is you.
Someone on the network
Over plain HTTP, the password and the session token cross the network readable, which gives an eavesdropper the same position as the operator. Over TLS they see only traffic volume and timing. Notes are encrypted either way. See reverse proxy setup for adding TLS.
What a malicious or compromised server could do
A malicious or compromised server could do any of the following, and the app detects none of it today.
- Take the password. At the next sign-in it receives the password, and with it every note.
- Withhold data. It can leave objects out of the list it returns, or stop accepting uploads. The app cannot tell a withheld note from one that doesn’t exist.
- Roll back. It can serve an older blob for a note, swap blobs between objects, or restore an older copy of its database. Blobs are not bound to their object or version, and the app does not check that versions or the change order only move forward, so an older blob decrypts and is applied like any other change.
- Delete. It can mark objects deleted. When a device receives a deletion, it deletes its local copy if that copy is unchanged since the last sync, and keeps it as a conflict copy if it has local edits. It can also delete the whole vault.
- Forge notes, but only with the password. Without the vault key it cannot produce a blob that decrypts. Someone holding only the disk cannot insert notes.
Your defenses are to run the server yourself, put TLS in front of it, and keep backups of your notes folder. The notes on each device are plain files, so a device backup does not depend on the server. See backing up the server.
Sessions and sign-in
- Sign-in is
POST /api/auth/password/loginwith{"password": "..."}. The server allows 10 attempts per minute per client address. Behind a reverse proxy it sees only the proxy’s address, so all clients share one limit. - Session tokens are 32 random bytes, hex-encoded. The server stores only their SHA-256 hash, so a copy of the database contains no usable token.
- Lifetime is seven days from sign-in, and use does not extend it. After that the app signs in again with its saved password.
- No revocation. Changing the server’s password does not end existing sessions, and disconnecting a device in the app does not end its session on the server. A token stays valid until it expires or the server’s database is replaced.
- Where the token lives. The desktop app keeps its current token in plain text in
.app-state.jsonin the notes folder, so a copy of that folder can include a working token for up to seven days. The iOS and Android apps keep the token only in memory.
A stolen token lets someone act as your devices do: list and download encrypted blobs, upload, delete objects, or delete the vault. It does not let them decrypt anything, because a token carries no key.
Next steps
- How the encryption works: the primitives, key hierarchy, and blob format.
- Reverse proxy setup: put TLS in front of the server.
- Back up the server: protect against a lost or damaged server.