# define environment variables # interface and port for the server to listen on HOST=0.0.0.0 PORT=8000 # Security Configuration # IMPORTANT: Change this to a secure random string! # Generate with: python -c "import secrets; print(secrets.token_urlsafe(32))" ADMIN_API_KEY=CHANGE_ME_TO_SECURE_RANDOM_STRING # Rate Limiting Configuration # Maximum requests per minute from a single IP RATE_LIMIT_REQUESTS_PER_MINUTE=60 # Maximum requests per second from a single IP (burst protection) RATE_LIMIT_REQUESTS_PER_SECOND=10 # Ban Durations (in seconds) # Duration for rate limit violations BAN_DURATION_RATE_LIMIT=3600 # Duration for suspicious request patterns (/.env, /*.php, etc) BAN_DURATION_SUSPICIOUS=86400 # File Paths for Persistent Storage BANNED_IPS_FILE=data/banned_ips.json GEO_RULES_FILE=data/geo_rules.json # Hand-written per-IP overrides: trusted addresses (and whether they still pay # the rate limit) and addresses blocked outright. Re-read whenever the file # changes, so adding a bot is an edit rather than a redeploy. See SECURITY.md. IP_RULES_FILE=data/ip_rules.json # GeoIP City/ASN Databases (Optional) # City-level coordinates and the AS org/number overlay geoip2fast's country # data. By default both come from free jsdelivr mirrors of GeoLite2-City and # GeoLite2-ASN. Set both credentials below to use MaxMind's official licensed # databases instead (sign up free at https://www.maxmind.com/en/geolite2/signup); # on failure they fall back to the free mirrors automatically. # MAXMIND_ACCOUNT_ID=your_account_id # MAXMIND_LICENSE_KEY=your_license_key # Editions to download (defaults GeoLite2-City / GeoLite2-ASN) # MAXMIND_CITY_EDITION=GeoLite2-City # MAXMIND_ASN_EDITION=GeoLite2-ASN # Free mirror URLs, used when MaxMind credentials are not set. # GEOIP_CITY_DB_URL=https://cdn.jsdelivr.net/npm/geolite2-city/GeoLite2-City.mmdb.gz # GEOIP_ASN_DB_URL=https://cdn.jsdelivr.net/npm/geolite2-asn/GeoLite2-ASN.mmdb.gz # Public Suffix List (Mozilla), used to tell a real lookup target from a probe. # "/nasa.gov" has a public suffix and is answered; "/admin.php" has none, so it # is treated as a scan and banned. A stale list makes a newly delegated TLD read # as a probe, so the list is kept in the data volume and refreshed on a # schedule: seeded from the copy bundled with the `tld` package, pulled once on # first boot, then re-checked daily and re-fetched once older than the max age. # TLD_LIST_URL=https://publicsuffix.org/list/public_suffix_list.dat # TLD_NAMES_DIR=./data/tld # TLD_MAX_AGE_DAYS=14 # How soon to retry a failed refresh (seconds). # TLD_UPDATE_RETRY_SECONDS=3600 # Background Job Configuration # How often to clean up expired bans (seconds) CLEANUP_INTERVAL_SECONDS=300 # How often to clean up old rate limit records (seconds) RATE_LIMIT_CLEANUP_INTERVAL=60 # How soon to retry a failed GeoIP database refresh (seconds). The regular # refresh runs every 3 days; this keeps one failure from leaving stale or # bundled-fallback data in place for the whole interval. GEOIP_UPDATE_RETRY_SECONDS=3600 # Geographic Blocking Configuration (Optional) # Mode: disabled, allowlist, or blocklist # GEO_MODE=disabled # Comma-separated country codes to block (ISO 3166-1 alpha-2) # GEO_BLOCKED_COUNTRIES=CN,RU,KP,IR # Comma-separated country codes to allow (only used in allowlist mode) # GEO_ALLOWED_COUNTRIES=US,CA,GB,DE,JP # Block IPs from unknown/unresolved countries # GEO_BLOCK_UNKNOWN=false # Canonical public URL, used for the copyable curl example on the page. # Only needed when the reverse proxy does not forward x-forwarded-proto: without # it the example would say http://, the proxy would answer 302, and curl would # print "Found" instead of JSON. # PUBLIC_BASE_URL=https://ip.1kko.com # MCP (Model Context Protocol) Configuration # Set to false to drop the /mcp mount entirely (env change + restart, no deploy). MCP_ENABLED=true # Comma-separated Host headers the MCP transport will accept (DNS-rebinding guard). MCP_ALLOWED_HOSTS=ip.1kko.com,ip.1kko.com:* # Comma-separated Origin headers to accept; empty means requests with no Origin # header are still allowed (the normal case), but any Origin that's present must # match one of these or the request gets a 403. # MCP_ALLOWED_ORIGINS= # MCP's own rate-limit bucket, looser than the browser limit and never bans. MCP_RATE_LIMIT_PER_MINUTE=120 MCP_RATE_LIMIT_PER_SECOND=5 # Reject a POST /mcp body over this size (bytes) with 413, before it's read. MCP_MAX_BODY_BYTES=262144