Self-hosting

Self-hosting overview

The sync server is a single Node.js file that stores one encrypted blob per account. Here is what it needs and how to try it.

On this page

What the server stores

The app encrypts everything before uploading it and never sends the key, so the server can’t read your hosts, passwords, keys or snippets.

What the server does see:

  • user names
  • a SHA-256 hash of each account’s login key
  • the size and time of each upload
  • the IP addresses of the devices that connect

It is a single file (server.js) with no dependencies. It needs Node.js 24 or newer for the built-in node:sqlite.

Requirements

The Docker setup needs:

  • a Linux server with Docker and Docker Compose v2
  • a reverse proxy on that server that already handles HTTPS for other sites, like Nginx Proxy Manager, Caddy, Traefik or nginx
  • a domain for sync, like sync.example.com

The app refuses sync servers that don’t use HTTPS, except localhost.

Configuration

The server is configured with environment variables:

VariableDefaultMeaning
PORT3000Port the server listens on.
DB_PATH./sync.dbSQLite database file.
REGISTRATION_CODEemptyInvite code needed to create an account. Empty turns registration off.
TRUST_PROXYoffSet to 1 only when the server can be reached through your reverse proxy alone, and that proxy overwrites X-Real-IP with the client’s address. The address is used to slow down repeated failed logins. The header is only used when the connection comes from a local or private address (127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, ::1, fc00::/7), which is where a proxy on the same server or in Docker connects from.

Try it locally

From a clone of the repository:

bash
cd server
REGISTRATION_CODE=test node server.js

In the app, go to Settings → Sync → Create account and use http://localhost:3000 as the server and test as the invite code.

Next steps

Set up with Docker walks through a real server in eight steps. Server maintenance covers updates and backups.

Made with love by zukotuutori