Environment Variables
TaskView is configured through environment variables set in the .env.taskview file (or passed directly to the Docker container). This page documents every available variable.
Database
These must match your PostgreSQL setup.
| Variable | Required | Default | Description |
|---|---|---|---|
DB_HOST | Yes | - | Database hostname. Use db when running in Docker Compose. |
DB_USER | Yes | - | Database username |
DB_PASSWORD | Yes | - | Database password |
DB_NAME | Yes | - | Database name |
DB_PORT | No | 5432 | Database port |
DB_POOL_MAX | No | 20 | Maximum Postgres connections per API worker (each worker opens its own pool) |
Connection budget: the total number of Postgres connections is roughly PM2_INSTANCES × DB_POOL_MAX. Keep it below the max_connections of your PostgreSQL (default 100), leaving ~10 connections of headroom for migrations and maintenance. The API logs a warning at startup when the estimate exceeds 80.
Application
| Variable | Required | Default | Description |
|---|---|---|---|
APP_PORT | No | 1401 | Port the API server listens on |
PM2_INSTANCES | No | 2 | Number of API worker processes (PM2 cluster mode). Accepts a number or max (one worker per CPU core). When using max, set DB_POOL_MAX yourself so the connection budget above still fits. |
APP_URL | Yes | https://app.taskview.tech | Full URL of the web app (e.g. https://tasks.company.com). Used for OAuth redirects and email links. |
API_PUBLIC_URL | No | - | Public URL of the API server as external systems see it (e.g. https://api.company.com). Used to build the SSO callback/ACS URL and the SCIM endpoint shown in organization settings. Set it when the API runs behind a reverse proxy — otherwise those URLs are derived from the browser's address and may show an internal host that your IdP cannot reach. The server refuses to start if the value is not a valid http(s) URL. |
TRUST_PROXY | No | false | Set when running behind a reverse proxy so X-Forwarded-Proto/X-Forwarded-For are honoured (correct https URLs, real client IP). Use the number of proxies in front of the app (1 for a single Caddy/nginx), or an IP/subnet list (10.0.0.0/8, uniquelocal). Leave unset for direct access. Avoid true (trusts any hop, allows header spoofing). |
Web app
Unlike everything else on this page, this variable is set on the web app container (taskview-webapp), not in .env.taskview.
| Variable | Required | Default | Description |
|---|---|---|---|
TASKVIEW_API_URL | No | - | Pins the API server URL for the web app (e.g. https://api.company.com). When set, the "Select server" section disappears from the login page and the app always talks to this API. When unset, users pick the API server on the login page themselves. |
Authentication
| Variable | Required | Default | Description |
|---|---|---|---|
JWT_SIGN | Yes | - | Secret key for signing JWT tokens. Use a long random string. |
ACCESS_LIFE_TIME | No | 1d | How long access tokens are valid. Examples: 1h, 1d, 7d |
REFRESH_LIFE_TIME | No | 2d | How long refresh tokens are valid |
JWT_ALG | No | HS256 | JWT signing algorithm |
AUTH_LOGIN_METHODS | No | all enabled | Comma-separated list of login methods to offer: magic-link, password, sso, social. Disabled methods disappear from the login page and their API endpoints return 403. The API refuses to start if the list contains a typo or disables every method. |
PASSWORD_CHANGE_CONFIRMATION | No | email | How account password changes are confirmed: email — a confirmation code is sent to the user's email (requires SMTP); password — the user confirms with their current password (works without SMTP, recommended for installs without a mail server). |
ALLOW_PUBLIC_REGISTRATION | No | true | Set to false to close the instance: strangers can no longer create accounts — the registration endpoint returns 403, and magic-link / social sign-in stop auto-creating users. Emails invited to an organization or project can still sign in and get their account created on first login. |
node -e "console.log(require('crypto').randomBytes(64).toString('hex'))"Closing an instance: how ALLOW_PUBLIC_REGISTRATION=false works
By default anyone who can reach your instance can create an account — through the registration endpoint, or simply by entering an email on the login page (magic-link and social sign-in create the account on first login). Set ALLOW_PUBLIC_REGISTRATION=false to close the instance: from that moment accounts are created by invitation only.
Who can still get an account on a closed instance. TaskView invitations are stored by email, before any account exists. An email is considered invited — and its owner can sign in and get an account created on first login — if it appears in any of these places:
- Organization members — added via organization settings (or provisioned through SCIM)
- Project collaborators — invited to a project by an existing user
Everyone else is rejected: the registration endpoint returns 403, magic-link refuses to send a code to an unknown email, and social sign-in redirects back to the login page with an error. Existing accounts are not affected in any way — the flag only controls the creation of new ones.
SSO is not blocked by this flag. Signing in through a SAML/OIDC provider still provisions accounts, because an identity provider is configured by the administrator and is itself a controlled channel — your IdP decides who gets in.
The value must be true or false. Any other value (a typo like Flase, 0, no) stops the server at startup with a clear error instead of silently leaving the instance open.
SMTP (Email)
Required for password recovery, email confirmation, and invitation notifications. Without SMTP, these features won't work, but everything else functions normally.
| Variable | Required | Default | Description |
|---|---|---|---|
SMTP_HOST | No | - | SMTP server hostname |
SMTP_PORT | No | 465 | SMTP port |
SMTP_USERNAME | No | - | SMTP login |
SMTP_PASSWORD | No | - | SMTP password |
SMTP_ENCRYPTION | No | ssl | ssl or tls |
SMTP_FROM_NAME | No | TaskView | Sender name in emails |
SMTP_FROM_EMAIL | No | - | Sender email address |
INVITE_EMAIL_ENABLED | No | false | Set to true to email a person when they are invited to a project. The email is localized (English/Russian) by the inviter's browser language and links to the project. Requires SMTP; the value must be true or false — anything else stops the server at startup. |
INVITE_EMAIL_HOURLY_LIMIT | No | 30 | Maximum invite emails one user may trigger per hour. On top of this cap, the same address is never emailed about the same project more than once per 24 hours. Must be a positive integer. |
Encryption
Required for SSO (SAML/OIDC) and GitHub/GitLab integrations. Secrets are encrypted at rest using AES-256-GCM.
| Variable | Required | Default | Description |
|---|---|---|---|
ENCRYPTION_KEY | Yes | - | 32-byte hex string (64 characters). Required for SSO and integrations. |
Generate a key:
openssl rand -hex 32
What is encrypted:
- SSO: SAML certificates, SAML signing keys, OIDC client secrets
- Integrations: GitHub/GitLab OAuth tokens, webhook secrets
GitHub Integration
For connecting GitHub repositories. See GitHub, GitLab & Gitea Setup for a step-by-step guide.
| Variable | Required | Default | Description |
|---|---|---|---|
GITHUB_INTEGRATION_CLIENT_ID | No | - | OAuth App client ID |
GITHUB_INTEGRATION_CLIENT_SECRET | No | - | OAuth App client secret |
GITHUB_INTEGRATION_CALLBACK_URL | No | - | OAuth callback URL |
GITHUB_BASE_URL | No | https://github.com | Override for GitHub Enterprise |
GITHUB_API_URL | No | https://api.github.com | Override for GitHub Enterprise API |
GitLab Integration
For connecting GitLab repositories.
| Variable | Required | Default | Description |
|---|---|---|---|
GITLAB_INTEGRATION_CLIENT_ID | No | - | OAuth App client ID |
GITLAB_INTEGRATION_CLIENT_SECRET | No | - | OAuth App client secret |
GITLAB_INTEGRATION_CALLBACK_URL | No | - | OAuth callback URL |
GITLAB_BASE_URL | No | https://gitlab.com | Override for self-hosted GitLab |
GITLAB_API_URL | No | https://gitlab.com/api/v4 | Override for self-hosted GitLab API |
Gitea Integration
For connecting Gitea repositories.
| Variable | Required | Default | Description |
|---|---|---|---|
GITEA_INTEGRATION_CLIENT_ID | No | - | OAuth2 application client ID |
GITEA_INTEGRATION_CLIENT_SECRET | No | - | OAuth2 application client secret |
GITEA_INTEGRATION_CALLBACK_URL | No | - | OAuth callback URL |
GITEA_BASE_URL | No | https://gitea.com | Override for self-hosted Gitea |
GITEA_API_URL | No | {GITEA_BASE_URL}/api/v1 | Override for self-hosted Gitea API |
Messaging Integrations (Telegram / Slack)
For delivering task notifications to messengers. See Telegram & Slack Setup for a step-by-step guide.
| Variable | Required | Default | Description |
|---|---|---|---|
TELEGRAM_BOT_TOKEN | No | - | Bot token from @BotFather |
TELEGRAM_BOT_USERNAME | No | - | Bot username without @ (used to build deep-links) |
TELEGRAM_WEBHOOK_SECRET | No | - | Secret verified against Telegram's X-Telegram-Bot-Api-Secret-Token header on inbound updates |
SLACK_CLIENT_ID | No | - | Slack app client ID |
SLACK_CLIENT_SECRET | No | - | Slack app client secret |
SLACK_CALLBACK_URL | No | - | OAuth callback URL (must match the Slack app redirect URL) |
SLACK_SIGNING_SECRET | No | - | Slack request signing secret — verifies inbound slash commands / interactivity (/task, Done/Assign buttons) |
SLACK_API_BASE_URL | No | https://slack.com/api | Override the Slack Web API base (testing / enterprise proxy) |
SLACK_AUTHORIZE_URL | No | https://slack.com/oauth/v2/authorize | Override the Slack OAuth authorize URL |
SLACK_WEBHOOK_PREFIX | No | https://hooks.slack.com/ | Override the incoming-webhook URL prefix (used to detect legacy webhook connections) |
Notifications
Optional configuration for real-time and push notification delivery.
Centrifugo (real-time WebSocket notifications)
Required for in-app real-time notification delivery. Without Centrifugo, notifications are still saved to the database but will not appear instantly in the browser. Users will see them on the next page load.
| Variable | Required | Default | Description |
|---|---|---|---|
CENTRIFUGO_API_URL | No | - | Internal Centrifugo API URL (e.g. http://centrifugo:8000) |
CENTRIFUGO_API_KEY | No | - | Centrifugo API key for server-to-server communication. Must match http_api.key in Centrifugo config. |
CENTRIFUGO_TOKEN_SECRET | No | - | Secret for generating client connection tokens (HMAC). Must match client.token.hmac_secret_key in Centrifugo config. |
CENTRIFUGO_PUBLIC_URL | No | - | Full WebSocket URL for browser clients (e.g. wss://api.example.com/centrifugo/connection/websocket) |
Firebase Cloud Messaging (mobile push notifications)
Required for native push notifications on iOS and Android. Without Firebase, push notifications are silently skipped.
| Variable | Required | Default | Description |
|---|---|---|---|
FIREBASE_CREDENTIALS_PATH | No | - | Path to Firebase service account JSON file (e.g. ./firebase-credentials.json) |
Centrifugo configuration file
Centrifugo v6 uses a nested JSON config. Create centrifugo/config.json:
{
"client": {
"allowed_origins": ["https://app.example.com"],
"token": {
"hmac_secret_key": "your_centrifugo_token_secret"
}
},
"channel": {
"namespaces": [
{
"name": "personal",
"presence": false,
"join_leave": false,
"history_size": 0,
"history_ttl": "0s"
}
]
},
"http_api": {
"key": "your_centrifugo_api_key"
}
}
http_api.keymust matchCENTRIFUGO_API_KEYin.env.taskviewclient.token.hmac_secret_keymust matchCENTRIFUGO_TOKEN_SECRETin.env.taskviewclient.allowed_originsshould list your frontend domain(s). Use["*"]only for development.
Nginx WebSocket proxy
To serve Centrifugo through your existing HTTPS domain, add to your nginx server block:
location /centrifugo/ {
proxy_pass http://localhost:8000/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
Then set CENTRIFUGO_PUBLIC_URL=wss://api.example.com/centrifugo/connection/websocket.
Full example
Here's a complete .env.taskview file for a production deployment:
DB_HOST="db"
DB_USER="taskview_db_user"
DB_PASSWORD="password"
DB_NAME="taskview"
DB_PORT=5432
# Postgres connections per API worker (this is the default)
DB_POOL_MAX=20
APP_PORT=1401
# API worker processes (this is the default). Accepts a number or "max" (one worker per CPU core).
# Keep PM2_INSTANCES x DB_POOL_MAX below the Postgres max_connections limit (default 100).
PM2_INSTANCES=2
JWT_ALG="HS256"
JWT_SIGN="secret"
ACCESS_LIFE_TIME="3d"
REFRESH_LIFE_TIME="9d"
# Login methods offered on the login page (unset = all enabled)
#AUTH_LOGIN_METHODS="magic-link,password,sso,social"
# Password change confirmation: "email" (code by email, needs SMTP) or "password" (no SMTP needed)
#PASSWORD_CHANGE_CONFIRMATION="email"
SMTP_HOST=smtp
SMTP_PORT=587
SMTP_USERNAME=
SMTP_PASSWORD=
SMTP_ENCRYPTION=tls
SMTP_FROM_NAME=TaskView
SMTP_FROM_EMAIL=
# Your domain
APP_URL="https://app.taskview.tech"
GOOGLE_CLIENT_ID=""
GOOGLE_CLIENT_SECRET=""
#You domain
GOOGLE_CALLBACK_URL="https://api.taskview.tech/module/auth/provider/google/callback"
GITHUB_CLIENT_ID=""
GITHUB_CLIENT_SECRET=""
GITHUB_CALLBACK_URL="https://api.taskview.tech/module/auth/provider/github/callback"
APPLE_CLIENT_ID=""
APPLE_TEAM_ID=""
APPLE_KEY_ID=""
APPLE_KEY_LOCATION="/usr/src/app/AuthKey.p8"
# Your domain
APPLE_CALLBACK_URL="https://api.taskview.tech/module/auth/provider/apple/callback"
#integrations
GITHUB_INTEGRATION_CLIENT_ID=
GITHUB_INTEGRATION_CLIENT_SECRET=
GITHUB_INTEGRATION_CALLBACK_URL=https://api.taskview.tech/module/integrations/oauth/github/callback
GITLAB_INTEGRATION_CLIENT_ID=
GITLAB_INTEGRATION_CLIENT_SECRET=
GITLAB_INTEGRATION_CALLBACK_URL=https://api.taskview.tech/module/integrations/oauth/github/callback
ENCRYPTION_KEY=
# Messaging integrations
TELEGRAM_BOT_TOKEN=
TELEGRAM_BOT_USERNAME=
TELEGRAM_WEBHOOK_SECRET=
# SLACK_CLIENT_ID=
# SLACK_CLIENT_SECRET=
# SLACK_SIGNING_SECRET=
# Notifications (optional)
# FIREBASE_CREDENTIALS_PATH=./firebase-credentials.json
# CENTRIFUGO_API_URL=http://centrifugo:8000
# CENTRIFUGO_API_KEY=your_centrifugo_api_key
# CENTRIFUGO_TOKEN_SECRET=your_centrifugo_token_secret
# CENTRIFUGO_PUBLIC_URL=wss://api.example.com/centrifugo/connection/websocket
Telegram & Slack Setup
Connect Telegram and Slack to TaskView to receive task notifications. Personal direct messages and project-wide group channels, with instance-level bot credentials, OAuth, signed inbound webhooks, and SHA-256 hashed binding tokens.
Authentication
Configure authentication in TaskView - email/password, email/code, OAuth with GitHub, Google, and Apple Sign In. JWT session management, password recovery, and account deletion for your self-hosted instance.
