<?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: Rodrigo Sanchez</title>
    <description>The latest articles on DEV Community by Rodrigo Sanchez (@elcid).</description>
    <link>https://dev.to/elcid</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%2F4163030%2F44f0120d-3066-455f-8e38-1e18c9221149.jpg</url>
      <title>DEV Community: Rodrigo Sanchez</title>
      <link>https://dev.to/elcid</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/elcid"/>
    <language>en</language>
    <item>
      <title>Securely sharing media from OpenMediaVault with FileBrowser Quantum and Cloudflare Tunnel</title>
      <dc:creator>Rodrigo Sanchez</dc:creator>
      <pubDate>Sun, 11 Oct 2026 13:23:32 +0000</pubDate>
      <link>https://dev.to/elcid/securely-sharing-media-from-openmediavault-with-filebrowser-quantum-and-cloudflare-tunnel-38oc</link>
      <guid>https://dev.to/elcid/securely-sharing-media-from-openmediavault-with-filebrowser-quantum-and-cloudflare-tunnel-38oc</guid>
      <description>&lt;h2&gt;
  
  
  Context
&lt;/h2&gt;

&lt;p&gt;Recently I've had the opportunity to work on a few long-form media projects. These projects required us to collect what I would consider a fair bit of media for what are relatively small theatre companies that wanted to try their hand at increasing their social media exposure for shows. To give you an idea, one project required multiple photo shoots, which resulted in hundreds of photos, and then required full recordings of a tech run and a final recording of the full show on closing night. The stills and video needed to be processed like normal, but the videos needed to be taken further to create trailers and social media content, and also cut into clips so that actors could show off their performances in their portfolios.&lt;/p&gt;

&lt;p&gt;To give you a sense of how the data scaled, a single 3-hour show run in 4K ProRes 422 HQ comes to roughly 800GB. Multiply this by two because we have to do closing night too, and we have ~1.6TB of footage. The 600 Fuji RAW files then add another ~10GB.&lt;/p&gt;

&lt;p&gt;After a few days of editing we can shrink this down to a few ~25GB renders, each with different colour grades and feels, and about 4GB of stills. This is great, that's a lot of space saved. Final project files end up being ~80GB give or take. Oh, and those renders are H.265. Yes, I know AV1 exists, but we have to stay compatible with client hardware. And nobody is building new PCs with the current price of hardware.&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%2Fby5v5jezvewmpdqgpmyo.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%2Fby5v5jezvewmpdqgpmyo.png" width="800" height="452"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;Typically my projects don't require 3 hours of straight recording, so I've been able to get away with juggling cloud services. If the final render is under 15GB I can just use Google Drive and let Google handle security and links. If not, maybe we need to split project files and put the stills on Dropbox to make it all work.&lt;/p&gt;

&lt;p&gt;But free tiers only go so far, and growing them 500MB at a time with referrals isn't a plan. And what happens when a client asks for the raw footage?&lt;/p&gt;

&lt;p&gt;If you've made it this far, thank you, and you can probably guess where this is going: how do I get these files to clients without mailing or lending out my 2TB NVMe?&lt;/p&gt;

&lt;p&gt;The obvious answer is yet another monthly subscription for 1–2TB of cloud storage. The &lt;em&gt;responsible&lt;/em&gt; answer might be Azure Storage, handing out SAS URLs to blobs, and wrapping everything in password-protected zips.&lt;/p&gt;

&lt;p&gt;But that's boring, and I've got a Dell R730xd under my desk that's spent far too long as a footrest.&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 1 - The setup
&lt;/h2&gt;

&lt;p&gt;The server I received already came with ESXi installed and a few TBs that are managed through an internal RAID controller. I won't go into too much detail about the server itself, since the same result can be achieved on bare metal, a VM or containers. The main requirement is a place you can install OpenMediaVault (OMV) and a big storage pool. I was lucky enough that the server came with an HDD1 store of 12TB, and I've added HDD2 and HDD3 as supplementary storage for apps, config backups and other things.&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%2F06cwx69wlroibniviysh.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%2F06cwx69wlroibniviysh.png" width="601" height="217"&gt;&lt;/a&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%2Fhhc3wo910qva148oh1py.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%2Fhhc3wo910qva148oh1py.png" width="800" height="129"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I've chosen to separate the data by using HDD1 as the main storage location for FileBrowser Quantum and HDD2 for Docker components and any other configs, because I prefer the physical boundary. You don't have to do it this way. You may well only have one giant pool; you'll still be able to separate the locations using OMV's shared folder functionality.&lt;/p&gt;

&lt;h3&gt;
  
  
  Installing the OS
&lt;/h3&gt;




&lt;p&gt;OMV has a lot of useful documentation, and the installation process is pretty straightforward with their installer. You burn the ISO to a USB and boot into the installer. If you're on Windows, Rufus is the tool I use; otherwise Etcher or &lt;code&gt;dd&lt;/code&gt; can be used on Linux.&lt;/p&gt;

&lt;p&gt;Through ESXi we can skip all that and upload the ISO image directly to one of our datastores, so that we can bind it to the VM during the creation step. We then run through the VM creation steps, choosing Linux as the guest OS family, Debian as the OS version, and binding the ISO.&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%2Fk0mp054h2eoviwi24jje.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%2Fk0mp054h2eoviwi24jje.png" width="800" height="758"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Another great tweak is to enable the VM to start on boot, so if the server restarts or something happens the VM automagically comes back online.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You should now be able to follow the standard installation guide from OMV and end up with a similar-looking terminal displaying an IP that hosts the web frontend, and some credentials to use on the login page.&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%2Fp50d7fpoj89mmuou3jp7.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%2Fp50d7fpoj89mmuou3jp7.png" width="799" height="518"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Install done.&lt;/p&gt;

&lt;h3&gt;
  
  
  Configuring OpenMediaVault
&lt;/h3&gt;




&lt;p&gt;At this stage you should be able to log in to OMV through your browser and click around to familiarise yourself with the interface. I would also strongly recommend you check for updates under&lt;/p&gt;

&lt;p&gt;&lt;code&gt;System -&amp;gt; Update Management -&amp;gt; Updates&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;so that you have the latest security fixes and features. Oh, and make sure all your disks show up under&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Storage -&amp;gt; Disks&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;We should now be able to start creating Shared Folders and set up SMB. I will create three Shared Folders:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;DockerAppData - Where we store our Docker compose files&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;FileBrowserShares - Where we store what we want to share&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Media1 - The original location of all our data (optional)&lt;/p&gt;&lt;/li&gt;
&lt;/ol&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%2F3zpxddfseludfj7e6ce4.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%2F3zpxddfseludfj7e6ce4.png" width="800" height="200"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I have Media1 here because I was already using OMV for storing the giant RAW footage. Everything can work off a single share, but then all of it will be exposed to the container.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now we just need to enable a way to move files over the network to OMV. Personally I picked SMB for this, since NFS permissions are IP-based and file ownership uses user IDs. Rsync is also a really good option for large files.&lt;/p&gt;

&lt;p&gt;Head down to&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Services -&amp;gt; SMB/CIFS -&amp;gt; Settings&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;and enable it there. You should now be able to create SMB shares under&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Services -&amp;gt; SMB/CIFS -&amp;gt; Shares&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Another optional step is to create a user or a group if you want to limit actions. You should only need one or two shares depending on your setup. Point them at the correct Shared Folders from the previous step:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;FileBrowserShares - Where we drop our final render&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Media1 - Where we store the raw footage&lt;/p&gt;&lt;/li&gt;
&lt;/ol&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%2Fpb4ur7ak694mxk4m7ri2.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%2Fpb4ur7ak694mxk4m7ri2.png" width="798" height="120"&gt;&lt;/a&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%2F1lb0bt32jzto81jyk3gv.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%2F1lb0bt32jzto81jyk3gv.png" width="800" height="452"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Add it to your file browser of choice or your &lt;code&gt;fstab&lt;/code&gt; file and test.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting up OMV Docker
&lt;/h3&gt;




&lt;p&gt;With OMV Shared Folders done and SMB set up, we now need to set up Docker and omv-extras, a set of community-maintained packages that add extra functionality.&lt;/p&gt;

&lt;p&gt;In a terminal, either directly or through SSH, we need to run the install script.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;wget &lt;span class="nt"&gt;-O&lt;/span&gt; - https://github.com/OpenMediaVault-Plugin-Developers/packages/raw/master/install | bash

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should now have a new option in your sidebar under&lt;/p&gt;

&lt;p&gt;&lt;code&gt;System -&amp;gt; omv-extras&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Tick the Docker repo box and click the big blue Save button. Then run apt clean and wait until it says done.&lt;/p&gt;

&lt;p&gt;With omv-extras enabled we should now be able to install openmediavault-compose, which will let us create our Docker containers from compose files. Install the plugin under &lt;code&gt;System -&amp;gt; Plugins&lt;/code&gt; and refresh the page. If you get a connection lost message, it's because OMV restarts its web UI server; just refresh the browser.&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%2Fyg1kgruo5ab8xt86jj8l.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%2Fyg1kgruo5ab8xt86jj8l.png" width="800" height="264"&gt;&lt;/a&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%2F6pmpuxfblxpvlzkd4t6n.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%2F6pmpuxfblxpvlzkd4t6n.png" width="800" height="312"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In your sidebar you should now see a new&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Services -&amp;gt; Compose -&amp;gt; Settings&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;page, which we will need to set up. The first thing you'll want to change is your compose files shared folder. Point this to your DockerAppData shared folder and hit Save. Then hit Install or Reinstall Docker.&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%2Fvh8nro5b7tbljo7dzxvb.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%2Fvh8nro5b7tbljo7dzxvb.png" width="797" height="109"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;DON'T FORGET TO HIT INSTALL OR REINSTALL DOCKER AT THE BOTTOM&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Part 2 - Installing FileBrowser and cloudflared
&lt;/h2&gt;

&lt;p&gt;At this point you should have OMV installed with SSH or direct terminal access, a few Shared Folders set up, SMB or some other way to sync files over the network, and omv-extras with Docker enabled and configured for compose files.&lt;/p&gt;

&lt;p&gt;One hard requirement for this second part is a domain using Cloudflare DNS (the free plan is fine), which gives you access to Cloudflare Zero Trust tunnels. With that said, we're going to start this section by getting the tunnel set up before continuing with OMV. So go ahead and open a new tab or browser window.&lt;/p&gt;

&lt;p&gt;We're going to start by creating a tunnel through the Cloudflare dashboard. You should be able to find the option under&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Protect and Connect -&amp;gt; Zero Trust&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This should redirect you to a new page with a different nav bar that should have&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Networks -&amp;gt; Tunnels&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Here you should be able to create a new tunnel of type &lt;code&gt;Cloudflared&lt;/code&gt;, then for your connector make sure you select Docker.&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%2Fdx99rrjsj4w456e96u5d.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%2Fdx99rrjsj4w456e96u5d.png" width="800" height="237"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;IMPORTANT: Save the token displayed on this page, as it will be used in our compose file later.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Finally, at the publish step you should be able to set a subdomain and a path. I've chosen &lt;code&gt;files&lt;/code&gt; as my subdomain, so I get &lt;code&gt;files.[my-domain].com&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The other crucial step here, if you want to narrow access to just the generated links, is to set the Path field to &lt;code&gt;^/public/.*&lt;/code&gt;. This stops intruders from spamming your login page and scraping anything that's outside of FileBrowser's public folder. The tradeoff is that you also won't be able to access the login page or application externally. For me this isn't an issue, as 90% of the time I will be accessing it locally.&lt;/p&gt;

&lt;p&gt;Lastly, the service section is the connection between our &lt;code&gt;cloudflared&lt;/code&gt; container and &lt;code&gt;FileBrowser Quantum&lt;/code&gt; container. We want to set the type to &lt;code&gt;HTTP&lt;/code&gt; because FileBrowser serves plain HTTP and this hop never leaves the VM. Visitors still get HTTPS via Cloudflare, and the tunnel itself is encrypted. Set the URL to &lt;code&gt;filebrowser:80&lt;/code&gt; (we can use the container names here since Docker provides name resolution between containers; alternatively you could use &lt;code&gt;[server-ip]:8080&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%2Fqivzkqvv1siojp1mjjr6.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%2Fqivzkqvv1siojp1mjjr6.png" width="799" height="232"&gt;&lt;/a&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%2Fxs1j2824mwr1f3myx6bc.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%2Fxs1j2824mwr1f3myx6bc.png" width="800" height="677"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With the tunnel all set up, we can go back to OMV and start writing our compose file!&lt;/p&gt;

&lt;h3&gt;
  
  
  Final steps - Back to OMV
&lt;/h3&gt;




&lt;p&gt;OK, we're nearly done. Hopefully you haven't run into any issues! With the tunnel all set up, we can write our configs and compose files and try to spin up our containers!&lt;/p&gt;

&lt;p&gt;For this step, make sure you have that tunnel connector token handy.&lt;/p&gt;

&lt;p&gt;First we're going to create the FileBrowser config file, so that when the container spins up it's ready to go. This typically lives under a &lt;code&gt;/data&lt;/code&gt; folder in FileBrowser. We're also going to create a separate volume in our container called &lt;code&gt;/deliveries&lt;/code&gt; that will be the publicly exposed directory.&lt;/p&gt;

&lt;p&gt;Create a new folder under &lt;code&gt;DockerAppData/filebrowser/data&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="s2"&gt;"/srv/dev-disk-by-uuid-[disk-uuid]/DockerAppData/filebrowser/data"&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now create a new &lt;code&gt;config.yaml&lt;/code&gt; file inside this folder using a text editor such as &lt;code&gt;nano&lt;/code&gt; or &lt;code&gt;vim&lt;/code&gt;. Make sure you set your external URL correctly.&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;http&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;externalUrl&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://files.[domain].com"&lt;/span&gt;
  &lt;span class="na"&gt;trustProxyHeaders&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="na"&gt;disableWebDAV&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;

&lt;span class="na"&gt;server&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;cacheDir&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/home/filebrowser/data/tmp&lt;/span&gt;
  &lt;span class="na"&gt;sources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/deliveries&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deliveries&lt;/span&gt;
      &lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;defaultEnabled&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;

&lt;span class="na"&gt;frontend&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;MySiteName"&lt;/span&gt;
  &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Client&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;video&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;delivery"&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;The path here needs to match the compose file's volume from our next step, so take note.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Lastly, we need to set the owner to the container's user so it can read and write to its database.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;chown&lt;/span&gt; &lt;span class="nt"&gt;-R&lt;/span&gt; 1000:1000 &lt;span class="s2"&gt;"/srv/dev-disk-by-uuid-[disk-uuid]/DockerAppData/filebrowser/data"&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now for our compose file. Back in OMV's web UI we can create compose files directly by navigating to&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Services -&amp;gt; Compose -&amp;gt; Files&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You should get a form where you can copy and paste the following YAML, substituting your disk UUIDs and your token from Cloudflare's tunnel setup.&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;filebrowser&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/gtsteffaniak/filebrowser:2.0-stable&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;filebrowser&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;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;8080:80"&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;/srv/dev-disk-by-uuid-[disk-uuid]/FileBrowserShares:/deliveries:ro&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;/srv/dev-disk-by-uuid-[disk-uuid]/DockerAppData/filebrowser/data:/home/filebrowser/data&lt;/span&gt;

  &lt;span class="na"&gt;cloudflared&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;cloudflare/cloudflared: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;cloudflared&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;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;tunnel --no-autoupdate run --token [MyBigToken]&lt;/span&gt;
    &lt;span class="na"&gt;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;filebrowser&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fdu3kgjsv3fjlz9eqzwxe.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%2Fdu3kgjsv3fjlz9eqzwxe.png" width="800" height="435"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You'll notice here that we mount &lt;code&gt;/deliveries&lt;/code&gt; and &lt;code&gt;/data&lt;/code&gt; from our previous step. The rest of the YAML is pretty self-explanatory. Hit that Save button.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The &lt;code&gt;:ro&lt;/code&gt; at the end of the &lt;code&gt;/deliveries&lt;/code&gt; volume mounts it read-only. FileBrowser can show and share your files, but it can never modify or delete them, even if something goes wrong. I've done this because I'm testing and didn't want to accidentally delete files. Once you're happy you can remove this&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Back in the main list you should be able to see a new row containing the new FileBrowser compose file. Select the row and click the "Up" button in the toolbar. This will download the images and spin up our containers!&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%2F6ti6nu1dw0v1lyad9xfl.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%2F6ti6nu1dw0v1lyad9xfl.png" width="799" height="162"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 3 - The fun part!
&lt;/h2&gt;




&lt;p&gt;If everything went well, you should see a green "Up" status and the bound ports on the right. You can click the URLs or navigate to your server's IP on port 8080 and see a login screen!&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%2Ffcmmqeumqi2316c3joij.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%2Ffcmmqeumqi2316c3joij.png" width="800" height="626"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You'll need to grab the credentials from the Docker logs, as they are auto-generated by default. You can do this in the terminal using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker logs filebrowser 2&amp;gt;&amp;amp;1 | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; password

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Log in as &lt;code&gt;admin&lt;/code&gt; using that password (you'll be asked to set a new one straight away), and you should be greeted with an empty dashboard! You can now prep some files and drag them through SMB, or whatever network method you chose before, into your &lt;code&gt;FileBrowserShares&lt;/code&gt; shared folder and they will appear!&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%2Fa6dlcazdh8z0bo12hyud.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%2Fa6dlcazdh8z0bo12hyud.png" width="800" height="266"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Back in Cloudflare Tunnels you should now be able to see a Healthy status and one active connector, which confirms everything is hooked up correctly.&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%2Ffdikmen06v06kaidi6yd.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%2Ffdikmen06v06kaidi6yd.png" width="797" height="109"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Testing Links
&lt;/h3&gt;




&lt;p&gt;The final step is to right-click a directory or file and hit Share to generate a link! Give it an expiration time and a password and test it internally. You can then send it to someone, or test it on your phone, to make sure it works externally.&lt;/p&gt;

&lt;p&gt;You should also test that hitting &lt;code&gt;files.[domain].com&lt;/code&gt; directly results in a 404, as we don't want direct traffic.&lt;/p&gt;

&lt;p&gt;If you've reached the end, everything should be working, and your FileBrowser instance should be tunnelled and only allow publicly served content and links in and out.&lt;/p&gt;

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

&lt;p&gt;This was quite a journey, I'm not going to lie. It was my first time working with Cloudflare and its many features, and frankly I'm not convinced it's the absolute best solution to my problem. Maybe blob storage in a cloud provider would have been way easier, who knows. But it was an interesting mini project that taught me a lot, and I'll be testing it out for a few months.&lt;/p&gt;

&lt;p&gt;Ive heard Cloudflare could potentially throttle this solution since serving large video is restricted and has to be routed through their paid services like Stream or R2 but the writing on the wall is that it only applies to 'disproportionate' usage. it will be interesting to see if this applies to my case of a few files a month.&lt;/p&gt;

&lt;p&gt;If anybody knows of any other similar solutions, let me know! I'd love to see how other people have solved this.&lt;/p&gt;




&lt;p&gt;References&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.openmediavault.org/install.html" rel="noopener noreferrer"&gt;https://www.openmediavault.org/install.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.openmediavault.org/en/stable/installation/index.html" rel="noopener noreferrer"&gt;https://docs.openmediavault.org/en/stable/installation/index.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/gtsteffaniak/filebrowser" rel="noopener noreferrer"&gt;https://github.com/gtsteffaniak/filebrowser&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://forum.openmediavault.org/index.php?thread/5549-omv-extras-org-plugin/" rel="noopener noreferrer"&gt;https://forum.openmediavault.org/index.php?thread/5549-omv-extras-org-plugin/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.cloudflare.com/service-specific-terms-application-services/" rel="noopener noreferrer"&gt;https://www.cloudflare.com/service-specific-terms-application-services/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://blog.cloudflare.com/updated-tos/" rel="noopener noreferrer"&gt;https://blog.cloudflare.com/updated-tos/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>selfhosted</category>
      <category>homelab</category>
      <category>cloudflare</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
