Complete documentation suite for KiteStacks covering all 11 services across 2-host active-active architecture. Includes beginner track (with AI, 8 files) and advanced track (without AI, 7 files) with time estimates, real troubleshooting cases, and command-by-command explanations. Updates certifications roadmap to reflect July 7 2026 A+ Core 2 exam goal. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
6.9 KiB
Step 4 — Core Services: Portal, Forgejo, and Authentik
Track: With AI (Beginner)
Time for this step: 3–5 hours
These three services form the foundation of KiteStacks:
- Portal — the homepage that links to everything
- Forgejo — stores all your code and configurations in Git
- Authentik — handles all logins for every service (SSO)
Set these up first. Everything else depends on them.
How Docker Compose Files Work
Every service in this homelab has its own folder with a docker-compose.yml file.
That file describes the service: what image to use, what environment variables to set,
what folders to use for data, and what network to join.
You will create these files using nano (a simple text editor in the terminal).
Ask your AI: "Can you explain what each section of a docker-compose.yml file does: services, image, container_name, restart, environment, volumes, networks?"
Service 1 — The Portal (Homepage)
The portal is your home page at www.yourdomain.com. It shows links to all your
services and displays live system stats.
mkdir -p ~/kitestacks-live/docker/kitestacks-portal/public
cd ~/kitestacks-live/docker/kitestacks-portal
Create docker-compose.yml:
services:
homepage:
image: nginx:alpine
container_name: homepage
restart: unless-stopped
volumes:
- ./public:/usr/share/nginx/html:ro
- ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
networks:
- kitestacks
networks:
kitestacks:
external: true
Create a basic nginx.conf:
server {
listen 3000;
root /usr/share/nginx/html;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
}
Create a basic public/index.html to test:
<!DOCTYPE html>
<html>
<head><title>KiteStacks</title></head>
<body>
<h1>KiteStacks is live!</h1>
</body>
</html>
Start it:
docker compose up -d
docker ps
Visit www.yourdomain.com in a browser. You should see your page.
If it works, you have confirmed the tunnel is routing correctly.
Ask your AI: "I want to build a proper homepage for my homelab. It should have a dark cyberpunk theme with cards for each of my services. Can you help me write the HTML?"
Work with your AI to build the portal you want. The KiteStacks portal source is in
~/kitestacks-homelab/apps/kitestacks-portal/ as reference.
Service 2 — Forgejo (Git)
Forgejo stores all your code. You will push your homelab configs to it so everything is version-controlled and you never lose your work.
First, set up the shared PostgreSQL database (Forgejo will use this):
mkdir -p ~/kitestacks-live/docker/postgres
cd ~/kitestacks-live/docker/postgres
Create .env:
POSTGRES_USER=authentik
POSTGRES_PASSWORD=choose-a-strong-password-here
POSTGRES_DB=authentik
Create docker-compose.yml:
services:
authentik-postgres:
image: postgres:16-alpine
container_name: authentik-postgres
restart: unless-stopped
env_file: .env
volumes:
- ./data:/var/lib/postgresql/data
networks:
- kitestacks
networks:
kitestacks:
external: true
docker compose up -d
Now create the Forgejo service:
mkdir -p ~/kitestacks-live/docker/forgejo
cd ~/kitestacks-live/docker/forgejo
Create .env:
FORGEJO_DB_TYPE=postgres
FORGEJO_DB_HOST=authentik-postgres:5432
FORGEJO_DB_NAME=forgejo
FORGEJO_DB_USER=forgejo
FORGEJO_DB_PASSWD=choose-a-strong-password-here
FORGEJO_DOMAIN=gitforge.yourdomain.com
FORGEJO_SSH_DOMAIN=gitforge.yourdomain.com
FORGEJO_ROOT_URL=https://gitforge.yourdomain.com
Create docker-compose.yml:
services:
forgejo:
image: codeberg.org/forgejo/forgejo:latest
container_name: forgejo
restart: unless-stopped
env_file: .env
volumes:
- ./data:/data
networks:
- kitestacks
networks:
kitestacks:
external: true
docker compose up -d
docker logs forgejo -f
Wait for it to finish starting (about 30 seconds), then visit gitforge.yourdomain.com.
You will see a Forgejo setup page — follow the on-screen instructions to create your admin account.
Ask your AI: "How do I create a repository on Forgejo and push my local files to it?"
Service 3 — Authentik (Single Sign-On)
Authentik is the most complex service to set up, but it is worth it — once done, you log in once and every other service recognizes you automatically.
First, set up Redis (Authentik needs this for session management):
mkdir -p ~/kitestacks-live/docker/redis
cd ~/kitestacks-live/docker/redis
Create docker-compose.yml:
services:
authentik-redis:
image: redis:alpine
container_name: authentik-redis
restart: unless-stopped
networks:
- kitestacks
networks:
kitestacks:
external: true
docker compose up -d
Now create Authentik:
mkdir -p ~/kitestacks-live/docker/authentik
cd ~/kitestacks-live/docker/authentik
Generate a secret key (run this and save the output):
openssl rand -base64 60 | tr -d '\n'
Create .env (replace the values):
PG_PASS=same-postgres-password-from-above
AUTHENTIK_SECRET_KEY=paste-the-generated-key-here
AUTHENTIK_BOOTSTRAP_EMAIL=your@email.com
AUTHENTIK_BOOTSTRAP_PASSWORD=choose-a-strong-admin-password
AUTHENTIK_POSTGRESQL__HOST=authentik-postgres
AUTHENTIK_POSTGRESQL__USER=authentik
AUTHENTIK_POSTGRESQL__NAME=authentik
AUTHENTIK_POSTGRESQL__PASSWORD=same-postgres-password-from-above
AUTHENTIK_REDIS__HOST=authentik-redis
Create docker-compose.yml:
services:
authentik:
image: ghcr.io/goauthentik/server:latest
container_name: authentik
restart: unless-stopped
command: server
env_file: .env
networks:
- kitestacks
authentik-worker:
image: ghcr.io/goauthentik/server:latest
container_name: authentik-worker
restart: unless-stopped
command: worker
env_file: .env
networks:
- kitestacks
networks:
kitestacks:
external: true
docker compose up -d
Authentik takes about 2 minutes to start on first run (it sets up the database). Watch the logs:
docker logs authentik -f
When you see "Starting authentik server" it is ready.
Visit auth.yourdomain.com and log in with the bootstrap email and password you set.
Ask your AI: "I have Authentik running. How do I create an OAuth2 provider for Grafana so it can use SSO? Walk me through the steps in the Authentik admin panel."
Use the same process (with your AI's help) to create OAuth2 providers for each service as you add them in the next steps.
Checkpoint
Before moving to Step 5:
- Portal is live at
www.yourdomain.com - Forgejo is live at
gitforge.yourdomain.comwith your admin account created - Authentik is live at
auth.yourdomain.comand you can log in - You can see all three containers in
docker ps