Przejdź do treści

SmartBox Infrastructure

📖 Online: docs.smartbox.ergoflow.app/components/infra/

Docker Compose stack for the entire SmartBox platform.

Stack

Service Image Public URL Auth
Traefik traefik:latest traefik.smartbox.ergoflow.app basic auth
Postgres postgres:16-alpine internal only postgres user
Redis redis:7-alpine internal only password
RabbitMQ rabbitmq:3.13-management-alpine rabbit.smartbox.ergoflow.app RMQ user
Keycloak quay.io/keycloak/keycloak:26.0 auth.smartbox.ergoflow.app KC admin
Gitea gitea/gitea:1.22 git.smartbox.ergoflow.app Gitea user
Portainer portainer/portainer-ce:lts ops.smartbox.ergoflow.app Portainer user
Dozzle amir20/dozzle:latest logs.smartbox.ergoflow.app basic auth
Backend smartbox/backend:latest (built) api.smartbox.ergoflow.app OIDC + API key
Docs smartbox/docs:latest (built — MkDocs Material → nginx) docs.smartbox.ergoflow.app public

All services share the smartbox Docker network. Only Traefik exposes ports to the host (80, 443); everything else is reachable only through Traefik.

First-time deploy (fresh Ubuntu 24.04 LTS host)

```bash

1. Get the code on the server (rsync/tar from workstation, or git clone)

target: /opt/smartbox (chown to your user)

2. Install Docker + firewall

cd /opt/smartbox/infra make bootstrap

log out and back in so docker group takes effect

3. Generate .env with strong random secrets

make env

NOTE: copy the printed admin password — it is NOT stored in .env

4. Bring infra up (backend will fail until step 6, that's fine)

make up

5. Bootstrap Keycloak realm (creates smartbox realm + clients +

seed admin user). Run once after Keycloak is healthy.

bash keycloak/bootstrap-realm.sh

COPY the printed seed-user password — KC admin has it via UI but

this script only reports it on first run.

6. Build + deploy backend

docker compose build backend docker compose up -d backend ```

Day-to-day

bash make ps # list services + status make logs # tail all make logs-backend # tail one make health # docker ps with status make update # pull + recreate make down # stop everything

Deploying backend / panel / kiosk changes

The canonical flow today is manual tar | ssh from the workstation — no registry, no Gitea Actions, no make update for app code. The Gitea remote is the audit trail; the source of truth that runs is what gets tared up.

```powershell

On workstation (PowerShell):

cd C:\Projekty\SmartBox git commit -am "etap-X.Y: …" git push gitea main

Ship backend (or frontend-web) source to the VM

tar -czf - backend infra | ssh smartbox-pub "cd /opt/smartbox && tar -xzf -"

Build + restart the affected service on the VM

ssh smartbox-pub "cd /opt/smartbox/infra && docker compose build backend && docker compose up -d backend && docker compose logs backend --tail=80" ```

For the kiosk: build a Windows release locally, zip it, scp into the backend's release volume, then INSERT a MachineRelease + MachineReleaseAssignment row — the SmartBoxKioskAgent PowerShell task on the kiosk picks it up within 30 s. Recipe in the project root README.md → "Pushing an OTA update".

(Will be one git push triggering Gitea Actions in etap 8 — make update in the table above is the old "pull from registry" path that we don't use.)

Hairpin NAT note

If port 443 to the public IP doesn't loop back through the router, the backend container reaches Keycloak via extra_hosts: host-gateway — the container resolves auth.smartbox.ergoflow.app to the docker-host gateway, and from there the request goes through Traefik. JWKS validation, KC admin calls, and JIT user provisioning all work without a hairpin-capable router.

Subdomain DNS prerequisite

These A records must point to the server's public IP before running make up for the first time, otherwise the HTTP-01 ACME challenge fails:

smartbox.ergoflow.app api.smartbox.ergoflow.app auth.smartbox.ergoflow.app git.smartbox.ergoflow.app docs.smartbox.ergoflow.app ops.smartbox.ergoflow.app logs.smartbox.ergoflow.app traefik.smartbox.ergoflow.app rabbit.smartbox.ergoflow.app

Files

infra/ ├── docker-compose.yml ├── .env.example template; .env (gitignored) is generated by gen-env.sh ├── Makefile convenience commands ├── docs/ │ ├── Dockerfile multi-stage MkDocs Material build → nginx alpine │ └── nginx.conf gzip + cache rules for the static site ├── keycloak/ │ └── bootstrap-realm.sh one-shot realm + clients + seed admin ├── postgres/ │ └── init.sh creates per-app users + databases on first cluster boot ├── scripts/ │ ├── bootstrap-server.sh installs Docker, ufw, make on the host │ └── gen-env.sh generates .env + traefik admin htpasswd └── traefik/ └── dynamic/ ├── middlewares.yml security headers + admin basic-auth └── users.htpasswd generated; gitignored

Service-specific first-run notes

  • Portainer: visit https://ops.smartbox.ergoflow.app within 5 minutes of first start and set the admin password (built-in safety lockout). If you miss the window, docker compose restart portainer resets it.
  • Keycloak: log in to https://auth.smartbox.ergoflow.app with KEYCLOAK_ADMIN / KEYCLOAK_ADMIN_PASSWORD from .env. Realm smartbox is created by bootstrap-realm.sh.
  • Gitea: log in with the seed admin (created via CLI on first deploy). HTTPS-only push, no SSH.
  • RabbitMQ: management UI at https://rabbit.smartbox.ergoflow.app, default user/password from .env (RABBITMQ_USER, RABBITMQ_PASSWORD).
  • Backend: /health at https://api.smartbox.ergoflow.app/health, Swagger UI at /docs. JWT bearer or X-Machine-Api-Key required for protected endpoints.
  • ErgoFlow integration (etap 6): the backend talks to the customer's upstream HR system at the URL configured under System → Integracje → ErgoFlow → Synchronizacja in the panel. No infra changes required — the integration runs entirely inside the backend container. The only outbound dependency is HTTPS access from the host to the configured ErgoFlow base URL (typically garos.ergoflow.app).