Configuration Reference
Ce contenu n'est pas encore disponible dans votre langue.
This comprehensive guide covers all configuration options for self-hosted Onetime Secret instances.
Configuration Files
Section titled “Configuration Files”Onetime Secret uses multiple configuration files:
.env
- Environment variables for common settings. Use for simple configuration and Docker deployments without modifying YAML files. (Copy from.env.example
)config/config.yaml
- Main application configuration using ERB templates. Environment variables are integrated here, making it easy to see how each setting is applied. (Copy frometc/config.example.yaml
)
Main Configuration
Section titled “Main Configuration”The main configuration file is config/config.yaml
, which uses ERB templates to integrate environment variables.
Getting started:
- Copy the example:
cp etc/config.example.yaml config/config.yaml
- Edit values as needed for your deployment
- Most common settings can be overridden with environment variables
View the complete configuration file: config.example.yaml
Key Configuration Sections
Section titled “Key Configuration Sections”Here are the most important sections you’ll likely need to customize:
---:site: :host: <%= ENV['HOST'] || 'localhost:3000' %> # Turns https/http on or off when generating links :ssl: <%= ENV['SSL'] == 'true' || false %> # IMPORTANT: After setting the secret, it should not be changed. # Be sure to create and store a backup in a secure offsite # location. Changing the secret can lead to unforeseen issues # like not being able to decrypt existing secrets. :secret: <%= ENV['SECRET'] || nil %> # API and UI Configuration :interface: :ui: # Controls whether the web interface is enabled # When false, only a basic explanation page is shown :enabled: <%= ENV['UI_ENABLED'] != 'false' %> # Header configuration # Controls branding and navigation in the site header :header: # Control switch to enable/disable header customization :enabled: <%= ENV['HEADER_ENABLED'] != 'false' %> # Branding configuration for logo and company name :branding: # Logo configuration :logo: # URL to logo image file :url: <%= ENV['LOGO_URL'] || 'DefaultLogo.vue' %> # Alt text for logo image :alt: <%= ENV['LOGO_ALT'] || 'Share a Secret One-Time' %> # Where the logo links to when clicked :href: <%= ENV['LOGO_LINK'] || '/' %> # Company name override (falls back to i18n if not set) :site_name: <%= ENV['SITE_NAME'] || 'One-Time Secret' %> # Navigation configuration :navigation: # Enable/disable header navigation entirely :enabled: <%= ENV['HEADER_NAV_ENABLED'] != 'false' %> # Footer link configuration # These links appear in the footer of each page :footer_links: # Master switch to enable/disable all footer links :enabled: <%= ENV['FOOTER_LINKS'] == 'true' || false %> # Organized groups of links :groups: - :name: legal :i18n_key: web.footer.legals :links: - :text: Terms of Service :i18n_key: terms-of-service # Replace with your own terms URL or use relative path like /terms :url: <%= ENV['TERMS_URL'] %> :external: <%= ENV['TERMS_EXTERNAL'] || false %> - :text: Privacy Policy :i18n_key: privacy-policy # Replace with your own privacy URL or use relative path like /privacy :url: <%= ENV['PRIVACY_URL'] %> :external: <%= ENV['PRIVACY_EXTERNAL'] || false %> - :name: resources :i18n_key: web.footer.resources :links: - :text: Status :i18n_key: status # Replace with your status page URL if you have one :url: <%= ENV['STATUS_URL'] %> :external: <%= ENV['STATUS_EXTERNAL'] || true %> :icon: signal - :text: About :i18n_key: web.COMMON.about # Replace with your about page URL :url: <%= ENV['ABOUT_URL'] %> :external: <%= ENV['ABOUT_EXTERNAL'] || false %> - :name: support :i18n_key: web.footer.support :links: - :text: Contact :i18n_key: web.footer.contact :url: <%= ENV['CONTACT_URL'] %> :external: false # Controls whether the API endpoints are available. When disabled, the API # is completely disabled. Requests to /api/* will return 404. :api: :enabled: <%= ENV['API_ENABLED'] != 'false' %> # Configuration options for secret management :secret_options: # Default Time-To-Live (TTL) for secrets in seconds # This value is used if no specific TTL is provided when creating a secret :default_ttl: <%= ENV['DEFAULT_TTL'] || nil %> # Available TTL options for secret creation (in seconds) # These options will be presented to users when they create a new secret # Format: String of integers representing seconds :ttl_options: <%= (ENV['TTL_OPTIONS'] || nil) %> # Settings for the passphrase field that protects access to secrets :passphrase: # Require users to enter a passphrase when creating secrets :required: <%= ENV['PASSPHRASE_REQUIRED'] == 'true' || false %> # Minimum number of characters required for passphrases :minimum_length: <%= ENV['PASSPHRASE_MIN_LENGTH'] || 8 %> # Maximum number of characters allowed for passphrases :maximum_length: <%= ENV['PASSPHRASE_MAX_LENGTH'] || 128 %> # Enforce complexity requirements (uppercase, lowercase, numbers, symbols) :enforce_complexity: <%= ENV['PASSPHRASE_ENFORCE_COMPLEXITY'] == 'true' || false %> # Settings for password generation (when users click "Generate Password") :password_generation: # Default length for generated passwords :default_length: <%= ENV['PASSWORD_GEN_LENGTH'] || 12 %> # Character sets to include in generated passwords :character_sets: # Include uppercase letters (A-Z) :uppercase: <%= ENV['PASSWORD_GEN_UPPERCASE'] != 'false' %> # Include lowercase letters (a-z) :lowercase: <%= ENV['PASSWORD_GEN_LOWERCASE'] != 'false' %> # Include numbers (0-9) :numbers: <%= ENV['PASSWORD_GEN_NUMBERS'] != 'false' %> # Include symbols (!@#$%^&*()_+-=[]{}|;:,.<>?) :symbols: <%= ENV['PASSWORD_GEN_SYMBOLS'] == 'true' || false %> # Exclude ambiguous characters (0, O, l, 1, I) to prevent confusion :exclude_ambiguous: <%= ENV['PASSWORD_GEN_EXCLUDE_AMBIGUOUS'] != 'false' %> # Registration and Authentication settings :authentication: # Can be disabled altogether, including API authentication. :enabled: <%= ENV['AUTH_ENABLED'] != 'false' %> # Allow users to create accounts. This can be disabled if you plan # to create accounts manually or enable during setup when accounts # can be created and then disabled to prevent any new users from # creating accounts. :signup: <%= ENV['AUTH_SIGNUP'] != 'false' %> # Generally if you allow registration, you allow signin. But there # are circumstances where it's helpful to turn off authentication # temporarily. :signin: <%= ENV['AUTH_SIGNIN'] != 'false' %> # By default, new accounts need to verify their email address before # they can sign in. This is a security measure to prevent spamming # and abuse of the system. If you're running a private instance or # an instance for your team or company, you can disable this feature # to make it easier for users to sign in. :autoverify: <%= ENV['AUTH_AUTOVERIFY'] == 'true' || false %> # When enabled, the homepage secret form is not available unless # the user is logged in. Similar to a disabled homepage, but still # shows the header with logo and navigation links. This allows for # a more restrictive mode where only authenticated users can create # secrets while maintaining site navigation and branding. :required: <%= ENV['AUTH_REQUIRED'] == 'true' %> # Email addresses listed below will be granted automatic # administrative privileges upon account creation. These # accounts have access to a page that show basic system stats. # The term "colonel" is used instead of "admin". "Colonel" (which # is pronounced "kernel") references both the protected core of a # Linux system and a military rank, symbolizing high-level access # permissions. This naming helps avoid basic, automated attacks # that target common admin URLs or role names. :colonels: - <%= ENV['COLONEL'] || 'CHANGEME@example.com' %> # A captcha-like feature that protects the feedback form # from bots and other tomfoolery. :authenticity: :type: <%= ENV['AUTHENTICITY_TYPE'] || 'altcha' %> :secret_key: <%= ENV['AUTHENTICITY_SECRET_KEY'] || '<REPLACE_WITH_STRONG_HMAC_KEY>' %> # Links to documentation. For onetimesecret.com, this is # docs.onetimesecret.com. :support: :host: <%= ENV['SUPPORT_HOST'] || nil %> :plans: :enabled: <%= ENV['PLANS_ENABLED'] == 'true' || false %> :stripe_key: <%= ENV['STRIPE_KEY'] || nil %> :regions: :enabled: <%= ENV['REGIONS_ENABLED'] == 'true' || false %> :current_jurisdiction: <%= ENV['JURISDICTION'] || nil %> :domains: :enabled: <%= ENV['DOMAINS_ENABLED'] == 'true' || false %> # The default domain used for link URLs. When not set or empty, # site.host is used. :default: <%= ENV['DEFAULT_DOMAIN'] || nil %> # The cluster type determines how the application will support # multiple domains. The default is nil which means that the # application itself is responsible for handling multiple domains. :cluster: :type: <%= ENV['CLUSTER_TYPE'] || nil %> :api_key: <%= ENV['APPROXIMATED_API_KEY'] || nil %> :cluster_ip: <%= ENV['APPROXIMATED_PROXY_CLUSTER_IP'] || '<CLUSTER_IP>' %> :cluster_host: <%= ENV['APPROXIMATED_PROXY_CLUSTER_HOST'] || '<CLUSTER_HOST>' %> :cluster_name: <%= ENV['APPROXIMATED_PROXY_CLUSTER_NAME'] || '<CLUSTER_NAME>' %> :vhost_target: <%= ENV['APPROXIMATED_PROXY_VHOST_TARGET'] || '<VHOST_TARGET>' %>:features: :incoming: :enabled: false :email: CHANGEME@example.com :passphrase: abacus# Redis Configuration:redis: # Main Redis connection URI - Specify full connection string including auth # Format: redis://[:password@]host[:port]/[db-number] # Examples: # - redis://mypassword@localhost:6379/0 # Simple password auth # - redis://user:pass@localhost:6379/0 # Username/password auth # - redis://redis.example.com:6379/0 # No auth (development only) :uri: <%= ENV['REDIS_URL'] || 'redis://CHANGEME@127.0.0.1:6379/0' %>
# Logging Configuration:logging: # HTTP request logs (Rack::CommonLogger) :http_requests: <%= ENV['LOG_HTTP_REQUESTS'] != 'false' %>
# Sending Emails:emailer: # Local Development with Mailpit # ----------------------------- # Mailpit is a dev SMTP server that captures emails for testing # Install: brew install mailpit # Start: mailpit # Web UI: http://localhost:8025 # # :mode: smtp # Use SMTP mode for local testing # :from: secure@onetimesecret.com # Sender address # :fromname: OTS Support # Sender name # :host: 127.0.0.1 # Mailpit host # :port: 1025 # Mailpit default SMTP port # :user: ~ # No auth needed for Mailpit # :pass: ~ # No auth needed for Mailpit # :auth: false # Disable SMTP auth for Mailpit # :tls: false # Disable TLS for local testing
# Production Settings (for reference) # ---------------------------------- :mode: <%= ENV['EMAILER_MODE'] || 'smtp' %> :from: <%= ENV['FROM_EMAIL'] || ENV['FROM'] || 'CHANGEME@example.com' %> :fromname: <%= ENV['FROMNAME'] || 'Support' %> :host: <%= ENV['SMTP_HOST'] || 'smtp.provider.com' %> :port: <%= ENV['SMTP_PORT'] || 587 %> :user: <%= ENV['SMTP_USERNAME'] %> :pass: <%= ENV['SMTP_PASSWORD'] %> :auth: <%= ENV['SMTP_AUTH'] || 'login' %> :tls: <%= ENV['SMTP_TLS'] %>
:mail: :truemail: # Available validation types: :regex, :mx, :mx_blacklist, :smtp :default_validation_type: :regex # Required for :smtp validation :verifier_email: <%= ENV['VERIFIER_EMAIL'] || 'CHANGEME@example.com' %> #:verifier_domain: <%= ENV['VERIFIER_DOMAIN'] || 'example.com' %> #:connection_timeout: 2 #:response_timeout: 2 #:connection_attempts: 3 #:validation_type_for: # 'example.com': :regex # # Truemail will only validate email addresses that match the # domains listed in :allowed_domains. If the domain is not # listed, the email address will always be considered invalid. :allowed_domains_only: false # # Email addresses in this list will always be valid. #:allowed_emails: [] # # Email addresses in this list will always be invalid. #:blocked_emails: [] # # Addresses with these domains will always be valid #:allowed_domains: [] # # Addresses with these domains will always be invalid #:blocked_domains: [] # # Exclude these IP addresses from the MX lookup process. #:blocked_mx_ip_addresses: [] # # Name servers to use for MX et al record lookup. # Default is CloudFlare, Google, Oracle/OpenDNS servers. :dns: - 1.1.1.1 - 8.8.4.4 - 208.67.220.220 #:smtp_port: 25 # # End smtp validation after the first invalid response rather than # retrying, followed by trying the next server. Can reduce the time # time to validate an email address, but may not catch all issues. :smtp_fail_fast: false # # Parse the content of the SMTP error message to determine if the # email address is valid. This can be useful for some SMTP servers # that don't return exact answers. :smtp_safe_check: true # # Whether to disable the RFC MX lookup flow. When true, only DNS # validation will be performed on MX and Null MX records. :not_rfc_mx_lookup_flow: false # # Override default regular expression pattern for email addresses # and/or the content in SMTP error messages. #:email_pattern: /regex_pattern/ #:smtp_error_body_pattern: /regex_pattern/ # # Log to the console, a file, or both. The ruby process must have # write access to the log file. The log file will be created if it # does not exist. Log file rotation is not handled by the app. :logger: # One of: :error (default), :unrecognized_error, :recognized_error, :all. :tracking_event: :error :stdout: true # log_absolute_path: '/home/app/log/truemail.log'
:internationalization: :enabled: <%= ENV['I18N_ENABLED'] == 'true' || false %> :default_locale: <%= ENV['I18N_DEFAULT_LOCALE'] || 'en' %> :fallback_locale: fr-CA: [fr_CA, fr_FR, en] fr: [fr_FR, fr_CA, en] de-AT: [de_AT, de, en] de: [de, de_AT, en] it: [it_IT, en] pt: [pt_BR, en] default: [en] # A list of ISO language codes (e.g., 'en' for English, 'es' # for Spanish, etc.). There is a corresponding file in src/locales # with the same name containing the translated text. If it's not # selected automatically, users are able to select their preferred # language by using the toggle in the footer or in the settings # modal if they're logged in. :locales: - bg - da_DK - de - de_AT - el_GR - en - es - fr_CA - fr_FR - it_IT - ja - ko - mi_NZ - nl - tr - uk - pl - pt_BR - sv_SE
:experimental: # SECURITY FEATURE: Controls whether the application can run without a # site.secret (either in this file or via the SECRET env var). # # DEFAULT: false (application will fail to start if site.secret is nil) # # WARNING: Setting to true presents significant security risks: # - Secrets may be stored without proper encryption # - Unauthorized access to sensitive data becomes possible # - Secret link integrity cannot be guaranteed # # VALID USE CASES (temporary only): # 1. RECOVERY: You accidentally ran with nil secret and need to recover # existing secrets created during that time. Enable temporarily until # all affected secrets expire (max TTL period). # 2. MIGRATION: During a controlled migration between encryption schemes, # with proper security measures in place. # # BEHAVIOR WHEN TRUE: # - Application starts without failing # - Warning logs appear at startup # - When decrypting, CipherErrors with the real secret will cause # automatic retry with nil secret # :allow_nil_global_secret: <%= ENV['ALLOW_NIL_GLOBAL_SECRET'] == 'true' || false %> # SECURITY FEATURE: Support for rotating global secret # # FORMAT: Array of strings containing previous secret values # ["old_secret_1", "old_secret_2", "oldest_secret"] # # USAGE: When rotating secrets, add old values here while setting new primary # secret in site.secret or SECRET env var. The application will: # 1. Use current primary secret for all new encryptions # 2. Try each rotated secret (in order) for decryption when primary fails # # MAINTENANCE: Remove secrets from this list after the relevant secrets # have expired or has been successfully re-encrypted with the current # primary secret. An easy guideline is the maximum TTL in `ttl_options`. :rotated_secrets: [] # When set to true, the Rack::Builder#freeze_app freezes the middleware stack # after initialization to prevent any runtime modifications to the app # middleware chain. This is a security measure that prevents malicious # code from injecting new middleware. # # Effects: # - Freezes the middleware stack, preventing adding/removing after boot # - Freezes the app object passed to Rack::Builder # - Does not affect request/response object mutability # # Note: This setting can help make your application more secure by preventing # middleware chain manipulation at runtime. For most applications, this # should be enabled in production environments. :freeze_app: false # Middleware Configuration # Controls which security and performance middleware components are enabled :middleware: # Serve static files for frontend vue application :static_files: true # Sanitizes request parameters to ensure proper UTF-8 encoding # Prevents encoding-based attacks and malformed input :utf8_sanitizer: true # Protects against Cross-Site Request Forgery (CSRF) attacks # Validates that requests originate from the same site :http_origin: false # Escapes HTML entities in request parameters # Helps prevent XSS attacks via request parameters :escaped_params: false # Sets X-XSS-Protection header to enable browser XSS filtering # Modern browsers rely less on this as CSP becomes standard :xss_header: false # Prevents your site from being embedded in frames (clickjacking protection) # Sets X-Frame-Options header to SAMEORIGIN or DENY :frame_options: false # Blocks directory traversal attacks using "../" in paths # Critical for preventing unauthorized file access :path_traversal: false # Protects against cookie tossing attacks # Prevents session fixation via manipulated cookies :cookie_tossing: false # Prevents IP spoofing attacks by validating IP addresses # Useful when IP-based access controls are implemented :ip_spoofing: false # Forces all connections to use HTTPS via HSTS headers # Disable only for development or when behind a secure proxy :strict_transport: false # When enabled, adds Content-Security-Policy headers to the response. When # `development.enabled=true`, the headers will be less restrictive but still # prevent any content loading from other origins. In regular production mode, # a secure nonce will be included with the headers and unsafe-inline content # is completely blocked. The nonce can be accessed via the rack request object # `req.env['ots.nonce']`. The backend views grab it from there to add it to # all front-end script and style assets automatically. You'd only need to use # the none if you're adding new script or style dependencies. # When disabled, no csp headers are included in any environment. :csp: :enabled: <%= ENV['CSP_ENABLED'] == 'true' || false %>