Hello,
I recently migrated a Passbolt CE instance from one machine to another. The migration itself was successful and transparent for most users.
What changed:
- The server IP address
- The reverse proxy (from Traefik to Caddy)
- Previously it was hosted as docker compose witin VM, now it is on LXC container
What stayed the same:
- Passbolt is still running in Docker
- Same Passbolt version and configuration (as far as I can tell)
Problem:
After the migration, the Passbolt browser extension does not work on Brave Browser on an Apple Silicon MacBook.
What works fine:
- Passbolt iOS app
- Passbolt browser extension on Firefox (Windows)
- Passbolt browser extension on Firefox (macOS, Apple Silicon)
So far, the issue seems to be specific to Brave Browser on macOS (Apple Silicon). The migration had no visible impact on other platforms or users.
Extension logs
index.js:2 Error: Failed to fetch
at handleFetchResponse (index.js:2:790320)
at handleOffscreenResponse (index.js:2:791347)
sendRequest @ index.js:2
await in sendRequest
isAuthenticated @ index.js:2
await in isAuthenticated
checkAuthStatus @ index.js:2
await in checkAuthStatus
isUserAuthenticated @ index.js:2
updateSuggestedResourcesBadge @ index.js:2
await in updateSuggestedResourcesBadge
handleSuggestedResourcesOnFocusedWindow @ index.js:2
index.js:2 PassboltServiceUnavailableError: Unable to reach the server, an unexpected error occurred
at lt.sendRequest (index.js:2:65448)
at async ma.isAuthenticated (index.js:2:187561)
at async fa.checkAuthStatus (index.js:2:188612)
at async Object.isUserAuthenticated (index.js:2:289589)
at async Object.updateSuggestedResourcesBadge (index.js:2:289099)
at async Object.handleSuggestedResourcesOnFocusedWindow (index.js:2:288790)
isUserAuthenticated @ index.js:2
await in isUserAuthenticated
updateSuggestedResourcesBadge @ index.js:2
await in updateSuggestedResourcesBadge
handleSuggestedResourcesOnFocusedWindow @ index.js:2
index.js:2 Error: Failed to fetch
at handleFetchResponse (index.js:2:790320)
at handleOffscreenResponse (index.js:2:791347)
sendRequest @ index.js:2
await in sendRequest
isAuthenticated @ index.js:2
await in isAuthenticated
checkAuthStatus @ index.js:2
await in checkAuthStatus
isUserAuthenticated @ index.js:2
resetSuggestedResourcesBadge @ index.js:2
handleSuggestedResourcesOnFocusedWindow @ index.js:2
index.js:2 PassboltServiceUnavailableError: Unable to reach the server, an unexpected error occurred
at lt.sendRequest (index.js:2:65448)
at async ma.isAuthenticated (index.js:2:187561)
at async fa.checkAuthStatus (index.js:2:188612)
at async Object.isUserAuthenticated (index.js:2:289589)
at async Object.resetSuggestedResourcesBadge (index.js:2:288938)
at async Object.handleSuggestedResourcesOnFocusedWindow (index.js:2:288748)
isUserAuthenticated @ index.js:2
await in isUserAuthenticated
resetSuggestedResourcesBadge @ index.js:2
handleSuggestedResourcesOnFocusedWindow @ index.js:2
Healtcheck:
Healthcheck:
Environment
[INFO] Linux 55ff5ec61101 6.17.2-1-pve #1 SMP PREEMPT_DYNAMIC PMX 6.17.2-1 (2025-10-21T11:55Z) x86_64 GNU/Linux
[PASS] PHP version 8.4.16.
[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://DOMAIN_REDACTED
[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: unable to get local issuer certificate
[WARN] Hostname does not match when validating certificates.
[HELP] cURL Error (60) SSL certificate problem: unable to get local issuer certificate
[WARN] Using a self-signed certificate.
[HELP] Check https://help.passbolt.com/faq/hosting/troubleshoot-ssl
[HELP] cURL Error (60) SSL certificate problem: unable to get local issuer certificate
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.
[PASS] No custom SSL configuration for SMTP server.
JWT Authentication
[PASS] The JWT Authentication plugin is enabled.
[FAIL] The /etc/passbolt/jwt/ directory should not be writable.
[HELP] You can try:
[HELP] sudo chown -Rf root:www-data /etc/passbolt/jwt/
[HELP] sudo chmod 750 /etc/passbolt/jwt/
[HELP] sudo chmod 640 /etc/passbolt/jwt/jwt.key
[HELP] sudo chmod 640 /etc/passbolt/jwt/jwt.pem
[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.
[FAIL] The server OpenPGP key is not set.
[HELP] Create a key, export it and add the fingerprint to /etc/passbolt/passbolt.php
[HELP] See. https://www.passbolt.com/help/tech/install#toc_gpg
[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.
[FAIL] The server key fingerprint doesn't match the one defined in /etc/passbolt/passbolt.php.
[HELP] Double check the key fingerprint, example:
[HELP] sudo su -s /bin/bash -c "gpg --list-keys --fingerprint --home /var/lib/passbolt/.gnupg" www-data | grep -i -B 2 'SERVER_KEY_EMAIL'
[HELP] SERVER_KEY_EMAIL: The email you used when you generated the server key.
[HELP] See. https://www.passbolt.com/help/tech/install#toc_gpg
[FAIL] The server public key defined in the /etc/passbolt/passbolt.php (or environment variables) is not in the keyring
[HELP] Import the private server key in the keyring of the webserver user.
[HELP] you can try:
[HELP] sudo su -s /bin/bash -c "gpg --home /var/lib/passbolt/.gnupg --import /etc/passbolt/gpg/serverkey_private.asc" www-data
[FAIL] The server key does not have a valid email id.
[HELP] Edit or generate another key with a valid email id.
[FAIL] The private key cannot be used to decrypt a message
[FAIL] The private key cannot be used to decrypt and verify a message
[FAIL] The public key cannot be used to verify a signature.
Application configuration
[PASS] Using latest passbolt version (5.8.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.
Database
[PASS] The application is able to connect to the database
[PASS] 35 tables found.
[PASS] Some default content is present.
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] 9 error(s) found. Hang in there!
docker-compose.yml
docker-compose.yml
version: '3.9'
services:
caddy:
image: caddy
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- ./caddy_data:/data
- ./caddy_config:/config
- /root/certs:/certs:ro
db:
image: mariadb:10.10
restart: unless-stopped
environment:
MYSQL_RANDOM_ROOT_PASSWORD: "true"
MYSQL_USER: "passbolt"
MYSQL_PASSWORD: ${MYSQL_PASSWORD}
MYSQL_DATABASE: "passbolt"
volumes:
- /root/data/mysql/:/var/lib/mysql
pass:
image: passbolt/passbolt:latest-ce
container_name: pass
restart: unless-stopped
depends_on:
- db
environment:
EMAIL_DEFAULT_FROM: ${EMAIL_DEFAULT_FROM}
EMAIL_TRANSPORT_DEFAULT_HOST: ${EMAIL_TRANSPORT_DEFAULT_HOST}
EMAIL_TRANSPORT_DEFAULT_PORT: 587
EMAIL_TRANSPORT_DEFAULT_USERNAME: ${EMAIL_TRANSPORT_DEFAULT_USERNAME}
EMAIL_TRANSPORT_DEFAULT_PASSWORD: ${EMAIL_TRANSPORT_DEFAULT_PASSWORD}
EMAIL_TRANSPORT_DEFAULT_TLS: true
APP_FULL_BASE_URL: ${APP_FULL_BASE_URL}
DATASOURCES_DEFAULT_HOST: "db"
DATASOURCES_DEFAULT_USERNAME: "passbolt"
DATASOURCES_DEFAULT_PASSWORD: ${MYSQL_PASSWORD}
DATASOURCES_DEFAULT_DATABASE: "passbolt"
volumes:
- /root/data/gpg/:/etc/passbolt/gpg
- /root/data/jwt/:/etc/passbolt/jwt
command: ["/usr/bin/wait-for.sh", "-t", "0", "db:3306", "--", "/docker-entrypoint.sh"]
Caddyfile:
DOMAIN_REDACTED {
tls /certs/cert.pem /certs/privkey.pem
log {
output file /var/log/caddy-access.log {
roll_size 100mb
roll_keep 20
roll_keep_for 720h
}
}
@skip remote_ip 10.0.0.0/8 127.0.0.0/8
skip_log @skip
reverse_proxy pass:80
}```
