# 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 KiteStacks

KiteStacks is live!

``` 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)