Troubleshooting¶
The common surprises during install, in the order you tend to hit them.
Google Workspace setup¶
Org policy blocks service-account key creation¶
When you click Add key → Create new key → JSON in Google Workspace setup §3, the dialog refuses with:
An organisation policy that blocks service accounts key creation has been enforced on your organisation.
This is the GCP org constraint iam.disableServiceAccountKeyCreation. It's a defensible security default — Google recommends it — but it blocks ARIS's current install path: core reads the service-account JSON from disk and exchanges it for a Workspace API token via DWD.
Three paths forward, in order of preference.
A. Override the policy at the ARIS project level (recommended)¶
This is the simplest path: the override itself is the scope, so no tag or condition is needed.
- With the ARIS project selected in the top-of-page resource picker, open IAM & Admin → Organisation policies.
- Find Disable service account key creation. Open it.
- Manage policy. Confirm Applies to: Project '\<your-aris-project>' at the top.
- Set Policy source to Override parent's policy.
- Under Rules, on the New rule card, set Enforcement to Off.
- Leave Add condition alone — you don't need one. (The "Condition builder" is for narrowing the exception further inside this project, e.g. only for tagged resources. ARIS doesn't need that — you want the override to apply project-wide.)
- Set policy.
Re-run §3 — the Create new key button now works for the ARIS project only. Every other project in the org keeps inheriting the org-level "On".
If you don't have Org Admin or Project Owner access, send the policy page link to whoever does and ask for the project-level override above (not an org-wide toggle). That keeps org-wide protection intact while unblocking ARIS.
B. Use a pre-existing key¶
Keys created before the policy was enforced are not revoked retroactively. Check the service account's Keys tab. If you (or a colleague) generated a JSON key earlier and still have the file, use it — set ARIS_GOOGLE_SERVICE_ACCOUNT_KEY_FILE to that path and skip the Add key step entirely.
C. Wait for keyless auth (no current support)¶
ARIS today reads ARIS_GOOGLE_SERVICE_ACCOUNT_KEY_FILE as a JSON key on disk. Keyless alternatives (Workload Identity Federation, ambient Application Default Credentials with impersonation) are not wired into core in the current MVP. If your security posture forbids JSON keys org-wide and an exception is off the table, this is a feature request, not a config change. The DWD authorisation in §4 is orthogonal — it stays the same regardless of how the service-account token is obtained — so the feature is a small swap of the credential source, not a re-architecture.
Boot¶
core exits at boot with missing ARIS_AUTH_TOKEN_SECRET ...¶
.env is incomplete or hasn't been picked up by Docker Compose.
- Confirm
.envexists at the repository root (the same directory ascompose.yml). Compose only reads.envfrom the project root, not from arbitrary subdirectories. - Confirm the variable in question is non-empty in
.envand not commented out. - If you populated
.envwhile compose was already running, you needdocker compose down && docker compose up— running containers do not pick up.envchanges.
core exits at boot with ARIS_AUTH_TOKEN_SECRET must be at least 32 bytes¶
Your secret is too short. openssl rand -hex 32 produces 64 hex characters, which is 32 bytes — exactly the minimum. Anything shorter is rejected at boot to prevent issuing weak tokens.
core boots but the first sync errors out with a Google API failure¶
unauthorized_clientoraccess_denied→ domain-wide delegation isn't authorised for the service account, or the wrong scopes are listed. Re-check Google Workspace setup §4. The two scopes must be the read-only variants exactly as listed there.invalid_grant→ the delegate email isn't a real Workspace user, or it doesn't have admin permissions to read the directory. Use a Super Admin account.key file not found/invalid private key→ the service-account JSON path in.envis wrong, or the file isn't readable by the user running Docker. Confirm with the verification command in Configure §4.
Postgres healthcheck never passes¶
Most often: POSTGRES_PASSWORD contains a special character that confused the shell. Wrap the value in single quotes in .env:
Login¶
/login?error=UnknownIdentity¶
Your Google account has no authentication_identity row in ARIS. Two causes:
- Sync hasn't run yet, or hasn't run since you joined the Workspace domain. Check
docker compose logs core | grep 'directory.sync.run report'. If you see a recent run witherrorsnon-zero, fix the sync error first. - Your account is in a different Workspace domain than
ARIS_GOOGLE_DOMAIN. ARIS only links identities for users in the configured domain.
/login?error=PersonInactive¶
A person row exists but its status is not active — usually external_deleted (the user disappeared from a previous Workspace sync) or deactivated (the user is Suspended=true or Archived=true in Workspace).
To recover: reactivate the user in Google Workspace and wait for the next sync (default 1 hour) or restart core to trigger a boot sync.
/login?error=EmailUnverified¶
Google reports email_verified=false for the account. Workspace-managed accounts are always verified; this typically means you tried to log in with a personal Gmail address that isn't part of your Workspace domain. Use a Workspace user instead.
/login?error=AccessDenied¶
The Google user is not allowed to use this OAuth client.
- The OAuth consent screen is set to Internal but the user is not in the configured Workspace domain.
- The OAuth consent screen is set to External / Testing and the user is not on the test-user list.
Either move the user into the right Workspace domain or change the consent screen to Internal (recommended for production).
/login?error=Callback¶
NextAuth's catch-all error. Two common causes:
- Redirect URI mismatch. The URI registered on the OAuth client must exactly match
${NEXTAUTH_URL}/api/auth/callback/google. Mismatch (e.g. http vs https, or a port typo) produces a Google-side rejection that NextAuth surfaces asCallback. - DB lookup threw. Inspect
docker compose logs web | grep 'signIn: identity lookup failed'. Most likely the web container can't reach Postgres — see § "I'm in the admin group..." below for connectivity checks.
Redirect loop between / and /login¶
NEXTAUTH_SECRET is missing or different across container restarts. Confirm:
The value should be present and stable. If you regenerate it, every existing session is invalidated and operators have to re-login.
Authorisation¶
I'm in the admin group but only got read¶
Three possible causes, in order:
- Sync hasn't seen the membership change yet. Group membership changes only take effect on the next directory sync. Either wait
ARIS_DIRECTORY_SYNC_INTERVALor restart core (docker compose restart core) to trigger a boot sync. - Group name mismatch. ARIS looks for the literal group address
aris-admin@<ARIS_GOOGLE_DOMAIN>(andaris-auditor@...). A group calledaris-adminsor[email protected]does not match. Check group membership with: - The web container can't reach core. Hit
curl http://localhost:8080/v1/whoamidirectly with a hand-minted token (see First login §5) — if that returns admin scopes but the UI shows read-only, the bug is in the web→core path.
/v1/whoami returns 401 invalid bearer token: invalid token signature¶
core and web were given different ARIS_AUTH_TOKEN_SECRET values. Confirm both containers see the same value:
docker compose exec core env | grep ARIS_AUTH_TOKEN_SECRET
docker compose exec web env | grep ARIS_AUTH_TOKEN_SECRET
The compose file passes the same .env value to both — if they differ, you started one container before populating .env and the value is stale.
Collector¶
core does not log ingest listening¶
Collector ingest is disabled unless ARIS_INGEST_GRPC_ADDR is set. Confirm the core container sees the variable and the three required TLS file paths:
If the TLS files are mounted from the host, remember that ARIS_INGEST_SERVER_CERT_FILE, ARIS_INGEST_SERVER_KEY_FILE, and ARIS_INGEST_CLIENT_CA_FILE are container-internal paths.
aris-collector validate-config rejects the key file permissions¶
Collector private keys must not be group/world readable on Unix. Fix the key mode:
The same rule applies to core's ingest server key.
host_id ... does not match client certificate identity¶
In secure mode, the collector's host_id is derived from the client certificate's single DNS or URI SAN identity. Either remove the explicit host_id from collector.yaml or set it exactly to that SAN. Multi-identity collector certificates are rejected.
Forwarder shows last_err and no acks¶
Check these in order:
- The collector can reach
forwarder.core_endpointon the network. forwarder.mtls.server_namematches a DNS SAN on core's ingest server certificate.forwarder.mtls.server_ca_pathcontains the CA that issued core's ingest server certificate.- Core's
ARIS_INGEST_CLIENT_CA_FILEcontains the CA that issued the collector client certificate.
Use:
sent increasing with flat acked usually means core accepted the connection but is not acknowledging records. Inspect core logs for ingest errors.
When you really need to start over¶
docker compose down -v # deletes the DB volume too
rm .env # if you want to redo configuration
docker compose up --build # full clean install
Anything not covered here belongs in a support ticket. Capture docker compose logs --no-color > aris-logs.txt and include it.