Zero-knowledge one-time secret sharing with end-to-end encryption
Share passwords, API keys, and sensitive text through self-destructing links.
| Feature | Details | |
|---|---|---|
| 🔐 | Zero-knowledge encryption | Secrets are encrypted in your browser with AES-GCM. The server never sees plaintext. |
| 🔥 | Self-destructing links | Each link works exactly once, then the data is permanently deleted. |
| 🏠 | Self-hosted | Run your own instance with Docker Compose in under 2 minutes. |
| 👤 | No signup required | Paste a secret, get a link, share it. No accounts, no tracking. |
| 🔑 | Built-in generators | Password, passphrase, API key, and WiFi password generators included. |
| 💻 | First-party CLI | npm i -g @1time/cli — pipe secrets from your terminal, perfect for DevOps workflows. |
| ⚡ | Lightweight stack | Go + Redis backend, static Next.js frontend. Minimal resource usage. |
You Server Recipient
│ │ │
│ 1. Type secret │ │
│ 2. Browser encrypts │ │
│ with AES-GCM │ │
│ 3. Send encrypted blob ──► │ Stores encrypted blob │
│ 4. Get link with key │ (cannot decrypt it) │
│ in URL fragment (#) │ │
│ │ │
│ 5. Share link ─────────────┼──────────────────────────► │
│ │ │
│ │ ◄── 6. Fetch encrypted blob │
│ │ 7. Delete blob permanently │
│ │ 8. Send blob ──────────► │
│ │ │
│ │ 9. Browser decrypts │
│ │ with key from # │
The encryption key stays in the URL fragment (#), which is never sent to the server. Even with full database access, secrets cannot be read.
Cryptographic details: Keys are derived using HKDF-SHA256 with a fixed salt. Two separate keys are produced — one for AES-256-GCM encryption and one for authentication (hash-based proof-of-knowledge). The server verifies the auth hash with constant-time comparison before releasing the encrypted blob, then permanently deletes it.
1time.io — free, no signup, ready to use.
npm install -g @1time/cli
# Send a secret
printf 'postgres://user:pass@host/db' | 1time send
# → https://1time.io/v/#...
# Read a secret
1time read 'https://1time.io/v/#...'Pipe-friendly, no browser needed. Works with self-hosted instances via --host. See CLI docs for more.
Option 1: Pre-built images (recommended)
curl -O https://raw.githubusercontent.com/shingrus/1time/master/docker-compose.yml
curl -O https://raw.githubusercontent.com/shingrus/1time/master/.env.example
cp .env.example .env
# Edit .env: set APP_HOSTNAME to your domain
docker compose up -dOption 2: Build from source
git clone https://github.com/shingrus/1time.git
cd 1time
cp .env.example .env
# Edit .env: set APP_HOSTNAME to your domain
docker compose -f docker-compose.dev.yml up -d --buildBoth options start on http://localhost:8080 with Redis persistence, the Go API, and nginx serving the frontend. Multi-arch images (amd64 + arm64) are available.
| Variable | Default | Description |
|---|---|---|
APP_HOSTNAME |
1time.io |
Public hostname for links and metadata |
APP_PORT |
8080 |
External HTTP port |
DATA_DIR |
./data |
Host path for Redis persistence |
SHOW_BLOG |
false |
Enable blog routes (for hosted version) |
Put your own reverse proxy (Caddy, Traefik, nginx) in front for HTTPS/TLS termination.
Note: The frontend image is generic — changing
APP_HOSTNAMEdoes not require rebuilding. The hostname is injected at container startup.
| Feature | 1time | OneTimeSecret | Yopass | PrivateBin | Password Pusher |
|---|---|---|---|---|---|
| Zero-knowledge (E2E encrypted) | Yes | No | Yes | Yes | No |
| Self-destructing after first read | Yes | Yes | Yes | Optional | Optional |
| No signup required | Yes | Yes | Yes | Yes | Yes |
| Self-hosted Docker Compose | Yes | Yes | Yes | Yes | Yes |
| First-party CLI | Yes | No | Yes | No | Yes |
| Built-in password generators | Yes | No | No | No | No |
| Lightweight (Go + static HTML) | Yes | No (Ruby) | Yes (Go) | No (PHP) | No (Ruby) |
| Open source | MIT | MIT | Apache-2.0 | zlib | Apache-2.0 |
- Password Generator — strong random passwords
- Passphrase Generator — memorable multi-word passphrases
- API Key Generator — random tokens for developers
- WiFi Password Generator — easy-to-type network passwords
| Layer | Technology |
|---|---|
| Backend | Go (stdlib, no frameworks) |
| Storage | Redis with RDB persistence |
| Frontend | Next.js (static export) |
| CLI | Node.js (@1time/cli) |
| Encryption | Web Crypto API (AES-256-GCM, HKDF-SHA256) |
| Deployment | Docker Compose + nginx |
- Go 1.22+
- Redis 7+
- Node.js 20+ and npm
# Start Redis locally
export REDISHOST=127.0.0.1:6379
export REDISPASS=
# Run the backend
go run .
# Listening on http://127.0.0.1:8080
# Tests
GOCACHE=/tmp/go-cache go test ./...cd frontend
npm install
npm run dev
# Dev server on http://127.0.0.1:3001, proxies /api to Go backend
# Production build
npm run build
# Tests
npm testcd cli
npm install
npm test
# Run locally against dev backend
printf 'hello' | node index.mjs send --host http://127.0.0.1:8080make build
# Produces: bin/1time-api (backend) + frontend/build/ (static assets)make build
sudo ./scripts/init_vm.shInstalls nginx, Redis, creates the 1time systemd service, and deploys the built artifacts.
Contributions are welcome! Please open an issue first to discuss what you'd like to change.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes
- Push to the branch
- Open a Pull Request
The encryption model is designed so that the server operator cannot read secrets, even with full database and infrastructure access. If you find a security vulnerability, please email the maintainer directly instead of opening a public issue.
MIT — Copyright (c) 2018-2026 1time.io

