Pular para o conteúdo

You're viewing the prerelease documentation siteContent here is for testing and may differ from the live docs.

Go to live docs

Images and variants

Este conteúdo não está disponível em sua língua ainda.

onetimesecret/onetimesecret is the image to deploy. It is the default build target, and it is what both shipped Compose stacks and the project’s own quick start run. Everything else on this page is either a specialised build of it or a companion service that sits in front of it.

The main image is single-process: one Puma web server started by the container entrypoint, listening on port 3000, running as a non-root user (uid 1001), with a health check baked in. It carries no datastore — the lite variant below is the only image that does — so you run Valkey or Redis alongside it.

Install with Docker is the next page: it runs this image under the two Compose stacks the project ships. If you are not running containers at all, Install on Linux installs from a source checkout instead — the vX.Y.Z release names below apply there too, as git tags rather than image tags.

The project builds four images from one repository, and the release workflow publishes three of them. Each published image goes to two registries under matching names, so ghcr.io/onetimesecret/<name> and onetimesecret/<name> on Docker Hub are interchangeable.

Variant Repository name Published by the release workflow
Main onetimesecret yes
S6 onetimesecret-s6 yes
Lite onetimesecret-lite yes
Caddy onetimesecret-caddy no — build it yourself

Published images are built for linux/amd64 and linux/arm64.

Commands and Compose snippets throughout these pages name a shell variable rather than a literal tag. Set it once per shell to the release you intend to run, choosing it from the releases list:

Terminal window
export OTS_VERSION=vX.Y.Z

Tags of the form vX.Y.Z are immutable and point at one release forever. The rest move: latest follows the newest release, next follows release candidates and pushes to develop, edge and a sanitized branch name follow any branch push, nightly is rebuilt by a 03:00 UTC schedule, and dev is what a manual build with no version input produces.

Pin an immutable tag. Releases before 1.0 can introduce breaking changes between minor versions, which is why the shipped Compose stacks default their OTS_IMAGE_TAG variable to a specific release rather than to latest — and why a CI guard fails the build if that default drifts from the release the project’s own quick start names, or if it is set to a moving tag at all.

S6 — web, worker and scheduler supervised in one container

Section titled “S6 — web, worker and scheduler supervised in one container”

onetimesecret-s6 is the application built on top of the s6-overlay supervisor, which runs three processes in a single container: the web server, the email worker and the scheduler. It restarts its own services on crash and coordinates their shutdown, where the main image runs one process and leaves supervision to Compose, systemd or your orchestrator. It is published to both registries alongside the main image.

Lite — demos and testing, never production

Section titled “Lite — demos and testing, never production”

onetimesecret-lite is the main image with a Redis server installed inside it, so a single container gives you a working instance with nothing else to set up. It is ephemeral by design: the datastore lives in the container and every secret is lost when that container stops. It also runs as root, because redis-server needs write access the application user does not have. Use it for a demo, a local trial or a throwaway test, and for nothing else.

Caddy — the TLS proxy the full stack builds

Section titled “Caddy — the TLS proxy the full stack builds”

onetimesecret-caddy is not the application. It is a custom Caddy build carrying plugins that stock caddy:2 does not have: caddy-ratelimit, caddy-security, transform-encoder, and a configurable caddy-dns module for DNS challenges. The release workflow does not publish it; the full Compose stack builds it from docker/variants/caddy.dockerfile rather than pulling it.

It ships with PUBLIC_DIR empty on purpose. The application container serves its own built assets, so the proxy static-serves only what exists under that directory and proxies everything else — an empty directory means proxy everything. Mounting assets in at run time is what makes Caddy serve them.

Every image is built with Docker Bake from docker/bake.hcl. Invoking it with no target builds the main image; the all group builds all four, and the ci group builds the three the release workflow publishes. A local bake produces a single-architecture image unless you set PLATFORMS.

A brand pack can be baked into the image at build time with --build-arg BRAND_PACK=<name>, and the build fails outright if the named pack was never generated. The same pack can also be selected at run time through BRAND_PACK or BRAND_ASSETS_DIR, with no rebuild.