# zapiska configuration # Copy this file to .env and set the required values. # ADMIN_TOKEN is the only required variable. # # Docker quick start: # cp .env.example .env # docker compose up -d # Required ADMIN_TOKEN="change-me-to-a-random-secret" # Identity and networking # Set these values to the origin and public origin of your site. BIND_ADDR=127.0.0.1:3000 PUBLIC_TARGET_ORIGIN=https://nithitsuki.com # Use one origin, a comma-separated list, or *. # The value * is for local testing only. ALLOWED_CORS_ORIGIN=https://nithitsuki.com # SQLite file path. Docker uses /data/comments.db. DATABASE_PATH=./comments.db # Run PRAGMA quick_check at startup and refuse to start on corruption. # Set to false only to bypass the gate for recovery. DB_QUICK_CHECK=true # GitHub enrichment # A token raises the anonymous GitHub API limit from 60 to 5000 requests/hour. # GITHUB_TOKEN=ghp_your_pat # Limits and worker settings MAX_CONTENT_LEN=2000 MAX_AUTHOR_LEN=100 MAX_BODY_SIZE=8192 FETCH_TIMEOUT_MS=4000 WORKER_BACKLOG=64 # Rate limits. Each burst uses a per-IP governor. RATE_LIMIT_NATIVE=100 RATE_LIMIT_NATIVE_WINDOW=60 RATE_LIMIT_WEBMENTION=60 RATE_LIMIT_WEBMENTION_WINDOW=60 RATE_LIMIT_READ=300 RATE_LIMIT_READ_WINDOW=60 RATE_LIMIT_ADMIN_MODERATE=30 RATE_LIMIT_ADMIN_MODERATE_WINDOW=60 # Reverse proxy client-IP handling. Default false ignores X-Forwarded-For, # X-Real-IP, and Forwarded (spoof-proof: per-IP limits see the proxy peer). # Set true only when EVERYTHING arrives via a proxy you control (Cloudflare # proxy/Tunnel, or a firewall allow-listing Cloudflare IPs) — then the edge-set # CF-Connecting-IP wins when present, else leftmost X-Forwarded-For. A client # that can reach the origin directly can set these headers itself, including # CF-Connecting-IP. Append-only forwarding lets any client spoof another # client's identity and quota. See the reverse-proxy section in # docs/deployment.md. TRUST_PROXY=false # Spam protection # Trap field name: 1-64 chars of [A-Za-z0-9_-] (anything else refuses boot). # The served widget emits the configured name automatically; custom forms # must use it. The current native form uses the field name website. # HONEYPOT_FIELD=website MAX_COMMENTS_PER_IP_PER_DAY=50 MAX_WEBMENTIONS_PER_DOMAIN_PER_HOUR=10 # When true, zapiska stores the raw submitter IP and a SHA-256 hash. # The raw value is needed for direct admin IP lookup. STORE_IP_ADDRESS=false # IP_HASH_SECRET= # Moderation DEFAULT_COMMENT_STATUS=pending # MODERATION_WEBHOOK_URL=http://localhost:9000/webhook MODERATION_WEBHOOK_MODE=async # Optional HMAC secret: when set, every webhook payload carries # X-Zapiska-Timestamp and X-Zapiska-Signature headers so the moderation # service can verify authenticity and freshness. Empty = unsigned. # WEBHOOK_SIGNING_SECRET= # Admin dashboard: open /admin on the server host and sign in with # ADMIN_TOKEN. The session cookie is __Host-admin_token (Secure), so the # dashboard requires HTTPS. # Notifications # Telegram needs both variables. # TELEGRAM_BOT_TOKEN= # TELEGRAM_CHAT_ID= TELEGRAM_API_BASE=https://api.telegram.org # SLACK_WEBHOOK_URL= # DISCORD_WEBHOOK_URL= # Notification batching # Set NOTIFY_BATCH_SECS=0 for immediate delivery. NOTIFY_BATCH_SECS=60 NOTIFY_BATCH_THRESHOLD=20 NOTIFY_BATCH_GRANULARITY=page # Reactions # Values: admin or anyone. Admin is the safe default. REACTIONS_ALLOWED=admin # REACTIONS_SET=👍,❤️,😄,😮,😢,😡 # Language filtering # Values use ISO 639-1 codes. # COMMENT_LANG_ALLOWED=en,de,ja # COMMENT_LANG_BLOCKED= # Values: always, never, or if_unknown. COMMENT_LANG_ALLOW_EMOJI=always # Threaded replies # Zero disables replies. The server clamps this value to 0 through 10. MAX_THREAD_DEPTH=0 # Cloudflare Turnstile TURNSTILE_ENABLED=false # TURNSTILE_SECRET_KEY= TURNSTILE_VERIFY_URL=https://challenges.cloudflare.com/turnstile/v0/siteverify # Logging RUST_LOG=info