Compare commits
87 Commits
ac7863802a
...
a08a2189e1
| Author | SHA1 | Date | |
|---|---|---|---|
| a08a2189e1 | |||
| 45f0100784 | |||
| d5da49e566 | |||
| e0e27445c7 | |||
| 9f61854bc2 | |||
| ded87979c5 | |||
| 538fca4195 | |||
| 5ffcfc7d01 | |||
| f958d65528 | |||
| 4197072593 | |||
| d6f0f375b7 | |||
| 051691e71f | |||
| 4a709391e6 | |||
| 1880df2525 | |||
| 02ed3e3145 | |||
| b59025d495 | |||
| 306b4b8458 | |||
| 2e6f811d12 | |||
| ea08411128 | |||
| a09333ba38 | |||
| bff6b83d11 | |||
| a94bd95248 | |||
| 2c0622583e | |||
| 86490b74c4 | |||
| 2ef8a7bbc2 | |||
| ae85dcfeaa | |||
| 41292eff0b | |||
| a69bd45455 | |||
| a3a5b1a9bd | |||
| 938f6b336c | |||
| 3c97a02fa7 | |||
| 980892a5b4 | |||
| adf7d7eb31 | |||
| 2fe8f7ea6a | |||
| c00b760976 | |||
| d78fc77825 | |||
| a6ab2b44af | |||
| 3a207c7d94 | |||
| d45cf950ec | |||
| 193c820fc6 | |||
| c3524cec3d | |||
| f214e394d0 | |||
| 07cffbeec0 | |||
| 576221c47d | |||
| f63d39e5aa | |||
| 48bce52660 | |||
| 5b1a209d9a | |||
| 5437b985e8 | |||
| f49e341445 | |||
| 8c64a4b067 | |||
| 7b5001c581 | |||
| fc0c5c1250 | |||
| 39fc2aacde | |||
| 33f0d67b34 | |||
| 48a2a53023 | |||
| 269b6cd7ad | |||
| b06b5d7612 | |||
| 0f1994c384 | |||
| 3df06948a9 | |||
| 30ac7e5ac1 | |||
| 0b8e4f012a | |||
| 2eecba7f55 | |||
| bd5f1b3a67 | |||
| 9ff70673e3 | |||
| 755c54f26b | |||
| f4588b4304 | |||
| e36f7059ea | |||
| 6deefc514e | |||
| 33ff3d20aa | |||
| 65de7602c9 | |||
| 9b77a89b0d | |||
| 6a86590484 | |||
| 8cc80f695f | |||
| 50c25b1b92 | |||
| a85fac9002 | |||
| 5bfeffe31f | |||
| 8459ea7058 | |||
| 6efe79819f | |||
| 33d07dcf5c | |||
| 7257762c45 | |||
| bff64dba65 | |||
| f72dc43f76 | |||
| 47a73af27e | |||
| 1ee60d9534 | |||
| 63d82af268 | |||
| 47cbc9b9f6 | |||
| 001e9c36fe |
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
AGENTS.md
|
||||||
12
clusters/atlas/applications/kustomization.yaml
Normal file
12
clusters/atlas/applications/kustomization.yaml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
# clusters/atlas/applications/kustomization.yaml
|
||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
resources:
|
||||||
|
- ../../services/crypto
|
||||||
|
- ../../services/gitea
|
||||||
|
- ../../services/jellyfin
|
||||||
|
- ../../services/jitsi
|
||||||
|
- ../../services/monitoring
|
||||||
|
- ../../services/pegasus
|
||||||
|
- ../../services/vault
|
||||||
|
- ../../services/zot
|
||||||
@ -1,4 +1,4 @@
|
|||||||
# infrastructure/flux-system/kustomization-crypto.yaml
|
# clusters/atlas/flux-system/applications/crypto/kustomization.yaml
|
||||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||||
kind: Kustomization
|
kind: Kustomization
|
||||||
metadata:
|
metadata:
|
||||||
@ -1,4 +1,4 @@
|
|||||||
# infrastructure/flux-system/kustomization-gitea.yaml
|
# clusters/atlas/flux-system/applications/gitea/kustomization.yaml
|
||||||
apiVersion: kustomize.toolkit.fluxcd.io/v1beta2
|
apiVersion: kustomize.toolkit.fluxcd.io/v1beta2
|
||||||
kind: Kustomization
|
kind: Kustomization
|
||||||
metadata:
|
metadata:
|
||||||
@ -1,4 +1,4 @@
|
|||||||
# infrastructure/flux-system/kustomization-jellyfin.yaml
|
# clusters/atlas/flux-system/applications/jellyfin/kustomization.yaml
|
||||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||||
kind: Kustomization
|
kind: Kustomization
|
||||||
metadata:
|
metadata:
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
# clusters/atlas/flux-system/applications/jitsi/kustomization.yaml
|
||||||
|
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||||
|
kind: Kustomization
|
||||||
|
metadata:
|
||||||
|
name: jitsi
|
||||||
|
namespace: flux-system
|
||||||
|
spec:
|
||||||
|
interval: 10m
|
||||||
|
path: ./services/jitsi
|
||||||
|
targetNamespace: jitsi
|
||||||
|
prune: true
|
||||||
|
sourceRef:
|
||||||
|
kind: GitRepository
|
||||||
|
name: flux-system
|
||||||
|
namespace: flux-system
|
||||||
|
dependsOn:
|
||||||
|
- name: core
|
||||||
|
wait: true
|
||||||
|
timeout: 5m
|
||||||
15
clusters/atlas/flux-system/applications/kustomization.yaml
Normal file
15
clusters/atlas/flux-system/applications/kustomization.yaml
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
# clusters/atlas/flux-system/applications/kustomization.yaml
|
||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
resources:
|
||||||
|
- zot/kustomization.yaml
|
||||||
|
- gitea/kustomization.yaml
|
||||||
|
- vault/kustomization.yaml
|
||||||
|
- jitsi/kustomization.yaml
|
||||||
|
- crypto/kustomization.yaml
|
||||||
|
- monerod/kustomization.yaml
|
||||||
|
- pegasus/kustomization.yaml
|
||||||
|
- pegasus/image-automation.yaml
|
||||||
|
- jellyfin/kustomization.yaml
|
||||||
|
- xmr-miner/kustomization.yaml
|
||||||
|
- sui-metrics/kustomization.yaml
|
||||||
@ -1,4 +1,4 @@
|
|||||||
# infrastructure/flux-system/kustomization-monerod.yaml
|
# clusters/atlas/flux-system/applications/monerod/kustomization.yaml
|
||||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||||
kind: Kustomization
|
kind: Kustomization
|
||||||
metadata:
|
metadata:
|
||||||
@ -0,0 +1,20 @@
|
|||||||
|
# clusters/atlas/flux-system/applications/pegasus/image-automation.yaml
|
||||||
|
apiVersion: image.toolkit.fluxcd.io/v1beta1
|
||||||
|
kind: ImageUpdateAutomation
|
||||||
|
metadata:
|
||||||
|
name: pegasus
|
||||||
|
namespace: flux-system
|
||||||
|
spec:
|
||||||
|
interval: 1m0s
|
||||||
|
sourceRef:
|
||||||
|
kind: GitRepository
|
||||||
|
name: flux-system
|
||||||
|
git:
|
||||||
|
commit:
|
||||||
|
author:
|
||||||
|
email: ops@bstein.dev
|
||||||
|
name: flux-bot
|
||||||
|
messageTemplate: "chore(pegasus): update image to {{range .Updated.Images}}{{.}}{{end}}"
|
||||||
|
update:
|
||||||
|
strategy: Setters
|
||||||
|
path: ./services/pegasus
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
# clusters/atlas/flux-system/applications/pegasus/kustomization.yaml
|
||||||
|
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||||
|
kind: Kustomization
|
||||||
|
metadata:
|
||||||
|
name: pegasus
|
||||||
|
namespace: flux-system
|
||||||
|
spec:
|
||||||
|
interval: 10m
|
||||||
|
path: ./services/pegasus
|
||||||
|
targetNamespace: jellyfin
|
||||||
|
prune: true
|
||||||
|
sourceRef:
|
||||||
|
kind: GitRepository
|
||||||
|
name: flux-system
|
||||||
|
namespace: flux-system
|
||||||
|
dependsOn:
|
||||||
|
- name: core
|
||||||
|
wait: true
|
||||||
|
timeout: 5m
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
# clusters/atlas/flux-system/applications/sui-metrics/kustomization.yaml
|
||||||
|
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||||
|
kind: Kustomization
|
||||||
|
metadata:
|
||||||
|
name: sui-metrics
|
||||||
|
namespace: flux-system
|
||||||
|
spec:
|
||||||
|
interval: 10m
|
||||||
|
path: ./services/sui-metrics/overlays/atlas
|
||||||
|
prune: true
|
||||||
|
dependsOn:
|
||||||
|
- name: monitoring
|
||||||
|
sourceRef:
|
||||||
|
kind: GitRepository
|
||||||
|
name: flux-system
|
||||||
|
namespace: flux-system
|
||||||
|
wait: true
|
||||||
|
timeout: 5m
|
||||||
|
targetNamespace: sui-metrics
|
||||||
@ -1,4 +1,4 @@
|
|||||||
# infrastructure/flux-system/kustomization-vault.yaml
|
# clusters/atlas/flux-system/applications/vault/kustomization.yaml
|
||||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||||
kind: Kustomization
|
kind: Kustomization
|
||||||
metadata:
|
metadata:
|
||||||
@ -1,4 +1,4 @@
|
|||||||
# infrastructure/flux-system/kustomization-core.yaml
|
# clusters/atlas/flux-system/applications/xmr-miner/kustomization.yaml
|
||||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||||
kind: Kustomization
|
kind: Kustomization
|
||||||
metadata:
|
metadata:
|
||||||
@ -1,4 +1,4 @@
|
|||||||
# infrastructure/flux-system/kustomization-zot.yaml
|
# clusters/atlas/flux-system/applications/zot/kustomization.yaml
|
||||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||||
kind: Kustomization
|
kind: Kustomization
|
||||||
metadata:
|
metadata:
|
||||||
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
# This manifest was generated by flux. DO NOT EDIT.
|
# This manifest was generated by flux. DO NOT EDIT.
|
||||||
# Flux Version: v2.5.1
|
# Flux Version: v2.5.1f reconzaq1= zaq1= aq1= 1= w2cile kustomization flux-system --namespace flux-system --with-source
|
||||||
# Components: source-controller,kustomize-controller,helm-controller,notification-controller
|
# Components: source-controller,kustomize-controller,helm-controller,notification-controller
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Namespace
|
kind: Namespace
|
||||||
@ -8,7 +8,7 @@ metadata:
|
|||||||
spec:
|
spec:
|
||||||
interval: 1m0s
|
interval: 1m0s
|
||||||
ref:
|
ref:
|
||||||
branch: main
|
branch: restructure/hybrid-clusters
|
||||||
secretRef:
|
secretRef:
|
||||||
name: flux-system-gitea
|
name: flux-system-gitea
|
||||||
url: ssh://git@scm.bstein.dev:2242/bstein/titan-iac.git
|
url: ssh://git@scm.bstein.dev:2242/bstein/titan-iac.git
|
||||||
@ -20,7 +20,7 @@ metadata:
|
|||||||
namespace: flux-system
|
namespace: flux-system
|
||||||
spec:
|
spec:
|
||||||
interval: 10m0s
|
interval: 10m0s
|
||||||
path: ./
|
path: ./clusters/atlas/flux-system
|
||||||
prune: true
|
prune: true
|
||||||
sourceRef:
|
sourceRef:
|
||||||
kind: GitRepository
|
kind: GitRepository
|
||||||
8
clusters/atlas/flux-system/kustomization.yaml
Normal file
8
clusters/atlas/flux-system/kustomization.yaml
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
# clusters/atlas/flux-system/kustomization.yaml
|
||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
resources:
|
||||||
|
- gotk-components.yaml
|
||||||
|
- gotk-sync.yaml
|
||||||
|
- platform
|
||||||
|
- applications
|
||||||
15
clusters/atlas/flux-system/platform/core/kustomization.yaml
Normal file
15
clusters/atlas/flux-system/platform/core/kustomization.yaml
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
# clusters/atlas/flux-system/platform/core/kustomization.yaml
|
||||||
|
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||||
|
kind: Kustomization
|
||||||
|
metadata:
|
||||||
|
name: core
|
||||||
|
namespace: flux-system
|
||||||
|
spec:
|
||||||
|
interval: 10m
|
||||||
|
path: ./infrastructure/core
|
||||||
|
prune: true
|
||||||
|
sourceRef:
|
||||||
|
kind: GitRepository
|
||||||
|
name: flux-system
|
||||||
|
namespace: flux-system
|
||||||
|
wait: false
|
||||||
@ -1,4 +1,4 @@
|
|||||||
# infrastructure/flux-system/kustomization-helm.yaml
|
# clusters/atlas/flux-system/platform/helm/kustomization.yaml
|
||||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||||
kind: Kustomization
|
kind: Kustomization
|
||||||
metadata:
|
metadata:
|
||||||
9
clusters/atlas/flux-system/platform/kustomization.yaml
Normal file
9
clusters/atlas/flux-system/platform/kustomization.yaml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
# clusters/atlas/flux-system/platform/kustomization.yaml
|
||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
resources:
|
||||||
|
- core/kustomization.yaml
|
||||||
|
- helm/kustomization.yaml
|
||||||
|
- traefik/kustomization.yaml
|
||||||
|
- monitoring/kustomization.yaml
|
||||||
|
- longhorn-ui/kustomization.yaml
|
||||||
@ -1,3 +1,4 @@
|
|||||||
|
# clusters/atlas/flux-system/platform/longhorn-ui/kustomization.yaml
|
||||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||||
kind: Kustomization
|
kind: Kustomization
|
||||||
metadata:
|
metadata:
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
# clusters/atlas/flux-system/platform/monitoring/kustomization.yaml
|
||||||
|
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||||
|
kind: Kustomization
|
||||||
|
metadata:
|
||||||
|
name: monitoring
|
||||||
|
namespace: flux-system
|
||||||
|
spec:
|
||||||
|
interval: 10m
|
||||||
|
path: ./services/monitoring
|
||||||
|
prune: true
|
||||||
|
sourceRef:
|
||||||
|
kind: GitRepository
|
||||||
|
name: flux-system
|
||||||
|
wait: true
|
||||||
@ -0,0 +1,18 @@
|
|||||||
|
# clusters/atlas/flux-system/platform/traefik/kustomization.yaml
|
||||||
|
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||||
|
kind: Kustomization
|
||||||
|
metadata:
|
||||||
|
name: traefik
|
||||||
|
namespace: flux-system
|
||||||
|
spec:
|
||||||
|
interval: 10m
|
||||||
|
path: ./infrastructure/traefik
|
||||||
|
targetNamespace: traefik
|
||||||
|
prune: true
|
||||||
|
sourceRef:
|
||||||
|
kind: GitRepository
|
||||||
|
name: flux-system
|
||||||
|
namespace: flux-system
|
||||||
|
dependsOn:
|
||||||
|
- name: core
|
||||||
|
wait: true
|
||||||
7
clusters/atlas/platform/kustomization.yaml
Normal file
7
clusters/atlas/platform/kustomization.yaml
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
# clusters/atlas/platform/kustomization.yaml
|
||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
resources:
|
||||||
|
- ../../../infrastructure/modules/base
|
||||||
|
- ../../../infrastructure/modules/profiles/atlas-ha
|
||||||
|
- ../../../infrastructure/sources/cert-manager/letsencrypt.yaml
|
||||||
5
clusters/oceanus/README.md
Normal file
5
clusters/oceanus/README.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
# Oceanus Cluster Scaffold
|
||||||
|
|
||||||
|
This directory prepares the Flux and Kustomize layout for a future Oceanus-managed cluster.
|
||||||
|
Populate `flux-system/` with `gotk-components.yaml` and related manifests after running `flux bootstrap`.
|
||||||
|
Define node-specific resources under `infrastructure/modules/profiles/oceanus-validator/` and reference workloads in `applications/` as they come online.
|
||||||
4
clusters/oceanus/applications/kustomization.yaml
Normal file
4
clusters/oceanus/applications/kustomization.yaml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
# clusters/oceanus/applications/kustomization.yaml
|
||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
resources: []
|
||||||
9
clusters/oceanus/flux-system/kustomization.yaml
Normal file
9
clusters/oceanus/flux-system/kustomization.yaml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
# clusters/oceanus/flux-system/kustomization.yaml
|
||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
resources:
|
||||||
|
# Populate when oceanus cluster is bootstrapped with Flux.
|
||||||
|
# - gotk-components.yaml
|
||||||
|
# - gotk-sync.yaml
|
||||||
|
- ../platform
|
||||||
|
- ../applications
|
||||||
6
clusters/oceanus/platform/kustomization.yaml
Normal file
6
clusters/oceanus/platform/kustomization.yaml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
# clusters/oceanus/platform/kustomization.yaml
|
||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
resources:
|
||||||
|
- ../../infrastructure/modules/base
|
||||||
|
- ../../infrastructure/modules/profiles/oceanus-validator
|
||||||
16
docs/topology.md
Normal file
16
docs/topology.md
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
# Titan Homelab Topology
|
||||||
|
|
||||||
|
| Hostname | Role / Function | Managed By | Notes |
|
||||||
|
|------------|--------------------------------|---------------------|-------|
|
||||||
|
| titan-0a | Kubernetes control-plane | Flux (atlas cluster)| HA leader, tainted for control only |
|
||||||
|
| titan-0b | Kubernetes control-plane | Flux (atlas cluster)| Standby control node |
|
||||||
|
| titan-0c | Kubernetes control-plane | Flux (atlas cluster)| Standby control node |
|
||||||
|
| titan-04-19| Raspberry Pi workers | Flux (atlas cluster)| Workload nodes, labelled per hardware |
|
||||||
|
| titan-22 | GPU mini-PC (Jellyfin) | Flux + Ansible | NVIDIA runtime managed via `modules/profiles/atlas-ha` |
|
||||||
|
| titan-24 | Tethys hybrid node | Flux + Ansible | Runs SUI metrics via K8s, validator via Ansible |
|
||||||
|
| titan-db | HA control plane database | Ansible | PostgreSQL / etcd backing services |
|
||||||
|
| titan-jh | Jumphost & bastion | Ansible | Entry point / future KVM services |
|
||||||
|
| oceanus | Dedicated SUI validator host | Ansible / Flux prep | Baremetal validator workloads, exposes metrics to atlas; Kustomize scaffold under `clusters/oceanus/` |
|
||||||
|
| styx | Air-gapped workstation | Manual / Scripts | Remains isolated, scripts tracked in `hosts/styx` |
|
||||||
|
|
||||||
|
Use the `clusters/` directory for cluster-scoped state and the `hosts/` directory for baremetal orchestration.
|
||||||
2
hosts/group_vars/all.yaml
Normal file
2
hosts/group_vars/all.yaml
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
# hosts/group_vars/all.yaml
|
||||||
|
validator_version: latest
|
||||||
2
hosts/host_vars/titan-24.yaml
Normal file
2
hosts/host_vars/titan-24.yaml
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
# hosts/host_vars/titan-24.yaml
|
||||||
|
validator_compose_path: /opt/sui-validator
|
||||||
28
hosts/inventory/lab.yaml
Normal file
28
hosts/inventory/lab.yaml
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
# hosts/inventory/lab.yaml
|
||||||
|
# Replace ansible_host and ansible_user values with real connectivity details.
|
||||||
|
all:
|
||||||
|
children:
|
||||||
|
atlas:
|
||||||
|
hosts:
|
||||||
|
titan-24:
|
||||||
|
ansible_host: REPLACE_ME
|
||||||
|
ansible_user: ubuntu
|
||||||
|
roleset: tethys_hybrid
|
||||||
|
titan-22:
|
||||||
|
ansible_host: REPLACE_ME
|
||||||
|
ansible_user: debian
|
||||||
|
roleset: minipc_gpu
|
||||||
|
baremetal:
|
||||||
|
hosts:
|
||||||
|
titan-db:
|
||||||
|
ansible_host: REPLACE_ME
|
||||||
|
ansible_user: postgres
|
||||||
|
roleset: database
|
||||||
|
titan-jh:
|
||||||
|
ansible_host: REPLACE_ME
|
||||||
|
ansible_user: jump
|
||||||
|
roleset: jumphost
|
||||||
|
oceanus:
|
||||||
|
ansible_host: REPLACE_ME
|
||||||
|
ansible_user: validator
|
||||||
|
roleset: validator
|
||||||
29
hosts/playbooks/site.yaml
Normal file
29
hosts/playbooks/site.yaml
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
# hosts/playbooks/site.yaml
|
||||||
|
---
|
||||||
|
- name: Configure titan-db
|
||||||
|
hosts: titan-db
|
||||||
|
gather_facts: true
|
||||||
|
roles:
|
||||||
|
- common
|
||||||
|
- titan_db
|
||||||
|
|
||||||
|
- name: Configure titan-jh
|
||||||
|
hosts: titan-jh
|
||||||
|
gather_facts: true
|
||||||
|
roles:
|
||||||
|
- common
|
||||||
|
- titan_jh
|
||||||
|
|
||||||
|
- name: Configure oceanus validator host
|
||||||
|
hosts: oceanus
|
||||||
|
gather_facts: true
|
||||||
|
roles:
|
||||||
|
- common
|
||||||
|
- oceanus_base
|
||||||
|
|
||||||
|
- name: Prepare hybrid tethys node
|
||||||
|
hosts: titan-24
|
||||||
|
gather_facts: true
|
||||||
|
roles:
|
||||||
|
- common
|
||||||
|
- tethys_canary
|
||||||
9
hosts/roles/common/tasks/main.yaml
Normal file
9
hosts/roles/common/tasks/main.yaml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
# hosts/roles/common/tasks/main.yaml
|
||||||
|
---
|
||||||
|
- name: Ensure base packages present
|
||||||
|
ansible.builtin.package:
|
||||||
|
name:
|
||||||
|
- curl
|
||||||
|
- vim
|
||||||
|
state: present
|
||||||
|
tags: ['common', 'packages']
|
||||||
6
hosts/roles/oceanus_base/tasks/main.yaml
Normal file
6
hosts/roles/oceanus_base/tasks/main.yaml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
# hosts/roles/oceanus_base/tasks/main.yaml
|
||||||
|
---
|
||||||
|
- name: Placeholder for oceanus base configuration
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg: "Install validator prerequisites and monitoring exporters here."
|
||||||
|
tags: ['oceanus']
|
||||||
6
hosts/roles/tethys_canary/tasks/main.yaml
Normal file
6
hosts/roles/tethys_canary/tasks/main.yaml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
# hosts/roles/tethys_canary/tasks/main.yaml
|
||||||
|
---
|
||||||
|
- name: Placeholder for SUI validator container runtime setup
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg: "Configure container runtime and validator compose stack here."
|
||||||
|
tags: ['tethys', 'validator']
|
||||||
6
hosts/roles/titan_db/tasks/main.yaml
Normal file
6
hosts/roles/titan_db/tasks/main.yaml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
# hosts/roles/titan_db/tasks/main.yaml
|
||||||
|
---
|
||||||
|
- name: Placeholder for titan-db provisioning
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg: "Install database packages, configure backups, and manage users here."
|
||||||
|
tags: ['titan_db']
|
||||||
6
hosts/roles/titan_jh/tasks/main.yaml
Normal file
6
hosts/roles/titan_jh/tasks/main.yaml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
# hosts/roles/titan_jh/tasks/main.yaml
|
||||||
|
---
|
||||||
|
- name: Placeholder for jumphost hardening
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg: "Harden SSH, manage bastion tooling, and configure audit logging here."
|
||||||
|
tags: ['jumphost']
|
||||||
2
hosts/styx/README.md
Normal file
2
hosts/styx/README.md
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
# hosts/styx/README.md
|
||||||
|
Styx is air-gapped; provisioning scripts live under `scripts/`.
|
||||||
@ -1,5 +0,0 @@
|
|||||||
# infrastructure/core/gpu/daemonsets/profiles/jetson-only/kustomization.yaml
|
|
||||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
|
||||||
kind: Kustomization
|
|
||||||
resources:
|
|
||||||
- ../../device-plugin-jetson
|
|
||||||
@ -1,6 +0,0 @@
|
|||||||
# infrastructure/core/gpu/daemonsets/profiles/minipc-and-jetson/kustomization.yaml
|
|
||||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
|
||||||
kind: Kustomization
|
|
||||||
resources:
|
|
||||||
- ../../device-plugin-minipc
|
|
||||||
- ../../device-plugin-jetson
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
# infrastructure/core/gpu/daemonsets/profiles/minipc-only/kustomization.yaml
|
|
||||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
|
||||||
kind: Kustomization
|
|
||||||
resources:
|
|
||||||
- ../../device-plugin-minipc
|
|
||||||
@ -2,7 +2,6 @@
|
|||||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
kind: Kustomization
|
kind: Kustomization
|
||||||
resources:
|
resources:
|
||||||
- base
|
- ../modules/base
|
||||||
# - gpu/profiles/jetson-only
|
- ../modules/profiles/atlas-ha
|
||||||
# - gpu/profiles/minipc-and-jetson
|
- ../sources/cert-manager/letsencrypt.yaml
|
||||||
- gpu/profiles/minipc-only
|
|
||||||
|
|||||||
@ -1,22 +0,0 @@
|
|||||||
# infrastructure/flux-system/kustomization-core.yaml
|
|
||||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
|
||||||
kind: Kustomization
|
|
||||||
metadata:
|
|
||||||
name: core
|
|
||||||
namespace: flux-system
|
|
||||||
spec:
|
|
||||||
interval: 10m
|
|
||||||
path: ./infrastructure/core
|
|
||||||
prune: true
|
|
||||||
sourceRef:
|
|
||||||
kind: GitRepository
|
|
||||||
name: flux-system
|
|
||||||
namespace: flux-system
|
|
||||||
wait: true
|
|
||||||
|
|
||||||
# Only wait for the NVIDIA device-plugin DaemonSet on titan-22
|
|
||||||
healthChecks:
|
|
||||||
- apiVersion: apps/v1
|
|
||||||
kind: DaemonSet
|
|
||||||
name: nvidia-device-plugin-minipc
|
|
||||||
namespace: kube-system
|
|
||||||
@ -2,15 +2,4 @@
|
|||||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
kind: Kustomization
|
kind: Kustomization
|
||||||
resources:
|
resources:
|
||||||
- gotk-components.yaml
|
- ../clusters/atlas/flux-system
|
||||||
- gotk-sync.yaml
|
|
||||||
- kustomization-zot.yaml
|
|
||||||
- kustomization-core.yaml
|
|
||||||
- kustomization-helm.yaml
|
|
||||||
- kustomization-gitea.yaml
|
|
||||||
- kustomization-vault.yaml
|
|
||||||
- kustomization-crypto.yaml
|
|
||||||
- kustomization-monerod.yaml
|
|
||||||
- kustomization-jellyfin.yaml
|
|
||||||
- kustomization-xmr-miner.yaml
|
|
||||||
- kustomization-longhorn-ui.yaml
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
# infrastructure/core/base/kustomization.yaml
|
# infrastructure/modules/base/kustomization.yaml
|
||||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
kind: Kustomization
|
kind: Kustomization
|
||||||
resources:
|
resources:
|
||||||
@ -1,4 +1,4 @@
|
|||||||
# infrastructure/core/base/priorityclass/kustomization.yaml
|
# infrastructure/modules/base/priorityclass/kustomization.yaml
|
||||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
kind: Kustomization
|
kind: Kustomization
|
||||||
resources:
|
resources:
|
||||||
@ -1,4 +1,4 @@
|
|||||||
# infrastructure/core/base/priorityclass/scavenger.yaml
|
# infrastructure/modules/base/priorityclass/scavenger.yaml
|
||||||
apiVersion: scheduling.k8s.io/v1
|
apiVersion: scheduling.k8s.io/v1
|
||||||
kind: PriorityClass
|
kind: PriorityClass
|
||||||
metadata:
|
metadata:
|
||||||
@ -1,4 +1,4 @@
|
|||||||
# infrastructure/core/base/storageclass/kustomization.yaml
|
# infrastructure/modules/base/runtimeclass/kustomization.yaml
|
||||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
kind: Kustomization
|
kind: Kustomization
|
||||||
resources:
|
resources:
|
||||||
@ -1,4 +1,4 @@
|
|||||||
# services/jellyfin/runtimeclass.yaml
|
# infrastructure/modules/base/runtimeclass/runtimeclass.yaml
|
||||||
apiVersion: node.k8s.io/v1
|
apiVersion: node.k8s.io/v1
|
||||||
kind: RuntimeClass
|
kind: RuntimeClass
|
||||||
metadata:
|
metadata:
|
||||||
@ -1,4 +1,4 @@
|
|||||||
# infrastructure/core/base/storageclass/asteria.yaml
|
# infrastructure/modules/base/storageclass/asteria.yaml
|
||||||
apiVersion: storage.k8s.io/v1
|
apiVersion: storage.k8s.io/v1
|
||||||
kind: StorageClass
|
kind: StorageClass
|
||||||
metadata:
|
metadata:
|
||||||
@ -8,6 +8,9 @@ parameters:
|
|||||||
fromBackup: ""
|
fromBackup: ""
|
||||||
numberOfReplicas: "2"
|
numberOfReplicas: "2"
|
||||||
staleReplicaTimeout: "30"
|
staleReplicaTimeout: "30"
|
||||||
|
fsType: "ext4"
|
||||||
|
replicaAutoBalance: "least-effort"
|
||||||
|
dataLocality: "disabled"
|
||||||
provisioner: driver.longhorn.io
|
provisioner: driver.longhorn.io
|
||||||
reclaimPolicy: Retain
|
reclaimPolicy: Retain
|
||||||
allowVolumeExpansion: true
|
allowVolumeExpansion: true
|
||||||
@ -1,4 +1,4 @@
|
|||||||
# infrastructure/core/base/storageclass/astreae.yaml
|
# infrastructure/modules/base/storageclass/astreae.yaml
|
||||||
apiVersion: storage.k8s.io/v1
|
apiVersion: storage.k8s.io/v1
|
||||||
kind: StorageClass
|
kind: StorageClass
|
||||||
metadata:
|
metadata:
|
||||||
@ -1,4 +1,4 @@
|
|||||||
# infrastructure/core/base/storageclass/kustomization.yaml
|
# infrastructure/modules/base/storageclass/kustomization.yaml
|
||||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
kind: Kustomization
|
kind: Kustomization
|
||||||
resources:
|
resources:
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
# infrastructure/modules/profiles/atlas-ha/kustomization.yaml
|
||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
resources:
|
||||||
|
- ../components/device-plugin-jetson
|
||||||
|
- ../components/device-plugin-minipc
|
||||||
|
- ../components/device-plugin-tethys
|
||||||
@ -1,4 +1,4 @@
|
|||||||
# infrastructure/core/gpu/daemonsets/device-plugin-jetson/daemonset.yaml
|
# infrastructure/modules/profiles/components/device-plugin-jetson/daemonset.yaml
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1
|
||||||
kind: DaemonSet
|
kind: DaemonSet
|
||||||
metadata:
|
metadata:
|
||||||
@ -1,4 +1,4 @@
|
|||||||
# infrastructure/core/gpu/daemonsets/device-plugin-jetson/kustomization.yaml
|
# infrastructure/modules/profiles/components/device-plugin-jetson/kustomization.yaml
|
||||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
kind: Kustomization
|
kind: Kustomization
|
||||||
resources:
|
resources:
|
||||||
@ -1,4 +1,4 @@
|
|||||||
# infrastructure/core/gpu/daemonsets/device-plugin-minipc/daemonset.yaml
|
# infrastructure/modules/profiles/components/device-plugin-minipc/daemonset.yaml
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1
|
||||||
kind: DaemonSet
|
kind: DaemonSet
|
||||||
metadata:
|
metadata:
|
||||||
@ -24,7 +24,6 @@ spec:
|
|||||||
tolerations:
|
tolerations:
|
||||||
- operator: Exists
|
- operator: Exists
|
||||||
priorityClassName: system-node-critical
|
priorityClassName: system-node-critical
|
||||||
runtimeClassName: nvidia
|
|
||||||
containers:
|
containers:
|
||||||
- name: nvidia-device-plugin-ctr
|
- name: nvidia-device-plugin-ctr
|
||||||
image: nvcr.io/nvidia/k8s-device-plugin:v0.16.2
|
image: nvcr.io/nvidia/k8s-device-plugin:v0.16.2
|
||||||
@ -1,4 +1,4 @@
|
|||||||
# infrastructure/core/gpu/daemonsets/device-plugin-minipc/kustomization.yaml
|
# infrastructure/modules/profiles/components/device-plugin-minipc/kustomization.yaml
|
||||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
kind: Kustomization
|
kind: Kustomization
|
||||||
resources:
|
resources:
|
||||||
@ -0,0 +1,49 @@
|
|||||||
|
# infrastructure/modules/profiles/components/device-plugin-tethys/daemonset.yaml
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: DaemonSet
|
||||||
|
metadata:
|
||||||
|
name: nvidia-device-plugin-tethys
|
||||||
|
namespace: kube-system
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: nvidia-device-plugin
|
||||||
|
app.kubernetes.io/instance: titan24
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app.kubernetes.io/name: nvidia-device-plugin
|
||||||
|
app.kubernetes.io/instance: titan24
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: nvidia-device-plugin
|
||||||
|
app.kubernetes.io/instance: titan24
|
||||||
|
spec:
|
||||||
|
nodeSelector:
|
||||||
|
kubernetes.io/hostname: titan-24
|
||||||
|
kubernetes.io/arch: amd64
|
||||||
|
tolerations:
|
||||||
|
- operator: Exists
|
||||||
|
priorityClassName: system-node-critical
|
||||||
|
runtimeClassName: nvidia
|
||||||
|
containers:
|
||||||
|
- name: nvidia-device-plugin-ctr
|
||||||
|
image: nvcr.io/nvidia/k8s-device-plugin:v0.16.2
|
||||||
|
imagePullPolicy: IfNotPresent
|
||||||
|
args:
|
||||||
|
- "--fail-on-init-error=false"
|
||||||
|
- "--device-list-strategy=envvar"
|
||||||
|
- "--mig-strategy=none"
|
||||||
|
securityContext:
|
||||||
|
privileged: true
|
||||||
|
env:
|
||||||
|
- name: NVIDIA_VISIBLE_DEVICES
|
||||||
|
value: "all"
|
||||||
|
- name: NVIDIA_DRIVER_CAPABILITIES
|
||||||
|
value: "compute,video,utility"
|
||||||
|
volumeMounts:
|
||||||
|
- name: device-plugin
|
||||||
|
mountPath: /var/lib/kubelet/device-plugins
|
||||||
|
volumes:
|
||||||
|
- name: device-plugin
|
||||||
|
hostPath:
|
||||||
|
path: /var/lib/kubelet/device-plugins
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
# infrastructure/modules/profiles/components/device-plugin-tethys/kustomization.yaml
|
||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
resources:
|
||||||
|
- daemonset.yaml
|
||||||
@ -0,0 +1,4 @@
|
|||||||
|
# infrastructure/modules/profiles/oceanus-validator/kustomization.yaml
|
||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
resources: []
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
# infrastructure/modules/profiles/tethys-hybrid/kustomization.yaml
|
||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
resources:
|
||||||
|
- ../components/device-plugin-tethys
|
||||||
@ -4,7 +4,7 @@ metadata:
|
|||||||
name: letsencrypt
|
name: letsencrypt
|
||||||
spec:
|
spec:
|
||||||
acme:
|
acme:
|
||||||
email: you@bstein.dev
|
email: brad.stein@gmail.com
|
||||||
server: https://acme-v02.api.letsencrypt.org/directory
|
server: https://acme-v02.api.letsencrypt.org/directory
|
||||||
privateKeySecretRef:
|
privateKeySecretRef:
|
||||||
name: letsencrypt-account-key
|
name: letsencrypt-account-key
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
# infrastructure/sources/helm/grafana.yaml
|
||||||
apiVersion: source.toolkit.fluxcd.io/v1
|
apiVersion: source.toolkit.fluxcd.io/v1
|
||||||
kind: HelmRepository
|
kind: HelmRepository
|
||||||
metadata:
|
metadata:
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
# infrastructure/sources/helm/hashicorp.yaml
|
||||||
apiVersion: source.toolkit.fluxcd.io/v1
|
apiVersion: source.toolkit.fluxcd.io/v1
|
||||||
kind: HelmRepository
|
kind: HelmRepository
|
||||||
metadata:
|
metadata:
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
# infrastructure/sources/helm/jetstack.yaml
|
||||||
apiVersion: source.toolkit.fluxcd.io/v1
|
apiVersion: source.toolkit.fluxcd.io/v1
|
||||||
kind: HelmRepository
|
kind: HelmRepository
|
||||||
metadata:
|
metadata:
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
# infrastructure/sources/helm/prometheus.yaml
|
||||||
apiVersion: source.toolkit.fluxcd.io/v1
|
apiVersion: source.toolkit.fluxcd.io/v1
|
||||||
kind: HelmRepository
|
kind: HelmRepository
|
||||||
metadata:
|
metadata:
|
||||||
|
|||||||
9
infrastructure/sources/helm/victoria-metrics.yaml
Normal file
9
infrastructure/sources/helm/victoria-metrics.yaml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
# infrastructure/sources/helm/victoria-metrics.yaml
|
||||||
|
apiVersion: source.toolkit.fluxcd.io/v1
|
||||||
|
kind: HelmRepository
|
||||||
|
metadata:
|
||||||
|
name: victoria-metrics
|
||||||
|
namespace: flux-system
|
||||||
|
spec:
|
||||||
|
interval: 1h
|
||||||
|
url: https://victoriametrics.github.io/helm-charts/
|
||||||
@ -35,6 +35,12 @@ items:
|
|||||||
- --entrypoints.web.address=:80
|
- --entrypoints.web.address=:80
|
||||||
- --entrypoints.websecure.address=:443
|
- --entrypoints.websecure.address=:443
|
||||||
- --api.dashboard=true
|
- --api.dashboard=true
|
||||||
|
- --metrics.prometheus=true
|
||||||
|
- --metrics.prometheus.addEntryPointsLabels=true
|
||||||
|
- --metrics.prometheus.addRoutersLabels=true
|
||||||
|
- --metrics.prometheus.addServicesLabels=true
|
||||||
|
- --entrypoints.metrics.address=:9100
|
||||||
|
- --metrics.prometheus.entryPoint=metrics
|
||||||
image: traefik:v3.3.3
|
image: traefik:v3.3.3
|
||||||
imagePullPolicy: IfNotPresent
|
imagePullPolicy: IfNotPresent
|
||||||
name: traefik
|
name: traefik
|
||||||
@ -48,6 +54,9 @@ items:
|
|||||||
- containerPort: 8080
|
- containerPort: 8080
|
||||||
name: admin
|
name: admin
|
||||||
protocol: TCP
|
protocol: TCP
|
||||||
|
- containerPort: 9100
|
||||||
|
name: metrics
|
||||||
|
protocol: TCP
|
||||||
terminationMessagePath: /dev/termination-log
|
terminationMessagePath: /dev/termination-log
|
||||||
terminationMessagePolicy: File
|
terminationMessagePolicy: File
|
||||||
dnsPolicy: ClusterFirst
|
dnsPolicy: ClusterFirst
|
||||||
|
|||||||
@ -9,3 +9,4 @@ resources:
|
|||||||
- serviceaccount.yaml
|
- serviceaccount.yaml
|
||||||
- clusterrole.yaml
|
- clusterrole.yaml
|
||||||
- clusterrolebinding.yaml
|
- clusterrolebinding.yaml
|
||||||
|
- service.yaml
|
||||||
|
|||||||
20
infrastructure/traefik/service.yaml
Normal file
20
infrastructure/traefik/service.yaml
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
# infrastructure/traefik/service.yaml
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: traefik-metrics
|
||||||
|
namespace: traefik
|
||||||
|
labels:
|
||||||
|
app: traefik
|
||||||
|
annotations:
|
||||||
|
prometheus.io/scrape: "true"
|
||||||
|
prometheus.io/port: "9100"
|
||||||
|
prometheus.io/path: "/metrics"
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
selector:
|
||||||
|
app: traefik
|
||||||
|
ports:
|
||||||
|
- name: metrics
|
||||||
|
port: 9100
|
||||||
|
targetPort: metrics
|
||||||
2
scripts/longhorn_volume_usage.fish
Normal file → Executable file
2
scripts/longhorn_volume_usage.fish
Normal file → Executable file
@ -1,3 +1,5 @@
|
|||||||
|
#!/usr/bin/env fish
|
||||||
|
|
||||||
function pvc-usage --description "Show Longhorn PVC usage (human-readable) mapped to namespace/name"
|
function pvc-usage --description "Show Longhorn PVC usage (human-readable) mapped to namespace/name"
|
||||||
begin
|
begin
|
||||||
kubectl -n longhorn-system get volumes.longhorn.io -o json \
|
kubectl -n longhorn-system get volumes.longhorn.io -o json \
|
||||||
|
|||||||
218
scripts/styx_kioskification.sh
Normal file
218
scripts/styx_kioskification.sh
Normal file
@ -0,0 +1,218 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# 0) Create dedicated user if it doesn't exist
|
||||||
|
if ! id -u styx >/dev/null 2>&1; then
|
||||||
|
sudo useradd -m -s /bin/bash styx
|
||||||
|
echo "Created user 'styx'"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 1) App directory
|
||||||
|
sudo mkdir -p /opt/styx-kiosk/keys
|
||||||
|
sudo chown -R styx:styx /opt/styx-kiosk
|
||||||
|
|
||||||
|
# 2) Drop the kiosk app (written below) into place
|
||||||
|
sudo tee /opt/styx-kiosk/kiosk.py >/dev/null <<'PY'
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
import base64, json, os, subprocess, threading, tempfile
|
||||||
|
from datetime import datetime
|
||||||
|
import tkinter as tk
|
||||||
|
from tkinter import ttk, messagebox
|
||||||
|
|
||||||
|
APP_TITLE = "STYX Airgap Signer"
|
||||||
|
CAMERA_DEV = os.environ.get("ZBAR_DEV", "/dev/video0")
|
||||||
|
KEY_PATH = os.environ.get("STYX_KEY", "/vault/keys/signer_ed25519.pem") # in the LUKS vault
|
||||||
|
ALGO = os.environ.get("STYX_ALGO", "ed25519") # or 'secp256r1'
|
||||||
|
QR_TMP = "/tmp/styx_signed.png"
|
||||||
|
|
||||||
|
def zbar_scan_oneshot():
|
||||||
|
# --raw -> data only; --nodisplay -> no preview window; --oneshot -> exit after first code
|
||||||
|
# (zbarcam supports --oneshot; prints one code and exits). :contentReference[oaicite:2]{index=2}
|
||||||
|
cmd = ["zbarcam", "--raw", "--nodisplay", "--oneshot", CAMERA_DEV]
|
||||||
|
try:
|
||||||
|
out = subprocess.check_output(cmd, text=True, timeout=30)
|
||||||
|
out = out.strip()
|
||||||
|
return out if out else None
|
||||||
|
except Exception as e:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def openssl_pub_der_b64(key_path):
|
||||||
|
der = subprocess.check_output(["openssl","pkey","-in",key_path,"-pubout","-outform","DER"])
|
||||||
|
return base64.b64encode(der).decode()
|
||||||
|
|
||||||
|
def sign_bytes(msg: bytes, key_path: str, algo: str) -> bytes:
|
||||||
|
with tempfile.NamedTemporaryFile(delete=False) as f:
|
||||||
|
f.write(msg)
|
||||||
|
msg_path = f.name
|
||||||
|
try:
|
||||||
|
if algo.lower() == "ed25519":
|
||||||
|
# Ed25519 expects raw message; OpenSSL handles hashing internally.
|
||||||
|
sig = subprocess.check_output(
|
||||||
|
["openssl","pkeyutl","-sign","-inkey",key_path,"-rawin","-in",msg_path]
|
||||||
|
)
|
||||||
|
return sig
|
||||||
|
elif algo.lower() in ("secp256r1","prime256v1","p256"):
|
||||||
|
# ECDSA over P-256; hash with SHA-256; OpenSSL returns DER-encoded (r,s)
|
||||||
|
sig = subprocess.check_output(
|
||||||
|
["openssl","dgst","-sha256","-sign",key_path,msg_path]
|
||||||
|
)
|
||||||
|
return sig
|
||||||
|
else:
|
||||||
|
raise RuntimeError(f"Unsupported algo: {algo}")
|
||||||
|
finally:
|
||||||
|
try: os.unlink(msg_path)
|
||||||
|
except: pass
|
||||||
|
|
||||||
|
def make_signed_envelope(scanned_text: str, key_path: str, algo: str) -> dict:
|
||||||
|
# Accept either raw string or JSON with 'tx_bytes' (base64) or 'message'
|
||||||
|
try:
|
||||||
|
obj = json.loads(scanned_text)
|
||||||
|
if "tx_bytes" in obj:
|
||||||
|
msg = base64.b64decode(obj["tx_bytes"])
|
||||||
|
elif "message" in obj:
|
||||||
|
msg = obj["message"].encode()
|
||||||
|
else:
|
||||||
|
# If it's JSON but doesn't carry known fields, sign canonical JSON bytes
|
||||||
|
msg = json.dumps(obj, sort_keys=True, separators=(",",":")).encode()
|
||||||
|
request_id = obj.get("request_id")
|
||||||
|
except Exception:
|
||||||
|
# Non-JSON → treat the scanned text as the message to sign
|
||||||
|
msg = scanned_text.encode()
|
||||||
|
request_id = None
|
||||||
|
|
||||||
|
sig = sign_bytes(msg, key_path, algo)
|
||||||
|
env = {
|
||||||
|
"algo": algo.lower(),
|
||||||
|
"signature_b64": base64.b64encode(sig).decode(),
|
||||||
|
"pubkey_spki_der_b64": openssl_pub_der_b64(key_path),
|
||||||
|
"payload_sha256_b64": base64.b64encode(subprocess.check_output(["openssl","dgst","-sha256","-binary"], input=msg)).decode(),
|
||||||
|
"quote_raw": scanned_text,
|
||||||
|
"request_id": request_id,
|
||||||
|
"device": os.uname().nodename,
|
||||||
|
"ts_utc": datetime.utcnow().isoformat(timespec="seconds") + "Z",
|
||||||
|
}
|
||||||
|
return env
|
||||||
|
|
||||||
|
def qrencode_to_file(text: str, path: str):
|
||||||
|
# Use qrencode CLI to render a PNG we can display.
|
||||||
|
subprocess.run(["qrencode","-l","M","-s","16","-t","PNG","-o",path], input=text.encode(), check=True)
|
||||||
|
|
||||||
|
class App(tk.Tk):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__()
|
||||||
|
self.title(APP_TITLE)
|
||||||
|
self.attributes("-fullscreen", True)
|
||||||
|
self.configure(background="black")
|
||||||
|
self.bind("<Escape>", lambda e: self.quit()) # for maintenance only
|
||||||
|
|
||||||
|
s = ttk.Style(self)
|
||||||
|
s.configure("Big.TButton", font=("DejaVu Sans", 48), padding=24)
|
||||||
|
s.configure("Big.TLabel", font=("DejaVu Sans", 32), foreground="white", background="black")
|
||||||
|
|
||||||
|
self.container = tk.Frame(self, bg="black")
|
||||||
|
self.container.pack(expand=True, fill="both")
|
||||||
|
|
||||||
|
self.status = ttk.Label(self.container, text="Ready", style="Big.TLabel")
|
||||||
|
self.status.pack(pady=20)
|
||||||
|
|
||||||
|
self.scan_btn = ttk.Button(self.container, text="SCAN", style="Big.TButton", command=self.start_scan)
|
||||||
|
self.scan_btn.pack(pady=20)
|
||||||
|
|
||||||
|
self.image_label = tk.Label(self.container, bg="black")
|
||||||
|
self.image_label.pack(pady=10)
|
||||||
|
|
||||||
|
self.new_btn = ttk.Button(self.container, text="NEW SCAN", style="Big.TButton", command=self.reset)
|
||||||
|
self.new_btn.pack_forget()
|
||||||
|
|
||||||
|
self.note = ttk.Label(self.container, text="", style="Big.TLabel")
|
||||||
|
self.note.pack(pady=10)
|
||||||
|
|
||||||
|
if not os.path.exists(KEY_PATH):
|
||||||
|
self.status.config(text=f"Key not found at {KEY_PATH}\nInsert/unlock vault to proceed.")
|
||||||
|
|
||||||
|
def reset(self):
|
||||||
|
self.image_label.configure(image="")
|
||||||
|
self.image_label.image = None
|
||||||
|
self.new_btn.pack_forget()
|
||||||
|
self.note.config(text="")
|
||||||
|
self.status.config(text="Ready")
|
||||||
|
self.scan_btn.config(state="normal")
|
||||||
|
|
||||||
|
def start_scan(self):
|
||||||
|
if not os.path.exists(KEY_PATH):
|
||||||
|
messagebox.showerror("Key missing", f"Signing key not found at:\n{KEY_PATH}\nUnlock your vault.")
|
||||||
|
return
|
||||||
|
self.status.config(text="Scanning…")
|
||||||
|
self.scan_btn.config(state="disabled")
|
||||||
|
threading.Thread(target=self._do_scan_and_sign, daemon=True).start()
|
||||||
|
|
||||||
|
def _do_scan_and_sign(self):
|
||||||
|
scanned = zbar_scan_oneshot()
|
||||||
|
if not scanned:
|
||||||
|
self.after(0, self._scan_failed)
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
envelope = make_signed_envelope(scanned, KEY_PATH, ALGO)
|
||||||
|
payload = json.dumps(envelope, separators=(",",":"))
|
||||||
|
qrencode_to_file(payload, QR_TMP)
|
||||||
|
self.after(0, self._show_qr, envelope)
|
||||||
|
except Exception as e:
|
||||||
|
self.after(0, lambda: self._error(str(e)))
|
||||||
|
|
||||||
|
def _scan_failed(self):
|
||||||
|
self.status.config(text="No QR detected. Try again.")
|
||||||
|
self.scan_btn.config(state="normal")
|
||||||
|
|
||||||
|
def _show_qr(self, envelope):
|
||||||
|
# Display the PNG produced by qrencode
|
||||||
|
try:
|
||||||
|
img = tk.PhotoImage(file=QR_TMP)
|
||||||
|
self.image_label.configure(image=img)
|
||||||
|
self.image_label.image = img
|
||||||
|
except Exception as e:
|
||||||
|
self.status.config(text=f"QR render failed: {e}")
|
||||||
|
self.scan_btn.config(state="normal")
|
||||||
|
return
|
||||||
|
self.status.config(text="Signed. Show this QR to your online box.")
|
||||||
|
self.note.config(text=f"Algo: {envelope['algo']} Host: {envelope['device']}")
|
||||||
|
self.new_btn.pack(pady=20)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
App().mainloop()
|
||||||
|
PY
|
||||||
|
sudo chmod +x /opt/styx-kiosk/kiosk.py
|
||||||
|
sudo chown -R styx:styx /opt/styx-kiosk
|
||||||
|
|
||||||
|
# 3) Minimal X session: openbox + kiosk; no mouse pointer
|
||||||
|
sudo -u styx tee /home/styx/.xinitrc >/dev/null <<'XRC'
|
||||||
|
xset -dpms
|
||||||
|
xset s off
|
||||||
|
xset s noblank
|
||||||
|
# If 'unclutter' is installed, uncomment the next line to hide cursor:
|
||||||
|
# unclutter -idle 0 -root &
|
||||||
|
openbox-session &
|
||||||
|
/opt/styx-kiosk/kiosk.py
|
||||||
|
XRC
|
||||||
|
sudo chown styx:styx /home/styx/.xinitrc
|
||||||
|
sudo chmod 0755 /home/styx/.xinitrc
|
||||||
|
|
||||||
|
# 4) Autologin the 'styx' user on tty1, auto-start X
|
||||||
|
sudo mkdir -p /etc/systemd/system/getty@tty1.service.d
|
||||||
|
sudo tee /etc/systemd/system/getty@tty1.service.d/override.conf >/dev/null <<'OVR'
|
||||||
|
[Service]
|
||||||
|
ExecStart=
|
||||||
|
ExecStart=-/sbin/agetty --autologin styx --noclear %I $TERM
|
||||||
|
Type=idle
|
||||||
|
OVR
|
||||||
|
|
||||||
|
sudo -u styx tee -a /home/styx/.bash_profile >/dev/null <<'BRC'
|
||||||
|
# Start X on the first tty automatically, headless
|
||||||
|
if [ -z "$DISPLAY" ] && [ "$(tty)" = "/dev/tty1" ]; then
|
||||||
|
exec startx -- -nocursor
|
||||||
|
fi
|
||||||
|
BRC
|
||||||
|
|
||||||
|
sudo systemctl daemon-reload
|
||||||
|
sudo systemctl enable getty@tty1.service
|
||||||
|
|
||||||
|
echo "Done. Reboot to try the kiosk."
|
||||||
195
scripts/styx_prep.sh
Executable file
195
scripts/styx_prep.sh
Executable file
@ -0,0 +1,195 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# === CONFIG ===
|
||||||
|
STYX_USER="styx"
|
||||||
|
STYX_PASS="TempPass#123" # change at first login
|
||||||
|
STYX_HOSTNAME="styx"
|
||||||
|
SSH_PUBKEY="" # e.g., 'ssh-ed25519 AAAA... your@host' (optional)
|
||||||
|
|
||||||
|
# === helpers ===
|
||||||
|
require_root() {
|
||||||
|
if [[ $EUID -ne 0 ]]; then exec sudo -E "$0" "$@"; fi
|
||||||
|
}
|
||||||
|
|
||||||
|
ensure_binfmt_arm64() {
|
||||||
|
# If binfmt for arm64 isn't registered, register it via Docker (idempotent).
|
||||||
|
if [[ ! -e /proc/sys/fs/binfmt_misc/qemu-aarch64 ]]; then
|
||||||
|
command -v docker >/dev/null || { echo "Docker required to register binfmt (sudo pacman -S docker)"; exit 1; }
|
||||||
|
sudo systemctl enable --now docker >/dev/null 2>&1 || true
|
||||||
|
sudo docker run --rm --privileged tonistiigi/binfmt --install arm64
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
find_parts() {
|
||||||
|
BOOT=$(lsblk -o LABEL,PATH -nr | awk '$1=="system-boot"{print $2}' | head -n1)
|
||||||
|
ROOT=$(lsblk -o LABEL,PATH -nr | awk '$1=="writable"{print $2}' | head -n1)
|
||||||
|
if [[ -z "${BOOT:-}" || -z "${ROOT:-}" ]]; then
|
||||||
|
echo "Could not find 'system-boot'/'writable' on any device."
|
||||||
|
lsblk -o NAME,SIZE,FSTYPE,LABEL,PATH -nr
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
mount_parts() {
|
||||||
|
mkdir -p /mnt/pi-boot /mnt/pi-root
|
||||||
|
mount "$ROOT" /mnt/pi-root
|
||||||
|
mount "$BOOT" /mnt/pi-boot
|
||||||
|
|
||||||
|
# Bind only what we need (avoid /run to prevent postinst fights)
|
||||||
|
for d in dev dev/pts proc sys; do mount --bind "/$d" "/mnt/pi-root/$d"; done
|
||||||
|
|
||||||
|
# Ubuntu images use a resolv.conf symlink—replace with a real file
|
||||||
|
if [[ -L /mnt/pi-root/etc/resolv.conf || ! -e /mnt/pi-root/etc/resolv.conf ]]; then
|
||||||
|
rm -f /mnt/pi-root/etc/resolv.conf
|
||||||
|
cat /etc/resolv.conf > /mnt/pi-root/etc/resolv.conf
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
prep_chroot() {
|
||||||
|
# Block service starts inside chroot (no systemd there)
|
||||||
|
cat >/mnt/pi-root/usr/sbin/policy-rc.d <<'EOF'
|
||||||
|
#!/bin/sh
|
||||||
|
exit 101
|
||||||
|
EOF
|
||||||
|
chmod +x /mnt/pi-root/usr/sbin/policy-rc.d
|
||||||
|
|
||||||
|
# All the work happens inside the ARM64 rootfs
|
||||||
|
CHCMD=$(cat <<'EOS'
|
||||||
|
set -euo pipefail
|
||||||
|
export DEBIAN_FRONTEND=noninteractive TZ=Etc/UTC
|
||||||
|
# Ensure sbin is in PATH so user/group tools work
|
||||||
|
export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
|
||||||
|
|
||||||
|
apt-get update
|
||||||
|
apt-get -y full-upgrade
|
||||||
|
|
||||||
|
# Remove snaps and keep them gone (Ubuntu for Pi ships with snaps)
|
||||||
|
apt-get -y purge snapd || true
|
||||||
|
rm -rf /snap /var/snap /var/lib/snapd /home/*/snap || true
|
||||||
|
mkdir -p /etc/apt/preferences.d
|
||||||
|
printf 'Package: snapd\nPin: release *\nPin-Priority: -10\n' > /etc/apt/preferences.d/nosnap.pref
|
||||||
|
|
||||||
|
# Ensure user/group tools exist
|
||||||
|
apt-get install -y passwd adduser || true
|
||||||
|
getent group i2c >/dev/null || /usr/sbin/groupadd i2c
|
||||||
|
|
||||||
|
# Base packages
|
||||||
|
BASE_PKGS="openssh-server git i2c-tools python3-smbus python3-pil zbar-tools qrencode lm-sensors"
|
||||||
|
apt-get install -y $BASE_PKGS
|
||||||
|
|
||||||
|
# ------- OLED (Luma) -------
|
||||||
|
# Prefer distro package; fall back to pip if not present in this release
|
||||||
|
if ! dpkg -s python3-luma.oled >/dev/null 2>&1; then
|
||||||
|
apt-get update
|
||||||
|
if ! apt-get install -y python3-luma.oled; then
|
||||||
|
apt-get install -y python3-pip
|
||||||
|
pip3 install --no-input --break-system-packages luma.oled
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ------- Camera apps -------
|
||||||
|
# Ubuntu renamed libcamera-apps -> rpicam-apps for Raspberry Pi.
|
||||||
|
# Try in order; tolerate absence (the box might be display-only).
|
||||||
|
apt-get update
|
||||||
|
if ! apt-get install -y rpicam-apps; then
|
||||||
|
apt-get install -y libcamera-apps || apt-get install -y libcamera-tools || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Enable SSH on boot (no systemctl in chroot)
|
||||||
|
mkdir -p /etc/systemd/system/multi-user.target.wants
|
||||||
|
ln -sf /lib/systemd/system/ssh.service /etc/systemd/system/multi-user.target.wants/ssh.service
|
||||||
|
|
||||||
|
# Create user and set password
|
||||||
|
if ! id -u STYX_USER >/dev/null 2>&1; then
|
||||||
|
/usr/sbin/useradd -m -s /bin/bash -G sudo,video,i2c STYX_USER
|
||||||
|
fi
|
||||||
|
echo 'STYX_USER:STYX_PASS' | /usr/sbin/chpasswd
|
||||||
|
|
||||||
|
# Optional: preload SSH key
|
||||||
|
if [ -n 'SSH_PUBKEY' ] && echo 'SSH_PUBKEY' | grep -q 'ssh-'; then
|
||||||
|
install -d -m700 /home/STYX_USER/.ssh
|
||||||
|
echo 'SSH_PUBKEY' >> /home/STYX_USER/.ssh/authorized_keys
|
||||||
|
chmod 600 /home/STYX_USER/.ssh/authorized_keys
|
||||||
|
chown -R STYX_USER:STYX_USER /home/STYX_USER/.ssh
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Freenove code
|
||||||
|
git clone https://github.com/Freenove/Freenove_Computer_Case_Kit_for_Raspberry_Pi.git /opt/freenove || true
|
||||||
|
|
||||||
|
# Hostname
|
||||||
|
echo 'STYX_HOSTNAME' > /etc/hostname
|
||||||
|
if grep -q '^127\.0\.1\.1' /etc/hosts; then
|
||||||
|
sed -i 's/^127\.0\.1\.1.*/127.0.1.1\tSTYX_HOSTNAME/' /etc/hosts
|
||||||
|
else
|
||||||
|
echo -e '127.0.1.1\tSTYX_HOSTNAME' >> /etc/hosts
|
||||||
|
fi
|
||||||
|
|
||||||
|
apt-get clean
|
||||||
|
EOS
|
||||||
|
)
|
||||||
|
# Inject config values safely
|
||||||
|
CHCMD="${CHCMD//STYX_USER/${STYX_USER}}"
|
||||||
|
CHCMD="${CHCMD//STYX_PASS/${STYX_PASS}}"
|
||||||
|
CHCMD="${CHCMD//STYX_HOSTNAME/${STYX_HOSTNAME}}"
|
||||||
|
CHCMD="${CHCMD//SSH_PUBKEY/${SSH_PUBKEY}}"
|
||||||
|
|
||||||
|
chroot /mnt/pi-root /bin/bash -lc "$CHCMD"
|
||||||
|
}
|
||||||
|
|
||||||
|
install_service_host() {
|
||||||
|
# Systemd unit for the Freenove example app
|
||||||
|
mkdir -p /mnt/pi-root/etc/systemd/system/multi-user.target.wants
|
||||||
|
cat >/mnt/pi-root/etc/systemd/system/freenove-case.service <<'SERVICE'
|
||||||
|
[Unit]
|
||||||
|
Description=Freenove Case OLED/Fans/LEDs
|
||||||
|
After=multi-user.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
ExecStart=/usr/bin/python3 /opt/freenove/Code/application.py
|
||||||
|
Restart=on-failure
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
SERVICE
|
||||||
|
ln -sf /etc/systemd/system/freenove-case.service \
|
||||||
|
/mnt/pi-root/etc/systemd/system/multi-user.target.wants/freenove-case.service || true
|
||||||
|
}
|
||||||
|
|
||||||
|
boot_tweaks() {
|
||||||
|
# Enable I2C and set DSI panel on the BOOT partition
|
||||||
|
grep -q 'dtparam=i2c_arm=on' /mnt/pi-boot/config.txt || echo 'dtparam=i2c_arm=on' >> /mnt/pi-boot/config.txt
|
||||||
|
# Append kernel cmdline only once
|
||||||
|
if ! grep -q 'DSI-1:800x480@60D' /mnt/pi-boot/cmdline.txt 2>/dev/null; then
|
||||||
|
sed -i '1 s#$# video=DSI-1:800x480@60D video=HDMI-A-1:off video=HDMI-A-2:off#' /mnt/pi-boot/cmdline.txt || true
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup() {
|
||||||
|
rm -f /mnt/pi-root/usr/sbin/policy-rc.d || true
|
||||||
|
for d in dev/pts dev proc sys; do umount -lf "/mnt/pi-root/$d" 2>/dev/null || true; done
|
||||||
|
umount -lf /mnt/pi-boot 2>/dev/null || true
|
||||||
|
umount -lf /mnt/pi-root 2>/dev/null || true
|
||||||
|
sync || true
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
require_root
|
||||||
|
ensure_binfmt_arm64
|
||||||
|
find_parts
|
||||||
|
trap 'echo "ERROR at line $LINENO" >&2; cleanup' ERR INT
|
||||||
|
mount_parts
|
||||||
|
prep_chroot
|
||||||
|
install_service_host
|
||||||
|
boot_tweaks
|
||||||
|
cleanup
|
||||||
|
echo "✅ Done. Move the NVMe to the Pi and boot."
|
||||||
|
echo " Login: user '${STYX_USER}' pass '${STYX_PASS}' (change with 'passwd')."
|
||||||
|
echo " Quick checks on the Pi:"
|
||||||
|
echo " sudo i2cdetect -y 1"
|
||||||
|
echo " rpicam-still -n -o test.jpg # (if rpicam-apps installed)"
|
||||||
|
echo " libcamera-still -n -o test.jpg # (if legacy libcamera-apps installed)"
|
||||||
|
echo " systemctl status freenove-case"
|
||||||
|
}
|
||||||
|
main "$@"
|
||||||
@ -23,6 +23,11 @@ spec:
|
|||||||
spec:
|
spec:
|
||||||
nodeSelector:
|
nodeSelector:
|
||||||
jellyfin: "true"
|
jellyfin: "true"
|
||||||
|
securityContext:
|
||||||
|
runAsUser: 1000
|
||||||
|
fsGroup: 65532
|
||||||
|
fsGroupChangePolicy: OnRootMismatch
|
||||||
|
runAsGroup: 65532
|
||||||
runtimeClassName: nvidia
|
runtimeClassName: nvidia
|
||||||
containers:
|
containers:
|
||||||
- name: jellyfin
|
- name: jellyfin
|
||||||
@ -36,6 +41,12 @@ spec:
|
|||||||
value: "compute,video,utility"
|
value: "compute,video,utility"
|
||||||
- name: JELLYFIN_PublishedServerUrl
|
- name: JELLYFIN_PublishedServerUrl
|
||||||
value: "https://stream.bstein.dev"
|
value: "https://stream.bstein.dev"
|
||||||
|
- name: PUID
|
||||||
|
value: "1000"
|
||||||
|
- name: PGID
|
||||||
|
value: "65532"
|
||||||
|
- name: UMASK
|
||||||
|
value: "002"
|
||||||
resources:
|
resources:
|
||||||
limits:
|
limits:
|
||||||
nvidia.com/gpu: 1
|
nvidia.com/gpu: 1
|
||||||
@ -64,4 +75,4 @@ spec:
|
|||||||
claimName: jellyfin-cache-astreae
|
claimName: jellyfin-cache-astreae
|
||||||
- name: media
|
- name: media
|
||||||
persistentVolumeClaim:
|
persistentVolumeClaim:
|
||||||
claimName: jellyfin-media-asteria
|
claimName: jellyfin-media-asteria-new
|
||||||
|
|||||||
@ -36,5 +36,19 @@ spec:
|
|||||||
accessModes: ["ReadWriteMany"]
|
accessModes: ["ReadWriteMany"]
|
||||||
resources:
|
resources:
|
||||||
requests:
|
requests:
|
||||||
storage: 2Ti
|
storage: 4Ti
|
||||||
|
storageClassName: asteria
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: jellyfin-media-asteria-new
|
||||||
|
namespace: jellyfin
|
||||||
|
spec:
|
||||||
|
accessModes: ["ReadWriteMany"]
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 4Ti
|
||||||
storageClassName: asteria
|
storageClassName: asteria
|
||||||
|
|||||||
171
services/jitsi/deployment.yaml
Normal file
171
services/jitsi/deployment.yaml
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
# services/jitsi/deployment.yaml
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: jitsi-prosody
|
||||||
|
namespace: jitsi
|
||||||
|
spec:
|
||||||
|
replicas: 0
|
||||||
|
selector:
|
||||||
|
matchLabels: { app: jitsi-prosody }
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels: { app: jitsi-prosody }
|
||||||
|
spec:
|
||||||
|
nodeSelector:
|
||||||
|
kubernetes.io/hostname: titan-22
|
||||||
|
kubernetes.io/arch: amd64
|
||||||
|
containers:
|
||||||
|
- name: prosody
|
||||||
|
image: jitsi/prosody:stable
|
||||||
|
ports:
|
||||||
|
- { name: c2s, containerPort: 5222, protocol: TCP }
|
||||||
|
- { name: http, containerPort: 5280, protocol: TCP }
|
||||||
|
- { name: comp, containerPort: 5347, protocol: TCP }
|
||||||
|
env:
|
||||||
|
- { name: XMPP_DOMAIN, value: "meet.jitsi" }
|
||||||
|
- { name: XMPP_AUTH_DOMAIN, value: "auth.meet.jitsi" }
|
||||||
|
- { name: XMPP_MUC_DOMAIN, value: "muc.meet.jitsi" }
|
||||||
|
- { name: XMPP_INTERNAL_MUC_DOMAIN, value: "internal-muc.meet.jitsi" }
|
||||||
|
- { name: ENABLE_AUTH, value: "0" } # open instance, no auth (fastest path)
|
||||||
|
- { name: ENABLE_GUESTS, value: "1" }
|
||||||
|
- { name: JICOFO_AUTH_USER, value: "focus" }
|
||||||
|
- { name: JVB_AUTH_USER, value: "jvb" }
|
||||||
|
- name: JICOFO_AUTH_PASSWORD
|
||||||
|
valueFrom: { secretKeyRef: { name: jitsi-internal-secrets, key: JICOFO_AUTH_PASSWORD } }
|
||||||
|
- name: JICOFO_COMPONENT_SECRET
|
||||||
|
valueFrom: { secretKeyRef: { name: jitsi-internal-secrets, key: JICOFO_COMPONENT_SECRET } }
|
||||||
|
- name: JVB_AUTH_PASSWORD
|
||||||
|
valueFrom: { secretKeyRef: { name: jitsi-internal-secrets, key: JVB_AUTH_PASSWORD } }
|
||||||
|
volumeMounts:
|
||||||
|
- { name: cfg, mountPath: /config }
|
||||||
|
volumes:
|
||||||
|
- name: cfg
|
||||||
|
persistentVolumeClaim: { claimName: jitsi-prosody-config }
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: jitsi-jicofo
|
||||||
|
namespace: jitsi
|
||||||
|
spec:
|
||||||
|
replicas: 0
|
||||||
|
selector:
|
||||||
|
matchLabels: { app: jitsi-jicofo }
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels: { app: jitsi-jicofo }
|
||||||
|
spec:
|
||||||
|
nodeSelector:
|
||||||
|
kubernetes.io/hostname: titan-22
|
||||||
|
kubernetes.io/arch: amd64
|
||||||
|
containers:
|
||||||
|
- name: jicofo
|
||||||
|
image: jitsi/jicofo:stable
|
||||||
|
env:
|
||||||
|
- { name: XMPP_DOMAIN, value: "meet.jitsi" }
|
||||||
|
- { name: XMPP_AUTH_DOMAIN, value: "auth.meet.jitsi" }
|
||||||
|
- { name: XMPP_MUC_DOMAIN, value: "muc.meet.jitsi" }
|
||||||
|
- { name: XMPP_INTERNAL_MUC_DOMAIN, value: "internal-muc.meet.jitsi" }
|
||||||
|
- { name: XMPP_SERVER, value: "jitsi-prosody.jitsi.svc.cluster.local" }
|
||||||
|
- { name: JICOFO_AUTH_USER, value: "focus" }
|
||||||
|
- name: JICOFO_AUTH_PASSWORD
|
||||||
|
valueFrom: { secretKeyRef: { name: jitsi-internal-secrets, key: JICOFO_AUTH_PASSWORD } }
|
||||||
|
- name: JICOFO_COMPONENT_SECRET
|
||||||
|
valueFrom: { secretKeyRef: { name: jitsi-internal-secrets, key: JICOFO_COMPONENT_SECRET } }
|
||||||
|
- { name: JVB_BREWERY_MUC, value: "jvbbrewery" }
|
||||||
|
volumeMounts:
|
||||||
|
- { name: cfg, mountPath: /config }
|
||||||
|
volumes:
|
||||||
|
- name: cfg
|
||||||
|
persistentVolumeClaim: { claimName: jitsi-jicofo-config }
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: jitsi-jvb
|
||||||
|
namespace: jitsi
|
||||||
|
spec:
|
||||||
|
replicas: 0
|
||||||
|
selector:
|
||||||
|
matchLabels: { app: jitsi-jvb }
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels: { app: jitsi-jvb }
|
||||||
|
spec:
|
||||||
|
nodeSelector:
|
||||||
|
kubernetes.io/hostname: titan-22
|
||||||
|
kubernetes.io/arch: amd64
|
||||||
|
containers:
|
||||||
|
- name: jvb
|
||||||
|
image: jitsi/jvb:stable
|
||||||
|
ports:
|
||||||
|
- { name: colibri-ws, containerPort: 9090, protocol: TCP } # WebSocket control channel
|
||||||
|
- { name: rtp-udp, containerPort: 10000, hostPort: 10000, protocol: UDP } # media
|
||||||
|
- { name: rtp-tcp, containerPort: 4443, hostPort: 4443, protocol: TCP }
|
||||||
|
env:
|
||||||
|
- { name: XMPP_DOMAIN, value: "meet.jitsi" }
|
||||||
|
- { name: XMPP_AUTH_DOMAIN, value: "auth.meet.jitsi" }
|
||||||
|
- { name: XMPP_MUC_DOMAIN, value: "muc.meet.jitsi" }
|
||||||
|
- { name: XMPP_INTERNAL_MUC_DOMAIN, value: "internal-muc.meet.jitsi" }
|
||||||
|
- { name: XMPP_SERVER, value: "jitsi-prosody.jitsi.svc.cluster.local" }
|
||||||
|
- { name: JVB_AUTH_USER, value: "jvb" }
|
||||||
|
- name: JVB_AUTH_PASSWORD
|
||||||
|
valueFrom: { secretKeyRef: { name: jitsi-internal-secrets, key: JVB_AUTH_PASSWORD } }
|
||||||
|
- { name: JVB_BREWERY_MUC, value: "jvbbrewery" }
|
||||||
|
- { name: JVB_PORT, value: "10000" } # matches hostPort above
|
||||||
|
- { name: ENABLE_COLIBRI_WEBSOCKET, value: "1" } # enables /colibri-ws
|
||||||
|
# - { name: JVB_STUN_SERVERS, value: "stun.l.google.com:19302,stun1.l.google.com:19302,meet-jit-si-turnrelay.jitsi.net:443" }
|
||||||
|
- { name: JVB_ENABLE_APIS, value: "rest,colibri" }
|
||||||
|
- { name: JVB_WS_DOMAIN, value: "meet.bstein.dev:443" }
|
||||||
|
- { name: JVB_WS_TLS, value: "true" }
|
||||||
|
- { name: JVB_ADVERTISE_IPS, value: "38.28.125.112" }
|
||||||
|
- { name: JVB_TCP_HARVESTER_DISABLED, value: "false" }
|
||||||
|
- { name: JVB_TCP_PORT, value: "4443" }
|
||||||
|
volumeMounts:
|
||||||
|
- { name: cfg, mountPath: /config }
|
||||||
|
volumes:
|
||||||
|
- name: cfg
|
||||||
|
persistentVolumeClaim: { claimName: jitsi-jvb-config }
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: jitsi-web
|
||||||
|
namespace: jitsi
|
||||||
|
spec:
|
||||||
|
replicas: 0
|
||||||
|
selector:
|
||||||
|
matchLabels: { app: jitsi-web }
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels: { app: jitsi-web }
|
||||||
|
spec:
|
||||||
|
nodeSelector:
|
||||||
|
kubernetes.io/hostname: titan-22
|
||||||
|
kubernetes.io/arch: amd64
|
||||||
|
containers:
|
||||||
|
- name: web
|
||||||
|
image: jitsi/web:stable
|
||||||
|
ports:
|
||||||
|
- { name: http, containerPort: 80, protocol: TCP }
|
||||||
|
env:
|
||||||
|
- { name: PUBLIC_URL, value: "https://meet.bstein.dev" }
|
||||||
|
- { name: XMPP_DOMAIN, value: "meet.jitsi" }
|
||||||
|
- { name: XMPP_AUTH_DOMAIN, value: "auth.meet.jitsi" }
|
||||||
|
- { name: XMPP_MUC_DOMAIN, value: "muc.meet.jitsi" }
|
||||||
|
- { name: XMPP_INTERNAL_MUC_DOMAIN, value: "internal-muc.meet.jitsi" }
|
||||||
|
- { name: XMPP_BOSH_URL_BASE, value: "https://meet.bstein.dev" }
|
||||||
|
- { name: ENABLE_XMPP_WEBSOCKET, value: "1" }
|
||||||
|
- { name: ENABLE_COLIBRI_WEBSOCKET, value: "1" }
|
||||||
|
volumeMounts:
|
||||||
|
- { name: cfg, mountPath: /config }
|
||||||
|
volumes:
|
||||||
|
- name: cfg
|
||||||
|
persistentVolumeClaim: { claimName: jitsi-web-config }
|
||||||
41
services/jitsi/ingress.yaml
Normal file
41
services/jitsi/ingress.yaml
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
# services/jitsi/ingress.yaml
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: jitsi
|
||||||
|
namespace: jitsi
|
||||||
|
annotations:
|
||||||
|
cert-manager.io/cluster-issuer: "letsencrypt-prod"
|
||||||
|
spec:
|
||||||
|
ingressClassName: traefik
|
||||||
|
tls:
|
||||||
|
- hosts: [ "meet.bstein.dev" ]
|
||||||
|
secretName: jitsi-meet-tls
|
||||||
|
rules:
|
||||||
|
- host: meet.bstein.dev
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- path: /colibri-ws
|
||||||
|
pathType: Prefix
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: jitsi-jvb
|
||||||
|
port: { number: 9090 }
|
||||||
|
- path: /xmpp-websocket
|
||||||
|
pathType: Prefix
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: jitsi-prosody
|
||||||
|
port: { number: 5280 }
|
||||||
|
- path: /http-bind
|
||||||
|
pathType: Prefix
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: jitsi-prosody
|
||||||
|
port: { number: 5280 }
|
||||||
|
- path: /
|
||||||
|
pathType: Prefix
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: jitsi-web
|
||||||
|
port: { number: 80 }
|
||||||
10
services/jitsi/kustomization.yaml
Normal file
10
services/jitsi/kustomization.yaml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
# services/jitsi/kustomization.yaml
|
||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
resources:
|
||||||
|
- namespace.yaml
|
||||||
|
- deployment.yaml
|
||||||
|
- service.yaml
|
||||||
|
- pvc.yaml
|
||||||
|
- ingress.yaml
|
||||||
|
- secret.yaml
|
||||||
5
services/jitsi/namespace.yaml
Normal file
5
services/jitsi/namespace.yaml
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
# services/jitsi/namespace.yaml
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: jitsi
|
||||||
42
services/jitsi/pvc.yaml
Normal file
42
services/jitsi/pvc.yaml
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
# services/jitsi/pvc.yaml
|
||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: jitsi-web-config
|
||||||
|
namespace: jitsi
|
||||||
|
spec:
|
||||||
|
accessModes: ["ReadWriteOnce"]
|
||||||
|
resources: { requests: { storage: 10Gi } }
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: jitsi-prosody-config
|
||||||
|
namespace: jitsi
|
||||||
|
spec:
|
||||||
|
accessModes: ["ReadWriteOnce"]
|
||||||
|
resources: { requests: { storage: 10Gi } }
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: jitsi-jicofo-config
|
||||||
|
namespace: jitsi
|
||||||
|
spec:
|
||||||
|
accessModes: ["ReadWriteOnce"]
|
||||||
|
resources: { requests: { storage: 10Gi } }
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: jitsi-jvb-config
|
||||||
|
namespace: jitsi
|
||||||
|
spec:
|
||||||
|
accessModes: ["ReadWriteOnce"]
|
||||||
|
resources: { requests: { storage: 10Gi } }
|
||||||
11
services/jitsi/secret.yaml
Normal file
11
services/jitsi/secret.yaml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
# services/jitsi/secret.yaml
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: jitsi-internal-secrets
|
||||||
|
namespace: jitsi
|
||||||
|
type: Opaque
|
||||||
|
data:
|
||||||
|
JICOFO_COMPONENT_SECRET: bEg5Y09hZFJBem5PUFliQlp4RHkwRTRP
|
||||||
|
JICOFO_AUTH_PASSWORD: VVkyUmczaVRDWUZ0MzdQdmN3UDN1SFc5
|
||||||
|
JVB_AUTH_PASSWORD: d0M5aWJ4dWlPTnhFak9lRHJqSHdYa0g5
|
||||||
36
services/jitsi/service.yaml
Normal file
36
services/jitsi/service.yaml
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
# services/jitsi/service.yaml
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: jitsi-prosody
|
||||||
|
namespace: jitsi
|
||||||
|
spec:
|
||||||
|
selector: { app: jitsi-prosody }
|
||||||
|
ports:
|
||||||
|
- { name: c2s, port: 5222, targetPort: 5222, protocol: TCP }
|
||||||
|
- { name: http, port: 5280, targetPort: 5280, protocol: TCP }
|
||||||
|
- { name: comp, port: 5347, targetPort: 5347, protocol: TCP }
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: jitsi-jvb
|
||||||
|
namespace: jitsi
|
||||||
|
spec:
|
||||||
|
selector: { app: jitsi-jvb }
|
||||||
|
ports:
|
||||||
|
- { name: colibri-ws, port: 9090, targetPort: 9090, protocol: TCP }
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: jitsi-web
|
||||||
|
namespace: jitsi
|
||||||
|
spec:
|
||||||
|
selector: { app: jitsi-web }
|
||||||
|
ports:
|
||||||
|
- { name: http, port: 80, targetPort: 80, protocol: TCP }
|
||||||
212
services/monitoring/helmrelease.yaml
Normal file
212
services/monitoring/helmrelease.yaml
Normal file
@ -0,0 +1,212 @@
|
|||||||
|
# services/monitoring/kube-state-metrics-helmrelease.yaml
|
||||||
|
apiVersion: helm.toolkit.fluxcd.io/v2
|
||||||
|
kind: HelmRelease
|
||||||
|
metadata:
|
||||||
|
name: kube-state-metrics
|
||||||
|
namespace: monitoring
|
||||||
|
spec:
|
||||||
|
interval: 15m
|
||||||
|
chart:
|
||||||
|
spec:
|
||||||
|
chart: kube-state-metrics
|
||||||
|
version: "~6.0.0"
|
||||||
|
sourceRef:
|
||||||
|
kind: HelmRepository
|
||||||
|
name: prometheus
|
||||||
|
namespace: flux-system
|
||||||
|
values:
|
||||||
|
prometheusScrape: false
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
apiVersion: helm.toolkit.fluxcd.io/v2
|
||||||
|
kind: HelmRelease
|
||||||
|
metadata:
|
||||||
|
name: node-exporter
|
||||||
|
namespace: monitoring
|
||||||
|
spec:
|
||||||
|
interval: 15m
|
||||||
|
install:
|
||||||
|
disableWait: true
|
||||||
|
chart:
|
||||||
|
spec:
|
||||||
|
chart: prometheus-node-exporter
|
||||||
|
version: "~4.0.0"
|
||||||
|
sourceRef:
|
||||||
|
kind: HelmRepository
|
||||||
|
name: prometheus
|
||||||
|
namespace: flux-system
|
||||||
|
upgrade:
|
||||||
|
disableWait: true
|
||||||
|
values:
|
||||||
|
rbac:
|
||||||
|
pspEnabled: false
|
||||||
|
service:
|
||||||
|
annotations:
|
||||||
|
prometheus.io/scrape: "true"
|
||||||
|
prometheus.io/port: "9100"
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
apiVersion: helm.toolkit.fluxcd.io/v2
|
||||||
|
kind: HelmRelease
|
||||||
|
metadata:
|
||||||
|
name: victoria-metrics-single
|
||||||
|
namespace: monitoring
|
||||||
|
spec:
|
||||||
|
interval: 15m
|
||||||
|
chart:
|
||||||
|
spec:
|
||||||
|
chart: victoria-metrics-single
|
||||||
|
version: "~0.15.0" # or omit to track appVersion
|
||||||
|
sourceRef:
|
||||||
|
kind: HelmRepository
|
||||||
|
name: victoria-metrics
|
||||||
|
namespace: flux-system
|
||||||
|
values:
|
||||||
|
server:
|
||||||
|
# keep ~3 months; change as you like (supports "d", "y")
|
||||||
|
extraArgs:
|
||||||
|
retentionPeriod: "90d" # VM flag -retentionPeriod=90d. :contentReference[oaicite:11]{index=11}
|
||||||
|
|
||||||
|
persistentVolume:
|
||||||
|
enabled: true
|
||||||
|
size: 100Gi # adjust; uses default StorageClass (Longhorn)
|
||||||
|
# storageClassName: "" # set if you want a specific class
|
||||||
|
|
||||||
|
# Enable built-in Kubernetes scraping
|
||||||
|
scrape:
|
||||||
|
enabled: true # chart enables promscrape. :contentReference[oaicite:12]{index=12}
|
||||||
|
config:
|
||||||
|
global:
|
||||||
|
scrape_interval: 15s
|
||||||
|
|
||||||
|
scrape_configs:
|
||||||
|
# VM self-metrics
|
||||||
|
- job_name: victoriametrics
|
||||||
|
static_configs:
|
||||||
|
- targets: ["localhost:8428"]
|
||||||
|
|
||||||
|
# --- K8s control-plane & nodes (from VM docs guide) ---
|
||||||
|
- job_name: "kubernetes-apiservers"
|
||||||
|
kubernetes_sd_configs: [{ role: endpoints }]
|
||||||
|
scheme: https
|
||||||
|
tls_config:
|
||||||
|
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
|
||||||
|
insecure_skip_verify: true
|
||||||
|
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
|
||||||
|
relabel_configs:
|
||||||
|
- action: keep
|
||||||
|
source_labels: [__meta_kubernetes_namespace,__meta_kubernetes_service_name,__meta_kubernetes_endpoint_port_name]
|
||||||
|
regex: default;kubernetes;https
|
||||||
|
|
||||||
|
- job_name: "kubernetes-nodes"
|
||||||
|
scheme: https
|
||||||
|
tls_config:
|
||||||
|
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
|
||||||
|
insecure_skip_verify: true
|
||||||
|
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
|
||||||
|
kubernetes_sd_configs: [{ role: node }]
|
||||||
|
relabel_configs:
|
||||||
|
- action: labelmap
|
||||||
|
regex: __meta_kubernetes_node_label_(.+)
|
||||||
|
- target_label: __address__
|
||||||
|
replacement: kubernetes.default.svc:443
|
||||||
|
- source_labels: [__meta_kubernetes_node_name]
|
||||||
|
regex: (.+)
|
||||||
|
target_label: __metrics_path__
|
||||||
|
replacement: /api/v1/nodes/$1/proxy/metrics
|
||||||
|
|
||||||
|
- job_name: "kubernetes-nodes-cadvisor"
|
||||||
|
scheme: https
|
||||||
|
tls_config:
|
||||||
|
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
|
||||||
|
insecure_skip_verify: true
|
||||||
|
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
|
||||||
|
kubernetes_sd_configs: [{ role: node }]
|
||||||
|
relabel_configs:
|
||||||
|
- action: labelmap
|
||||||
|
regex: __meta_kubernetes_node_label_(.+)
|
||||||
|
- target_label: __address__
|
||||||
|
replacement: kubernetes.default.svc:443
|
||||||
|
- source_labels: [__meta_kubernetes_node_name]
|
||||||
|
regex: (.+)
|
||||||
|
target_label: __metrics_path__
|
||||||
|
replacement: /api/v1/nodes/$1/proxy/metrics/cadvisor
|
||||||
|
|
||||||
|
# --- Annotated Services (generic autodiscovery) ---
|
||||||
|
- job_name: "kubernetes-service-endpoints"
|
||||||
|
kubernetes_sd_configs: [{ role: endpoints }]
|
||||||
|
relabel_configs:
|
||||||
|
- action: keep
|
||||||
|
source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape]
|
||||||
|
regex: "true"
|
||||||
|
- action: replace
|
||||||
|
source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scheme]
|
||||||
|
regex: (https?)
|
||||||
|
target_label: __scheme__
|
||||||
|
- action: replace
|
||||||
|
source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path]
|
||||||
|
target_label: __metrics_path__
|
||||||
|
- action: replace
|
||||||
|
regex: (.+)(?::\d+);(\d+)
|
||||||
|
replacement: $1:$2
|
||||||
|
source_labels: [__address__, __meta_kubernetes_service_annotation_prometheus_io_port]
|
||||||
|
target_label: __address__
|
||||||
|
|
||||||
|
# --- Annotated Pods (generic autodiscovery) ---
|
||||||
|
- job_name: "kubernetes-pods"
|
||||||
|
kubernetes_sd_configs: [{ role: pod }]
|
||||||
|
relabel_configs:
|
||||||
|
- action: keep
|
||||||
|
source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
|
||||||
|
regex: "true"
|
||||||
|
- action: drop
|
||||||
|
source_labels: [__meta_kubernetes_pod_container_port_name]
|
||||||
|
regex: ".*health.*"
|
||||||
|
- action: replace
|
||||||
|
source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path]
|
||||||
|
target_label: __metrics_path__
|
||||||
|
- action: replace
|
||||||
|
regex: (.+):(?:\d+);(\d+)
|
||||||
|
replacement: $1:$2
|
||||||
|
source_labels: [__address__, __meta_kubernetes_pod_annotation_prometheus_io_port]
|
||||||
|
target_label: __address__
|
||||||
|
|
||||||
|
# --- kube-state-metrics (via its Service) ---
|
||||||
|
- job_name: "kube-state-metrics"
|
||||||
|
kubernetes_sd_configs: [{ role: endpoints }]
|
||||||
|
relabel_configs:
|
||||||
|
- action: keep
|
||||||
|
source_labels: [__meta_kubernetes_service_label_app_kubernetes_io_name]
|
||||||
|
regex: kube-state-metrics
|
||||||
|
|
||||||
|
# --- Longhorn ---
|
||||||
|
- job_name: "longhorn-backend"
|
||||||
|
static_configs:
|
||||||
|
- targets: ["longhorn-backend.longhorn-system.svc:9500"]
|
||||||
|
metrics_path: /metrics
|
||||||
|
|
||||||
|
# --- cert-manager (pods expose on 9402) ---
|
||||||
|
- job_name: "cert-manager"
|
||||||
|
kubernetes_sd_configs: [{ role: pod }]
|
||||||
|
relabel_configs:
|
||||||
|
- action: keep
|
||||||
|
source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_pod_label_app_kubernetes_io_name]
|
||||||
|
regex: cert-manager;cert-manager
|
||||||
|
- action: drop
|
||||||
|
source_labels: [__meta_kubernetes_pod_container_port_name]
|
||||||
|
regex: ".*health.*"
|
||||||
|
- action: replace
|
||||||
|
source_labels: [__address__]
|
||||||
|
regex: "(.+):\\d+"
|
||||||
|
replacement: "$1:9402"
|
||||||
|
target_label: __address__
|
||||||
|
|
||||||
|
# --- Flux controllers (default :8080/metrics) ---
|
||||||
|
- job_name: "flux"
|
||||||
|
kubernetes_sd_configs: [{ role: pod }]
|
||||||
|
relabel_configs:
|
||||||
|
- action: keep
|
||||||
|
source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_pod_label_app_kubernetes_io_part_of]
|
||||||
|
regex: flux-system;flux
|
||||||
8
services/monitoring/kustomization.yaml
Normal file
8
services/monitoring/kustomization.yaml
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
# services/monitoring/kustomization.yaml
|
||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
namespace: monitoring
|
||||||
|
resources:
|
||||||
|
- namespace.yaml
|
||||||
|
- rbac.yaml
|
||||||
|
- helmrelease.yaml
|
||||||
4
services/monitoring/namespace.yaml
Normal file
4
services/monitoring/namespace.yaml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: monitoring
|
||||||
33
services/monitoring/rbac.yaml
Normal file
33
services/monitoring/rbac.yaml
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
# services/monitoring/rbac.yaml
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
name: vmsingle-scrape
|
||||||
|
rules:
|
||||||
|
- apiGroups: [""]
|
||||||
|
resources:
|
||||||
|
- nodes
|
||||||
|
- nodes/proxy
|
||||||
|
- nodes/metrics
|
||||||
|
- services
|
||||||
|
- endpoints
|
||||||
|
- pods
|
||||||
|
verbs: ["get","list","watch"]
|
||||||
|
- apiGroups: ["networking.k8s.io","extensions"]
|
||||||
|
resources: ["ingresses"]
|
||||||
|
verbs: ["get","list","watch"]
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
metadata:
|
||||||
|
name: vmsingle-scrape
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: ClusterRole
|
||||||
|
name: vmsingle-scrape
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: victoria-metrics-single
|
||||||
|
namespace: monitoring
|
||||||
48
services/pegasus/configmap.yaml
Normal file
48
services/pegasus/configmap.yaml
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
# services/pegasus/configmap.yaml
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: pegasus-config
|
||||||
|
namespace: jellyfin
|
||||||
|
data:
|
||||||
|
PEGASUS_MEDIA_ROOT: "/media"
|
||||||
|
PEGASUS_BIND: ":8080"
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: pegasus-user-map
|
||||||
|
namespace: jellyfin
|
||||||
|
data:
|
||||||
|
user-map.yaml: |
|
||||||
|
map:
|
||||||
|
mary_grace_allison:
|
||||||
|
- "allison"
|
||||||
|
- "gavilan"
|
||||||
|
maddie_rejcek:
|
||||||
|
- "rangeejcek"
|
||||||
|
- "gavilan"
|
||||||
|
carol_mcguinness:
|
||||||
|
- "mcguinness_family"
|
||||||
|
- "gavilan"
|
||||||
|
ed_stein:
|
||||||
|
- "stein_family"
|
||||||
|
- "gavilan"
|
||||||
|
brad_stein:
|
||||||
|
- "stein_brad"
|
||||||
|
- "gavilan"
|
||||||
|
lisa_stein:
|
||||||
|
- "scott"
|
||||||
|
channa_cox:
|
||||||
|
- "cox"
|
||||||
|
- "gavilan"
|
||||||
|
chelie_sheehan:
|
||||||
|
- "sheehan"
|
||||||
|
- "gavilan"
|
||||||
|
olya_bulgakova:
|
||||||
|
- "bulgakova"
|
||||||
|
sean_mcguinness:
|
||||||
|
- "mcguinness_sean"
|
||||||
|
- "gavilan"
|
||||||
114
services/pegasus/deployment.yaml
Normal file
114
services/pegasus/deployment.yaml
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: pegasus
|
||||||
|
namespace: jellyfin
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
revisionHistoryLimit: 3
|
||||||
|
strategy:
|
||||||
|
type: RollingUpdate
|
||||||
|
rollingUpdate:
|
||||||
|
maxSurge: 0
|
||||||
|
maxUnavailable: 1
|
||||||
|
selector: { matchLabels: { app: pegasus } }
|
||||||
|
template:
|
||||||
|
metadata: { labels: { app: pegasus } }
|
||||||
|
spec:
|
||||||
|
nodeSelector:
|
||||||
|
kubernetes.io/arch: amd64
|
||||||
|
imagePullSecrets:
|
||||||
|
- name: zot-regcred
|
||||||
|
securityContext:
|
||||||
|
runAsNonRoot: true
|
||||||
|
runAsUser: 65532
|
||||||
|
runAsGroup: 65532
|
||||||
|
fsGroup: 65532
|
||||||
|
fsGroupChangePolicy: "OnRootMismatch"
|
||||||
|
initContainers:
|
||||||
|
- name: fix-perms
|
||||||
|
image: alpine:3.20
|
||||||
|
command:
|
||||||
|
- sh
|
||||||
|
- -lc
|
||||||
|
- |
|
||||||
|
set -eux
|
||||||
|
|
||||||
|
# Scratch area for tus uploads (always writable)
|
||||||
|
mkdir -p /media/.pegasus-tus
|
||||||
|
chmod 0777 /media/.pegasus-tus
|
||||||
|
|
||||||
|
# Make each top-level library dir group-writable and setgid,
|
||||||
|
# and try to set its group to 65532 (so the app can write).
|
||||||
|
for d in /media/*; do
|
||||||
|
[ -d "$d" ] || continue
|
||||||
|
base="$(basename "$d")"
|
||||||
|
[ "$base" = ".pegasus-tus" ] && continue
|
||||||
|
# chgrp can fail on some backends; don't block the pod if it does.
|
||||||
|
chgrp 65532 "$d" || true
|
||||||
|
chmod 2775 "$d" || true
|
||||||
|
done
|
||||||
|
securityContext:
|
||||||
|
runAsUser: 0
|
||||||
|
runAsGroup: 0
|
||||||
|
runAsNonRoot: false
|
||||||
|
allowPrivilegeEscalation: false
|
||||||
|
volumeMounts:
|
||||||
|
- { name: media, mountPath: /media }
|
||||||
|
|
||||||
|
containers:
|
||||||
|
- name: pegasus
|
||||||
|
image: registry.bstein.dev/pegasus:1.2.32 # {"$imagepolicy": "jellyfin:pegasus"}
|
||||||
|
imagePullPolicy: Always
|
||||||
|
command: ["/pegasus"]
|
||||||
|
env:
|
||||||
|
- name: PEGASUS_MEDIA_ROOT
|
||||||
|
valueFrom: { configMapKeyRef: { name: pegasus-config, key: PEGASUS_MEDIA_ROOT } }
|
||||||
|
- name: PEGASUS_BIND
|
||||||
|
valueFrom: { configMapKeyRef: { name: pegasus-config, key: PEGASUS_BIND } }
|
||||||
|
- name: PEGASUS_USER_MAP_FILE
|
||||||
|
value: "/config/user-map.yaml"
|
||||||
|
- name: PEGASUS_SESSION_KEY
|
||||||
|
valueFrom: { secretKeyRef: { name: pegasus-secrets, key: PEGASUS_SESSION_KEY } }
|
||||||
|
- name: JELLYFIN_URL
|
||||||
|
valueFrom: { secretKeyRef: { name: pegasus-secrets, key: JELLYFIN_URL } }
|
||||||
|
- name: JELLYFIN_API_KEY
|
||||||
|
valueFrom: { secretKeyRef: { name: pegasus-secrets, key: JELLYFIN_API_KEY } }
|
||||||
|
- name: PEGASUS_DEBUG
|
||||||
|
value: "1"
|
||||||
|
- name: PEGASUS_DRY_RUN
|
||||||
|
value: "0"
|
||||||
|
ports: [{ name: http, containerPort: 8080 }]
|
||||||
|
readinessProbe:
|
||||||
|
httpGet: { path: /healthz, port: http }
|
||||||
|
initialDelaySeconds: 2
|
||||||
|
periodSeconds: 5
|
||||||
|
timeoutSeconds: 1
|
||||||
|
livenessProbe:
|
||||||
|
httpGet: { path: /healthz, port: http }
|
||||||
|
initialDelaySeconds: 10
|
||||||
|
periodSeconds: 10
|
||||||
|
timeoutSeconds: 2
|
||||||
|
securityContext:
|
||||||
|
allowPrivilegeEscalation: false
|
||||||
|
readOnlyRootFilesystem: true
|
||||||
|
capabilities: { drop: ["ALL"] }
|
||||||
|
resources:
|
||||||
|
requests: { cpu: 100m, memory: 256Mi }
|
||||||
|
limits: { cpu: 1000m, memory: 1Gi }
|
||||||
|
volumeMounts:
|
||||||
|
- name: media
|
||||||
|
mountPath: /media
|
||||||
|
- name: config
|
||||||
|
mountPath: /config
|
||||||
|
readOnly: true
|
||||||
|
- name: tmp
|
||||||
|
mountPath: /tmp
|
||||||
|
volumes:
|
||||||
|
- name: media
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: jellyfin-media-asteria-new
|
||||||
|
- name: config
|
||||||
|
configMap: { name: pegasus-user-map }
|
||||||
|
- name: tmp
|
||||||
|
emptyDir: {}
|
||||||
25
services/pegasus/image.yaml
Normal file
25
services/pegasus/image.yaml
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
# services/pegasus/image.yaml
|
||||||
|
apiVersion: image.toolkit.fluxcd.io/v1beta2
|
||||||
|
kind: ImageRepository
|
||||||
|
metadata:
|
||||||
|
name: pegasus
|
||||||
|
namespace: jellyfin
|
||||||
|
spec:
|
||||||
|
image: registry.bstein.dev/pegasus
|
||||||
|
interval: 1m0s
|
||||||
|
secretRef:
|
||||||
|
name: zot-regcred
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
apiVersion: image.toolkit.fluxcd.io/v1beta2
|
||||||
|
kind: ImagePolicy
|
||||||
|
metadata:
|
||||||
|
name: pegasus
|
||||||
|
namespace: jellyfin
|
||||||
|
spec:
|
||||||
|
imageRepositoryRef:
|
||||||
|
name: pegasus
|
||||||
|
policy:
|
||||||
|
semver:
|
||||||
|
range: "1.x"
|
||||||
25
services/pegasus/ingress.yaml
Normal file
25
services/pegasus/ingress.yaml
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
# services/pegasus/ingress.yaml
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: pegasus
|
||||||
|
namespace: jellyfin
|
||||||
|
annotations:
|
||||||
|
kubernetes.io/ingress.class: traefik
|
||||||
|
traefik.ingress.kubernetes.io/router.entrypoints: websecure
|
||||||
|
traefik.ingress.kubernetes.io/router.tls: "true"
|
||||||
|
cert-manager.io/cluster-issuer: letsencrypt-prod
|
||||||
|
spec:
|
||||||
|
tls:
|
||||||
|
- hosts: [ "pegasus.bstein.dev" ]
|
||||||
|
secretName: pegasus-bstein-dev-tls
|
||||||
|
rules:
|
||||||
|
- host: pegasus.bstein.dev
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- pathType: Prefix
|
||||||
|
path: /
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: pegasus
|
||||||
|
port: { number: 80 }
|
||||||
21
services/pegasus/kustomization.yaml
Normal file
21
services/pegasus/kustomization.yaml
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
# services/pegasus/kustomization.yaml
|
||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
resources:
|
||||||
|
- configmap.yaml
|
||||||
|
- service.yaml
|
||||||
|
- deployment.yaml
|
||||||
|
- ingress.yaml
|
||||||
|
patches:
|
||||||
|
- target: { kind: Deployment, name: pegasus, namespace: jellyfin }
|
||||||
|
patch: |
|
||||||
|
- op: add
|
||||||
|
path: /spec/template/spec/containers/-
|
||||||
|
value:
|
||||||
|
name: shell
|
||||||
|
image: alpine:3.20
|
||||||
|
command: ["sh","-c","sleep infinity"]
|
||||||
|
securityContext: { runAsUser: 10001, runAsGroup: 10001, allowPrivilegeEscalation: false }
|
||||||
|
volumeMounts:
|
||||||
|
- { name: media, mountPath: /media }
|
||||||
|
- { name: config, mountPath: /config, readOnly: true }
|
||||||
12
services/pegasus/service.yaml
Normal file
12
services/pegasus/service.yaml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
# services/pegasus/service.yaml
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: pegasus
|
||||||
|
namespace: jellyfin
|
||||||
|
spec:
|
||||||
|
selector: { app: pegasus }
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
port: 80
|
||||||
|
targetPort: http
|
||||||
16
services/sui-metrics/base/configmap.yaml
Normal file
16
services/sui-metrics/base/configmap.yaml
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
# services/sui-metrics/base/configmap.yaml
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: sui-metrics-config
|
||||||
|
namespace: sui-metrics
|
||||||
|
data:
|
||||||
|
vmagent.yaml: |
|
||||||
|
global:
|
||||||
|
scrape_interval: 15s
|
||||||
|
scrape_timeout: 10s
|
||||||
|
scrape_configs:
|
||||||
|
- job_name: oceanus-node-exporter
|
||||||
|
static_configs:
|
||||||
|
- targets:
|
||||||
|
- "192.168.22.23:9100"
|
||||||
63
services/sui-metrics/base/deployment.yaml
Normal file
63
services/sui-metrics/base/deployment.yaml
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
# services/sui-metrics/base/deployment.yaml
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: sui-metrics
|
||||||
|
namespace: sui-metrics
|
||||||
|
labels:
|
||||||
|
app: sui-metrics
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: sui-metrics
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: sui-metrics
|
||||||
|
spec:
|
||||||
|
serviceAccountName: sui-metrics
|
||||||
|
containers:
|
||||||
|
- name: vmagent
|
||||||
|
image: victoriametrics/vmagent:v1.103.0
|
||||||
|
imagePullPolicy: IfNotPresent
|
||||||
|
args:
|
||||||
|
- -promscrape.config=/etc/vmagent/config/vmagent.yaml
|
||||||
|
- -remoteWrite.url=$(REMOTE_WRITE_URL)
|
||||||
|
- -remoteWrite.tmpDataPath=/var/lib/vmagent
|
||||||
|
- -loggerFormat=json
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
containerPort: 8429
|
||||||
|
protocol: TCP
|
||||||
|
env:
|
||||||
|
- name: TZ
|
||||||
|
value: Etc/UTC
|
||||||
|
- name: REMOTE_WRITE_URL
|
||||||
|
value: http://victoria-metrics-single.monitoring.svc.cluster.local:8428/api/v1/write
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 256Mi
|
||||||
|
limits:
|
||||||
|
cpu: 500m
|
||||||
|
memory: 512Mi
|
||||||
|
volumeMounts:
|
||||||
|
- name: config
|
||||||
|
mountPath: /etc/vmagent/config
|
||||||
|
readOnly: true
|
||||||
|
- name: data
|
||||||
|
mountPath: /var/lib/vmagent
|
||||||
|
securityContext:
|
||||||
|
allowPrivilegeEscalation: false
|
||||||
|
runAsNonRoot: true
|
||||||
|
runAsUser: 65534
|
||||||
|
runAsGroup: 65534
|
||||||
|
capabilities:
|
||||||
|
drop: ["ALL"]
|
||||||
|
volumes:
|
||||||
|
- name: config
|
||||||
|
configMap:
|
||||||
|
name: sui-metrics-config
|
||||||
|
- name: data
|
||||||
|
emptyDir: {}
|
||||||
10
services/sui-metrics/base/kustomization.yaml
Normal file
10
services/sui-metrics/base/kustomization.yaml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
# services/sui-metrics/base/kustomization.yaml
|
||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
namespace: sui-metrics
|
||||||
|
resources:
|
||||||
|
- namespace.yaml
|
||||||
|
- serviceaccount.yaml
|
||||||
|
- configmap.yaml
|
||||||
|
- deployment.yaml
|
||||||
|
- service.yaml
|
||||||
5
services/sui-metrics/base/namespace.yaml
Normal file
5
services/sui-metrics/base/namespace.yaml
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
# services/sui-metrics/base/namespace.yaml
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: sui-metrics
|
||||||
16
services/sui-metrics/base/service.yaml
Normal file
16
services/sui-metrics/base/service.yaml
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
# services/sui-metrics/base/service.yaml
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: sui-metrics
|
||||||
|
namespace: sui-metrics
|
||||||
|
labels:
|
||||||
|
app: sui-metrics
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
selector:
|
||||||
|
app: sui-metrics
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
port: 8429
|
||||||
|
targetPort: 8429
|
||||||
6
services/sui-metrics/base/serviceaccount.yaml
Normal file
6
services/sui-metrics/base/serviceaccount.yaml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
# services/sui-metrics/base/serviceaccount.yaml
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
name: sui-metrics
|
||||||
|
namespace: sui-metrics
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user