Short Note: faster loading of credentials from Bitwarden using rbw
I have been playing around with the https://ergaster.org/posts/2025/07/28-direnv-bitwarden-integration/. It is a necessary read before you read this note since it explains the problem in quite nice details and builds the proposed solution step by step.
It works just as advertised, but a bit slow for me - in case I have a list of credentials I want to load in my project it takes quite a bit of time to make it work. For example, in my homelab I have around 8 secret variables that I want to export each time.
So, I found a new solution using very similar approach - instead of using bw (which takes ~3 seconds per exported credential), the solution is using rbw (https://github.com/doy/rbw) which takes just a second longer to load the entire project, but if you use IDs to fetch secrets - it is instantaneous from that point on.
The approach proposed below migrates the source of truth about the list of the credentials from the envrc file into Bitwarden / Vaultwarden (I use the latter). Now I can create a folder and put secrets in it on my server and the envrc will just pull them all in, without having to list them one by one in the file. This allows me to more easily “scale” the project setups by just changing things in one place
Additional benefit I also noticed with rbw is that it is present in nix packages, so I can use my Jetify devbox flow out of the box (bw is there as well, but it just doesn’t compile or is broken most of the time on my Apple Silicon MBP). I guess Rust code is easier to deploy across platforms?
Solution
EDIT (01/09/2025): I have adapted the code to reflect longer-term usage of the tool. Apparently if the vault is locked the rbw-agent will be spawned (that’s OK) but (FD?) leaks will remain and direnv will never finish loading. The solution is simple: once finished just terminate the newly created agent (if one exists), which will lock the vault, remove the leak and allow direnv to proceed with loading of the .envrc file
My .envrc file:
rbw_export_folder personal homelab
The function (defined in ~/.config/direnv/lib/bw_to_env.sh) looks like this:
#!/usr/bin/env bash
rbw_export_folder() {
if [[ "$#" -lt 2 ]]; then
echo "You must specify profile for rbw, and a folder as two arguments" >&2
return
fi
local profile=$1
local folder=$2
echo "🔍 Exporting secrets from profile=$profile, folder: $folder"
local existing_agents=$(pgrep -f "rbw-agent" 2>/dev/null || true)
while read -r folder name id; do
export "$name=$(RBW_PROFILE=$profile rbw get "$id")"
echo "✅️ Exported $name"
done < <(RBW_PROFILE=$profile rbw list --fields folder --fields name --fields id 2>/dev/null | grep "^${folder}")
# Kill only the NEW rbw-agent for this profile
local current_agents=$(pgrep -f "rbw-agent" 2>/dev/null || true)
for pid in $current_agents; do
if [[ ! "$existing_agents" =~ $pid ]]; then
kill "$pid" 2>/dev/null || true
echo "🔒 Locked the vault again (rbw-agent $pid stopped)"
fi
done
}
When I enter my folder the output is like this:
🔍 Exporting secrets from profile=personal, folder: homelab
✅️ Exported ANSIBLE_VAULT_PASSWORD
✅️ Exported RESTIC_PASSWORD
✅️ Exported RESTIC_REPOSITORY
✅️ Exported SOL_PASSWORD
✅️ Exported SOL_USERNAME
✅️ Exported VAULT_ADDR
✅️ Exported VAULT_TOKEN
🔒 Locked the vault again (rbw-agent 92468 stopped)
milan@mbp ~/SourceCode/personal/homelab →
