basecamp/kamal · error · RuntimeError

Failed to login to Passbolt

Error message

Failed to login to Passbolt

What it means

Raised in Passbolt#login when `passbolt verify` exits non-zero. Unlike other adapters there is NO loggedin? short-circuit — every single fetch runs `passbolt verify` first, so any Passbolt CLI configuration problem (missing GPG key, wrong server URL, bad fingerprint, expired passphrase cache) turns every kamal secrets pull into this error. The adapter sets requires_account? false; authentication state lives entirely in the passbolt CLI's own config.

Source

Thrown at lib/kamal/secrets/adapters/passbolt.rb:10

class Kamal::Secrets::Adapters::Passbolt < Kamal::Secrets::Adapters::Base
  def requires_account?
    false
  end

  private

    def login(*)
      `passbolt verify`
      raise RuntimeError, "Failed to login to Passbolt" unless $?.success?
    end

    def fetch_secrets(secrets, from:, **)
      secrets = prefixed_secrets(secrets, from: from)
      raise ArgumentError, "No secrets given to fetch" if secrets.empty?

      secret_names = secrets.collect { |s| s.split("/").last }
      folders = secrets_get_folders(secrets)

      # build filter conditions for each secret with its corresponding folder
      filter_conditions = []
      secrets.each do |secret|
        parts = secret.split("/")
        secret_name = parts.last

        if parts.size > 1
          # get the folder path without the secret name
          folder_path = parts[0..-2]

View on GitHub (pinned to eee0083b38)

Solutions

  1. Run `passbolt verify` directly to see its error output, then fix what it complains about (usually configuration or GPG key).
  2. Configure the CLI: `passbolt configure --url https://passbolt.example.com --userKey <fingerprint>` (exact flags per your passbolt CLI version) after importing the user's GPG secret key with `gpg --import`.
  3. Verify server reachability and TLS (curl the URL) if configuration is correct but verify still fails.
  4. Re-run `kamal secrets pull` only after `passbolt verify` exits 0 standalone.

Example fix

# before: unconfigured passbolt CLI
#   -> RuntimeError: Failed to login to Passbolt

# after: import key + configure, verify standalone
gpg --import passbolt-user-private.asc
passbolt configure --url https://passbolt.example.com
passbolt verify && kamal secrets pull
Defensive patterns

Strategy: try-catch

Validate before calling

require "open3"

def passbolt_verified?
  Open3.capture3("passbolt", "verify")[2].success?
end

abort "passbolt CLI not configured/verified: run `passbolt configure` and import your GPG key" unless passbolt_verified?

Try / catch

begin
  secrets = adapter.fetch(names)
rescue RuntimeError => e
  if e.message == "Failed to login to Passbolt"
    raise "passbolt verify failed: check CLI config, GPG secret key, and server reachability before deploying"
  end
  raise
end

Prevention

When it happens

Trigger: adapter.fetch(...) whenever `passbolt verify` fails: passbolt CLI never configured (no server/user/GPG key set), GPG secret key for the Passbolt user missing from the local keyring, wrong fingerprint or server URL in the CLI config, or the server unreachable/SSL failing.

Common situations: New machine or CI container where the passbolt CLI was installed but `passbolt configure` was never run; GPG key not imported (gpg --import) after OS reinstall; Passbolt server hostname or self-signed cert changed; user account key rotated in Passbolt but local keyring still holds the old one.

Related errors


AI-assisted analysis of basecamp/kamal@eee0083b38 (2026-08-21). Data as JSON: /api/errors/51533d7c12653546. Report an issue: GitHub.