MinePanel
Pannello Minecraft self-hosted, sicuro e senza cloud obbligatorio. ⛏️

La Storia
Avviare un server Minecraft è facile.
Gestirlo bene è tutta un'altra cosa.
Appena entrano in gioco più utenti, permessi, autenticazione, limiti di risorse, monitoraggio, lifecycle dei server e amministrazione remota, non stai più costruendo uno script per un game server. Stai iniziando a gestire vera infrastruttura.
Io volevo la comodità di un pannello hosted, ma senza cedere a una piattaforma esterna il controllo di tutto quello che c'è sotto. I server dovevano girare sul mio hardware. I dati dovevano stare dove decidevo io. Docker, database, autenticazione e istanze Minecraft dovevano restare sotto il controllo dell'operatore.
Da qui è nato MinePanel.
All'inizio l'idea era semplice: costruire una bella interfaccia per gestire server Minecraft eseguiti in Docker.
Poi ho iniziato a prendere sul serio ogni dettaglio.
Cosa succede se arrivano due operazioni sullo stesso server nello stesso momento? Cosa succede se il database dice che un server è attivo ma Docker racconta un'altra storia? Come faccio a dare a un moderatore il controllo di un singolo server senza trasformarlo in amministratore di tutto? Come posso offrire una dashboard hosted senza creare l'ennesimo servizio cloud centralizzato? Come gestisco l'autenticazione tra domini diversi senza mettere token nel browser solo perché è più comodo? E come pubblico aggiornamenti dei container senza rendere latest una roulette russa?
Sono domande che hanno trasformato MinePanel da semplice pannello a uno dei progetti tecnicamente più ambiziosi che abbia mai costruito.
Oggi è diviso intenzionalmente in tre parti:
- un backend controllato dall'operatore, eseguito accanto a Docker, PostgreSQL, Caddy e ai workload Minecraft;
- una PWA React hosted che collega direttamente il browser al backend MinePanel scelto dall'utente;
- un sito pubblico in SvelteKit che racconta il progetto e ne mostra la roadmap aggiornata.
Tra l'utente e la sua infrastruttura non c'è un cloud MinePanel obbligatorio.
Ed è proprio questo vincolo ad aver guidato molte delle scelte più importanti del progetto.
Cosa Lo Rende Speciale
Il principio centrale di MinePanel è rimasto lo stesso dall'inizio:
la comodità può essere hosted senza che lo debba essere anche l'infrastruttura.
La dashboard su app.minepanel.xyz è un'applicazione statica. Non fa da proxy per le API, non custodisce le credenziali degli operatori, non inoltra le sessioni e non mantiene un database centrale delle installazioni collegate.
Il modello è questo:
app.minepanel.xyz
PWA React statica
│
│ HTTPS / WebSocket
▼
dominio dell'operatore
│
Caddy
│
NestJS ───── PostgreSQL
│
│ Docker socket
▼
mc-{serverId}
container MinecraftIl browser parla direttamente con il backend dell'operatore.
La PWA può salvare più installazioni MinePanel, ma conserva soltanto metadati locali come origin canonico, label e timestamp. Non persiste credenziali, token di sessione, materiale TOTP, setup token, dati del backend o traffico WebSocket.
Per me questa è una delle parti più riuscite del progetto: una sola applicazione web può gestire installazioni self-hosted completamente indipendenti senza che MinePanel debba controllare l'infrastruttura nel mezzo.
Arrivarci mi ha costretto a ragionare davvero su sicurezza del browser, CORS, cookie cross-origin, capability discovery, isolamento dello stato locale e trust boundary.
Da fuori MinePanel deve sembrare semplice.
La complessità preferisco gestirla io sotto la superficie.
La Parte Tecnica
Funzionalità Principali
Control plane self-hosted Backend, PostgreSQL, dati Minecraft, container Docker e API di gestione restano sull'infrastruttura dell'operatore.
PWA hosted multi-panel Una sola dashboard installabile può collegarsi direttamente a più installazioni MinePanel indipendenti, mantenendo separati i relativi metadati locali tramite IndexedDB.
Un container per ogni server Ogni istanza Minecraft gira nel proprio container Docker gestito, su una rete dedicata, con un lifecycle prevedibile e confini chiari.
Gestione completa del lifecycle Creazione, avvio, arresto graceful, riavvio, ispezione e rimozione passano da operazioni controllate dal backend invece di esporre Docker direttamente agli utenti.
Resource admission e reconciliation Prima di creare nuovi workload, MinePanel controlla le risorse dell'host. All'avvio confronta inoltre lo stato persistito con quello reale dell'infrastruttura invece di fidarsi ciecamente del database.
Autorizzazione granulare ADMIN, MOD e USER non sono sufficienti da soli. I ruoli vengono combinati con permessi granulari e autorizzazione per-server.
Accesso OPEN / REQUEST / PRIVATE Ogni server può essere aperto agli utenti autenticati, accessibile tramite richiesta oppure completamente privato. I server REQUEST hanno una discovery dedicata che non espone quelli PRIVATE.
Autenticazione basata su sessioni JWT a breve durata tramite cookie HttpOnly, refresh session, revoca, logout globale, recovery, rate limiting e bootstrap protetto del primo amministratore.
2FA completa TOTP, enrollment, verifica, disattivazione e backup code monouso sono integrati sia nel backend sia nella PWA.
Google authentication challenge-bound Login e account linking utilizzano challenge monouso generate dal backend e flussi espliciti di collegamento dell'account.
Capability negotiation Il backend espone versione del protocollo e capability supportate. La PWA utilizza ciò che il backend dichiara realmente invece di dedurre compatibilità da una stringa di versione.
Telemetria real-time CPU, RAM e disco dell'host vengono trasmessi agli amministratori tramite WebSocket autenticati.
Hosted auth hardenizzata L'attuale modello utilizza cookie HttpOnly partitioned e Web Locks per coordinare il refresh tra tab e contesti diversi senza affidarsi alla persistenza dei token nel browser.
Origin validation rigorosa In produzione vengono accettati solo origin HTTPS pubblici e canonici. IP letterali, credenziali nell'URL, path, localhost e target ambigui vengono rifiutati.
Offline volutamente limitato Il service worker può cacheare l'application shell, ma non API, autenticazione, WebSocket, mutazioni o dati del backend.
Release engineering automatizzato Typecheck, lint, test, migrazioni, build delle immagini, smoke test, security scan e controlli sul contratto di deployment fanno parte della pipeline prima della pubblicazione.
Il Cuore Tecnologico
Il backend utilizza:
- NestJS 11 + TypeScript per moduli, dependency injection, guard, validazione, WebSocket e confini architetturali chiari.
- Bun 1.3 come runtime di produzione e package manager.
- PostgreSQL 16 come principale dipendenza stateful.
- Drizzle ORM per accesso tipizzato e migrazioni SQL esplicite.
- Dockerode per controllare il daemon Docker.
- itzg/minecraft-server come base dei workload Minecraft.
- Caddy 2 come reverse proxy e boundary TLS.
- Socket.IO per la comunicazione real-time autenticata.
La dashboard hosted utilizza:
- React 19
- Vite 7
- React Router 7
- TanStack Query
- IndexedDB
- Tailwind CSS 4
- Socket.IO Client
- vite-plugin-pwa
- Cloudflare Pages
Il sito pubblico utilizza:
- Svelte 5 + SvelteKit 2
- Cloudflare Pages
- caricamento server-side delle roadmap dai repository;
- validazione dei dati prima del rendering;
- edge caching;
- asset locali;
- nessun advertising o behavioral analytics.
I repository sono separati perché hanno responsabilità diverse.
Il sito non deve decidere come funziona il backend.
La PWA non deve diventare parte dell'infrastruttura trusted dell'operatore.
E il backend non deve sapere come un frontend decide di rappresentarne le funzionalità.
A tenere tutto insieme è il contratto API.
Sfide e Soluzioni
Una Dashboard Hosted Senza un Cloud MinePanel
Sfida: La soluzione più semplice per costruire una dashboard hosted sarebbe stata mettere un server MinePanel nel mezzo: proxy delle API, relay delle sessioni e magari un database centrale con tutte le installazioni.
Avrebbe semplificato parecchie cose.
Ma avrebbe anche tradito il motivo per cui MinePanel esiste.
Soluzione: Ho costruito la PWA come client statico che comunica direttamente con backend HTTPS scelti dall'utente.
Questo ha richiesto origin validation rigorosa, CORS esatto, capability discovery, cookie cross-site, Web Locks per coordinare i refresh, isolamento delle query per pannello e cleanup dello stato quando cambiano pannello o utente.
Non ho spostato i token in localStorage solo perché sarebbe stato più semplice.
Non ho trasformato il service worker in una cache invisibile delle API.
E l'app hosted non inoltra il traffico attraverso infrastruttura MinePanel.
Risultato: Posso offrire una singola applicazione hosted mantenendo completamente self-hosted il vero control plane.
È probabilmente la scelta architetturale che oggi rappresenta meglio MinePanel.
Dare Accesso a Docker Senza Far Finta Che Sia Innocuo
Sfida:
Avere accesso a /var/run/docker.sock significa avere un livello enorme di controllo sull'host.
Non è qualcosa che considero una normale dipendenza applicativa.
Soluzione: Ho reso quel confine esplicito nell'architettura.
NestJS non viene pubblicato direttamente su Internet: davanti c'è Caddy. PostgreSQL non espone porte pubbliche. I container vengono creati attraverso path controllati lato server. Le directory host vengono validate. Il backend vede i dati Minecraft in sola lettura. I workload gestiti utilizzano una rete Docker dedicata e le operazioni possono agire soltanto sulle risorse riconosciute come appartenenti a MinePanel.
Anche il deployment fa quindi parte del modello di sicurezza.
Risultato: MinePanel mantiene la potenza dell'orchestrazione Docker senza nascondere quanto sia delicato il confine su cui si basa.
Andare Oltre ADMIN e USER
Sfida: Un modello ADMIN / USER sembra sufficiente finché non vuoi permettere a qualcuno di gestire un server senza dargli automaticamente accesso amministrativo a tutto il sistema.
Soluzione: Ho separato identità, stato dell'account, ruolo globale, permessi granulari, visibilità dei server e accesso ai singoli server.
Il backend resta sempre l'autorità.
Il frontend può nascondere un'azione che un utente non può eseguire, ma quello serve solo alla UX. La sicurezza rimane nei guard e nelle regole lato server.
Ho aggiunto anche invarianti come la protezione dell'ultimo amministratore e veri workflow di richiesta e approvazione per i server REQUEST.
Risultato:
Il sistema dei permessi può crescere insieme al prodotto senza trasformarsi in una cascata di if (role === ...).
Quando Docker e il Database Non Sono D'Accordo
Sfida: L'infrastruttura non è CRUD.
Se il database dice RUNNING, il container non inizia magicamente a funzionare. Docker può fallire nel mezzo di un'operazione. Il backend può riavviarsi. Due richieste possono correre l'una contro l'altra.
Soluzione: Ho progettato il lifecycle attorno a transizioni esplicite, update condizionati, resource admission, startup reconciliation e failure path che distinguono ciò che sappiamo essere successo da ciò che non possiamo confermare.
Il sistema parte dal presupposto che lo stato persistito e quello osservato possano divergere.
Risultato: Il backend si comporta sempre più come un piccolo infrastructure controller e sempre meno come un wrapper HTTP sopra Docker.
Ed è una distinzione che ha cambiato profondamente il progetto.
La CI Fa Parte del Prodotto
Sfida: Se stai pubblicando un container che qualcuno installerà su una macchina con accesso al daemon Docker, "da me funziona" non è una strategia di release.
Migrazioni, contenuto dell'immagine, dipendenze, architetture supportate, file Compose e tag diventano tutti parte del contratto.
Soluzione: La CI di MinePanel controlla molto più del codice TypeScript.
La pipeline comprende unit test, E2E con PostgreSQL reale, migrazioni su database puliti, build dell'immagine, smoke test, test trusted con Docker reale nelle release, vulnerability scanning, deployment contract check e pubblicazione multi-architettura.
Le immagini includono provenance e SBOM e possono essere identificate tramite tag immutabili derivati dai commit.
Anche i channel sono espliciti:
masterpubblicaedgee un tag SHA immutabile;- le future release versionate pubblicheranno semver e
latest; - immagini e asset di deployment devono appartenere alla stessa release.
Risultato: La release non è più "pushare un'immagine Docker".
È una parte progettata e verificabile del sistema.
Dietro le Quinte
MinePanel è probabilmente il progetto personale che più ha cambiato il mio modo di sviluppare software.
Ogni cosa che completavo apriva immediatamente un problema più profondo.
L'autenticazione ha portato alle sessioni. Le sessioni hanno portato a revoca, recovery, 2FA, OAuth e cookie cross-origin. I ruoli hanno portato ai permessi. Il lifecycle Docker ha portato a concorrenza, reconciliation e resource admission. La dashboard hosted ha portato a CORS, CHIPS, Web Locks, capability negotiation, IndexedDB e service worker boundary.
A un certo punto anche la documentazione ha smesso di essere semplicemente documentazione.
Il backend ha una specifica canonica che descrive non solo ciò che esiste, ma anche gli invarianti da preservare, ciò che è ancora aperto, ciò che è opzionale e ciò che le fasi future possono dare per scontato.
Backend e PWA pubblicano inoltre la propria roadmap machine-readable, mentre il sito la consuma senza diventare lui stesso la fonte di verità.
Questa disciplina è diventata ancora più importante da quando utilizzo pesantemente agenti AI nello sviluppo.
Con MinePanel ho capito una cosa molto bene: più l'AI mi permette di costruire velocemente, più devo essere rigoroso su architettura, specifiche e revisioni.
Uso gli agenti come implementation worker con scope limitato, reviewer, researcher e ulteriori occhi sul progetto. Il mio ruolo si è spostato sempre di più verso la definizione del sistema entro cui devono lavorare: progettare l'architettura, stabilire invarianti, separare le responsabilità, revisionare patch, verificare assunzioni e decidere quando qualcosa può davvero essere considerato completato.
Perché senza una struttura forte, l'AI può produrre molto velocemente tantissimo codice che, preso singolarmente, sembra corretto ma che nel complesso costruisce il sistema sbagliato.
MinePanel è quindi cresciuto attorno all'idea opposta: specifiche forti, trust boundary espliciti, contratti testabili e una CI che renda difficili le regressioni accidentali.
Ed è uno dei motivi per cui questo progetto conta così tanto per me.
In superficie è un pannello per server Minecraft.
Sotto è diventato il mio laboratorio personale per backend architecture, autenticazione, browser security, autorizzazione, PostgreSQL, Docker orchestration, sistemi real-time, deployment engineering, CI/CD, protocol design e frontend architecture.
Non volevo costruire un mockup ben fatto di qualcosa di ambizioso.
Volevo continuare finché anche le parti difficili fossero diventate vere.
Stato Attuale
MinePanel si sta avvicinando alla prima release stabile del backend.
La foundation principale è completa: autenticazione, autorizzazione, lifecycle Docker, resource admission, telemetria host, deployment, migrazioni automatiche e release automation sono già implementati.
Anche il core della fase Identity / Onboarding è completo, con autenticazione Google, account linking, visibilità dei server, access request, discovery dei server richiedibili e permessi granulari per i moderatori.
La dashboard hosted copre già l'attuale superficie di gestione: multi-panel, autenticazione, sicurezza dell'account, lifecycle dei server, workflow di accesso, gestione utenti, permessi MOD e telemetria host.
Il prossimo milestone è Stable-v1 Hardening: stabilizzare ulteriormente il protocollo pubblico, migliorare error contract e protezioni anti-abuso, rafforzare l'isolamento delle risorse, rendere riproducibile la strategia delle immagini Minecraft ed espandere i test trusted del lifecycle Docker reale.
Dopo arriveranno le parti ancora più operative: audit log, console e log real-time, backup, scheduled task, filesystem management, player, plugin e mod, notifiche, preset e networking.
Come Iniziare
Il backend pre-stable viene attualmente pubblicato sul canale edge.
Servono una macchina Linux con Docker Engine e Compose, un dominio e le porte 80 e 443 disponibili.
Gli asset di deployment possono essere scaricati direttamente:
curl -fsSLo docker-compose.yml https://raw.githubusercontent.com/MinePanelProject/minepanel-backend/master/docker-compose.yml
curl -fsSLo .env.example https://raw.githubusercontent.com/MinePanelProject/minepanel-backend/master/.env.example
curl -fsSLo Caddyfile https://raw.githubusercontent.com/MinePanelProject/minepanel-backend/master/Caddyfile
cp .env.example .envDopo aver configurato dominio, credenziali, setup token e percorso dei dati:
docker compose pull
docker compose up -dCaddy configura HTTPS automaticamente, PostgreSQL applica le migrazioni prima dell'avvio dell'API e il backend può essere aggiunto direttamente alla PWA su app.minepanel.xyz.
Non serve un account MinePanel per collegare le due parti.
Nessun server MinePanel fa da intermediario.
L'infrastruttura rimane tua.
Ed è ancora questo l'obiettivo con cui ho iniziato:
rendere la gestione di infrastruttura Minecraft seria sul proprio hardware comoda quanto una piattaforma hosted, senza rinunciare al controllo per ottenerla.