Skip to content

bitwarden

Install and configure Bitwarden CLI tools on Ubuntu/Debian systems.

This role automates the installation and configuration of:

  1. Bitwarden CLI (bw) - Official Bitwarden command-line interface for vault management
  2. Bitwarden Secrets CLI (bws) - Specialized CLI for secrets management
  3. Bitwarden Configuration - Server URL and API endpoint configuration
  • Downloads official binaries directly from GitHub releases
  • Supports version pinning with override capability
  • Automatic architecture detection (x86_64/amd64, aarch64/arm64)
  • Idempotent installation (skips if already installed)
  • Configurable Bitwarden server URL (supports self-hosted instances)
  • Custom API endpoint configuration
  • Comprehensive verification and status reporting
  • Ubuntu/Debian-based system
  • Internet connection for downloading binaries
  • Root/sudo privileges for system-wide installation
VariableDefaultDescription
bitwarden_install_bwtrueInstall Bitwarden CLI (bw)
bitwarden_install_bwstrueInstall Bitwarden Secrets CLI (bws)
bitwarden_configuretrueConfigure Bitwarden settings
bitwarden_install_path/usr/local/binInstallation directory for binaries
VariableDefaultDescription
bitwarden_bw_version2026.7.0Bitwarden CLI version (bump to upgrade)
bitwarden_bws_version2.1.0Bitwarden Secrets CLI version (bump to upgrade)
VariableDefaultDescription
bitwarden_server_urlhttps://vault.bitwarden.euBitwarden server URL
VariableDefaultDescription
bitwarden_bws_server_apihttps://api.bitwarden.euAPI server URL for bws config
bitwarden_bws_server_identityhttps://identity.bitwarden.euIdentity server URL for bws config
bitwarden_bws_config_path~/.config/bwsDirectory for bws config file

Note: The bws CLI uses a TOML configuration file at ~/.config/bws/config. This role defaults to the European endpoints; for the US region set bitwarden_bws_server_api: 'https://api.bitwarden.com' and bitwarden_bws_server_identity: 'https://identity.bitwarden.com'.

Installs a dedicated BWS machine-account token on the host so bws works with no per-user setup, for root and for members of the bws group.

These tasks live in tasks/distribute_token.yml and are not part of the role’s default flow — main.yml does not include them, so setup_new_machine.yml installs the CLIs without touching the token. Distribution has its own playbook, so rotating the token never requires a full provisioning run.

VariableDefaultDescription
bitwarden_bws_token_env_varBWS_HOST_ACCESS_TOKENController env var holding the token
bitwarden_bws_token_requiredfalseFail instead of skip when the env var is unset
bitwarden_bws_token_file/etc/bws/tokenOn-host token path (root:bws, 0640)
bitwarden_bws_token_groupbwsGroup granted read access to the token
bitwarden_bws_token_users['{{ ansible_user_id }}']Accounts added to the bws group
bitwarden_bws_system_config_file/etc/bws/configSystem-wide bws config (exported as BWS_CONFIG_FILE)
bitwarden_bws_write_root_configtrueAlso write /root/.config/bws/config
bitwarden_bws_write_user_configtrueWrite the per-user ~/.config/bws/config

Set the token on the controller before running:

ansible/.env
BWS_HOST_ACCESS_TOKEN=0.<uuid>.<key>

Use a separate, read-only machine account scoped to only the projects the hosts need. Do not reuse BWS_ACCESS_TOKEN — that token stays on the controller for restart-docker-stacks.yml, and reusing it would place a broad credential on every container.

Then run the dedicated playbook:

Terminal window
# Whole fleet
ansible-playbook -i inventory/proxmox.proxmox.yml playbooks/distribute-bws-token.yml
# One host (recommended for the first run)
ansible-playbook -i inventory/proxmox.proxmox.yml playbooks/distribute-bws-token.yml --limit arcane

That playbook sets bitwarden_bws_token_required: true, so a missing env var is an error rather than a silent skip. The role default is false: if you include distribute_token.yml from somewhere else and the token is absent, the group, config and shell snippets still converge and any existing token file is left untouched.

PathOwner:GroupModeContents
/etc/bws/tokenroot:bws0640The access token
/etc/bws/configroot:root0644TOML with the region endpoints
/etc/profile.d/bws.shroot:root0644Exports both, if readable
/etc/fish/conf.d/bws.fishroot:root0644Same, written only where fish exists
/root/.config/bws/configroot:root0644Region endpoints for root
  • Group changes need a re-login. An account newly added to bws must log out and back in (or run newgrp bws) before $BWS_ACCESS_TOKEN appears. Existing SSH sessions keep their old group set.
  • Only login shells get the export. /etc/profile.d is not read by ssh host '<cmd>', cron, systemd units, or Ansible’s own shell/command tasks. Use bash -lc '...', or read /etc/bws/token directly. Fish is unaffected — conf.d is sourced by every fish shell.
  • sudo strips the variable (env_reset is the default). Use sudo -i, or sudo BWS_ACCESS_TOKEN="$(cat /etc/bws/token)" bws .... Do not add an env_keep sudoers rule — that widens exposure to every sudo call.
  • Do not put the token in /etc/environment. It is world-readable and read by pam_env for every session, which would defeat the 0640 design.
  • Rotation rewrites the file on the next run, but open sessions keep the old value until re-login, and the old token must be revoked in the web vault separately — the playbook cannot do that.
VariableDefaultDescription
bitwarden_bw_github_repobitwarden/clientsGitHub repository for bw CLI
bitwarden_bws_github_repobitwarden/sdk-smGitHub repository for bws CLI
bitwarden_temp_dir/tmp/bitwarden-installTemporary download directory

See defaults/main.yml for all available variables.

None.

Install both CLI tools with default versions and configuration:

---
- hosts: all
roles:
- role: bitwarden

Configure for a self-hosted Bitwarden instance:

---
- hosts: all
roles:
- role: bitwarden
bitwarden_server_url: 'https://vault.example.com'

Configure for Bitwarden’s European region:

---
- hosts: all
roles:
- role: bitwarden
bitwarden_server_url: 'https://vault.bitwarden.eu'
bitwarden_bws_server_api: 'https://api.bitwarden.eu'
bitwarden_bws_server_identity: 'https://identity.bitwarden.eu'

This will create ~/.config/bws/config with:

[profiles.default]
server_api = "https://api.bitwarden.eu"
server_identity = "https://identity.bitwarden.eu"

Install only the Bitwarden CLI, skip bws and configuration:

---
- hosts: all
roles:
- role: bitwarden
bitwarden_install_bw: true
bitwarden_install_bws: false
bitwarden_configure: false

Install only the Bitwarden Secrets CLI:

---
- hosts: all
roles:
- role: bitwarden
bitwarden_install_bw: false
bitwarden_install_bws: true
bitwarden_configure: false

Pin specific versions and configure custom server:

---
- hosts: all
roles:
- role: bitwarden
bitwarden_bw_version: '2024.8.0'
bitwarden_bws_version: '0.9.0'
bitwarden_server_url: 'https://vault.example.com'
bitwarden_bws_server_api: 'https://api.example.com'
bitwarden_bws_server_identity: 'https://identity.example.com'

Control role execution with Ansible tags:

---
- hosts: all
roles:
- role: bitwarden
tags:
- bitwarden
- security
- cli-tools

Run only specific tasks:

Terminal window
# Install only bw
ansible-playbook playbook.yml --tags bitwarden
# Skip bitwarden role
ansible-playbook playbook.yml --skip-tags bitwarden

After the role completes, the CLI tools are ready to use:

Terminal window
# Verify installation
bw --version
# Login to Bitwarden
bw login
# Or login with API key
bw login --apikey
# Configure server (if not done by role)
bw config server https://vault.example.com
# Sync vault
bw sync
# List vault items
bw list items
# Get a specific item
bw get item <item-id>
# Unlock vault and store session
export BW_SESSION="$(bw unlock --raw)"
# Search for items
bw list items --search "github"
Terminal window
# Verify installation
bws --version
# View configuration
cat ~/.config/bws/config
# View help
bws --help
# Use with access token
export BWS_ACCESS_TOKEN="your-access-token"
bws secret list
# Get a specific secret
bws secret get <secret-id>

The role automatically creates ~/.config/bws/config with the appropriate server URLs based on your bitwarden_server_url setting:

[profiles.default]
server_api = "https://api.bitwarden.eu"
server_identity = "https://identity.bitwarden.eu"
  • bw CLI: Generic Linux build (works on all architectures)
  • bws CLI: Architecture-specific builds
    • x86_64 (amd64) - Most common desktop/server architecture
    • aarch64 (arm64) - ARM-based systems (Raspberry Pi 4+, AWS Graviton, etc.)

The role automatically detects the system architecture for bws and downloads the appropriate binary.

If the download fails, check:

  1. GitHub releases exist for the specified version
  2. Network connectivity to GitHub
  3. Correct version format (e.g., 2024.9.0, not v2024.9.0)

If installed binaries are not found:

Terminal window
# Check installation path
ls -la /usr/local/bin/bw /usr/local/bin/bws
# Verify PATH includes installation directory
echo $PATH
# Add to PATH if needed
export PATH="/usr/local/bin:$PATH"

Ensure the role is run with configuration enabled:

bitwarden_configure: true

And that bw CLI is installed:

bitwarden_install_bw: true
  • Bitwarden CLI (bw): Default version 2026.7.0
  • Bitwarden Secrets CLI (bws): Default version 2.1.0

Both repositories are monorepos that tag several products, so /releases/latest does not return the CLI — it is usually a web, desktop, rust or python release. Filter the release list by tag prefix instead:

Terminal window
# Check bw releases (cli-v tags)
curl -s 'https://api.github.com/repos/bitwarden/clients/releases?per_page=100' \
| grep '"tag_name"' | grep cli-v | head -5
# Check bws releases (bws-v tags)
curl -s 'https://api.github.com/repos/bitwarden/sdk-sm/releases?per_page=100' \
| grep '"tag_name"' | grep bws-v | head -5

MIT

Created for ubuntu-server-config repository.

To contribute improvements:

  1. Test changes thoroughly
  2. Update documentation
  3. Follow existing code style
  4. Ensure idempotency
  5. Verify on multiple architectures if possible