|
| 1 | +# NitroCraft Pterodactyl Egg |
| 2 | + |
| 3 | +This guide covers the quickest way to self-host NitroCraft with the included egg: |
| 4 | + |
| 5 | +- Egg file: `egg-nitrocraft.json` |
| 6 | +- Runtime image: `docker.io/repgraphics/nitrocraft:latest` |
| 7 | + |
| 8 | +## What This Egg Does |
| 9 | + |
| 10 | +- Runs NitroCraft on your server allocation port automatically. |
| 11 | +- Creates required image cache folders: |
| 12 | + - `images/faces` |
| 13 | + - `images/helms` |
| 14 | + - `images/skins` |
| 15 | + - `images/renders` |
| 16 | + - `images/capes` |
| 17 | +- Supports Redis cache or memory cache. |
| 18 | +- If `CACHE_BACKEND=redis` but `REDIS_URL` is empty, it safely falls back to `memory`. |
| 19 | +- Boots from `/home/container/.output` when available, otherwise uses the app bundled in the Docker image. |
| 20 | + |
| 21 | +## Quick Setup (Recommended) |
| 22 | + |
| 23 | +1. In Pterodactyl Admin, import [`egg-nitrocraft.json`](./egg-nitrocraft.json). |
| 24 | +2. Create a new server using the NitroCraft egg. |
| 25 | +3. Keep the default startup command. |
| 26 | +4. Set these variables first: |
| 27 | + - `EXTERNAL_URL=https://your-domain.example` |
| 28 | + - `CORS_ORIGIN=https://your-frontend.example` (or `All` for public/open use) |
| 29 | + - `CACHE_BACKEND=memory` (or `redis`) |
| 30 | + - `REDIS_URL=redis://host:6379` (required only when using Redis) |
| 31 | +5. Start the server and wait for log output containing: |
| 32 | + - `Listening on http://` |
| 33 | +6. Open your service URL and test: |
| 34 | + - `/avatars/d634462bd663401d9788a8596307bc4d?size=160&overlay` |
| 35 | + - `/metrics` |
| 36 | + |
| 37 | +## Important Variables |
| 38 | + |
| 39 | +Use these first for a stable production setup: |
| 40 | + |
| 41 | +- `EXTERNAL_URL`: public base URL for NitroCraft. |
| 42 | +- `BIND`: keep `0.0.0.0`. |
| 43 | +- `PORT`: usually leave empty; the egg uses the allocation port automatically. |
| 44 | +- `CACHE_BACKEND`: `memory` or `redis`. |
| 45 | +- `REDIS_URL`: required if `CACHE_BACKEND=redis`. |
| 46 | +- `CACHE_LOCAL`: internal metadata cache TTL (seconds). |
| 47 | +- `CACHE_BROWSER`: browser cache TTL (seconds). |
| 48 | +- `REQUESTS_RATE_LIMIT`: inbound per-IP request limit (empty disables). |
| 49 | +- `REQUESTS_RATE_LIMIT_WINDOW_MS`: window for inbound limiter. |
| 50 | +- `REQUESTS_RATE_LIMIT_TRUST_PROXY`: keep `true` when behind a reverse proxy/CDN. |
| 51 | +- `REQUESTS_RATE_LIMIT_EXCLUDE`: optional comma-separated path prefixes to skip limiter. |
| 52 | +- `SESSIONS_RATE_LIMIT`: outbound Mojang API request rate cap. |
| 53 | +- `MAX_TEXTURE_BYTES`: max downloaded skin/cape payload size. |
| 54 | +- `RETENTION_ENABLED`: periodic cleanup of stale files/cache. |
| 55 | +- `RETENTION_DAYS` and `RETENTION_INTERVAL_HOURS`: cleanup age/interval. |
| 56 | + |
| 57 | +## Redis vs Memory |
| 58 | + |
| 59 | +- `memory`: |
| 60 | + - Easiest setup, no external dependency. |
| 61 | + - Best for single-instance deployments. |
| 62 | +- `redis`: |
| 63 | + - Better consistency across restarts and scaling scenarios. |
| 64 | + - Requires reachable Redis and valid `REDIS_URL`. |
| 65 | + |
| 66 | +If Redis is misconfigured, this egg logs a warning and runs with memory cache so the API still comes online. |
| 67 | + |
| 68 | +## Reverse Proxy Notes |
| 69 | + |
| 70 | +- Put NitroCraft behind Nginx/Caddy/Traefik (and optional Cloudflare) for TLS. |
| 71 | +- Forward standard headers (`X-Forwarded-For`, `X-Forwarded-Proto`, `Host`). |
| 72 | +- Keep `REQUESTS_RATE_LIMIT_TRUST_PROXY=true` when proxied, or client IP limits may be inaccurate. |
| 73 | + |
| 74 | +## Updating NitroCraft |
| 75 | + |
| 76 | +Choose one of these update strategies: |
| 77 | + |
| 78 | +- Image-first (recommended): |
| 79 | + 1. Pull/redeploy using `docker.io/repgraphics/nitrocraft:latest`. |
| 80 | + 2. Restart server. |
| 81 | +- Source-ref pinning: |
| 82 | + 1. Set `SOURCE_REPO` and `SOURCE_REF` (branch or tag). |
| 83 | + 2. Reinstall the server to refresh `/home/container` bootstrap content. |
| 84 | + |
| 85 | +## Data Persistence |
| 86 | + |
| 87 | +Keep server storage persistent so generated assets and counters survive restarts: |
| 88 | + |
| 89 | +- `images/faces/` |
| 90 | +- `images/helms/` |
| 91 | +- `images/skins/` |
| 92 | +- `images/renders/` |
| 93 | +- `images/capes/` |
| 94 | +- `data/` (if using file-backed counters/metrics settings) |
| 95 | + |
| 96 | +## Troubleshooting |
| 97 | + |
| 98 | +- `CACHE_BACKEND=redis but REDIS_URL is empty` warning: |
| 99 | + - Set `REDIS_URL`, or switch `CACHE_BACKEND=memory`. |
| 100 | +- API starts but you get blocked CORS in browser: |
| 101 | + - Set `CORS_ORIGIN` to your frontend origin(s), or `All`. |
| 102 | +- Users hit `429` too often: |
| 103 | + - Raise `REQUESTS_RATE_LIMIT`, increase window, or add route exclusions. |
| 104 | +- Slow or failing external lookups: |
| 105 | + - Increase `EXTERNAL_HTTP_TIMEOUT` (default `2000` ms). |
| 106 | + |
| 107 | +## Useful Endpoints |
| 108 | + |
| 109 | +- API docs/spec: `/openapi.json` |
| 110 | +- Prometheus metrics: `/metrics` |
| 111 | +- Live server-list tool: `/tools/server-list` |
| 112 | +- API call count endpoint: `/metrics/api-calls` |
0 commit comments