Server
The server is a single Go binary that receives the screenshots uploaded by the extension, stores them as PNG files with thumbnails and the address of the page they were taken from, and serves the web UI where users browse, annotate and share them. It keeps its metadata in SQLite or PostgreSQL and needs nothing else: no object store, no cache, no JavaScript toolchain.
Its source is public at github.com/mkende/screenshotter_server and a container image is published at ghcr.io/mkende/screenshotter.
Users and authentication
Users are identified by one or more of these backends, which can be combined:
- OpenID Connect, with any standard provider (Google, Keycloak, Dex, …). The server keeps a signed session cookie that the extension reuses for its uploads, so users log in once in the browser.
- Tailscale, taking the identity that a Tailscale proxy adds to each request.
- Proxy authentication, taking it from the headers set by a reverse proxy such as Authelia or oauth2-proxy.
- Anonymous, a single shared identity for local use or a fully trusted network.
Each user only sees their own screenshots. Administrators, designated by email or by group, additionally get a page listing every user and their images.
Access model
A screenshot’s link contains a random ID and, by default, opening that link
requires no login: the ID is the secret, which is what makes a link enough to
share a screenshot with a colleague or paste it in a chat. These public routes
are rate limited per source IP so IDs cannot be enumerated at scale. Set
server.require_auth_to_view = true if links must only work for logged-in
users.
Everything else (the gallery, thumbnails, annotation, deletion) is limited to the image owner and administrators.
The server expects to sit behind a reverse proxy that terminates TLS. Its session cookie is only sent over HTTPS, and it redirects every request to the canonical address it is configured with.