Skip to content
Core · Node · Proto · Log-Shipper · Panel

One control plane.
Every host.
Every server.

This is the product you actually touch. Core is the REST + gRPC brain: auth, scheduling, console, live events. Node runs on every host and drives Docker directly. The Panel is the Next.js UI. And a tiny log-shipper rides inside every server container, streaming logs home.

DockerRuns on a single host with bundled Postgres, or scales out across a Swarm. You can self-host all of it.
Core43,356 Go

REST + gRPC control plane: auth, scheduler, RCON console, live events, migrations.

res (est.)
60-120 MB
image (est.)
~22 MB alpine
Node10,695 Go

Host agent that drives Docker: server lifecycle, ports, quotas, files, stats.

res (est.)
40-80 MB
image (est.)
~20 MB alpine

MC server containers it launches use eclipse-temurin JRE on Alpine (~120-190 MB; Java 8, 17, 21).

Panel26,005 TS

Next.js 16 web console, SSE-driven. The surface you actually touch.

res (est.)
80-150 MB
image (est.)
~200 MB node:22
Log-shipper416 Go

PID 1 inside each MC container; wraps the JVM and streams logs to Redis.

res (est.)
5-10 MB
image (est.)
embedded
Shared libs6,704 Go

agent (stats + DDoS), proto (gRPC contract), pkg (helpers). Compiled in, no own image.

res (est.)
library
image (est.)
n/a

Line counts from source. Resource use and image sizes are rough estimates.

01 · Overview

Control Plane Flow

PANELNext.js UIbrowserREST+ SSECORE🐳 control planeREST API · :25500gRPC mesh · :25501JWT auth · scheduler · RCONSSE events · Beam ticketsRedis leader electionPostgres 16GORM · TimescaleRedisqueues · streamsNode dialsgRPC outNODE🐳 host agent/var/run/docker.sockport alloc · disk quotasSFTP · Beam · host statsRedis command queuedockerMC SERVERSurvivallog-shipper PID 1MC SERVERCreativelog-shipper PID 1log stream → Redis → Panel console (SSE)panel ↔ corecore ↔ node (outbound mesh)live logs
Control Plane

Core is a single Go service exposing a REST API and a gRPC mesh endpoint. It owns auth, the scheduler, the RCON console, live event streams, and durable state in PostgreSQL. On one host it bundles its own database; in a Swarm it points at external Postgres.

Host Agent

Node runs on every machine in the fleet and talks to the local Docker socket. It dials out to Core over gRPC, so a node behind NAT or on a home connection needs no inbound reachability to join.

Live Everything

A tiny log-shipper is PID 1 inside every server container. It streams stdout to Redis, and Core fans that out to the Panel over SSE, so the console you see is the real process output, live.

02 · Core

The Control Plane

43,356 LoC · GoDocker

The largest module in the project. One binary that every other piece talks to.

Core serves a REST API on :25500 (Gorilla Mux) and a gRPC mesh endpoint on :25501. It is the single source of truth: users, servers, audit log, settings and time-series stats live in PostgreSQL through GORM. It runs its own migrations, signs Beam file tickets, drives the scheduler, and elects a leader through Redis so singleton work runs exactly once across replicas.

REST
:25500
Gorilla Mux · serves the Panel + API
gRPC mesh
:25501
Core ↔ Node contract
Database
Postgres 16
GORM · TimescaleDB or Supabase
Auth
JWT
refuses to boot on a placeholder secret
Single host vs. Swarm

On a single machine, Core bundles TimescaleDB and keeps server stats in a hypertable. In a Swarm deployment it points at external PostgreSQL (for example Supabase) and falls back to a plain stats table with an hourly retention sweep. Same binary, same schema, two footprints.

core · startup log · 🐳 control plane
$ dylaris-core
[core] pid 1 · 🐳 docker
──────────────────────────────────────
JWT_SECRET present · not a placeholder
Postgres connected · GORM · v16
TimescaleDB detected · stats hypertable
migrations applied · schema up to date
── Listeners ────────────────────────
:25500 · REST API + Panel
:25501 · gRPC node mesh (mTLS)
SSE · /api/system/events
── Singletons ───────────────────────
redis leader lease acquired
scheduler started · cron tasks loaded
✓ core ready · waiting for nodes...
[node] host-eu-01 connected · gRPC mesh up
[node] host-eu-01 · 3 servers reconciled
03 · Node

The Host Agent

10,695 LoC · GoDocker

One per machine. This is what turns a plain box (or a gaming PC) into a Dylaris node.

Node mounts the Docker socket and creates, starts, stops and deletes Minecraft server containers directly. It reads its command queue from Redis, allocates host ports from a configured range, enforces per-server disk quotas, and collects host CPU/RAM/network stats. It exposes file access over SFTP or over Beam, and it dials Core outbound, so it never needs an inbound port of its own.

Routing Modes · switchable at runtime
ip_portNode binds a host port. Players connect to node-ip:port directly. No gateway required.
gatewayNode binds no host port. Traffic arrives Edge → Link tunnel → Node. This is the portless path.
bothPorts bound and gateway routes active at the same time, for migrations.
Containers
Docker
direct socket · one per server
Files
SFTP · Beam
:25520 SFTP · :25521 Beam gRPC
Isolation
quotas
project-quota disk limits per server
Reach
outbound
NAT / home nodes join freely
node · host-eu-01 · 🐳 docker
$ dylaris-node --core grpc://core:25501
[node] host-eu-01 · outbound only
docker.sock reachable · api v1.45
gRPC mesh dialed · core:25501 (mTLS)
redis queue attached
routing mode · gateway (no host port)
── Reconciling servers ──────────────
create · survival · paper 1.21.11
container up · quota 20 GB · port n/a
log-shipper PID 1 · streaming to redis
link route published · survival.play…
✓ 3 servers running · 0 host ports open
>
04 · Proto

The Core ↔ Node Contract

4,511 LoC · generated

Everything Core and Node say to each other is a typed gRPC contract. Two .proto files define it; the .pb.go code is generated and committed. The heart of it is NodeConnect, a bidirectional stream the Node opens outbound. Once it is up, Core can drive the node without ever opening a socket toward it.

Files
2 .proto
node.proto · beam_node.proto
Wire
protobuf3
over gRPC · streaming + unary
Direction
Node → Core
stream dialed outbound, NAT-safe
node.proto · shape only
// Node dials this stream outbound to Core.
// Shape only, fields trimmed.
service
NodeService {
rpc
NodeConnect(stream NodeMsg)
returns (stream CoreMsg);
rpc
FileOp(stream Chunk)
returns (stream Chunk);
}
message
CoreMsg {
oneof cmd { CreateServer create = 1;
StartServer start = 2;
/* … */ }
}

Illustrative shape, not the real schema. The outbound stream is the reason a node behind NAT, on a home connection, or on a gaming PC can join the fleet at all.

05 · Log-Shipper

PID 1 in Every Container

416 LoC · GoDocker

The smallest binary in the project, and one of the most important. Node launches every Minecraft container with the log-shipper as PID 1. It execs the Java process, captures its stdout and stderr, and streams every line into a Redis stream keyed by server. Core reads those streams and pushes them to the Panel, so the console is the live process, not a polled file.

Role
init
PID 1 · wraps the Java process
Ships to
Redis
one stream per server / sub-server
Size
416 LoC
one main.go, no dependencies to speak of
Console
live
Panel reads the stream over SSE
log-shipper · inside the MC container
// Node injects env on container launch
SERVER_UUID = a3f1…
REDIS_ADDR = redis:6379
// PID 1 wraps the JVM
exec java -jar server.jar nogui
stdout captured · line-buffered
XADD dylaris:server:{uuid}:logs
signals forwarded · clean shutdown
[core] fanned out to panel console · SSE
06 · Panel

The Product

26,005 LoC · TS

Next.js 16 · React 19 · lucide · VT323. The same design system as this very site.

The Panel is a 237-file Next.js App Router app that talks only to Core's REST API and its SSE stream. It is the surface for everything below: create a server, watch the live console, browse files, schedule tasks, install a modpack, profile a laggy tick, manage users and API keys. It uses the same tokens, fonts and icon set you see across the marketing site, so the product and its landing page feel like one thing.

Server management

Create, start, stop and delete servers. Live status, resource use and a full lifecycle, all from the browser.

Live console (RCON)

Real stdout streamed over SSE plus RCON command input. The console is the live process, not a tailed file.

File browser

Browse and edit server files over Beam or SFTP, without exposing a raw file port to the internet.

Scheduled tasks

Cron-style tasks for restarts, backups and commands, run by Core's scheduler.

Modpack browser

Search and install Modrinth modpacks directly, alongside the Technic/Solder + Modrinth builder.

Spark profiler

Attach the Spark profiler to a running server and read the results back inside the panel.

Custom tabs

Pin your own tools as tabs or pop-outs next to the built-in views.

Users & API keys

Multi-tenant accounts, roles and scoped API keys for automation.

Setup wizard

A first-run wizard that configures Core, the first node and routing without touching a config file.

07 · Separation

Platform and Gateway are two separate things

The Platform is the panel and the servers. The Gateway is the optional edge that gives them portless, DDoS-protected ingress. They deploy independently and coordinate only through shared Redis keys and queues. Run the Platform alone in ip_port mode today; add the Gateway later without touching the panel.

Codebase, by side
Platform · Go61,171
Panel · TypeScript26,005
Gateway · Go12,618
XDP · C216

Roughly 74k lines of Go plus 26k of TypeScript. The Platform is ~80% of the Go; the Gateway is a compact, self-contained edge.

ComponentRoleProtocolOpen PortsDockerLoC
Core
Control plane · API, auth, scheduler, consoleREST + gRPC + SSE25500, 25501image43,356
Node
Host agent · Docker, ports, files, statsgRPC (outbound) + Redis25520, 25521image10,695
Agent
Host stats + DDoS detection libraryin-processnonelib962
Proto
Core ↔ Node gRPC contractprotobuf3n/agenerated4,511
Pkg
Shared queue / Redis / auth helpersin-processnonelib1,231
Log-shipper
PID 1 in each MC container, ships logsRedis streamsnonein container416
Panel
Next.js UI · the product surfaceREST + SSE (to Core)served by Corestatic/SSR26,005 TS

Built to host at scale.

A full control plane and an optional portless edge, both Docker-native, both self-hostable, shipped in the open in numbered phases.