Security
evertap is for development data, not production. It still holds the root keys of every database and bucket service it runs, and it takes sign-ins over the network, so this page sets out what it exposes and what it trusts. To report a vulnerability, follow SECURITY.md.
What listens where
On the machine running evertap:
| What | network and cloudflare | local | Before setup |
|---|---|---|---|
The UI and API (EVERTAP_PORT, 8080) | The address chosen in setup | 127.77.0.1 | 127.0.0.1 |
| Database and bucket entries | 127.0.0.1: 6432, 3306, 6379, 9000, 3900 | 127.77.0.1: 5432, 3306, 6379, 9000, 3900 | 127.0.0.1 |
| The services in Docker | 127.0.0.1, on ports Docker picks | The same | The same |
| The CLI's socket | evertap.sock in the data directory | The same | The same |
| Buckets reached from anywhere (9900) | Beside the UI, once buckets have an address | None | None |
- Only the UI ever listens where other machines can connect, and only in
networkmode when you choose such an address. Incloudflaremode, other machines reach it through your tunnel. Databases and buckets are reached from other machines only through the UI's address, by a signed-inevertap connect. - The one exception is a bucket you make reachable from anywhere, through the address you give
buckets (Signed links that work anywhere). Its
entry listens beside the UI, on its own port, so evertap tells its requests apart by where they
arrive, not by a Host header anyone can send. It answers only for those buckets, and each request
still needs a signature made with that bucket's key. It listens on another address of the machine
only when you chose one for the UI; for every interface it stays on
127.0.0.1. - evertap never asks Docker to publish on
0.0.0.0. Docker's firewall rules bypassufw, so a port Docker published there would be open whateverufwsays. - Docker Engine before 28.0, and 28.2 to 28.3.2 once firewalld reloads, lets other machines on the
same network reach what Docker publishes on
127.0.0.1. The Doctor warns about it; update Docker. - Listening on every interface of a machine with an address the internet routes to opens the sign-in page to the internet over plain HTTP. Setup, Settings, and the log warn about it.
- The engines' own consoles and admin APIs, such as RustFS's console and Garage's admin API, are never published. evertap alone holds their keys.
On a laptop, evertap connect listens on 127.77.0.1 alone unless you pass --host.
Signing in
Every request that arrives over the network needs a sign-in, in every mode and from every address,
including 127.0.0.1: a tunnel or proxy on the same machine arrives from there too. Only two things
skip it:
- The CLI on the machine running evertap, over
evertap.sock. The data directory is readable by the user running evertap alone, and so is the socket in it. - Demo mode (
EVERTAP_DEMO=1), which has no real data and no sign-in.
evertap has no passwords. There are two kinds of sign-in:
| Who | How it signs in | What it sends |
|---|---|---|
| A browser | A signed-in browser approves the code it shows, or a one-time link from evertap signin-link or evertap setup | A session cookie |
| A paired CLI, or a script | evertap login, approved in a signed-in browser; or an API key created in the UI | Authorization: Bearer <token> |
- A cookie works only on the UI's API, which also needs a header that only evertap's own pages send, so another site cannot act as you. A token works only on the CLI's API. Neither works on the other's.
- The session cookie is
HttpOnlyandSameSite=Strict, andSecureover HTTPS. A browser stays signed in for 30 days after its last request. - Codes and sign-in links expire after 10 minutes, and a link works once. The approval page shows the request's address, the machine's name, and when it was made: approve only a code you just saw yourself.
- Approving sign-ins, creating API keys, and revoking are for a person in the UI. A paired CLI or an API key can do everything else, but cannot add or remove clients, so a leaked token cannot grant itself more access.
- A protected resource cannot be deleted. From the CLI or the API, protection has to be turned off
first, as a separate step (
evertap unprotect). - evertap keeps tokens and API keys only as SHA-256 hashes. An API key is shown once, when it is created.
- Clients in the UI lists every browser, CLI, and API key, with where it was last used from. Revoking one ends it at once; its open database connections close within about a minute.
- While sign-ins wait for approval, each address can hold 5 of them, so one caller cannot keep
everyone else from signing in.
evertap signin-linkis never limited.
The CLI saves its token in ~/.config/evertap/config.json, readable by your user alone. Anyone with
that file acts as you. evertap logout revokes it.
Addresses and names evertap trusts
- evertap never trusts a request because of where it comes from.
- It answers only to requests that name its own address,
localhost, an IP address, or innetworkmode its name on your network. A web page that points its own hostname at your machine is turned away. - In
networkandcloudflaremode, a request from loopback or from a Docker bridge network comes from a proxy, a tunnel, or a container on this machine, so evertap takes the caller's address from the last entry ofX-Forwarded-For. From anywhere else, and inlocalmode, it takes the connection's own address. A proxy on this machine must add the address it saw toX-Forwarded-For, not pass on what the caller sent, or callers can pretend to be someone else (Reverse proxies).
Plain HTTP
evertap serves plain HTTP and leaves HTTPS to a proxy or a tunnel. Over plain HTTP, anyone who can
watch the traffic can read sign-in cookies and tokens and act as you. Use plain HTTP only on a
network you trust, or one Tailscale encrypts. evertap login warns when the address is http://
and not on loopback.
What the data directory holds
The data directory, ~/.local/share/evertap unless EVERTAP_DATA_DIR says otherwise, is readable
by the user running evertap alone (mode 0700). Inside, in plain text:
evertap.db: every database password and bucket key evertap handed out, the root and admin keys of every service, the token hashes, and the settings. Before an upgrade changes its format, a copy is kept beside it asevertap.db.v<version>-<time>.bak, with the same contents.postgresql/pgbouncer/userlist.txtandpgbouncer.ini: each PostgreSQL database's password, for PgBouncer. These files are readable by others (0644) so that PgBouncer can read them; the directory above keeps other users out.mysql/proxysql.cnf: ProxySQL's admin password.garage/garage.toml: Garage's admin token and secret.
Treat a backup or a copy of the data directory as you would those passwords. The data itself is in
Docker volumes whose names start with evertap, which a backup of the data directory does not
include.
Anyone who can use Docker on that machine can read the same secrets from the containers, and can do
anything else as root. Add to the docker group only users you would trust with root.
Data stays on one machine
evertap sends nothing to anyone else: no telemetry, and no account. It downloads the engines' images from Docker Hub the first time it needs them, pinned by digest.
The evertap name and logo are not licensed with the code (section 6 of the license). You may use them to refer to evertap, but not to name or brand your own product or service, or in a way that suggests evertap made or endorses it, without permission.
evertap is an independent project. It is not affiliated with, endorsed, sponsored, supported, or certified by the owners of the software it runs, and it uses their names only to say which software that is.
- Postgres, PostgreSQL and the Slonik Logo are trademarks or registered trademarks of the PostgreSQL Community Association of Canada, and used with their permission.
- MySQL is a registered trademark of Oracle and/or its affiliates.
- Redis is a registered trademark of Redis Ltd. Any rights therein are reserved to Redis Ltd.
- RustFS is a trademark of RustFS, Inc.
- Other names, including Garage, may be trademarks of their respective owners.