Back to Overview

Environment Variables Reference

Complete reference for all Tymeslot environment variables — required settings, defaults, and examples.

Luka Breitig — Software Engineer & AI Developer
Luka Breitig

Software Engineer & AI Developer

⚙️ Core Application

SECRET_KEY_BASE Required

64+ character secret used for session encryption and signing. By default it also derives the key that encrypts integration credentials at rest — so unless you set DATA_ENCRYPTION_KEY (below), rotating this value would make stored credentials undecryptable. Generate with the command shown in the example.

Default: none  ·  Example: openssl rand -base64 64 | tr -d '\\n'

DATA_ENCRYPTION_KEY Optional

Dedicated key for encrypting integration credentials at rest, independent of SECRET_KEY_BASE. Setting it lets you rotate SECRET_KEY_BASE without breaking stored credentials. Base64 that decodes to at least 32 bytes; must stay stable once set. On Cloudron it is generated automatically. See the Data-at-Rest Encryption guide for migration steps.

Default: derived from SECRET_KEY_BASE  ·  Example: openssl rand -base64 48 | tr -d '\\n'

PHX_HOST Required

Your domain name without the protocol prefix.

Default: none  ·  Example: tymeslot.yourdomain.com

PORT Optional

HTTP port for the application server to listen on.

Default: 4000  ·  Example: 4000

DEPLOYMENT_TYPE Optional

Deployment variant. Set to docker or cloudron to control deployment-specific behaviour.

Default: auto-detected  ·  Example: docker

REGISTRATION_ENABLED Optional

Set to false to disable new user registration on this instance. Also runtime-toggleable from the admin UI without a restart; a UI override takes precedence over this env var.

Default: true  ·  Example: false

PASSWORD_AUTH_ENABLED Optional

Set to false to disable email/password login entirely. The login form, sign-up page, and password reset flow are hidden; only OAuth login is available. Useful for SSO-only deployments where all users must authenticate through an identity provider. Also runtime-toggleable from the admin UI.

Default: true  ·  Example: false

LISTEN_IP Optional

IP address to bind the HTTP server. Default :: enables IPv4+IPv6 dual-stack.

Default: ::  ·  Example: 0.0.0.0

URL_SCHEME Optional

Request scheme used in generated URLs. Set to https for production.

Default: https  ·  Example: https

WS_ALLOWED_ORIGINS Optional

Comma-separated list of origins allowed to open WebSocket connections.

Default: derived from PHX_HOST  ·  Example: tymeslot.yourdomain.com,app.example.com

ANALYTICS_SALT_SECRET Optional

Keys the cookie-less daily visitor fingerprint used by booking analytics. Only required when booking analytics is enabled — most self-hosters leave analytics off and never need it. When the feature is enabled, this variable becomes mandatory and the app fails fast at boot if it is missing. Generate it once and keep it constant across deployments — changing it re-hashes the same visitor and double-counts uniques.

Default: none  ·  Example: openssl rand -base64 48

🗄️ Database

DATABASE_HOST Optional

PostgreSQL server hostname.

Default: localhost  ·  Example: db.internal

DATABASE_PORT Optional

PostgreSQL server port.

Default: 5432  ·  Example: 5432

POSTGRES_DB Optional

Database name.

Default: tymeslot  ·  Example: tymeslot

POSTGRES_USER Optional

Database user.

Default: tymeslot  ·  Example: tymeslot

POSTGRES_PASSWORD Required

Database password.

Default: none  ·  Example: a_secure_password

DATABASE_POOL_SIZE Optional

PostgreSQL connection pool size. Reduce for resource-constrained environments.

Default: 60  ·  Example: 20

✉️ Email

EMAIL_ADAPTER Optional

Email delivery method. Use smtp or postmark. Defaults to smtp if not set.

Default: smtp  ·  Example: smtp

Cloudron Users

On Cloudron, email is configured automatically via the sendmail addon. You don't need to set EMAIL_ADAPTER, SMTP_*, or EMAIL_FROM_* variables. Set EMAIL_ADAPTER explicitly only if you want to use a different provider.
EMAIL_FROM_NAME Required

Sender display name shown in email clients.

Default: none  ·  Example: Your Company

EMAIL_FROM_ADDRESS Required

Sender email address.

Default: none  ·  Example: hello@yourdomain.com

EMAIL_SUPPORT_ADDRESS Optional

Support contact email. Defaults to EMAIL_FROM_ADDRESS if not set.

Default: EMAIL_FROM_ADDRESS  ·  Example: support@yourdomain.com

SMTP_HOST Optional

Required for SMTP adapter. SMTP server hostname.

Default: none  ·  Example: smtp.gmail.com

SMTP_PORT Optional

SMTP server port. Use 587 for STARTTLS (recommended) or 465 for SMTPS.

Default: 587  ·  Example: 587

SMTP_USERNAME Optional

Required for SMTP adapter. SMTP authentication username.

Default: none  ·  Example: hello@yourdomain.com

SMTP_PASSWORD Optional

Required for SMTP adapter. SMTP authentication password or app password.

Default: none  ·  Example: your_smtp_password

POSTMARK_API_KEY Optional

Required for Postmark adapter. Server API token from your Postmark dashboard.

Default: none  ·  Example: your-server-api-token

🔑 Google OAuth

ENABLE_GOOGLE_AUTH Optional

Set to true to show a "Sign in with Google" button on the login page.

Default: false  ·  Example: true

GOOGLE_CLIENT_ID Optional

Required to use Google Login, Google Calendar, or Google Meet. OAuth client ID from Google Cloud Console.

Default: none  ·  Example: 123456-abc.apps.googleusercontent.com

GOOGLE_CLIENT_SECRET Optional

Required to use Google features. OAuth client secret from Google Cloud Console.

Default: none  ·  Example: GOCSPX-your-secret

GOOGLE_STATE_SECRET Optional

Required to use Google features. Random secret for OAuth CSRF state verification.

Default: none  ·  Example: openssl rand -hex 32

🔑 Microsoft OAuth

OUTLOOK_CLIENT_ID Optional

Required to use Outlook Calendar or Microsoft Teams. Azure app Application (client) ID.

Default: none  ·  Example: your-azure-app-client-id

OUTLOOK_CLIENT_SECRET Optional

Required to use Microsoft features. Azure app client secret value.

Default: none  ·  Example: your-client-secret-value

OUTLOOK_STATE_SECRET Optional

Required to use Microsoft features. Random secret for OAuth CSRF state verification.

Default: none  ·  Example: openssl rand -hex 32

🎥 Video Conferencing

Tymeslot can attach a Zoom meeting to confirmed bookings. Self-hosters create their own Zoom Marketplace app — see the Zoom integration guide for the full walkthrough.

ZOOM_CLIENT_ID Optional

Required to use Zoom. Marketplace app Client ID.

Default: none  ·  Example: your-zoom-client-id

ZOOM_CLIENT_SECRET Optional

Required to use Zoom. Marketplace app Client Secret.

Default: none  ·  Example: your-zoom-client-secret

ZOOM_STATE_SECRET Optional

Required to use Zoom. Random secret for OAuth CSRF state verification.

Default: none  ·  Example: openssl rand -hex 32

ZOOM_DEAUTH_SECRET Optional

Required to use Zoom. Marketplace Secret Token used to verify the HMAC-SHA256 signature on Zoom's deauthorization webhook posted to /auth/zoom/deauthorize . Find it under Features → Deauthorization Notification in the Marketplace app.

Default: none  ·  Example: <marketplace secret token>

📅 Calendar Sync

WEBHOOK_BASE_URL Optional

Public HTTPS base URL that Google and Microsoft call back to for real-time calendar change notifications (Google push channels and Outlook Graph subscriptions). Usually the same as your PHX_HOST with an https:// prefix — scheme and host only, no trailing slash or path.

When unset, calendar sync falls back to polling every 15 minutes — fully functional, just not instant. Set it only when the host is reachable from the public internet over HTTPS: providers run a validation handshake against the URL when a subscription is registered, so localhost, private-network, and NAT deployments should leave it unset. Existing calendar connections adopt push when their owner reconnects; new connections register automatically.

Default: none (polling fallback)  ·  Example: https://tymeslot.yourdomain.com

💳 Meeting Payments (Stripe)

MEETING_PAYMENTS_ENABLED Optional

Opt-in switch for meeting payments. Exposes the payments dashboard and the per-event-type payment toggle. Requires your instance to be registered as a Stripe Connect platform — see the Stripe Payments Setup guide .

Default: false  ·  Example: true

STRIPE_SECRET_KEY Optional

Your platform's Stripe secret key. Required when MEETING_PAYMENTS_ENABLED=true; the webhook secrets below are only read when this is set.

Default: unset  ·  Example: sk_live_51...

STRIPE_CONNECT_WEBHOOK_SECRET Optional

Signing secret of the Connect webhook endpoint (/webhooks/stripe/connect) that receives connected-account events. Required to verify checkout, refund and dispute events for meeting payments.

Default: unset  ·  Example: whsec_...

MEETING_PAYMENTS_APPLICATION_FEE_BP Optional

Optional platform fee in basis points (100 = 1%), taken from each charge. Defaults to 0, so no platform cut is taken unless you opt in. Range 0 to 10000.

Default: 0  ·  Example: 100

🔑 GitHub OAuth

ENABLE_GITHUB_AUTH Optional

Set to true to show a "Sign in with GitHub" button on the login page.

Default: false  ·  Example: true

GITHUB_CLIENT_ID Optional

Required for GitHub Login. OAuth app client ID from GitHub Developer settings.

Default: none  ·  Example: your_client_id

GITHUB_CLIENT_SECRET Optional

Required for GitHub Login. OAuth app client secret.

Default: none  ·  Example: your_client_secret

🔑 Generic OAuth / OIDC SSO

ENABLE_OAUTH_AUTH Optional

Set to true to show an "SSO" button on the login page.

Default: false  ·  Example: true

Cloudron Users

On Cloudron, SSO is enabled automatically via the OIDC addon — users can log in with their Cloudron account. You don't need to set any OAUTH_* variables. Set ENABLE_OAUTH_AUTH=false to disable SSO entirely.
OAUTH_CLIENT_ID Optional

OAuth 2.0 client ID registered with your identity provider.

Default: none  ·  Example: tymeslot

OAUTH_CLIENT_SECRET Optional

OAuth 2.0 client secret from your identity provider.

Default: none  ·  Example: your-client-secret

OAUTH_PROVIDER_URL Optional

Base URL of your identity provider. Used as the OAuth 2.0 site parameter.

Default: none  ·  Example: https://idp.example.com

OAUTH_AUTHORIZE_URL Optional

Full URL of the authorization endpoint.

Default: none  ·  Example: https://idp.example.com/authorize

OAUTH_TOKEN_URL Optional

Full URL of the token endpoint.

Default: none  ·  Example: https://idp.example.com/token

OAUTH_USERINFO_URL Optional

Full URL of the userinfo endpoint. Must return a JSON object with a sub claim (or id/user_id if OAUTH_ALLOW_ID_FALLBACK is enabled).

Default: none  ·  Example: https://idp.example.com/userinfo

OAUTH_SCOPE Optional

Space-separated list of OAuth scopes to request.

Default: openid email profile  ·  Example: openid email profile groups

OAUTH_ALLOW_ID_FALLBACK Optional

Set to true to accept id or user_id claims when the IdP does not return a standard sub claim. Only enable this for non-OIDC providers.

Default: false  ·  Example: true

🛡️ reCAPTCHA

RECAPTCHA_SITE_KEY Optional

Required to enable reCAPTCHA. v3 site key from Google reCAPTCHA admin console.

Default: none  ·  Example: 6Le-your-site-key

RECAPTCHA_SECRET_KEY Optional

Required to enable reCAPTCHA. v3 secret key from Google reCAPTCHA admin console.

Default: none  ·  Example: 6Le-your-secret-key

RECAPTCHA_SIGNUP_ENABLED Optional

Enable reCAPTCHA score verification on the signup form.

Default: false  ·  Example: true

RECAPTCHA_SIGNUP_MIN_SCORE Optional

Minimum reCAPTCHA score (0.0–1.0) required to pass signup. Higher is more strict.

Default: 0.3  ·  Example: 0.5

RECAPTCHA_BOOKING_ENABLED Optional

Enable reCAPTCHA score verification on booking forms.

Default: false  ·  Example: true

RECAPTCHA_BOOKING_MIN_SCORE Optional

Minimum reCAPTCHA score required to submit a booking.

Default: 0.3  ·  Example: 0.3

RECAPTCHA_EXPECTED_HOSTNAMES Optional

Comma-separated list of hostnames from which reCAPTCHA tokens are accepted. Prevents token replay attacks.

Default: none  ·  Example: tymeslot.yourdomain.com

✈️ Telegram Notifications

TELEGRAM_BOT_TOKEN Optional

Bot token from @BotFather. Setting this variable enables shared bot mode — all three Telegram variables must be set together. The application refuses to start if the token is set but the other two are missing.

Default: none  ·  Example: 123456789:ABCdef...

TELEGRAM_BOT_USERNAME Optional

Username of the bot (without the @ prefix). Required when TELEGRAM_BOT_TOKEN is set.

Default: none  ·  Example: MyTymeslotBot

TELEGRAM_WEBHOOK_SECRET Optional

Random secret passed to Telegram's setWebhook API and verified on every incoming webhook call. Required when TELEGRAM_BOT_TOKEN is set.

Default: none  ·  Example: openssl rand -hex 32

TELEGRAM_ENABLED Optional

Set to true to enable Telegram in own-bot mode (each user supplies their own bot token and chat ID). Only effective when TELEGRAM_BOT_TOKEN is not set — setting the token automatically enables shared bot mode regardless of this flag.

Default: false  ·  Example: true

💬 Slack Notifications

SLACK_CLIENT_ID Optional

Slack App client ID from api.slack.com/apps. Setting this variable enables Slack notifications and unlocks OAuth mode — users see a one-click "Add to Slack" button. Must be paired with SLACK_CLIENT_SECRET.

Default: none  ·  Example: 1234567890.1234567890

SLACK_CLIENT_SECRET Optional

Slack App client secret from the same page. Required alongside SLACK_CLIENT_ID to complete the OAuth code-for-token exchange.

Default: none  ·  Example: abcdef0123456789abcdef0123456789

SLACK_ENABLED Optional

Set to true to enable Slack in webhook-URL-only mode (each user pastes their own Incoming Webhook URL). Ignored when SLACK_CLIENT_ID is set — OAuth mode includes webhook-URL support automatically.

Default: false  ·  Example: true

🚨 Admin Alerts

ADMIN_ALERTS_ENABLED Optional

Set to true to receive operational alert emails for webhook processing failures, integration health issues, and background job errors. Requires ADMIN_ALERT_EMAIL to be set.

Default: false  ·  Example: true

ADMIN_ALERT_EMAIL Optional

Recipient address that admin alert emails are delivered to. Required when ADMIN_ALERTS_ENABLED=true — without it, alerts are logged but no email is sent.

Default: none  ·  Example: admin@yourdomain.com

🔀 HTTP Proxy

HTTPS_PROXY Optional

Route HTTPS outbound requests through this proxy. Also accepts lowercase https_proxy.

Default: none  ·  Example: http://proxy.corp.com:3128

HTTP_PROXY Optional

Route HTTP outbound requests through this proxy. Also accepts lowercase http_proxy.

Default: none  ·  Example: http://proxy.corp.com:3128

NO_PROXY Optional

Comma-separated list of hosts, IP addresses, or CIDR ranges that bypass the proxy. Also accepts lowercase no_proxy.

Default: none  ·  Example: localhost,127.0.0.1,10.0.0.0/8

🛡️ Outbound Network (SSRF)

In production, outbound requests to hosts that resolve to a private, loopback, or link-local address are blocked to prevent server-side request forgery. If you self-host integrations on a private network, the switches below opt specific subsystems out. Both default to blocking; leave them unset unless you genuinely run those services on an internal network.

ALLOW_PRIVATE_IPS_FOR_CALENDAR Optional

Permit calendar (CalDAV) and self-hosted video (e.g. MiroTalk) connections whose hostname resolves to a private address. Does not affect webhooks.

Default: false  ·  Example: true

ALLOW_PRIVATE_IPS_FOR_WEBHOOKS Optional

Permit outbound webhook deliveries to URLs that resolve to a private address. Separate from the calendar switch, so relaxing calendar or video SSRF does not also open webhooks to internal hosts.

Default: false  ·  Example: true

🌐 Clustering

DNS_CLUSTER_QUERY Optional

DNS query used for Erlang cluster node discovery in multi-node deployments.

Default: none  ·  Example: tymeslot.internal

Minimum Configuration

A minimal Docker deployment only requires: SECRET_KEY_BASE, PHX_HOST, POSTGRES_PASSWORD, and email configuration (EMAIL_FROM_NAME, EMAIL_FROM_ADDRESS, and SMTP or Postmark credentials). All other variables have defaults or are feature-specific.

Frequently Asked Questions

What is the minimum set of environment variables I need to run Tymeslot?

For a Docker deployment you need five variables to start the application:

  • SECRET_KEY_BASE — required for session signing
  • PHX_HOST — your public domain name
  • POSTGRES_PASSWORD — the only truly required database variable; hostname, name, and user all have defaults
  • EMAIL_FROM_NAME and EMAIL_FROM_ADDRESS — required for outbound email

Plus credentials for your chosen email adapter — SMTP variables if using the default adapter, or POSTMARK_API_KEY if using Postmark.

How do I generate a value for SECRET_KEY_BASE?

Run either of these commands and paste the output as the variable value:

mix phx.gen.secret — requires an Elixir installation

openssl rand -base64 64 | tr -d '\n' — works on any system with OpenSSL

The value must be at least 64 characters long. Never reuse a value across environments and never commit it to version control.

Can I use a .env file instead of setting environment variables directly?

Yes, in three different ways depending on how you deploy:

  • Docker Compose: a .env file next to your docker-compose.yml is auto-loaded by Compose and substituted into the file.
  • Standalone release / Docker image: Tymeslot reads $RELEASE_ROOT/.env at boot. Mount or bake a .env into the release directory and any keys not already set in the shell are loaded from it.
  • Cloudron: Tymeslot reads /app/data/.env at boot — the persistent data volume so the file survives upgrades. Place or edit it via cloudron exec or cloudron push .

In every case, shell-supplied variables (set via the platform's CLI or dashboard) take precedence over .env entries — the file is a default that the environment can override per-key. Malformed .env files are skipped with a warning rather than crashing the boot.

Never commit a .env file containing secrets to a public repository.

What format should DATABASE_URL be in?

Tymeslot's Docker deployment uses individual variables (DATABASE_HOST, POSTGRES_DB, etc.) rather than a single connection URL. If you are on Cloudron, the platform injects its own CLOUDRON_POSTGRESQL_* variables automatically — you do not need to set any database variables manually.

If your hosting platform provides a single URL and you need to break it apart, the standard PostgreSQL format is: postgres://username:password@hostname:5432/database_name

I changed an environment variable but the application behaviour did not change — why?

Environment variables are read at startup only. A running container retains the values it was started with regardless of any later changes to your .env file or platform configuration.

Restart the container after every environment variable change: docker-compose restart tymeslot (or a full docker-compose up -d to pick up changes to the Compose file itself).

🔗 Related Articles

Read Docker Self-Hosting

Docker Self-Hosting

Deploy Tymeslot with Docker Compose on any VPS or home server. Includes reverse proxy setup, file upload volumes, and WebSocket configuration for LiveView.

Read Cloudron Deployment

Cloudron Deployment

Install Tymeslot on Cloudron in minutes. PostgreSQL, SSL certificates, email relay, and automatic updates are all provisioned and managed for you.

Read Railway Deployment

Railway Deployment

Deploy Tymeslot to Railway with one click. PostgreSQL is provisioned and connected automatically — set two environment variables and your instance is live.