Zero-knowledge one-time secret sharing with end-to-end encryption
Share passwords, API keys, sensitive text, and encrypted files 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 | Links burn after reading by default; text secrets can optionally allow a few views. Either way the data is permanently deleted once the last view is used. |
| 📁 | Encrypted file sharing | Send files with one-time download links by default, or choose a small fixed download limit. File contents and metadata stay inside the encrypted payload. |
| 🏠 | 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 Astro frontend. Minimal resource usage. |
Share the text you just selected as an encrypted one-time link, straight from the right-click menu (or Alt+Shift+S) — Add to Chrome. Encryption happens in the browser, and the extension works against 1time.io or your own self-hosted instance (set the host in the extension options). Source lives in extension/.
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 — and since the server stores only a hash of the read token, database access cannot consume or destroy them either.
The same zero-knowledge model also powers encrypted file sharing: the browser encrypts the file and its metadata before upload, and the server stores only encrypted bytes until the one default download—or the last explicitly allowed download—is reserved.
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 read token (hash-based proof-of-knowledge). The sender uploads only SHA-256 of the read token, never the token itself, so the stored record cannot be used to read or destroy a secret. The recipient presents the token, the server hashes it and compares constant-time before releasing the encrypted blob, then permanently deletes it.
1time.io — free, no signup, ready to use.
Use the web app to share both text secrets and encrypted files with one-time links. File links allow one download by default and can optionally permit up to 10.
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/#...'
# Send an encrypted file
1time send-file ./backup-codes.txt
# Read an encrypted file
1time read-file 'https://1time.io/f/#...'Pipe-friendly, no browser needed. Works with self-hosted instances via --host. See CLI docs for more.
Want 1time links in your app, bot or script? The developers page has the complete protocol spec, HTTP API, limits and test vectors, written so you can paste it straight into your coding agent. The same spec is available as plain text.
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, encrypted file storage under DATA_DIR/files, 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 and encrypted file storage |
BACKEND_UPSTREAM |
backend:8080 |
Backend upstream (host:port) nginx proxies /api/ requests to |
SHOW_BLOG |
true |
Build-time flag for source-built web images |
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 |
- Secure File Sharing — send encrypted files with one-time links and controlled download limits
- 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
- Share Passwords with QR Code — hand off secrets across devices and in person
| Layer | Technology |
|---|---|
| Backend | Go (stdlib, no frameworks) |
| Storage | Redis plus encrypted file blobs on disk |
| Frontend | Astro static build |
| 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
mkdir -p /tmp/1time-files
export FILE_STORAGE_DIR=/tmp/1time-files
export REDISHOST=127.0.0.1:6379
export REDISPASS=
# Run the backend
go run ./backend
# Listening on http://127.0.0.1:8080
# Tests
GOCACHE=/tmp/go-cache go test ./backend/...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
# Type/content check
npm run checkcd 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
# First time on a fresh host. Note `sudo env` — a plain `sudo VAR=... ./script`
# is refused by the default sudoers, and the install would silently end up with
# empty values.
sudo env REDIS_PASS=... ./scripts/update_vm.sh --init
# Every deploy after that. Configuration is never touched.
sudo ./scripts/update_vm.sh--init installs nginx and Redis, creates the service user, and writes
/etc/1time/env. It will not overwrite that file on a later run, so if the
first attempt captured the wrong values, edit /etc/1time/env directly and
sudo systemctl restart 1time.
Later deploys install the binary, the static site, the nginx config and the unit,
then restart. They never read or write /etc/1time/env, so a deploy cannot clear
a secret by forgetting to pass it.
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



