Skip to main content

Why we revamped file management

· 4 min read
Technical Content Editor and Full-Stack Developer at Authentik Security Inc

authentik is an open source Identity Provider that unifies your identity needs into a single platform, replacing Okta, Keycloak, and Ping. Authentik Security is a public benefit company building on top of the open source authentik project.


For years, we relied on Django's built-in storage backend, which is a solid base for less complex projects, but as time passed we started to push it to its limits. However, that's not all on Django; we had some technical debt on our side. For example, before 2025.12, you could not upload a file directly to a brand; you had to provide a full URL. I'll dive into why this was the case later on.

Discovering the problem

When I first explored the codebase, I found our storage logic was about 150 lines of Python serving as a band-aid over Django's storage framework. One of my first GitHub issues for authentik highlighted that S3 files weren't deleted when removed from authentik; it didn't consume gigabytes of storage, but it was frustrating nonetheless.

That issue exposed deeper problems: no visibility into which files were stored, no way to clean up hanging files, and no mapping between authentik objects (like applications, flows, brands, or sources) and the files they referenced (icons, logos, and flow background images). From an admin's perspective, files were effectively write-only.

Plus, each Django model backing those objects had to implement its own file handling logic which resulted in duplicated code and inconsistent approaches across the codebase.

During a team meeting, we brainstormed mockups and a general plan of what was needed. With CSV exporting planned for 2025.12, we knew that we needed to fix the problem, once and for all.

Our solution

The solution: centralized and pluggable modules. We introduced a pluggable backend system with four different backends:

  • FileBackend: Local filesystem storage
  • S3Backend: Full S3-compatible storage
  • StaticBackend: Read-only access to bundled static assets (like default icons and source icons)
  • PassthroughBackend: Support for external URLs (HTTP/HTTPS)

Each backend implements an interface with methods such as list_files(), file_url(), save_file(), and delete_file(). Want to add support for some obscure storage backend no one has ever heard of? Implement the interface (and plug it in), and the rest of the UI and API stays the same.

This is also a filesystem-first approach. The storage backend itself is the source of truth, not some PostgreSQL table that we hope stays in sync. When you ask "does this file exist?", authentik queries the backend. If a file is there, authentik knows about it. If it's gone, it's gone. Simple and reliable.

Plus, we now have a file manager that can route files based on their usage. Do you want your CSV reports stored on the local filesystem while media uploads go to S3-compatible storage (like Amazon S3, MinIO, or Cloudflare R2)? No problem.

What this means for you

But what does this mean for you as an authentik administrator?

  • Central file management: All files are now visible and manageable from a single location in the Admin interface.
  • RBAC for files: File access is now governed by the same RBAC as the rest of authentik. You can control who can upload, view, and delete files.
  • One API endpoint: Instead of scattered file handling across multiple endpoints, there's now a unified file API that makes integrations and automation much cleaner.
  • Universal file picker: A consistent file picker (with upload and search) across all of authentik. Whether you're setting an application icon, a flow background, or a brand logo, you get the same intuitive picker.

Let us know what you think

We always want to hear feedback on our decisions and directions. Let us know what you think about the new file management system. Does it improve your workflow? Are there additional backends or features you'd like to see?

Share your thoughts on GitHub, Discord, or via email at [email protected].