base on Keep passwords and other sensitive information out of your inboxes and chat logs. # Onetime Secret - Secure One-Time Message Sharing _Keep passwords and other sensitive information out of your inboxes and chat logs._ A onetime secret is a link that can be viewed only once. A single-use URL. **Try it out**: [OnetimeSecret.com](https://onetimesecret.com/) > [!NOTE] > **Branch Information**: You're viewing the `main` branch (stable production release). For the latest features and active development, check out the [`develop` branch](https://github.com/onetimesecret/onetimesecret/tree/develop). Note that `develop` may contain work-in-progress features as we prepare for the next major release. ## Why use Onetime Secret? When you send sensitive info like passwords via email or chat, copies persist in many places. Onetime links self-destruct after viewing, ensuring only the intended recipient sees the information. ## Quick Start with Docker **1. Start Redis:** ```bash docker run -p 6379:6379 -d redis:bookworm ``` **2. Generate and store a persistent secret key:** ```bash # First, generate a persistent secret key and store it openssl rand -hex 32 > .ots_secret chmod 600 .ots_secret echo "Secret key saved to .ots_secret (keep this file secure!)" # Now run the container using the key docker run -p 3000:3000 -d \ -e REDIS_URL=redis://host.docker.internal:6379/0 \ -e SECRET="$(cat .ots_secret)" \ -e HOST=localhost:3000 \ -e SSL=false \ # ⚠️ WARNING: Set SSL=true for production deployments onetimesecret/onetimesecret:latest ``` **3. Access:** http://localhost:3000 ## Configuration ### UI Controls **Disable Web Interface** (`UI_ENABLED=false`): - Shows minimal explanation page instead of full interface - Useful for maintenance or API-only deployments **Require Authentication** (`AUTH_REQUIRED=true`): - Homepage secret creation requires login - Maintains site navigation while restricting access ### Essential Settings Create `./etc/config.yaml` from the example: ```bash cp ./etc/defaults/config.defaults.yaml ./etc/config.yaml ``` Key configuration areas: - **Email**: SMTP or SendGrid setup - **Authentication**: Enable/disable login requirements - **Rate limits**: Control usage patterns - **UI settings**: Customize user experience ### Environment Variables Common overrides: ```bash HOST=your-domain.com SSL=true SECRET=your-secure-random-key REDIS_URL=redis://host:6379/0 AUTH_REQUIRED=true PASSPHRASE_REQUIRED=true PASSWORD_GEN_LENGTH=8 TTL_OPTIONS='1800 43200 86400 259200' # 30m, 12h, 24h, 3d ``` > **Important**: Generate a secure SECRET key and back it up safely: > > ```bash > openssl rand -hex 32 > ``` ## Installation Options ### Docker Images **Pre-built images:** ```bash # GitHub Container Registry docker pull ghcr.io/onetimesecret/onetimesecret:latest # Docker Hub docker pull onetimesecret/onetimesecret:latest # Lite version (smaller, optimized) docker pull ghcr.io/onetimesecret/onetimesecret-lite:latest ``` **Build locally:** ```bash git clone https://github.com/onetimesecret/onetimesecret.git cd onetimesecret docker build -t onetimesecret . ``` ### Manual Installation **System Requirements:** - Ruby 3.1+ - Redis 5+ - Node.js 22+ (for development) - 1GB RAM, 2 CPU cores minimum **Quick setup:** ```bash git clone https://github.com/onetimesecret/onetimesecret.git cd onetimesecret bundle install cp ./etc/defaults/config.defaults.yaml ./etc/config.yaml # Edit config.yaml as needed RACK_ENV=production bundle exec thin -R config.ru -p 3000 start ``` > **For detailed installation instructions**, including system setup, troubleshooting, and advanced configuration, see [INSTALL.md](./INSTALL.md). ## Development ### Frontend Development Mode For active development with live reloading: 1. Enable development mode in `etc/config.yaml`: ```yaml :development: :enabled: true :frontend_host: 'http://localhost:5173' ``` 2. Start servers: ```bash # Terminal 1: Main server RACK_ENV=development bundle exec thin -R config.ru -p 3000 start # Terminal 2: Vite dev server pnpm run dev ``` ### Docker Compose For complete setup with dependencies: [Docker Compose repo](https://github.com/onetimesecret/docker-compose/) ### Git JSON Merge Driver (Recommended) This repository uses a custom merge driver for locale JSON files to automatically resolve conflicts: 1. Install dependencies: `pnpm install` 2. Configure Git (one-time setup): ```bash git config merge.json.driver "npx git-json-merge %A %O %B" git config merge.json.name "Custom 3-way merge driver for JSON files" ``` The driver automatically resolves conflicts when multiple branches modify different keys in the same locale file. If a conflict cannot be resolved automatically (e.g., same key modified on both sides), Git falls back to standard conflict markers. ## Support - **Issues**: [GitHub Issues](https://github.com/onetimesecret/onetimesecret/issues) - **Documentation**: Check `docs/` directory for detailed guides - **Security**: Review `SECURITY.md` for security considerations ### Production Deployments See [Dockerfile](./Dockerfile) ## AI Development Assistance This version of Familia was developed with assistance from AI tools. The following tools provided significant help with architecture design, code generation, and documentation: - **Claude (Desktop, Code Max plan, Sonnet 4, Opus 4.1)** - Interactive development sessions, debugging, architecture design, code generation, and documentation - **Google Gemini** - Refactoring suggestions, code generation, and documentation. - **GitHub Copilot** - Code completion and refactoring assistance - **Qodo Merge Pro** - Code review and QA improvements I remain responsible for all design decisions and the final code. I believe in being transparent about development tools, especially as AI becomes more integrated into our workflows as developers. ## Similar Services This section provides an overview of services similar to our project, highlighting their unique features and how they compare. These alternatives may be useful for users looking for specific functionalities or wanting to explore different options in the same domain. By presenting this information, we aim to give our users a comprehensive view of the available options in the secure information sharing space. **Note:** Our in-house legal counsel ([codium-pr-agent-pro bot](https://github.com/onetimesecret/onetimesecret/pull/610#issuecomment-2333317937)) suggested adding this introduction and the disclaimer at the end. | URL | Service | Description | Distinctive Feature | | ---------------------------------- | ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ | | <https://protonurl.ch/> | protonURL | A simple and secure tool to share secret, confidential, or non-confidential content via a self-destructing link. | Temporary, self-destructing links for sensitive content with strong encryption and available in 15 languages | | <https://pwpush.com/> | Password Pusher | A tool that uses browser cookies to help you share passwords and other sensitive information. | Temporary, self-destructing links for password sharing | | <https://scrt.link/en> | Share a Secret | A service that allows you to share sensitive information anonymously. Crucial for journalists, lawyers, politicians, whistleblowers, and oppressed individuals. | Anonymous, self-destructing message sharing | | <https://cryptgeon.com/> | Cryptgeon | A service for sharing secrets and passwords securely. | Offers a secret generator, password generator, and secret vault | | <https://www.vanish.so/> | Vanish | A service for sharing secrets and passwords securely. | Self-destructing messages with strong encryption | | <https://password.link/en> | Password.link | A service for securely sending and receiving sensitive information. | Secure link creation for sensitive information sharing | | <https://www.sharesecret.co/> | ShareSecret | A service for securely sharing passwords in Slack and email. | Secure password sharing with Slack and email integration | | <https://teampassword.com/> | TeamPassword | A password manager for teams. | Fast, easy-to-use, and secure team password management | | <https://secretshare.io/> | Secret Share | A service for sharing passwords securely. | Strong encryption for data in transit and at rest | | <https://retriever.corgea.io/> | Retriever | A service for requesting secrets securely. | Secure secret request and retrieval with encryption | | <https://winden.app/s> | Winden | A service for sharing secrets and passwords securely. | Securely transfers files with end-to-end encryption | | <https://www.snote.app/> | SNote | A privacy-focused workspace with end-to-end encryption. | Secure collaboration on projects, to-dos, tasks, and shared files | | <https://www.burnafterreading.me/> | Burn After Reading | A service for sharing various types of sensitive information. | Self-destructing messages with diceware passphrase encryption | | <https://pvtnote.com/en/> | PvtNote | A service for sending private, self-destructing messages. | Clean design with self-destructing messages | | <https://k9crypt.xyz/> | K9Crypt | A secure and anonymous messaging platform. | End-to-end encryption with 2-hour message deletion | _Summarized, fetched, and collated by [Cohere Command R+](https://cohere.com/blog/command-r-plus-microsoft-azure), formatted by [Claude 3.5 Sonnet](https://www.anthropic.com/news/claude-3-5-sonnet), and proofread by [GitHub Copilot](https://github.com/features/copilot)._ The inclusion of these services in this list does not imply endorsement. Users are encouraged to conduct their own research and due diligence before using any of the listed services, especially when handling sensitive information. ", Assign "at most 3 tags" to the expected json: {"id":"10865","tags":[]} "only from the tags list I provide: [{"id":77,"name":"3d"},{"id":89,"name":"agent"},{"id":17,"name":"ai"},{"id":54,"name":"algorithm"},{"id":24,"name":"api"},{"id":44,"name":"authentication"},{"id":3,"name":"aws"},{"id":27,"name":"backend"},{"id":60,"name":"benchmark"},{"id":72,"name":"best-practices"},{"id":39,"name":"bitcoin"},{"id":37,"name":"blockchain"},{"id":1,"name":"blog"},{"id":45,"name":"bundler"},{"id":58,"name":"cache"},{"id":21,"name":"chat"},{"id":49,"name":"cicd"},{"id":4,"name":"cli"},{"id":64,"name":"cloud-native"},{"id":48,"name":"cms"},{"id":61,"name":"compiler"},{"id":68,"name":"containerization"},{"id":92,"name":"crm"},{"id":34,"name":"data"},{"id":47,"name":"database"},{"id":8,"name":"declarative-gui "},{"id":9,"name":"deploy-tool"},{"id":53,"name":"desktop-app"},{"id":6,"name":"dev-exp-lib"},{"id":59,"name":"dev-tool"},{"id":13,"name":"ecommerce"},{"id":26,"name":"editor"},{"id":66,"name":"emulator"},{"id":62,"name":"filesystem"},{"id":80,"name":"finance"},{"id":15,"name":"firmware"},{"id":73,"name":"for-fun"},{"id":2,"name":"framework"},{"id":11,"name":"frontend"},{"id":22,"name":"game"},{"id":81,"name":"game-engine "},{"id":23,"name":"graphql"},{"id":84,"name":"gui"},{"id":91,"name":"http"},{"id":5,"name":"http-client"},{"id":51,"name":"iac"},{"id":30,"name":"ide"},{"id":78,"name":"iot"},{"id":40,"name":"json"},{"id":83,"name":"julian"},{"id":38,"name":"k8s"},{"id":31,"name":"language"},{"id":10,"name":"learning-resource"},{"id":33,"name":"lib"},{"id":41,"name":"linter"},{"id":28,"name":"lms"},{"id":16,"name":"logging"},{"id":76,"name":"low-code"},{"id":90,"name":"message-queue"},{"id":42,"name":"mobile-app"},{"id":18,"name":"monitoring"},{"id":36,"name":"networking"},{"id":7,"name":"node-version"},{"id":55,"name":"nosql"},{"id":57,"name":"observability"},{"id":46,"name":"orm"},{"id":52,"name":"os"},{"id":14,"name":"parser"},{"id":74,"name":"react"},{"id":82,"name":"real-time"},{"id":56,"name":"robot"},{"id":65,"name":"runtime"},{"id":32,"name":"sdk"},{"id":71,"name":"search"},{"id":63,"name":"secrets"},{"id":25,"name":"security"},{"id":85,"name":"server"},{"id":86,"name":"serverless"},{"id":70,"name":"storage"},{"id":75,"name":"system-design"},{"id":79,"name":"terminal"},{"id":29,"name":"testing"},{"id":12,"name":"ui"},{"id":50,"name":"ux"},{"id":88,"name":"video"},{"id":20,"name":"web-app"},{"id":35,"name":"web-server"},{"id":43,"name":"webassembly"},{"id":69,"name":"workflow"},{"id":87,"name":"yaml"}]" returns me the "expected json"