Skip to content

Latest commit

 

History

898 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Leia em Português (Brasil)

CraftControl logo

CraftControl

A mobile-first control center for Minecraft Bedrock servers.

Manage worlds, players, rules, access, backups, and structured gameplay statistics without living in a server console.

Quality gates Coverage License: Apache-2.0 Python 3.12 Flask 3 SQLite Docker Compose

Nginx JavaScript ES modules OpenAPI 3.1 Swagger UI Languages: PT, EN, ES

Important

CraftControl targets trusted private networks. Local authentication and CSRF protection are active, but TLS termination and restricted Docker access remain deployment requirements. Do not expose port 8082 directly to the Internet.

What CraftControl provides

  • Purpose-built controls for server properties, gamerules, time, weather, permissions, packs, and lifecycle operations.
  • Permanent player profiles with aliases, sessions, play time, deaths, permissions, and individual telemetry.
  • Global activity, death, ranking, block, combat, exploration, and 7/30-day analytics.
  • A companion Behavior Pack for authoritative kills, blocks, damage, distance, dimensions, and structured deaths.
  • Coordinated world and SQLite backups with verification, retention, offline restore, and recovery copies.
  • Player-backed owner, operator, and viewer accounts with opaque sessions and session-bound CSRF tokens.
  • A responsive interface in Portuguese, English, and Spanish with original CraftControl pixel-art icons.

CraftControl Server remains useful without the optional CraftControl Telemetry Pack, Prometheus, Grafana, Loki, or any external observability service.

Interface

The six primary areas are task-oriented:

Area Responsibility
Home Server health, online players, freshness, and shortcuts
World World identity, generation, time, weather, and cycles
Players Permanent profiles, sessions, access, permissions, and individual telemetry
Data Activity, deaths, rankings, blocks, combat, exploration, and periods
Rules Gameplay, interface, mobs, drops, commands, fire, TNT, and regeneration
Server CraftControl Telemetry Pack, network, performance, backups, and container lifecycle

The profile includes a browser-local appearance preference; see Color themes.

Navigation is encoded in the URL, so refreshing a browser preserves the active area. Persistent setting changes enter a review drawer; lightning-marked gamerules apply immediately.

Restart-required changes are tracked as server operations. A failed operation is reconciled read-only against Bedrock's effective server.properties before the panel refreshes its settings: requested values are never shown as applied until they are observed. See Operation lifecycle.

An operation opens in a global drawer. It can be dismissed without interrupting the server work; a persistent indicator keeps its live status and reopens the same drawer from any area of the application.

The Host Agent probes Bedrock immediately after restart and then uses capped exponential backoff (1–10 seconds) while waiting for health. The configured operation deadline remains authoritative; status updates remain independent of the probe cadence.

Architecture

CraftControl is a monorepo with two independently deployable containerized application services, not a set of microservices. The backend remains a modular monolith; an optional systemd host agent is a separate host-level execution boundary.

flowchart TD
    client["CraftControl Client<br/>browser"]

    subgraph docker["Docker Engine / Compose"]
        frontend["CraftControl Client<br/>Nginx · static UI · API/SSE proxy"]
        server["CraftControl Server<br/>Flask modular monolith<br/>API · event broker · SSE"]
        bedrock["Minecraft Bedrock Server<br/>optional CraftControl Telemetry Pack"]
        daemon["Docker Engine<br/>container events"]
        frontend --> server
    end

    agent["CraftControl Host Agent<br/>systemd · outside Docker"]

    client --> frontend
    server -->|"when HOST_AGENT_URL is set:<br/>configuration and restart workflow"| agent
    agent -->|"Compose, filesystem, health probe"| bedrock
    server -->|"allowlisted Bedrock console;<br/>lifecycle fallback"| bedrock
    bedrock -. "logs and optional telemetry" .-> server
    daemon -. "container events" .-> server
Loading

CraftControl Client owns the public origin. Nginx serves static assets and proxies /api/*, including unbuffered Server-Sent Events, to the private CraftControl Server. The Client has no persistent or privileged mounts. The Server owns durable state (SQLite), Bedrock files, coordinated backups, console operations, log streaming, and Docker events.

CraftControl has three runtime boundaries: the CraftControl Client (Nginx container serving static assets and proxying the API), the CraftControl Server (Flask modular monolith inside Docker managing state, auth, and Bedrock operations), and the CraftControl Host Agent (craftcontrol-host-agent, a systemd service running on the Docker host outside all containers).

When the CraftControl Host Agent is configured (HOST_AGENT_URL is set), server lifecycle operations — PREPARATION (writing configuration), RESTART (restarting the Compose service), and HEALTH_WAIT (polling the transport-aware Bedrock readiness probe: RakNet ping for transport=raknet, console-log evidence for transport=nethernet on Bedrock 1.26.50+) — are delegated to it over an authenticated HTTP channel. The agent handles Docker socket access for those three stages so the CraftControl Server does not need to execute them directly; the Docker socket remains mounted in the Server for Bedrock console attachment, log streaming, and Docker events, which are not part of the Host Agent contract. Without the Host Agent, the Server performs all lifecycle operations directly.

The host agent is intentionally not a Docker container. Containerizing it would require either mounting the Docker socket into the container (defeating least-privilege isolation) or using privileged host mounts with elevated network namespaces. Running it as a systemd service on the host gives Docker socket access through OS-level group membership without exposing the socket to the container network or the backend image.

The backend intentionally runs one Gunicorn worker with multiple threads. Its event broker, supervisors, refresh lock, and SSE delivery are process-local; multiple workers would duplicate those responsibilities.

Repository ownership

flowchart TD
    repo["CraftControl repository"] --> apps["apps/"]
    apps --> frontend["apps/client/ — Nginx image, HTML, CSS, and native ES modules"]
    apps --> backend["apps/server/ — Flask image, composition root, and Python application"]
    repo --> services["services/bedrock-proxy/ — independently deployed systemd service"]
    repo --> contracts["packages/contracts/ — canonical OpenAPI 3.1 contract and generated types"]
    repo --> telemetry["packs/telemetry/ — embedded Behavior Pack and lifecycle assets"]
    repo --> versions["versions.env — tested frontend/backend release pair"]
Loading

Root Python links and the combined image are compatibility overlays. They preserve existing tooling and emergency rollback while migration continues; new application code belongs under apps/.

Frontend modules

The frontend uses browser-native ES modules with no bundler or build-time framework.

flowchart TD
    static["apps/client/static/"] --> app["app.js — minimal bootstrap"]
    static --> js["js/"]
    js --> composition["composition.js — dependency assembly and application startup"]
    js --> core["core/ — state, DOM, routing, navigation, and invalidation"]
    js --> components["components/ — shared feedback and time presentation"]
    js --> features["features/ — auth, settings, world, rules, server, players, analytics"]
    js --> i18n["i18n/ — PT, EN, ES catalogs and localized game terminology"]
Loading

Feature modules own their markup, bindings, and local state; core/ modules do not import features/. See Architecture for dependency rules, event consistency, deliberate non-goals, and the incremental target layout.

Backend layers

flowchart TD
    manager["apps/server/controlplane/"] --> composition["composition.py — manual production dependency injection"]
    manager --> http["http/ — HTTP mapping grouped by domain"]
    manager --> players["players/ — player application use cases"]
    manager --> auth["auth/ — accounts, sessions, roles, CSRF, and audit"]
    manager --> operations["operations/ — backup, restore, and operational workflows"]
    manager --> runtime["runtime/ — log, Docker-event, and reconciliation supervisors"]
    manager --> ports["ports.py — structural external-boundary contracts"]
Loading

Routes translate HTTP requests and responses. Use cases coordinate behavior. Repositories own persistence. See apps/server/controlplane/README.md for the full package layout and architecture rules.

Contracts and API documentation

packages/contracts/openapi.json is the canonical OpenAPI 3.1 business contract. Generated client declarations live at apps/client/static/js/api-contract.d.ts; the quality gate rejects stale declarations.

Authenticated installations expose:

  • /api/openapi.json — machine-readable contract;
  • /api/docs — Swagger UI using the current session;
  • /api/events — persisted and live Server-Sent Events.
  • /api/diagnostics — owner-only local telemetry and SSE diagnostics; it does not require an observability stack.

Persistence diagnostics report SQLite connection wait, bounded retry pressure, final contention failures, and database size without exposing database contents or filesystem paths. Only idempotent reads may retry after transient SQLite contention; writes fail without automatic retry.

GET /api/operations returns bounded, paginated operation history through a one-based page query parameter and a limit page size from 1 to 100 (default 10).

Swagger attaches the session-bound CSRF token to unsafe “Try it out” requests and never bypasses role capabilities. There is no arbitrary shell or console endpoint.

Event-driven state and telemetry

CraftControl follows Bedrock logs and Docker lifecycle events, commits durable evidence to SQLite, publishes changes through SSE, performs targeted refreshes, and runs a full safety reconciliation every 15 minutes by default. Stale information remains visible and marked instead of being replaced by false empty data.

flowchart LR
    logs["Bedrock logs"] --> broker["event broker"]
    docker["Docker events"] --> broker
    operations["Manager operations"] --> broker
    broker --> sqlite["SQLite"] --> sse["SSE"] --> browser["browser"]
    broker --> reconciliation["targeted reconciliation"]
Loading

The optional CraftControl Telemetry Pack (0.4.0) emits schema-versioned JSON and supports authoritative snapshots plus incremental events. Snapshots can recover lifetime aggregates after downtime; they cannot recreate every missed event, timestamp, cause, or coordinate.

See Architecture for the event and consistency model, and CraftControl Telemetry Pack integration for the lifecycle and recovery runbook.

Installation

CraftControl requires Docker Engine with the Compose plugin and an existing itzg/minecraft-bedrock-server deployment. It runs alongside the Bedrock project and must be deployed with its guarded commands. Never run a bare docker compose up from a development checkout. Coordinated releases prepare both versioned images before recreating either service and attempt image builds up to three times.

See Installation for prerequisites, expected directory layout, configuration, cutover, access, post-install checks, and troubleshooting.

The optional Host Agent has a supported idempotent prerequisite installer. Run it as root after installing the systemd service; it verifies the agent account, Docker access, scoped ACLs, the .env ACL watcher, and the systemd sandbox without restarting Bedrock. See Host Agent.

Configuration

CraftControl is configured through environment variables (MANAGER_PORT, MINECRAFT_CONTAINER, DATABASE_PATH, HOST_AGENT_URL, TZ, and others) and reads versions.env for the tested frontend/backend release pair.

See Configuration for the full variable reference, Bedrock configuration authority rules, and host-agent timeout settings.

Authentication and access

Panel accounts attach to players Bedrock has already observed. Three roles — Viewer, Operator, and Owner — control access to settings, lifecycle commands, and user management. Minecraft permission and CraftControl role are independent.

Generate the first one-time owner code after that player has joined Bedrock:

docker compose -f docker-compose.split.yml exec craftcontrol-backend \
  craftcontrol auth bootstrap --player VonCrush

Every authenticated mutation requires a CSRF token tied to the exact session and a valid same-origin request. See Local authentication and authorization for the full capability matrix, invitation flow, and session policy.

Player data and analytics

SQLite stores permanent profiles, aliases, presence, sessions, accumulated play time, permissions, deaths, event history, and optional structured telemetry. Disconnecting a player closes or infers the session; it never deletes the profile.

The Players area consolidates one player’s lifetime totals and breakdowns before recent evidence: kills by creature, blocks by type, exploration by dimension, sessions, deaths, and technical history. The Data area provides server-wide filtered and paginated views. Structured and derived deaths are deduplicated for display while raw evidence remains private.

Creature, block, projectile, navigation, action, state, and metric icons use original bundled SVG pixel art. Game identifiers are localized in Portuguese, English, and Spanish, with a localized neutral fallback for unknown identifiers. See Visual system rules.

An owner can export what the panel shows as JSON or CSV: player profiles, sessions, activity and deaths, plus the analytics rankings, periods, blocks, combat and exploration aggregates. Exports never contain XUIDs, tokens, addresses or raw server evidence, are bounded by documented ceilings and refused rather than truncated, and every attempt is audited. See Data exports.

Backups and recovery

CraftControl does not own the Minecraft world. The world remains in the Bedrock project; manager state lives in manager.db. SQLite migrations are transactional and create an immutable database backup before the first pending migration.

Use coordinated commands instead of copying a live database or world:

docker compose -f docker-compose.split.yml exec craftcontrol-backend craftcontrol backup create
docker compose -f docker-compose.split.yml exec craftcontrol-backend craftcontrol backup list
docker compose -f docker-compose.split.yml exec craftcontrol-backend craftcontrol backup verify BACKUP_ID

When Bedrock is running, the backup service holds saves only for the copy window and resumes them even after failure. Recovery sets include the world, SQLite database, server configuration, allowlists, permissions, Behavior Pack files, checksums, and a versioned manifest. Restore is deliberately offline and creates a pre-restore recovery copy.

See Coordinated backup and restore and Database migrations.

Independent releases and rollback

versions.env pins the tested frontend/backend pair. Deploy both or only the changed component:

bin/deploy-craftcontrol-release --check
bin/deploy-craftcontrol-release

bin/deploy-craftcontrol-frontend
bin/deploy-craftcontrol-backend

bin/deploy-craftcontrol-frontend --rollback VERSION
bin/deploy-craftcontrol-backend --rollback VERSION
bin/deploy-craftcontrol-release --rollback FRONTEND_VERSION BACKEND_VERSION

Frontend deployment proves that the backend container is unchanged. Backend deployment creates and verifies a coordinated backup, checks SQLite and persistent mounts, and proves the frontend container was not recreated. bin/cutover-craftcontrol-split performs the one-time split cutover and retains the combined image as the explicit emergency compatibility path.

The interface reads /version.json from the frontend and release metadata from the backend, keeping image activation separate from Behavior Pack installation and runtime response timestamps.

Development and quality gates

CraftControl uses Python 3.12, Flask, Gunicorn, SQLite, Docker SDK for Python, Nginx, and dependency-free browser JavaScript.

bin/check-frontend       # JS syntax, i18n, interaction and visual-contract tests
bin/check-backend        # Python application and persistence tests
bin/check-bedrock-proxy     # Standalone host-agent tests and coverage report
bin/check-contracts      # OpenAPI, route surface, Swagger, generated declarations
bin/check-integration    # Compose builds, split runtime, architecture and deploy safety
bin/check                # complete local gate

GitHub Actions and Gitea Actions run the six quality gates independently. Successful Gitea main runs deploy automatically through the repository-scoped homelab runner. See Contributing for commit conventions and PR workflow. See apps/server/controlplane/README.md for the backend package layout and test infrastructure reference. See Development setup for prerequisites, environment configuration, and common development tasks.

Security status

Current safeguards include local player-backed accounts, role capabilities, hashed one-time credentials, revocable opaque sessions, login throttling, security audit records, session-bound CSRF, origin validation, strict command allowlists, input validation, atomic configuration writes, hidden XUIDs, and no-new-privileges.

Remaining hardening work:

  1. replace direct Docker socket access with a restricted operations gateway;
  2. document and automate a supported TLS/reverse-proxy boundary;
  3. continue removing compatibility overlays after tested migration windows;
  4. expand community installation, diagnostics, and release automation.

For the full threat model, current safeguards, and hardening roadmap see docs/security.md. To report a vulnerability privately see SECURITY.md.

Contributing

See CONTRIBUTING.md for branch naming, PR title format, metadata requirements, Conventional Commits, quality gate, and CodeRabbit interaction.

Codex skills

If you use Codex, install the global cody-dr portable workflow plugin for issue authoring, delivery, reviews, and findings handling. CraftControl does not shadow those lifecycle skills locally; the plugin discovers the shared project profile automatically.

Skill When to use
backend Padrões Python: DI, Protocols, is None, composition root e fakes
frontend Padrões JS: injeção de deps, ESM, i18n e testes
manage-project Gerencia issues nos GitHub Project boards
manage-milestone Gerencia milestones e audita backlog

The local skills complement the plugin: Codex continues to follow AGENTS.md and the security instructions. A request to execute an issue até o PR (inclusive via link) autoriza branch, commit, push e abertura do PR; merge e deploy continuam exigindo pedido explícito.

The tool-neutral .dr-agents/craftcontrol/PROFILE.md contains the safeguards specific to Cody DR and Claudio DR reviews. Provide the profile path explicitly with the requested PR/ref — it does not load automatically. The profile augments generic review skills and does not trigger review by itself.

License and trademarks

Copyright 2026 Danilo Ramos.

CraftControl is licensed under the Apache License 2.0. The license applies to the original CraftControl source code, documentation, Telemetry Pack, and visual assets contained in this repository unless a file states otherwise.

CraftControl is independent and is not affiliated with Mojang Studios or Microsoft. Minecraft is a trademark of Microsoft Corporation.

About

Mobile-first web control panel for managing a self-hosted Minecraft Bedrock server, including settings, gamerules, players, world actions, and container operations.

Topics

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages