Webinterface error: Could not verify the server key. You are already logged in

Checklist
I have read intro post: https://community.passbolt.com/t/about-the-installation-issues-category/12
I have read the tutorials, help and searched for similar issues
I provide relevant information about my server (component names and versions, etc.)
I provide a copy of my logs and healthcheck
I describe the steps I have taken to trouble shoot the problem
I describe the steps on how to reproduce the issue

I’m starting blank with the latest docker container.
Firefox with fresh installed Passbolt add-in.
Docker host time is NTP synced.

What steps did you take?

  1. Created directories for volumes and set www-data as owner for the gpg_volume and jwt_volume
  2. Modified the original docker compose file to my needs / settings
  3. Started the container and waited until it finished starting
  4. Retrieved the gpg key fingerprint
  5. Stopped the container, added the fingerprint as environment variable, started the container
  6. Created first admin user
  7. Used the link sent by mail → installed browser extension, set passphrase, downloaded recovery kit, selected anti-phishing token

What happened?
After that I see the “signing in, please wait” screen but it then stops with the following error:
Something went wrong!
The operation failed with the following error:
Could not verify the server key. You are already logged in.

The browser addon seems to work though since I can create and use credentials in it.

What did you expect instead?
Access to the webinterface.

Healthcheck

Summary
docker compose -f docker-compose.yml exec passbolt su -m -c "/usr/share/php/passbolt/bin/cake passbolt healthcheck" -s /bin/sh www-data

 ____                  __          ____  
/ __ \____  _____ ____/ /_  ____  / / /_ 

/ // / __ `/ / / __ / __ / / _/
/ / // (  |  ) // / // / / /
//    _,///./_//__/

Open source password manager for teams

Healthcheck shell
If you want to have more information about the different checks, please take a look at the documentation: https://www.passbolt.com/docs/admin/server-maintenance/passbolt-api-status/.

Environment

[INFO] Linux 676ef63250c4 6.12.75+rpt-rpi-v8 #1 SMP PREEMPT Debian 1:6.12.75-1+rpt1 (2026-03-11) aarch64 GNU/Linux
[PASS] PHP version 8.4.23.
[PASS] PHP version is 8.2 or above.
[PASS] 64-bit architecture system detected.
[INFO] gpg (GnuPG) 2.4.7 / libgcrypt 1.11.0
[PASS] PCRE compiled with unicode support.
[PASS] Mbstring extension is installed.
[PASS] Intl extension is installed.
[PASS] GD or Imagick extension is installed.
[PASS] The temporary directory and its content are writable and not executable.
[PASS] The logs directory /var/log/passbolt/ and its content are writable.
[WARN] System clock and NTP service information cannot be found.
[HELP] See timedatectl | grep -i -A 1 clock. More information: https://www.passbolt.com/docs/hosting/configure/ntp/

Config files

[PASS] The application config file is present
[WARN] The passbolt config file is missing in /etc/passbolt/
[HELP] Copy /etc/passbolt/passbolt.default.php to /etc/passbolt/passbolt.php
[HELP] The passbolt config file is not required if passbolt is configured with environment variables

Core config

[PASS] Cache is working.
[PASS] Debug mode is off.
[PASS] Unique value set for security.salt
[PASS] Full base url is set to https://passwort.int.mydomain.tld
[PASS] App.fullBaseUrl validation OK.
[PASS] /healthcheck/status is reachable.

SSL Certificate

[WARN] SSL peer certificate does not validate.
[HELP] cURL Error (60) SSL certificate problem: self-signed certificate in certificate chain
[WARN] Hostname does not match when validating certificates.
[HELP] cURL Error (60) SSL certificate problem: self-signed certificate in certificate chain
[WARN] Using a self-signed certificate.
[HELP] Check https://help.passbolt.com/faq/hosting/troubleshoot-ssl
[HELP] cURL Error (60) SSL certificate problem: self-signed certificate in certificate chain

SMTP settings

[PASS] The SMTP Settings plugin is enabled.
[PASS] SMTP Settings coherent. You may send a test email to validate them.
[WARN] The SMTP Settings source is: env variables.
[HELP] It is recommended to set the SMTP Settings in the database through the administration section.
[WARN] The SMTP Settings plugin endpoints are enabled.
[HELP] It is recommended to disable the plugin endpoints.
[HELP] Set the PASSBOLT_SECURITY_SMTP_SETTINGS_ENDPOINTS_DISABLED environment variable to true.
[HELP] Or set passbolt.security.smtpSettings.endpointsDisabled to true in /etc/passbolt/passbolt.php.
[INFO] Custom SSL certificate options for SMTP server is in use.

JWT Authentication

[PASS] The JWT Authentication plugin is enabled.
[PASS] The /etc/passbolt/jwt/ directory is not writable.
[PASS] A valid JWT key pair was found.

GPG Configuration

[PASS] PHP GPG Module is installed and loaded.
[PASS] The environment variable GNUPGHOME is set to /var/lib/passbolt/.gnupg.
[PASS] The directory /var/lib/passbolt/.gnupg containing the keyring is writable by the webserver user.
[PASS] The server OpenPGP key is not the default one.
[PASS] The public key file is defined in /etc/passbolt/passbolt.php and readable.
[PASS] The private key file is defined in /etc/passbolt/passbolt.php and readable.
[PASS] The server key fingerprint matches the one defined in /etc/passbolt/passbolt.php.
[PASS] The server public key defined in the /etc/passbolt/passbolt.php (or environment variables) is in the keyring.
[PASS] There is a valid email id defined for the server key.
[PASS] The public key can be used to encrypt a message.
[PASS] The private key can be used to sign a message.
[PASS] The public and private keys can be used to encrypt and sign a message.
[PASS] The private key can be used to decrypt a message.
[PASS] The private key can be used to decrypt and verify a message.
[PASS] The public key can be used to verify a signature.
[PASS] The server public key format is Gopengpg compatible.
[PASS] The server private key format is Gopengpg compatible.

Application configuration

[PASS] Using latest passbolt version (5.13.0).
[FAIL] Passbolt is not configured to force SSL use.
[HELP] Set passbolt.ssl.force to true in /etc/passbolt/passbolt.php.
[PASS] App.fullBaseUrl is set to HTTPS.
[PASS] Selenium API endpoints are disabled.
[PASS] Search engine robots are told not to index content.
[INFO] The Self Registration plugin is enabled.
[INFO] Registration is closed, only administrators can add users.
[PASS] The deprecated self registration public setting was not found in /etc/passbolt/passbolt.php.
[WARN] Host availability checking is disabled.
[HELP] Make sure this instance is not publicly available on the internet.
[HELP] Or set the PASSBOLT_EMAIL_VALIDATE_MX environment variable to true.
[HELP] Or set passbolt.email.validate.mx to true in /etc/passbolt/passbolt.php.
[PASS] Serving the compiled version of the javascript app.
[WARN] Some email notifications are disabled by the administrator.
[PASS] The database schema is up to date.
[PASS] The edition served is CE.

Database

[PASS] The application is able to connect to the database
[PASS] 53 tables found.
[PASS] Some default content is present.
[PASS] The database version is supported.

Metadata

[PASS] The server is able to decrypt the metadata private key.
[PASS] Active metadata key found or not required.
[PASS] The server has access to the metadata keys or does not require access to it.
[PASS] The server metadata private key is valid.

[FAIL] 1 error(s) found. Hang in there!

Docker container preparation

Summary
mkdir /srv/docker/Passbolt && cd /srv/docker/Passbolt

mkdir gpg_volume jwt_volume database_volume

chown -R www-data:www-data gpg_volume jwt_volume

vi docker-compose.yml

Docker Compose file

Summary
services:
        passbolt_db:
                image: mariadb:10.11
                container_name: "passbolt_db"
                restart: unless-stopped
                environment:
                        MYSQL_RANDOM_ROOT_PASSWORD: "true"
                        MYSQL_DATABASE: "passbolt"
                        MYSQL_USER: "passbolt"
                        MYSQL_PASSWORD: "P4ssb0lt"
                volumes:
                        - '/srv/docker/Passbolt/database_volume:/var/lib/mysql'

                networks:
                        - passbolt_internal

        passbolt:
                image: passbolt/passbolt:latest-ce
                container_name: "passbolt"
                restart: unless-stopped
                depends_on:
                        - passbolt_db
                environment:
                        APP_FULL_BASE_URL: https://passwort.int.mydomain.tld
                        DATASOURCES_DEFAULT_HOST: "passbolt_db"
                        DATASOURCES_DEFAULT_USERNAME: "passbolt"
                        DATASOURCES_DEFAULT_PASSWORD: "P4ssb0lt"
                        DATASOURCES_DEFAULT_DATABASE: "passbolt"
                        EMAIL_DEFAULT_FROM_NAME: 'Passbolt'
                        EMAIL_DEFAULT_FROM: 'passbolt@mydomain.tld'
                        EMAIL_TRANSPORT_DEFAULT_HOST: 'mail.int.mydomain.tld'
                        EMAIL_TRANSPORT_DEFAULT_PORT: 587
                        EMAIL_TRANSPORT_DEFAULT_USERNAME: 'passbolt@mydomain.tld'
                        EMAIL_TRANSPORT_DEFAULT_PASSWORD: 'HIDDEN'
                        EMAIL_TRANSPORT_DEFAULT_TLS: true
                        PASSBOLT_KEY_NAME: 'Passbolt Server'
                        PASSBOLT_KEY_EMAIL: 'passbolt@mydomain.tld'
                        PASSBOLT_KEY_EXPIRATION: 0
                        PASSBOLT_SSL_FORCE: false
                        PASSBOLT_PLUGINS_SMTP_SETTINGS_SECURITY_SSL_ALLOW_SELF_SIGNED: true
                        PASSBOLT_PLUGINS_SMTP_SETTINGS_SECURITY_SSL_CAFILE: '/root.crt'
                        PASSBOLT_GPG_SERVER_KEY_FINGERPRINT: 'HIDDEN'
                        PASSBOLT_SECURITY_PROXIES_ACTIVE: true
                volumes:
                        - '/srv/docker/Passbolt/gpg_volume:/etc/passbolt/gpg'
                        - '/srv/docker/Passbolt/jwt_volume:/etc/passbolt/jwt'
                        - '/srv/docker/Passbolt/ca_cert/root.crt:/root.crt'
                command:
                        [
                                "/usr/bin/wait-for.sh",
                                "-t",
                                "0",
                                "passbolt_db:3306",
                                "--",
                                "/docker-entrypoint.sh",
                        ]
                networks:
                        - traefik_backend
                        - passbolt_internal
                labels:
                        - "traefik.enable=true"
                        - "traefik.docker.network=traefik_backend"
                        - "traefik.http.routers.passbolt-http.rule=Host(`passwort.int.mydomain.tld`)"
                        - "traefik.http.routers.passbolt-http.entrypoints=http"
                        - "traefik.http.routers.passbolt-http.middlewares=passbolt_redirect-to-https"
                        - "traefik.http.routers.passbolt-https.rule=Host(`passwort.int.mydomain.tld`)"
                        - "traefik.http.routers.passbolt-https.entrypoints=https"
                        - "traefik.http.routers.passbolt-https.tls=true"
                        - "traefik.http.routers.passbolt-https.tls.certresolver=openbao"
                        - "traefik.http.services.passbolt.loadbalancer.server.port=80"
                        - "traefik.http.middlewares.passbolt_redirect-to-https.redirectscheme.scheme=https"
                        - "traefik.http.middlewares.passbolt_redirect-to-https.redirectscheme.permanent=true"

networks:
        traefik_backend:
                external: true
        passbolt_internal:
                external: false

Short description for the docker compose file
The Passbolt instance runs behind a Traefik reverse proxy which does the http to https redirection and certificate handling (ACME, OpenBao).
I have my own certificate authority, that’s why I need the CAFILE variable to be able to use STARTTLS. Otherwise it would refuse the connection due to the invalid SSL certificate.

Server log

Summary
<Internal container IP> - - [12/Jul/2026:00:39:28 +0000] "GET /auth/login?redirect=%2F&locale=de-DE HTTP/1.1" 200 1130 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:152.0) Gecko/20100101 Firefox/152.0"

2026-07-12 00:39:28,395 INFO reaped unknown pid 1560 (exit status 0)

<Internal container IP> - - [12/Jul/2026:00:39:28 +0000] "GET /settings.json?api-version=v2 HTTP/1.1" 200 1702 "https://passwort.int.mydomain.tld/auth/login?redirect=%2F&locale=de-DE" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:152.0) Gecko/20100101 Firefox/152.0"

2026-07-12 00:39:28,606 INFO reaped unknown pid 1566 (exit status 0)

<Internal container IP> - - [12/Jul/2026:00:39:28 +0000] "GET /settings.json?api-version=v2 HTTP/1.1" 200 3606 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:152.0) Gecko/20100101 Firefox/152.0"

2026-07-12 00:39:28 error: [Cake\Http\Exception\BadRequestException] You are already logged in. in /usr/share/php/passbolt/src/Controller/Auth/AuthLoginController.php on line 92

Request URL: /auth/verify.json?api-version=v2

Client IP: <Client IP>

<Internal container IP> - - [12/Jul/2026:00:39:28 +0000] "POST /auth/verify.json?api-version=v2 HTTP/1.1" 409 259 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:152.0) Gecko/20100101 Firefox/152.0"

<Internal container IP> - - [12/Jul/2026:00:39:28 +0000] "GET /auth/verify.json?api-version=v2 HTTP/1.1" 200 2853 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:152.0) Gecko/20100101 Firefox/152.0"

<Internal container IP> - - [12/Jul/2026:00:39:30 +0000] "GET /resources.json?api-version=v2&contain%5Bpermission%5D=1&contain%5Bfavorite%5D=1&contain%5Btag%5D=1&limit=10000&page=1&sort%5BResources.modified%5D=desc HTTP/1.1" 200 2063 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:152.0) Gecko/20100101 Firefox/152.0"

<Internal container IP> - - [12/Jul/2026:00:39:30 +0000] "GET /metadata/session-keys.json?api-version=v2 HTTP/1.1" 200 275 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:152.0) Gecko/20100101 Firefox/152.0

What else did I try?

  • Tried using different combinations for the port config (force SSL, let Traefik use 443 instead of 80, change base URL from http to https)
  • Rotated GPG keys
  • Omitted the “PASSBOLT_SECURITY_PROXIES_ACTIVE” variable
  • Omitted the “EMAIL_” and “PASSBOLT_” variables
  • Container tag 5.12.0-1-ce instead of latest
  • Cleared database / gpg key / jwt token directories between all tests to ensure clean starting point
  • Followed a lot of troubleshooting steps regarding the server key error

Steps to reproduce

  • Create docker container according to the configs (passwords, URLs, GPG fingerprint need to be changed depending on your data. The certresolver label needs to be removed to get an automatically (invalid) created certificate from Traefik)
  • Follow the “what steps did I take” list

Please let me know if you need additional logs or outputs.

G’day cubical_scheme,

Your server key looks fine despite the message: every GPG and metadata check passes, so it’s not a broken or unverifiable key.

The error is really the sign-in handshake. Before signing you in, the extension asks the server to prove it holds the private key, with a POST /auth/verify.json. Your log shows that coming back 409 You are already logged in, which passbolt only returns when the request already carries a valid session, so a session cookie is reaching a step that’s meant to run before you’re logged in. The extension reports that failed step as “Could not verify the server key”. It fits what you saw: right after the 409 the log has it loading your resources fine, so it’s effectively signed in already.

I’d start by clearing the cookies and site data for passwort.int.mydomain.tld, then reloading. A session cookie lives in the browser, so it can outlive the container even when you wipe the db/gpg/jwt volumes, and a leftover one would do exactly this. Clearing the site’s cookies won’t touch your key or passphrase.

If that doesn’t do it, worth checking whether Traefik is holding or replaying a cookie: watch the failing POST /auth/verify.json in dev tools and see what Cookie header it sends. Paste that and I can suggest where to look next.

Let us know how you go.

Cheers
Gareth

Hello @gyaresu,

it actually was an cookie issue but not the way we probably thought it would be :slight_smile:

For testing I tend to use the private mode in Firefox to keep my browser history clean.
I’ve closed the private sessions between every new test and I used the “delete private session” function in the browser. Sometimes the add-in kept being logged in despite killing the private sessions which suprised me but I didn’t think much about it.

I’ve tested logging in again today and it works now in the regular sessions but not in private mode.

Steps to reproduce:

  1. Login to your selfhosted Passbolt instance → works, add-in logged in also
  2. Open a private window in your browser
  3. Try to login to your selfhosted Passbolt instance → same error message is shown

Since I don’t have an account for a Passbolt hosted instance I can’t test if it happens there too but I’d guess it does since it’s the same constellation between the two browser sessions.

If you can reproduce it I’ll open an GitHub issue.

Thank you for your help!