Complete Setup Guide for Beginners
Understanding the big picture before we start
One login to access all your self-hosted apps. No more remembering dozens of passwords!
| Phase | Time | Difficulty |
|---|---|---|
| Prerequisites & Accounts | 30-60 min | Easy |
| Local Machine Setup (SSH client) | 10-20 min | Easy |
| Server Setup (Docker, Firewall) | 30-45 min | Medium |
| Core Services | 45-60 min | Medium |
| Authentik Configuration | 30-45 min | Medium |
Total: 3-4 hours (can be split across multiple sessions)
Two machines, different roles
Docker is installed on the SERVER, not your computer!
Windows, Mac, or Linux
Install:
• SSH Client (to connect to server)
• Web Browser (to access apps)
Ubuntu Linux (required)
Install:
• Docker & Docker Compose
• Traefik, Authentik, etc.
| Option | Pros | Cons |
|---|---|---|
| Old PC/Laptop | Free, good performance | Uses power, takes space |
| Mini PC (Intel NUC, etc) | Small, quiet, efficient | Costs $150-400 |
| Raspberry Pi 5 | Cheap ($80), tiny | Limited performance |
| Virtual Machine | Run on existing computer | Shares resources |
| Cloud VPS | No hardware needed | Monthly cost ($5-20) |
Your server needs Ubuntu Server 24.04 LTS (or similar Linux). This is where Docker will be installed. Your personal computer (Windows/Mac) is just used to connect to it.
What you need before starting
Make sure you have everything ready to avoid interruptions
| Component | Minimum | Recommended |
|---|---|---|
| CPU | 4 cores | 8 cores |
| RAM | 8 GB | 16 GB |
| Storage | 100 GB SSD | 250 GB SSD |
For your SERVER: Ubuntu Server 24.04 LTS
⬇️ Download Ubuntu ServerSearch YouTube for "How to install Ubuntu Server 24.04" for step-by-step video guides. It takes about 15-20 minutes.
Sign up for these services first
You'll need accounts with these services. All are FREE for home use!
Throughout this guide, we'll use homelab.dev as an example. Replace this with YOUR domain:
Your Domain: __________________ (write it down!)
Setting up YOUR computer to connect to the server
Install the tool to connect to your server remotely
Good news! Modern Windows has SSH pre-installed. Just use PowerShell or Command Prompt.
# Open PowerShell (Press Windows key, type "PowerShell", hit Enter)
# Connect to your server (replace with your details)
ssh your-username@192.168.1.100
# Example: if your username is "riz" and server IP is 192.168.1.50
ssh riz@192.168.1.50
# First time connecting? Type "yes" when asked about fingerprint
# Then enter your server password
For a better experience, download Windows Terminal from the Microsoft Store. It's free and much nicer!
If you prefer a GUI application:
macOS comes with SSH pre-installed. Just use Terminal.
# Open Terminal:
# Press Cmd + Space, type "Terminal", hit Enter
# Connect to your server (replace with your details)
ssh your-username@192.168.1.100
# Example: if your username is "riz" and server IP is 192.168.1.50
ssh riz@192.168.1.50
# First time connecting? Type "yes" when asked about fingerprint
# Then enter your server password
For a better terminal experience, download iTerm2. It's free and has many useful features!
All Linux distributions come with SSH. Just open your terminal.
# Open your terminal application
# (Usually Ctrl + Alt + T on Ubuntu/Debian)
# Connect to your server (replace with your details)
ssh your-username@192.168.1.100
# Example: if your username is "riz" and server IP is 192.168.1.50
ssh riz@192.168.1.50
# First time connecting? Type "yes" when asked about fingerprint
# Then enter your server password
On your server (with keyboard/monitor attached), run: ip addr or hostname -I
Look for an IP like 192.168.x.x or 10.0.x.x
Installing Docker on your Ubuntu Server
First, SSH into your server from your computer. Then run these commands.
All commands below are run ON THE SERVER, not your local computer!
First, SSH into your server, then update all packages:
# Update package lists
sudo apt update
# Upgrade all packages
sudo apt upgrade -y
# Install required packages
sudo apt install -y curl git openssl ufw ca-certificates
Docker runs your applications in containers. This is where Authentik and Traefik will live.
# ============================================
# DOCKER INSTALLATION FOR UBUNTU SERVER 24.04
# Run these commands ONE BY ONE on your server
# ============================================
# Step 1: Set up Docker's apt repository
sudo apt-get update
sudo apt-get install -y ca-certificates curl
# Step 2: Add Docker's official GPG key
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
# Step 3: Add Docker repository to Apt sources
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# Step 4: Install Docker packages
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
# Step 5: Add your user to docker group (so you don't need sudo)
sudo usermod -aG docker $USER
# Step 6: IMPORTANT - Log out and log back in!
echo "Now type 'exit' to logout, then SSH back in"
After running these commands, type exit to disconnect, then SSH back in. This applies the docker group membership.
# After logging back in via SSH, verify Docker works
docker --version
# Should show: Docker version 24.x.x or newer
docker compose version
# Should show: Docker Compose version v2.x.x
# Test Docker (should run without sudo)
docker run hello-world
# Should show: "Hello from Docker!" message
Protect your server with UFW firewall:
# Set default policies
sudo ufw default deny incoming
sudo ufw default allow outgoing
# Allow SSH (IMPORTANT - don't lock yourself out!)
sudo ufw allow ssh
# Allow HTTP and HTTPS for web traffic
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
# Enable the firewall
sudo ufw enable
# Type 'y' when asked to proceed
# Check status
sudo ufw status
# Create main project directory
mkdir -p ~/homelab-iam
# Create subdirectories
mkdir -p ~/homelab-iam/traefik/{dynamic,acme}
mkdir -p ~/homelab-iam/authentik
mkdir -p ~/homelab-iam/apps
# Navigate to the project
cd ~/homelab-iam
# Verify structure
ls -la
Forward ports 80 and 443 from your router to your server:
| External Port | Internal IP | Internal Port | Protocol |
|---|---|---|---|
| 80 | Your server IP | 80 | TCP |
| 443 | Your server IP | 443 | TCP |
Docker is installed and running. Now let's deploy the actual services!
Setting up Traefik and Authentik
Traefik handles web traffic. Authentik handles identity. Together, they secure your apps.
This file stores your secrets. Run this on your SERVER:
# Navigate to project directory
cd ~/homelab-iam
# Generate random passwords automatically
POSTGRES_PASS=$(openssl rand -base64 32 | tr -d '\n')
REDIS_PASS=$(openssl rand -base64 32 | tr -d '\n')
AUTHENTIK_KEY=$(openssl rand -base64 50 | tr -d '\n')
# Create the .env file with your secrets
cat > .env << EOF
# ============================================
# HOMELAB IAM CONFIGURATION
# ============================================
# IMPORTANT: Replace these with YOUR values!
DOMAIN=yourdomain.com
ACME_EMAIL=your-email@example.com
# Database passwords (auto-generated - don't change)
POSTGRES_PASSWORD=${POSTGRES_PASS}
REDIS_PASSWORD=${REDIS_PASS}
AUTHENTIK_SECRET_KEY=${AUTHENTIK_KEY}
EOF
# Protect the file
chmod 600 .env
# Show the file contents
cat .env
You MUST edit the .env file to add your real domain and email:
nano ~/homelab-iam/.env
Change yourdomain.com to your actual domain.
Press Ctrl+O to save, Ctrl+X to exit.
cat > ~/homelab-iam/traefik/traefik.yml << 'EOF'
# Traefik Configuration
api:
dashboard: true
log:
level: INFO
entryPoints:
web:
address: ":80"
http:
redirections:
entryPoint:
to: websecure
scheme: https
websecure:
address: ":443"
certificatesResolvers:
letsencrypt:
acme:
email: ${ACME_EMAIL}
storage: /etc/traefik/acme/acme.json
httpChallenge:
entryPoint: web
providers:
docker:
endpoint: "unix:///var/run/docker.sock"
exposedByDefault: false
network: traefik-public
file:
directory: /etc/traefik/dynamic
watch: true
EOF
cat > ~/homelab-iam/traefik/dynamic/middlewares.yml << 'EOF'
http:
middlewares:
authentik-auth:
forwardAuth:
address: "http://authentik-server:9000/outpost.goauthentik.io/auth/traefik"
trustForwardHeader: true
authResponseHeaders:
- X-authentik-username
- X-authentik-groups
- X-authentik-email
- X-authentik-name
- X-authentik-uid
security-headers:
headers:
frameDeny: true
contentTypeNosniff: true
browserXssFilter: true
stsSeconds: 31536000
stsIncludeSubdomains: true
EOF
# Create certificate storage file
touch ~/homelab-iam/traefik/acme/acme.json
chmod 600 ~/homelab-iam/traefik/acme/acme.json
cat > ~/homelab-iam/docker-compose.yml << 'EOF'
services:
# TRAEFIK - Reverse Proxy
traefik:
image: traefik:v3.0
container_name: traefik
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./traefik/traefik.yml:/etc/traefik/traefik.yml:ro
- ./traefik/dynamic:/etc/traefik/dynamic:ro
- ./traefik/acme:/etc/traefik/acme
environment:
- ACME_EMAIL=${ACME_EMAIL}
networks:
- traefik-public
labels:
- "traefik.enable=true"
- "traefik.http.routers.traefik.rule=Host(\`traefik.${DOMAIN}\`)"
- "traefik.http.routers.traefik.entrypoints=websecure"
- "traefik.http.routers.traefik.tls.certresolver=letsencrypt"
- "traefik.http.routers.traefik.service=api@internal"
# POSTGRESQL - Database
postgres:
image: postgres:16-alpine
container_name: postgres
restart: unless-stopped
environment:
POSTGRES_USER: authentik
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: authentik
volumes:
- postgres_data:/var/lib/postgresql/data
networks:
- authentik-internal
healthcheck:
test: ["CMD-SHELL", "pg_isready -U authentik"]
interval: 10s
timeout: 5s
retries: 5
# REDIS - Session Cache
redis:
image: redis:7-alpine
container_name: redis
restart: unless-stopped
command: redis-server --requirepass ${REDIS_PASSWORD}
volumes:
- redis_data:/data
networks:
- authentik-internal
healthcheck:
test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD}", "ping"]
interval: 10s
timeout: 5s
retries: 5
# AUTHENTIK SERVER
authentik-server:
image: ghcr.io/goauthentik/server:2024.4.2
container_name: authentik-server
restart: unless-stopped
command: server
environment:
AUTHENTIK_POSTGRESQL__HOST: postgres
AUTHENTIK_POSTGRESQL__USER: authentik
AUTHENTIK_POSTGRESQL__PASSWORD: ${POSTGRES_PASSWORD}
AUTHENTIK_POSTGRESQL__NAME: authentik
AUTHENTIK_REDIS__HOST: redis
AUTHENTIK_REDIS__PASSWORD: ${REDIS_PASSWORD}
AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET_KEY}
AUTHENTIK_ERROR_REPORTING__ENABLED: false
volumes:
- authentik_media:/media
- authentik_templates:/templates
networks:
- traefik-public
- authentik-internal
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
labels:
- "traefik.enable=true"
- "traefik.http.routers.authentik.rule=Host(\`authentik.${DOMAIN}\`)"
- "traefik.http.routers.authentik.entrypoints=websecure"
- "traefik.http.routers.authentik.tls.certresolver=letsencrypt"
- "traefik.http.services.authentik.loadbalancer.server.port=9000"
# AUTHENTIK WORKER
authentik-worker:
image: ghcr.io/goauthentik/server:2024.4.2
container_name: authentik-worker
restart: unless-stopped
command: worker
environment:
AUTHENTIK_POSTGRESQL__HOST: postgres
AUTHENTIK_POSTGRESQL__USER: authentik
AUTHENTIK_POSTGRESQL__PASSWORD: ${POSTGRES_PASSWORD}
AUTHENTIK_POSTGRESQL__NAME: authentik
AUTHENTIK_REDIS__HOST: redis
AUTHENTIK_REDIS__PASSWORD: ${REDIS_PASSWORD}
AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET_KEY}
volumes:
- authentik_media:/media
- authentik_templates:/templates
networks:
- authentik-internal
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
networks:
traefik-public:
name: traefik-public
authentik-internal:
name: authentik-internal
volumes:
postgres_data:
redis_data:
authentik_media:
authentik_templates:
EOF
# Navigate to project directory
cd ~/homelab-iam
# Pull all images first
docker compose pull
# Start all services
docker compose up -d
# Check status
docker compose ps
Let's Encrypt needs time to issue your HTTPS certificates. If you get certificate errors, wait and try again.
Setting up your Identity Provider
Authentik is where you manage users, groups, and application access
Write down your admin username and password. This is your master key!
| Group Name | Purpose | Is Superuser? |
|---|---|---|
| users | All authenticated users | No |
| admins | Full system administrators | Yes ✅ |
You now have a working Identity Provider with MFA enabled!
Verify everything works correctly
Let's verify every component is working
# Check all containers are running
docker compose ps
# Check for any errors
docker compose logs --tail=20
# Check Authentik specifically
docker logs authentik-server --tail=20
# Check Traefik
docker logs traefik --tail=20
Cause: Let's Encrypt hasn't issued certificates yet
Solutions:
• Wait 5-10 minutes
• Check DNS: nslookup authentik.yourdomain.com
• Check Traefik logs: docker logs traefik
• Verify ports 80/443 are forwarded correctly
Cause: Backend service isn't running
Solutions:
• Check services: docker compose ps
• Restart: docker compose restart
• Check logs: docker compose logs
Cause: SSH or network issue
Solutions:
• Verify server is on: check with monitor/keyboard
• Check IP address: run ip addr on server
• Check firewall: sudo ufw status
• Ensure SSH is allowed: sudo ufw allow ssh
Your Zero-Trust SSO Gateway is running!
You now have enterprise-grade identity management in your home lab!