A minimal, anonymous pastebin. Paste text, get a short link, share it. No accounts, no tracking, no noise.
Pastor is a small distributed system composed of several services that each own a single responsibility:
NGINX acts as the API gateway — it terminates connections, enforces rate limits on paste creation, and reverse-proxies to the API service.
API service (Go) handles all HTTP — creating pastes, reading them, and deleting them. On a write it acquires a pre-generated slug from the hash service, stores the content in MinIO, and writes metadata (slug, size, TTL, timestamps) to PostgreSQL. On a read it checks Valkey for both metadata and content before falling back to PostgreSQL and MinIO.
Hash service (Go, gRPC) maintains a pool of pre-generated short slugs. It refills the pool proactively so the API service can acquire a slug instantly without computing one on the hot path.
PostgreSQL stores paste metadata. MinIO stores paste content as objects. Two Valkey instances cache metadata and content separately — different eviction profiles, different memory ceilings.
Pastes are anonymous and optionally ephemeral. Planning an expiry worker that runs as a background process, sweeping expired rows from PostgreSQL, deleting the corresponding objects from MinIO, and invalidating both caches.
| Requirement | Version |
|---|---|
| Docker | 24+ |
| Docker Compose | v2.20+ (the docker compose plugin, not docker-compose) |
That's it. All services, databases, and runtimes run inside containers.
Clone the repository and set the required environment variables. All secrets are injected via Docker secrets backed by environment variables — nothing is hardcoded.
# Required
export DB_USER=pastor
export DB_PASSWORD=changeme
export MINIO_ROOT_USER=minioadmin
export MINIO_ROOT_PASSWORD=changeme
# Keys must be the same as MINIO_ROOT_USER and MINIO_ROOT_PASSWORD,
# if you don't want to create a service account
export S3_ACCESS_KEY=minioadmin
export S3_SECRET_KEY=changemeThen bring the stack up:
docker compose -f deployments/docker-compose.yml up --buildThe API is available at http://localhost:3010. The MinIO web console (useful for inspecting stored objects during development) is at http://localhost:9001.
POST /v1/paste
Content-Type: application/json
{
"title": "optional title",
"content": "your text here"
}
GET /v1/paste/{slug}
MIT