Installation
Run your own instance of Pass It Around using containers (recommended) or build from source.
Container (Docker / Podman)
The recommended way to run Pass It Around is with a container. The image includes everything needed: the Go server binary and Apprise for notifications.
Quick Start
# Build the image
podman build -t pass-it-around .
# Run it
podman run -d \
--name pass-it-around \
-p 8080:8080 \
-v pass-it-around-data:/data/secrets \
pass-it-around
The app is now running at http://localhost:8080.
Docker Compose / Podman Compose
services:
pass-it-around:
build: .
ports:
- "8080:8080"
volumes:
- secrets-data:/data/secrets
environment:
- MAX_UPLOAD_MB=256
- MAX_LIFETIME_HOURS=168
# Add any other configuration here
restart: unless-stopped
volumes:
secrets-data:
With TLS
Pass It Around has built-in TLS support. Mount your certificate and key files and set the environment variables:
podman run -d \
--name pass-it-around \
-p 443:8080 \
-v pass-it-around-data:/data/secrets \
-v /path/to/certs:/certs:ro \
-e TLS_CERT=/certs/fullchain.pem \
-e TLS_KEY=/certs/privkey.pem \
pass-it-around
TLS_CERT and TLS_KEY unset.
From Source
Requirements: Go 1.24 or later, and optionally Python 3 with apprise installed for notification support.
# Clone and build
git clone https://your-repo-url/pass-it-around.git
cd pass-it-around
go build -o pass-it-around .
# Run
./pass-it-around
The binary embeds all web assets, so no additional files are needed. Just copy the binary to your server and run it.
Apprise for Notifications
The receive mode notification feature requires the apprise command to be available on the system:
pip3 install apprise
If apprise is not installed, the app still works normally, but notification URLs in receive mode will be silently ignored.
Configuration
All configuration is done through environment variables. Every setting has a sensible default, so you only need to set the ones you want to change.
Server Settings
| Variable | Default | Description |
|---|---|---|
LISTEN_ADDR |
:8080 |
Address and port to listen on |
DATA_DIR |
/data/secrets |
Directory where encrypted secrets are stored on disk |
TLS_CERT |
(none) | Path to TLS certificate file. TLS is enabled only if both TLS_CERT and TLS_KEY are set. |
TLS_KEY |
(none) | Path to TLS private key file |
Limits
| Variable | Default | Description |
|---|---|---|
MAX_UPLOAD_MB |
512 |
Maximum upload size in megabytes. The UI will prevent uploads that exceed this limit. |
MAX_VIEWS |
20 |
Maximum number of views a single secret can have. Users can set 0 for unlimited views. |
MAX_LIFETIME_HOURS |
720 |
Maximum lifetime in hours (720 = 30 days). Set to 0 to allow unlimited lifetime. The UI lifetime dropdown automatically adjusts to this. |
MAX_LINKS |
20 |
Maximum number of one-time links per multi-link secret |
Tiered Lifetime Caps
Large uploads are automatically given shorter maximum lifetimes to conserve disk space. These thresholds are configurable:
| Variable | Default | Description |
|---|---|---|
LARGE_UPLOAD_MB |
256 |
Size threshold (MB) for "large" upload cap |
LARGE_UPLOAD_MAX_DAYS |
3 |
Maximum lifetime in days for uploads above the large threshold |
MEDIUM_UPLOAD_MB |
64 |
Size threshold (MB) for "medium" upload cap |
MEDIUM_UPLOAD_MAX_DAYS |
7 |
Maximum lifetime in days for uploads above the medium threshold |
Rate Limiting
| Variable | Default | Description |
|---|---|---|
PW_RATE_THRESHOLD |
5 |
Failed password attempts before throttling kicks in |
CREATE_RATE_THRESHOLD |
30 |
Secret creation requests before throttling |
CLEANUP_INTERVAL |
10m |
How often the server checks for and deletes expired secrets |
Timeouts
| Variable | Default | Description |
|---|---|---|
READ_HEADER_TIMEOUT |
10s |
Max time to read request headers |
READ_TIMEOUT |
10m |
Max time to read request body (needs to be high for large uploads) |
WRITE_TIMEOUT |
10m |
Max time to write response (needs to be high for large downloads) |
IDLE_TIMEOUT |
60s |
Max idle time for keep-alive connections |
SHUTDOWN_TIMEOUT |
10s |
How long to wait for active connections on graceful shutdown |
OAuth2 / OpenID Connect
Pass It Around supports optional OAuth2 authentication via any OpenID Connect provider. Authentication is disabled by default and enabled by setting OAUTH2_ISSUER.
| Variable | Default | Description |
|---|---|---|
OAUTH2_ISSUER |
(none) | OpenID Connect issuer URL (e.g. https://auth.example.com). Setting this enables authentication. |
OAUTH2_CLIENT_ID |
(none) | OAuth2 client ID from your provider |
OAUTH2_CLIENT_SECRET |
(none) | OAuth2 client secret from your provider |
OAUTH2_REDIRECT_URL |
(none) | Callback URL, must be https://your-domain/auth/callback |
OAUTH2_SCOPES |
openid |
Space-separated OAuth2 scopes. Only openid is needed; no personal data is collected. |
OAUTH2_CREATE_REQUIRES_AUTH |
false |
When true, only signed-in users can create secrets |
OAUTH2_SESSION_KEY |
(auto-generated) | HMAC key for signing session cookies. If not set, a random key is generated on startup (sessions will not survive restarts). |
Example: OAuth2 with Docker Compose
services:
pass-it-around:
build: .
ports:
- "8080:8080"
volumes:
- secrets-data:/data/secrets
environment:
- OAUTH2_ISSUER=https://auth.example.com
- OAUTH2_CLIENT_ID=pass-it-around
- OAUTH2_CLIENT_SECRET=your-client-secret
- OAUTH2_REDIRECT_URL=https://secrets.example.com/auth/callback
- OAUTH2_SESSION_KEY=a-stable-random-string
- OAUTH2_CREATE_REQUIRES_AUTH=true
restart: unless-stopped
volumes:
secrets-data:
OAUTH2_SESSION_KEY in production. Without it, a random key is generated each time the server starts, which invalidates all existing sessions. Use any long random string.
For details on how authentication works for users, see Authentication.
Data Storage
Secrets are stored as encrypted files on disk in the DATA_DIR directory. Each secret consists of a .meta file (metadata like expiry, view count) and a .data file (the encrypted content).
The server runs a cleanup loop every CLEANUP_INTERVAL that deletes expired secrets and orphaned data files.