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

Metadata

Release files for bwssh 0.1.7

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for bwssh 0.1.7
File Size Uploaded
bwssh-0.1.7.tar.gz 46.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for bwssh 0.1.7
File Interpreter ABI Platform
bwssh-0.1.7-py3-none-any.whl Python 3 none any Details

Total release size: 108.0 kB

Release files / bwssh-0.1.7.tar.gz

Download URL bwssh-0.1.7.tar.gz
Size 46.1 kB
Tags Source
SHA-256 checksum
How to use checksums
6efc9c13dc4d2da6669b4fff4a0a81700e8ae0fe902b4be66e4fcb4335f5cf5a
BLAKE2b-256 checksum
How to use checksums
845f7e5c6c1a305586dee795c2dce5e85542f04a374603025325dfaf8573e3cf
Upload date
Uploaded using Trusted Publishing?
What is 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}

Release files / bwssh-0.1.7-py3-none-any.whl

Download URL bwssh-0.1.7-py3-none-any.whl
Size 61.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
aacade99f78fd782698b3ff97dc3581b1c2b377d1e2d917d2d0e7b1b838b218a
BLAKE2b-256 checksum
How to use checksums
503480b09ad3cdfc5bb6cd7c12f709bff14e2605c4a989a513446f71e043d337
Upload date
Uploaded using Trusted Publishing?
What is 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}

Release history Release notifications | RSS feed

This release

0.1.7 This release

2 release files

0.1.6

2 release files

0.1.5

2 release files

0.1.4

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page