Skip to main content

bwssh

Bitwarden-backed SSH agent for Linux. Store your SSH keys in Bitwarden and use them seamlessly with any SSH client.

Features

  • Bitwarden integration: SSH keys stored securely in your Bitwarden vault
  • Standard SSH agent: Works with ssh, git, and any SSH client
  • Systemd integration: Runs as a user service, starts on login
  • Forwarding protection: Blocks remote servers from using your keys
  • Optional polkit prompts: Desktop authorization popups (disabled by default)

Requirements

  • Linux with systemd user services (including WSL2)
  • Python 3.12+
  • Bitwarden CLI (bw) installed and logged in

Installation

uv sync

Bitwarden CLI

Install the Bitwarden CLI (bw) and log in before using bwssh. See https://bitwarden.com/help/cli/ for installation instructions.

bw --version
bw login

Quick start

uv run bwssh install --user-systemd
uv run bwssh start
uv run bwssh unlock
export SSH_AUTH_SOCK=${XDG_RUNTIME_DIR}/bwssh/agent.sock
ssh -T git@github.com

Configuration

Config file: ~/.config/bwssh/config.toml

Quick Setup (Recommended)

The easiest way to configure bwssh is to use the init command:

# First, unlock Bitwarden
export BW_SESSION=$(bw unlock --raw)

# Then run init to auto-discover SSH keys
bwssh config init

This will find all SSH keys in your Bitwarden vault and create a config file.

Manual Setup

If you prefer to configure manually, first find your SSH key IDs:

bw list items | jq -r '.[] | select(.sshKey != null) | "\(.id) \(.name)"'

Then create ~/.config/bwssh/config.toml:

[bitwarden]
bw_path = "/full/path/to/bw"  # Use 'which bw' to find this
item_ids = [
    "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",  # your-key-name
]

Full Config Example

[daemon]
log_level = "INFO"

[bitwarden]
bw_path = "/usr/bin/bw"
mode = "explicit"
item_ids = [
    "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
]

[auth]
# Polkit authorization prompts (default: disabled)
require_polkit = false

# Block forwarded agent requests (recommended)
deny_forwarded_by_default = true

[ssh]
allow_ed25519 = true
allow_ecdsa = true
allow_rsa = true

WSL2 + Windows Bitwarden app mode

If you already use Bitwarden/SSH agent on Windows, you can run bwssh in bridge mode so WSL tools use that agent state.

[bitwarden]
mode = "windows_bridge"
windows_pipe_command = ["npiperelay.exe", "-ei", "-s", "//./pipe/openssh-ssh-agent"]
auto_unlock_poll_seconds = 5

Behavior in this mode:

  • bwssh unlock does not ask for a password in WSL.
  • It reports whether Windows is already unlocked or asks you to unlock in the Windows app.
  • The daemon polls automatically and switches between locked/unlocked when the Windows app state changes.

Environment Variables

  • BWSSH_RUNTIME_DIR: Override socket directory
  • BWSSH_LOG_LEVEL: Override log level
  • BW_SESSION: Bitwarden session key (auto-detected by bwssh unlock)

Security

Default Mode

By default, bwssh allows all local signing requests without prompts. Security comes from:

  • Auto-lock on sleep: Keys are cleared when your laptop sleeps (enabled by default)
  • Forwarded agent blocking: Remote servers can't use your keys
  • Manual lock: Run bwssh lock when stepping away

Polkit Prompts (Optional)

For extra security, enable polkit to show desktop prompts for each signing request:

[auth]
require_polkit = true

This requires installing the polkit policy:

bwssh install --polkit | sudo tee /usr/share/polkit-1/actions/io.github.reidond.bwssh.policy > /dev/null

See docs/ for detailed polkit setup instructions.

CLI Commands

# Daemon control
bwssh start              # Start the agent daemon
bwssh stop               # Stop the agent daemon
bwssh status             # Show daemon status

# Key management
bwssh unlock             # Unlock vault and load keys
bwssh lock               # Lock agent and clear keys
bwssh sync               # Reload keys from Bitwarden
bwssh keys               # List loaded SSH keys

# Configuration
bwssh config init        # Auto-discover SSH keys and create config
bwssh config show        # Show current configuration

# Installation
bwssh install --user-systemd   # Install systemd user service
bwssh install --polkit         # Print polkit policy file

System Tray

bwssh includes an optional system tray icon (bwssh tray) that shows agent status and provides quick lock/unlock controls. Install with the gui extra:

uv tool install bwssh[gui]

Build dependencies

PyGObject must be compiled from source, which requires system development packages.

Fedora / RHEL / CentOS:

sudo dnf install gobject-introspection-devel cairo-gobject-devel python3-devel \
    gtk3-devel libayatana-appindicator-gtk3

Arch / Manjaro:

sudo pacman -S gobject-introspection cairo python gtk3 libayatana-appindicator

openSUSE:

sudo zypper install gobject-introspection-devel cairo-devel python3-devel \
    gtk3-devel typelib-1_0-AyatanaAppIndicator3-0_1

Debian / Ubuntu:

sudo apt install libgirepository1.0-dev libcairo2-dev python3-dev \
    libgtk-3-dev libayatana-appindicator3-1 gir1.2-ayatanaappindicator3-0.1

Alternatively, skip building from source by using system-installed PyGObject:

sudo dnf install python3-gobject gtk3 libayatana-appindicator-gtk3  # Fedora
uv tool install --system-site-packages bwssh[gui]

Documentation

Full documentation lives in docs/ and can be served locally:

cd docs
bun install
bun run dev

Development

uv run ruff check .
uv run ruff format .
uv run mypy src tests
uv run pytest

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

bwssh-0.1.7.tar.gz (46.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

bwssh-0.1.7-py3-none-any.whl (61.8 kB view details)

Uploaded Python 3

File details

Details for the file bwssh-0.1.7.tar.gz.

File metadata

  • Download URL: bwssh-0.1.7.tar.gz
  • Upload date:
  • Size: 46.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.10.9 {"installer":{"name":"uv","version":"0.10.9","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for bwssh-0.1.7.tar.gz
Algorithm Hash digest
SHA256 6efc9c13dc4d2da6669b4fff4a0a81700e8ae0fe902b4be66e4fcb4335f5cf5a
MD5 6afcc09357fdcafc8940ead983bfa592
BLAKE2b-256 845f7e5c6c1a305586dee795c2dce5e85542f04a374603025325dfaf8573e3cf

See more details on using hashes here.

File details

Details for the file bwssh-0.1.7-py3-none-any.whl.

File metadata

  • Download URL: bwssh-0.1.7-py3-none-any.whl
  • Upload date:
  • Size: 61.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.10.9 {"installer":{"name":"uv","version":"0.10.9","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for bwssh-0.1.7-py3-none-any.whl
Algorithm Hash digest
SHA256 aacade99f78fd782698b3ff97dc3581b1c2b377d1e2d917d2d0e7b1b838b218a
MD5 6e4de5397673e78b69c00e024f33a757
BLAKE2b-256 503480b09ad3cdfc5bb6cd7c12f709bff14e2605c4a989a513446f71e043d337

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.1.7 This release

2 files

0.1.6

2 files

0.1.5

2 files

0.1.4

2 files

0.1.3

2 files

0.1.2

2 files

0.1.1

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page