Files
CubeAdmin/README.md
2026-03-08 23:25:43 +01:00

13 KiB

CubeAdmin-logo

A production-ready Minecraft server administration panel built with Next.js, Bun, and SQLite.

Features

  • Real-time console — stream server output and send commands via Socket.io
  • Server control — start, stop, and restart your Minecraft server from the dashboard
  • Player management — view online/offline players, ban/unban, manage the whitelist
  • Plugin management — list, enable/disable, and upload plugins
  • File explorer — browse, upload, download, and delete server files
  • Backup system — create and restore backups on demand or on a schedule
  • Team management — invite team members by email with role-based access control
  • World map — embedded BlueMap 3D map integration
  • Server version management — switch between Vanilla, Paper, and Fabric versions
  • Monitoring — live CPU and memory charts
  • Task scheduler — run RCON commands on a cron schedule
  • Audit log — full record of all administrative actions
  • Dark/light theme — persisted per user

Tech Stack

Layer Technology
Runtime Bun
Framework Next.js 16 (App Router)
Database SQLite via bun:sqlite + Drizzle ORM
Auth Better Auth v1.5
UI shadcn/ui v4 + Base UI + Tailwind CSS v4
Real-time Socket.io
Email Nodemailer (any SMTP server)

Quick Start (Development)

Prerequisites

  • Bun ≥ 1.1
  • A Minecraft server with RCON enabled (or use the provided docker-compose.dev.yml)

1. Clone and install

git clone https://github.com/your-org/cubeadmin.git
cd cubeadmin
bun install

2. Configure environment

cp .env.example .env.local

Edit .env.local — at minimum you need:

BETTER_AUTH_SECRET=your-32-char-secret-here
MC_SERVER_PATH=/path/to/your/minecraft/server
MC_RCON_PASSWORD=your-rcon-password

3. Spin up a local Minecraft server (optional)

docker compose -f docker-compose.dev.yml up -d

This starts a Paper Minecraft server with RCON exposed on port 25575.

4. Run the development server

bun dev

Open http://localhost:3000. The first account you register automatically becomes the administrator.


Deployment

This is the easiest way to run CubeAdmin and a Minecraft server together on a single host.

1. Create your environment file

cp .env.example .env

Fill in all required values (see Environment Variables below).

2. Start the stack

docker compose up -d

This starts three services:

Service Description Port
cubeadmin The admin panel 3000
minecraft Paper Minecraft server 25565
bluemap 3D world map (optional) 8100

Put Nginx or Caddy in front of CubeAdmin on port 3000. Example Caddyfile:

cubeadmin.example.com {
    reverse_proxy localhost:3000
}

Important: Socket.io requires WebSocket support. Ensure your proxy forwards the Upgrade header.

Nginx snippet:

location / {
    proxy_pass http://localhost:3000;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
}

4. First login

Navigate to https://your-domain.com and register the first account — it is automatically granted the superadmin role.


Option B — Bare Metal (Bun)

1. Build

bun install
bun run build

2. Run

NODE_ENV=production bun --bun run server.ts

The server binds to 0.0.0.0:3000 by default. Use PORT and HOSTNAME env vars to change this.

3. Run as a systemd service

# /etc/systemd/system/cubeadmin.service
[Unit]
Description=CubeAdmin
After=network.target

[Service]
Type=simple
User=cubeadmin
WorkingDirectory=/opt/cubeadmin
ExecStart=/usr/local/bin/bun --bun run server.ts
Restart=on-failure
RestartSec=5
Environment=NODE_ENV=production
EnvironmentFile=/opt/cubeadmin/.env

[Install]
WantedBy=multi-user.target
systemctl daemon-reload
systemctl enable --now cubeadmin

Database Migrations

CubeAdmin uses Drizzle ORM with a SQLite database. Migrations are applied automatically at startup via lib/db/migrate.ts.

To generate a new migration after changing lib/db/schema.ts:

bun run db:generate

Note: bun run db:migrate (drizzle-kit) does not work with Bun's native bun:sqlite driver. Always apply migrations through the app startup migrator or manually with bun:sqlite scripts.

To open the Drizzle Studio database browser:

bun run db:studio

Environment Variables

Authentication

Variable Required Default Description
BETTER_AUTH_SECRET Yes Secret key used to sign sessions and tokens. Must be at least 32 characters. Generate one with openssl rand -base64 32.
BETTER_AUTH_URL No http://localhost:3000 The public base URL of the CubeAdmin app. Used by Better Auth to construct callback URLs.
NEXT_PUBLIC_BETTER_AUTH_URL No (inferred from browser) Browser-side auth URL. Only needed if the public URL differs from what the browser can infer (e.g. behind a proxy).
BETTER_AUTH_TRUSTED_ORIGINS No http://localhost:3000 Comma-separated list of allowed origins for CORS and CSRF protection. Add your public domain in production.

Email (SMTP)

CubeAdmin sends email via any standard SMTP server — Gmail, Mailgun, Postfix, Brevo, Amazon SES, or your own self-hosted relay. Email is only used for team invitations and magic-link sign-in. The app starts without email configured; invitations will fail gracefully with a logged error.

Variable Required Default Description
SMTP_HOST No* SMTP server hostname (e.g. smtp.gmail.com, smtp.mailgun.org, localhost). Required for any email to be sent.
SMTP_PORT No 587 SMTP server port. Common values: 587 (STARTTLS), 465 (TLS/SSL), 25 (plain, relay), 1025 (local dev).
SMTP_SECURE No false Set to true to use implicit TLS (port 465). Leave false for STARTTLS (port 587) or plain.
SMTP_USER No SMTP authentication username. Leave unset for unauthenticated relay (e.g. local Postfix).
SMTP_PASS No SMTP authentication password or app-specific password.
EMAIL_FROM No CubeAdmin <noreply@example.com> The From address on outgoing emails. Must be authorised by your SMTP provider to avoid spam filtering.

Common SMTP configurations

Gmail (app password required — enable 2FA first):

SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_SECURE=false
SMTP_USER=you@gmail.com
SMTP_PASS=your-app-password
EMAIL_FROM=CubeAdmin <you@gmail.com>

Mailgun:

SMTP_HOST=smtp.mailgun.org
SMTP_PORT=587
SMTP_SECURE=false
SMTP_USER=postmaster@mg.yourdomain.com
SMTP_PASS=your-mailgun-smtp-password
EMAIL_FROM=CubeAdmin <noreply@yourdomain.com>

Amazon SES:

SMTP_HOST=email-smtp.us-east-1.amazonaws.com
SMTP_PORT=587
SMTP_SECURE=false
SMTP_USER=your-ses-access-key-id
SMTP_PASS=your-ses-smtp-secret
EMAIL_FROM=CubeAdmin <noreply@yourdomain.com>

Local dev with Mailpit (catches all emails, no real sending):

SMTP_HOST=localhost
SMTP_PORT=1025
SMTP_SECURE=false
# no SMTP_USER / SMTP_PASS needed

Run Mailpit with docker run -p 1025:1025 -p 8025:8025 axllent/mailpit and view emails at http://localhost:8025.

Minecraft Server

Variable Required Default Description
MC_SERVER_PATH No /opt/minecraft/server Absolute path to the Minecraft server directory on the host. CubeAdmin reads/writes files here and spawns the server process from this directory.
MC_RCON_HOST No 127.0.0.1 Hostname or IP where the Minecraft RCON interface is listening. Use minecraft when running the Docker Compose stack.
MC_RCON_PORT No 25575 TCP port for the Minecraft RCON interface. Must match rcon.port in server.properties.
MC_RCON_PASSWORD Yes* Password for the Minecraft RCON interface. Must match rcon.password in server.properties. Required for player management, whitelist, and scheduler features.

*Only truly required if you want RCON-based features (player commands, scheduler). The app will start without it.

Database

Variable Required Default Description
DATABASE_PATH No ./data/cubeadmin.db Path to the SQLite database file. The directory must exist and be writable. In Docker, this is mapped to a named volume.

Server

Variable Required Default Description
PORT No 3000 TCP port the HTTP server listens on.
HOSTNAME No 0.0.0.0 Hostname the HTTP server binds to.
NODE_ENV No development Set to production for production deployments. Affects CSP headers, error verbosity, and Hot Module Replacement.

Optional / Advanced

Variable Required Default Description
BLUEMAP_URL No URL where BlueMap is accessible from the browser (e.g. http://localhost:8100). Enables the Map page. Configurable from the Server Settings UI as well.
RATE_LIMIT_RPM No 100 Maximum number of API requests per minute per IP address. Applied to all /api/* routes by the middleware.

Role System

CubeAdmin has three roles:

Role Description
superadmin Full access — server control, settings, team management, everything. Automatically granted to the first registered user.
admin Can manage players, plugins, files, backups, and the scheduler. Cannot change server settings or manage team roles.
moderator Read-only access to most sections. Can send console commands and manage players.

Roles are assigned when inviting team members. The initial superadmin can promote/demote others from the Team page.


Project Structure

.
├── app/
│   ├── (auth)/             # Login, register, accept-invite pages
│   ├── (dashboard)/        # All protected dashboard pages
│   │   ├── dashboard/      # Overview page (/)
│   │   ├── console/        # Real-time server console
│   │   ├── players/        # Player management
│   │   ├── plugins/        # Plugin management
│   │   ├── files/          # File explorer
│   │   ├── backups/        # Backup manager
│   │   ├── monitoring/     # CPU/RAM charts
│   │   ├── scheduler/      # Cron task scheduler
│   │   ├── team/           # Team & invitations
│   │   ├── audit/          # Audit log
│   │   ├── map/            # BlueMap integration
│   │   ├── server/         # Server settings
│   │   ├── updates/        # Version management
│   │   └── settings/       # Account settings
│   └── api/                # API routes
├── components/
│   ├── layout/             # Sidebar, Topbar
│   └── ui/                 # shadcn/ui components
├── lib/
│   ├── auth/               # Better Auth config + client
│   ├── backup/             # Backup manager
│   ├── db/                 # Drizzle schema + migrations
│   ├── email/              # Nodemailer SMTP client + email templates
│   ├── minecraft/          # Process manager, RCON, version fetcher
│   ├── security/           # Rate limiting
│   └── socket/             # Socket.io server setup
├── data/                   # SQLite database (gitignored)
├── server.ts               # Bun entry point (HTTP + Socket.io)
├── proxy.ts                # Next.js middleware (auth guard + CSP)
├── docker-compose.yml      # Production stack
└── docker-compose.dev.yml  # Dev Minecraft server only

Enabling RCON on Your Minecraft Server

Add these lines to your server.properties:

enable-rcon=true
rcon.port=25575
rcon.password=your-strong-password
broadcast-rcon-to-ops=false

Restart the Minecraft server after editing server.properties.


Security Notes

  • Change the default BETTER_AUTH_SECRET before going to production. A leaked secret allows anyone to forge session tokens.
  • Use a strong RCON password. RCON has full server control — never expose RCON port 25575 to the public internet.
  • HTTPS in production. Better Auth cookies are Secure in production; the app will not authenticate over plain HTTP.
  • BETTER_AUTH_TRUSTED_ORIGINS — add your production domain to prevent CSRF attacks from other origins.
  • The middleware (proxy.ts) enforces a strict Content Security Policy with per-request nonces. No inline scripts are permitted.
  • All API routes are rate-limited to 100 requests/minute per IP by default.