Repository navigation
Installation and Deployment
See Host Networking for the current Linux container topology, loopback-only maintenance API, explicit add-on migration, listener ports and recovery rules.
Ubuntu host
├── /opt/classroom-hub
├── classroom-hub-host-agent.service
│ └── /run/classroom-control-hub/host-agent.sock
└── Docker
├── classroom-control-hub
└── classroom-control-hub-maintenance
The previous Caddy/TLS service has been removed for now. The current appliance exposes direct HTTP on port 3000 while HTTPS is redesigned.
http://APPLIANCE-IP:3000/controller/
Default values:
HUB_BIND_ADDRESS=0.0.0.0
HUB_PORT=3000
TRUST_PROXY_HOPS=0
Installer reruns and web-managed updates preserve a valid explicit proxy-hop
count and default to 0 only when absent. Same-host HTTPS proxy use still
requires direct backend access to be blocked.
Restrict the port to the trusted classroom/admin network and do not expose this temporary HTTP-only deployment directly to the public Internet.
The standard production checkout is /opt/classroom-hub. Older references to /opt/classroom-control-hub are migration-era defaults unless a deployment intentionally chose a custom path.
Recommended baseline:
- Ubuntu Server 24.04 LTS on
amd64;arm64is not supported until its images and Android/ADB toolchain are validated - Docker Engine with Docker Compose v2
- Git
- persistent storage for application data and backups
- trusted LAN/firewall controls for TCP/3000
For a clean Ubuntu Server 24.04 LTS amd64 host:
curl --proto '=https' --tlsv1.2 -fsSL \
https://raw.githubusercontent.com/wagnerks1990/RoomGoblin/main/deploy/bootstrap.sh \
-o /tmp/classroom-hub-bootstrap.sh
sudo bash /tmp/classroom-hub-bootstrap.shThe HTTPS command above is only for securely downloading the bootstrap from GitHub. The installed Hub currently uses HTTP.
The bootstrap generates unique appliance credentials, verifies the running components, and prints the first-time administrator setup URL. It refuses to replace an existing deployment by default; use the controller's update/revert workflow for an installed appliance.
Install a compatible release normally, establish administrator access, then use
Infrastructure & Recovery → Import Full Recovery to restore one encrypted
.rgbak. Submit its separately stored 16-character-or-longer passphrase only
through loopback or HTTPS terminated by a same-host loopback reverse proxy; never through the temporary
direct-HTTP LAN URL.
For the same-host TLS proxy, configure its exact TRUST_PROXY_HOPS value and firewall
direct client access to port 3000. Otherwise a client could bypass the proxy and
forge forwarded transport headers. Leave the value at 0 for direct/loopback
deployments.
The operation stages beneath ${HOST_BACKUP_DIR}/recovery-staging, serializes
against application updates, takes a complete safety snapshot and maintains a
durable Host Agent journal until commit and verification finish. Preserve this
state after any failure so automatic rollback can complete. RoomGoblin restores
only its owned service state and never replaces adopted/external services.
Before declaring success, verify database/schema/secret health, login and site identity, schedules/displays/automations, Morning Announcements and Background Music recovery, assets, Android inventory and ADB trust without re-pairing, Android signing identity, Veyon/lab state, owned service lifecycle, and version convergence. See Database-First Recovery for limits, the full operator drill and rollback rules.
Custom roots can be supplied when required; keep them separate and beneath /opt:
sudo CLASSROOM_HUB_DIR=/opt/classroom-hub \
CLASSROOM_HUB_SERVICES_DIR=/opt/classroom-services \
CLASSROOM_HUB_BACKUP_DIR=/opt/classroom-backups \
bash /tmp/classroom-hub-bootstrap.shFor manual installation or migration:
sudo git clone https://github.com/wagnerks1990/RoomGoblin.git /opt/classroom-hub
cd /opt/classroom-hub
sudo cp .env.example .env
sudo bash install.shThe supported production installer pulls the exact sha-<commit> main and
maintenance images published after GitHub validation. It does not compile Gradle,
JitPack, or Node dependencies on the appliance. sudo bash install.sh --build-local
is an explicit development-only escape hatch.
The images are also rejected unless their org.opencontainers.image.revision
label equals the exact trusted Git commit, even if their displayed RoomGoblin
version matches.
The installer fills blank appliance secrets automatically, preserves the old master key when present, repairs the shared data-root ownership model, restarts the Host Agent, removes obsolete TLS settings/Caddy containers, starts the HTTP-only application, and verifies component convergence.
Shared roots:
/opt/classroom-hub/data root:10001 0770
/opt/classroom-hub/data/backups root:10001 0700
Application-owned files remain 10001:10001.
Master key:
/etc/classroom-control-hub/master.key
An older /etc/classroom-hub/master.key must be migrated instead of silently replaced.
The web controller follows exact trusted main commits through classroom-hub-app-update.service. The native transaction requires the matching validated Hub/maintenance image pair before mutation, creates the operational recovery backup, and restores the previous source/state if backend HTTP, maintenance, Host Agent, database/scheduler, mount or version checks fail. Do not pull source first; follow Main-based updates.
Manual update:
sudo bash /opt/classroom-hub/deploy/update-production.sh --plan
sudo bash /opt/classroom-hub/deploy/update-production.shMain is the sole source, but its exact published image pair is required before source/runtime mutation. Do not pull source first. Follow Main-based updates for the one-time transition from the retired production-branch wrapper; retain the native backup/journal/health/rollback safeguards.
Development rebuild after a valid install:
sudo docker compose build --no-cache
sudo docker compose up -d --remove-orphans
sudo docker compose ps
curl -fsS http://127.0.0.1:3000/health--remove-orphans removes the old TLS container when upgrading from a Caddy-based release.
Before converting an existing installation to Git:
- Back up the current application tree and database.
- Preserve
.env, persistent data, media/uploads, backups, keys, and site configuration. - Clone the repository into the standard production path.
- Restore only runtime state; do not copy legacy tracked source over the Git checkout.
- Verify the Host Agent service uses
/opt/classroom-huband/run/classroom-control-hub/host-agent.sock. - Ensure
MAINTENANCE_TOKENis non-empty before recreating maintenance. - Confirm the shared data-root ownership matches the documented root/group model.
- Run
sudo bash install.shso obsolete Caddy/TLS state is removed safely. - Validate controller, displays, automations, Morning Announcements, Background Music, class schedule rules, and integrations.
- Retain a known-good rollback snapshot until the new deployment is verified.
sudo systemctl status classroom-hub-host-agent.service --no-pager -l
sudo test -S /run/classroom-control-hub/host-agent.sock && echo "Host Agent socket OK"
sudo docker exec classroom-control-hub-maintenance ls -la /run/classroom-control-hub/During the HTTP-only phase, enrollment requires explicit acknowledgement:
.\Install-Agent.ps1 -HubUrl http://APPLIANCE-IP:3000 -AllowHttpUse this only on a trusted network.
The public repository intentionally contains generic defaults. After migration, configure MQTT/Govee, Pluto, Veyon, Music Assistant, stream URLs, device mappings, and school calendar rules through the controller. Existing .env integration values remain first-start/migration fallbacks; database values become authoritative after the corresponding GUI settings are saved.
Optional or slow integration probes must not delay the initial controller Overview screen, and one integration failure must not falsely mark another integration offline.
Preserve at minimum:
- SQLite database/runtime data
-
.envand site configuration - uploaded media/assets
- integration configuration
- master/private keys required for recovery
- off-host copies of important backups
Container images and tracked source are replaceable. Runtime state is not.
Recovery backups can contain site configuration, internal addresses, device/user/student data, media, and secrets. Treat them as sensitive administrative records and confirm that sensitivity explicitly when creating them. Full backups require an additional secrets confirmation.
Only the metadata-only diagnostic archive is intended for support. It
excludes databases, runtime data, managed-service state, device/ADB identity,
student records, .env, and keys. Inspect it before sharing.
HTTPS should return only as a separately reviewed feature with DNS/SNI testing, client trust guidance, rollback coverage, and no circular health dependency. Do not reintroduce Caddy ad hoc through local Compose edits.
-
ESPHome devices — native enrollment, security boundaries, supported controls, and recovery behavior.
-
ESPHome discovery — automatic mDNS discovery and adoption of already-flashed devices.