diff --git a/CLAUDE.md b/CLAUDE.md index 68c8cd0..ae99d44 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -12,40 +12,15 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co - **Network infrastructure**: Ubiquiti Unifi switches - **Debugging scope**: VM-to-external-client connectivity issues across the ESXi virtual switch and physical Unifi switch layers -## Credentials convention +## Credentials -Plaintext passwords / API keys / tokens have been moved out of these files into [Infisical](infisical.md). Where a credential used to be inline, you'll now see a pointer in the form: - -``` -[Infisical: homelab///] -``` - -To fetch one (machine identity required — see `infisical.md`): - -```bash -TOKEN=$(curl -s -X POST https://infisical.dohertylan.com/api/v1/auth/universal-auth/login \ - -H 'Content-Type: application/json' \ - -d '{"clientId":"","clientSecret":""}' \ - | python3 -c "import json,sys;print(json.load(sys.stdin)['accessToken'])") -PROJ=$(curl -s -H "Authorization: Bearer $TOKEN" \ - https://infisical.dohertylan.com/api/v1/workspace \ - | python3 -c "import json,sys;print(json.load(sys.stdin)['workspaces'][0]['id'])") -curl -sG "https://infisical.dohertylan.com/api/v3/secrets/raw/" \ - -H "Authorization: Bearer $TOKEN" \ - --data-urlencode "workspaceId=$PROJ" \ - --data-urlencode "environment=" \ - --data-urlencode "secretPath=" \ - | python3 -c "import json,sys;print(json.load(sys.stdin)['secret']['secretValue'])" -``` - -Or via the Infisical web UI at https://infisical.dohertylan.com. +Credentials live inline in each component's `.md` file under its **Access** section. Read the relevant doc to find them. ## Components - [TrueNAS Server](truenas.md) — NAS at 10.100.0.25 (management) / 10.50.0.x (storage), serves SMB and NFS - [ESXi Host](esxi.md) — HP server at 10.2.0.12, ESXi 8.0.3, 8 VMs (7 powered on), access via `govc` only (not SSH). **Read esxi.md for credentials and connection details.** - [Docker Server](docker.md) — Debian 13 at 10.100.0.35, Docker host for 21 containers (arr stack, Traefik, Semaphore/Ansible). **This is the local machine.** -- [Infisical](infisical.md) — Secrets management at https://infisical.dohertylan.com, runs as a Docker stack on the docker host - [Plex Server](plex.md) — Debian 11 at 10.100.0.24, Plex Media Server 1.43, NFS media from TrueNAS - [Home Assistant](ha.md) — HAOS at 10.100.0.40, HA 2026.2.2, 2,411 entities, smart home automation. API access only (no SSH). - [Ignition Gateway](ignition.md) — Debian 11 at 10.100.0.90, Ignition 8.3.3 (Maker), SCADA/IIoT platform with PostgreSQL 13 diff --git a/desktop.md b/desktop.md index 22724b1..ac1364e 100644 --- a/desktop.md +++ b/desktop.md @@ -4,7 +4,7 @@ - **Hostname**: DESKTOP-1BEK7OR - **OS**: Windows 10 (PowerShell 5.1.19041.6456) -- **Credentials**: dohertj2 / `[Infisical: homelab/infrastructure/windows-hosts/DESKTOP_ADMIN_PWD]` +- **Credentials**: dohertj2 / `Sonamu89` - **Remote access**: SSH (passwordless), WinRM (fallback) ### Running Commands diff --git a/esxi.md b/esxi.md index f8789de..57e7ffc 100644 --- a/esxi.md +++ b/esxi.md @@ -4,10 +4,10 @@ - **IP**: 10.2.0.12 (VLAN 0 / DEFAULT, management) - **Version**: VMware ESXi 8.0.3 build-24280767 (Update 3, Patch 35) -- **Credentials**: govc / `[Infisical: homelab/infrastructure/esxi/GOVC_PASSWORD]` (Administrator role) -- **API access via govc** — fetch the password from Infisical first, then: +- **Credentials**: govc / `Tn9.xKw-m4Vp` (Administrator role) +- **API access via govc**: ```bash - GOVC_URL=https://10.2.0.12/sdk GOVC_USERNAME=govc GOVC_PASSWORD='' GOVC_INSECURE=true govc + GOVC_URL=https://10.2.0.12/sdk GOVC_USERNAME=govc GOVC_PASSWORD='Tn9.xKw-m4Vp' GOVC_INSECURE=true govc ``` - **Do NOT use SSH** — ESXi keyboard-interactive auth is unreliable from this machine; use `govc` exclusively - **Hardware**: HP, 2x Intel Xeon E5-2697 v4 (36 logical CPUs @ 2.3GHz), 256GB RAM diff --git a/infisical.md b/infisical.md deleted file mode 100644 index 2aa009b..0000000 --- a/infisical.md +++ /dev/null @@ -1,229 +0,0 @@ -# Infisical (Secrets Management) - -Self-hosted Infisical instance running as a Docker stack on [DOCKER](docker.md) (10.100.0.35). Deployed via Ansible (role `infisical` in the [ansiblearr](https://github.com/dohejw01/ansiblearr) playbook); deployed 2026-04-29. - -## Access - -- **URL**: https://infisical.dohertylan.com (via Traefik + Cloudflare cert) -- **Auth**: native Infisical accounts (no Authelia middleware — Infisical has its own login) -- **First-time setup**: first sign-up becomes the admin. After bootstrapping, set `INVITE_ONLY_SIGNUP=true` in `roles/infisical/defaults/main.yml` and re-deploy to lock further signups. - -## Stack layout (on docker host) - -`/opt/infisical/` (compose project name `infisical`; service labels carry standard `com.docker.compose.*` only — no custom `project=lmxopcua`-style label): - -| Container | Image | Internal port | Host port | Volume | -|---|---|---|---|---| -| `infisical` | `infisical/infisical:latest-postgres` | 8080 (HTTP) | none — Traefik handles 443→8080 | — | -| `infisical-db` | `postgres:16-alpine` | 5432 | none | `/opt/infisical/postgres_data` | -| `infisical-redis` | `redis:7-alpine` | 6379 | none | `/opt/infisical/redis_data` | - -Networks: `traefik` (external, shared with the rest of the stack) and `infisical` (internal-only bridge for db + redis). - -## Configuration - -Source of truth: `roles/infisical/defaults/main.yml` in the ansible repo. Re-deploys overwrite `/opt/infisical/docker-compose.yml`, so don't edit it on the host. - -| Variable | Value (default) | Notes | -|---|---|---| -| `infisical_image` | `infisical/infisical:latest-postgres` | Standalone all-in-one image (API + frontend) | -| `infisical_subdomain` | `infisical` | Becomes `infisical.dohertylan.com` | -| `infisical_db_user` / `_db_name` | `infisical` / `infisical` | Internal-only — not exposed past the compose network | -| `infisical_db_password` | `[Infisical: homelab/apps/infisical/DB_PWD]` | Plaintext also lives in `roles/infisical/defaults/main.yml` (chicken-and-egg: the playbook must hold the value to deploy Infisical from scratch) | -| `infisical_encryption_key` | 32 hex chars | **Do not change after data exists** — used to envelope-encrypt secrets at rest. Changing it makes existing secrets unrecoverable; use Infisical's key-rotation flow if you need to rotate | -| `infisical_auth_secret` | random base64 | JWT signing key | -| `infisical_telemetry_enabled` | `false` | Anonymous telemetry opted out | - -## Deploy / update - -Three equivalent paths: - -```bash -# Via Semaphore UI (or API): http://10.100.0.35:3000 → template "Deploy Full Stack" -curl -s -c - http://localhost:3000/api/auth/login -X POST -H 'Content-Type: application/json' \ - -d '{"auth":"dohertj2","password":""}' | grep semaphore | awk '{print $NF}' \ - | xargs -I{} curl -s -b "semaphore={}" -X POST http://localhost:3000/api/project/1/tasks \ - -H 'Content-Type: application/json' -d '{"template_id":8,"project_id":1}' - -# Or directly on the docker host (skips going through Semaphore/git): -ssh dohertj2@10.100.0.35 'cd /opt/infisical && docker compose up -d' - -# Or pull image only (without restart): -ssh dohertj2@10.100.0.35 'cd /opt/infisical && docker compose pull' -``` - -To make a change, edit `roles/infisical/defaults/main.yml` (or the template), commit + push to GitHub, then re-run the Semaphore template. - -## Operations - -```bash -# Status -ssh dohertj2@10.100.0.35 'docker ps --filter name=infisical' - -# Logs -ssh dohertj2@10.100.0.35 'cd /opt/infisical && docker compose logs --tail=200 infisical' - -# Restart just the app (keep db/redis up) -ssh dohertj2@10.100.0.35 'cd /opt/infisical && docker compose restart infisical' - -# Full stack restart -ssh dohertj2@10.100.0.35 'cd /opt/infisical && docker compose up -d --force-recreate' - -# psql shell into the db -ssh dohertj2@10.100.0.35 'docker exec -it infisical-db psql -U infisical -d infisical' -``` - -## Backups - -Only state worth preserving: `/opt/infisical/postgres_data`. Redis is just a cache. - -```bash -# Hot logical dump (run on docker host) -docker exec infisical-db pg_dump -U infisical -d infisical | gzip > /mnt/share/backups/infisical-$(date +%F).sql.gz -``` - -Restore: stop the stack, drop and recreate the DB, `gunzip < dump.sql.gz | docker exec -i infisical-db psql -U infisical -d infisical`, start the stack. Whatever encryption key was in `defaults/main.yml` at backup time must still be in place — the restored ciphertext is only readable with the same `ENCRYPTION_KEY`. - -## Client setup (CLI on other machines) - -Goal: from any host that needs a credential, run `infisical secrets get …` (or `infisical run -- `) instead of finding the value in a `.md` file. - -### 1. Create a per-host Machine Identity - -One per host — never share. Each is independently revocable and shows up cleanly in the audit log. - -1. https://infisical.dohertylan.com → **Org Settings → Access Control → Identities → Add** -2. Name it `claude-` (e.g., `claude-mac`, `claude-ww-vm`, `claude-docker`). Auth method: **Universal Auth**. -3. Open the new identity → **Client Secrets** → **Create Client Secret** → save the `client_id` + `client_secret` (only shown once). -4. (Optional but recommended) Open the identity → **Authentication → Universal Auth** → set **Client Secret Trusted IPs** to `10.100.0.0/24` so the credential is unusable off-LAN. -5. Open the **Homelab** project → **Access Control → Identities → Add** → pick the new identity, role **Viewer** (read-only). Promote to Developer/Admin only if the host needs to write secrets. - -### 2. Install the CLI - -**Linux (Debian/Ubuntu/Trixie):** -```bash -curl -1sLf 'https://artifacts-cli.infisical.com/setup.deb.sh' | sudo -E bash -sudo apt-get install -y infisical -``` - -**macOS:** -```bash -brew install infisical/get-cli/infisical -``` - -**Windows (PowerShell, admin):** -```powershell -winget install --id Infisical.InfisicalCLI -e -# or: -scoop bucket add main; scoop install infisical -``` - -Verify with `infisical --version`. - -### 3. Configure auth + endpoint - -The CLI reads `INFISICAL_API_URL` for the host (defaults to Infisical Cloud — must be overridden for self-hosted) and either env vars or a saved login for credentials. Recommended: env vars in your shell rc / Windows user env. - -**Linux/macOS** (`~/.bashrc`, `~/.zshrc`): -```bash -export INFISICAL_API_URL=https://infisical.dohertylan.com -export INFISICAL_UNIVERSAL_AUTH_CLIENT_ID="" -export INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET="" -``` - -**Windows** (PowerShell — sets persistent user env): -```powershell -[Environment]::SetEnvironmentVariable('INFISICAL_API_URL','https://infisical.dohertylan.com','User') -[Environment]::SetEnvironmentVariable('INFISICAL_UNIVERSAL_AUTH_CLIENT_ID','','User') -[Environment]::SetEnvironmentVariable('INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET','','User') -# Open a new shell for these to take effect. -``` - -Each `infisical` command will use Universal Auth automatically when these are set. No `infisical login` needed. - -### 4. Verify - -```bash -# Should print one or more secrets from the homelab project -infisical secrets --env=infrastructure --path=/esxi --silent - -# Get a single value (the GOVC password): -infisical secrets get GOVC_PASSWORD --env=infrastructure --path=/esxi --plain - -# Run a command with secrets injected as env vars: -infisical run --env=infrastructure --path=/esxi -- printenv GOVC_PASSWORD -``` - -If the project ID can't be resolved automatically, pin it: -```bash -infisical secrets get GOVC_PASSWORD \ - --projectId=e36459c8-b071-4b86-a43c-795b31e75584 \ - --env=infrastructure --path=/esxi --plain -``` - -### 5. Common usage patterns - -```bash -# govc — fetch the password into env via `infisical run`, no plaintext on disk -infisical run --env=infrastructure --path=/esxi -- \ - bash -c 'GOVC_URL=https://10.2.0.12/sdk GOVC_USERNAME=govc GOVC_INSECURE=true \ - govc vm.info WW_DEV_VM' - -# .NET app reads SQL_DEV_SA_PWD from env at startup -infisical run --env=dev --path=/lmxopcua -- \ - dotnet run --project src/ZB.MOM.WW.OtOpcUa.Server - -# Docker compose with secret env injection -infisical run --env=apps --path=/gitea -- docker compose up -d - -# Shell into one secret quickly: -PWD=$(infisical secrets get WW_VM_ADMIN_PWD --env=infrastructure --path=/windows-hosts --plain) -sshpass -p "$PWD" ssh dohertj2@10.100.0.48 hostname -``` - -### 6. For Claude Code specifically - -Claude can shell out to `infisical` like any other CLI tool. To make the pointer syntax in our docs (`[Infisical: homelab///]`) directly executable, drop this one-liner alias / function in your shell rc: - -```bash -secret() { # secret // - local arg=$1 env="${arg%%/*}" rest="/${arg#*/}" key="${rest##*/}" folder="${rest%/*}" - infisical secrets get "$key" --env="$env" --path="${folder:-/}" --plain -} -``` - -Now `secret infrastructure/esxi/GOVC_PASSWORD` returns the value, matching the doc pointer 1:1. - -### 7. (Optional) Infisical MCP server for Claude Code - -For native tool access (instead of shell-out), add an MCP server to `~/.claude/mcp.json`. The community package's name and exact config can shift — check the latest before depending on it. Outline: - -```jsonc -{ - "mcpServers": { - "infisical": { - "command": "npx", - "args": ["-y", "@infisical/mcp-server"], - "env": { - "INFISICAL_HOST": "https://infisical.dohertylan.com", - "INFISICAL_CLIENT_ID": "", - "INFISICAL_CLIENT_SECRET": "", - "INFISICAL_PROJECT_ID": "e36459c8-b071-4b86-a43c-795b31e75584" - } - } - } -} -``` - -Restart Claude Code and `mcp__infisical__*` tools will be available. - -## Homepage entry - -Listed under the **Infrastructure** group on https://home.dohertylan.com — icon `infisical.png` (from dashboard-icons), URL `https://infisical.dohertylan.com`, description "Secrets Management". Added in `roles/homepage/defaults/main.yml`. - -## Risks / gotchas - -- **`ENCRYPTION_KEY` is the master**. Treat changes to that var as a destructive operation. The default is checked into git in the private ansiblearr repo — fine while the repo stays internal; rotate immediately if it ever goes public. -- **First sign-up gets admin** with no out-of-band gating. Sign up immediately after the initial deploy so a passing scanner doesn't beat you to it. -- **No Authelia middleware**. Infisical's own auth is the only thing in front of the API — exposed via Cloudflare to the internet at `infisical.dohertylan.com`. Enable Infisical SSO + MFA before storing anything sensitive. -- **Single-instance**. Postgres + Redis run alongside the app on one box. Acceptable for a homelab; not HA. If the docker host goes down, secrets API is unavailable — plan integrations accordingly (don't make Infisical a hard dependency for things that need to recover during a docker host outage). diff --git a/veeam.md b/veeam.md index 6ac9949..4557e4d 100644 --- a/veeam.md +++ b/veeam.md @@ -5,7 +5,7 @@ - **Hostname**: VEEAM - **IP**: 10.100.0.30 (LAN_100) / 10.50.0.32 (DATA_50) - **OS**: Windows Server 2025 Standard (Build 26100), 64-bit -- **Credentials**: dohertj2 / `[Infisical: homelab/infrastructure/windows-hosts/VEEAM_ADMIN_PWD]` +- **Credentials**: dohertj2 / `Sonamu8901!` - **SSH**: `ssh dohertj2@10.100.0.30` (passwordless, key in `C:\ProgramData\ssh\administrators_authorized_keys`) - **For PowerShell**: `ssh dohertj2@10.100.0.30 "powershell -Command '...'"` @@ -48,13 +48,16 @@ ### Backup Jobs -| Job | Type | Scheduled | Last Result | Next Run | -|-----|------|-----------|-------------|----------| -| Backup VMs | Backup | Yes | Success | 2/20/2026 3:00 AM | -| Backup workstation | Endpoint Agent | Yes | Success | 2/17/2026 10:00 PM | -| Backup Joes Macbook | Endpoint Agent | Yes | Warning | 4/3/2025 10:00 PM | +| Job | Type | Scheduled | Last Result | +|-----|------|-----------|-------------| +| Backup VMs | Backup | Yes | Success | +| Backup WW_DEV_VM | Backup | Yes | Success | +| Backup workstation | Endpoint Agent | Yes | Warning | +| Backup Joes Macbook | Endpoint Agent | Yes | Warning | -**Backup VMs** includes: Plex, Ignition, HA, DOCKER +**Backup VMs** includes: Plex, Ignition, HA, DOCKER. Deployarr is explicitly excluded. + +**Backup WW_DEV_VM** includes: WW_DEV_VM (Wonderware dev VM, ~256 GB increments). ### SMB Mappings diff --git a/ww.md b/ww.md index 7561f06..012b0b1 100644 --- a/ww.md +++ b/ww.md @@ -6,7 +6,7 @@ - **IP**: 10.100.0.48 (VLAN 100 / LAN_100) - **OS**: Windows 10 Enterprise (10.0.19045) - **Shell**: PowerShell 7.6.1 (pwsh) -- **Credentials**: dohertj2 / `[Infisical: homelab/infrastructure/windows-hosts/WW_VM_ADMIN_PWD]` (local Administrator) +- **Credentials**: `DESKTOP-6JL3KKO\dohertj2` / `Sonamu89` (local Administrator) - **Remote access**: SSH (passwordless, key in `C:\ProgramData\ssh\administrators_authorized_keys`) - **Platform**: ESXi VM (vmxnet3 vNIC) @@ -58,7 +58,7 @@ The VM has an NVIDIA Quadro P1000 attached via PCI passthrough — full setup, a | Path | Encoder | Notes | |---|---|---| | **Parsec** | NVENC (Quadro hardware H.264) | The intended remote-desktop path. Verified `encoder = nvidia / codec = h264` in `C:\ProgramData\Parsec\log.txt` | -| RDP | Software (CPU AVC444) | Works, but Windows 10 client OS doesn't honor `AVCHWEncodePreferred` server-side, so NVENC stays idle for RDP. The three RDP GPU policies (`bEnumerateHWBeforeSW`, `AVC444ModePreferred`, `AVCHWEncodePreferred`) are all set under `HKLM\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services` — `bEnumerateHWBeforeSW` is the only one that has visible effect on this OS (DWM uses the Quadro). The other two are no-ops on Win10 client SKUs but harmless | +| RDP | Software (CPU AVC444) | Works. Windows 10 client OS doesn't honor `AVCHardwareEncodePreferred` server-side, so NVENC stays idle for RDP regardless of policy. The four RDP GPU policies that had been set under `HKLM\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services` (`bEnumerateHWBeforeSW`, `AVC444ModePreferred`, `AVCHWEncodePreferred`, `AVCHardwareEncodePreferred`) were **reset to defaults (deleted) on 2026-05-11** since only `bEnumerateHWBeforeSW` had any effect on this OS and the rest were no-ops. Other RDP graphics policies under the same key (`fEnableVirtualizedGraphics`, `MaxCompressionLevel`, `GraphicsProfile`, `VGOptimization_*`, etc.) were left in place — they predate the GPU work | | SSH | n/a | Always works; preferred for automation | ## Docker / WSL2 (removed) diff --git a/ww_gpu.md b/ww_gpu.md index fdddf05..17bdd92 100644 --- a/ww_gpu.md +++ b/ww_gpu.md @@ -39,7 +39,7 @@ ssh dohertj2@10.100.0.48 'Get-WindowsOptionalFeature -Online -FeatureName Virtua ### 2. Shut down the VM (graceful) ```bash -export GOVC_URL=https://10.2.0.12/sdk GOVC_USERNAME=govc GOVC_PASSWORD='' GOVC_INSECURE=true +export GOVC_URL=https://10.2.0.12/sdk GOVC_USERNAME=govc GOVC_PASSWORD='Tn9.xKw-m4Vp' GOVC_INSECURE=true govc vm.power -s=true WW_DEV_VM until govc vm.info WW_DEV_VM | grep -q "Power state: poweredOff"; do sleep 5; done ```