A simple, secure, self-destructing message service that uses HashiCorp Vault as a backend for temporary secret storage. Share sensitive information with confidence knowing it will be automatically deleted after being read once.

🔐 Security First: Messages are stored in Vault's cubbyhole backend with one-time tokens and automatic expiration.
Read more about the reasoning behind this project in the relevant blog post.
The web interface is built with modern vanilla JavaScript and has minimal external dependencies:
| Dependency | Size | Purpose |
|---|---|---|
| ClipboardJS v2.0.11 | 8.9KB | Copy to clipboard functionality |
| Montserrat Font | 46KB | Self-hosted typography |
| Custom CSS | 2.3KB | Application styling |
✅ No external CDNs or tracking - All dependencies are self-hosted for privacy and security.
📦 Total JavaScript bundle size: 8.9KB (previously 98KB with jQuery)
Get up and running in less than 2 minutes:
# Clone the repository
git clone https://github.com/algolia/sup3rS3cretMes5age.git
cd sup3rS3cretMes5age
# Start with Docker Compose (recommended)
make run
# Access the application
open http://localhost:8082
The service will start with:
- Application: http://localhost:8082
- Vault dev server: In-memory storage with token supersecret
# Start Vault dev server
docker run -d --name vault-dev -p 8200:8200 \
-e VAULT_DEV_ROOT_TOKEN_ID=supersecret \
hashicorp/vault:latest
# Build and run the application
go build -o sup3rs3cret cmd/sup3rS3cretMes5age/main.go
VAULT_ADDR=http://localhost:8200 \
VAULT_TOKEN=supersecret \
SUPERSECRETMESSAGE_HTTP_BINDING_ADDRESS=":8080" \
./sup3rs3cret
make run # Start services (Vault + App)
make logs # View logs
make stop # Stop services
make clean # Remove containers
docker compose -f deploy/docker-compose.yml up --build -d
By default, the application runs on port 8082 in HTTP mode: http://localhost:8082
💡 You can modify deploy/docker-compose.yml to enable HTTPS, HTTP redirection, or change ports. See Configuration options.
The image is available at:
- Docker Hub: algolia/supersecretmessage:latest
- Platforms: linux/amd64, linux/arm64
Build multi-platform images with SBOM and provenance attestations:
# Build for multiple architectures
make image
# Builds: linux/amd64, linux/arm64 with SBOM and provenance
For detailed step-by-step instructions on deploying to AWS, see our comprehensive AWS Deployment Guide. The guide covers:
# Build for multiple architectures
make image
# Builds: linux/amd64, linux/arm64 with SBOM and provenance
Deploy using your preferred orchestration tool:
| Platform | Documentation |
|---|---|
| Kubernetes | See Helm Chart below |
| Docker Swarm | Use the provided docker-compose.yml |
| AWS ECS | Use the Docker image with ECS task definition |
Important: Deploy alongside a production Vault server. Configure via environment variables:
- VAULT_ADDR: Your Vault server URL
- VAULT_TOKEN: Vault authentication token
See configuration examples below.
⚠️ Critical: Always run this service behind SSL/TLS in production. Secrets sent over HTTP are vulnerable to interception!
Option 1: Inside the Container (Recommended for simplicity) - Configure via environment variables - Automatic Let's Encrypt certificates - See Configuration examples - TLS
Option 2: External Load Balancer/Reverse Proxy - Simpler certificate management - Offload TLS processing - Ensure secure network between proxy and container - Examples: AWS ALB, Nginx, Traefik, Cloudflare
Deploy to Kubernetes using the included Helm chart:
helm install supersecret ./deploy/charts/supersecretmessage \
--set config.vault.address=http://vault.default.svc.cluster.local:8200 \
--set config.vault.token_secret.name=vault-token
Chart Details: - Chart Version: 0.1.0 - App Version: 0.2.5 - Includes: Deployment, Service, Ingress, HPA, ServiceAccount
For full documentation, see the Helm Chart README
Endpoint: POST /secret
Content-Type: multipart/form-data
Parameters:
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| msg | string | Yes | The secret message content |
| ttl | string | No | Time-to-live (default: 48h, max: 168h) |
| file | file | No | File to upload (max 50MB) |
Response:
{
"token": "s.abc123def456",
"filetoken": "s.xyz789uvw012", // If file uploaded
"filename": "secret.pdf" // If file uploaded
}
Example:
# Text message
curl -X POST -F 'msg=This is a secret' http://localhost:8082/secret
# With custom TTL
curl -X POST -F 'msg=Short-lived secret' -F 'ttl=1h' http://localhost:8082/secret
# With file
curl -X POST -F 'msg=Check this file' -F 'file=@secret.pdf' http://localhost:8082/secret
Endpoint: GET /secret?token=<token>
Parameters:
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| token | string | Yes | The token from POST response |
Response:
{
"msg": "This is a secret"
}
Example:
curl "http://localhost:8082/secret?token=s.abc123def456"
⚠️ Note: After retrieval, the message and token are permanently deleted. Second attempts will fail.
Endpoint: GET /health
Response: OK (HTTP 200)
For convenient command line integration and automation, see our comprehensive CLI Guide which includes shell functions for Bash, Zsh, Fish, and WSL.
Quick example:
# Add to your ~/.bashrc or ~/.zshrc
o() { cat "$@" | curl -sF 'msg=<-' https://your-domain.com/secret | jq -r .token | awk '{print "https://your-domain.com/getmsg?token="$1}'; }
# Usage
echo "secret message" | o
o secret-file.txt
VAULT_ADDR: address of the Vault server used for storing the temporary secrets.VAULT_TOKEN: Vault token used to authenticate to the Vault server.SUPERSECRETMESSAGE_HTTP_BINDING_ADDRESS: HTTP binding address (e.g. :80).SUPERSECRETMESSAGE_HTTPS_BINDING_ADDRESS: HTTPS binding address (e.g. :443).SUPERSECRETMESSAGE_HTTPS_REDIRECT_ENABLED: whether to enable HTTPS redirection or not (e.g. true).SUPERSECRETMESSAGE_TLS_AUTO_DOMAIN: domain to use for "Auto" TLS, i.e. automatic generation of certificate with Let's Encrypt. See Configuration examples - TLS - Auto TLS.SUPERSECRETMESSAGE_TLS_CERT_FILEPATH: certificate filepath to use for "manual" TLS.SUPERSECRETMESSAGE_TLS_CERT_KEY_FILEPATH: certificate key filepath to use for "manual" TLS.SUPERSECRETMESSAGE_VAULT_PREFIX: vault prefix for secrets (default cubbyhole/)Here is an example of a functionnal docker-compose.yml file
version: '3.2'
services:
vault:
image: vault:latest
container_name: vault
environment:
VAULT_DEV_ROOT_TOKEN_ID: root
cap_add:
- IPC_LOCK
expose:
- 8200
supersecret:
build: ./
image: algolia/supersecretmessage:latest
container_name: supersecret
environment:
VAULT_ADDR: http://vault:8200
VAULT_TOKEN: root
SUPERSECRETMESSAGE_HTTP_BINDING_ADDRESS: ":80"
SUPERSECRETMESSAGE_HTTPS_BINDING_ADDRESS: ":443"
SUPERSECRETMESSAGE_HTTPS_REDIRECT_ENABLED: "true"
SUPERSECRETMESSAGE_TLS_AUTO_DOMAIN: secrets.example.com
ports:
- "80:80"
- "443:443"
depends_on:
- vault
VAULT_ADDR=http://vault:8200
VAULT_TOKEN=root
SUPERSECRETMESSAGE_HTTP_BINDING_ADDRESS=:80
VAULT_ADDR=http://vault:8200
VAULT_TOKEN=root
SUPERSECRETMESSAGE_HTTPS_BINDING_ADDRESS=:443
SUPERSECRETMESSAGE_TLS_AUTO_DOMAIN=secrets.example.com
VAULT_ADDR=http://vault:8200
VAULT_TOKEN=root
SUPERSECRETMESSAGE_HTTP_BINDING_ADDRESS=:80
SUPERSECRETMESSAGE_HTTPS_BINDING_ADDRESS=:443
SUPERSECRETMESSAGE_HTTPS_REDIRECT_ENABLED=true
SUPERSECRETMESSAGE_TLS_AUTO_DOMAIN=secrets.example.com
VAULT_ADDR=http://vault:8200
VAULT_TOKEN=root
SUPERSECRETMESSAGE_HTTPS_BINDING_ADDRESS=:443
SUPERSECRETMESSAGE_TLS_CERT_FILEPATH=/mnt/ssl/cert_secrets.example.com.pem
SUPERSECRETMESSAGE_TLS_CERT_KEY_FILEPATH=/mnt/ssl/key_secrets.example.com.pem
Clean, intuitive interface for creating self-destructing messages with optional file uploads and custom TTL.
Simple, secure interface for viewing self-destructing messages that are permanently deleted upon retrieval.
# Clone the repository
git clone https://github.com/algolia/sup3rS3cretMes5age.git
cd sup3rS3cretMes5age
# Download dependencies
go mod download
# Build the binary
go build -o sup3rs3cret cmd/sup3rS3cretMes5age/main.go
# Run all tests
make test
# Or directly with go
go test ./... -v
# Format code
gofmt -s -w .
# Lint
golangci-lint run --timeout 300s
# Static analysis
go vet ./...
.
├── cmd/sup3rS3cretMes5age/ # Application entry point
│ └── main.go # (23 lines)
├── internal/ # Core business logic
│ ├── config.go # Configuration (77 lines)
│ ├── handlers.go # HTTP handlers (88 lines)
│ ├── server.go # Server setup (94 lines)
│ └── vault.go # Vault integration (174 lines)
├── web/static/ # Frontend assets
│ ├── index.html # Message creation page
│ ├── getmsg.html # Message retrieval page
│ ├── application.css # Styling
│ └── clipboard-2.0.11.min.js
├── deploy/ # Deployment configs
│ ├── Dockerfile # Multi-stage build
│ ├── docker-compose.yml # Local dev stack
│ └── charts/ # Helm chart
└── Makefile # Build automation
Total Code: 609 lines of Go across 7 files
Contributions are welcome! 🎉
git checkout -b feature/amazing-feature)$ claude mcp add sup3rS3cretMes5age \
-- python -m otcore.mcp_server <graph>