Credentials & Rotation
The installer generates every secret your install needs, so nothing ships with a default password. This page lists what it generated, where each value lives, and how to change it without breaking the install.
What the installer generated
| Secret | Generated as | Stored in | Protects |
|---|---|---|---|
| Admin password | 16-character random string | .conzent-credentials (mode 600) and bcrypt-hashed in the database | Dashboard login |
DB_PASSWORD | 24-character random string | .env, twice: DB_PASSWORD= and inside DATABASE_URL= | MariaDB access |
SCANNER_API_KEY | 32-character random string | .env | App-to-scanner authentication |
APP_SECRET | 64-character hex string | .env | Reserved — no code path reads it today |
View the saved admin credentials at any time with bash scripts/install.sh --config.
First thing to do: .conzent-credentials holds your admin password in plain text. It exists so the installer can show it to you again if you missed it. Once the password is in a password manager, delete the file with rm .conzent-credentials. Nothing depends on it.
Rotating the admin password
If you can log in, change it in the dashboard under Account → Profile.
If you cannot log in, reset it from the host. This used to be a dead end: bin/oci setup refuses to run once an account exists, and the "forgot password" email needs a working SMTP server, which self-hosted installs often do not have.
# Generate a new password and print it
docker compose exec app php bin/oci user:password --email=you@example.com
# Or set a specific one
docker compose exec app php bin/oci user:password --email=you@example.com --password='your-new-password'
The command bcrypt-hashes and stores the new password, signs out every existing session for that user, and clears any lockout from failed login attempts. It works for any user, not just admins — useful when a client forgets theirs and you have no mail server.
To make the email flow work instead, configure SMTP in .env (MAIL_HOST, MAIL_PORT, MAIL_USERNAME, MAIL_PASSWORD, MAIL_ENCRYPTION, MAIL_FROM_ADDRESS), restart, and test with docker compose exec app php bin/oci test:email --to=you@example.com. With MAIL_HOST empty, Conzent logs "Email not sent: no SMTP server configured" and moves on — reset links are never delivered.
Rotating the database password
Four places have to agree: MariaDB itself, DB_PASSWORD, DATABASE_URL, and the running containers.
# 1. Pick a new password
NEW_PASS=$(openssl rand -hex 16)
# 2. Change it inside MariaDB
docker compose exec -T mariadb mariadb -uroot -p"$DB_ROOT_PASSWORD" \
-e "ALTER USER 'oci'@'%' IDENTIFIED BY '$NEW_PASS'; FLUSH PRIVILEGES;"
# 3. Update BOTH places in .env
sed -i "s|^DB_PASSWORD=.*|DB_PASSWORD=$NEW_PASS|" .env
sed -i "s|^DATABASE_URL=.*|DATABASE_URL=mysql://oci:$NEW_PASS@mariadb:3306/oci?charset=utf8mb4|" .env
# 4. Restart the services holding connections
docker compose up -d --force-recreate app worker scheduler beacon-worker
# 5. Confirm
docker compose exec app php bin/oci health
If health reports a database failure, the two .env values disagree. DATABASE_URL is what the application actually uses; DB_PASSWORD is what MariaDB is initialised with. Both must carry the new value.
DB_ROOT_PASSWORD defaults to root. The MariaDB container publishes no host port in the self-hosted stack, so it is only reachable from inside the Compose network — but set a real value before adding any host port mapping of your own.
Rotating the scanner API key
sed -i "s|^SCANNER_API_KEY=.*|SCANNER_API_KEY=$(openssl rand -hex 16)|" .env
docker compose up -d --force-recreate scanner app worker scheduler
docker compose exec app php bin/oci scanner:register
docker compose exec app php bin/oci scanner:health
Registration is keyed by URL and idempotent, so re-running updates the existing record rather than adding a duplicate. If you run additional scanners, rotate the key on each and re-register each URL.
API keys and site keys
Two credentials the installer does not generate:
- API keys — created per user for programmatic access. Revoke and re-issue from the dashboard.
- Site keys — the
data-keyvalue in each embed snippet. This is a public identifier, not a secret: it appears in the page source of every site using the banner. It cannot be rotated without updating that site's embed.
Handling .env
.env is the most sensitive file in the install. It is gitignored and created mode 600 — if you copied it around, restore that with chmod 600 .env. It is included in backup archives, which is why those are also written mode 600 and belong somewhere private.
The full reference lives with the code: docs/credentials.md on GitHub.