<?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: Sam March</title>
    <description>The latest articles on DEV Community by Sam March (@sam_march).</description>
    <link>https://dev.to/sam_march</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3724609%2F315e00c3-5876-474f-b06d-6c3aebbf11af.webp</url>
      <title>DEV Community: Sam March</title>
      <link>https://dev.to/sam_march</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sam_march"/>
    <language>en</language>
    <item>
      <title>1.4.0: Authentication and local storage</title>
      <dc:creator>Sam March</dc:creator>
      <pubDate>Tue, 17 Feb 2026 02:50:00 +0000</pubDate>
      <link>https://dev.to/sam_march/140-authentication-and-local-storage-3pa0</link>
      <guid>https://dev.to/sam_march/140-authentication-and-local-storage-3pa0</guid>
      <description>&lt;p&gt;I'm thrilled to announce the 1.4.0 release for BlitzBrowser. This new version contains a new security layer for public deployments and user data storage on local disk by default.&lt;/p&gt;

&lt;p&gt;Until now, persisting user data required setting up an S3 compatible provider. It is great for scale and cloud deployment, it added friction for local development and integration tests. Deploying into the cloud required an external way to restrict access to the browsers. I added a built-in authentication layer on the dashboard and on BlitzBrowser. You can now deploy BlitzBrowser on the internet securly.&lt;/p&gt;

&lt;h2&gt;
  
  
  User Data Storage on Local Disk
&lt;/h2&gt;

&lt;p&gt;In 1.4.0 you are no longer forced to use S3 (like AWS, Cloudflare R2 or RustFS) to save your browser user data. You can now mount a local directory directly to your Docker container to persist them.&lt;/p&gt;

&lt;p&gt;Simply map a volume to &lt;code&gt;/blitzbrowser/user-data&lt;/code&gt; and your user data will persist between container restarts.&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;blitzbrowser&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;ghcr.io/blitzbrowser/blitzbrowser:latest&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="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;9999:9999"&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;./user-data:/blitzbrowser/user-data&lt;/span&gt;
    &lt;span class="na"&gt;shm_size&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2gb"&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;always&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Find all the details about the &lt;a href="https://docs.blitzbrowser.com/self-hosted/features/user-data-storage" rel="noopener noreferrer"&gt;user data storage&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Built-in Authentication
&lt;/h2&gt;

&lt;p&gt;Previously BlitzBrowser was open to anyone who could reach it. Version 1.4.0 introduces built-in authentication to control who can access the browsers and the dashboard. BlitzBrowser and the dashboard can now be configured to use an API key and an authentication key.&lt;/p&gt;

&lt;h3&gt;
  
  
  Configuration
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;BlitzBrowser&lt;/strong&gt;: All CDP and HTTP connections must provide a valid &lt;code&gt;API_KEY&lt;/code&gt;. You can pass the API key by:

&lt;ul&gt;
&lt;li&gt;HTTP header: &lt;code&gt;x-api-key: ${API_KEY}&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Query parameter: &lt;code&gt;apiKey=${API_KEY}&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Dashboard&lt;/strong&gt;: Users must provide the &lt;code&gt;AUTH_KEY&lt;/code&gt; to log in. The dashboard uses the &lt;code&gt;BLITZBROWSER_API_KEY&lt;/code&gt; to connect to the API.&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;For detailed setup instructions, please refer to the &lt;a href="https://docs.blitzbrowser.com/self-hosted/configurations/dashboard" rel="noopener noreferrer"&gt;dashboard configuration&lt;/a&gt; and the &lt;a href="https://docs.blitzbrowser.com/self-hosted/configurations/blitzbrowser" rel="noopener noreferrer"&gt;BlitzBrowser configuration&lt;/a&gt; pages.&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>devops</category>
      <category>browser</category>
    </item>
    <item>
      <title>How I built Live View for browsers running in Docker</title>
      <dc:creator>Sam March</dc:creator>
      <pubDate>Thu, 05 Feb 2026 14:50:00 +0000</pubDate>
      <link>https://dev.to/sam_march/how-i-built-live-view-for-browsers-running-in-docker-47bd</link>
      <guid>https://dev.to/sam_march/how-i-built-live-view-for-browsers-running-in-docker-47bd</guid>
      <description>&lt;p&gt;Debugging browsers in docker is usually a blind experience. You have to screenshot or log every step to see what happens. That's why I built the Live View feature.&lt;/p&gt;

&lt;p&gt;While updating the &lt;a href="https://docs.blitzbrowser.com/tutorials/crawl-with-crawl4ai-ollama-and-blitzbrowser" rel="noopener noreferrer"&gt;tutorial&lt;/a&gt; using Crawl4AI, Ollama and BlitzBrowser to run a self hosted AI crawler, I had issues. It wasn't extracting the data I expected and restarting the script every time to debug was painful. I wished to see the browser in real time to understand why.&lt;/p&gt;

&lt;p&gt;My first idea was to create a video stream of the browser, but I remembered my &lt;a href="https://github.com/blitzbrowser/blitzbrowser/issues/1" rel="noopener noreferrer"&gt;first issue&lt;/a&gt; requesting a real time interaction with the browser. I started to look for an equivalent of the RDP protocol on Linux. I discovered the VNC (Virtual Network Computing) protocol and the &lt;a href="https://github.com/novnc/noVNC" rel="noopener noreferrer"&gt;NoVNC&lt;/a&gt; javascript client.&lt;/p&gt;

&lt;h2&gt;
  
  
  Under the Hood
&lt;/h2&gt;

&lt;p&gt;To see the browser running in docker, I needed to bridge the gap between the Linux virtual display and the web browser. This is the stack used.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Display&lt;/strong&gt;: First the browsers are run in a virtual display. The virtual displays are managed by &lt;a href="https://en.wikipedia.org/wiki/X_Window_System" rel="noopener noreferrer"&gt;x11&lt;/a&gt; and each browser has its own display. I'm using &lt;a href="https://github.com/fluxbox/fluxbox" rel="noopener noreferrer"&gt;Fluxbox&lt;/a&gt; as a window manager.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;VNC Server&lt;/strong&gt;: If the Live View feature is enabled, the browser will be started with a &lt;a href="https://github.com/LibVNC/x11vnc" rel="noopener noreferrer"&gt;x11vnc&lt;/a&gt; server to create the remote access. It will be accessible from a TCP port on the localhost network.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Websocket-to-TCP bridge&lt;/strong&gt;: To connect to the VNC server from a web client, the web server exposes the websocket endpoint &lt;code&gt;/browser-instances/:browser_instance_id/vnc&lt;/code&gt;. When a client connects to the endpoint, it creates a TCP connection to the VNC server. It will bridge the websocket and the TCP socket by transmitting all the data received from the TCP socket to the websocket and all the websocket data to the TCP. &lt;a href="https://github.com/blitzbrowser/blitzbrowser/blob/main/blitzbrowser/src/gateways/vnc.gateway.ts#L13" rel="noopener noreferrer"&gt;This is the code&lt;/a&gt; if you are interesting.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Frontend&lt;/strong&gt;: The NoVNC client to connect the VNC server through the websocket. Once the connection is established, NoVNC streams the virtual display and transmit all the interactions done by the user to the server.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The result
&lt;/h2&gt;

&lt;p&gt;Once the Live View feature was functionnal, I debugged my AI crawler in seconds. The website was detecting my bot, I had no stealth precaution implemented, and it was hiding some data. I changed the tutorial to use the developer doc and it was working perfectly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;If you ever need to debug your headless browsers, I hope this feature will help you to debug faster.&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>devops</category>
      <category>browser</category>
      <category>ai</category>
    </item>
  </channel>
</rss>
