Self-Hosting OneTimeSecret with Docker Compose

What Is OneTimeSecret?

OneTimeSecret lets you share sensitive information through self-destructing links. Paste a password, API key, or private message — get a link that can only be viewed once, then it’s permanently deleted. No accounts needed for sharing. It replaces onetimesecret.com and similar services, keeping your secrets on your own infrastructure. Official site.

Updated March 2026: Verified with latest Docker images and configurations.

Prerequisites

  • A Linux server (Ubuntu 22.04+ recommended)
  • Docker and Docker Compose installed (guide)
  • 512 MB of free RAM
  • 1 GB of free disk space
  • A domain name (recommended for HTTPS)

Docker Compose Configuration

Create a docker-compose.yml file:

services:
  onetimesecret:
    image: onetimesecret/onetimesecret:v0.24.1
    container_name: onetimesecret
    restart: unless-stopped
    ports:
      - "3000:3000"
    environment:
      # Required: encryption key — generate with: openssl rand -hex 32
      SECRET: "change_me_run_openssl_rand_hex_32"
      # Required: your domain (used in generated links)
      HOST: "secrets.example.com"
      # Required: Redis connection
      REDIS_URL: "redis://ots-redis:6379/0"
      # Enable HTTPS links (set true behind reverse proxy)
      SSL: "true"
    depends_on:
      ots-redis:
        condition: service_healthy

  ots-redis:
    image: redis:7.4-alpine
    container_name: ots-redis
    restart: unless-stopped
    volumes:
      - ots-redis-data:/data
    command: redis-server --appendonly yes
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 5s
      retries: 5

volumes:
  ots-redis-data:

Generate the SECRET value before starting:

# Generate a secure encryption key
openssl rand -hex 32
# Output example: a1b2c3d4e5f6... (64 characters)
# Paste this value into the SECRET environment variable

Start the stack:

docker compose up -d

Initial Setup

  1. Open http://your-server-ip:3000 in your browser
  2. You’ll see the OneTimeSecret interface — paste any text and click “Create a secret link”
  3. Share the generated link — the recipient can view it exactly once, then it’s permanently deleted
  4. No account needed for basic sharing

Create an Admin Account

To manage secrets and view metadata, create an account through the web interface:

  1. Click “Sign Up” in the navigation
  2. Enter an email and password
  3. Logged-in users can set custom TTL values and view their secret history

Configuration

Environment Variables

VariableRequiredDescription
SECRETYesEncryption key (run openssl rand -hex 32)
HOSTYesYour domain name for generated links
REDIS_URLYesRedis connection string
SSLRecommendedSet true for HTTPS links
AUTH_REQUIREDNoRequire login to create secrets (default: false)
UI_ENABLEDNoDisable web UI for API-only (default: true)
TTL_OPTIONSNoAvailable TTL options in seconds (default: 1800 43200 86400 259200)

TTL Options

Default expiry options are 30 minutes, 12 hours, 24 hours, and 3 days. Customize with space-separated seconds:

environment:
  TTL_OPTIONS: "300 3600 86400 604800"  # 5min, 1hr, 1day, 7days

API Usage

Create secrets programmatically:

# Create a secret via API
curl -X POST "https://secrets.example.com/api/v1/share" \
  -u "your-email:your-api-key" \
  -d "secret=my-super-secret-password&ttl=3600"

# Response includes the secret_key for building the link
# Link format: https://secrets.example.com/secret/SECRET_KEY

Restricting Access

For internal use only, require authentication:

environment:
  AUTH_REQUIRED: "true"  # Only logged-in users can create secrets

Reverse Proxy

HTTPS is strongly recommended for a secret-sharing service. Set SSL: "true" in the environment and place behind a reverse proxy. See Reverse Proxy Setup.

Example Caddy config:

secrets.example.com {
    reverse_proxy onetimesecret:3000
}

Backup

Redis data is the only persistent state. Back up the Redis volume:

# Trigger a Redis save
docker exec ots-redis redis-cli BGSAVE

# Copy the dump file
docker cp ots-redis:/data/dump.rdb ./ots-backup-$(date +%Y%m%d).rdb

See Backup Strategy for automated backup approaches.

Troubleshooting

”Connection Refused” to Redis

Symptom: OneTimeSecret fails to start with Redis connection error. Fix: Ensure the Redis container is running and healthy: docker compose ps. Check that REDIS_URL uses the correct service name (ots-redis, not localhost). Verify both containers are on the same Docker network.

Symptom: Secret links use localhost or the wrong domain. Fix: Set the HOST environment variable to your actual domain. Set SSL: "true" if behind HTTPS. Restart the container after changing.

Secrets Not Expiring

Symptom: Secrets remain accessible after TTL should have expired. Fix: Redis handles TTL expiry. Check Redis is persisting correctly with docker exec ots-redis redis-cli INFO keyspace. Verify TTL_OPTIONS values are in seconds.

Resource Requirements

  • RAM: ~80 MB idle (app + Redis), ~150 MB under load
  • CPU: Very low
  • Disk: Minimal — secrets auto-delete after viewing or TTL expiry

Verdict

OneTimeSecret is the simplest way to share passwords and secrets securely. The workflow is intuitive — paste, share link, done. For a secret-sharing tool, that simplicity is the entire value proposition. If you need encrypted pastebins for code or text, PrivateBin is more flexible. If you need one-time links with zero UI and maximum simplicity, Yopass is even more minimal. OneTimeSecret hits the sweet spot: clean UI, API support, and self-destructing secrets with custom TTL.

Comments