<?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: Thomas Schmitz</title>
    <description>The latest articles on DEV Community by Thomas Schmitz (@fledxdev).</description>
    <link>https://dev.to/fledxdev</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%2F3691107%2F72113963-8644-40db-a0c3-593f5a9f138b.png</url>
      <title>DEV Community: Thomas Schmitz</title>
      <link>https://dev.to/fledxdev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/fledxdev"/>
    <language>en</language>
    <item>
      <title>Why distributing software securely is harder than it looks</title>
      <dc:creator>Thomas Schmitz</dc:creator>
      <pubDate>Mon, 05 Jan 2026 12:49:13 +0000</pubDate>
      <link>https://dev.to/fledxdev/why-distributing-software-securely-is-harder-than-it-looks-5g74</link>
      <guid>https://dev.to/fledxdev/why-distributing-software-securely-is-harder-than-it-looks-5g74</guid>
      <description>&lt;p&gt;Shipping software is easy. Distributing it securely is not.&lt;/p&gt;

&lt;p&gt;Most teams start simple: you build a binary, upload it somewhere, and share a link. That works surprisingly well, until it doesn't. The moment you ship software to paying customers, especially in B2B environments, distribution stops being a file hosting problem and turns into an access control, security, and operations problem.&lt;/p&gt;

&lt;p&gt;This post is about why that happens and why software distribution is often underestimated.&lt;/p&gt;

&lt;h2&gt;
  
  
  The naive setup (and why it's attractive)
&lt;/h2&gt;

&lt;p&gt;For many teams, the first iteration looks familiar. A GitHub Release, maybe a private S3 bucket with presigned URLs, a simple download page, and links sent via email or dropped into documentation. And honestly, this is not wrong.&lt;/p&gt;

&lt;p&gt;It is fast to set up, has almost no operational overhead, and works perfectly fine for open-source projects or early prototypes. You get versioning, hosting, and global availability almost for free.&lt;/p&gt;

&lt;p&gt;The problem is not the approach itself. The problem is what happens when reality kicks in.&lt;/p&gt;

&lt;h2&gt;
  
  
  When things start breaking
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Customers are not anonymous users
&lt;/h3&gt;

&lt;p&gt;Once you have paying customers, you quickly realize that "anyone with the link" is not a valid access model. Suddenly you need answers to questions you never thought about before. Which customer is allowed to download which product? Do different customers have access to different versions? What happens when a contract ends or a trial expires?&lt;/p&gt;

&lt;p&gt;At that point, distribution becomes a customer-scoped problem, not a public one. Every artifact needs context about who should have access and under what conditions.&lt;/p&gt;

&lt;h3&gt;
  
  
  CI/CD is the real consumer
&lt;/h3&gt;

&lt;p&gt;In many setups, humans rarely download artifacts directly. Instead, downloads are triggered by CI pipelines pulling dependencies, update agents checking for new versions, or installers running unattended on customer infrastructure.&lt;/p&gt;

&lt;p&gt;This changes everything. Automation requires long-lived credentials and non-interactive authentication. The blast radius when something leaks is much larger than a single user losing access. Links and shared secrets do not age well in this environment. What works for a human clicking a button once becomes a security liability when embedded in a script that runs thousands of times.&lt;/p&gt;

&lt;h3&gt;
  
  
  Links always leak
&lt;/h3&gt;

&lt;p&gt;This part is uncomfortable, but important. Download links will be forwarded, pasted into support tickets, shared in&lt;br&gt;
Slack channels, stored in CI logs, and bookmarked in browsers. If a link works, you should assume it will be shared, intentionally or not.&lt;/p&gt;

&lt;p&gt;Security by obscurity only works until the first copy-paste. The question is not whether a link will leak, but what happens when it does.&lt;/p&gt;

&lt;p&gt;Here's a concrete example I have seen more than once: a customer is on a time-limited trial, gets an installer link, and shares it internally.&lt;/p&gt;

&lt;p&gt;Someone pastes it into a support ticket to speed up troubleshooting. A CI job logs it while building an update image. A week later the trial ends, but the link is still floating around in places you do not control. Now you need answers: who is still downloading, should they be allowed to, and can you cut off access without breaking everyone else?&lt;/p&gt;

&lt;h2&gt;
  
  
  "Just use presigned URLs" is not enough
&lt;/h2&gt;

&lt;p&gt;Presigned URLs are often presented as the solution, and they do solve an important part of the problem. They protect your storage backend by ensuring nobody can access the underlying bucket directly.&lt;/p&gt;

&lt;p&gt;What they do not provide is customer context, revocation, auditability, or authorization beyond time limits. A presigned URL answers "is this link still valid?" It does not answer "is this customer allowed to download this artifact?"&lt;/p&gt;

&lt;p&gt;Storage can validate a signature. It cannot make distribution decisions like whether a release is actually published, whether a customer is entitled to that product, or whether access should be suspended right now.&lt;/p&gt;

&lt;p&gt;The distinction matters. Presigned URLs solve storage security, not distribution security. They are a necessary building block, but not a complete solution.&lt;/p&gt;

&lt;h2&gt;
  
  
  The hidden requirements nobody lists upfront
&lt;/h2&gt;

&lt;p&gt;Once you start looking closer, a surprisingly consistent set of requirements appears:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Customer-scoped access control: different customers should see different artifacts.&lt;/li&gt;
&lt;li&gt;Product-level entitlements: model what each customer has purchased or is allowed to access.&lt;/li&gt;
&lt;li&gt;Release lifecycle boundaries: keep drafts private and make publishing explicit.&lt;/li&gt;
&lt;li&gt;Time-bound availability: trials, expiring contracts, and phased rollouts.&lt;/li&gt;
&lt;li&gt;Revocation and suspension: end entitlements or suspend customers without rotating credentials everywhere.&lt;/li&gt;
&lt;li&gt;Auditability: support cases and compliance questions need clear answers.&lt;/li&gt;
&lt;li&gt;Automation-first authentication: machines are usually your primary consumers.&lt;/li&gt;
&lt;li&gt;Minimal operational overhead: you still want this to be boring to run.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of these are exotic. What is rare is treating them as first-class concepts instead of bolting them on later when the pain becomes unbearable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this pushed me to rethink release distribution
&lt;/h2&gt;

&lt;p&gt;I ran into these problems repeatedly while working on B2B and self-hosted software. Existing tools were either optimized for humans rather than automation, deeply UI-driven with APIs as an afterthought, tightly coupled to licensing or DRM systems I did not need, or simply hard to integrate cleanly into CI/CD workflows.&lt;/p&gt;

&lt;p&gt;I was not looking to invent a new category. I just wanted a model where the implicit requirements become explicit, where access control, entitlements, and auditability are part of the design from day one, not features added under pressure.&lt;/p&gt;

&lt;p&gt;That line of thinking eventually turned into an API-first, self-hosted release backend called Releasy. But the ideas themselves apply far beyond a single project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Once you have customers, distribution becomes an access control problem.&lt;/li&gt;
&lt;li&gt;Once you have automation, it becomes an operations and security problem too.&lt;/li&gt;
&lt;li&gt;Presigned URLs help, but do not replace customer context, revocation, and auditability.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;In the next post, I will look at what an API-first release platform actually looks like, and why optimizing for automation changes many design decisions.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This post is part of a series about building a self-hosted, API-first release platform. The project that grew out of this work is open source and called Releasy.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>devops</category>
      <category>security</category>
      <category>selfhosted</category>
      <category>api</category>
    </item>
    <item>
      <title>A self-hosted backend for software release access</title>
      <dc:creator>Thomas Schmitz</dc:creator>
      <pubDate>Sat, 03 Jan 2026 10:11:25 +0000</pubDate>
      <link>https://dev.to/fledxdev/a-self-hosted-backend-for-software-release-access-4fno</link>
      <guid>https://dev.to/fledxdev/a-self-hosted-backend-for-software-release-access-4fno</guid>
      <description>&lt;p&gt;Over the last years I noticed that release distribution often becomes messy much earlier than expected. As long as everything is public, a GitHub release or an S3 bucket is usually enough. The moment you need slightly different access rules, things start to break down.&lt;/p&gt;

&lt;p&gt;One customer should get build A but not build B. Another one should only download artifacts for a limited time. CI pipelines need access, but you do not want to hand out long-lived credentials. What often follows is a combination of spreadsheets, ad-hoc scripts, bucket policies and a growing fear of breaking something that already works. &lt;/p&gt;

&lt;p&gt;I started building Releasy to address exactly this gap.&lt;/p&gt;

&lt;p&gt;Releasy is an open source, self-hosted backend that sits in front of your release artifacts and decides who can access what. It does not try to be a licensing SDK, a payment system or a hosted SaaS. It focuses purely on controlled access to releases and downloads, with infrastructure you own and operate yourself.&lt;/p&gt;

&lt;p&gt;The core idea is simple. You publish releases, attach artifacts to them, and grant access via short-lived download tokens or API keys with explicit scopes. A client, a CI job or a customer never talks to your object storage directly. Instead, Releasy validates permissions and issues time-limited access when a download is requested.&lt;/p&gt;

&lt;p&gt;Everything runs as a single Rust service backed by PostgreSQL. It can be deployed on one machine for small setups or split across multiple hosts if needed. Authentication is handled via API keys and optional JWT integration, but it also works without any external identity provider if you want to keep things minimal.&lt;br&gt;
Releasy is fully self-hosted by design. There is no central service, no call-home behavior and no dependency on a vendor backend. If you can run Docker and PostgreSQL, you can run Releasy. The full source code, deployment playbooks and documentation are available publicly.&lt;/p&gt;

&lt;p&gt;This project grew out of a real need in my own work, and I am sharing it in case others are facing similar problems with release distribution and access control. It is still evolving, but already usable for real setups.&lt;br&gt;
If this sounds relevant to you, you can find the repository and documentation here:&lt;br&gt;
&lt;a href="https://github.com/releasyhq/releasy" rel="noopener noreferrer"&gt;https://github.com/releasyhq/releasy&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Feedback, questions and critical perspectives are very welcome.&lt;/p&gt;

</description>
      <category>selfhosted</category>
      <category>devops</category>
      <category>api</category>
      <category>security</category>
    </item>
  </channel>
</rss>
