A small Bun and Hono service for public Minecraft Bedrock status checks, internal server ownership verification, and isolated project artifact validation.
- Bedrock status queries over native RakNet UDP ping
- DNS TXT and Bedrock MOTD ownership verification
- Private and reserved network blocking before outbound UDP traffic
- Bounded ports, timeouts, concurrency, request bodies, and request rates
- API-key protection for internal verification routes
- Conservative detection of default or explicitly branded Geyser responses
- Java status and SRV correlation for customized Geyser proxies
- Private validation of Bedrock packs, worlds, skins, and Blockbench models
bun install
cp .env.example .env
bun run dev
bun run dev:workerThe API and Convex deployment must share the same secret:
- API:
API_SECRET_KEY - Convex:
BEDROCKNEXUS_API_KEY
Convex may also set:
BEDROCKNEXUS_API_URLfor status checksSERVER_VERIFICATION_API_URLfor ownership verification
bun run lint
bun run typecheck
bun run test
bun run dev
bun run dev:workerQuery a public Bedrock server.
Query parameters:
iprequired: public server hostname or IP addressportoptional:1-65535, default19132timeoutoptional:1000-8000milliseconds, default8000
{
"online": true,
"players": { "online": 10, "max": 100 },
"motd": "Welcome to My Server",
"version": "1.21.80",
"gamemode": "Survival",
"latencyMs": 42,
"software": {
"classification": "native_bedrock",
"javaEndpoints": [],
"reasons": ["No Java status endpoint was detected"]
}
}Private, loopback, link-local, reserved, and mixed public/private DNS targets are rejected.
Internal endpoints require:
X-API-Key: your-secret-keyGenerate an ownership verification code.
{ "code": "A1B2C3D4" }The token placed in DNS or the MOTD is:
bedrocknexus-verify=A1B2C3D4
DNS request:
{
"host": "play.example.com",
"code": "A1B2C3D4",
"method": "dns_txt",
"port": 19132
}MOTD request:
{
"host": "play.example.com",
"port": 19132,
"code": "A1B2C3D4",
"method": "motd_token"
}DNS verification requires an exact TXT value matching the token. MOTD verification checks both Bedrock MOTD lines on the exact host and port. Both methods also require the Bedrock server to be online and classified as native Bedrock.
{ "verified": true }This endpoint is exposed only by the validator worker and requires the API key. It accepts a short-lived R2 URL plus the expected project type, file name, and file size. The response contains either a sanitized validation report or a stable rejection code.
The worker rejects non-HTTPS and non-allowlisted download hosts, archive path traversal, duplicate or encrypted entries, unsafe expansion ratios, malformed pack manifests, invalid Bedrock worlds, non-64x64 or animated skins, and Blockbench models with external textures.
Deploy the same image as a second service and override its command:
bun run start:workerSet PORT to the service port, use the same API_SECRET_KEY as Convex, and set
ARTIFACT_ALLOWED_HOSTS to the exact hostname used by your R2 signed URLs, for
example:
your-bucket-id.r2.cloudflarestorage.com
Do not expose the validator endpoint through the public status API service.
Geyser intentionally builds a normal Bedrock pong and can replace or pass through both MOTD lines. The ping protocol exposes no mandatory Geyser software identifier.
The API combines several signals:
- Geyser default or explicit MOTD branding
- Java status responses on the same hostname and Bedrock port
- Java status responses on port
25565 _minecraft._tcpSRV targets- MOTD similarity
- Synchronized player counts and matching capacity
- Java proxy signatures such as Velocity, BungeeCord, and Waterfall
The result is native_bedrock, geyser_likely, or ambiguous. Automatic ownership verification accepts only native_bedrock. This catches customized networks such as Complex Gaming without treating every hostname that offers Java Edition as definite Geyser.
| Variable | Description | Default |
|---|---|---|
PORT |
API listening port | 3001 |
API_SECRET_KEY |
Required production key for internal routes | none |
CORS_ORIGINS |
Comma-separated browser origins | * |
TRUST_PROXY_HEADERS |
Trust proxy-replaced client IP headers | false |
GENERAL_RATE_LIMIT |
General requests per minute per key | 60 |
STATUS_RATE_LIMIT |
Status requests per minute per key | 30 |
MAX_CONCURRENT_STATUS_CHECKS |
Simultaneous UDP checks per instance | 25 |
ARTIFACT_ALLOWED_HOSTS |
Exact comma-separated R2 hosts accepted by the validator worker | none |
Rate limits use an in-memory store per API instance. Use a shared store before horizontally scaling the API.
Read CONTRIBUTING.md before opening a pull request. Report security vulnerabilities privately by following SECURITY.md, not through a public issue.
BedrockNexus API is available under the MIT License.