Installing Authentik and Putting My Homelab Services Behind It

sherbmeister1 pts0 comments

Installing Authentik and Putting My Homelab Services Behind It | Marius Serbanica

Tech blog

Installing Authentik and Putting My Homelab Services Behind It

03 Apr 2026

I finally got around to doing something I should have done a while ago: putting a proper front door in front of the self-hosted services I actually care about.<br>For a long time, my setup worked, but it was messy. Some apps were public, some were only reachable internally, some lived behind random reverse proxy rules, and a few had their own local logins that I didn't really want to keep managing forever. It wasn't terrible, but it also wasn't the kind of setup that gives you confidence when you look at it six months later.<br>So I rebuilt that part of the stack around Authentik.<br>The goal was simple:<br>one place to handle authentication<br>fewer publicly exposed services<br>cleaner access for internal dashboards and admin panels<br>the option to keep selected paths public when I actually need them to be<br>something I could keep expanding without reinventing the wheel every weekend<br>Cloudflare Tunnel handles the public edge, Authentik handles login and policy, and the services themselves stay internal.

Why I picked Authentik<br>I wanted something that felt at home in a self-hosted environment rather than something that constantly nudged me back towards a managed platform.<br>What sold me was that Authentik can be installed pretty cleanly with Docker Compose, supports proxy providers out of the box, and has an embedded outpost that removes a lot of the usual friction when you're fronting internal web apps. Once that clicked, the rest of the design got a lot simpler.<br>I also liked that I didn't need to throw every application directly onto the internet just to make it usable. Cloudflare Tunnel gave me the external entry point, while Authentik became the thing sitting in front of the apps I actually wanted to protect.

The stack I ended up withNothing exotic here. I kept it straightforward:<br>Authentik running in Docker Compose<br>PostgreSQL and Redis as part of the stack<br>Cloudflare Tunnel publishing the external hostnames<br>Internal services sitting on private addresses<br>Proxy providers in Authentik for the apps I wanted to protect

Installing Authentik<br>I went with the Docker Compose route because it is fast, easy to reason about, and perfectly fine for a small production-style homelab setup.<br>The rough flow was:<br>Download the current compose.yml<br>Generate the PostgreSQL password and Authentik secret key<br>Bring the stack up<br>Run the browser-based initial setup flow<br>Create the first admin account and start wiring apps into it<br>wget https://docs.goauthentik.io/compose.yml<br>echo "PG_PASS=$(openssl rand -base64 36 | tr -d '\n')" >> .env<br>echo "AUTHENTIK_SECRET_KEY=$(openssl rand -base64 60 | tr -d '\n')" >> .env<br>docker compose pull<br>docker compose up -dOnce the containers were healthy, I opened the initial setup flow and finished the first-run configuration from the browser.<br>What I liked: the install didn't ask me to invent a whole platform around it first. It was just a clean Docker Compose deployment, then the real work started in the Authentik UI.

Publishing it with Cloudflare TunnelI didn't want to forward a pile of ports or leave random web apps hanging out on my WAN IP. Cloudflare Tunnel was the obvious fit for that.<br>The key idea is simple: instead of exposing the origin directly, cloudflared creates an outbound-only connection to Cloudflare and publishes hostnames from there. That means the apps can stay on internal addresses.<br>For this setup, both of these public hostnames point to the Authentik server, not directly to the app:<br>auth.example.com<br>monitor.example.com<br>That part matters.<br>When using Authentik's embedded outpost, the request comes into the Authentik server and gets routed by hostname to the correct proxy provider. So rather than aiming monitor.example.com straight at something like http://192.168.69.182:3001, I aimed it at Authentik and let Authentik forward the request to the internal service after authentication.<br>tunnel:<br>credentials-file: /home/marius/.cloudflared/.json<br>ingress:<br>- hostname: auth.example.com<br>service: http://192.168.69.10:9000<br>- hostname: monitor.example.com<br>service: http://192.168.69.10:9000<br>- hostname: dashboard.example.com<br>service: http://192.168.69.10:9000<br>- service: http_status:404Once I switched to that model, the whole setup made a lot more sense.<br>How I actually protected the apps<br>For each service, I created a Proxy Provider in Authentik and pointed it at the internal service URL.<br>A simplified example:<br>External host: https://monitor.example.com<br>Internal host: http://192.168.69.182:3001<br>That gives Authentik the public-facing hostname users hit, plus the internal upstream it should proxy to once the request is allowed.<br>The nice bit is that it scales well. Once the pattern is in place, adding more apps is mostly repetition instead of invention.

Uptime Kuma was the first app that made the pattern clickUptime Kuma is a good example because it has...

authentik apps internal example compose services

Related Articles