# ============================================================================= # TrueVuln Environment Configuration # ============================================================================= # Copy this file to .env and adjust values before starting: # cp .env.example .env # # Designed to run behind a reverse proxy (Nginx Proxy Manager, Traefik, etc.) # with HTTPS termination at the proxy level. # ============================================================================= # --- Database --- POSTGRES_USER=vulnmanager POSTGRES_PASSWORD=changeme # Change this! POSTGRES_DB=vulnmanager POSTGRES_PORT=5432 # --- Application Ports --- # These are the internal Docker ports. Map them in your reverse proxy. BACKEND_PORT=8022 FRONTEND_PORT=3003 # --- Security (REQUIRED) --- # Generate with: openssl rand -hex 32 JWT_SECRET_KEY=CHANGE-ME-GENERATE-WITH-openssl-rand-hex-32 # --- Environment --- # 'production' disables Swagger docs and enables security headers. # 'development' enables Swagger UI at /docs and relaxes some checks. ENV=production # Expose Swagger UI (/docs) + ReDoc (/redoc) on a production instance without # switching to development — handy for ITSM/CMDB API integrators. Default off. # The raw OpenAPI spec (/openapi.json) is always served regardless. ENABLE_API_DOCS=false # --- Cookies --- # Set to true when using HTTPS (recommended, required behind HTTPS proxy) AUTH_COOKIE_SECURE=true AUTH_COOKIE_SAMESITE=lax # --- Reverse Proxy --- # Enable if running behind a reverse proxy to trust X-Forwarded-For headers # for correct client IP in rate limiting and audit logs. TRUST_PROXY_HEADERS=true # --- Default Admin Account --- # Created on first start only (if no admin exists in the database). # The password MUST satisfy strength rules (>=8 chars, upper, lower, digit, special), # otherwise the admin will NOT be created and login will be impossible. # Change the password immediately after first login. DEFAULT_ADMIN_USERNAME=admin DEFAULT_ADMIN_PASSWORD=ChangeMe123! DEFAULT_ADMIN_EMAIL=admin@vulnmanager.local # Set to true to skip default admin creation entirely # DISABLE_DEFAULT_ADMIN=false # --- Emergency Admin Reset (optional) --- # Uncomment and set a token to enable the /auth/setup-admin endpoint. # SETUP_ADMIN_TOKEN=your-setup-token # ALLOW_ADMIN_RESET=false # --- Timezone --- TIMEZONE=Europe/Zurich # --- Dashboard URL --- # Base URL used to build ALL links in email notifications (dashboard button, # per-CVE / per-asset deep links, the CVE links inside the digest table). # The backend can't know how your browser reaches the frontend, so you MUST set # this to exactly how users open TrueVuln — otherwise links point at the # fallback http://localhost:3000 and won't work. # e.g. http://:${FRONTEND_PORT} or https://vuln.example.com behind a proxy # Set it, then restart the backend (docker compose up -d). DASHBOARD_URL=http://localhost:3003 # --- Microsoft Intune / Graph (optional) --- # Configured in the UI: Settings → "Microsoft Intune (Graph API)" card # (stored encrypted as the `intune_config` setting), NOT via env. Pulls # Intune managed devices → assets + OS-EOL. # App-only (client-credentials): register an Entra app, add the Application # permission DeviceManagementManagedDevices.Read.All, grant admin consent, # create a client secret. (Defender TVM phase: BOTH Machine.Read.All AND # Vulnerability.Read.All on WindowsDefenderATP — the /api/machines call # requires Machine.Read.All.) No env vars required. # --- NVD API key (optional, recommended) --- # Used to backfill each CVE's official published / lastModified date from # the NVD CVE API (drives the "Newly Published" dashboard widget sort). # Without a key NVD allows 5 requests / 30s; with one, 50 / 30s — so a # fresh database fills in published dates ~10x faster. Free, request at: # https://nvd.nist.gov/developers/request-an-api-key # NVD_API_KEY=your-nvd-api-key # --- VulnCheck KEV (optional) --- # Third "actively exploited" catalog next to CISA KEV and ENISA EUVD. Carries # ~5200 CVEs against CISA's ~1400 and usually lists them earlier; the KEV panel # shows the lead time per CVE. Free community account -> API token at # https://console.vulncheck.com/ # Free for commercial use as long as "VulnCheck KEV" stays attributed in the # UI (the Advisories page does that automatically). # Without a token the source stays silent and nothing changes. # VULNCHECK_API_TOKEN=vulncheck_... # # To also alert on it, add "vulncheck" to the kev_alert_sources setting # (default "cisa,euvd" — opting in is deliberate, it is ~4x the CVEs). # --- OpenRouter AI remediation (optional) --- # Enables the "AI Remediation" button on the CVE detail page — generates # OS-aware fix steps/commands on demand. OpenAI-compatible; get a key at # https://openrouter.ai/keys (free tier ~10 req/day across free models). # Without a key the feature stays hidden. # OPENROUTER_API_KEY=sk-or-... # Model slug (OpenRouter uses dots, e.g. anthropic/claude-sonnet-4.6). # Default openrouter/free auto-routes across available free models. # OPENROUTER_MODEL=openrouter/free # Optional comma-separated fallback models (route=fallback): # OPENROUTER_FALLBACKS=openrouter/auto,anthropic/claude-sonnet-4.6 # ============================================================================= # Multi-Provider Authentication (LDAP / OIDC / SAML / TOTP-MFA) # ============================================================================= # Default config = local only (backwards compatible). Enable providers # below by listing them in AUTH_PROVIDERS and filling in the matching block. # ============================================================================= # Comma-separated list of enabled providers. Local is always recommended # as fallback for emergency admin access. AUTH_PROVIDERS=local # AUTH_PROVIDERS=local,ldap,oidc,saml # Order in which credential-based providers are tried for username/password # login. SSO providers (saml/oidc) are not in this chain — they have their # own redirect endpoints. AUTH_LOOKUP_ORDER=local,ldap # Auto-create local user stub on first SSO/LDAP login. Re-evaluates role # from external groups on every subsequent login. AUTH_JIT_PROVISIONING=true # Fallback role when no group-mapping rule matches. # Values: admin, editor, readonly AUTH_JIT_DEFAULT_ROLE=readonly # Fernet key for encrypting LDAP bind-pw and TOTP secrets at rest. # Generate with: # python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())" # CHANGE THIS — losing the key invalidates all stored TOTP secrets. AUTH_PROVIDER_CRYPTO_KEY=CHANGE-ME-FERNET-KEY # ----------------------------------------------------------------------------- # LDAPS (Active Directory by default) # ----------------------------------------------------------------------------- LDAP_HOST=ldaps.company.internal LDAP_PORT=636 LDAP_USE_SSL=true LDAP_USE_STARTTLS=false # mutually exclusive with USE_SSL # CA bundle that signed the LDAPS server cert (required for strict validation). LDAP_CA_CERT_PATH=/etc/ssl/certs/company-ca.pem LDAP_VALIDATE_CERT=true # NEVER set to false in production # Service account for the search-then-bind flow. LDAP_BIND_DN=cn=svc-truevuln,ou=ServiceAccounts,dc=company,dc=local # Bootstrap password — loaded once, encrypted, stored in DB. # Remove from env AFTER the first successful start. LDAP_BIND_PASSWORD_BOOTSTRAP= # User search LDAP_USER_SEARCH_BASE=ou=Users,dc=company,dc=local # {username} is replaced by the login form input (filter-escaped). LDAP_USER_SEARCH_FILTER=(&(objectClass=user)(sAMAccountName={username})) LDAP_USER_ATTR_USERNAME=sAMAccountName LDAP_USER_ATTR_EMAIL=mail LDAP_USER_ATTR_GROUPS=memberOf LDAP_USER_ATTR_GUID=objectGUID # AD stable identifier LDAP_USER_ATTR_DISPLAY=displayName # ----------------------------------------------------------------------------- # OIDC (OpenID Connect) — Entra ID / Okta / Keycloak / Google # ----------------------------------------------------------------------------- OIDC_PROVIDER_NAME=Entra ID # Examples: # Entra ID: https://login.microsoftonline.com//v2.0/.well-known/openid-configuration # Okta: https:///.well-known/openid-configuration # Keycloak: https://kc.company.com/realms//.well-known/openid-configuration # Google: https://accounts.google.com/.well-known/openid-configuration OIDC_DISCOVERY_URL= OIDC_CLIENT_ID= OIDC_CLIENT_SECRET= OIDC_REDIRECT_URI=https://truevuln.company.com/auth/oidc/callback OIDC_SCOPES=openid profile email groups # Claim names — defaults work for Entra ID / Keycloak. Adjust per IdP. OIDC_CLAIM_USERNAME=preferred_username OIDC_CLAIM_EMAIL=email OIDC_CLAIM_GROUPS=groups OIDC_CLAIM_DISPLAY=name OIDC_CLAIM_SUBJECT=sub # ----------------------------------------------------------------------------- # SAML 2.0 # ----------------------------------------------------------------------------- SAML_PROVIDER_NAME=Single Sign-On SAML_SP_ENTITY_ID=https://truevuln.company.com/auth/saml/metadata SAML_SP_ACS_URL=https://truevuln.company.com/auth/saml/acs SAML_SP_SLO_URL=https://truevuln.company.com/auth/saml/slo # SP cert + key — generate a keypair specifically for this SP: # openssl req -x509 -newkey rsa:2048 -nodes \ # -keyout sp.key -out sp.crt -days 730 \ # -subj "/CN=truevuln.company.com" SAML_SP_CERT_PATH=/etc/truevuln/saml/sp.crt SAML_SP_PRIVATE_KEY_PATH=/etc/truevuln/saml/sp.key # IdP metadata source — exactly one of: SAML_IDP_METADATA_URL= # SAML_IDP_METADATA_PATH=/etc/truevuln/saml/idp-metadata.xml # Attribute mapping (defaults work for most IdPs) SAML_ATTR_USERNAME=urn:oid:0.9.2342.19200300.100.1.1 SAML_ATTR_EMAIL=urn:oid:1.2.840.113549.1.9.1 SAML_ATTR_GROUPS=http://schemas.xmlsoap.org/claims/Group SAML_ATTR_DISPLAY=urn:oid:2.16.840.1.113730.3.1.241