Configuration
YAML, one file. Edit and run /georestrict reload — no restart needed.
The full file
This is what gets written the first time the plugin runs.
plugins/GeoRestrict/config.yml
# Schema version. Bumped by us when the file layout changes.
configVersion: 4
# ---- Lookup gateway ----
gatewayUrl: "https://geoprotect.demonzdevelopment-e64.workers.dev/"
gatewayToken: ""
directFallbackEnabled: false
blockOnLookupFailure: true
lookupThreads: 4
maxCacheEntries: 100000
# ---- Country ----
countryMode: BLOCKLIST # ALLOWLIST | BLOCKLIST | DISABLED
countries:
- CN
- RU
- KP
- IR
# ---- ASN ----
asnMode: DISABLED # ALLOWLIST | BLOCKLIST | DISABLED
asns: []
# ---- VPN detection ----
vpnCheckEnabled: true
vpnKeywords:
- "vpn"
- "nordvpn"
- "expressvpn"
- "protonvpn"
- "mullvad"
- "shadowsocks"
- "wireguard"
- "digitalocean"
- "ovh sas"
- "hetzner"
- "amazon aws"
- "google cloud"
- "tor exit"
- "exit node"
# ---- Kick messages ----
kickMessageCountry: "Your country is not allowed on this server."
kickMessageAsn: "Your ISP/ASN is not allowed on this server."
kickMessageVpn: "VPN or proxy connections are not allowed."
kickMessageLookupFailure: "Geo verification is temporarily unavailable. Please try again later."
# ---- Cache & network ----
cacheTtlDays: 30
updateCheck: true
connectionTimeoutMs: 3000
# ---- Discord ----
discord:
webhook: ""
maskIp: true
logAllowed: false
logDenied: true
title: "GeoRestrict"
colorAllowed: 65280
colorDenied: 16711680
fields:
- { name: "Player", value: "%player%", inline: true }
- { name: "Status", value: "%status%", inline: true }
- { name: "IP", value: "%ip%", inline: true }
- { name: "Country", value: "%country%", inline: true }
- { name: "ASN", value: "%asn%", inline: true }
- { name: "ISP", value: "%isp%", inline: false }
- { name: "Reason", value: "%reason%", inline: false }
Every key, one by one
| Key | Type | Default | Notes |
|---|---|---|---|
configVersion | int | 4 | Schema version. Bumped when file layout changes. Don't edit. |
gatewayUrl | URL | public Worker | Where lookups go. Auto-prefixed with https:// if you forget. |
gatewayToken | string | "" | Bearer token for the Worker. Required when the Worker has tokens configured. |
directFallbackEnabled | bool | false | Hit an upstream provider directly if the Worker is down. Privacy: the IP leaves your server without the gateway's token. |
blockOnLookupFailure | bool | true | When every lookup path fails, block. Recommended. Flip to false if you prefer fail-open. |
lookupThreads | int 1–32 | 4 | Background threads for HTTP calls and webhook delivery. |
maxCacheEntries | int | 100000 | Hard cap. Oldest entries are evicted past this. 0 = no cap. |
countryMode | enum | BLOCKLIST | ALLOWLIST / BLOCKLIST / DISABLED. |
countries | list | CN, RU, KP, IR | ISO-3166 alpha-2. Case is normalized. |
asnMode | enum | DISABLED | ALLOWLIST / BLOCKLIST / DISABLED. Auto-disables if asns is empty. |
asns | list | [] | AS numbers, e.g. AS16276. With or without prefix is fine. |
vpnCheckEnabled | bool | true | Enable ISP keyword + boolean flag checks. |
vpnKeywords | list | ~80 strings | Matched case-insensitive against the ISP/AS name. Be careful — overly broad terms cause false positives on legit ISPs. |
kickMessageCountry | string | — | Shown to players blocked by country. |
kickMessageAsn | string | — | Shown to players blocked by ASN. |
kickMessageVpn | string | — | Shown to players blocked by VPN/hosting detection. |
kickMessageLookupFailure | string | — | Shown when blockOnLookupFailure: true and lookup failed. |
cacheTtlDays | int 1–365 | 30 | How long a cached lookup is trusted. |
updateCheck | bool | true | Hits Modrinth every 6h, logs when a new version is out. |
connectionTimeoutMs | int | 3000 | HTTP timeout for both the Worker and direct fallback. |
discord.webhook | URL | "" | Empty = no notifications. Use a private webhook URL. |
discord.maskIp | bool | true | Show 1.2.x.x instead of the full IPv4. |
discord.logAllowed | bool | false | Webhook on every allow. This can be high-volume on an active server. |
discord.logDenied | bool | true | Webhook on every deny. |
discord.title | string | — | Embed title. |
discord.colorAllowed | int | 65280 | Decimal RGB. Green by default. |
discord.colorDenied | int | 16711680 | Decimal RGB. Red by default. |
discord.fields | list | 7 default | Embed fields. Placeholders: %player%, %status%, %ip%, %country%, %asn%, %isp%, %reason%. |
Migrating old configs
If your configVersion is older than the bundled one, the plugin merges the bundled defaults into your file on next load. Your values win. New keys are added in-place rather than appended at the bottom of the file. The result is re-written and configVersion is bumped. A log line tells you it happened.
Back up your config before upgrading. Auto-migration is one-way. If you've heavily customized
vpnKeywords or Discord field names, double-check after the first restart.