Environment variables
All Tether configuration is done through environment variables in the .env file. This page documents every variable, its default value, and its effect.
Some variables (marked "first run only") are only read when the database is empty. Changing them after first run has no effect — use the Settings page in the UI instead.
Core
| Variable | Default | Required | Description |
|---|---|---|---|
SECRET_KEY | (insecure placeholder) | Yes | Used to sign and verify JWT login tokens. Must be a long, random string. If this changes, all existing login sessions are immediately invalidated. Generate with: python -c "import secrets; print(secrets.token_hex(32))" |
BASE_DOMAIN | atechsolutions.org | Yes | Your root domain. A tenant with slug acme is accessed at acme.BASE_DOMAIN. For local development use localhost. |
DEPLOYMENT_MODE | selfhosted | No | Controls billing behaviour. selfhosted = no limits. saas = tier limits enforced. demo = enables the hourly reset endpoint. |
Admin account
These are only read on the first run when the database has no users. After the MSP admin account is created, changing these values has no effect — use Settings → Change Password in the UI.
| Variable | Default | Description |
|---|---|---|
ADMIN_EMAIL | admin@atechsolutions.org | Email address for the initial MSP admin account |
ADMIN_PASSWORD | admin | Password for the initial MSP admin account. Change this immediately after first login. |
ADMIN_NAME | MSP Admin | Display name for the initial MSP admin |
The default password admin is universally known. If you deploy Tether with the default and don't change it immediately, anyone who finds your server can log in as an administrator.
Database connection
Tether resolves the database connection in this priority order:
- If
DATABASE_URLis set, it is used directly and allDB_*variables are ignored - If
DB_HOSTandDB_USERare set, a MariaDB connection string is built automatically - If neither is set, SQLite is used with the file at
TETHER_DATA/tether.db
| Variable | Default | Description |
|---|---|---|
DATABASE_URL | (auto-built) | Full connection string. Overrides all DB_* vars. Format: mysql+pymysql://user:pass@host:3306/db?charset=utf8mb4 |
DB_HOST | (unset) | MariaDB/MySQL hostname or IP. When set (alongside DB_USER), triggers MariaDB connection mode. |
DB_PORT | 3306 | Database port. Change if your MariaDB runs on a non-standard port. |
DB_NAME | tether | Database name |
DB_USER | (unset) | Database username |
DB_PASSWORD | (unset) | Database password |
DB_ROOT_PASSWORD | changeme | MariaDB root password. Only used by the Docker Compose db service. |
TETHER_DATA | ./data | Directory where Tether stores its data files. In Docker, this is /data (mounted as a named volume). |
Demo mode
| Variable | Default | Description |
|---|---|---|
RESET_SECRET | (unset) | A secret token that must be included in the X-Reset-Secret HTTP header to call the demo reset endpoint. Set this to a long random string and configure the same value in your Cloudflare Worker. |
Default tenant
On first run, Tether creates one demo tenant. These variables control what it's called. Only read once on first run.
| Variable | Default | Description |
|---|---|---|
DEFAULT_TENANT_SLUG | demo | URL slug for the demo tenant (becomes demo.yourdomain.com) |
DEFAULT_TENANT_NAME | Demo Client | Display name for the demo tenant |
Generating a SECRET_KEY
The SECRET_KEY should be a 64-character random hex string. Generate one with Python:
bashpython3 -c "import secrets; print(secrets.token_hex(32))"
Or with OpenSSL:
bashopenssl rand -hex 32
Using the same secret key across multiple environments (e.g. staging and production) creates a security risk — a token generated on one could authenticate on the other. Always generate a unique key per environment.
Full .env.example
bash# Deployment mode: selfhosted (no limits) | saas (tier limits) | demo DEPLOYMENT_MODE=selfhosted # Generate: python3 -c "import secrets; print(secrets.token_hex(32))" SECRET_KEY=please-change-this-to-a-long-random-string # Your domain — subdomains will be tenant.BASE_DOMAIN BASE_DOMAIN=atechsolutions.org # Database — set DB_HOST+DB_USER to use MariaDB, or leave unset for SQLite DB_HOST=localhost DB_PORT=3306 DB_NAME=tether DB_USER=tether DB_PASSWORD=tether DB_ROOT_PASSWORD=changeme # Docker only # Admin account (first run only) ADMIN_EMAIL=admin@atechsolutions.org ADMIN_PASSWORD=admin ADMIN_NAME=MSP Admin # Demo tenant (first run only) DEFAULT_TENANT_SLUG=demo DEFAULT_TENANT_NAME=Demo Client