Configure

Last updated on June 26, 2026

Configuration lives in a single .env file that is generated on first run. To create it, SSH into your server and run the deploy command from Orbit:

curl -fsSL https://tofupilot.sh/deploy | bash -s -- --license YOUR_LICENSE_KEY

The script writes a .env template into the current directory and exits. Open it with your editor of choice:

nano .env

The .env file also holds auto-generated secrets (AUTH_SECRET, DB_PASSWORD, S3_SECRET_ACCESS_KEY, the CENTRIFUGO_* keys, and DEPLOYER_TOKEN). Do not delete or modify them. They are created on first deploy and reused on every re-run.

Domains

TofuPilot needs three subdomains. Create a DNS A record for each pointing to your server, then set them in .env:

  • DOMAIN_NAME for the application (e.g. tofupilot.yourcompany.com).
  • STORAGE_DOMAIN_NAME for file storage (e.g. storage.tofupilot.yourcompany.com).
  • CENTRIFUGO_DOMAIN_NAME for realtime updates over WebSocket (e.g. realtime.tofupilot.yourcompany.com). Defaults to realtime.<DOMAIN_NAME> if unset.

Realtime features (live station status and telemetry, dashboard updates, and streaming build logs) need the CENTRIFUGO_DOMAIN_NAME record and its TLS certificate. Without it the app still works, but those views fall back to manual refresh.

SSL certificates

HTTPS is handled by Let's Encrypt by default. To enable it, set your email:

SSL_MODE=letsencryptSSL_LETSENCRYPT_EMAIL=admin@yourcompany.com

If you use your own certificate authority, switch to custom mode and provide absolute paths on the host:

SSL_MODE=customSSL_CERT_PATH=/etc/ssl/tofupilot/fullchain.pemSSL_KEY_PATH=/etc/ssl/tofupilot/privkey.pem

Authentication

You need at least one sign-in method. TofuPilot supports email magic links and several OAuth providers, and you can enable as many as you want.

When you skip email, users sign in only through OAuth, which means no invitations or notifications.

The email method sends a one-time code by email and drives invitations and notifications.

EMAIL_SMTP_HOST=smtp.yourcompany.comEMAIL_SMTP_PORT=587EMAIL_SMTP_USER=noreply@yourcompany.comEMAIL_SMTP_PASSWORD=your-smtp-passwordEMAIL_FROM_AUTH=noreply@yourcompany.com

Google

Create an OAuth app in the Google Cloud Console and set the redirect URI to:

https://tofupilot.yourcompany.com/api/auth/callback/google

Copy the Client ID and Client Secret into .env:

AUTH_GOOGLE_ID=your-client-idAUTH_GOOGLE_SECRET=your-client-secret

Microsoft Entra ID

Register an app in the Azure Portal under App registrations and set the redirect URI to:

https://tofupilot.yourcompany.com/api/auth/callback/microsoft

Copy the Application (client) ID and Secret into .env:

AUTH_MICROSOFT_ENTRA_ID_ID=your-client-idAUTH_MICROSOFT_ENTRA_ID_SECRET=your-client-secretAUTH_MICROSOFT_ENTRA_ID_ISSUER=https://login.microsoftonline.com/your-tenant-id/v2.0

Replace your-tenant-id with your Azure AD tenant ID. For Azure Government, use login.microsoftonline.us.

GitHub

Create an OAuth app in GitHub Developer Settings and set the callback URL to:

https://tofupilot.yourcompany.com/api/auth/callback/github

Copy the Client ID and Client Secret into .env:

AUTH_GITHUB_ID=your-client-idAUTH_GITHUB_SECRET=your-client-secret

GitLab

Create an application in GitLab (or your self-hosted GitLab instance) with the read_user and openid scopes, and set the redirect URI to:

https://tofupilot.yourcompany.com/api/auth/callback/gitlab

Copy the Application ID and Secret into .env:

AUTH_GITLAB_ID=your-application-idAUTH_GITLAB_SECRET=your-application-secretAUTH_GITLAB_ISSUER=https://gitlab.com

For self-hosted GitLab, replace https://gitlab.com with your instance URL.

Git provider

TofuPilot can connect to GitHub or GitLab so you can drive automatic Deployments from your CI/CD pipelines.

GitHub

Self-hosted instances need their own GitHub App.

Step 1. Go to your GitHub organization Settings > Developer Settings > GitHub Apps > New GitHub App and fill in:

FieldValue
App nametofupilot-yourcompany (must be globally unique on GitHub)
Homepage URLhttps://DOMAIN_NAME

Step 2. In Identifying and authorizing users, leave the Callback URL empty. Uncheck Request user authorization (OAuth) during installation and Expire user authorization tokens.

Step 3. Fill in the remaining sections:

  • Post installation
    • Setup URL: https://DOMAIN_NAME/api/github/setup
    • Redirect on update: unchecked
  • Webhook
    • Active: checked
    • Webhook URL: https://DOMAIN_NAME/api/webhooks/github
    • Secret: a random string (e.g. run openssl rand -hex 32 in your terminal)
  • Repository permissions
    • Contents: Read-only (clone repositories and read commits)
    • Administration: Read and write (required to create a repository from a template)
    • Metadata: Read-only (automatically selected)
    • Pull requests: Read-only
  • Organization permissions: none
  • Account permissions: none
  • Subscribe to events
    • Delete, Pull request, Push, Repository
  • Install target
    • Only on this account

Administration: Read and write is required for cloning starter templates. Without it, creating a procedure from a template fails with a 403.

Step 4. Click Create GitHub App. GitHub may redirect you to your instance's sign-in page afterward. That is expected: the App is already created. On the App's General page, note the App ID.

Make sure Push is checked under Subscribe to events (Step 3). Without it GitHub won't notify your instance of new commits and auto-deploy won't trigger.

Step 5. Scroll to Private keys, click Generate a private key, and base64-encode the downloaded file:

base64 -w 0 < downloaded_file.pem
base64 -i downloaded_file.pem
[Convert]::ToBase64String([IO.File]::ReadAllBytes("downloaded_file.pem"))

Step 6. Add these variables to .env:

GITHUB_APP_ID=your-app-idGITHUB_APP_PRIVATE_KEY=your-base64-encoded-private-keyGITHUB_APP_WEBHOOK_SECRET=your-webhook-secretGITHUB_APP_SLUG=tofupilot-yourcompany
  • GITHUB_APP_ID comes from Step 4 (App's General page).
  • GITHUB_APP_PRIVATE_KEY comes from Step 5 (base64-encoded output).
  • GITHUB_APP_WEBHOOK_SECRET comes from Step 3 (webhook secret).
  • GITHUB_APP_SLUG is the last segment of your App URL: https://github.com/apps/{slug}.

Step 7. After deploying, go to Settings > GitHub in your dashboard to install the App and select repositories.

GitLab

GitLab needs no extra environment variables. Go to Settings > GitLab in your dashboard and click Connect to add your GitLab access token, instance URL, and select a group.

Deployments

The deployments pipeline builds procedure bundles from your Git repository and serves them to stations. It runs automatically on self-hosted installs, no extra .env configuration is required:

  • The tofupilot-deployer container builds bundles in an isolated Docker-in-Docker sandbox.
  • Artifacts are stored in a dedicated bucket on the bundled object storage; the dashboard mints short-lived presigned links for stations to download them.
  • DEPLOYER_TOKEN and the ARTIFACT_* settings are generated and wired automatically.

The deployer needs a privileged container to run its build sandbox (its own Docker-in-Docker daemon — it does not mount the host Docker socket). It will not start under rootless Docker; the rest of the stack is unaffected. Use a standard (root) Docker installation if you need the build pipeline. Because builds execute your procedure code inside this privileged worker, run self-hosted on a host you control and treat the build worker as part of your trust boundary.

The bundled object storage (SeaweedFS) serves both the app and artifact buckets without S3 authentication, so anything reachable on storage.<your-domain> can read stored objects directly. Keep that hostname on a trusted network, or front it with your own access control, if your build bundles contain proprietary source. This applies to the existing app bucket too.

To deploy automatically when you push to a branch, configure the GitHub App above. The push webhook triggers a build for procedures with auto-deploy enabled. Manual deploys from the dashboard work without it.

How is this guide?

On this page