# Environment Configuration All settings are configured in `backend/.env`. Copy `backend/.env.example` to `backend/.env` and fill in the values for the providers you want to use. The backend must be restarted after any changes to `.env`. --- ## Cloudflare | Variable | Required | Description | |----------|----------|-------------| | `CLOUDFLARE_API_TOKEN` | Yes | API token with Zone:Read and DNS:Edit permissions | Create a token at **dash.cloudflare.com → My Profile → API Tokens → Create Token**. See `API-ACCESS.md` for the required permissions. --- ## Loopia | Variable | Required | Description | |----------|----------|-------------| | `LOOPIA_USER` | Yes | API username in the format `youruser@loopiaapi` | | `LOOPIA_PASSWORD` | Yes | API user password | Create an API user at **customerzone.loopia.se → My Account → API Users**. See `API-ACCESS.md` for the required method groups. --- ## Pi-hole | Variable | Required | Description | |----------|----------|-------------| | `PIHOLE_URL` | Yes | Base URL of the Pi-hole instance, e.g. `http://192.168.1.x` | | `PIHOLE_PASSWORD` | Yes | Pi-hole web interface password | Requires Pi-hole v6. Only A, AAAA, and CNAME records are supported. TTL is not configurable via the Pi-hole API. --- ## Azure DNS | Variable | Required | Description | |----------|----------|-------------| | `AZURE_TENANT_ID` | Yes | Azure AD tenant ID | | `AZURE_CLIENT_ID` | Yes | Service principal application (client) ID | | `AZURE_CLIENT_SECRET` | Yes | Service principal client secret | | `AZURE_SUBSCRIPTION_ID` | Yes | Azure subscription ID containing the DNS zones | The service principal requires the **DNS Zone Contributor** role on the subscription or resource group. See `API-ACCESS.md` for setup instructions. --- ## cPanel | Variable | Required | Description | |----------|----------|-------------| | `CPANEL_URL` | Yes | cPanel URL including port, e.g. `https://hostname:2083` | | `CPANEL_USERNAME` | Yes | cPanel account username | | `CPANEL_API_TOKEN` | Yes | API token created in cPanel → Security → Manage API Tokens | | `CPANEL_INSECURE` | No | Set to `true` to disable SSL certificate verification. Use when cPanel uses a self-signed certificate. Defaults to `false`. | The cPanel account must own the domains you want to manage. Uses the cPanel UAPI and API 2 (ZoneEdit module). See `API-ACCESS.md` for setup instructions. --- ## Authentik SSO Single sign-on via Authentik (optional). When configured, a **Sign in with Authentik** button appears on the login page alongside the regular username/password form. Users who sign in via SSO for the first time are automatically created as local accounts. | Variable | Required | Description | |----------|----------|-------------| | `AUTHENTIK_URL` | Yes | Issuer URL of your Authentik application, e.g. `https://auth.example.com/application/o/sloth-manager` | | `AUTHENTIK_CLIENT_ID` | Yes | Client ID from the Authentik OAuth2/OIDC Provider | | `AUTHENTIK_CLIENT_SECRET` | Yes | Client secret from the Authentik OAuth2/OIDC Provider | **Setup steps in Authentik:** 1. Go to **Applications → Providers → Create** and choose **OAuth2/OpenID Provider**. 2. Set **Client type** to `Confidential`. 3. Under **Redirect URIs**, add your Sloth Manager URL with a trailing slash, e.g. `https://slothmgmt.example.com/`. The trailing slash is required — Authentik does exact-match on redirect URIs. 4. Copy the **Client ID** and **Client Secret** into your `.env`. 5. Go to **Applications → Applications → Create**, select the provider, and note the **Slug**. 6. Set `AUTHENTIK_URL` to `https://your-authentik-host/application/o/`. SSO is disabled (and the button is hidden) when any of the three `AUTHENTIK_*` variables are missing. --- ## phpIPAM Import IP addresses and devices from a self-hosted [phpIPAM](https://phpipam.net/) instance (optional). When configured, the IPAM page gains a **Sync External** button and shows a phpIPAM source badge on synced entries. Addresses can be edited or deleted with write-back to phpIPAM. | Variable | Required | Description | |----------|----------|-------------| | `PHPIPAM_URL` | Yes | Base URL of your phpIPAM instance, e.g. `https://ipam.example.com` | | `PHPIPAM_APP_ID` | Yes | API application ID created in phpIPAM → Administration → API | | `PHPIPAM_TOKEN` | Yes | Static app token (token-based auth, no username/password needed) | **Setup steps in phpIPAM:** 1. Go to **Administration → phpIPAM Settings** and enable the REST API. 2. Go to **Administration → API** and click **+ Create API key**. 3. Set **App identifier** to any slug (e.g. `sloth-manager`), **App permissions** to `Read/Write`, and **App security** to `SSL with App code token`. 4. Copy the **App code** — this is your `PHPIPAM_TOKEN`. 5. Set `PHPIPAM_APP_ID` to the same slug you chose as the App identifier. phpIPAM integration is disabled when any of the three `PHPIPAM_*` variables are missing. --- ## Tailscale Import devices from a [Tailscale](https://tailscale.com/) tailnet (optional). When configured, the IPAM page shows devices with their Tailscale IPs. Devices can be authorized/de-authorized or removed from the tailnet directly from Sloth Manager. | Variable | Required | Description | |----------|----------|-------------| | `TAILSCALE_API_KEY` | Yes | API key generated at [tailscale.com/settings/keys](https://login.tailscale.com/admin/settings/keys) | | `TAILSCALE_TAILNET` | Yes | Tailnet name, e.g. `yourorg.github` — use `-` to target your default tailnet | **Setup steps:** 1. Go to **tailscale.com → Settings → Keys → Generate access token**. 2. Grant the token **Devices: Read** and **Devices: Write** (write is needed for authorize and delete actions). 3. Set `TAILSCALE_TAILNET` to your tailnet name (visible in the Admin console URL: `login.tailscale.com/admin/machines/`), or use `-` for the default. Tailscale integration is disabled when either variable is missing. --- ## Authentication | Variable | Required | Description | |----------|----------|-------------| | `JWT_SECRET` | Yes | A long random string used to sign login tokens. Generate one with: `node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"` | | `JWT_EXPIRES_IN` | No | How long login sessions last. Defaults to `24h`. Accepts values like `12h`, `7d`. | --- ## General | Variable | Required | Description | |----------|----------|-------------| | `DISABLED_PROVIDERS` | No | Comma-separated list of provider IDs to hide from the app without removing credentials. Valid values: `cloudflare`, `loopia`, `pihole`, `azure`, `cpanel`. Example: `DISABLED_PROVIDERS=loopia,cpanel` | | `PORT` | No | Port the backend listens on. Defaults to `3001`. | | `DB_PATH` | No | Path to the DNS record cache file. Defaults to `backend/dns-cache.json`. | | `SETTINGS_PATH` | No | Path to the settings file. Defaults to `backend/settings.json`. | | `USERS_PATH` | No | Path to the users file. Defaults to `backend/users.json`. | | `AUDIT_PATH` | No | Path to the audit log file. Defaults to `backend/audit-log.json`. | --- ## Example ```env # Cloudflare CLOUDFLARE_API_TOKEN=your_token_here # Loopia LOOPIA_USER=youruser@loopiaapi LOOPIA_PASSWORD=yourpassword # Pi-hole (v6) PIHOLE_URL=http://192.168.1.10 PIHOLE_PASSWORD=yourpassword # Azure DNS AZURE_TENANT_ID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx AZURE_CLIENT_ID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx AZURE_CLIENT_SECRET=your_secret AZURE_SUBSCRIPTION_ID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx # cPanel CPANEL_URL=https://hostname:2083 CPANEL_USERNAME=myuser CPANEL_API_TOKEN=your_token CPANEL_INSECURE=false # Authentik SSO (optional) AUTHENTIK_URL=https://auth.example.com/application/o/sloth-manager AUTHENTIK_CLIENT_ID=your_client_id AUTHENTIK_CLIENT_SECRET=your_client_secret # phpIPAM (optional) PHPIPAM_URL=https://ipam.example.com PHPIPAM_APP_ID=sloth-manager PHPIPAM_TOKEN=your_app_token # Tailscale (optional) TAILSCALE_API_KEY=tskey-api-xxxxxxxxxxxxxxxx TAILSCALE_TAILNET=yourorg.github # Auth JWT_SECRET=your-long-random-secret-here JWT_EXPIRES_IN=24h # Disable specific providers DISABLED_PROVIDERS= PORT=3001 ```