Skip to content

Reset the Console Admin Password

There's no self-service "forgot password" email flow — resets are admin-driven. Passwords are bcrypt-hashed (passlib, CryptContext(schemes=["bcrypt"])) in the users table.

Method 1 — Another admin account still works

  1. Log in with that account.
  2. Identity → Users.
  3. Find the locked-out account → Reset Password. (Disabled for AD/LDAP accounts — those store a sentinel value and are never checked at login; reset the password at the domain controller instead.)
  4. Enter a new password (8+ characters) and save.

This calls POST /api/iam/users/{username}/reset-password and takes effect immediately — no restart needed.

Method 2 — Fully locked out (no working admin account)

Reset the password hash directly in Postgres from the host running the console's containers.

  1. Find the app and DB container names:

    docker ps --format 'table {{.Names}}\t{{.Image}}'
    
    Compose v2 names them <project>-app-1-1 and <project>-db-1 (the <project> prefix is the install directory name, e.g. mfconsole) — adjust the names below to match what you actually see.

  2. Generate a bcrypt hash for the new password inside the app container — it already has passlib installed, so there's nothing extra to install:

    docker exec <app-container> python3 -c "
    from passlib.context import CryptContext
    print(CryptContext(schemes=['bcrypt']).hash('YOUR-NEW-PASSWORD'))
    "
    

  3. Write the hash into the users table:

    docker exec <db-container> psql -U postgres -d mfconsole -c \
      "UPDATE users SET password='<hash from step 2>', must_change_password=TRUE WHERE username='admin';"
    
    must_change_password=TRUE forces a real password to be chosen on next login instead of leaving your temporary one live.

Don't want to pick one on the spot?

Hash the documented lab default (mfpro) instead of a real password — the forced first-login change means it's only live for the few seconds it takes you to log in and set a proper one.

If login fails for everyone, not just you

Before assuming it's a password problem: POST /api/login is rate-limited via slowapi, backed by Redis (RATELIMIT_STORAGE_URI). If Redis is down, the login route throws a 500 for every request regardless of credentials — it looks exactly like a broken login but has nothing to do with passwords.

docker ps --filter name=redis --format 'table {{.Names}}\t{{.Status}}'
# If it shows "Exited":
docker start <redis-container>

Confirm by checking the app container's logs for redis.exceptions.ConnectionError around the time of the failed login attempts:

docker logs <app-container> --tail 50 | grep -i redis