Minecraft 26.2 Fabric server stack with CraftDeck management panel

- docker-compose: itzg/minecraft-server (Fabric, offline mode, whitelist
  enforced, Modrinth-managed mods), itzg/mc-backup sidecar, custom dashboard
- Gated auth for offline mode: approve username -> whitelisted with a short
  registration window -> EasyAuth /register + /login; auto-revoke on expiry
- CraftDeck panel (Next.js 16, zero native deps): live console (SSE), players
  & stats, lag diagnostics (server TPS vs player ping via spark), performance
  graphs, Modrinth mod search/manager, backups & restore, sandboxed file
  browser/editor, .env config editor with compose apply, cron schedules,
  Discord alerts, scrypt-hashed panel login
- scripts/setup.sh generates secrets; docs/ covers auth, mods, updating,
  backups, networking (Tailscale), troubleshooting

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Aryan SinghandClaude Fable 5 committed 2026-07-10 11:07:07 -05:00
commit 279d137ce5
98 files changed
+9925

No files matched your search

+35
View File
@@ -0,0 +1,35 @@
import path from "node:path";
/**
* Central environment access. In production these are set by docker-compose;
* in local dev sensible fallbacks point at ./dev-data so the app boots
* without the container stack (integrations degrade to "offline" states).
*/
const dev = process.env.NODE_ENV !== "production";
function str(key: string, fallback: string): string {
const v = process.env[key];
return v !== undefined && v !== "" ? v : fallback;
}
export const env = {
dev,
sessionSecret: str("PANEL_SESSION_SECRET", dev ? "craftdeck-dev-secret-do-not-use" : ""),
initialAdminPassword: str("PANEL_ADMIN_PASSWORD", dev ? "admin" : ""),
rconHost: str("RCON_HOST", "127.0.0.1"),
rconPort: Number(str("RCON_PORT", "25575")),
rconPassword: str("RCON_PASSWORD", "minecraft"),
dockerSocket: str("DOCKER_SOCKET", "/var/run/docker.sock"),
mcContainer: str("MC_CONTAINER", "mc"),
backupContainer: str("BACKUP_CONTAINER", "mc-backup"),
mcDataDir: path.resolve(str("MC_DATA_DIR", dev ? "./dev-data/mc" : "/mc-data")),
backupsDir: path.resolve(str("BACKUPS_DIR", dev ? "./dev-data/backups" : "/backups")),
appDataDir: path.resolve(str("APP_DATA_DIR", dev ? "./dev-data/app" : "/app-data")),
projectDir: path.resolve(str("PROJECT_DIR", dev ? ".." : "/project")),
registrationWindowMinutes: Number(str("REGISTRATION_WINDOW_MINUTES", "2")),
discordWebhookUrl: str("DISCORD_WEBHOOK_URL", ""),
};