Skip to content
digitaleraluhutPublic

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

Homelab: Personal Infrastructure as Code

Part of digitaleraluhut — the platform layer. Provides the k3s cluster that homelab-apps deploys onto, and the networking that exposes local-ai endpoints to the internet.

Type-safe Kubernetes homelab with Pulumi. Zero inbound ports via Cloudflare Tunnel. Everything version-controlled.

Quick Start

# Preview infrastructure changes
npm run preview

# Deploy
npm run up

# Tear down
npm run destroy

# Type-check code
npm run type-check

# Lint code style
npm run lint

Architecture

Internet → Cloudflare Edge → Encrypted Tunnel → k3s Cluster → Your Apps
(HTTPS)   (TLS, DDoS)       (outbound-only)    (no ports)

Key Components:

  • Cloudflare Tunnel: Secure internet exposure without open ports
  • cert-manager: Automatic TLS certificates (Let's Encrypt)
  • Traefik Gateway API: HTTP(S) routing and load balancing with ForwardAuth
  • External Secrets: Sync secrets from Pulumi ESC/Vault/AWS

Project Structure

homelab/                          ← Pulumi project (root)
├── src/index.ts                 ← Orchestrator entry point
├── Pulumi.yaml                  ← Pulumi config
├── package.json                 ← Dependencies & scripts
│
└── packages/                    ← Reusable libraries
    ├── core/
    │   ├── components/          ← ExposedWebApp, HomelabContext
    │   ├── config/              ← Centralized Pulumi config
    │   └── infrastructure/      ← Cloudflare, cert-manager, ingress, secrets
    │
    ├── stacks/
    │   └── base-infra/          ← Orchestrates core infrastructure
    │
    └── demo-apps/
        └── hello-world/         ← Demo / smoke-test application (extensible pattern)

Key Features

  • 🔒 Secure: No inbound ports, outbound-only tunnel
  • 📝 Type-Safe: Pulumi + TypeScript instead of YAML
  • 🧩 Modular: Reusable components and stacks
  • 📦 Infrastructure-as-Code: Git-versioned, reproducible
  • 🚀 Production-Ready: Tested patterns (OAuth, storage, secrets)

Deploying Personal Apps

Recommended: homelab-apps monorepo pattern

For real personal apps (e.g. LobeHub, Vaultwarden, Gitea) use the dedicated digitaleraluhut/homelab-apps monorepo.

Why a separate repo?

  • One repo → one secret set (KUBECONFIG, PULUMI_ACCESS_TOKEN, Tailscale OAuth)
  • No need to fork upstream projects just to carry deployment code
  • Clean separation: this repo is the framework and contains demo/smoke-test apps, homelab-apps is your real apps

Structure:

homelab-apps/
├── apps/
│   └── lobehub/          ← each app is a Pulumi project
│       ├── Pulumi.yaml
│       ├── Pulumi.dev.yaml
│       └── src/index.ts  ← uses @mrsimpson/homelab-core-components
└── .github/workflows/
    └── deploy-lobehub.yml  ← calls deploy-to-cluster.yml@main (this repo)

Bootstrap in one command:

# from this repo
./scripts/setup-homelab-apps.sh

Adding a new app: Use the deploy-homelab-app skill in homelab-apps/skills/ — load it in your AI agent and say "add a new app to homelab-apps". It covers workspace scaffolding, RBAC setup, CI workflow, and security considerations.

Demo apps (in this repo)

The packages/demo-apps/ folder contains lightweight demo / smoke-test framework examples:

mkdir -p packages/demo-apps/my-app/src
# Create: package.json, tsconfig.json, src/index.ts
npm install

Use @mrsimpson/homelab-core-components:

import { createHomelabContextFromStack } from "@mrsimpson/homelab-core-components";

const homelab = createHomelabContextFromStack(homelabStack);
homelab.createExposedWebApp("my-app", { ... });

Adding Infrastructure

Create new stack in packages/stacks/my-stack/ following the base-infra pattern.

Or extend packages/core/infrastructure/ for reusable modules.

Documentation

Security & Secrets

How secrets are stored

What Mechanism Tracked in git?
Pulumi stack config (passwords, tokens, keys) Pulumi Cloud AES-256-GCM encryption (secure: values) No — Pulumi.*.yaml is gitignored
Infrastructure secrets at rest (SOPS) Age-encrypted homelab-config/pulumi-config.enc.yaml Yes — ciphertext only
OAuth2-proxy user email lists Pulumi config (oauth2-proxy:usersEmails, oauth2-proxy:developersEmails) No — stored in Pulumi Cloud
Age private key Never committed — lives in ~/.sops-backup/ No — *.age is gitignored

Local setup on a new machine

# 1. Install dependencies
./homelab-config/install-dependencies.sh   # pulumi, sops, age, kubectl, helm

# 2. Authenticate with Pulumi Cloud (restores all encrypted stack config)
pulumi login
pulumi stack select dev

# 3. Restore the Age key for SOPS decryption
#    Standard location: ~/.config/sops/age/keys.txt
#    See: https://github.com/getsops/sops?tab=readme-ov-file#22encrypting-using-age
mkdir -p ~/.config/sops/age
cp /path/to/your/backup/pulumi-homelab.age ~/.config/sops/age/keys.txt

# 4. Restore encrypted infrastructure config
./homelab-config/restore-config.sh

# 5. Set user email lists (first time only — already in Pulumi Cloud on subsequent machines)
pulumi config set --secret oauth2-proxy:usersEmails '["you@example.com"]' --stack dev
pulumi config set --secret oauth2-proxy:developersEmails '["you@example.com"]' --stack dev

Authentication Systems

This homelab provides two independent authentication systems:

OAuth2-Proxy (GitHub OAuth)

Protect routes with GitHub authentication for:

  • External developers and contributors
  • Public/semi-public applications
  • Email-based allowlists

See: OAuth2-Proxy Guide

Authelia (Local & LDAP)

Protect routes with local user accounts for:

  • Internal tools and dashboards
  • Service accounts and automation
  • MFA and advanced policies

Note: Routes use one or the other, never both. Choose based on your needs.

Quick Reference: Protecting a Route

With OAuth2-Proxy (GitHub users):

filters:
  - type: ExtensionRef
    extensionRef:
      group: traefik.io
      kind: Middleware
      name: forwardauth-oauth2-users
      namespace: oauth2-proxy  # Note: different namespace!

With Authelia (Local accounts):

filters:
  - type: ExtensionRef
    extensionRef:
      group: traefik.io
      kind: Middleware
      name: forwardauth-authelia
      namespace: traefik-system

Requirements

  • Node.js >=24.0.0
  • k3s cluster (see bootstrap/install-k3s.sh)
  • Cloudflare account (for tunnel and DNS)
  • Pulumi account (for state management)

License

MIT

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages