Install, Update & Upgrade ZERONE GRC
A complete, copy-and-run guide for installing the ZERONE GRC platform (customer edition) in your own environment with Docker Compose — then keeping it current with safe update, upgrade, backup and rollback procedures.
01 Overview
The customer edition of ZERONE GRC is a self-contained build you install in your own environment. It runs as a Docker Compose stack: a FastAPI backend serving a static frontend, backed by SQLite (default) or PostgreSQL. You install it, log in, activate your license, and use your licensed GRC modules.
- Deployment model: on-prem, private cloud, VPS or internal server — anywhere Docker runs.
- First boot is automatic: the database schema, your administrator account, and a stable deployment identity are created on the first start.
- License-verified: your installation verifies license signatures with the vendorpublic key only. Vendor-only APIs are removed at boot and return
404by design.
02 System Requirements
| Component | Minimum | Recommended |
|---|---|---|
| CPU | 2 vCPU | 4 vCPU |
| RAM | 4 GB | 8 GB |
| Disk | ~5 GB free (images + data) | 20 GB+ (with backups/logs) |
| OS | 64-bit Linux or Windows | Linux LTS (server) |
| Container runtime | Docker + Docker Compose v2 | Latest stable Docker Engine |
| Database | SQLite (bundled) | PostgreSQL (opt-in, for scale) |
| Network port | 8000 (app) | 443 via TLS reverse proxy |
| Internet | Not required (offline license) | Outbound only for online license / vendor connectivity |
| TLS/HTTPS | Required in production | Reverse proxy or external load balancer |
APP_ENV=staging and SECURE_COOKIES=false. Production must use HTTPS.03 Pre-Install Checklist
Confirm each item before you begin:
- Host provisioned and OS updated (64-bit, Docker + Compose v2 installed).
- Docker can write to the working directory (for
licenses/,logs/,backups/). - The installation package
zerone-grc-customer-install-package-v<version>.zipis on the host. - Your vendor license file (
.lic) and the accompanying public key are available. - Application URL / hostname decided (e.g.
grc.your-company.local). - Administrator username, email and a strong initial password decided.
- For production: TLS certificate (
fullchain.pem/privkey.pem) ready, or TLS terminated at your load balancer. - Backup location confirmed and an installation window agreed.
04 Installation (Docker Compose)
Extract the package
unzip zerone-grc-customer-install-package-<version>.zip
cd zerone-grc-customer-install-packageCreate your configuration
Copy the template, then edit the values described inEnvironment Configuration.
cp config/.env.example config/.env
# edit config/.env → set APP_URL, ADMIN_* and ZERONE_LICENSE_PUBLIC_KEYJWT_SECRET_KEY, VAULT_ENCRYPTION_KEY and FILE_ENCRYPTION_KEYat their CHANGE-ME values — the installer generates strong values automatically.Run the installer
It checks Docker, generates missing secrets, creates the runtime folders, then builds and starts the stack.
bash install/install.sh
.\install\setup.ps1
To use PostgreSQL instead of SQLite, set DATABASE_URL in config/.env and start with the postgres profile:
docker compose --profile postgres up -d --build
Wait for healthy
The installer polls the health endpoint and reports the local URL when the platform is ready. If it does not become healthy, inspect the logs:
docker compose logs -f zerone-app
05 Environment Configuration
All configuration lives in config/.env. Set the values below; everything else has safe defaults. Never commit or share this file — it holds your generated secrets.
| Variable | Set to | Notes |
|---|---|---|
APP_URL | Your platform URL | e.g. https://grc.your-company.local |
ADMIN_USERNAME | First admin login | Your initial administrator |
ADMIN_EMAIL | Admin email | Used to log in the first time |
ADMIN_PASSWORD | Strong password | Remove after first login |
ZERONE_LICENSE_PUBLIC_KEY | Vendor public key | Ships with your license |
DATABASE_URL | Leave default (SQLite) | Or postgresql+psycopg2://… |
APP_PORT | Leave 8000 | Change only if the port is taken |
APP_ENV | production | staging for an HTTP-only trial |
SECURE_COOKIES | true | false only for non-TLS trials |
BEHIND_PROXY | true if fronted by a proxy/LB | Honors X-Forwarded-* |
JWT_SECRET_KEY | Leave CHANGE-ME | Auto-generated by installer |
VAULT_ENCRYPTION_KEY | Leave CHANGE-ME | Auto-generated by installer |
FILE_ENCRYPTION_KEY | Leave CHANGE-ME | Auto-generated by installer |
Example (placeholders only — no real secrets):
APP_URL=https://grc.your-company.local APP_ENV=production SECURE_COOKIES=true ADMIN_USERNAME=admin ADMIN_EMAIL=[email protected] ADMIN_PASSWORD=<strong-initial-password> ZERONE_LICENSE_PUBLIC_KEY=<paste-vendor-public-key> # leave these — the installer fills them in: JWT_SECRET_KEY=CHANGE-ME VAULT_ENCRYPTION_KEY=CHANGE-ME FILE_ENCRYPTION_KEY=CHANGE-ME # DATABASE_URL=postgresql+psycopg2://user:pass@postgres:5432/zerone
06 First Boot & Login
On the very first start the platform automatically: creates the database schema, creates your administrator from the ADMIN_* values, generates a stable deployment identity (deployment_id), and locks all built-in default accounts.
- Open
APP_URL(orhttp://localhost:8000). - Log in with
ADMIN_EMAIL/ADMIN_PASSWORD. - Change the password when prompted.
- Remove
ADMIN_PASSWORDfromconfig/.env.
*.grc.local demo accounts are intentionally locked and cannot be used — this is expected.07 License Activation
After first login, go to Administration → License Management and activate your license (offline upload of the .lic file, or optional online activation).
- Your license binds to this installation's
deployment_id(stored in the database). - Each license entitles updates up to its
max_supported_versionand support untilsupport_until— visible on License Management → Overview. - Provide your Deployment ID (Administration → System Information) when requesting or renewing a license.
08 HTTPS / TLS (production)
Production requires HTTPS. Either terminate TLS at your own load balancer (setBEHIND_PROXY=true) or use the bundled nginx reverse-proxy profile:
Place your certificate
Put fullchain.pem and privkey.pem into docker/certs/.
Configure the proxy
Copy the sample and set your server_name:
cp docker/nginx.conf.example docker/nginx.conf
# edit docker/nginx.conf → set server_name to your domainStart with the proxy profile
docker compose --profile proxy up -d
The proxy redirects HTTP→HTTPS, terminates TLS 1.2/1.3 with HSTS, and forwards to the app on port 8000.
A record for your app hostname (e.g. grc.your-company.local → server IP). Certificates are supplied by you — there is no automatic issuance.09 Service Management
bash install/start.sh # start bash install/stop.sh # stop (data preserved) bash install/restart.sh # restart (deployment_id unchanged) bash install/healthcheck.sh # liveness + DB readiness docker compose logs -f zerone-app # follow logs
docker compose down -v destroys the data volumes and changes your deployment_id (invalidating the license). Use it only to wipe the deployment on purpose.10 Update patch / minor
An update is a same-major release (e.g. 1.9.2 → 1.9.3) delivered as a new package — bug fixes, security patches and small features, normally within your current license. It is low-risk and uses the same steps as an upgrade:
Back up first
Always snapshot the database, config/.env and licenses/ — seeBackup & Restore.
Stop the stack
bash install/stop.sh
Swap in the new package
Replace the package contents with the new version, keeping config/.env,./licenses, and the app-data / pg-data volumes (donot delete volumes).
Rebuild & start
docker compose up -d --build
Schema changes apply automatically on boot (additive idempotent migrations on SQLite; new tables created on PostgreSQL).
Verify
bash install/healthcheck.sh
Then check Administration → System Information for the new version andLicense Management → Overview.
11 Upgrade new version
An upgrade moves to a new feature version. The mechanical steps are identical to anUpdate above — but first confirm license compatibility:
max_supported_version and support_until onLicense Management → Overview. A license only entitles updates up to itsmax_supported_version; going beyond it requires a renewed license. Until a valid license is installed, the platform may run in a limited/grace state.- Back up the database,
config/.envandlicenses/. - Verify the target version is within (or below) your license
max_supported_version; renew the license if not. bash install/stop.sh- Replace the package with the new version, keeping
config/.env,./licensesand the data volumes. docker compose up -d --build— migrations run automatically on boot.- Review the release notes for any version-specific manual steps.
- Verify with
bash install/healthcheck.sh, then System Information andLicense Management.
deployment_id lives in the database and is preserved across upgrades, so your license stays bound and valid.12 Backup & Restore
Back up before every update/upgrade and on a regular schedule. Store backups encrypted and off-host. Back up three things: the database, config/.env (your secrets), and./licenses.
SQLite (default)
# Backup docker compose exec zerone-app sh -c 'cp /data/zerone.db /srv/backups/zerone-$(date +%F).db' # Restore (stop app first) docker compose stop zerone-app docker compose run --rm -v "$PWD/backups:/b" zerone-app sh -c 'cp /b/zerone-YYYY-MM-DD.db /data/zerone.db' docker compose start zerone-app
PostgreSQL (opt-in)
# Backup docker compose exec postgres pg_dump -U "$POSTGRES_USER" "$POSTGRES_DB" > backups/zerone-$(date +%F).sql # Restore (into an empty database) cat backups/zerone-YYYY-MM-DD.sql | docker compose exec -T postgres psql -U "$POSTGRES_USER" "$POSTGRES_DB"
Config & licenses
cp config/.env backups/env-$(date +%F).bak tar czf backups/licenses-$(date +%F).tgz licenses/
deployment_id lives in the database, and config/.env holds the keys that decrypt vault data. Restoring the samedatabase + .env keeps your license valid and your encrypted data readable.13 Rollback
If an update/upgrade misbehaves, roll back to the previous version:
bash install/stop.sh- Restore the pre-upgrade database backup (see Backup & Restore).
- Re-deploy the previous package version.
- Start and verify:
bash install/start.shthenbash install/healthcheck.sh. - Confirm license status under License Management → Overview.
14 Verify & Health
Confirm the platform is healthy and functional after install or upgrade:
bash install/healthcheck.sh # liveness + DB readiness curl -fsS http://localhost:8000/health/live # liveness (200) curl -fsS http://localhost:8000/health/ready # DB connectivity (200/503)
Then spot-check in the UI:
- Login works and the admin password change was enforced.
- System Information shows the expected version and Deployment ID.
- License Management → Overview shows an active, valid license.
- Create a user, a risk and an incident; upload a file; confirm the audit log records actions.
- HTTPS is enforced (production) and a restart preserves data.
15 Troubleshooting
First stop for everything: docker compose logs -f zerone-app andbash install/healthcheck.sh.
▲ App does not start
Secrets still at CHANGE-ME, or a production config error (SECURE_COOKIES/APP_DEBUG), or the port is taken.
Re-run bash install/install.sh (it generates secrets), or change APP_PORT. For an HTTP trial: APP_ENV=staging,SECURE_COOKIES=false.
docker compose logs zerone-app
▲ Cannot log in
Wrong credentials, or HTTPS-only cookies over plain HTTP.
Use ADMIN_EMAIL/ADMIN_PASSWORD fromconfig/.env (first boot). Built-in *.grc.local accounts are locked. Over HTTP set SECURE_COOKIES=false or use the TLS proxy.
▲ Database connection error
Volume not writable (SQLite) or wrong Postgres profile/credentials.
SQLite: ensure app-data is writable andDATABASE_URL=sqlite:////data/zerone.db. Postgres: start with--profile postgres, host postgres, matching POSTGRES_*.
docker compose logs postgres
▲ License invalid / rejected
Modified file or wrong public key; deployment-ID mismatch; expired.
Re-download the .lic and set the correctZERONE_LICENSE_PUBLIC_KEY. For a mismatch, re-export the request (Activation tab) and have it re-issued for this deployment_id. If expired, obtain a renewal.
▲ Deployment ID changed
You are pointing at a fresh/empty database (volume deleted or DB backend switched).
Restore your DB backup, or have the license re-issued for the newdeployment_id.
▲ A module is locked
Your license does not enable that module (enforced in the backend).
Check License Management → Modules; contact your vendor to add it.
▲ Asset limit reached
Only Active/Managed assets consume a seat.
Free seats or raise the limit — seeLicense Management → Usage / Discovery Impact. Discovery keeps running.
▲ Vendor pages/APIs return 404
This is the customer edition — vendor portal pages and/api/vendor/*, /api/updates/* are not shipped.
None needed — the 404 is by design, not a fault.
▲ Docker errors
permission denied on volumes, or a stale build.
Ensure Docker can write to ./licenses, ./logs,./backups. Clean rebuild: docker compose build --no-cache zerone-app.
16 Support
When contacting support or requesting/renewing a license, always include your Deployment ID(Administration → System Information) and the platform version. Full reference docs ship in the package under docs/: INSTALL.md, UPGRADE.md,BACKUP_RESTORE.md, LICENSE_ACTIVATION.md, TROUBLESHOOTING.md.
Vendor contact: [email protected]
