<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>Colas.Nahaboo.net - file</title>
    <subtitle>Colas Nahaboo personal site, with discussions about programming code, web and computing topics, surfing and SUPing, and various musings.</subtitle>
    <link rel="self" type="application/atom+xml" href="https://colas.nahaboo.net/tags/file/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://colas.nahaboo.net"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2026-07-30T00:00:00+00:00</updated>
    <id>https://colas.nahaboo.net/tags/file/atom.xml</id>
    <entry xml:lang="en">
        <title>filewebx: a simple, private, web file exchange</title>
        <published>2026-07-30T00:00:00+00:00</published>
        <updated>2026-07-30T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://colas.nahaboo.net/code/filewebx-simple-private-web-file-exchange/"/>
        <id>https://colas.nahaboo.net/code/filewebx-simple-private-web-file-exchange/</id>
        
        <content type="html" xml:base="https://colas.nahaboo.net/code/filewebx-simple-private-web-file-exchange/">&lt;p&gt;&lt;img src=&quot;filewebx-logo-240x200.png&quot; align=right&gt;I often need to send files to people — photos, documents, archives — and I got tired of the usual suspects: WeTransfer limits you, SwissTransfer is great but you depend on a third party, and all of them impose size caps, retention limits, and account management overhead.&lt;&#x2F;p&gt;
&lt;p&gt;So I wrote &lt;strong&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;ColasNahaboo&#x2F;filewebx&quot;&gt;filewebx&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;. It is a self-hosted CGI Bash system for private file exchange, using &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;capability-urls&#x2F;&quot;&gt;Capability URLs&lt;&#x2F;a&gt;: you upload a file, get back a non-guessable link, share it. No logins, no passwords, no accounts.&lt;&#x2F;p&gt;
&lt;p&gt;It is your own private WeTransfer &#x2F; MASV &#x2F; Smash &#x2F; SwissTransfer, on your own server.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-it-does&quot;&gt;What it does&lt;a class=&quot;zola-anchor&quot; href=&quot;#what-it-does&quot; aria-label=&quot;Anchor link for: what-it-does&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;No accounts needed&lt;&#x2F;strong&gt;: The URL &lt;em&gt;is&lt;&#x2F;em&gt; the authentication. Your secret admin URL (e.g: &lt;code&gt;https:&#x2F;&#x2F;your.site&#x2F;yJDdYNEXmB&lt;&#x2F;code&gt;) is your dashboard. Share it with nobody, and it is secure.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Guest accounts&lt;&#x2F;strong&gt;: Create isolated spaces for other people by just giving them a link. They can upload and get their own shareable links without seeing yours.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Auto-expiry&lt;&#x2F;strong&gt;: Files expire after a configurable delay (100 days by default). A daily cron job cleans them up.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Nice interface&lt;&#x2F;strong&gt; with for instance an upload progress bar, easy copying of the url, nice colored logs that work without JavaScript frameworks; Just plain HTML + CSS + JS served by a Bash CGI.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Slug URLs&lt;&#x2F;strong&gt;: Download links are readable: &lt;code&gt;https:&#x2F;&#x2F;your.site&#x2F;_&#x2F;OLw6bZrh65lj&#x2F;my-photo.jpg&lt;&#x2F;code&gt; instead of raw url-encoded gibberish.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Geolocalized logs&lt;&#x2F;strong&gt;: See where downloads come from, with IP colors assigned via &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;medium.com&#x2F;@winwardo&#x2F;simple-non-repeating-colour-generation-6efc995832b8&quot;&gt;golden-angle hue sampling&lt;&#x2F;a&gt; to spot patterns at a glance.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Quotas&lt;&#x2F;strong&gt;: Reserve free disk space. Per-guest quotas available.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;how-it-works&quot;&gt;How it works&lt;a class=&quot;zola-anchor&quot; href=&quot;#how-it-works&quot; aria-label=&quot;Anchor link for: how-it-works&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Three bash scripts, one web server, a single directory for data. Uploads go to &lt;code&gt;data&#x2F;&lt;&#x2F;code&gt;, metadata is stored as bash associative arrays via &lt;code&gt;declare -p&lt;&#x2F;code&gt; (from my &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;ColasNahaboo&#x2F;colas-bash-lib&quot;&gt;colas-bash-lib&lt;&#x2F;a&gt;). The download script (&lt;code&gt;_&lt;&#x2F;code&gt;) logs access and serves the file. The admin script handles the UI, guest management, and cleaning.&lt;&#x2F;p&gt;
&lt;p&gt;The whole thing is plain files — no database, no Docker, no snap, flatpak, no dependencies beyond &lt;code&gt;iconv&lt;&#x2F;code&gt; and a CGI-capable web server (tested with Apache).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why-bash&quot;&gt;Why bash?&lt;a class=&quot;zola-anchor&quot; href=&quot;#why-bash&quot; aria-label=&quot;Anchor link for: why-bash&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Because for a CGI system that runs once per request, startup time does not matter, and bash makes deployment trivial: copy three files, rename one to your admin password, done. No compilation, no npm install, no virtualenv. No dependencies on library that can break at any time in the future. It works now, it will still work in twenty years and more. Also, the bash associative array metadata format (&lt;code&gt;declare -p&lt;&#x2F;code&gt;) is surprisingly practical as simple database — it is both human-readable and machine-parseable without a custom serializer.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;guest-accounts&quot;&gt;Guest accounts&lt;a class=&quot;zola-anchor&quot; href=&quot;#guest-accounts&quot; aria-label=&quot;Anchor link for: guest-accounts&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;You can create guest accounts from the admin tab. A guest only sees its own files. Mark a guest as &quot;admin&quot; to get a link back to the main admin account — useful for creating separate namespaces for different audiences (work, family, surfing buddies).&lt;&#x2F;p&gt;
&lt;p&gt;Non-admin guests cannot access the main account, see other guests, or create new guests. Perfect for giving to people who just need to send you a file.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;deploy&quot;&gt;Deploy&lt;a class=&quot;zola-anchor&quot; href=&quot;#deploy&quot; aria-label=&quot;Anchor link for: deploy&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;Create a directory on your server with &lt;code&gt;data&#x2F;&lt;&#x2F;code&gt; and &lt;code&gt;cgi&#x2F;&lt;&#x2F;code&gt; subdirectories.&lt;&#x2F;li&gt;
&lt;li&gt;Copy &lt;code&gt;filewebx&lt;&#x2F;code&gt; as your admin password name into &lt;code&gt;cgi&#x2F;&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Copy &lt;code&gt;filewebdl&lt;&#x2F;code&gt; as &lt;code&gt;_&lt;&#x2F;code&gt; into &lt;code&gt;cgi&#x2F;&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Copy &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;ColasNahaboo&#x2F;cgibashopts&quot;&gt;cgibashopts&lt;&#x2F;a&gt; into &lt;code&gt;cgi&#x2F;&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Set up a virtual host, add a cron job for daily cleanup.&lt;&#x2F;li&gt;
&lt;li&gt;Done.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;See the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;ColasNahaboo&#x2F;filewebx&quot;&gt;README&lt;&#x2F;a&gt; for full install instructions and Apache config samples. Configuration is done via a single bash-syntax file: set &lt;code&gt;validity&lt;&#x2F;code&gt;, &lt;code&gt;passlen&lt;&#x2F;code&gt;, &lt;code&gt;freequota&lt;&#x2F;code&gt;, &lt;code&gt;guestquotas&lt;&#x2F;code&gt;, and a few more.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-i-like-about-it&quot;&gt;What I like about it&lt;a class=&quot;zola-anchor&quot; href=&quot;#what-i-like-about-it&quot; aria-label=&quot;Anchor link for: what-i-like-about-it&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;It is the simplest thing that works: data is plain files, so I can &lt;code&gt;ls&lt;&#x2F;code&gt;, &lt;code&gt;grep&lt;&#x2F;code&gt;, &lt;code&gt;rsync&lt;&#x2F;code&gt; everything without special tools.&lt;&#x2F;li&gt;
&lt;li&gt;Capability URLs mean I never have to manage a user database. The random tokens are generated from &lt;code&gt;&#x2F;dev&#x2F;urandom&lt;&#x2F;code&gt; — 12 characters give about 10^14 combinations.&lt;&#x2F;li&gt;
&lt;li&gt;The log coloring with perceptually-spaced HSL hues makes browsing download history genuinely pleasant.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The code is at &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;ColasNahaboo&#x2F;filewebx&quot;&gt;github.com&#x2F;ColasNahaboo&#x2F;filewebx&lt;&#x2F;a&gt;, MIT license. Contributions, issues, and ideas welcome.&lt;&#x2F;p&gt;
</content>
        
    </entry>
</feed>
