## Summary Deploy a cloud-free NVR stack for the GableCam (ReoLink Elite Floodlight at 192.168.1.159): - **Mosquitto** — shared MQTT broker in `mqtt` namespace (cluster-internal, no auth) - **Ntfy** — self-hosted push notifications in `ntfy` namespace, exposed at `ntfy.tail8d86e.ts.net` / `ntfy.ops.eblu.me` - **Frigate** — NVR with GableCam via HTTP-FLV, ONNX CPU detection, NFS recordings on sifaka, exposed at `nvr.tail8d86e.ts.net` / `nvr.ops.eblu.me` - **frigate-notify** — bridges Frigate detection events (person, car, dog, cat) to Ntfy alerts via MQTT Also includes: - Prometheus scrape target for Frigate metrics - Grafana dashboard for Frigate (status, inference speed, FPS, CPU/memory, storage) - Caddy reverse proxy entries for `nvr.ops.eblu.me` and `ntfy.ops.eblu.me` ## Prerequisites - [ ] Create NFS share `frigate` on sifaka (`/volume1/frigate`, RW for indri) - [ ] Create 1Password item "Reolink Floodlight Camera" in `blumeops` vault with `username` and `password` fields ## Deployment (after merge) ```bash argocd app sync apps argocd app sync mosquitto argocd app sync ntfy argocd app sync frigate argocd app sync grafana-config argocd app sync prometheus mise run provision-indri -- --tags caddy mise run services-check ``` ## Verification - [ ] Mosquitto pod running, accepting connections on 1883 - [ ] Ntfy web UI accessible at `ntfy.ops.eblu.me` - [ ] Frigate web UI at `nvr.ops.eblu.me` showing GableCam live feed - [ ] Object detection working (ONNX, person/car/dog/cat) - [ ] Recordings appearing in NFS share on sifaka - [ ] frigate-notify sending detection alerts to Ntfy - [ ] Prometheus scraping Frigate metrics - [ ] Grafana dashboard showing Frigate data Reviewed-on: https://forge.ops.eblu.me/eblume/blumeops/pulls/190 |
||
|---|---|---|
| .. | ||
| argocd-cm-patch.yaml | ||
| argocd-cmd-params-cm.yaml | ||
| argocd-rbac-cm-patch.yaml | ||
| argocd-ssh-known-hosts-cm.yaml | ||
| external-secret-repo-forge.yaml | ||
| ingress-tailscale.yaml | ||
| kustomization.yaml | ||
| README.md | ||
ArgoCD
GitOps continuous delivery for Kubernetes, with self-management via ArgoCD.
Prerequisites
- Tailscale operator deployed (see
argocd/manifests/tailscale-operator/README.md) - SSH key added to Forgejo user for access to all forge repos (not a deploy key)
Manual Bootstrap
Bootstrap is required when setting up a new cluster. After bootstrap, ArgoCD manages itself.
# 1. Create namespace
kubectl create namespace argocd
# 2. Apply ArgoCD manifests via kustomize
kubectl apply -k argocd/manifests/argocd/
# 3. Wait for ArgoCD to be ready
kubectl wait --for=condition=available deployment/argocd-server -n argocd --timeout=300s
# 4. Get initial admin password
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d && echo
# 5. Login and change password
argocd login argocd.tail8d86e.ts.net --username admin --grpc-web
argocd account update-password
# 6. Apply repo-creds-forge credential template for SSH access to all forge repos
PRIV_KEY=$(op read "op://vg6xf6vvfmoh5hqjjhlhbeoaie/csjncynh6htjvnh2l2da65y32q/private key?ssh-format=openssh")$'\n' && \
kubectl create secret generic repo-creds-forge -n argocd \
--from-literal=type=git \
--from-literal=url='ssh://forgejo@forge.ops.eblu.me:2222/eblume/' \
--from-literal=insecure=true \
--from-literal=sshPrivateKey="$PRIV_KEY" && \
kubectl label secret repo-creds-forge -n argocd argocd.argoproj.io/secret-type=repo-creds
# 7. Apply ArgoCD Applications (self-management + app-of-apps)
kubectl apply -f argocd/apps/argocd.yaml
kubectl apply -f argocd/apps/apps.yaml
After step 7, ArgoCD manages itself and all applications defined in argocd/apps/.
Access
- URL: https://argocd.tail8d86e.ts.net
- Username:
admin - Password: Stored in 1Password after initial setup
ArgoCD CLI Commands
# Check all applications
argocd app list
# Sync a specific application
argocd app sync <app-name>
# Check application status
argocd app get <app-name>
# Hard refresh (clear git cache)
argocd app get <app-name> --hard-refresh
Adding New Applications
- Create an Application manifest in
argocd/apps/<app-name>.yaml - Commit and push to forge
- ArgoCD (via app-of-apps) automatically picks it up
Example Application:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: my-app
namespace: argocd
spec:
project: default
source:
repoURL: ssh://forgejo@forge.ops.eblu.me:2222/eblume/blumeops.git
targetRevision: main
path: argocd/manifests/my-app
destination:
server: https://kubernetes.default.svc
namespace: my-app
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
Files
| File | Description |
|---|---|
kustomization.yaml |
References upstream install.yaml + local customizations |
service-tailscale.yaml |
Tailscale Ingress for external access with Let's Encrypt TLS |
argocd-cmd-params-cm.yaml |
Patch to disable HTTPS redirect (TLS terminates at Ingress) |
repo-forge-secret.yaml.tpl |
Template for forge SSH credential template (manual) |
README.md |
This file |
Notes
- TODO: Secrets (
repo-creds-forge) are not managed by ArgoCD and must be applied manually. Future improvement: integrate with a secrets operator (e.g., External Secrets). - The credential template (
repo-creds) uses a URL prefix to match all repos undereblume/. - ArgoCD uses Tailscale Ingress with Let's Encrypt for TLS termination.
- The
--grpc-webflag is required for CLI access through the Tailscale ingress.