Add production Docker compose + on-startup PocketBase bootstrap

Introduce registry-pull production stacks (docker-compose.prod.yml) for
both the multi-container Docker setup and the all-in-one Docker AIO image,
with everything an operator needs (superuser, super-admin, ports, volumes)
driven from .env.

The API Server now bootstraps PocketBase on startup: a new internal/bootstrap
package (Go port of setup-pocketbase.mjs) creates missing collections,
reconciles existing ones, and creates the DriverVault super-admin from
DRIVERVAULT_SUPERADMIN_* when absent. Idempotent and gated by PB_BOOTSTRAP.
The PocketBase superuser is still upserted by the PocketBase container, since
the REST API cannot bootstrap the first superuser.

Move PocketBase to port 8070 (internal + published) and the web app to 8090
across both stacks, with matching CORS defaults.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
tajniak81andClaude Opus 4.8 committed 2026-07-19 15:35:33 +02:00
1 parent 1e76c2b7f9
commit 30c9cdebe9
17 files changed
+1042 -23

No files matched your search

+16
View File
@@ -36,6 +36,18 @@ type Config struct {
// the charger at, instead of deriving it from request headers.
OCPPRequireTLS bool
OCPPPublicURL string
// Bootstrap controls the on-startup PocketBase schema setup: when true (the
// default) the server creates any missing collections and reconciles existing
// ones against the desired schema, then ensures the super-admin below exists.
// It requires a configured service account; without one it is a no-op.
Bootstrap bool
// Super-admin account created during bootstrap when both fields are set and no
// user with that email exists yet. Existing accounts are left untouched.
SuperAdminEmail string
SuperAdminPassword string
SuperAdminName string
}
// EnvFile is the .env path (relative to the working directory) that Load reads
@@ -63,6 +75,10 @@ func Load() Config {
PocketBaseAdminPassword: firstEnv("POCKETBASE_ADMIN_PASSWORD", "PB_ADMIN_PASSWORD"),
OCPPRequireTLS: boolEnv("OCPP_REQUIRE_TLS", true),
OCPPPublicURL: strings.TrimRight(getenv("OCPP_PUBLIC_URL", ""), "/"),
Bootstrap: boolEnv("PB_BOOTSTRAP", true),
SuperAdminEmail: firstEnv("DRIVERVAULT_SUPERADMIN_EMAIL", "SUPERADMIN_EMAIL"),
SuperAdminPassword: firstEnv("DRIVERVAULT_SUPERADMIN_PASSWORD", "SUPERADMIN_PASSWORD"),
SuperAdminName: getenv("DRIVERVAULT_SUPERADMIN_NAME", "Administrator"),
}
}