Add a README

This commit is contained in:
2026-04-17 18:04:55 +01:00
parent a7e09aa3e9
commit a044613c4a

95
README.md Normal file
View File

@@ -0,0 +1,95 @@
# `web-pinentry`: decrypt server keys from your phone
`web-pinentry` is a [pinentry](https://github.com/gpg/pinentry) program for
Linux servers, allowing you to decrypt keys on your server remotely via your
phone. It relies on HTTP and the Matrix protocol. This is a modern approach to
tasks often faced during server boot up, when things like SQL passwords and API
tokens need to be ascertained before services can begin.
Sensitive server credentials are historically stored in environment variable
files. Though this legacy approach eases automated server startup, it carries a
huge cost in terms of security. If the server becomes compromised, passwords
and other sensitive information within environment variables and plaintext
config files poses a security threat. Server admins may ultimately
feel compelled to reject server access to engineers or technicians lest they
gain knowledge of crucial passwords in config files.
To solve this headache, passwords can be encrypted with a GPG wrapper tool such
as `pass`. Rather than pulling passwords from a file, they are obtained through
subprocess calls, e.g.
`pass sql-root-password`
`pass github-token`
This is standard practice on desktops, but not yet on servers.
`web-pinentry` attempts to make this workflow more feasible on servers. Programs
typically pause for user authentication when executing GPG or `pass` commands. On desktop,
a user may types a password or inserts a Yubi key before things can resume. `web-pinentry`
does not assume the user has physical access to the computer, taking a radically
different yet somewhat simple approach.
## How `web-pinentry` works
`web-pinentry` is designed to override the builtin GPG `pinentry` program:
Rather than waiting for a password to be typed in the same terminal as the
current process, `web-pinentry` awaits a user password over the network
via a temporary login link. Here is an example of this altered workflow:
- An engineer reboots a server.
- The init system (systemd or otherwise) starts up the various services.
- Among these is a Scala REST API that attempts to reach a remote DB.
- In the Scala code, a subprocess is used to configure the SQL password:
- I.e. `pass sql-root-password` is executed as the REST API spins up.
- Under the hood, GNU `pass` attempts to decrypt a master-password-protected
file containing the SQL login details.
- This triggers a pinentry program which seeks the master password.
Usually this is the point at which most naively configured systems would
hang or timeout. However, with `web-pinentry` as your default pinentry program,
the workflow continues unininterupted:
- GPG communicates with `web-pinentry`, and the latter spins up a temporary
HTTP server.
- On this HTTP server, there is exactly one randomly generated path.
- This path is sent as a URL to a Matrix channel, where the system admin
can then enter the GPG master password.
- Passwords and API keys are then momentarily available for the server's
startup procedure.
## Security Details
- Login paths only live for two GET requests, and the pinentry program must
therefore try again with a new link if you type your password wrong.
- `web-pinentry`'s HTTP server only responds to requests made via docker
network IPs or localhost.
- It's imperative to run web-pinentry behind a HTTPS proxy (recommendation: `caddy`).
- All paths that are not the login path are restricted.
- The login link is sent to Matrix via `matrix-commander-rs`, which needs to be
configured in advance.
- The login link is randomly generated anew on each invocation.
- Once a password is entered correctly, the HTTP server is torn down.
**WARNING**: It is highly recommended to use a GPG master password that is randomly generated
and stored within a password manager. This protects you from phishing attacks
and can further automate the pinentry workflow. Without this protection, a bad
actor could create a visually similar website to the `web-pinentry` default
login, and attempt to prompt you for your password.
## Requirements
- [`matrix-commander-rs`](https://github.com/8go/matrix-commander-rs)
- [Matrix](https://matrix.org/)
- Your Matrix user
- A Matrix bot user (just a normal user with a noticeable username like `notification-bot`)
- A private Matrix channel between you and the bot (preferably encrypted).
- A proxy server with HTTPS support (E.g. [`caddy`](https://caddyserver.com/))
- A DNS subdomain/domain you control.
For development contributors only:
- [`rust`](https://rust-lang.org/)
## Installation instructions
```{sh}
cargo build
```