# PoracleWeb.NET Configuration # This file works for both Docker and standalone mode. # Copy to .env and fill in your values: cp .env.example .env # Or run: ./scripts/setup.sh # ═══════════════════════════════════════════════════════════════════════════════ # PORT # ═══════════════════════════════════════════════════════════════════════════════ # The port PoracleWeb.NET listens on PORT=8082 # ═══════════════════════════════════════════════════════════════════════════════ # DATABASE — Poracle (your existing PoracleJS database) # ═══════════════════════════════════════════════════════════════════════════════ # Docker: use host.docker.internal if DB is on the host machine # Standalone: use localhost or your DB server's IP DB_HOST=localhost DB_PORT=3306 DB_NAME=poracle DB_USER=root DB_PASSWORD=your_db_password # ═══════════════════════════════════════════════════════════════════════════════ # DATABASE — PoracleWeb.NET (separate database for app-owned data) # ═══════════════════════════════════════════════════════════════════════════════ # This is NOT the Poracle DB — it stores user geofences, settings, etc. # Create it manually: CREATE DATABASE poracle_web; — tables are auto-created on startup. WEB_DB_HOST=localhost WEB_DB_PORT=3306 WEB_DB_NAME=poracle_web WEB_DB_USER=root WEB_DB_PASSWORD=your_db_password # ═══════════════════════════════════════════════════════════════════════════════ # SCANNER DATABASE (optional — Golbat, for gym picker in raid/egg dialogs) # ═══════════════════════════════════════════════════════════════════════════════ # SCANNER_DB_CONNECTION=Server=localhost;Port=3306;Database=golbat;User=root;Password=your_password # ═══════════════════════════════════════════════════════════════════════════════ # GOLBAT API (optional — enables "currently spawning" Pokemon indicators) # ═══════════════════════════════════════════════════════════════════════════════ # GOLBAT_API_ADDRESS=http://localhost:9001 # GOLBAT_API_SECRET=your_golbat_secret # ═══════════════════════════════════════════════════════════════════════════════ # JWT — Authentication token signing # ═══════════════════════════════════════════════════════════════════════════════ # Minimum 32 characters. Generate one: openssl rand -base64 48 JWT_SECRET=generate-a-long-random-secret-key-at-least-32-chars # Optional — defaults are fine for most users. Override if you need distinct token identities # or to preserve tokens from a previous install (changing these invalidates all existing JWTs # and logs every user out once). JWT_ISSUER=PoracleWeb JWT_AUDIENCE=PoracleWeb.App # ═══════════════════════════════════════════════════════════════════════════════ # DISCORD — OAuth2 login # ═══════════════════════════════════════════════════════════════════════════════ # Create an app at https://discord.com/developers/applications # Set redirect URI: http://your-host:PORT/api/auth/discord/callback DISCORD_CLIENT_ID=your_discord_client_id DISCORD_CLIENT_SECRET=your_discord_client_secret DISCORD_BOT_TOKEN=your_discord_bot_token # Discord guild ID (optional — used for role checks) # DISCORD_GUILD_ID= # Forum channel for geofence submission threads (optional) # DISCORD_GEOFENCE_FORUM_CHANNEL_ID= # Public URL where users reach this site, no trailing slash (optional). # Used to link geofence review threads straight to the admin review page. # The link is omitted when this is unset. # PUBLIC_URL=https://alerts.example.com # ═══════════════════════════════════════════════════════════════════════════════ # TELEGRAM (optional) # ═══════════════════════════════════════════════════════════════════════════════ TELEGRAM_ENABLED=false # TELEGRAM_BOT_TOKEN= # TELEGRAM_BOT_USERNAME= # ═══════════════════════════════════════════════════════════════════════════════ # EXTERNAL SSO / OIDC (optional — delegate login to your own OAuth2/OIDC provider) # ═══════════════════════════════════════════════════════════════════════════════ # Point PoracleWeb at any OAuth2/OIDC provider (Keycloak, Authentik, Auth0, Okta, …) for SSO. # The provider's userinfo endpoint must return a claim holding the user's Poracle id # (a Discord/Telegram id) — set OIDC_IDENTITY_CLAIM to that claim name. # Enabled is auto-inferred when ClientId + the three URLs are all set; set explicitly to override. # Replace the example URLs below with your provider's actual endpoints. # OIDC_ENABLED=true # OIDC_PROVIDER_NAME=My SSO # OIDC_AUTHORIZATION_URL=https://sso.example.com/authorize # OIDC_TOKEN_URL=https://sso.example.com/oauth/token # OIDC_USERINFO_URL=https://sso.example.com/oauth/userinfo # OIDC_CLIENT_ID=your_oidc_client_id # OIDC_CLIENT_SECRET=your_oidc_client_secret # OIDC_SCOPES=openid profile email # OIDC_IDENTITY_CLAIM=discord_id # OIDC_USERNAME_CLAIM=preferred_username # OIDC_AVATAR_CLAIM=picture # OIDC_IDENTITY_TYPE=discord:user # OIDC_USE_PKCE=true # # --- Refresh tokens (optional, opt-in) — silent session renewal + revocation propagation --- # When OFF (default) the provider's tokens are discarded after login and the internal session # JWT lives its full Jwt:ExpirationMinutes (24h); users re-auth at expiry. When ON, PoracleWeb # brokers the provider's refresh token SERVER-SIDE (encrypted at rest, never sent to the browser), # silently renews the session, and propagates provider-side disable/logout. Requires the provider # to actually issue a refresh token. Fully provider-agnostic — see docs/configuration/oidc-refresh-tokens.md. # OIDC_USE_REFRESH_TOKENS=true # OIDC_ACCESS_TOKEN_MINUTES=30 # internal JWT lifetime for refresh-backed OIDC sessions only # OIDC_REFRESH_TOKEN_LIFETIME_DAYS=30 # PoracleWeb-side absolute session cap before a real re-login # OIDC_SESSION_REVOKED_RETENTION_DAYS=2 # how long revoked/rotated session rows are kept (replay detection) before cleanup deletes them # OIDC_OFFLINE_ACCESS_SCOPE=offline_access # appended to the authorize scope so the provider issues an RT; empty to disable # OIDC_TOKEN_AUTH_METHOD=client_secret_post # client_secret_post (body) | client_secret_basic (HTTP Basic) # # Per-provider notes (token auth method / offline scope / identity claim): # PogoAlerts : OIDC_OFFLINE_ACCESS_SCOPE=offline_access OIDC_TOKEN_AUTH_METHOD=client_secret_post OIDC_IDENTITY_CLAIM=discord_id # Keycloak : OIDC_OFFLINE_ACCESS_SCOPE=offline_access OIDC_TOKEN_AUTH_METHOD=client_secret_basic OIDC_IDENTITY_CLAIM=sub # Authentik : OIDC_OFFLINE_ACCESS_SCOPE=offline_access OIDC_TOKEN_AUTH_METHOD=client_secret_post OIDC_IDENTITY_CLAIM=sub # Auth0 : OIDC_OFFLINE_ACCESS_SCOPE=offline_access OIDC_TOKEN_AUTH_METHOD=client_secret_post OIDC_IDENTITY_CLAIM=sub # Okta : OIDC_OFFLINE_ACCESS_SCOPE=offline_access OIDC_TOKEN_AUTH_METHOD=client_secret_basic OIDC_IDENTITY_CLAIM=sub # Azure/Entra: OIDC_OFFLINE_ACCESS_SCOPE=offline_access OIDC_TOKEN_AUTH_METHOD=client_secret_post OIDC_IDENTITY_CLAIM=sub # Google : OIDC_OFFLINE_ACCESS_SCOPE= (empty) and append ?access_type=offline to OIDC_AUTHORIZATION_URL # ═══════════════════════════════════════════════════════════════════════════════ # PORACLE API — your running PoracleNG instance # ═══════════════════════════════════════════════════════════════════════════════ # This is how PoracleWeb.NET talks to Poracle. Must be reachable from wherever PoracleWeb.NET runs. PORACLE_API_ADDRESS=http://localhost:3030 PORACLE_API_SECRET=your_poracle_api_secret # Comma-separated Discord/Telegram user IDs for admin access PORACLE_ADMIN_IDS=your_discord_user_id # ═══════════════════════════════════════════════════════════════════════════════ # KOJI — Geofence API (required for custom geofences feature) # ═══════════════════════════════════════════════════════════════════════════════ # Used for: fetching regions, promoting approved geofences to public areas. # PoracleWeb.NET serves ALL geofences (admin from Koji + user from DB) via /api/geofence-feed. KOJI_API_ADDRESS=http://localhost:8080 KOJI_BEARER_TOKEN=your_koji_bearer_token KOJI_PROJECT_ID=1 KOJI_PROJECT_NAME=YourProjectName # ═══════════════════════════════════════════════════════════════════════════════ # CORS — required in production # ═══════════════════════════════════════════════════════════════════════════════ # Set to the URL you access PoracleWeb.NET from. Not required in development mode. # CORS_ORIGIN=http://192.168.1.50:8082 # ═══════════════════════════════════════════════════════════════════════════════ # PUBLIC URL — the address users reach this instance on # ═══════════════════════════════════════════════════════════════════════════════ # Sets the OAuth callback URLs (Discord and OIDC) outright instead of guessing them # from each incoming request. Set this if sign-in fails with an invalid redirect_uri, # or just set it anyway — it is the one value your identity provider must also have # registered, so stating it here keeps the two in step. # # Origin only: no trailing path, no query. A bad value stops the app at startup. # Leave it blank to keep the old behaviour of following the incoming request, which # is correct for a direct-exposed instance or one whose proxy is declared below. # PUBLIC_URL=https://poracle.example.com # ═══════════════════════════════════════════════════════════════════════════════ # REVERSE PROXY — required if anything sits in front of PoracleWeb.NET # ═══════════════════════════════════════════════════════════════════════════════ # Nginx, Caddy, Traefik, Cloudflare Tunnel and friends terminate TLS themselves and # announce the original request with X-Forwarded-For and X-Forwarded-Proto. Those # headers are only believed from addresses named here — a forgeable header would let # any caller hand itself a fresh rate-limit allowance on the sign-in endpoints. # # Leave both blank only if the app is exposed directly. Behind an undeclared proxy the # app sees every request as plain HTTP from the proxy's address, which means all users # share one rate-limit bucket AND OAuth callback URLs are built as http:// — Discord # and OIDC providers then reject the sign-in with "Invalid redirect_uri". (PUBLIC_URL # above fixes the sign-in on its own; only these settings fix the rate-limit bucket.) # # Comma-separated. Use the address the proxy connects FROM, as the container sees it. # PROXY_KNOWN_PROXIES=10.0.3.20 # PROXY_KNOWN_NETWORKS=172.18.0.0/16,10.0.0.0/8 # ═══════════════════════════════════════════════════════════════════════════════ # PORACLE CONFIG (optional — for DTS template previews) # ═══════════════════════════════════════════════════════════════════════════════ # Mount the PoracleJS config directory so DTS files are auto-loaded PORACLE_CONFIG_DIR=/path/to/PoracleJS/config