<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Stefan Sabolowitsch</title>
    <description>The latest articles on DEV Community by Stefan Sabolowitsch (@stefan_sabolowitsch_3bd10).</description>
    <link>https://dev.to/stefan_sabolowitsch_3bd10</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2288152%2F2a45461c-1384-4511-b499-3ea2a0240780.png</url>
      <title>DEV Community: Stefan Sabolowitsch</title>
      <link>https://dev.to/stefan_sabolowitsch_3bd10</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/stefan_sabolowitsch_3bd10"/>
    <language>en</language>
    <item>
      <title>Stop testing your flow collector with random NetFlow tuples</title>
      <dc:creator>Stefan Sabolowitsch</dc:creator>
      <pubDate>Fri, 10 Jul 2026 10:31:11 +0000</pubDate>
      <link>https://dev.to/stefan_sabolowitsch_3bd10/stop-testing-your-flow-collector-with-random-netflow-tuples-4c</link>
      <guid>https://dev.to/stefan_sabolowitsch_3bd10/stop-testing-your-flow-collector-with-random-netflow-tuples-4c</guid>
      <description>&lt;p&gt;If you have ever built or operated a flow collector, you know the problem: the&lt;br&gt;
usual test generators emit random tuples. Random source IP, random destination,&lt;br&gt;
random ports, random counters. That is fine for a parser smoke test — and&lt;br&gt;
useless for everything after the parser. Dashboards look like noise, enrichment&lt;br&gt;
has nothing meaningful to enrich, and "does my Top-Talkers panel actually make&lt;br&gt;
sense?" is a question random data cannot answer.&lt;/p&gt;

&lt;p&gt;I ran into this while building my own collector stack (flow collector →&lt;br&gt;
VictoriaLogs → Grafana) and converting ElastiFlow dashboards to LogsQL. I&lt;br&gt;
needed traffic that &lt;em&gt;behaves&lt;/em&gt; like an enterprise network — repeatably, at a&lt;br&gt;
controlled rate, without pointing test tooling at production. So I built one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://forgejo.sabolowitsch.org/StefanSA/flowsimulator-go" rel="noopener noreferrer"&gt;flowsimulator-go&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
is an open-source enterprise flow simulation platform written in Go. MIT&lt;br&gt;
licensed, single static binary, one dependency.&lt;/p&gt;

&lt;h2&gt;
  
  
  The core idea: simulate sessions, not tuples
&lt;/h2&gt;

&lt;p&gt;Instead of rolling dice per record, &lt;code&gt;flowsimulator-go&lt;/code&gt; models an enterprise&lt;br&gt;
network in YAML — sites, VLANs, address pools, endpoint personas&lt;br&gt;
(&lt;code&gt;windows_client&lt;/code&gt;, &lt;code&gt;domain_controller&lt;/code&gt;, &lt;code&gt;firewall&lt;/code&gt;, …), applications, and&lt;br&gt;
services — and then plays &lt;strong&gt;ordered session chains&lt;/strong&gt; on top of it.&lt;/p&gt;

&lt;p&gt;The built-in &lt;code&gt;windows-login&lt;/code&gt; template is a good example. One session produces&lt;br&gt;
six flow records, in order:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3lywrcuug8x1ww3vvosd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3lywrcuug8x1ww3vvosd.png" alt="windows-login session template: dns_query and dns_response to the DNS server, kerberos and ldap to the domain controller, smb_read and tcp_disconnect to the file server — each event emits one flow record" width="800" height="407"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;DNS before Kerberos, Kerberos before LDAP, LDAP before SMB — the way a real&lt;br&gt;
Windows logon looks on the wire. Web browsing resolves DNS before opening TLS.&lt;br&gt;
Backups authenticate before they transfer. A behaviour profile&lt;br&gt;
(&lt;code&gt;interactive-tcp&lt;/code&gt;, &lt;code&gt;bulk-transfer&lt;/code&gt;, &lt;code&gt;asymmetric-download&lt;/code&gt;, …) shapes bytes,&lt;br&gt;
packets, duration, and TCP flags per event.&lt;/p&gt;

&lt;p&gt;There are ~30 built-in templates, including security patterns: port scans,&lt;br&gt;
SSH/RDP brute force, SMB enumeration, beaconing, DNS tunneling, exfiltration,&lt;br&gt;
and lateral movement. Crucially, these run as &lt;em&gt;low-weight&lt;/em&gt; scenarios blended&lt;br&gt;
into dominant normal traffic — because a detection dashboard tested against&lt;br&gt;
100% attack traffic tells you nothing.&lt;/p&gt;

&lt;h2&gt;
  
  
  One neutral core, four wire protocols
&lt;/h2&gt;

&lt;p&gt;Architecturally, everything funnels through a protocol-neutral &lt;code&gt;FlowRecord&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhqyc8pc4ylb13tsmkqyj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhqyc8pc4ylb13tsmkqyj.png" alt="Architecture: YAML config feeds the scenario engine, which produces protocol-neutral FlowRecords that per-exporter encoders serialize as NetFlow v5, NetFlow v9, IPFIX, or sFlow v5 and send over UDP to a flow collector" width="800" height="319"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The scenario engine knows nothing about wire formats; the encoders (NetFlow v5,&lt;br&gt;
NetFlow v9, IPFIX, sFlow v5) know nothing about scenarios. Each exporter keeps&lt;br&gt;
its own encoder state — sequence numbers, NetFlow v9/IPFIX template&lt;br&gt;
refresh/cache, sFlow sample pools — so a mixed-protocol simulation behaves like&lt;br&gt;
a fleet of independent devices. Templates are derived from a central,&lt;br&gt;
source-backed IANA/IPFIX information element registry; custom enterprise IEs&lt;br&gt;
can be added via registry files.&lt;/p&gt;

&lt;p&gt;Runs are deterministic: same seed + same config = same dataset. That makes&lt;br&gt;
regression testing across collector versions actually meaningful.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quickstart
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://forgejo.sabolowitsch.org/StefanSA/flowsimulator-go.git
&lt;span class="nb"&gt;cd &lt;/span&gt;flowsimulator-go
go run ./cmd/flowsimulator-go run &lt;span class="nt"&gt;-c&lt;/span&gt; configs/examples/minimal-netflow5.yaml &lt;span class="nt"&gt;--duration&lt;/span&gt; 5s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That sends five seconds of NetFlow v5 to &lt;code&gt;127.0.0.1:2055&lt;/code&gt;. Minimal configs&lt;br&gt;
exist for all four protocols, enterprise examples model HQ/campus/datacenter/&lt;br&gt;
hybrid-cloud topologies, and a continuous lab config runs all four protocols&lt;br&gt;
until SIGTERM — useful as a permanent telemetry source for an observability&lt;br&gt;
lab or collector burn-in. A JSON status endpoint reports records, packets,&lt;br&gt;
bytes, per-protocol counters, and current rate while it runs.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it deliberately does NOT do
&lt;/h2&gt;

&lt;p&gt;A few honest boundaries, because I think tooling should state them up front:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No invented vendor fields.&lt;/strong&gt; Cisco/Palo Alto/Fortinet enterprise IEs only
enter the registry with a documented source. No made-up field numbers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No payloads, no PCAP replay, no fuzzing.&lt;/strong&gt; It serializes flow records,
nothing else. The security scenarios are synthetic flow &lt;em&gt;patterns&lt;/em&gt; for
testing detection pipelines — they do not perform attacks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;IPv4 only for now.&lt;/strong&gt; IPv6, IPFIX Options Templates, and richer
NAT/MPLS/VXLAN/SD-WAN records are on the roadmap.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Repo: &lt;a href="https://forgejo.sabolowitsch.org/StefanSA/flowsimulator-go" rel="noopener noreferrer"&gt;https://forgejo.sabolowitsch.org/StefanSA/flowsimulator-go&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Docs: session template library, scenario model, protocol coverage plan, and
integration test strategy are all in &lt;code&gt;docs/&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;License: MIT&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you build or operate flow collectors — or you just want realistic NetFlow/&lt;br&gt;
IPFIX/sFlow data for a Grafana lab — I would genuinely like to hear what breaks&lt;br&gt;
and what is missing. Issues and feedback welcome.&lt;/p&gt;

</description>
      <category>go</category>
      <category>networking</category>
      <category>opensource</category>
      <category>observability</category>
    </item>
    <item>
      <title>Vaultwarden-Plus v1.36.3: Organization Account Recovery — without breaking zero-knowledge</title>
      <dc:creator>Stefan Sabolowitsch</dc:creator>
      <pubDate>Fri, 03 Jul 2026 09:17:16 +0000</pubDate>
      <link>https://dev.to/stefan_sabolowitsch_3bd10/vaultwarden-plus-v1363-organization-account-recovery-without-breaking-zero-knowledge-144</link>
      <guid>https://dev.to/stefan_sabolowitsch_3bd10/vaultwarden-plus-v1363-organization-account-recovery-without-breaking-zero-knowledge-144</guid>
      <description>&lt;p&gt;Every operator who runs Vaultwarden for a team eventually hits the same wall: &lt;strong&gt;a member forgets their master password.&lt;/strong&gt; In a zero-knowledge system that's supposed to be a dead end by design — the server can't just "reset" what it never had access to.&lt;/p&gt;

&lt;p&gt;Bitwarden solves this upstream with &lt;strong&gt;Organization Account Recovery&lt;/strong&gt;: enrolled members hand the org an encrypted recovery blob, and an admin can trigger a recovery that forces a password reset — all without the server ever seeing a plaintext password or vault key. That capability has been on the operator wishlist for Vaultwarden for a long time.&lt;/p&gt;

&lt;p&gt;As of &lt;strong&gt;v1.36.3&lt;/strong&gt;, it's integrated into Vaultwarden-Plus.&lt;/p&gt;

&lt;h2&gt;
  
  
  What actually shipped
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Admin-triggered recovery&lt;/strong&gt; for enrolled organization members, driven through the official Web Vault Admin Console.&lt;/li&gt;
&lt;li&gt;Forced password-reset flow for the affected member on next login (&lt;code&gt;update-temp-password&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Support for both &lt;strong&gt;legacy&lt;/strong&gt; and &lt;strong&gt;V2&lt;/strong&gt; password payloads, plus &lt;strong&gt;2FA-only&lt;/strong&gt; recovery requests.&lt;/li&gt;
&lt;li&gt;A Web Vault adapter that handles the older &lt;code&gt;/reset-password&lt;/code&gt; path &lt;em&gt;and&lt;/em&gt; the current &lt;code&gt;/recover-account&lt;/code&gt; calls, so official-client compatibility stays intact.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The part I care about most: the security model didn't move
&lt;/h2&gt;

&lt;p&gt;Account recovery is exactly the kind of feature that's easy to ship &lt;em&gt;badly&lt;/em&gt; — by quietly weakening the threat model. So the hard constraint was: &lt;strong&gt;zero-knowledge stays zero-knowledge.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The server still never stores plaintext master passwords, plaintext vault keys, plaintext org private keys, passkey PRF secrets, trusted-device material, or decrypted vault contents. Recovery only works when org policy, enrollment, authorization, &lt;em&gt;and&lt;/em&gt; a valid recovery payload all line up — and credential mutation stays &lt;strong&gt;fail-closed&lt;/strong&gt; if a request is malformed or incomplete. Recovery material, tokens and mail links are never logged.&lt;/p&gt;

&lt;p&gt;In other words: an admin can get a locked-out colleague back into their vault, but "admin" never becomes "can read everyone's passwords."&lt;/p&gt;

&lt;h2&gt;
  
  
  Operator notes
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;No database or config migration required — drop-in for existing deployments.&lt;/li&gt;
&lt;li&gt;You'll need SMTP / sendmail / SES configured for recovery notification mail.&lt;/li&gt;
&lt;li&gt;The bundled Web Vault is &lt;strong&gt;intentionally pinned to 2026.4.1&lt;/strong&gt; (validated against this recovery flow); upgrades beyond it wait until an upstream artifact is available &lt;em&gt;and&lt;/em&gt; separately validated.&lt;/li&gt;
&lt;li&gt;Validated end-to-end on an isolated stack (SQLite + Maildev): policy → enrollment → admin recovery → forced reset → completion.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;vaultwarden&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;forgejo.sabolowitsch.org/stefansa/vaultwarden-plus:1.36.3&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;vaultwarden&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;unless-stopped&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;DOMAIN&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://vw.domain.tld"&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./vw-data/:/data/&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;127.0.0.1:8000:80&lt;/span&gt;   &lt;span class="c1"&gt;# TLS terminates at your reverse proxy&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Release &amp;amp; full notes: &lt;a href="https://forgejo.sabolowitsch.org/StefanSA/vaultwarden-plus/releases/tag/v1.36.3" rel="noopener noreferrer"&gt;https://forgejo.sabolowitsch.org/StefanSA/vaultwarden-plus/releases/tag/v1.36.3&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you run Vaultwarden for an organization, I'd love to hear how you currently handle lost-master-password situations — and whether this matches what you'd need. 🔐&lt;/p&gt;

</description>
      <category>vaultwarden</category>
      <category>selfhosted</category>
      <category>security</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Vaultwarden-Plus: A Password Manager Built for Operators</title>
      <dc:creator>Stefan Sabolowitsch</dc:creator>
      <pubDate>Wed, 24 Jun 2026 11:29:39 +0000</pubDate>
      <link>https://dev.to/stefan_sabolowitsch_3bd10/vaultwarden-plus-a-password-manager-built-for-operators-621</link>
      <guid>https://dev.to/stefan_sabolowitsch_3bd10/vaultwarden-plus-a-password-manager-built-for-operators-621</guid>
      <description>&lt;p&gt;If you search dev.to for Vaultwarden, you'll find dozens of excellent guides: how to deploy it with Docker, how to put it behind a reverse proxy, how to back it up, how to do it for $3 a month. They all answer the same question — &lt;em&gt;how do I stand this up?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This article answers a different one: &lt;strong&gt;what happens after it's running, for years, for other people?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That's the question behind Vaultwarden-Plus.&lt;/p&gt;

&lt;h2&gt;
  
  
  First, the obvious disclaimer
&lt;/h2&gt;

&lt;p&gt;Vaultwarden has been my password manager of choice for years. It's lightweight, fast, reliable, and one of the best examples of what a community-driven open source project can achieve. Thousands of people use it every day to self-host their passwords while staying fully compatible with the official Bitwarden clients.&lt;/p&gt;

&lt;p&gt;So why a fork?&lt;/p&gt;

&lt;p&gt;The honest answer surprised even me: &lt;strong&gt;I wasn't looking for more features. I was looking for a project that prioritizes long-term operation.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Vaultwarden-Plus is &lt;em&gt;not&lt;/em&gt; a replacement for upstream, and it's &lt;em&gt;not&lt;/em&gt; an attempt to compete. Upstream is excellent and keeps moving the whole ecosystem forward. Plus just asks a narrower question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What would a Vaultwarden distribution look like if every single decision were made from the perspective of the person who has to operate it?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  From self-hosting to operating
&lt;/h2&gt;

&lt;p&gt;Running a password manager for yourself is one thing. Running it for your family, your friends, or an organization changes the perspective completely.&lt;/p&gt;

&lt;p&gt;Every update matters. Every config change matters. Every security improvement matters. And — most underrated of all — every &lt;em&gt;unexpected behavior&lt;/em&gt; matters, because you're the one who gets the message at 23:00 that "the login is weird."&lt;/p&gt;

&lt;p&gt;Over time I'd accumulated a growing pile of local patches: security hardening, CI changes, operational notes. Eventually it stopped being a personal patch set and started being a project. Vaultwarden-Plus is that project, made public.&lt;/p&gt;

&lt;h2&gt;
  
  
  The rules I actually maintain it by
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. The official client comes first
&lt;/h3&gt;

&lt;p&gt;One rule is close to absolute:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If the official Bitwarden clients don't work, the feature is probably wrong.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Compatibility beats experimental functionality every time. You keep using the apps you already trust — browser extension, desktop, mobile, CLI — with no modified clients and no special workflows. A "cool feature" that only works in a patched client isn't a feature for an operator; it's a future support ticket.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Validation before implementation
&lt;/h3&gt;

&lt;p&gt;Implementing everything is easy. &lt;em&gt;Maintaining&lt;/em&gt; everything is not. So every proposed change runs the same gauntlet before a single line is written:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is there a real operational problem behind it?&lt;/li&gt;
&lt;li&gt;Does an upstream solution already exist?&lt;/li&gt;
&lt;li&gt;Does it improve security?&lt;/li&gt;
&lt;li&gt;How much maintenance cost does it add?&lt;/li&gt;
&lt;li&gt;Can it be reviewed independently?&lt;/li&gt;
&lt;li&gt;Can it be removed later without breaking unrelated things?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sometimes the answer is a new feature. Sometimes the best engineering decision is to do nothing — and write down &lt;em&gt;why&lt;/em&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Small changes scale better
&lt;/h3&gt;

&lt;p&gt;Big rewrites look impressive in a changelog and are miserable to review and maintain three years later. Plus deliberately prefers focused, well-scoped additions. The features that exist today exist because an operator hit a real wall:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Mail dispatch hardening&lt;/strong&gt; — non-critical account notifications are dispatched &lt;em&gt;outside&lt;/em&gt; latency-sensitive request paths, while critical OTP and security mails stay &lt;strong&gt;fail-closed&lt;/strong&gt;. A slow SMTP server should never block a login; a security mail should never silently get dropped.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DKIM signing&lt;/strong&gt; for outgoing notification mail — because "your users' password-reset mail lands in spam" is an operational problem, not a UI one.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AWS SES mail transport&lt;/strong&gt; — SES as a first-class alternative to plain SMTP for people who already run their mail through it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Send email verification&lt;/strong&gt; — require recipients to verify their address before they can open a Send.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OpenDAL / S3 enhancements&lt;/strong&gt; — better S3-compatible object storage for attachments and data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Passkey login&lt;/strong&gt; &lt;em&gt;(experimental)&lt;/em&gt; — passwordless sign-in via passkeys.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;2026.5 client-compatibility updates&lt;/strong&gt; — keeping pace with recent official Bitwarden client releases, so the "official client first" rule stays true in practice.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of these turn the UI upside down. All of them make the service a little more &lt;em&gt;predictable&lt;/em&gt; in production — which is exactly the property you care about when other people's passwords live on your box.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Documentation is part of the product
&lt;/h3&gt;

&lt;p&gt;One lesson from years of running infrastructure: &lt;strong&gt;undocumented decisions eventually become forgotten decisions.&lt;/strong&gt; Plus keeps a small set of canonical documents that evolve with the code — current project state, implemented functionality, upstream assessments, product goals, maintenance strategy. The docs are treated as part of the software, not an afterthought.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Upstream is a partner, not a competitor
&lt;/h3&gt;

&lt;p&gt;The biggest risk for any long-lived fork is pointless divergence. So every upstream proposal gets continuously categorized into one of four buckets:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Implement · Watch · Defer · Reject&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The goal is &lt;em&gt;not&lt;/em&gt; to collect the most custom features. It's to stay small, understandable, and maintainable while adopting the improvements that give operators clear value.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this means for you
&lt;/h2&gt;

&lt;p&gt;Vaultwarden-Plus will probably never have the longest feature list. &lt;strong&gt;That's intentional.&lt;/strong&gt; The focus stays on security, operational reliability, maintainability, reproducible releases, and compatibility with the official clients.&lt;/p&gt;

&lt;p&gt;If you already run Vaultwarden, the switch is meant to be undramatic: same clients, same data model, same mental model — just decisions tuned for the person holding the pager. One small but telling example of that mindset: Plus does &lt;strong&gt;not&lt;/strong&gt; recommend Rocket's built-in TLS for production. It expects TLS termination at an external reverse proxy (Traefik, Nginx, HAProxy, …) and the container to speak plain HTTP behind it — fewer moving parts in the crypto path, fewer surprises during an upgrade.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;Stable container images are published to the project's own registry, so a Compose file is all you need:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;vaultwarden&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;forgejo.sabolowitsch.org/stefansa/vaultwarden-plus:latest&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;vaultwarden&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;unless-stopped&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;DOMAIN&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://vw.domain.tld"&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./vw-data/:/data/&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;127.0.0.1:8000:80&lt;/span&gt;   &lt;span class="c1"&gt;# TLS terminates at your reverse proxy&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The project lives here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;👉 &lt;strong&gt;Source, releases, issues &amp;amp; container registry:&lt;/strong&gt; &lt;a href="https://forgejo.sabolowitsch.org/StefanSA/vaultwarden-plus" rel="noopener noreferrer"&gt;forgejo.sabolowitsch.org/StefanSA/vaultwarden-plus&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;One ground rule: report &lt;strong&gt;Plus-specific&lt;/strong&gt; behaviour to the Plus tracker, not to upstream. If a bug reproduces on a stock Vaultwarden install, it belongs upstream. Keeping that boundary clean is part of being a good downstream citizen.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you maintain self-hosted services or open source projects of your own, I'd genuinely like to hear how &lt;em&gt;you&lt;/em&gt; approach long-term maintenance — the patches that never made it upstream, the "we decided to do nothing" calls, the docs you wish you'd written sooner. That's the conversation I'm hoping this starts.&lt;/p&gt;

&lt;p&gt;Technical deep-dives on the individual hardening changes will follow. If that philosophy resonates, follow along. 🔐&lt;/p&gt;

</description>
      <category>vaultwarden</category>
      <category>selfhosted</category>
      <category>security</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
