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>
298 lines
6.9 KiB
Markdown
298 lines
6.9 KiB
Markdown
# 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.
|
||
|
||
```bash
|
||
mkdir -p ~/kitestacks-live/docker/kitestacks-portal/public
|
||
cd ~/kitestacks-live/docker/kitestacks-portal
|
||
```
|
||
|
||
Create `docker-compose.yml`:
|
||
```yaml
|
||
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`:
|
||
```nginx
|
||
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:
|
||
```html
|
||
<!DOCTYPE html>
|
||
<html>
|
||
<head><title>KiteStacks</title></head>
|
||
<body>
|
||
<h1>KiteStacks is live!</h1>
|
||
</body>
|
||
</html>
|
||
```
|
||
|
||
Start it:
|
||
```bash
|
||
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):
|
||
|
||
```bash
|
||
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`:
|
||
```yaml
|
||
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
|
||
```
|
||
|
||
```bash
|
||
docker compose up -d
|
||
```
|
||
|
||
Now create the Forgejo service:
|
||
```bash
|
||
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`:
|
||
```yaml
|
||
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
|
||
```
|
||
|
||
```bash
|
||
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):
|
||
```bash
|
||
mkdir -p ~/kitestacks-live/docker/redis
|
||
cd ~/kitestacks-live/docker/redis
|
||
```
|
||
|
||
Create `docker-compose.yml`:
|
||
```yaml
|
||
services:
|
||
authentik-redis:
|
||
image: redis:alpine
|
||
container_name: authentik-redis
|
||
restart: unless-stopped
|
||
networks:
|
||
- kitestacks
|
||
|
||
networks:
|
||
kitestacks:
|
||
external: true
|
||
```
|
||
|
||
```bash
|
||
docker compose up -d
|
||
```
|
||
|
||
Now create Authentik:
|
||
```bash
|
||
mkdir -p ~/kitestacks-live/docker/authentik
|
||
cd ~/kitestacks-live/docker/authentik
|
||
```
|
||
|
||
Generate a secret key (run this and save the output):
|
||
```bash
|
||
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`:
|
||
```yaml
|
||
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
|
||
```
|
||
|
||
```bash
|
||
docker compose up -d
|
||
```
|
||
|
||
Authentik takes about 2 minutes to start on first run (it sets up the database).
|
||
Watch the logs:
|
||
```bash
|
||
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.com` with your admin account created
|
||
- [ ] Authentik is live at `auth.yourdomain.com` and you can log in
|
||
- [ ] You can see all three containers in `docker ps`
|
||
|
||
---
|
||
|
||
**Next:** [Step 5 — All Remaining Services](05-all-services.md)
|