chore: initial infrastructure scaffold

Kustomize base + overlays for the full Sunbeam k3s stack:
- base/mesh      — Linkerd edge (crds + control-plane + viz)
- base/ingress   — custom Pingora edge proxy
- base/ory       — Kratos 0.60.1 + Hydra 0.60.1 + login-ui
- base/data      — CloudNativePG 0.27.1, Valkey 8, OpenSearch 2
- base/storage   — SeaweedFS master + volume + filer (S3 on :8333)
- base/lasuite   — Hive sync daemon + La Suite app placeholders
- base/media     — LiveKit livekit-server 1.9.0
- base/devtools  — Gitea 12.5.0 (external PG + Valkey)
overlays/local   — sslip.io domain, mkcert TLS, Lima hostPort
overlays/production — stub (TODOs for sunbeam.pt values)
scripts/         — local-up/down/certs/urls helpers
justfile         — up / down / certs / urls targets
This commit is contained in:
2026-02-28 13:42:27 +00:00
commit 5d9bd7b067
51 changed files with 2647 additions and 0 deletions

46
scripts/local-certs.sh Executable file
View File

@@ -0,0 +1,46 @@
#!/usr/bin/env bash
# Generate a mkcert wildcard TLS cert for the current Lima VM IP.
# Output: secrets/local/tls.crt + secrets/local/tls.key
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
SECRETS_DIR="$REPO_ROOT/secrets/local"
echo "==> Getting Lima VM IP..."
LIMA_IP=$(limactl shell sunbeam hostname -I | awk '{print $1}')
if [[ -z "$LIMA_IP" ]]; then
echo "ERROR: Could not determine Lima VM IP. Is the 'sunbeam' VM running?" >&2
exit 1
fi
DOMAIN="*.${LIMA_IP}.sslip.io"
echo "==> Generating mkcert cert for: $DOMAIN"
mkdir -p "$SECRETS_DIR"
cd "$SECRETS_DIR"
mkcert -install
mkcert "$DOMAIN"
# mkcert names the output files based on the domain; normalise to tls.crt / tls.key
CERT_FILE="_wildcard.${LIMA_IP}.sslip.io.pem"
KEY_FILE="_wildcard.${LIMA_IP}.sslip.io-key.pem"
if [[ -f "$CERT_FILE" ]]; then
mv "$CERT_FILE" tls.crt
mv "$KEY_FILE" tls.key
echo "==> Cert written to secrets/local/tls.crt and secrets/local/tls.key"
else
echo "ERROR: Expected cert file '$CERT_FILE' not found." >&2
exit 1
fi
echo "==> Domain: $DOMAIN"
echo "==> Lima IP: $LIMA_IP"
echo ""
echo "Next: run scripts/local-up.sh or manually apply the TLS secret:"
echo " kubectl create secret tls pingora-tls -n ingress \\"
echo " --cert=secrets/local/tls.crt \\"
echo " --key=secrets/local/tls.key \\"
echo " --dry-run=client -o yaml | kubectl apply -f -"

33
scripts/local-down.sh Executable file
View File

@@ -0,0 +1,33 @@
#!/usr/bin/env bash
# Stop the Sunbeam Lima VM (preserves disk by default).
set -euo pipefail
DELETE=false
HARD=false
for arg in "$@"; do
case $arg in
--delete) DELETE=true ;;
--hard) HARD=true ;;
*)
echo "Usage: $0 [--hard] [--delete]" >&2
exit 1
;;
esac
done
if $HARD; then
echo "==> Force-stopping Lima VM 'sunbeam'..."
limactl stop --force sunbeam
else
echo "==> Stopping Lima VM 'sunbeam' (graceful)..."
limactl stop sunbeam
fi
if $DELETE; then
echo "==> Deleting Lima VM 'sunbeam' (disk will be lost)..."
limactl delete sunbeam
echo "==> VM deleted."
else
echo "==> VM stopped. Disk preserved. Run scripts/local-up.sh to restart."
fi

122
scripts/local-up.sh Executable file
View File

@@ -0,0 +1,122 @@
#!/usr/bin/env bash
# Start the Sunbeam local dev stack.
# Idempotent: safe to run multiple times.
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
# ---------------------------------------------------------------------------
# 1. Check prerequisites
# ---------------------------------------------------------------------------
echo "==> Checking prerequisites..."
for tool in limactl mkcert kubectl helm linkerd; do
if ! command -v "$tool" &>/dev/null; then
echo "ERROR: '$tool' not found. Install with: brew install $tool" >&2
exit 1
fi
done
echo " OK"
# ---------------------------------------------------------------------------
# 2. Start Lima VM (skip if already running)
# ---------------------------------------------------------------------------
LIMA_STATUS=$(limactl list --json 2>/dev/null | \
python3 -c "import sys,json; vms=[v for v in json.load(sys.stdin) if v['name']=='sunbeam']; print(vms[0]['status'] if vms else 'none')" 2>/dev/null || echo "none")
if [[ "$LIMA_STATUS" == "Running" ]]; then
echo "==> Lima VM 'sunbeam' already running."
elif [[ "$LIMA_STATUS" == "Stopped" ]]; then
echo "==> Starting existing Lima VM 'sunbeam'..."
limactl start sunbeam
else
echo "==> Creating Lima VM 'sunbeam' (k3s, 6 CPU / 12 GB / 60 GB)..."
limactl start \
--name=sunbeam \
template://k3s \
--memory=12 \
--cpus=6 \
--disk=60 \
--vm-type=vz \
--mount-type=virtiofs
fi
# ---------------------------------------------------------------------------
# 3. Export kubeconfig
# ---------------------------------------------------------------------------
echo "==> Exporting kubeconfig..."
mkdir -p ~/.kube
limactl shell sunbeam kubectl config view --raw > ~/.kube/sunbeam.yaml
export KUBECONFIG=~/.kube/sunbeam.yaml
echo " KUBECONFIG=$KUBECONFIG"
# ---------------------------------------------------------------------------
# 4. Install Linkerd CRDs + control plane
# ---------------------------------------------------------------------------
echo "==> Adding Linkerd Helm repo..."
helm repo add linkerd https://helm.linkerd.io/stable --force-update
helm repo update linkerd
echo "==> Installing Linkerd CRDs..."
helm upgrade --install linkerd-crds linkerd/linkerd-crds \
-n mesh --create-namespace --wait
echo "==> Installing Linkerd control plane..."
helm upgrade --install linkerd-control-plane linkerd/linkerd-control-plane \
-n mesh \
--set-file identityTrustAnchorsPEM="$(linkerd identity trust-anchors 2>/dev/null || echo '')" \
--wait || {
echo "==> Bootstrapping Linkerd identity (first install)..."
linkerd install --crds | kubectl apply -f -
linkerd install | kubectl apply -f -
linkerd check
}
# ---------------------------------------------------------------------------
# 5. Generate mkcert wildcard cert
# ---------------------------------------------------------------------------
echo "==> Generating TLS cert..."
bash "$SCRIPT_DIR/local-certs.sh"
LIMA_IP=$(limactl shell sunbeam hostname -I | awk '{print $1}')
DOMAIN="${LIMA_IP}.sslip.io"
# ---------------------------------------------------------------------------
# 6. Create TLS Secret in ingress namespace
# ---------------------------------------------------------------------------
echo "==> Applying TLS Secret to ingress namespace..."
kubectl create namespace ingress --dry-run=client -o yaml | kubectl apply -f -
kubectl create secret tls pingora-tls \
--cert="$REPO_ROOT/secrets/local/tls.crt" \
--key="$REPO_ROOT/secrets/local/tls.key" \
-n ingress \
--dry-run=client -o yaml | kubectl apply -f -
# ---------------------------------------------------------------------------
# 7. Substitute domain and apply manifests
# ---------------------------------------------------------------------------
echo "==> Applying manifests (domain: $DOMAIN)..."
# Substitute DOMAIN_SUFFIX placeholder before piping to kubectl
kubectl kustomize "$REPO_ROOT/overlays/local" --enable-helm | \
sed "s/DOMAIN_SUFFIX/${DOMAIN}/g" | \
kubectl apply -f -
# ---------------------------------------------------------------------------
# 8. Wait for core components
# ---------------------------------------------------------------------------
echo "==> Waiting for PostgreSQL cluster..."
kubectl wait --for=condition=Ready cluster/postgres -n data --timeout=180s || true
echo "==> Waiting for Redis..."
kubectl rollout status deployment/redis -n data --timeout=120s || true
echo "==> Waiting for Kratos..."
kubectl rollout status deployment/kratos -n ory --timeout=120s || true
echo "==> Waiting for Hydra..."
kubectl rollout status deployment/hydra -n ory --timeout=120s || true
# ---------------------------------------------------------------------------
# 9. Print URLs
# ---------------------------------------------------------------------------
bash "$SCRIPT_DIR/local-urls.sh"

29
scripts/local-urls.sh Executable file
View File

@@ -0,0 +1,29 @@
#!/usr/bin/env bash
# Print all local service URLs for the current Lima VM IP.
set -euo pipefail
echo "==> Getting Lima VM IP..."
LIMA_IP=$(limactl shell sunbeam hostname -I | awk '{print $1}')
if [[ -z "$LIMA_IP" ]]; then
echo "ERROR: Could not determine Lima VM IP. Is the 'sunbeam' VM running?" >&2
exit 1
fi
BASE="${LIMA_IP}.sslip.io"
echo ""
echo "Sunbeam local URLs (Lima IP: $LIMA_IP)"
echo "============================================"
echo " Docs: https://docs.${BASE}"
echo " Meet: https://meet.${BASE}"
echo " Drive: https://drive.${BASE}"
echo " Mail: https://mail.${BASE}"
echo " Chat: https://chat.${BASE}"
echo " People: https://people.${BASE}"
echo " Source: https://src.${BASE}"
echo " Auth: https://auth.${BASE}"
echo " S3: https://s3.${BASE}"
echo ""
echo " Linkerd viz: kubectl port-forward -n mesh svc/linkerd-viz 8084:8084"
echo " then open http://localhost:8084"
echo ""