docs: migrate homelab docs from *.lthn.lan to *.lthn.sh
- Rewrite handover doc for lthn.sh with real TLS cert, proper DNS - Add UniFi gateway DNS record reference (16 A records, no wildcards) - Update OpenBrain usage guide to lthn.sh URLs - Split services: *.lthn.sh (lab) vs *.infra.lthn.sh (admin tools) - GoGetSSL wildcard cert covers lthn.sh + *.lthn.sh + *.infra.lthn.sh Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
parent
7fe48a6268
commit
e000e31567
3 changed files with 286 additions and 79 deletions
|
|
@ -1,4 +1,4 @@
|
|||
# lthn.lan Homelab Setup — Handover to Charon
|
||||
# lthn.sh Homelab Setup — Handover to Charon
|
||||
|
||||
> **For:** Charon (Linux homelab agent, 10.69.69.165)
|
||||
> **From:** Virgil (macOS)
|
||||
|
|
@ -6,42 +6,121 @@
|
|||
|
||||
## Goal
|
||||
|
||||
Stand up the Host UK Laravel app on the Linux homelab as `lthn.lan` — a private dev/ops hub away from production. This joins the existing `.lan` service mesh (ollama.lthn.lan, qdrant.lthn.lan, eaas.lthn.lan).
|
||||
Stand up the Host UK Laravel app on the Linux homelab as `hub.lthn.sh` — a private dev/ops hub away from production. This joins the existing homelab service mesh (ollama, qdrant, eaas) which is migrating from `*.lthn.lan` to `*.lthn.sh`.
|
||||
|
||||
## What lthn.lan Is
|
||||
## Domain Strategy
|
||||
|
||||
The personal admin hub — issues, dashboards, agent coordination. NOT production-facing. Runs the same codebase as lthn.ai but configured for homelab use with access to local AI services.
|
||||
Clean separation between production and homelab:
|
||||
|
||||
| Zone | Purpose | Visibility |
|
||||
|------|---------|------------|
|
||||
| `*.lthn.sh` | Homelab — ML, agents, lab services | Internal only |
|
||||
| `*.infra.lthn.sh` | Homelab — admin/infra tools | Internal only |
|
||||
| `lthn.ai` | Production — portal, forge, API | Public |
|
||||
| `lthn.io` | Production — landing, service mesh | Public |
|
||||
| `leth.in` | Internal prod DNS (CoreDNS on noc) | Internal |
|
||||
| `lthn.host` | Shared/collab — demos, community | Public when needed |
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
Mac (snider) ──hosts file──▶ lthn.lan (10.69.69.165)
|
||||
├── Traefik (TLS termination, self-signed)
|
||||
├── Laravel app (FrankenPHP/Octane, port 80)
|
||||
├── MariaDB 11 (port 3306)
|
||||
└── Redis/Dragonfly (port 6379)
|
||||
UniFi Gateway ──DNS──▶ 10.69.69.165 (Linux homelab)
|
||||
├── Traefik (TLS via real cert, *.lthn.sh + *.infra.lthn.sh)
|
||||
├── Laravel hub (FrankenPHP/Octane, port 80)
|
||||
├── MariaDB 11 (port 3306)
|
||||
└── Redis/Dragonfly (port 6379)
|
||||
|
||||
Already running on 10.69.69.165:
|
||||
ollama.lthn.lan → Ollama (embeddings, LEM inference)
|
||||
qdrant.lthn.lan → Qdrant (vector search)
|
||||
eaas.lthn.lan → EaaS scoring API v0.2.0
|
||||
ollama → Ollama (embeddings, LEM inference)
|
||||
qdrant → Qdrant (vector search)
|
||||
eaas → EaaS scoring API v0.2.0
|
||||
```
|
||||
|
||||
## Prerequisites
|
||||
**Hardware**: Ryzen 9, 128GB RAM, RX 7800 XT (AMD ROCm GPU)
|
||||
|
||||
These should already exist on the machine:
|
||||
## DNS Records — UniFi Gateway
|
||||
|
||||
- Docker (or Podman) with Traefik v3.6+ running
|
||||
- External Docker network `proxy` for Traefik
|
||||
- SSH key for forge.lthn.ai (port 2223) — needed for `composer install`
|
||||
No wildcard support on UniFi — each service needs an individual A record.
|
||||
All point to `10.69.69.165`.
|
||||
|
||||
If Traefik isn't set up yet, see the existing `.lan` services for the pattern.
|
||||
### Lab services (`*.lthn.sh`)
|
||||
|
||||
| Hostname | Service |
|
||||
|----------|---------|
|
||||
| `hub.lthn.sh` | Laravel admin hub |
|
||||
| `lab.lthn.sh` | LEM Lab |
|
||||
| `ollama.lthn.sh` | Ollama inference + embeddings |
|
||||
| `qdrant.lthn.sh` | Qdrant vector search |
|
||||
| `eaas.lthn.sh` | EaaS scoring API |
|
||||
|
||||
### Infrastructure (`*.infra.lthn.sh`)
|
||||
|
||||
| Hostname | Service |
|
||||
|----------|---------|
|
||||
| `traefik.infra.lthn.sh` | Traefik dashboard |
|
||||
| `grafana.infra.lthn.sh` | Grafana |
|
||||
| `prometheus.infra.lthn.sh` | Prometheus |
|
||||
| `influx.infra.lthn.sh` | InfluxDB |
|
||||
| `auth.infra.lthn.sh` | Authentik SSO |
|
||||
| `portainer.infra.lthn.sh` | Portainer |
|
||||
| `phpmyadmin.infra.lthn.sh` | phpMyAdmin |
|
||||
| `maria.infra.lthn.sh` | MariaDB admin |
|
||||
| `postgres.infra.lthn.sh` | PostgreSQL admin |
|
||||
| `redis.infra.lthn.sh` | Redis admin |
|
||||
|
||||
## TLS Certificate
|
||||
|
||||
A real GoGetSSL cert covers all homelab domains. No self-signed certs, no TLS skip logic.
|
||||
|
||||
**SANs**: `lthn.sh`, `*.lthn.sh`, `*.infra.lthn.sh`
|
||||
**Validity**: 3 Mar 2026 → 1 Jun 2026
|
||||
|
||||
### Deploy the cert to Traefik
|
||||
|
||||
Copy the cert + key to the homelab (from snider's Mac):
|
||||
|
||||
```bash
|
||||
# From Mac
|
||||
scp -P 4819 ~/Downloads/fullchain_lthn.sh.crt root@10.69.69.165:/opt/traefik/certs/lthn.sh.crt
|
||||
scp -P 4819 ~/Downloads/lthn.sh.key root@10.69.69.165:/opt/traefik/certs/lthn.sh.key
|
||||
```
|
||||
|
||||
Create a Traefik dynamic config file at `/opt/traefik/dynamic/lthn-sh-cert.yml`:
|
||||
|
||||
```yaml
|
||||
tls:
|
||||
certificates:
|
||||
- certFile: /certs/lthn.sh.crt
|
||||
keyFile: /certs/lthn.sh.key
|
||||
stores:
|
||||
default:
|
||||
defaultCertificate:
|
||||
certFile: /certs/lthn.sh.crt
|
||||
keyFile: /certs/lthn.sh.key
|
||||
```
|
||||
|
||||
Ensure Traefik's compose mounts the certs directory:
|
||||
|
||||
```yaml
|
||||
volumes:
|
||||
- /opt/traefik/certs:/certs:ro
|
||||
- /opt/traefik/dynamic:/etc/traefik/dynamic:ro
|
||||
```
|
||||
|
||||
And the static config watches for file provider changes:
|
||||
|
||||
```yaml
|
||||
providers:
|
||||
file:
|
||||
directory: /etc/traefik/dynamic
|
||||
watch: true
|
||||
```
|
||||
|
||||
## Step 1: Clone the Repo
|
||||
|
||||
```bash
|
||||
mkdir -p /opt/services/lthn-lan
|
||||
cd /opt/services/lthn-lan
|
||||
mkdir -p /opt/services/lthn-sh
|
||||
cd /opt/services/lthn-sh
|
||||
|
||||
# Clone via forge SSH
|
||||
git clone ssh://git@forge.lthn.ai:2223/lthn/hostuk.git app
|
||||
|
|
@ -59,7 +138,7 @@ Host forge.lthn.ai
|
|||
|
||||
## Step 2: Create docker-compose.yml
|
||||
|
||||
Create `/opt/services/lthn-lan/docker-compose.yml`:
|
||||
Create `/opt/services/lthn-sh/docker-compose.yml`:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
|
|
@ -67,31 +146,38 @@ services:
|
|||
build:
|
||||
context: ./app
|
||||
dockerfile: Dockerfile
|
||||
container_name: lthn-lan
|
||||
container_name: lthn-sh-hub
|
||||
restart: unless-stopped
|
||||
env_file: .env
|
||||
volumes:
|
||||
- app_storage:/app/storage/logs
|
||||
networks:
|
||||
- proxy
|
||||
- lthn-lan
|
||||
- lthn-sh
|
||||
depends_on:
|
||||
mariadb:
|
||||
condition: service_healthy
|
||||
labels:
|
||||
traefik.enable: "true"
|
||||
traefik.http.routers.lthn-sh-hub.rule: "Host(`hub.lthn.sh`)"
|
||||
traefik.http.routers.lthn-sh-hub.entrypoints: websecure
|
||||
traefik.http.routers.lthn-sh-hub.tls: "true"
|
||||
traefik.http.services.lthn-sh-hub.loadbalancer.server.port: "80"
|
||||
traefik.docker.network: proxy
|
||||
|
||||
mariadb:
|
||||
image: mariadb:11
|
||||
container_name: lthn-lan-db
|
||||
container_name: lthn-sh-db
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
MARIADB_ROOT_PASSWORD: "${DB_ROOT_PASSWORD}"
|
||||
MARIADB_DATABASE: lthn_lan
|
||||
MARIADB_USER: lthn_lan
|
||||
MARIADB_DATABASE: lthn_sh
|
||||
MARIADB_USER: lthn_sh
|
||||
MARIADB_PASSWORD: "${DB_PASSWORD}"
|
||||
volumes:
|
||||
- mariadb_data:/var/lib/mysql
|
||||
networks:
|
||||
- lthn-lan
|
||||
- lthn-sh
|
||||
healthcheck:
|
||||
test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
|
||||
interval: 10s
|
||||
|
|
@ -105,34 +191,34 @@ volumes:
|
|||
networks:
|
||||
proxy:
|
||||
external: true
|
||||
lthn-lan:
|
||||
lthn-sh:
|
||||
driver: bridge
|
||||
```
|
||||
|
||||
## Step 3: Create .env
|
||||
|
||||
Create `/opt/services/lthn-lan/.env`:
|
||||
Create `/opt/services/lthn-sh/.env`:
|
||||
|
||||
```bash
|
||||
APP_NAME="LTHN Hub"
|
||||
APP_ENV=local
|
||||
APP_KEY=
|
||||
APP_DEBUG=true
|
||||
APP_URL=https://lthn.lan
|
||||
APP_DOMAIN=lthn.lan
|
||||
APP_URL=https://hub.lthn.sh
|
||||
APP_DOMAIN=lthn.sh
|
||||
|
||||
TRUSTED_PROXIES=*
|
||||
|
||||
DB_CONNECTION=mariadb
|
||||
DB_HOST=lthn-lan-db
|
||||
DB_HOST=lthn-sh-db
|
||||
DB_PORT=3306
|
||||
DB_DATABASE=lthn_lan
|
||||
DB_USERNAME=lthn_lan
|
||||
DB_DATABASE=lthn_sh
|
||||
DB_USERNAME=lthn_sh
|
||||
DB_PASSWORD=changeme-generate-a-real-one
|
||||
DB_ROOT_PASSWORD=changeme-generate-a-real-one
|
||||
|
||||
SESSION_DRIVER=redis
|
||||
SESSION_DOMAIN=.lthn.lan
|
||||
SESSION_DOMAIN=.lthn.sh
|
||||
SESSION_SECURE_COOKIE=true
|
||||
|
||||
REDIS_CLIENT=predis
|
||||
|
|
@ -146,14 +232,14 @@ BROADCAST_CONNECTION=log
|
|||
|
||||
OCTANE_SERVER=frankenphp
|
||||
|
||||
# OpenBrain — connects to existing .lan services
|
||||
BRAIN_OLLAMA_URL=https://ollama.lthn.lan
|
||||
BRAIN_QDRANT_URL=https://qdrant.lthn.lan
|
||||
# OpenBrain — connects to homelab services
|
||||
BRAIN_OLLAMA_URL=https://ollama.lthn.sh
|
||||
BRAIN_QDRANT_URL=https://qdrant.lthn.sh
|
||||
BRAIN_COLLECTION=openbrain
|
||||
BRAIN_EMBEDDING_MODEL=embeddinggemma
|
||||
|
||||
# EaaS scorer
|
||||
EAAS_URL=https://eaas.lthn.lan
|
||||
EAAS_URL=https://eaas.lthn.sh
|
||||
```
|
||||
|
||||
Then generate the app key:
|
||||
|
|
@ -161,26 +247,45 @@ Then generate the app key:
|
|||
docker compose run --rm app php artisan key:generate
|
||||
```
|
||||
|
||||
## Step 4: Traefik Labels
|
||||
## Step 4: Update Existing Services
|
||||
|
||||
Add these labels to the `app` service in docker-compose.yml (or use a Traefik dynamic config file):
|
||||
Existing services (ollama, qdrant, eaas) need their Traefik router rules updated from `*.lthn.lan` to `*.lthn.sh`. For each service, update the Host rule:
|
||||
|
||||
**Docker labels** (if using label-based routing):
|
||||
```yaml
|
||||
labels:
|
||||
traefik.enable: "true"
|
||||
traefik.http.routers.lthn-lan.rule: "Host(`lthn.lan`)"
|
||||
traefik.http.routers.lthn-lan.entrypoints: websecure
|
||||
traefik.http.routers.lthn-lan.tls: "true"
|
||||
traefik.http.services.lthn-lan.loadbalancer.server.port: "80"
|
||||
traefik.docker.network: proxy
|
||||
# Example: ollama
|
||||
traefik.http.routers.ollama.rule: "Host(`ollama.lthn.sh`)"
|
||||
|
||||
# Example: qdrant
|
||||
traefik.http.routers.qdrant.rule: "Host(`qdrant.lthn.sh`)"
|
||||
|
||||
# Example: eaas
|
||||
traefik.http.routers.eaas.rule: "Host(`eaas.lthn.sh`)"
|
||||
```
|
||||
|
||||
Note: For `.lan` domains, Traefik uses self-signed certs (no Let's Encrypt — not a real TLD). The same pattern as ollama.lthn.lan/qdrant.lthn.lan/eaas.lthn.lan.
|
||||
**Or** Traefik dynamic config files (if using file provider):
|
||||
```yaml
|
||||
# /opt/traefik/dynamic/ollama.yml
|
||||
http:
|
||||
routers:
|
||||
ollama:
|
||||
rule: "Host(`ollama.lthn.sh`)"
|
||||
entryPoints: [websecure]
|
||||
tls: {}
|
||||
service: ollama
|
||||
services:
|
||||
ollama:
|
||||
loadBalancer:
|
||||
servers:
|
||||
- url: "http://127.0.0.1:11434"
|
||||
```
|
||||
|
||||
Infrastructure tools follow the same pattern with `*.infra.lthn.sh` hostnames.
|
||||
|
||||
## Step 5: Build and Start
|
||||
|
||||
```bash
|
||||
cd /opt/services/lthn-lan
|
||||
cd /opt/services/lthn-sh
|
||||
|
||||
# Build the image (amd64)
|
||||
docker compose build
|
||||
|
|
@ -209,27 +314,24 @@ docker compose ps
|
|||
# Check migrations ran
|
||||
docker compose logs app | grep -i migration
|
||||
|
||||
# Test HTTP (from the machine itself)
|
||||
curl -sk https://lthn.lan/ | head -20
|
||||
# Test HTTP (from any machine with DNS configured)
|
||||
curl -s https://hub.lthn.sh/ | head -20
|
||||
|
||||
# Check Horizon (queue workers)
|
||||
curl -sk https://lthn.lan/horizon/api/stats
|
||||
curl -s https://hub.lthn.sh/horizon/api/stats
|
||||
|
||||
# Verify TLS is the real cert (not self-signed)
|
||||
echo | openssl s_client -connect 10.69.69.165:443 -servername hub.lthn.sh 2>/dev/null | openssl x509 -noout -subject -dates
|
||||
```
|
||||
|
||||
## Step 7: /etc/hosts on Mac
|
||||
|
||||
Already done by snider:
|
||||
```
|
||||
10.69.69.165 lthn.lan
|
||||
```
|
||||
No `-k` flag needed — the cert is real and trusted.
|
||||
|
||||
## Embedding Model on GPU
|
||||
|
||||
The `embeddinggemma` model on ollama.lthn.lan appears to be running on CPU. It's only ~256MB — should fit easily alongside whatever else is on the RX 7800 XT. Check with:
|
||||
The `embeddinggemma` model on ollama may be running on CPU. It's only ~256MB — should fit easily alongside whatever else is on the RX 7800 XT. Check with:
|
||||
|
||||
```bash
|
||||
# On the Linux machine
|
||||
curl -sk https://ollama.lthn.lan/api/ps
|
||||
curl -s https://ollama.lthn.sh/api/ps
|
||||
```
|
||||
|
||||
If it shows CPU, try pulling it fresh or restarting Ollama — it should auto-detect the GPU.
|
||||
|
|
@ -245,7 +347,7 @@ The app container runs 4 supervised processes:
|
|||
| Scheduler | Cron loop (`schedule:run`) | — |
|
||||
| Redis | In-container cache/session/queue | 6379 |
|
||||
|
||||
Reverb (WebSocket) is optional for lthn.lan — skip it unless needed.
|
||||
Reverb (WebSocket) is optional — skip it unless needed.
|
||||
|
||||
## Key Artisan Commands
|
||||
|
||||
|
|
@ -276,15 +378,28 @@ SSH key must be available inside the container for forge access. The Dockerfile
|
|||
|
||||
## Known Issues
|
||||
|
||||
- **Self-signed TLS**: All `.lan` domains use self-signed certs. The app's `BrainService` auto-detects `.lan` URLs and skips verification. Browsers will warn — just accept.
|
||||
- **Embedding 500s on large sections**: Some very large plan sections (30KB+) cause Ollama to return 500. Not critical — only 4 out of 4,671 sections affected.
|
||||
- **PHP 8.5**: The Dockerfile uses PHP 8.5. Make sure the base image supports it (`dunglas/frankenphp:1-php8.5-trixie`).
|
||||
|
||||
## Migration Checklist — lthn.lan → lthn.sh
|
||||
|
||||
When switching existing services from the old `*.lthn.lan` naming:
|
||||
|
||||
- [ ] Deploy cert + key to `/opt/traefik/certs/`
|
||||
- [ ] Create `lthn-sh-cert.yml` dynamic config
|
||||
- [ ] Update Traefik router rules (Host matchers) for all services
|
||||
- [ ] Configure UniFi gateway DNS (all A records → 10.69.69.165)
|
||||
- [ ] Test from Mac: `curl https://hub.lthn.sh/`
|
||||
- [ ] Remove old `/etc/hosts` entries for `*.lthn.lan`
|
||||
- [ ] Update `php-agentic/config.php` defaults to `*.lthn.sh`
|
||||
- [ ] Update `Boot.php` — `verifySsl` can be `true` always (real certs)
|
||||
|
||||
## Future: Satellite Services
|
||||
|
||||
Once lthn.lan is stable, the plan is to add Website/Service satellites:
|
||||
- `eaas.lthn.ai` → Ethics scorer frontage
|
||||
- `models.lthn.ai` → Model data + HuggingFace info
|
||||
- Each feature (LEM.Lab etc) → its own subdomain via Website/Service pattern
|
||||
Once hub.lthn.sh is stable, the plan is to add Website/Service satellites:
|
||||
- `eaas.lthn.ai` → Ethics scorer frontage (public)
|
||||
- `models.lthn.ai` → Model data + HuggingFace info (public)
|
||||
- `lab.lthn.sh` → LEM Lab (internal)
|
||||
- Each feature gets its own subdomain via Website/Service pattern
|
||||
|
||||
These are just additional `Boot.php` modules with domain patterns — the multi-tenant modular monolith handles everything from one codebase.
|
||||
|
|
|
|||
|
|
@ -25,12 +25,14 @@ Agent ──recall()────▶ BrainService
|
|||
|
||||
| Service | URL | What |
|
||||
|---------|-----|------|
|
||||
| Ollama | `https://ollama.lthn.lan` | Embedding model (`embeddinggemma`, 768 dimensions) |
|
||||
| Qdrant | `https://qdrant.lthn.lan` | Vector storage + cosine similarity search |
|
||||
| MariaDB | `lthn-lan-db:3306` | `brain_memories` table (workspace-scoped) |
|
||||
| Laravel | `https://lthn.lan` | BrainService, artisan commands, MCP tools |
|
||||
| Ollama | `https://ollama.lthn.sh` | Embedding model (`embeddinggemma`, 768 dimensions) |
|
||||
| Qdrant | `https://qdrant.lthn.sh` | Vector storage + cosine similarity search |
|
||||
| MariaDB | `lthn-sh-db:3306` | `brain_memories` table (workspace-scoped) |
|
||||
| Laravel | `https://hub.lthn.sh` | BrainService, artisan commands, MCP tools |
|
||||
|
||||
All `.lan` services use self-signed TLS behind Traefik. The app auto-skips TLS verification for `.lan` URLs.
|
||||
All `*.lthn.sh` services use real TLS certs (GoGetSSL wildcard). Internal-only DNS via UniFi gateway.
|
||||
|
||||
> **Migration note**: Services are transitioning from `*.lthn.lan` (self-signed, /etc/hosts) to `*.lthn.sh` (real certs, proper DNS). During transition, either URL scheme works.
|
||||
|
||||
## Seeding Knowledge
|
||||
|
||||
|
|
@ -80,8 +82,8 @@ If the Laravel app isn't available, use the Go brain-seed tool:
|
|||
```bash
|
||||
cd ~/Code/go-ai
|
||||
go run cmd/brain-seed/main.go \
|
||||
--ollama=https://ollama.lthn.lan \
|
||||
--qdrant=https://qdrant.lthn.lan \
|
||||
--ollama=https://ollama.lthn.sh \
|
||||
--qdrant=https://qdrant.lthn.sh \
|
||||
--collection=openbrain \
|
||||
--model=embeddinggemma
|
||||
```
|
||||
|
|
@ -134,19 +136,21 @@ For debugging or bulk operations:
|
|||
|
||||
```bash
|
||||
# Collection stats
|
||||
curl -sk https://qdrant.lthn.lan/collections/openbrain | python3 -m json.tool
|
||||
curl -s https://qdrant.lthn.sh/collections/openbrain | python3 -m json.tool
|
||||
|
||||
# Raw vector search (embed query first via Ollama)
|
||||
VECTOR=$(curl -sk https://ollama.lthn.lan/api/embeddings \
|
||||
VECTOR=$(curl -s https://ollama.lthn.sh/api/embeddings \
|
||||
-d '{"model":"embeddinggemma","prompt":"Traefik setup"}' \
|
||||
| python3 -c "import sys,json; print(json.dumps(json.load(sys.stdin)['embedding']))")
|
||||
|
||||
curl -sk https://qdrant.lthn.lan/collections/openbrain/points/search \
|
||||
curl -s https://qdrant.lthn.sh/collections/openbrain/points/search \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d "{\"vector\":$VECTOR,\"limit\":5,\"with_payload\":true}" \
|
||||
| python3 -m json.tool
|
||||
```
|
||||
|
||||
No `-sk` flag needed — real TLS certs.
|
||||
|
||||
## Storing New Memories
|
||||
|
||||
### Via BrainService (PHP)
|
||||
|
|
@ -215,7 +219,7 @@ php artisan brain:ingest --workspace=1 --fresh --source=memory
|
|||
### Check Collection Health
|
||||
|
||||
```bash
|
||||
curl -sk https://qdrant.lthn.lan/collections/openbrain | \
|
||||
curl -s https://qdrant.lthn.sh/collections/openbrain | \
|
||||
python3 -c "import sys,json; r=json.load(sys.stdin)['result']; print(f'Points: {r[\"points_count\"]}, Status: {r[\"status\"]}')"
|
||||
```
|
||||
|
||||
|
|
@ -240,3 +244,4 @@ This deletes the Qdrant collection and re-creates it with fresh data.
|
|||
- **Embedding model**: `embeddinggemma` (768d, ~135ms per embedding on GPU)
|
||||
- **Collection status**: green
|
||||
- **4 failed sections**: Oversized plan sections that exceeded Ollama's context window — not critical
|
||||
- **Domain migration**: `*.lthn.lan` → `*.lthn.sh` (in progress)
|
||||
|
|
|
|||
87
docs/plans/2026-03-03-unifi-dns-records.md
Normal file
87
docs/plans/2026-03-03-unifi-dns-records.md
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
# UniFi Gateway DNS Records — lthn.sh
|
||||
|
||||
> **For:** snider (UniFi gateway config)
|
||||
> **Date:** 3 Mar 2026
|
||||
|
||||
## Overview
|
||||
|
||||
UniFi gateway doesn't support wildcard DNS. Each service needs an individual A record pointing to the homelab box (10.69.69.165).
|
||||
|
||||
All covered by a single GoGetSSL cert with SANs: `lthn.sh`, `*.lthn.sh`, `*.infra.lthn.sh`.
|
||||
|
||||
## Lab Services — `*.lthn.sh`
|
||||
|
||||
| Hostname | IP | Service |
|
||||
|----------|-----|---------|
|
||||
| `hub.lthn.sh` | 10.69.69.165 | Laravel admin hub |
|
||||
| `lab.lthn.sh` | 10.69.69.165 | LEM Lab |
|
||||
| `ollama.lthn.sh` | 10.69.69.165 | Ollama inference + embeddings |
|
||||
| `qdrant.lthn.sh` | 10.69.69.165 | Qdrant vector search |
|
||||
| `eaas.lthn.sh` | 10.69.69.165 | EaaS scoring API |
|
||||
|
||||
## Infrastructure — `*.infra.lthn.sh`
|
||||
|
||||
| Hostname | IP | Service |
|
||||
|----------|-----|---------|
|
||||
| `traefik.infra.lthn.sh` | 10.69.69.165 | Traefik dashboard |
|
||||
| `grafana.infra.lthn.sh` | 10.69.69.165 | Grafana |
|
||||
| `prometheus.infra.lthn.sh` | 10.69.69.165 | Prometheus |
|
||||
| `influx.infra.lthn.sh` | 10.69.69.165 | InfluxDB |
|
||||
| `auth.infra.lthn.sh` | 10.69.69.165 | Authentik SSO |
|
||||
| `portainer.infra.lthn.sh` | 10.69.69.165 | Portainer |
|
||||
| `phpmyadmin.infra.lthn.sh` | 10.69.69.165 | phpMyAdmin |
|
||||
| `maria.infra.lthn.sh` | 10.69.69.165 | MariaDB admin |
|
||||
| `postgres.infra.lthn.sh` | 10.69.69.165 | PostgreSQL admin |
|
||||
| `redis.infra.lthn.sh` | 10.69.69.165 | Redis admin |
|
||||
|
||||
## Bare domain
|
||||
|
||||
| Hostname | IP | Service |
|
||||
|----------|-----|---------|
|
||||
| `lthn.sh` | 10.69.69.165 | Redirects to `hub.lthn.sh` (or landing page) |
|
||||
|
||||
## Total: 16 A records
|
||||
|
||||
All pointing to the same IP. Add more as new services come online.
|
||||
|
||||
## After UniFi Config
|
||||
|
||||
Once DNS is live, remove the old `/etc/hosts` entries on Mac:
|
||||
|
||||
```
|
||||
# REMOVE these lines from /etc/hosts:
|
||||
10.69.69.165 ollama.lthn.lan
|
||||
10.69.69.165 qdrant.lthn.lan
|
||||
10.69.69.165 eaas.lthn.lan
|
||||
10.69.69.165 lthn.lan
|
||||
10.69.69.165 traefik.lthn.lan
|
||||
10.69.69.165 blesta.lthn.lan
|
||||
10.69.69.165 auth.lthn.lan
|
||||
10.69.69.165 phpmyadmin.lthn.lan
|
||||
10.69.69.165 portainer.lthn.lan
|
||||
10.69.69.165 grafana.lthn.lan
|
||||
10.69.69.165 lab.lthn.lan
|
||||
10.69.69.165 prometheus.lthn.lan
|
||||
10.69.69.165 influx.lthn.lan
|
||||
10.69.69.165 maria.lthn.lan
|
||||
10.69.69.165 postgres.lthn.lan
|
||||
10.69.69.165 redis.lthn.lan
|
||||
```
|
||||
|
||||
Test resolution:
|
||||
```bash
|
||||
# Should resolve to 10.69.69.165 via UniFi DNS
|
||||
dig hub.lthn.sh @<unifi-gateway-ip> +short
|
||||
|
||||
# Test each service
|
||||
for h in hub lab ollama qdrant eaas; do
|
||||
echo -n "$h.lthn.sh → "; dig $h.lthn.sh +short
|
||||
done
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- UniFi gateway DNS serves these records to all LAN clients automatically
|
||||
- No public DNS records exist for `lthn.sh` — the zone in CloudNS is empty (used only for ACME DNS-01 cert validation)
|
||||
- The Mac, the Linux homelab, and any other LAN device will all resolve via UniFi
|
||||
- Charon's CoreDNS on the Linux box can coexist — it handles `leth.in` (prod internal), UniFi handles `lthn.sh` (homelab)
|
||||
Loading…
Add table
Reference in a new issue