# Administrator Credentials and Settings Save Troubleshooting

This guide covers initial administrator credentials, existing database volumes,
and Settings UI write-permission errors for Docker deployments.

For general installation problems, see
[Installation Troubleshooting](INSTALL_TROUBLESHOOTING.md).

## Initial Administrator Behavior

On an empty database, QuantDinger creates the initial administrator from
`ADMIN_USER`, `ADMIN_PASSWORD`, and optional `ADMIN_EMAIL`. The password is
stored as a password hash (bcrypt in the standard image), never as plaintext.

For backward compatibility, a manual Docker deployment that leaves the example
administrator values unchanged can still sign in with `quantdinger` / `123456`.
Do not expose this credential to the internet. Set a non-default password before
the first start or change it immediately after the first login. The one-command
installer rejects `123456` as the selected password.

An existing PostgreSQL volume is persistent user data. Changing `ADMIN_USER` or
`ADMIN_PASSWORD` does not unconditionally replace existing accounts. Automatic
legacy migration occurs only when all of the following are true:

- the first active administrator still uses username `quantdinger` and password
  `123456`;
- a valid, non-default administrator username and password are configured;
- the requested username is not already used by another account.

QuantDinger never overwrites an administrator whose password has already been
changed. If another account already uses the requested username, migration stops
instead of promoting or merging that account.

## Settings UI Reports Save Failure

The Settings UI writes `/app/.env` directly. The corresponding host file is:

| Deployment | Host file |
| --- | --- |
| GHCR or one-command installer | `backend.env` |
| Source Compose | `backend_api_python/.env` |

The backend application runs as UID/GID `10001`. Current backend images start as
root, prepare the mounted file, change `/app/.env` ownership to `10001:10001`,
restrict it to mode `600`, and then drop privileges. This behavior applies to
both one-command and manual Docker Compose installations.

Check the runtime user and write access:

```bash
docker compose exec -u 10001:10001 -T backend sh -c '
  id
  ls -ln /app/.env
  test -r /app/.env && test -w /app/.env \
    && echo writable=yes || echo writable=no
'
```

When using a manually downloaded `docker-compose.ghcr.yml`, add
`-f docker-compose.ghcr.yml` after `docker compose`.

Expected output includes UID `10001`, file owner/group `10001 10001`, mode
`600`, and `writable=yes`.

### Repair an Installation That Still Uses an Old Image

Update the backend image first. Re-downloading `install.sh` alone does not update
an already running container:

```bash
docker compose pull backend
docker compose up -d --force-recreate backend
```

If the old image left the host file owned by root, repair only the backend
runtime file:

```bash
# GHCR or one-command installation
sudo chown 10001:10001 backend.env
sudo chmod 600 backend.env

# Source installation
sudo chown 10001:10001 backend_api_python/.env
sudo chmod 600 backend_api_python/.env
```

Do not use `chmod 755` or `chmod -R 777`. These files contain administrator
credentials, API keys, OAuth secrets, and broker or exchange settings. Mode
`755` exposes secrets to other local users and still does not let UID `10001`
write a root-owned file.

## Read-Only and Special Docker Deployments

Automatic ownership repair cannot make a deliberately read-only mount writable.
The Settings UI is read-only by design in these cases:

- `/app/.env` is mounted with `:ro`;
- `docker-compose.production.yml` is enabled;
- the container is forced to start as non-root with `user: 10001:10001` before
  ownership can be prepared;
- rootless Docker, user namespace remapping, NFS, or another filesystem policy
  rejects `chown`.

For a hardened read-only deployment, edit the host environment file and recreate
the services:

```bash
docker compose pull
docker compose up -d --force-recreate
```

Return to the [main README](../../README.md).
