Skip to content

ctqvva/JugglucoNG-Hub

Repository files navigation

JugglucoNG Hub

Screenshot

JugglucoNG Hub is a standalone mirror-first sync appliance for Juggluco and JugglucoNG.

It keeps compatibility with the current mirror protocol while adding:

  • a web admin UI
  • household management
  • calibration/profile ingestion
  • packaged deployment with prebuilt images
  • optional private-CA HTTPS without DNS or port 80/443 assumptions

Deployment Shape

The stack has three services:

  • mirror: native Juggluco mirror sidecar, default public TCP port 8795
  • hub: admin/API service, internal port 8787
  • proxy: bundled Caddy reverse proxy with private CA, default public HTTPS port 8443

Default public surfaces:

  • mirror protocol: 8795/tcp
  • admin UI: https://HOST:8443/

Internal only:

  • mirror web feed: 17580
  • hub HTTP: 8787

The stack does not assume ports 80/443. All public ports are configurable.

What Works Today

  • existing Juggluco/JugglucoNG mirror senders can target this server directly
  • follower/source QR generation works through the hub UI
  • mirrored calibration profiles are ingested
  • households can be created, renamed, and deleted in the admin UI
  • packaged releases can be installed without building on the target host
  • remote deploy over SSH is supported

Quick Start

Local one-click bootstrap

./scripts/one-click-compose.sh "Home CGM"

Optional fixed serial:

./scripts/one-click-compose.sh "Home CGM" "AIDEX-123"

That command:

  • ensures a container runtime is available locally
  • generates a private CA and server certificate under config/tls/
  • bootstraps one managed household and one admin token
  • writes .env.local
  • starts the full stack

Then:

  • point the source phone mirror sender to HOST:8795
  • open the admin UI at https://HOST:8443/
  • trust the generated CA if your browser/device requires it
  • use config/bootstrap-admin-token.json for first admin login

Day-to-Day Commands

Use the wrapper instead of raw Docker commands:

./scripts/hubctl.sh status
./scripts/hubctl.sh restart
./scripts/hubctl.sh logs
./scripts/hubctl.sh logs hub
./scripts/hubctl.sh logs mirror
./scripts/hubctl.sh stop
./scripts/hubctl.sh update
./scripts/hubctl.sh reset

Build a Deployable Release Bundle

This creates a release tarball with the source tree, scripts, and preloaded container images.

Standard docker-image release:

./scripts/build-release.sh

Lighter binary-artifact release that skips the native mirror build on the target host:

./scripts/build-release.sh --remote-binaries user@server

Output:

  • dist/JugglucoNG-Hub-release-src.tar.gz
  • dist/JugglucoNG-Hub-release-bin.tar.gz

If you run both commands, dist/ keeps both archives side by side.

Binary-artifact notes:

  • ships the mirror-native pieces that must match the build toolchain:
    • runtime/mirror/juggluco
    • runtime/mirror/lib/libjuice.so.1.6.2
    • runtime/mirror/lib/libstdc++.so.6
    • runtime/mirror/lib/libgcc_s.so.1
  • does not bundle caddy
  • for direct host-side mirror testing, use ./scripts/run-mirror-bin.sh instead of invoking runtime/mirror/juggluco naked

Included images:

  • jugglucong-hub:local
  • jugglucong-mirror:local
  • caddy:2-alpine

The target host does not need to build those images again.

Install a Release Bundle on a Host

For a copy-paste Ubuntu VPS walkthrough, see INSTALL-SERVER.md.

On the target host, unpack the release and run:

./scripts/install-release.sh \
  --household "Home CGM" \
  --public-host 203.0.113.10 \
  --https-port 8443 \
  --mirror-port 8795

Optional flags:

  • --serial SERIAL
  • --mirror-host HOST
  • --tls-alt-names "dns:example.com,ip:203.0.113.10"
  • --skip-load if images are already present

What it does:

  • loads bundled images when the release includes them
  • otherwise uses the packaged mirror binary runtime and builds only the light container wrapper on the host
  • generates private CA + server certificate
  • writes runtime config
  • boots the appliance

Maintenance helpers:

  • ./scripts/update-release.sh re-runs the installer for the current bundle
  • ./scripts/uninstall-release.sh removes the stack and data volumes
  • ./scripts/uninstall-release.sh --purge-config also removes local .env.local and bootstrap token files

Deploy Remotely Over SSH

From your local machine:

./scripts/deploy-remote.sh \
  --target user@server \
  --key ~/.ssh/id_ed25519 \
  --household "Home CGM" \
  --public-host 203.0.113.10 \
  --https-port 8443 \
  --mirror-port 8795

Optional flags:

  • --remote-dir /opt/jugglucong-hub
  • --serial SERIAL
  • --mirror-host HOST
  • --tls-alt-names "dns:example.com,ip:203.0.113.10"
  • --bundle /path/to/JugglucoNG-Hub-release-src.tar.gz
  • --bundle /path/to/JugglucoNG-Hub-release-bin.tar.gz
  • --bootstrap-docker
  • --no-bootstrap-docker
  • --sudo auto|always|never

What it does:

  • builds the release bundle locally if needed
  • uploads it with scp
  • optionally bootstraps Docker on the remote host
  • installs into the remote directory
  • starts the appliance there

TLS Model

Default TLS mode is private-ca.

That means:

  • no DNS is required
  • no public ACME/Let’s Encrypt flow is required
  • no assumption that ports 80/443 are free
  • browsers and devices may need to trust the generated CA certificate manually

Generated files:

  • config/tls/ca.crt
  • config/tls/ca.key
  • config/tls/server.crt
  • config/tls/server.key
  • config/tls/issued-for.txt

The admin UI exposes:

  • secure admin URL
  • CA fingerprint
  • server fingerprint
  • CA download at /ca.crt

Runtime Data

Runtime data is stored in Docker named volumes by default:

  • jng_hub_data
  • jng_mirror_data

Local repo paths are not used for live application state anymore.

Local config stays under:

  • config/
  • .env.local

Back up:

  • config/
  • Docker volume jng_hub_data
  • Docker volume jng_mirror_data

Admin UI

Current admin UI supports:

  • bootstrap admin login
  • mirror target/profile display
  • source/follower QR generation
  • household list
  • household create
  • household rename
  • household delete
  • overview, recent events, audit trail
  • CA download and TLS fingerprints

Mirror Setup

Source phone:

  • point the current mirror sender to HOST:MIRROR_PORT
  • use the generated source QR if preferred

Follower phone:

  • use the generated follower QR
  • no follower IP entry is required in the admin UI

The mirror sidecar remains the compatibility transport. The hub sits on top of it.

Environment

Copy .env.example to .env.local only if you want to edit values manually.

Important variables:

  • JNG_PORT
  • JNG_MIRROR_PORT
  • JNG_MIRROR_PUBLIC_HOST
  • JNG_MIRROR_PUBLIC_PORT
  • JNG_PUBLIC_TLS_MODE
  • JNG_PUBLIC_HOST
  • JNG_PUBLIC_HTTPS_PORT
  • JNG_PUBLIC_TLS_ALT_NAMES
  • JNG_PUBLIC_CA_CERT
  • JNG_PUBLIC_SERVER_CERT
  • JNG_PUBLIC_SERVER_KEY

Mirror ingest bridge variables are bootstrapped automatically.

Resource Expectations

On a real Linux VPS, the runtime footprint is modest.

Rough practical target:

  • personal/family use: 1 vCPU / 1 GB RAM
  • small shared host: 2 vCPU / 2 GB RAM

The large memory number seen on macOS during local development is mostly Colima/VM overhead, not the hub process itself.

Current Limitations

  • the current mirror-first ingestion still depends on the sidecar web feed plus calibration files
  • direct richer NG sync is not the primary path yet
  • retention modes such as relay-only or recent-only are not implemented yet
  • full public multi-tenant SaaS hardening is still future work

Development Notes

  • runtime state is intentionally gitignored
  • build/release artifacts live under dist/
  • the release path is the supported deployment path when you do not want on-site builds

About

Standalone mirror-first sync appliance for Juggluco and JugglucoNG

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors