mirror of
https://github.com/kerberos-io/deployment.git
synced 2026-11-05 20:10:26 +00:00
Compare commits
21
Commits
+14
-34
@@ -8,6 +8,7 @@ jobs:
|
||||
deploy:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-22.04, ubuntu-24.04]
|
||||
#k3d: [v5.5.2, v5.6.0, v5.7.5]
|
||||
@@ -29,8 +30,6 @@ jobs:
|
||||
kubectl get no
|
||||
kubectl get pods -A -o wide
|
||||
kubectl get sc
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
- name: Install OpenEBS
|
||||
run: |
|
||||
kubectl apply -f https://openebs.github.io/charts/openebs-operator.yaml
|
||||
@@ -50,16 +49,11 @@ jobs:
|
||||
kubectl wait --for=condition=available deployment/prometheus-operator -n default --timeout=300s
|
||||
kubectl get crd
|
||||
kubectl get po -A -o wide
|
||||
- name: Install Minio
|
||||
id: install-minio
|
||||
- name: Install Garage S3
|
||||
id: install-garage
|
||||
run: |
|
||||
git clone --depth 1 --branch v6.0.1 https://github.com/minio/operator.git && kubectl apply -k operator/
|
||||
kubectl apply -f ./base/minio/minio-tenant-base.yaml
|
||||
echo "Waiting for resources to be created..."
|
||||
sleep 10
|
||||
kubectl wait --for=jsonpath='{.status.readyReplicas}'=1 statefulset/myminio-pool-0 -n minio-tenant --timeout=300s
|
||||
kubectl get po -A -o wide
|
||||
kubectl get po -A -o wide | grep myminio-pool-0-0 | awk '{print $3}' | grep -q '2/2' && echo "myminio-pool-0-0 pod is running with status 2/2" || (echo "myminio-pool-0-0 pod is not running with status 2/2" && exit 1)
|
||||
bash scripts/install-garage.sh
|
||||
bash scripts/check-garage.sh
|
||||
- name: Install MongoDB
|
||||
id: install-mongodb
|
||||
run: |
|
||||
@@ -90,8 +84,7 @@ jobs:
|
||||
kubectl apply -f ./base/vault/mongodb-configmap.yaml -n kerberos-vault
|
||||
kubectl apply -f ./base/vault/kerberos-vault-deployment.yaml -n kerberos-vault
|
||||
kubectl apply -f ./base/vault/kerberos-vault-service.yaml -n kerberos-vault
|
||||
sleep 10
|
||||
kubectl wait --for=condition=available deployment/vault -n kerberos-vault --timeout=300s
|
||||
kubectl rollout status deployment/vault -n kerberos-vault --timeout=300s
|
||||
kubectl get pods -A -o wide
|
||||
kubectl get pods -A -o wide | grep vault | awk '{print $3}' | grep -q '1/1' && echo "vault pod is running with status 1/1" || (echo "vault pod is not running with status 1/1" && exit 1)
|
||||
- name: Install Agent
|
||||
@@ -106,37 +99,24 @@ jobs:
|
||||
id: install-hub
|
||||
run: |
|
||||
helm repo add kerberos https://charts.kerberos.io
|
||||
bash scripts/check-hub-runtime.sh
|
||||
kubectl create namespace kerberos-hub
|
||||
helm install hub kerberos/hub --values ./base/hub/kerberos-hub-values.yaml -n kerberos-hub --create-namespace
|
||||
helm install hub kerberos/hub --version 0.170.1 --values ./base/hub/kerberos-hub-values.yaml -n kerberos-hub --create-namespace
|
||||
sleep 10
|
||||
kubectl wait --for=condition=available deployment/admin -n kerberos-hub --timeout=300s
|
||||
kubectl wait --for=condition=available deployment/hub-api -n kerberos-hub --timeout=300s
|
||||
kubectl wait --for=condition=available deployment/hub-cleanup -n kerberos-hub --timeout=300s
|
||||
kubectl wait --for=condition=available deployment/hub-frontend -n kerberos-hub --timeout=300s
|
||||
kubectl wait --for=condition=available deployment/hub-frontend-demo -n kerberos-hub --timeout=300s
|
||||
kubectl wait --for=condition=available deployment/hub-monitor-device -n kerberos-hub --timeout=300s
|
||||
kubectl wait --for=condition=available deployment/hub-reactivate-subscription -n kerberos-hub --timeout=300s
|
||||
kubectl wait --for=condition=available deployment/pipe-analysis -n kerberos-hub --timeout=300s
|
||||
kubectl wait --for=condition=available deployment/pipe-counting -n kerberos-hub --timeout=300s
|
||||
kubectl wait --for=condition=available deployment/pipe-dominantcolor -n kerberos-hub --timeout=300s
|
||||
kubectl wait --for=condition=available deployment/pipe-event -n kerberos-hub --timeout=300s
|
||||
kubectl wait --for=condition=available deployment/pipe-export -n kerberos-hub --timeout=300s
|
||||
kubectl wait --for=condition=available deployment/pipe-monitor -n kerberos-hub --timeout=300s
|
||||
kubectl wait --for=condition=available deployment/pipe-notify -n kerberos-hub --timeout=300s
|
||||
kubectl wait --for=condition=available deployment/pipe-notify-test -n kerberos-hub --timeout=300s
|
||||
kubectl wait --for=condition=available deployment/pipe-sequence -n kerberos-hub --timeout=300s
|
||||
kubectl wait --for=condition=available deployment/pipe-sprite -n kerberos-hub --timeout=300s
|
||||
kubectl wait --for=condition=available deployment/pipe-throttler -n kerberos-hub --timeout=300s
|
||||
kubectl wait --for=condition=available deployment --all -n kerberos-hub --timeout=300s
|
||||
kubectl get pods -A -o wide
|
||||
- name: Collect deployment diagnostics
|
||||
if: failure()
|
||||
run: bash scripts/diagnose-deployment.sh
|
||||
- name: Send Slack Notification on Success
|
||||
if: success()
|
||||
env:
|
||||
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
|
||||
run: |
|
||||
curl -X POST -H 'Content-type: application/json' --data "{\"text\": \"✅ K3d deployment successful on ${{ matrix.os }} (${{ matrix.k3d }}) - triggered by ${{ github.actor }}\"}" $SLACK_WEBHOOK_URL
|
||||
bash scripts/notify-slack.sh "✅ K3d deployment successful on ${{ matrix.os }} (${{ matrix.k3d }}) - triggered by ${{ github.actor }}"
|
||||
- name: Send Slack Notification on Failure
|
||||
if: failure()
|
||||
env:
|
||||
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
|
||||
run: |
|
||||
curl -X POST -H 'Content-type: application/json' --data "{\"text\": \"❌ K3d deployment failed on ${{ matrix.os }} (${{ matrix.k3d }}) - <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|View logs>\"}" $SLACK_WEBHOOK_URL
|
||||
bash scripts/notify-slack.sh "❌ K3d deployment failed on ${{ matrix.os }} (${{ matrix.k3d }}) - <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|View logs>"
|
||||
+18
-33
@@ -8,6 +8,7 @@ jobs:
|
||||
deploy:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-22.04, ubuntu-24.04]
|
||||
#kind: [v0.21.0, v0.22.0, v0.23.0, v0.24.0, v0.25.0]
|
||||
@@ -26,7 +27,11 @@ jobs:
|
||||
kubectl get pods -A -o wide
|
||||
kubectl get sc
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
- name: Check promoted Hub runtime
|
||||
run: |
|
||||
helm repo add kerberos https://charts.kerberos.io
|
||||
bash scripts/check-hub-runtime.sh
|
||||
- name: Install OpenEBS
|
||||
run: |
|
||||
kubectl apply -f https://openebs.github.io/charts/openebs-operator.yaml
|
||||
@@ -46,16 +51,11 @@ jobs:
|
||||
kubectl wait --for=condition=available deployment/prometheus-operator -n default --timeout=300s
|
||||
kubectl get crd
|
||||
kubectl get po -A -o wide
|
||||
- name: Install Minio
|
||||
id: install-minio
|
||||
- name: Install Garage S3
|
||||
id: install-garage
|
||||
run: |
|
||||
git clone --depth 1 --branch v6.0.1 https://github.com/minio/operator.git && kubectl apply -k operator/
|
||||
kubectl apply -f ./base/minio/minio-tenant-base.yaml
|
||||
echo "Waiting for resources to be created..."
|
||||
sleep 10
|
||||
kubectl wait --for=jsonpath='{.status.readyReplicas}'=1 statefulset/myminio-pool-0 -n minio-tenant --timeout=300s
|
||||
kubectl get po -A -o wide
|
||||
kubectl get po -A -o wide | grep myminio-pool-0-0 | awk '{print $3}' | grep -q '2/2' && echo "myminio-pool-0-0 pod is running with status 2/2" || (echo "myminio-pool-0-0 pod is not running with status 2/2" && exit 1)
|
||||
bash scripts/install-garage.sh
|
||||
bash scripts/check-garage.sh
|
||||
- name: Install MongoDB
|
||||
id: install-mongodb
|
||||
run: |
|
||||
@@ -86,8 +86,7 @@ jobs:
|
||||
kubectl apply -f ./base/vault/mongodb-configmap.yaml -n kerberos-vault
|
||||
kubectl apply -f ./base/vault/kerberos-vault-deployment.yaml -n kerberos-vault
|
||||
kubectl apply -f ./base/vault/kerberos-vault-service.yaml -n kerberos-vault
|
||||
sleep 10
|
||||
kubectl wait --for=condition=available deployment/vault -n kerberos-vault --timeout=300s
|
||||
kubectl rollout status deployment/vault -n kerberos-vault --timeout=300s
|
||||
kubectl get pods -A -o wide
|
||||
kubectl get pods -A -o wide | grep vault | awk '{print $3}' | grep -q '1/1' && echo "vault pod is running with status 1/1" || (echo "vault pod is not running with status 1/1" && exit 1)
|
||||
- name: Install Agent
|
||||
@@ -103,36 +102,22 @@ jobs:
|
||||
run: |
|
||||
helm repo add kerberos https://charts.kerberos.io
|
||||
kubectl create namespace kerberos-hub
|
||||
helm install hub kerberos/hub --values ./base/hub/kerberos-hub-values.yaml -n kerberos-hub --create-namespace
|
||||
helm install hub kerberos/hub --version 0.170.1 --values ./base/hub/kerberos-hub-values.yaml -n kerberos-hub --create-namespace
|
||||
sleep 10
|
||||
kubectl wait --for=condition=available deployment/admin -n kerberos-hub --timeout=300s
|
||||
kubectl wait --for=condition=available deployment/hub-api -n kerberos-hub --timeout=300s
|
||||
kubectl wait --for=condition=available deployment/hub-cleanup -n kerberos-hub --timeout=300s
|
||||
kubectl wait --for=condition=available deployment/hub-frontend -n kerberos-hub --timeout=300s
|
||||
kubectl wait --for=condition=available deployment/hub-frontend-demo -n kerberos-hub --timeout=300s
|
||||
kubectl wait --for=condition=available deployment/hub-monitor-device -n kerberos-hub --timeout=300s
|
||||
kubectl wait --for=condition=available deployment/hub-reactivate-subscription -n kerberos-hub --timeout=300s
|
||||
kubectl wait --for=condition=available deployment/pipe-analysis -n kerberos-hub --timeout=300s
|
||||
kubectl wait --for=condition=available deployment/pipe-counting -n kerberos-hub --timeout=300s
|
||||
kubectl wait --for=condition=available deployment/pipe-dominantcolor -n kerberos-hub --timeout=300s
|
||||
kubectl wait --for=condition=available deployment/pipe-event -n kerberos-hub --timeout=300s
|
||||
kubectl wait --for=condition=available deployment/pipe-export -n kerberos-hub --timeout=300s
|
||||
kubectl wait --for=condition=available deployment/pipe-monitor -n kerberos-hub --timeout=300s
|
||||
kubectl wait --for=condition=available deployment/pipe-notify -n kerberos-hub --timeout=300s
|
||||
kubectl wait --for=condition=available deployment/pipe-notify-test -n kerberos-hub --timeout=300s
|
||||
kubectl wait --for=condition=available deployment/pipe-sequence -n kerberos-hub --timeout=300s
|
||||
kubectl wait --for=condition=available deployment/pipe-sprite -n kerberos-hub --timeout=300s
|
||||
kubectl wait --for=condition=available deployment/pipe-throttler -n kerberos-hub --timeout=300s
|
||||
kubectl wait --for=condition=available deployment --all -n kerberos-hub --timeout=300s
|
||||
kubectl get pods -A -o wide
|
||||
- name: Collect deployment diagnostics
|
||||
if: failure()
|
||||
run: bash scripts/diagnose-deployment.sh
|
||||
- name: Send Slack Notification on Success
|
||||
if: success()
|
||||
env:
|
||||
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
|
||||
run: |
|
||||
curl -X POST -H 'Content-type: application/json' --data "{\"text\": \"✅ Kind deployment successful on ${{ matrix.os }} (${{ matrix.kind }}) - triggered by ${{ github.actor }}\"}" $SLACK_WEBHOOK_URL
|
||||
bash scripts/notify-slack.sh "✅ Kind deployment successful on ${{ matrix.os }} (${{ matrix.kind }}) - triggered by ${{ github.actor }}"
|
||||
- name: Send Slack Notification on Failure
|
||||
if: failure()
|
||||
env:
|
||||
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
|
||||
run: |
|
||||
curl -X POST -H 'Content-type: application/json' --data "{\"text\": \"❌ Kind deployment failed on ${{ matrix.os }} (${{ matrix.kind }}) - <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|View logs>\"}" $SLACK_WEBHOOK_URL
|
||||
bash scripts/notify-slack.sh "❌ Kind deployment failed on ${{ matrix.os }} (${{ matrix.kind }}) - <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|View logs>"
|
||||
@@ -1,4 +1,4 @@
|
||||
name: Deploy on kind using Kustmize
|
||||
name: Validate Kustomize, Garage and Factory on kind
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
@@ -10,6 +10,7 @@ jobs:
|
||||
deploy:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-22.04, ubuntu-24.04]
|
||||
#kind: [v0.21.0, v0.22.0, v0.23.0, v0.24.0, v0.25.0]
|
||||
@@ -28,16 +29,56 @@ jobs:
|
||||
kubectl get pods -A -o wide
|
||||
kubectl get sc
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
- name: Render base Kustomize manifests
|
||||
run: kubectl kustomize base > "$RUNNER_TEMP/base.yaml"
|
||||
- name: Use Kind storage provisioner
|
||||
run: |
|
||||
kubectl get storageclass standard -o json |
|
||||
jq '{apiVersion,kind,metadata:{name:"ssd-hostpath"},provisioner,parameters,volumeBindingMode,reclaimPolicy}' |
|
||||
kubectl apply -f -
|
||||
- name: Install Garage and test persistent S3 access
|
||||
run: |
|
||||
bash scripts/install-garage.sh
|
||||
bash scripts/check-garage.sh
|
||||
credential_hash="$(kubectl -n garage get secret garage-credentials -o jsonpath='{.data}' | sha256sum)"
|
||||
bash scripts/install-garage.sh
|
||||
test "$credential_hash" = "$(kubectl -n garage get secret garage-credentials -o jsonpath='{.data}' | sha256sum)"
|
||||
bash scripts/check-garage.sh --restart
|
||||
- name: Install legacy Factory and upgrade the actual base
|
||||
run: |
|
||||
kubectl apply -f base/namespaces/kerberos-factory.yaml
|
||||
kubectl apply -f base/factory/kerberos-factory-clusterrole.yaml
|
||||
kubectl create --dry-run=client -n kerberos-factory -f base/factory/kerberos-factory-deployment.yaml -o json |
|
||||
jq '
|
||||
del(.spec.template.spec.securityContext, .spec.template.spec.volumes) |
|
||||
.spec.template.spec.containers[0] |= (
|
||||
.image = "ghcr.io/uug-ai/factory:v2.0.11" |
|
||||
.ports = [{"containerPort":80,"protocol":"TCP"}] |
|
||||
del(.securityContext, .volumeMounts, .startupProbe, .readinessProbe, .livenessProbe) |
|
||||
.env |= map(
|
||||
if .name == "K8S_PROXY" then .value = "http://localhost:80"
|
||||
elif .name == "PORT" then .value = "80"
|
||||
else . end))' |
|
||||
kubectl apply -n kerberos-factory -f -
|
||||
kubectl create --dry-run=client -n kerberos-factory -f base/factory/kerberos-factory-service.yaml -o json |
|
||||
jq '.spec.ports[0].targetPort = 80' |
|
||||
kubectl apply -n kerberos-factory -f -
|
||||
kubectl -n kerberos-factory rollout status deployment/factory --timeout=300s
|
||||
kubectl apply -k base/factory
|
||||
bash scripts/check-factory.sh
|
||||
- name: Collect deployment diagnostics
|
||||
if: failure()
|
||||
run: bash scripts/diagnose-deployment.sh
|
||||
- name: Send Slack Notification on Success
|
||||
if: success()
|
||||
env:
|
||||
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
|
||||
run: |
|
||||
curl -X POST -H 'Content-type: application/json' --data "{\"text\": \"✅ Kustomize deployment successful on ${{ matrix.os }} (${{ matrix.kind }}) - triggered by ${{ github.actor }}\"}" $SLACK_WEBHOOK_URL
|
||||
bash scripts/notify-slack.sh "✅ Kustomize deployment successful on ${{ matrix.os }} (${{ matrix.kind }}) - triggered by ${{ github.actor }}"
|
||||
- name: Send Slack Notification on Failure
|
||||
if: failure()
|
||||
env:
|
||||
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
|
||||
run: |
|
||||
curl -X POST -H 'Content-type: application/json' --data "{\"text\": \"❌ Kustomize deployment failed on ${{ matrix.os }} (${{ matrix.kind }}) - <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|View logs>\"}" $SLACK_WEBHOOK_URL
|
||||
bash scripts/notify-slack.sh "❌ Kustomize deployment failed on ${{ matrix.os }} (${{ matrix.kind }}) - <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|View logs>"
|
||||
@@ -8,6 +8,7 @@ jobs:
|
||||
deploy:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-22.04, ubuntu-24.04]
|
||||
microk8s: [1.32/stable]
|
||||
@@ -25,7 +26,7 @@ jobs:
|
||||
kubectl get no
|
||||
kubectl get pods -A -o wide
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
- name: Create storage class
|
||||
id: create-storage-class
|
||||
run: |
|
||||
@@ -39,16 +40,11 @@ jobs:
|
||||
kubectl wait --for=condition=available deployment/prometheus-operator -n default --timeout=300s
|
||||
kubectl get crd
|
||||
kubectl get po -A -o wide
|
||||
- name: Install Minio
|
||||
id: install-minio
|
||||
- name: Install Garage S3
|
||||
id: install-garage
|
||||
run: |
|
||||
git clone --depth 1 --branch v6.0.1 https://github.com/minio/operator.git && kubectl apply -k operator/
|
||||
kubectl apply -f ./base/minio/minio-tenant-base.yaml
|
||||
echo "Waiting for resources to be created..."
|
||||
sleep 10
|
||||
kubectl wait --for=jsonpath='{.status.readyReplicas}'=1 statefulset/myminio-pool-0 -n minio-tenant --timeout=300s
|
||||
kubectl get po -A -o wide
|
||||
kubectl get po -A -o wide | grep myminio-pool-0-0 | awk '{print $3}' | grep -q '2/2' && echo "myminio-pool-0-0 pod is running with status 2/2" || (echo "myminio-pool-0-0 pod is not running with status 2/2" && exit 1)
|
||||
bash scripts/install-garage.sh
|
||||
bash scripts/check-garage.sh
|
||||
- name: Install MongoDB
|
||||
id: install-mongodb
|
||||
run: |
|
||||
@@ -79,8 +75,7 @@ jobs:
|
||||
kubectl apply -f ./base/vault/mongodb-configmap.yaml -n kerberos-vault
|
||||
kubectl apply -f ./base/vault/kerberos-vault-deployment.yaml -n kerberos-vault
|
||||
kubectl apply -f ./base/vault/kerberos-vault-service.yaml -n kerberos-vault
|
||||
sleep 10
|
||||
kubectl wait --for=condition=available deployment/vault -n kerberos-vault --timeout=300s
|
||||
kubectl rollout status deployment/vault -n kerberos-vault --timeout=300s
|
||||
kubectl get pods -A -o wide
|
||||
kubectl get pods -A -o wide | grep vault | awk '{print $3}' | grep -q '1/1' && echo "vault pod is running with status 1/1" || (echo "vault pod is not running with status 1/1" && exit 1)
|
||||
- name: Install Agent
|
||||
@@ -95,38 +90,25 @@ jobs:
|
||||
id: install-hub
|
||||
run: |
|
||||
helm repo add kerberos https://charts.kerberos.io
|
||||
bash scripts/check-hub-runtime.sh
|
||||
kubectl create namespace kerberos-hub
|
||||
helm install hub kerberos/hub --values ./base/hub/kerberos-hub-values.yaml -n kerberos-hub --create-namespace
|
||||
helm install hub kerberos/hub --version 0.170.1 --values ./base/hub/kerberos-hub-values.yaml -n kerberos-hub --create-namespace
|
||||
sleep 10
|
||||
kubectl wait --for=condition=available deployment/admin -n kerberos-hub --timeout=300s
|
||||
kubectl wait --for=condition=available deployment/hub-api -n kerberos-hub --timeout=300s
|
||||
kubectl wait --for=condition=available deployment/hub-cleanup -n kerberos-hub --timeout=300s
|
||||
kubectl wait --for=condition=available deployment/hub-frontend -n kerberos-hub --timeout=300s
|
||||
kubectl wait --for=condition=available deployment/hub-frontend-demo -n kerberos-hub --timeout=300s
|
||||
kubectl wait --for=condition=available deployment/hub-monitor-device -n kerberos-hub --timeout=300s
|
||||
kubectl wait --for=condition=available deployment/hub-reactivate-subscription -n kerberos-hub --timeout=300s
|
||||
kubectl wait --for=condition=available deployment/pipe-analysis -n kerberos-hub --timeout=300s
|
||||
kubectl wait --for=condition=available deployment/pipe-counting -n kerberos-hub --timeout=300s
|
||||
kubectl wait --for=condition=available deployment/pipe-dominantcolor -n kerberos-hub --timeout=300s
|
||||
kubectl wait --for=condition=available deployment/pipe-event -n kerberos-hub --timeout=300s
|
||||
kubectl wait --for=condition=available deployment/pipe-export -n kerberos-hub --timeout=300s
|
||||
kubectl wait --for=condition=available deployment/pipe-monitor -n kerberos-hub --timeout=300s
|
||||
kubectl wait --for=condition=available deployment/pipe-notify -n kerberos-hub --timeout=300s
|
||||
kubectl wait --for=condition=available deployment/pipe-notify-test -n kerberos-hub --timeout=300s
|
||||
kubectl wait --for=condition=available deployment/pipe-sequence -n kerberos-hub --timeout=300s
|
||||
kubectl wait --for=condition=available deployment/pipe-sprite -n kerberos-hub --timeout=300s
|
||||
kubectl wait --for=condition=available deployment/pipe-throttler -n kerberos-hub --timeout=300s
|
||||
kubectl wait --for=condition=available deployment --all -n kerberos-hub --timeout=300s
|
||||
kubectl get pods -A -o wide
|
||||
- name: Collect deployment diagnostics
|
||||
if: failure()
|
||||
run: bash scripts/diagnose-deployment.sh
|
||||
- name: Send Slack Notification on Success
|
||||
if: success()
|
||||
env:
|
||||
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
|
||||
run: |
|
||||
curl -X POST -H 'Content-type: application/json' --data "{\"text\": \"✅ MicroK8s deployment successful on ${{ matrix.os }} (${{ matrix.microk8s }}) - triggered by ${{ github.actor }}\"}" $SLACK_WEBHOOK_URL
|
||||
bash scripts/notify-slack.sh "✅ MicroK8s deployment successful on ${{ matrix.os }} (${{ matrix.microk8s }}) - triggered by ${{ github.actor }}"
|
||||
- name: Send Slack Notification on Failure
|
||||
if: failure()
|
||||
env:
|
||||
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
|
||||
run: |
|
||||
curl -X POST -H 'Content-type: application/json' --data "{\"text\": \"❌ MicroK8s deployment failed on ${{ matrix.os }} (${{ matrix.microk8s }}) - <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|View logs>\"}" $SLACK_WEBHOOK_URL
|
||||
bash scripts/notify-slack.sh "❌ MicroK8s deployment failed on ${{ matrix.os }} (${{ matrix.microk8s }}) - <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|View logs>"
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
|
||||
+9
-8
@@ -24,16 +24,17 @@ With the Vault installed, we can proceed to configure the various components. Cu
|
||||
|
||||

|
||||
|
||||
- Navigate to the `Storage Providers` menu and select the (+ Add Storage Provider) button. A modal will appear where you can input the required details. After entering the information, click the "Verify" button to ensure the configuration is valid. Once you receive a "Configuration is valid and working" message, click the "Add Storage Provider" button to complete the process. **_(!You are advised to generate more complex access and secret key for Minio, this is just for demo purposes, do not use this in production)_**
|
||||
- Navigate to the `Storage Providers` menu and select the (+ Add Storage Provider) button. Verify and add the provider using the [Garage setup guide](./base/garage/README.md). These settings apply to the default Kubernetes installation; retain the matching provider settings for an existing MinIO or Docker installation.
|
||||
|
||||
- Minio
|
||||
- MinIO/S3-compatible provider type (Garage backend)
|
||||
- Enabled: true
|
||||
- Provider name: minio
|
||||
- Provider name: garage
|
||||
- Bucket name: mybucket
|
||||
- Region: na
|
||||
- Hostname: myminio-hl.minio-tenant:9000
|
||||
- Access key: minio
|
||||
- Secret key: minio123
|
||||
- Region: garage
|
||||
- Hostname: garage.garage:3900
|
||||
- SSL: false
|
||||
- Access key: `access-key` from Secret `garage/garage-credentials`
|
||||
- Secret key: `secret-key` from the same Secret
|
||||
|
||||
- Navigate to the `Integrations` menu and select the (+ Add Integration) button. A modal will appear where you can input the required details. After entering the information, click the "Verify" button to ensure the configuration is valid. Once you receive a "Configuration is valid and working" message, click the "Add Integration" button to complete the process. **_(!You are advised to generate more complex username and password for RabbitMQ, this is just for demo purposes, do not use this in production)_**
|
||||
|
||||
@@ -50,7 +51,7 @@ With the Vault installed, we can proceed to configure the various components. Cu
|
||||
|
||||
- Enabled: true
|
||||
- Account name: myaccount
|
||||
- Main provider: minio
|
||||
- Main provider: garage
|
||||
- Day limit: 30
|
||||
- Integration: rabbitmq
|
||||
- Directory: \*
|
||||
|
||||
+10
-10
@@ -1,8 +1,8 @@
|
||||
### Optimized Data Filtering for Enhanced Bandwidth Efficiency and Relevance
|
||||
|
||||
Once your Agents are properly connected and all recordings are stored in the Kerberos Vault, you may encounter additional challenges such as bandwidth limitations, storage constraints, and the need to efficiently locate relevant data. To accomplish this, we can configure an integration to filter the recordings, ensuring that only the relevant ones are retained.
|
||||
Once your Agents are properly connected and all recordings are stored in the Vault, you may encounter additional challenges such as bandwidth limitations, storage constraints, and the need to efficiently locate relevant data. To accomplish this, we can configure an integration to filter the recordings, ensuring that only the relevant ones are retained.
|
||||
|
||||
Assuming all configurations are correctly set and all Kubernetes deployments are operational, you can apply the `data-filtering-deployment.yaml` deployment. This deployment will schedule a pod that listens to the configured integration in Kerberos Vault and runs a YOLOv8 model to evaluate the recordings and match them against specified conditions.
|
||||
Assuming all configurations are correctly set and all Kubernetes deployments are operational, you can apply the `data-filtering-deployment.yaml` deployment. This deployment will schedule a pod that listens to the configured integration in Vault and runs a YOLOv8 model to evaluate the recordings and match them against specified conditions.
|
||||
|
||||
Please note that if you do not have a GPU on the device, you will need to disable the resource limit of the nvidia/gpu. Once done the filtering will run on the CPU.
|
||||
|
||||
@@ -18,7 +18,7 @@ Let's deploy the data filtering pod (with or without GPU support).
|
||||
kubectl apply -f data-filtering-deployment.yaml
|
||||
```
|
||||
|
||||
Each time a recording is stored in the Kerberos Vault, the `data-filtering` pod will receive a notification and execute the specified model (YOLOv8 by default). Based on the defined conditions, the `data-filtering` pod may forward the recording to a remote Kerberos Vault, trigger alerts, or send notifications.
|
||||
Each time a recording is stored in the Vault, the `data-filtering` pod will receive a notification and execute the specified model (YOLOv8 by default). Based on the defined conditions, the `data-filtering` pod may forward the recording to a remote Vault, trigger alerts, or send notifications.
|
||||
|
||||
Ensure that the `data-filtering` workload is actively running, receiving messages from the integration, and performing the necessary processing tasks.
|
||||
|
||||
@@ -27,7 +27,7 @@ kubectl get po -w -A
|
||||
kubectl logs -f data...
|
||||
```
|
||||
|
||||
You might see something like below, whereas the `data-filtering` pod is iterating over recordings and frames, looking for a person. Once it finds the person it will try to `forward` the recording to a remote Kerberos Vault.
|
||||
You might see something like below, whereas the `data-filtering` pod is iterating over recordings and frames, looking for a person. Once it finds the person it will try to `forward` the recording to a remote Vault.
|
||||
|
||||
```bash
|
||||
Persons: 0, Cars: 0, Trucks: 0
|
||||
@@ -49,27 +49,27 @@ Delete media from http://vault-lb.kerberos-vault/api
|
||||
8) Releasing video writer and closing video capture
|
||||
```
|
||||
|
||||
As indicated by the logs `Something went wrong while forwarding media`, the forwarding process failed due to the absence of an integration between the two `Kerberos Vaults`. Currently, only one `Kerberos Vault` is available. To enable this feature, you will need to [install a second `Kerberos Vault` in the cloud](./README.k8s-managed.md) with access to cloud storage.
|
||||
As indicated by the logs `Something went wrong while forwarding media`, the forwarding process failed due to the absence of an integration between the two `Vaults`. Currently, only one `Vault` is available. To enable this feature, you will need to [install a second `Vault` in the cloud](./README.k8s-managed.md) with access to cloud storage.
|
||||
|
||||
### Add forwarding integration
|
||||
|
||||
If you have setup a secondary Kerberos Vault in the cloud, attached cloud Object storage to it, we can continue and add an additional integration through the UI.
|
||||
If you have setup a secondary Vault in the cloud, attached cloud Object storage to it, we can continue and add an additional integration through the UI.
|
||||
|
||||
```bash
|
||||
ssh -L 8080:localhost:30080 user@server-ip -p 22
|
||||
```
|
||||
|
||||
Navigate to the `Kerberos Vault` application in your browser, access the `Integration` section, and add a new integration. This integration will connect your local Kerberos Vault to the remote Kerberos Vault, and will tell the system to set recordings in a `forwarding state`.
|
||||
Navigate to the `Vault` application in your browser, access the `Integration` section, and add a new integration. This integration will connect your local Vault to the remote Vault, and will tell the system to set recordings in a `forwarding state`.
|
||||
|
||||
- Add an integration
|
||||
|
||||
- Kerberos Vault
|
||||
- Vault
|
||||
- Enabled: true
|
||||
- Integration name: remote-vault
|
||||
- Forwarding mode: continuous
|
||||
- Url: http(s)://yourvault.com/api
|
||||
- Provider: The name of the remote storage provider
|
||||
- Access Key: The access key of the account you have created on the remote Kerberos Vault
|
||||
- Secret Access Key: The secret access key of the account you have created on the remote Kerberos Vault
|
||||
- Access Key: The access key of the account you have created on the remote Vault
|
||||
- Secret Access Key: The secret access key of the account you have created on the remote Vault
|
||||
|
||||
If the integration is functioning correctly, you should observe that recordings are initially marked in gray as "To be forwarded." After a short period, some recordings will be updated to green, indicating they have been "Forwarded by."
|
||||
|
||||
+53
-34
@@ -10,7 +10,7 @@
|
||||
|
||||
Kubernetes is an open-source platform for automating the deployment, scaling, and management of containerized applications. It provides features like automated deployment, self-healing, service discovery, and storage orchestration. Kubernetes is essential for modern cloud-native application development and operations.
|
||||
|
||||
In this tutorial, we will guide you through the installation of the Kerberos.io edge stack, which includes the Agent, Kerberos Vault, and the Data Filtering Service. This setup enables the storage of recordings from multiple cameras at the edge, facilitating local data processing and ensuring secure and efficient management of video streams.
|
||||
In this tutorial, we will guide you through installing the edge stack, which includes Agent, Vault, and the Data Filtering Service. This setup enables the storage of recordings from multiple cameras at the edge, facilitating local data processing and ensuring secure and efficient management of video streams.
|
||||
|
||||
## Install Kubernetes on Ubuntu with kubeadm
|
||||
|
||||
@@ -112,11 +112,11 @@ Ensure that all nodes are in the Ready state and all pods are in the Running sta
|
||||
|
||||
## Dependencies
|
||||
|
||||
When installing the Kerberos.io stack, several dependencies are required for storage, such as a database (e.g., MongoDB) and a message broker (e.g., RabbitMQ) for asynchronous behavior. We will install these components before setting up the Agents and Kerberos Vault.
|
||||
When installing the ecosystem, several dependencies are required for storage, such as a database (e.g., MongoDB) and a message broker (e.g., RabbitMQ) for asynchronous behavior. We will install these components before setting up the Agents and Vault.
|
||||
|
||||
### Clone repository
|
||||
|
||||
Next, we will clone this repository to our local environment. This will allow us to execute the necessary configuration files for installing the Minio operator, MongoDB Helm chart, and other required components.
|
||||
Next, clone this repository for the Garage S3 manifests, MongoDB Helm chart values, and other required components.
|
||||
|
||||
```bash
|
||||
git clone https://github.com/kerberos-io/deployment
|
||||
@@ -127,11 +127,25 @@ cd deployment
|
||||
|
||||
When you create a Kubernetes cluster using `kubeadm` on a bare metal machine
|
||||
|
||||
### Object storage: MinIO
|
||||
### Object storage: Garage (default)
|
||||
|
||||
After creating the `ssd-hostpath` StorageClass for your provisioner, run:
|
||||
|
||||
```sh
|
||||
bash scripts/install-garage.sh
|
||||
bash scripts/check-garage.sh
|
||||
```
|
||||
|
||||
See the [Garage guide](./base/garage/README.md) for generated credentials,
|
||||
Vault provider settings, persistence and existing MinIO compatibility. Garage
|
||||
uses S3 port `3900` internally and NodePort `30090`; it needs no operator.
|
||||
Skip the following legacy section when using the default installation.
|
||||
|
||||
### Optional legacy object storage: MinIO
|
||||
|
||||
MinIO is a high-performance, distributed object storage system that is compatible with Amazon S3 cloud storage service. It is designed to handle large-scale data storage and retrieval, making it an ideal choice for modern cloud-native applications.
|
||||
|
||||
In the context of the Kerberos.io stack, MinIO will be used to store recordings from the Agents. These recordings are crucial for surveillance and monitoring purposes, and having a reliable storage solution like MinIO ensures that the data is stored securely and can be accessed efficiently.
|
||||
In the context of the ecosystem, MinIO will be used to store recordings from the Agents. These recordings are crucial for surveillance and monitoring purposes, and having a reliable storage solution like MinIO ensures that the data is stored securely and can be accessed efficiently.
|
||||
|
||||
```bash
|
||||
git clone --depth 1 --branch v6.0.1 https://github.com/minio/operator.git && kubectl apply -k operator/
|
||||
@@ -213,7 +227,7 @@ To access the application, open your browser and navigate to `localhost:8080`. U
|
||||
|
||||
### Database: MongoDB
|
||||
|
||||
When using Kerberos Vault, it will persist references to the recordings stored in your storage provider in a MongoDB database. As used before, we are using `helm` to install MongoDB in our Kubernetes cluster. Within the Kerberos Vault project we are using the latest official mongodb driver, so we support all major MongoDB versions (4.x, 5.x, 6.x, 7.x).
|
||||
When using Vault, it will persist references to the recordings stored in your storage provider in a MongoDB database. As used before, we are using `helm` to install MongoDB in our Kubernetes cluster. Within the Vault project we are using the latest official mongodb driver, so we support all major MongoDB versions (4.x, 5.x, 6.x, 7.x).
|
||||
|
||||
Have a look into the `./mongodb-values.yaml` file, you will find plenty of configurations for the MongoDB helm chart. To change the username and password of the MongoDB instance, go ahead and [find the attribute where](https://github.com/kerberos-io/vault/blob/master/kubernetes/mongodb/values.yaml#L148) you can change the root password. Please note that we are using the official [Bitnami Mongodb helm chart](https://github.com/bitnami/charts/tree/main/bitnami/mongodb), so please use their repository for more indepth configuration.
|
||||
|
||||
@@ -262,9 +276,9 @@ View the RabbitMQ status and wait until it's properly running
|
||||
kubectl get po -w -A
|
||||
```
|
||||
|
||||
### Kerberos Vault
|
||||
### Vault
|
||||
|
||||
Kerberos Vault requires a configuration to connect to the MongoDB instance. To handle this a `configmap` is defined in the `./mongodb-configmap.yaml` file. Modify the MongoDB credentials in the `./mongodb-configmap.yaml` file, and make sure they match the credentials of your MongoDB instance, as described above. There are two ways of configuring the MongoDB connection, either you provide a `MONGODB_URI` or you specify the individual variables `MONGODB_USERNAME`, `MONGODB_PASSWORD`, etc.
|
||||
Vault requires a configuration to connect to the MongoDB instance. To handle this a `configmap` is defined in the `./mongodb-configmap.yaml` file. Modify the MongoDB credentials in the `./mongodb-configmap.yaml` file, and make sure they match the credentials of your MongoDB instance, as described above. There are two ways of configuring the MongoDB connection, either you provide a `MONGODB_URI` or you specify the individual variables `MONGODB_USERNAME`, `MONGODB_PASSWORD`, etc.
|
||||
|
||||
As mentioned above a managed MongoDB is easier to setup and manage, for example for MongoDB Atlas, you will get a MongoDB URI in the form of `"mongodb+srv://xx:xx@kerberos-hub.xxx.mongodb.net/?retryWrites=true&w=majority&appName=xxx"`. By applying this value into the `MONGODB_URI` field, you will have setup your MongoDB connection successfully.
|
||||
|
||||
@@ -288,7 +302,7 @@ Create the `kerberos-vault` namespace.
|
||||
kubectl create namespace kerberos-vault
|
||||
```
|
||||
|
||||
Apply the manifests, so the Kerberos Vault application is deployed and knows how to connect to the MongoDB.
|
||||
Apply the manifests, so the Vault application is deployed and knows how to connect to the MongoDB.
|
||||
|
||||
```bash
|
||||
kubectl apply -f ./mongodb-configmap.yaml -n kerberos-vault
|
||||
@@ -304,28 +318,33 @@ kubectl get po -w -A
|
||||
|
||||
#### Access the UI
|
||||
|
||||
If you have opted for the `NodePort` configuration, you can access the Kerberos Vault via the `http://localhost:30080` endpoint in your browser. For server installations without a GUI, consider setting up a reverse proxy to enable browser access from your local machine. Alternatively, you may utilize a `LoadBalancer` if one is available or if you are deploying on a managed Kubernetes service.
|
||||
If you have opted for the `NodePort` configuration, you can access the Vault via the `http://localhost:30080` endpoint in your browser. For server installations without a GUI, consider setting up a reverse proxy to enable browser access from your local machine. Alternatively, you may utilize a `LoadBalancer` if one is available or if you are deploying on a managed Kubernetes service.
|
||||
|
||||
```bash
|
||||
ssh -L 8080:localhost:30080 user@server-ip -p 22
|
||||
```
|
||||
|
||||
#### Configure the Kerberos Vault
|
||||
#### Configure the Vault
|
||||
|
||||
With the Kerberos Vault installed, we can proceed to configure the various components. Currently, this must be done through the Kerberos Vault UI, but we plan to make it configurable via environment variables, eliminating the need for manual UI configurations.
|
||||
With the Vault installed, we can proceed to configure the various components. Currently, this must be done through the Vault UI, but we plan to make it configurable via environment variables, eliminating the need for manual UI configurations.
|
||||
|
||||

|
||||
|
||||
- Navigate to the `Storage Providers` menu and select the (+ Add Storage Provider) button. A modal will appear where you can input the required details. After entering the information, click the "Verify" button to ensure the configuration is valid. Once you receive a "Configuration is valid and working" message, click the "Add Storage Provider" button to complete the process.
|
||||
|
||||
- Minio
|
||||
- MinIO/S3-compatible provider type (Garage backend)
|
||||
- Enabled: true
|
||||
- Provider name: minio
|
||||
- Provider name: garage
|
||||
- Bucket name: mybucket
|
||||
- Region: na
|
||||
- Hostname: myminio-hl.minio-tenant:9000
|
||||
- Access key: minio
|
||||
- Secret key: minio123
|
||||
- Region: garage
|
||||
- Hostname: garage.garage:3900
|
||||
- SSL: false
|
||||
- Access key: `access-key` from Secret `garage/garage-credentials`
|
||||
- Secret key: `secret-key` from the same Secret
|
||||
|
||||
For the optional legacy MinIO installation, retain that backend's hostname,
|
||||
credentials and provider name instead. See the [Garage guide](./base/garage/README.md)
|
||||
before switching an existing installation.
|
||||
|
||||
- Navigate to the `Integrations` menu and select the (+ Add Integration) button. A modal will appear where you can input the required details. After entering the information, click the "Verify" button to ensure the configuration is valid. Once you receive a "Configuration is valid and working" message, click the "Add Integration" button to complete the process.
|
||||
|
||||
@@ -342,7 +361,7 @@ With the Kerberos Vault installed, we can proceed to configure the various compo
|
||||
|
||||
- Enabled: true
|
||||
- Account name: myaccount
|
||||
- Main provider: minio
|
||||
- Main provider: garage (or the retained provider for an existing installation)
|
||||
- Day limit: 30
|
||||
- Integration: rabbitmq
|
||||
- Directory: \*
|
||||
@@ -351,26 +370,26 @@ With the Kerberos Vault installed, we can proceed to configure the various compo
|
||||
|
||||
### Create an Agent
|
||||
|
||||
After deploying the Kerberos Vault and configuring the necessary services for storage, database, and integration, you can proceed to deploy the Agent with the appropriate configuration. Review the `kerberos-agent-deployment.yaml` file and adjust the relevant settings, such as the RTSP URL, to ensure proper functionality. As mentioned below note that you can opt for the [Factory](https://github.com/kerberos-io/factory/tree/master/kubernetes) which gives you a UI to manage the creation of Agents. **_(Please note if you generated new the keys in the previous Kerberos Vault account creation, you need to update those in the Agent deployment)_**
|
||||
After deploying the Vault and configuring the necessary services for storage, database, and integration, you can proceed to deploy the Agent with the appropriate configuration. Review the `kerberos-agent-deployment.yaml` file and adjust the relevant settings, such as the RTSP URL, to ensure proper functionality. As mentioned below note that you can opt for the [Factory](https://github.com/kerberos-io/factory/tree/master/kubernetes) which gives you a UI to manage the creation of Agents. **_(Please note if you generated new the keys in the previous Vault account creation, you need to update those in the Agent deployment)_**
|
||||
|
||||
```bash
|
||||
kubectl apply -f kerberos-agent-deployment.yaml
|
||||
```
|
||||
|
||||
Review the creation of the Agent and review the logs of the container to validate the Agent is able to connect to the IP camera, and if a recording is being created and transferred to the Kerberos Vault
|
||||
Review the creation of the Agent and review the logs of the container to validate the Agent is able to connect to the IP camera, and if a recording is being created and transferred to the Vault
|
||||
|
||||
```bash
|
||||
kubectl get po -w -A
|
||||
kubectl logs -f kerberos-agent...
|
||||
```
|
||||
|
||||
To validate the Kerberos Vault and review any stored recordings, access the user interface at `http://localhost:30080` (after establishing the reverse tunnel).
|
||||
To validate the Vault and review any stored recordings, access the user interface at `http://localhost:30080` (after establishing the reverse tunnel).
|
||||
|
||||
### Create Agents through Factory
|
||||
|
||||
Managing Agents through seperate configuration files might feel cumbersome, especially for non-technical users. This is where Factory comes into the picture. Factory provides a visual view that allows you to rapidly connect cameras through a user interface, which allows users without any technical background about cameras and kubernetes create Agents.
|
||||
|
||||
Factory also requires a mongodb, just like Kerberos Vault. Luckily you can reuse the mongodb installation we have deployed earlier, the only thing we'll need to do is to create another `configmap.yaml` in the `kerberos-factory` namespace.
|
||||
Factory also requires a mongodb, just like Vault. Luckily you can reuse the mongodb installation we have deployed earlier, the only thing we'll need to do is to create another `configmap.yaml` in the `kerberos-factory` namespace.
|
||||
|
||||
Create the `kerberos-factory` namespace.
|
||||
|
||||
@@ -400,9 +419,9 @@ kubectl get po -w -A
|
||||
|
||||
### Optimized Data Filtering for Enhanced Bandwidth Efficiency and Relevance
|
||||
|
||||
Once your Agents are properly connected and all recordings are stored in the Kerberos Vault, you may encounter additional challenges such as bandwidth limitations, storage constraints, and the need to efficiently locate relevant data. To accomplish this, we can configure an integration to filter the recordings, ensuring that only the relevant ones are retained.
|
||||
Once your Agents are properly connected and all recordings are stored in the Vault, you may encounter additional challenges such as bandwidth limitations, storage constraints, and the need to efficiently locate relevant data. To accomplish this, we can configure an integration to filter the recordings, ensuring that only the relevant ones are retained.
|
||||
|
||||
Assuming all configurations are correctly set and all Kubernetes deployments are operational, you can apply the `data-filtering-deployment.yaml` deployment. This deployment will schedule a pod that listens to the configured integration in Kerberos Vault and runs a YOLOv8 model to evaluate the recordings and match them against specified conditions.
|
||||
Assuming all configurations are correctly set and all Kubernetes deployments are operational, you can apply the `data-filtering-deployment.yaml` deployment. This deployment will schedule a pod that listens to the configured integration in Vault and runs a YOLOv8 model to evaluate the recordings and match them against specified conditions.
|
||||
|
||||
Please note that if you do not have a GPU on the device, you will need to disable the resource limit of the nvidia/gpu. Once done the filtering will run on the CPU.
|
||||
|
||||
@@ -418,7 +437,7 @@ Let's deploy the data filtering pod (with or without GPU support).
|
||||
kubectl apply -f data-filtering-deployment.yaml
|
||||
```
|
||||
|
||||
Each time a recording is stored in the Kerberos Vault, the `data-filtering` pod will receive a notification and execute the specified model (YOLOv8 by default). Based on the defined conditions, the `data-filtering` pod may forward the recording to a remote Kerberos Vault, trigger alerts, or send notifications.
|
||||
Each time a recording is stored in the Vault, the `data-filtering` pod will receive a notification and execute the specified model (YOLOv8 by default). Based on the defined conditions, the `data-filtering` pod may forward the recording to a remote Vault, trigger alerts, or send notifications.
|
||||
|
||||
Ensure that the `data-filtering` workload is actively running, receiving messages from the integration, and performing the necessary processing tasks.
|
||||
|
||||
@@ -427,7 +446,7 @@ kubectl get po -w -A
|
||||
kubectl logs -f data...
|
||||
```
|
||||
|
||||
You might see something like below, whereas the `data-filtering` pod is iterating over recordings and frames, looking for a person. Once it finds the person it will try to `forward` the recording to a remote Kerberos Vault.
|
||||
You might see something like below, whereas the `data-filtering` pod is iterating over recordings and frames, looking for a person. Once it finds the person it will try to `forward` the recording to a remote Vault.
|
||||
|
||||
```bash
|
||||
Persons: 0, Cars: 0, Trucks: 0
|
||||
@@ -449,34 +468,34 @@ Delete media from http://vault-lb.kerberos-vault/api
|
||||
8) Releasing video writer and closing video capture
|
||||
```
|
||||
|
||||
As indicated by the logs `Something went wrong while forwarding media`, the forwarding process failed due to the absence of an integration between the two `Kerberos Vaults`. Currently, only one `Kerberos Vault` is available. To enable this feature, you will need to [install a second `Kerberos Vault` in the cloud](./README.k8s-managed.md) with access to cloud storage.
|
||||
As indicated by the logs `Something went wrong while forwarding media`, the forwarding process failed due to the absence of an integration between the two `Vaults`. Currently, only one `Vault` is available. To enable this feature, you will need to [install a second `Vault` in the cloud](./README.k8s-managed.md) with access to cloud storage.
|
||||
|
||||
### Add forwarding integration
|
||||
|
||||
If you have setup a secondary Kerberos Vault in the cloud, attached cloud Object storage to it, we can continue and add an additional integration through the UI.
|
||||
If you have setup a secondary Vault in the cloud, attached cloud Object storage to it, we can continue and add an additional integration through the UI.
|
||||
|
||||
```bash
|
||||
ssh -L 8080:localhost:30080 user@server-ip -p 22
|
||||
```
|
||||
|
||||
Navigate to the `Kerberos Vault` application in your browser, access the `Integration` section, and add a new integration. This integration will connect your local Kerberos Vault to the remote Kerberos Vault, and will tell the system to set recordings in a `forwarding state`.
|
||||
Navigate to the `Vault` application in your browser, access the `Integration` section, and add a new integration. This integration will connect your local Vault to the remote Vault, and will tell the system to set recordings in a `forwarding state`.
|
||||
|
||||
- Add an integration
|
||||
|
||||
- Kerberos Vault
|
||||
- Vault
|
||||
- Enabled: true
|
||||
- Integration name: remote-vault
|
||||
- Forwarding mode: continuous
|
||||
- Url: http(s)://yourvault.com/api
|
||||
- Provider: The name of the remote storage provider
|
||||
- Access Key: The access key of the account you have created on the remote Kerberos Vault
|
||||
- Secret Access Key: The secret access key of the account you have created on the remote Kerberos Vault
|
||||
- Access Key: The access key of the account you have created on the remote Vault
|
||||
- Secret Access Key: The secret access key of the account you have created on the remote Vault
|
||||
|
||||
If the integration is functioning correctly, you should observe that recordings are initially marked in gray as "To be forwarded." After a short period, some recordings will be updated to green, indicating they have been "Forwarded by."
|
||||
|
||||
## Cleanup
|
||||
|
||||
If you consider to remove the Kerberos.io stack you might just disable the microk8s installation
|
||||
If you consider to remove the ecosystem you might just disable the microk8s installation
|
||||
|
||||
```bash
|
||||
microk8s reset
|
||||
|
||||
+9
-3
@@ -86,7 +86,6 @@ microk8s enable dns
|
||||
microk8s enable dashboard
|
||||
microk8s enable nvidia
|
||||
microk8s enable hostpath-storage
|
||||
microk8s enable minio
|
||||
```
|
||||
|
||||
You can verify the status of the enabled addons by running the following command:
|
||||
@@ -103,7 +102,7 @@ kubectl get po -w -A
|
||||
|
||||
### Clone repository
|
||||
|
||||
Next, we will clone this repository to our local environment. This will allow us to execute the necessary configuration files for installing the Minio operator, MongoDB Helm chart, and other required components.
|
||||
Next, clone this repository for the Garage S3 manifests, MongoDB Helm chart values, and other required components.
|
||||
|
||||
```bash
|
||||
git clone https://github.com/kerberos-io/deployment
|
||||
@@ -112,6 +111,13 @@ cd deployment
|
||||
|
||||
## Kustomize
|
||||
|
||||
The default base uses [Garage S3](./base/garage/README.md). Before a native
|
||||
Kustomize apply, run `bash scripts/install-garage.sh --prepare-only` to create
|
||||
its namespace and persistent credentials. `configure.sh apply` does this
|
||||
automatically. Do not enable the MinIO addon for this default stack. Existing
|
||||
MinIO installations must keep their backend/provider settings until their data
|
||||
is explicitly migrated; do not prune their storage resources.
|
||||
|
||||
In contrast to the detailed installation instructions, as mentioned here, an easier option to install is to use our Kustomize configure. This will allow you to specify and create your own overlays to install all the different components through a single command line.
|
||||
|
||||
Kustomize uses the concept of `bases` and `overlays`, allowing you to customize the base installation with different settings (an overlay). Before executing the `kustomize` command below, navigate to the `overlays/microk8s/kustomization.yaml` file and modify the `inlineValues` of the Hub to match the IP address of your node. Please note that when using Multipass, WSL, or any other type of virtualization, your IP address will differ from the IP address of your host machine. Verify your IP address using the `ifconfig` command.
|
||||
@@ -185,7 +191,7 @@ namespace/kerberos-agent unchanged
|
||||
namespace/kerberos-factory unchanged
|
||||
namespace/kerberos-hub unchanged
|
||||
namespace/kerberos-vault unchanged
|
||||
namespace/minio-tenant unchanged
|
||||
namespace/garage unchanged
|
||||
namespace/mongodb unchanged
|
||||
namespace/rabbitmq unchanged
|
||||
namespace/vernemq unchanged
|
||||
|
||||
@@ -1,25 +1,51 @@
|
||||
# Deployment
|
||||
|
||||
Deploying the Kerberos.io stack may initially appear to be a complex task due to its design for scalability from the outset. This entails the integration of several scalable components within a distributed deployment architecture. To streamline the installation process, we have established this repository to offer comprehensive guidance. Our objective is to incorporate as much automation as possible within this repository, thereby ensuring that the installation process is straightforward and user-friendly. At the same time, we remain committed to delivering a scalable and highly available video surveillance system.
|
||||
Deploying the ecosystem may initially appear to be a complex task due to its design for scalability from the outset. This entails the integration of several scalable components within a distributed deployment architecture. To streamline the installation process, we have established this repository to offer comprehensive guidance. Our objective is to incorporate as much automation as possible within this repository, thereby ensuring that the installation process is straightforward and user-friendly. At the same time, we remain committed to delivering a scalable and highly available video surveillance system.
|
||||
|
||||

|
||||
[][draw-how-it-works]
|
||||
|
||||
The Kerberos.io stack offers flexible installation options, supporting deployment in hybrid environments, fully in the cloud, or entirely at the edge. This deployment guide covers the installation of various Kerberos.io components. For detailed information on each component, please refer to their respective repositories.
|
||||
[Edit in Draw][draw-how-it-works] · [Diagram source](./assets/diagrams/how-it-works.json)
|
||||
|
||||
- [Agent](https://github.com/kerberos-io/agent)
|
||||
- [Factory](https://github.com/kerberos-io/factory)
|
||||
- [Kerberos Vault](https://github.com/kerberos-io/vault)
|
||||
- [Kerberos Hub](https://github.com/kerberos-io/hub)
|
||||
The ecosystem offers flexible installation options, supporting deployment in hybrid environments, fully in the cloud, or entirely at the edge. This deployment guide covers installing its components. For detailed component documentation, please refer to the links below.
|
||||
|
||||
- [Agent](https://learn.uug.ai/docs/agent/)
|
||||
- [Factory](https://learn.uug.ai/docs/factory/)
|
||||
- [Vault](https://learn.uug.ai/docs/vault/)
|
||||
- [Hub](https://learn.uug.ai/docs/hub/)
|
||||
|
||||
## Continuous deployment
|
||||
|
||||
[<img src="https://github.com/kerberos-io/deployment/workflows/Deploy%20on%20Microk8s/badge.svg"/>](https://github.com/kerberos-io/deployment/actions/workflows/microk8s.yaml) [<img src="https://github.com/kerberos-io/deployment/workflows/Deploy%20on%20Kubernetes/badge.svg"/>](https://github.com/kerberos-io/deployment/actions/workflows/kind.yaml)
|
||||
[](https://github.com/uug-ai/deployment/actions/workflows/kind.yaml)
|
||||
[](https://github.com/uug-ai/deployment/actions/workflows/k3d.yaml)
|
||||
[](https://github.com/uug-ai/deployment/actions/workflows/microk8s.yaml)
|
||||
[](https://github.com/uug-ai/deployment/actions/workflows/kustomize.yaml)
|
||||
|
||||
This repository continuously tests the Kerberos.io deployment using GitHub Actions across various platforms. Refer to the badges for an overview of the operating systems and Kubernetes distributions we are deploying to. We welcome suggestions for additional automations to consider.
|
||||
These badges show the latest status of each GitHub Actions workflow on `main`.
|
||||
Select a badge to view its runs and platform-specific results. The deployment
|
||||
workflows continuously test the ecosystem across kind, k3d, and MicroK8s; the
|
||||
Kustomize workflow validates the Kustomize, Garage, and Factory setup.
|
||||
|
||||
Kubernetes examples and CI now use **Garage S3** for local object storage.
|
||||
See the [Garage setup guide](./base/garage/README.md) for generated credentials,
|
||||
Vault configuration, persistence tests and existing MinIO compatibility.
|
||||
This is a single-node example, not a replicated production storage deployment.
|
||||
The [MinIO manifests](./base/minio/) remain available; no existing data is
|
||||
migrated or removed automatically. The Docker guide retains its separate
|
||||
storage setup.
|
||||
|
||||
Slack notifications are optional. If `SLACK_WEBHOOK_URL` is unavailable (for
|
||||
example on fork PRs), CI emits a warning and skips delivery without masking
|
||||
deployment failures. Configured webhook delivery errors still fail the step.
|
||||
Failed deployment jobs collect pod events and bounded logs for diagnosis.
|
||||
|
||||
### Security
|
||||
|
||||
We harden our container images and check our solutions for known CVEs. See the
|
||||
[Secure repository](https://github.com/uug-ai/secure) for our security work.
|
||||
|
||||
## Architecture
|
||||
|
||||
As previously indicated, several integral components, including Object Storage, Database, and Message Brokers, are deployed and configured to ensure the proper functionality of Kerberos.io. The architecture diagrams below aims to provide a visual representation of these components and their interactions with one another depending the deployment; self-hosted or managed cloud deployment.
|
||||
As previously indicated, several integral components, including object storage, databases, and message brokers, are deployed and configured to support the ecosystem. The architecture diagrams below provide a visual representation of these components and how they interact in self-hosted and managed cloud deployments.
|
||||
|
||||
It is important to note that the ease of installation may vary depending on the chosen Kubernetes distribution and platform. For instance, distributions like Microk8s, which offer an addons feature, may simplify the installation process significantly. Managed Kubernetes services on platforms such as AWS, Azure, GCP, and others offer a range of supplementary services. These include, but are not limited to, cloud-based object storage, load balancers, persistent volumes, and additional resources that enhance the deployment experience. On the other hand running a self-hosted vanilla Kubernetes deployment will come with additinal work as it misses the out-of-the-box components from a managed deployment or the self-hosted Microk8s add-ons feature.
|
||||
|
||||
@@ -27,17 +53,28 @@ Given these differences, we have created specific architectural frameworks for s
|
||||
|
||||
## Edge (self-hosted) deployment
|
||||
|
||||
Edge (self-hosted) deployments are typically used for camera processing and edge storage. In this setup, Agents are deployed and connected to cameras, with recordings stored in the Kerberos Vault. Additionally, you may want to create integrations, such as [data filtering](https://github.com/uug-ai/data-filtering), to ensure only relevant recordings are retained, or set up custom notifications to your first or third-party platforms. In this edge scenario, hardware is being deployed in the local network to handle the workloads; for example AMD64 or ARM64 processors.
|
||||
Edge (self-hosted) deployments are typically used for camera processing and edge storage. In this setup, Agents are deployed and connected to cameras, with recordings stored in the Vault. Additionally, you may want to create integrations, such as [data filtering](https://github.com/uug-ai/data-filtering), to ensure only relevant recordings are retained, or set up custom notifications to your first or third-party platforms. In this edge scenario, hardware is being deployed in the local network to handle the workloads; for example AMD64 or ARM64 processors.
|
||||
|
||||

|
||||
[][draw-deployment-self-hosted]
|
||||
|
||||
A key aspect of this deployment is the scaling of Agents. Each camera is assigned a dedicated Agent container, which is linked to a central Kerberos Vault. The Kerberos Vault stores metadata in MongoDB, recordings in Minio (or another S3-compliant object storage), and can generate events in a message broker like RabbitMQ. This approach enables you to develop custom applications/logic that can respond to the creation of new recordings.
|
||||
[Edit in Draw][draw-deployment-self-hosted] · [Diagram source](./assets/diagrams/deployment-self-hosted.json)
|
||||
|
||||
Factory is optional and manages Agents when using Kubernetes. Event publishing
|
||||
and custom integrations are optional; recordings can stay entirely within the
|
||||
private edge network.
|
||||
|
||||
A key aspect of this deployment is the scaling of Agents. Each camera is
|
||||
assigned a dedicated Agent container, which is linked to a central Vault. Vault
|
||||
stores metadata in MongoDB, recordings in Garage (or another S3-compatible
|
||||
object storage), and can generate events in a message broker like RabbitMQ.
|
||||
This approach enables you to develop custom applications or logic that can
|
||||
respond to new recordings.
|
||||
|
||||
Based on your technology experience and preferences, you can choose from the following deployment guides:
|
||||
|
||||
- [[Easy] Install Kerberos.io on Docker](/README.docker.md)
|
||||
- [[Medium] Install Kerberos.io on Microk8s](/README.microk8s.md)
|
||||
- [[Advanced] Install Kerberos.io on Kubernetes](/README.k8s.md)
|
||||
- [[Easy] Install the ecosystem with Docker](/README.docker.md)
|
||||
- [[Medium] Install the ecosystem with Microk8s](/README.microk8s.md)
|
||||
- [[Advanced] Install the ecosystem with Kubernetes](/README.k8s.md)
|
||||
|
||||
## Managed deployment
|
||||
|
||||
@@ -59,13 +96,54 @@ As previously discussed, a managed deployment enhances resilience and high avail
|
||||
|
||||
The primary objective of maintaining a managed, public-facing deployment is to centralize multiple edge deployments through a unified interface. Typically, edge deployments are distributed across various environments such as hospitals, retail stores, and factories. These edge deployments are inherently secure and non-public facing, preventing direct internet access to these environments. To address this challenge, we operate a managed, public-facing environment that consolidates all recordings, live camera views, and permissions into a single, cohesive platform.
|
||||
|
||||

|
||||
[][draw-deployment-managed]
|
||||
|
||||
[Edit in Draw][draw-deployment-managed] · [Diagram source](./assets/diagrams/deployment-managed.json)
|
||||
|
||||
This example shows Agents uploading directly to cloud Vault, without exposing
|
||||
the camera networks to inbound internet traffic. Hybrid deployments can retain
|
||||
an edge Vault and forward selected recordings to cloud Vault instead. The
|
||||
backing services can be self-hosted or compatible managed services; their logical
|
||||
roles stay the same.
|
||||
|
||||
Based on your technology experience and preferences, you can choose from the following deployment guides:
|
||||
|
||||
- [[Medium] Install Kerberos.io on Kubernetes (AWS, GCP, Azure, etc.)](/README.k8s-managed.md)
|
||||
- [[Medium] Install the ecosystem with Kubernetes (AWS, GCP, Azure, etc.)](/README.k8s-managed.md)
|
||||
|
||||
Or provision the infrastructure yourself with infrastructure as code:
|
||||
|
||||
- [[AWS] Terraform: EKS cluster + Amazon DocumentDB](./modules/amazon-eks-documentdb/README.md)
|
||||
- [[Azure] Terraform: Event Hub with 10 partitions](./modules/azure-event-hub/README.md)
|
||||
|
||||
## Updating architecture diagrams
|
||||
|
||||
These diagrams use the same editable `groups`, `nodes`, and `connections` JSON
|
||||
format as the [Learn diagrams](https://learn.uug.ai/docs/prologue/how/) and
|
||||
[Draw](https://draw.uug.ai/). GitHub cannot run Learn's interactive renderer, so
|
||||
the README uses self-contained SVG exports from Draw, with an **Edit in Draw**
|
||||
link carrying the source in a base64-encoded UTF-8 URL fragment.
|
||||
|
||||
1. Update the corresponding JSON in [assets/diagrams](./assets/diagrams).
|
||||
Keep the product colours, labelled zones, cards and orthogonal connectors
|
||||
consistent with Learn; the overview follows Learn's solution stack.
|
||||
2. Run `node scripts/update-diagram-links.mjs` (Node.js 20+) to refresh the
|
||||
README's Draw links. Open the updated **Edit in Draw** link, or paste the
|
||||
JSON into Draw's **Templates** import.
|
||||
3. Use Draw's **Export board** action to download an SVG in light mode and
|
||||
replace the matching file in [assets/images](./assets/images). Export the
|
||||
whole diagram, not a screenshot of the editor. Draw embeds its image assets
|
||||
so GitHub does not need external icons or scripts.
|
||||
4. Run `node scripts/update-diagram-links.mjs --check` and preview the README.
|
||||
The check validates source bounds/connections, SVG presence and link
|
||||
freshness; also check the exported diagram visually.
|
||||
|
||||
Edits on a Draw board do not automatically update this repository. Mirror any
|
||||
board changes into the JSON source before refreshing the links and SVG. Commit
|
||||
the source, preview and README links together; do not hand-edit the generated
|
||||
links below.
|
||||
|
||||
<!-- BEGIN GENERATED DRAW LINKS -->
|
||||
[draw-how-it-works]: https://draw.uug.ai/#diagram=eyJncm91cHMiOlt7ImlkIjoiY2FwdHVyZSIsImxhYmVsIjoiMS4gQ2FtZXJhIHByb2Nlc3NpbmcgLSBlZGdlIC8gY2xvdWQiLCJ4IjowLCJ5IjoyMCwidyI6NTQwLCJoIjo1MjB9LHsiaWQiOiJwZXJzaXN0ZW5jZSIsImxhYmVsIjoiMi4gUGVyc2lzdGVuY2UgLSBlZGdlIC8gY2xvdWQiLCJ4Ijo2MjAsInkiOjIwLCJ3IjozMDAsImgiOjUyMH0seyJpZCI6ImFuYWx5c2lzIiwibGFiZWwiOiIzLiBBbmFseXNlIC0gZWRnZSAvIGNsb3VkIiwieCI6MTAwMCwieSI6MjAsInciOjMwMCwiaCI6NTIwfV0sIm5vZGVzIjpbeyJpZCI6ImNhbWVyYS0xIiwia2luZCI6ImNhbWVyYSIsIngiOjMwLCJ5IjoyMzAsInciOjE4MCwiaCI6MTQwLCJoZWFkZXIiOiJDQU1FUkEiLCJ0aXRsZSI6IkNhbWVyYSAxIiwic3VidGl0bGUiOiJSVFNQIHN0cmVhbSJ9LHsiaWQiOiJjYW1lcmEtMiIsImtpbmQiOiJjYW1lcmEiLCJ4IjozMCwieSI6MzkwLCJ3IjoxODAsImgiOjE0MCwiaGVhZGVyIjoiQ0FNRVJBIiwidGl0bGUiOiJDYW1lcmEgMiIsInN1YnRpdGxlIjoiUlRTUCBzdHJlYW0ifSx7ImlkIjoiZmFjdG9yeSIsImtpbmQiOiJmYWN0b3J5IiwieCI6MjgwLCJ5Ijo2MCwidyI6MjMwLCJoIjoxNDAsImhlYWRlciI6Ik9SQ0hFU1RSQVRFIiwidGl0bGUiOiJGYWN0b3J5Iiwic3VidGl0bGUiOiJNYW5hZ2Ugb24gS3ViZXJuZXRlcyJ9LHsiaWQiOiJhZ2VudC0xIiwia2luZCI6ImFnZW50IiwieCI6MjgwLCJ5IjoyMzAsInciOjIzMCwiaCI6MTQwLCJoZWFkZXIiOiJSRUNPUkQiLCJ0aXRsZSI6IkFnZW50IDEiLCJzdWJ0aXRsZSI6IlByb2Nlc3Mgb25lIGNhbWVyYSJ9LHsiaWQiOiJhZ2VudC0yIiwia2luZCI6ImFnZW50IiwieCI6MjgwLCJ5IjozOTAsInciOjIzMCwiaCI6MTQwLCJoZWFkZXIiOiJSRUNPUkQiLCJ0aXRsZSI6IkFnZW50IDIiLCJzdWJ0aXRsZSI6IlByb2Nlc3Mgb25lIGNhbWVyYSJ9LHsiaWQiOiJ2YXVsdCIsImtpbmQiOiJ2YXVsdCIsIngiOjY1MCwieSI6MjMwLCJ3IjoyNDAsImgiOjE0MCwiaGVhZGVyIjoiU1RPUkUiLCJ0aXRsZSI6IlZhdWx0Iiwic3VidGl0bGUiOiJTdG9yZSBhbmQgaW50ZWdyYXRlIn0seyJpZCI6InN0b3JhZ2UiLCJraW5kIjoic3RvcmFnZSIsIngiOjY1MCwieSI6MzkwLCJ3IjoyNDAsImgiOjE0MCwiaGVhZGVyIjoiT0JKRUNUIFNUT1JBR0UiLCJ0aXRsZSI6IlN0b3JhZ2UgYmFja2VuZCIsInN1YnRpdGxlIjoiQ2xvdWQgLyBlZGdlIn0seyJpZCI6Imh1YiIsImtpbmQiOiJodWIiLCJ4IjoxMDMwLCJ5IjoyMzAsInciOjI0MCwiaCI6MTQwLCJoZWFkZXIiOiJBTkFMWVNFIiwidGl0bGUiOiJIdWIiLCJzdWJ0aXRsZSI6Ik1vbml0b3IgYW5kIGFuYWx5c2UifV0sImNvbm5lY3Rpb25zIjpbeyJmcm9tIjoiY2FtZXJhLTEiLCJ0byI6ImFnZW50LTEiLCJmcm9tU2lkZSI6InJpZ2h0IiwidG9TaWRlIjoibGVmdCJ9LHsiZnJvbSI6ImNhbWVyYS0yIiwidG8iOiJhZ2VudC0yIiwiZnJvbVNpZGUiOiJyaWdodCIsInRvU2lkZSI6ImxlZnQifSx7ImZyb20iOiJmYWN0b3J5IiwidG8iOiJhZ2VudC0xIiwiZnJvbVNpZGUiOiJib3R0b20iLCJ0b1NpZGUiOiJ0b3AiLCJraW5kIjoiZGFzaGVkIn0seyJmcm9tIjoiZmFjdG9yeSIsInRvIjoiYWdlbnQtMiIsImZyb21TaWRlIjoicmlnaHQiLCJ0b1NpZGUiOiJyaWdodCIsImtpbmQiOiJkYXNoZWQifSx7ImZyb20iOiJhZ2VudC0xIiwidG8iOiJ2YXVsdCIsImZyb21TaWRlIjoicmlnaHQiLCJ0b1NpZGUiOiJsZWZ0In0seyJmcm9tIjoiYWdlbnQtMiIsInRvIjoidmF1bHQiLCJmcm9tU2lkZSI6InJpZ2h0IiwidG9TaWRlIjoibGVmdCJ9LHsiZnJvbSI6InZhdWx0IiwidG8iOiJzdG9yYWdlIiwiZnJvbVNpZGUiOiJib3R0b20iLCJ0b1NpZGUiOiJ0b3AifSx7ImZyb20iOiJ2YXVsdCIsInRvIjoiaHViIiwiZnJvbVNpZGUiOiJyaWdodCIsInRvU2lkZSI6ImxlZnQiLCJsYWJlbCI6IkV2ZW50cyJ9XX0=
|
||||
[draw-deployment-self-hosted]: https://draw.uug.ai/#diagram=eyJncm91cHMiOlt7ImlkIjoiZWRnZSIsImxhYmVsIjoiUHJpdmF0ZSBlZGdlIG5ldHdvcmsgLSBEb2NrZXIgLyBLdWJlcm5ldGVzIiwieCI6MCwieSI6MjAsInciOjEyNDAsImgiOjY4MH1dLCJub2RlcyI6W3siaWQiOiJjYW1lcmEtMSIsImtpbmQiOiJjYW1lcmEiLCJ4IjozMCwieSI6MjgwLCJ3IjoxODAsImgiOjE0MCwiaGVhZGVyIjoiQ0FNRVJBIiwidGl0bGUiOiJDYW1lcmEgMSIsInN1YnRpdGxlIjoiUlRTUCBzdHJlYW0ifSx7ImlkIjoiY2FtZXJhLTIiLCJraW5kIjoiY2FtZXJhIiwieCI6MzAsInkiOjUxMCwidyI6MTgwLCJoIjoxNDAsImhlYWRlciI6IkNBTUVSQSIsInRpdGxlIjoiQ2FtZXJhIDIiLCJzdWJ0aXRsZSI6IlJUU1Agc3RyZWFtIn0seyJpZCI6ImZhY3RvcnkiLCJraW5kIjoiZmFjdG9yeSIsIngiOjI4MCwieSI6ODAsInciOjIyMCwiaCI6MTQwLCJoZWFkZXIiOiJPUFRJT05BTCBPUkNIRVNUUkFUSU9OIiwidGl0bGUiOiJGYWN0b3J5Iiwic3VidGl0bGUiOiJNYW5hZ2Ugb24gS3ViZXJuZXRlcyJ9LHsiaWQiOiJhZ2VudC0xIiwia2luZCI6ImFnZW50IiwieCI6MjgwLCJ5IjoyODAsInciOjIyMCwiaCI6MTQwLCJoZWFkZXIiOiJSRUNPUkQiLCJ0aXRsZSI6IkFnZW50IDEiLCJzdWJ0aXRsZSI6Ik9uZSBjYW1lcmEgcGVyIGNvbnRhaW5lciJ9LHsiaWQiOiJhZ2VudC0yIiwia2luZCI6ImFnZW50IiwieCI6MjgwLCJ5Ijo1MTAsInciOjIyMCwiaCI6MTQwLCJoZWFkZXIiOiJSRUNPUkQiLCJ0aXRsZSI6IkFnZW50IDIiLCJzdWJ0aXRsZSI6Ik9uZSBjYW1lcmEgcGVyIGNvbnRhaW5lciJ9LHsiaWQiOiJ2YXVsdCIsImtpbmQiOiJ2YXVsdCIsIngiOjYyMCwieSI6MjgwLCJ3IjoyMzAsImgiOjE0MCwiaGVhZGVyIjoiU1RPUkUiLCJ0aXRsZSI6IlZhdWx0Iiwic3VidGl0bGUiOiJDZW50cmFsaXNlIGVkZ2UgcmVjb3JkaW5ncyJ9LHsiaWQiOiJtb25nb2RiIiwia2luZCI6ImRhdGFiYXNlIiwieCI6OTcwLCJ5Ijo4MCwidyI6MjQwLCJoIjoxNDAsImhlYWRlciI6Ik1FVEFEQVRBIiwidGl0bGUiOiJNb25nb0RCIiwic3VidGl0bGUiOiJWYXVsdCBtZXRhZGF0YSJ9LHsiaWQiOiJzdG9yYWdlIiwia2luZCI6InN0b3JhZ2UiLCJ4Ijo5NzAsInkiOjI4MCwidyI6MjQwLCJoIjoxNDAsImhlYWRlciI6IlJFQ09SRElOR1MiLCJ0aXRsZSI6Ik9iamVjdCBzdG9yYWdlIiwic3VidGl0bGUiOiJNaW5JTyAvIFMzLWNvbXBhdGlibGUifSx7ImlkIjoiYnJva2VyIiwia2luZCI6ImFtcXAiLCJ4Ijo5NzAsInkiOjUxMCwidyI6MjQwLCJoIjoxNDAsImhlYWRlciI6Ik9QVElPTkFMIEVWRU5UUyIsInRpdGxlIjoiUmFiYml0TVEiLCJzdWJ0aXRsZSI6IlJlY29yZGluZyBldmVudHMifSx7ImlkIjoiaW50ZWdyYXRpb24iLCJraW5kIjoiZGVmYXVsdCIsIngiOjYyMCwieSI6NTEwLCJ3IjoyMzAsImgiOjE0MCwiaGVhZGVyIjoiT1BUSU9OQUwgSU5URUdSQVRJT04iLCJ0aXRsZSI6IkN1c3RvbSBhcHBsaWNhdGlvbiIsInN1YnRpdGxlIjoiRmlsdGVyLCBub3RpZnkgb3IgaW50ZWdyYXRlIn1dLCJjb25uZWN0aW9ucyI6W3siZnJvbSI6ImNhbWVyYS0xIiwidG8iOiJhZ2VudC0xIiwiZnJvbVNpZGUiOiJyaWdodCIsInRvU2lkZSI6ImxlZnQiLCJsYWJlbCI6IlJUU1AifSx7ImZyb20iOiJjYW1lcmEtMiIsInRvIjoiYWdlbnQtMiIsImZyb21TaWRlIjoicmlnaHQiLCJ0b1NpZGUiOiJsZWZ0IiwibGFiZWwiOiJSVFNQIn0seyJmcm9tIjoiZmFjdG9yeSIsInRvIjoiYWdlbnQtMSIsImZyb21TaWRlIjoiYm90dG9tIiwidG9TaWRlIjoidG9wIiwia2luZCI6ImRhc2hlZCJ9LHsiZnJvbSI6ImZhY3RvcnkiLCJ0byI6ImFnZW50LTIiLCJmcm9tU2lkZSI6ImxlZnQiLCJ0b1NpZGUiOiJsZWZ0Iiwia2luZCI6ImRhc2hlZCJ9LHsiZnJvbSI6ImFnZW50LTIiLCJ0byI6InZhdWx0IiwiZnJvbVNpZGUiOiJyaWdodCIsInRvU2lkZSI6ImxlZnQifSx7ImZyb20iOiJhZ2VudC0xIiwidG8iOiJ2YXVsdCIsImZyb21TaWRlIjoicmlnaHQiLCJ0b1NpZGUiOiJsZWZ0IiwibGFiZWwiOiJVcGxvYWQifSx7ImZyb20iOiJ2YXVsdCIsInRvIjoibW9uZ29kYiIsImZyb21TaWRlIjoidG9wIiwidG9TaWRlIjoibGVmdCJ9LHsiZnJvbSI6InZhdWx0IiwidG8iOiJzdG9yYWdlIiwiZnJvbVNpZGUiOiJyaWdodCIsInRvU2lkZSI6ImxlZnQifSx7ImZyb20iOiJ2YXVsdCIsInRvIjoiYnJva2VyIiwiZnJvbVNpZGUiOiJyaWdodCIsInRvU2lkZSI6ImxlZnQiLCJsYWJlbCI6IkV2ZW50cyJ9LHsiZnJvbSI6ImJyb2tlciIsInRvIjoiaW50ZWdyYXRpb24iLCJmcm9tU2lkZSI6ImxlZnQiLCJ0b1NpZGUiOiJyaWdodCIsImxhYmVsIjoiQ29uc3VtZSJ9XX0=
|
||||
[draw-deployment-managed]: https://draw.uug.ai/#diagram=eyJncm91cHMiOlt7ImlkIjoiZWRnZSIsImxhYmVsIjoiUHJpdmF0ZSBlZGdlIHNpdGVzIC0gb3V0Ym91bmQgdXBsb2FkcyIsIngiOjAsInkiOjIwLCJ3Ijo1MDAsImgiOjc2MH0seyJpZCI6ImNsb3VkIiwibGFiZWwiOiJDbG91ZCAtIG1hbmFnZWQgS3ViZXJuZXRlcyBhbmQgYmFja2luZyBzZXJ2aWNlcyIsIngiOjYyMCwieSI6MjAsInciOjcwMCwiaCI6NzYwfV0sIm5vZGVzIjpbeyJpZCI6ImNhbWVyYS0xIiwia2luZCI6ImNhbWVyYSIsIngiOjMwLCJ5IjoxNzAsInciOjE4MCwiaCI6MTQwLCJoZWFkZXIiOiJTSVRFIEEiLCJ0aXRsZSI6IkNhbWVyYXMiLCJzdWJ0aXRsZSI6IlByaXZhdGUgbmV0d29yayJ9LHsiaWQiOiJjYW1lcmEtMiIsImtpbmQiOiJjYW1lcmEiLCJ4IjozMCwieSI6NTMwLCJ3IjoxODAsImgiOjE0MCwiaGVhZGVyIjoiU0lURSBCIiwidGl0bGUiOiJDYW1lcmFzIiwic3VidGl0bGUiOiJQcml2YXRlIG5ldHdvcmsifSx7ImlkIjoiYWdlbnQtMSIsImtpbmQiOiJhZ2VudCIsIngiOjI3MCwieSI6MTcwLCJ3IjoyMDAsImgiOjE0MCwiaGVhZGVyIjoiUkVDT1JEIiwidGl0bGUiOiJBZ2VudHMiLCJzdWJ0aXRsZSI6Ik9uZSBwZXIgY2FtZXJhIn0seyJpZCI6ImFnZW50LTIiLCJraW5kIjoiYWdlbnQiLCJ4IjoyNzAsInkiOjUzMCwidyI6MjAwLCJoIjoxNDAsImhlYWRlciI6IlJFQ09SRCIsInRpdGxlIjoiQWdlbnRzIiwic3VidGl0bGUiOiJPbmUgcGVyIGNhbWVyYSJ9LHsiaWQiOiJ2YXVsdCIsImtpbmQiOiJ2YXVsdCIsIngiOjY1MCwieSI6MTcwLCJ3IjoyMzAsImgiOjE0MCwiaGVhZGVyIjoiU1RPUkUiLCJ0aXRsZSI6IlZhdWx0Iiwic3VidGl0bGUiOiJSZWNlaXZlIHJlY29yZGluZ3MifSx7ImlkIjoic3RvcmFnZSIsImtpbmQiOiJzdG9yYWdlIiwieCI6MTA0MCwieSI6MTcwLCJ3IjoyNTAsImgiOjE0MCwiaGVhZGVyIjoiUkVDT1JESU5HUyIsInRpdGxlIjoiT2JqZWN0IHN0b3JhZ2UiLCJzdWJ0aXRsZSI6IlMzIC8gQXp1cmUgQmxvYiAvIEdDUyJ9LHsiaWQiOiJicm9rZXIiLCJraW5kIjoiYW1xcCIsIngiOjY1MCwieSI6MzgwLCJ3IjoyMzAsImgiOjE0MCwiaGVhZGVyIjoiRVZFTlRTIiwidGl0bGUiOiJSYWJiaXRNUSIsInN1YnRpdGxlIjoiUXVldWUgcmVjb3JkaW5nIGV2ZW50cyJ9LHsiaWQiOiJtb25nb2RiIiwia2luZCI6ImRhdGFiYXNlIiwieCI6MTA0MCwieSI6MzgwLCJ3IjoyNTAsImgiOjE0MCwiaGVhZGVyIjoiTUVUQURBVEEiLCJ0aXRsZSI6Ik1vbmdvREIiLCJzdWJ0aXRsZSI6IlZhdWx0IC8gSHViIGRhdGFiYXNlcyJ9LHsiaWQiOiJodWIiLCJraW5kIjoiaHViIiwieCI6NjUwLCJ5Ijo2MDAsInciOjIzMCwiaCI6MTQwLCJoZWFkZXIiOiJBTkFMWVNFIiwidGl0bGUiOiJIdWIiLCJzdWJ0aXRsZSI6IlBpcGVsaW5lLCBBUEkgYW5kIFVJIn1dLCJjb25uZWN0aW9ucyI6W3siZnJvbSI6ImNhbWVyYS0xIiwidG8iOiJhZ2VudC0xIiwiZnJvbVNpZGUiOiJyaWdodCIsInRvU2lkZSI6ImxlZnQifSx7ImZyb20iOiJjYW1lcmEtMiIsInRvIjoiYWdlbnQtMiIsImZyb21TaWRlIjoicmlnaHQiLCJ0b1NpZGUiOiJsZWZ0In0seyJmcm9tIjoiYWdlbnQtMiIsInRvIjoidmF1bHQiLCJmcm9tU2lkZSI6InJpZ2h0IiwidG9TaWRlIjoibGVmdCJ9LHsiZnJvbSI6ImFnZW50LTEiLCJ0byI6InZhdWx0IiwiZnJvbVNpZGUiOiJyaWdodCIsInRvU2lkZSI6ImxlZnQiLCJsYWJlbCI6IkhUVFBTIHVwbG9hZCJ9LHsiZnJvbSI6InZhdWx0IiwidG8iOiJtb25nb2RiIiwiZnJvbVNpZGUiOiJyaWdodCIsInRvU2lkZSI6ImxlZnQifSx7ImZyb20iOiJ2YXVsdCIsInRvIjoic3RvcmFnZSIsImZyb21TaWRlIjoicmlnaHQiLCJ0b1NpZGUiOiJsZWZ0IiwibGFiZWwiOiJSZWNvcmRpbmdzIn0seyJmcm9tIjoidmF1bHQiLCJ0byI6ImJyb2tlciIsImZyb21TaWRlIjoiYm90dG9tIiwidG9TaWRlIjoidG9wIiwibGFiZWwiOiJFdmVudHMifSx7ImZyb20iOiJicm9rZXIiLCJ0byI6Imh1YiIsImZyb21TaWRlIjoiYm90dG9tIiwidG9TaWRlIjoidG9wIiwibGFiZWwiOiJQcm9jZXNzIn0seyJmcm9tIjoiaHViIiwidG8iOiJtb25nb2RiIiwiZnJvbVNpZGUiOiJyaWdodCIsInRvU2lkZSI6ImJvdHRvbSJ9XX0=
|
||||
<!-- END GENERATED DRAW LINKS -->
|
||||
|
||||
+32
-13
@@ -71,7 +71,7 @@ For more detailed instructions and troubleshooting, please refer to the official
|
||||
|
||||
## Dependencies
|
||||
|
||||
Before installing, several dependencies are required for storage, such as a database (e.g., MongoDB) and a message broker (e.g., RabbitMQ) for asynchronous behavior. We will install these components before setting up the Agents and Kerberos Vault.
|
||||
Before installing, several dependencies are required for storage, such as a database (e.g., MongoDB) and a message broker (e.g., RabbitMQ) for asynchronous behavior. We will install these components before setting up the Agents and Vault.
|
||||
|
||||
One of the key advantages of MicroK8s is its out-of-the-box addons, which can be enabled with a single command. This eliminates the need for complex Helm charts or operators, simplifying the setup process. We will enable some common services, such as DNS, GPU support, and storage, to streamline the installation.
|
||||
|
||||
@@ -96,14 +96,29 @@ kubectl get po -w -A
|
||||
|
||||
### Clone repository
|
||||
|
||||
Next, we will clone this repository to our local environment. This will allow us to execute the necessary configuration files for installing the Minio operator, MongoDB Helm chart, and other required components.
|
||||
Next, clone this repository for the Garage S3 manifests, MongoDB Helm chart values, and other required components.
|
||||
|
||||
```bash
|
||||
git clone https://github.com/kerberos-io/deployment
|
||||
cd deployment
|
||||
```
|
||||
|
||||
### Object storage: MinIO
|
||||
### Object storage: Garage (default)
|
||||
|
||||
Create the `ssd-hostpath` StorageClass backed by MicroK8s hostpath storage:
|
||||
|
||||
```sh
|
||||
kubectl apply -f base/ssd-hostpath-storageclass.yaml
|
||||
bash scripts/install-garage.sh
|
||||
bash scripts/check-garage.sh
|
||||
```
|
||||
|
||||
See the [Garage guide](./base/garage/README.md) for generated credentials,
|
||||
Vault settings and persistence. Garage uses S3 port `3900` internally and
|
||||
NodePort `30090`; no MinIO operator or addon is required. Skip the following
|
||||
legacy section when using the default installation.
|
||||
|
||||
### Optional legacy object storage: MinIO
|
||||
|
||||
MinIO is a high-performance, distributed object storage system that is compatible with Amazon S3 cloud storage service. It is designed to handle large-scale data storage and retrieval, making it an ideal choice for modern cloud-native applications.
|
||||
|
||||
@@ -189,7 +204,7 @@ To access the application, open your browser and navigate to `localhost:8080`. U
|
||||
|
||||
### Database: MongoDB
|
||||
|
||||
When using Vault, it will persist references to the recordings stored in your storage provider in a MongoDB database. As used before, we are using `helm` to install MongoDB in our Kubernetes cluster. Within the Kerberos Vault project we are using the latest official mongodb driver, so we support all major MongoDB versions (4.x, 5.x, 6.x, 7.x).
|
||||
When using Vault, it will persist references to the recordings stored in your storage provider in a MongoDB database. As used before, we are using `helm` to install MongoDB in our Kubernetes cluster. Within the Vault project we are using the latest official mongodb driver, so we support all major MongoDB versions (4.x, 5.x, 6.x, 7.x).
|
||||
|
||||
Have a look into the `./mongodb-values.yaml` file, you will find plenty of configurations for the MongoDB helm chart. To change the username and password of the MongoDB instance, go ahead and [find the attribute where](https://github.com/kerberos-io/vault/blob/master/kubernetes/mongodb/values.yaml#L148) you can change the root password. Please note that we are using the official [Bitnami Mongodb helm chart](https://github.com/bitnami/charts/tree/main/bitnami/mongodb), so please use their repository for more indepth configuration.
|
||||
|
||||
@@ -299,16 +314,20 @@ With the Vault installed, we can proceed to configure the various components. Cu
|
||||
|
||||

|
||||
|
||||
- Navigate to the `Storage Providers` menu and select the (+ Add Storage Provider) button. A modal will appear where you can input the required details. After entering the information, click the "Verify" button to ensure the configuration is valid. Once you receive a "Configuration is valid and working" message, click the "Add Storage Provider" button to complete the process. **_(!You are advised to generate more complex access and secret key for Minio, this is just for demo purposes, do not use this in production)_**
|
||||
- Navigate to the `Storage Providers` menu and select the (+ Add Storage Provider) button. Verify and add the provider using the [Garage setup guide](./base/garage/README.md).
|
||||
|
||||
- Minio
|
||||
- MinIO/S3-compatible provider type (Garage backend)
|
||||
- Enabled: true
|
||||
- Provider name: minio
|
||||
- Provider name: garage
|
||||
- Bucket name: mybucket
|
||||
- Region: na
|
||||
- Hostname: myminio-hl.minio-tenant:9000
|
||||
- Access key: minio
|
||||
- Secret key: minio123
|
||||
- Region: garage
|
||||
- Hostname: garage.garage:3900
|
||||
- SSL: false
|
||||
- Access key: `access-key` from Secret `garage/garage-credentials`
|
||||
- Secret key: `secret-key` from the same Secret
|
||||
|
||||
For the optional legacy MinIO installation, retain that backend's hostname,
|
||||
credentials and provider name instead.
|
||||
|
||||
- Navigate to the `Integrations` menu and select the (+ Add Integration) button. A modal will appear where you can input the required details. After entering the information, click the "Verify" button to ensure the configuration is valid. Once you receive a "Configuration is valid and working" message, click the "Add Integration" button to complete the process. **_(!You are advised to generate more complex username and password for RabbitMQ, this is just for demo purposes, do not use this in production)_**
|
||||
|
||||
@@ -325,7 +344,7 @@ With the Vault installed, we can proceed to configure the various components. Cu
|
||||
|
||||
- Enabled: true
|
||||
- Account name: myaccount
|
||||
- Main provider: minio
|
||||
- Main provider: garage (or the retained provider for an existing installation)
|
||||
- Day limit: 30
|
||||
- Integration: rabbitmq
|
||||
- Directory: \*
|
||||
@@ -412,7 +431,7 @@ kubectl apply -f kerberos-hub-create-database-job.yaml -n kerberos-hub
|
||||
|
||||
## Cleanup
|
||||
|
||||
If you consider to remove the Kerberos.io stack you might just disable the microk8s installation
|
||||
If you consider to remove the ecosystem you might just disable the microk8s installation
|
||||
|
||||
```bash
|
||||
microk8s reset
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"groups": [
|
||||
{ "id": "edge", "label": "Private edge sites - outbound uploads", "x": 0, "y": 20, "w": 500, "h": 760 },
|
||||
{ "id": "cloud", "label": "Cloud - managed Kubernetes and backing services", "x": 620, "y": 20, "w": 700, "h": 760 }
|
||||
],
|
||||
"nodes": [
|
||||
{ "id": "camera-1", "kind": "camera", "x": 30, "y": 170, "w": 180, "h": 140,
|
||||
"header": "SITE A", "title": "Cameras", "subtitle": "Private network" },
|
||||
{ "id": "camera-2", "kind": "camera", "x": 30, "y": 530, "w": 180, "h": 140,
|
||||
"header": "SITE B", "title": "Cameras", "subtitle": "Private network" },
|
||||
{ "id": "agent-1", "kind": "agent", "x": 270, "y": 170, "w": 200, "h": 140,
|
||||
"header": "RECORD", "title": "Agents", "subtitle": "One per camera" },
|
||||
{ "id": "agent-2", "kind": "agent", "x": 270, "y": 530, "w": 200, "h": 140,
|
||||
"header": "RECORD", "title": "Agents", "subtitle": "One per camera" },
|
||||
{ "id": "vault", "kind": "vault", "x": 650, "y": 170, "w": 230, "h": 140,
|
||||
"header": "STORE", "title": "Vault", "subtitle": "Receive recordings" },
|
||||
{ "id": "storage", "kind": "storage", "x": 1040, "y": 170, "w": 250, "h": 140,
|
||||
"header": "RECORDINGS", "title": "Object storage", "subtitle": "S3 / Azure Blob / GCS" },
|
||||
{ "id": "broker", "kind": "amqp", "x": 650, "y": 380, "w": 230, "h": 140,
|
||||
"header": "EVENTS", "title": "RabbitMQ", "subtitle": "Queue recording events" },
|
||||
{ "id": "mongodb", "kind": "database", "x": 1040, "y": 380, "w": 250, "h": 140,
|
||||
"header": "METADATA", "title": "MongoDB", "subtitle": "Vault / Hub databases" },
|
||||
{ "id": "hub", "kind": "hub", "x": 650, "y": 600, "w": 230, "h": 140,
|
||||
"header": "ANALYSE", "title": "Hub", "subtitle": "Pipeline, API and UI" }
|
||||
],
|
||||
"connections": [
|
||||
{ "from": "camera-1", "to": "agent-1", "fromSide": "right", "toSide": "left" },
|
||||
{ "from": "camera-2", "to": "agent-2", "fromSide": "right", "toSide": "left" },
|
||||
{ "from": "agent-2", "to": "vault", "fromSide": "right", "toSide": "left" },
|
||||
{ "from": "agent-1", "to": "vault", "fromSide": "right", "toSide": "left", "label": "HTTPS upload" },
|
||||
{ "from": "vault", "to": "mongodb", "fromSide": "right", "toSide": "left" },
|
||||
{ "from": "vault", "to": "storage", "fromSide": "right", "toSide": "left", "label": "Recordings" },
|
||||
{ "from": "vault", "to": "broker", "fromSide": "bottom", "toSide": "top", "label": "Events" },
|
||||
{ "from": "broker", "to": "hub", "fromSide": "bottom", "toSide": "top", "label": "Process" },
|
||||
{ "from": "hub", "to": "mongodb", "fromSide": "right", "toSide": "bottom" }
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
{
|
||||
"groups": [
|
||||
{ "id": "edge", "label": "Private edge network - Docker / Kubernetes", "x": 0, "y": 20, "w": 1240, "h": 680 }
|
||||
],
|
||||
"nodes": [
|
||||
{ "id": "camera-1", "kind": "camera", "x": 30, "y": 280, "w": 180, "h": 140,
|
||||
"header": "CAMERA", "title": "Camera 1", "subtitle": "RTSP stream" },
|
||||
{ "id": "camera-2", "kind": "camera", "x": 30, "y": 510, "w": 180, "h": 140,
|
||||
"header": "CAMERA", "title": "Camera 2", "subtitle": "RTSP stream" },
|
||||
{ "id": "factory", "kind": "factory", "x": 280, "y": 80, "w": 220, "h": 140,
|
||||
"header": "OPTIONAL ORCHESTRATION", "title": "Factory", "subtitle": "Manage on Kubernetes" },
|
||||
{ "id": "agent-1", "kind": "agent", "x": 280, "y": 280, "w": 220, "h": 140,
|
||||
"header": "RECORD", "title": "Agent 1", "subtitle": "One camera per container" },
|
||||
{ "id": "agent-2", "kind": "agent", "x": 280, "y": 510, "w": 220, "h": 140,
|
||||
"header": "RECORD", "title": "Agent 2", "subtitle": "One camera per container" },
|
||||
{ "id": "vault", "kind": "vault", "x": 620, "y": 280, "w": 230, "h": 140,
|
||||
"header": "STORE", "title": "Vault", "subtitle": "Centralise edge recordings" },
|
||||
{ "id": "mongodb", "kind": "database", "x": 970, "y": 80, "w": 240, "h": 140,
|
||||
"header": "METADATA", "title": "MongoDB", "subtitle": "Vault metadata" },
|
||||
{ "id": "storage", "kind": "storage", "x": 970, "y": 280, "w": 240, "h": 140,
|
||||
"header": "RECORDINGS", "title": "Object storage", "subtitle": "MinIO / S3-compatible" },
|
||||
{ "id": "broker", "kind": "amqp", "x": 970, "y": 510, "w": 240, "h": 140,
|
||||
"header": "OPTIONAL EVENTS", "title": "RabbitMQ", "subtitle": "Recording events" },
|
||||
{ "id": "integration", "kind": "default", "x": 620, "y": 510, "w": 230, "h": 140,
|
||||
"header": "OPTIONAL INTEGRATION", "title": "Custom application", "subtitle": "Filter, notify or integrate" }
|
||||
],
|
||||
"connections": [
|
||||
{ "from": "camera-1", "to": "agent-1", "fromSide": "right", "toSide": "left", "label": "RTSP" },
|
||||
{ "from": "camera-2", "to": "agent-2", "fromSide": "right", "toSide": "left", "label": "RTSP" },
|
||||
{ "from": "factory", "to": "agent-1", "fromSide": "bottom", "toSide": "top", "kind": "dashed" },
|
||||
{ "from": "factory", "to": "agent-2", "fromSide": "left", "toSide": "left", "kind": "dashed" },
|
||||
{ "from": "agent-2", "to": "vault", "fromSide": "right", "toSide": "left" },
|
||||
{ "from": "agent-1", "to": "vault", "fromSide": "right", "toSide": "left", "label": "Upload" },
|
||||
{ "from": "vault", "to": "mongodb", "fromSide": "top", "toSide": "left" },
|
||||
{ "from": "vault", "to": "storage", "fromSide": "right", "toSide": "left" },
|
||||
{ "from": "vault", "to": "broker", "fromSide": "right", "toSide": "left", "label": "Events" },
|
||||
{ "from": "broker", "to": "integration", "fromSide": "left", "toSide": "right", "label": "Consume" }
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"groups": [
|
||||
{ "id": "capture", "label": "1. Camera processing - edge / cloud", "x": 0, "y": 20, "w": 540, "h": 520 },
|
||||
{ "id": "persistence", "label": "2. Persistence - edge / cloud", "x": 620, "y": 20, "w": 300, "h": 520 },
|
||||
{ "id": "analysis", "label": "3. Analyse - edge / cloud", "x": 1000, "y": 20, "w": 300, "h": 520 }
|
||||
],
|
||||
"nodes": [
|
||||
{ "id": "camera-1", "kind": "camera", "x": 30, "y": 230, "w": 180, "h": 140,
|
||||
"header": "CAMERA", "title": "Camera 1", "subtitle": "RTSP stream" },
|
||||
{ "id": "camera-2", "kind": "camera", "x": 30, "y": 390, "w": 180, "h": 140,
|
||||
"header": "CAMERA", "title": "Camera 2", "subtitle": "RTSP stream" },
|
||||
{ "id": "factory", "kind": "factory", "x": 280, "y": 60, "w": 230, "h": 140,
|
||||
"header": "ORCHESTRATE", "title": "Factory", "subtitle": "Manage on Kubernetes" },
|
||||
{ "id": "agent-1", "kind": "agent", "x": 280, "y": 230, "w": 230, "h": 140,
|
||||
"header": "RECORD", "title": "Agent 1", "subtitle": "Process one camera" },
|
||||
{ "id": "agent-2", "kind": "agent", "x": 280, "y": 390, "w": 230, "h": 140,
|
||||
"header": "RECORD", "title": "Agent 2", "subtitle": "Process one camera" },
|
||||
{ "id": "vault", "kind": "vault", "x": 650, "y": 230, "w": 240, "h": 140,
|
||||
"header": "STORE", "title": "Vault", "subtitle": "Store and integrate" },
|
||||
{ "id": "storage", "kind": "storage", "x": 650, "y": 390, "w": 240, "h": 140,
|
||||
"header": "OBJECT STORAGE", "title": "Storage backend", "subtitle": "Cloud / edge" },
|
||||
{ "id": "hub", "kind": "hub", "x": 1030, "y": 230, "w": 240, "h": 140,
|
||||
"header": "ANALYSE", "title": "Hub", "subtitle": "Monitor and analyse" }
|
||||
],
|
||||
"connections": [
|
||||
{ "from": "camera-1", "to": "agent-1", "fromSide": "right", "toSide": "left" },
|
||||
{ "from": "camera-2", "to": "agent-2", "fromSide": "right", "toSide": "left" },
|
||||
{ "from": "factory", "to": "agent-1", "fromSide": "bottom", "toSide": "top", "kind": "dashed" },
|
||||
{ "from": "factory", "to": "agent-2", "fromSide": "right", "toSide": "right", "kind": "dashed" },
|
||||
{ "from": "agent-1", "to": "vault", "fromSide": "right", "toSide": "left" },
|
||||
{ "from": "agent-2", "to": "vault", "fromSide": "right", "toSide": "left" },
|
||||
{ "from": "vault", "to": "storage", "fromSide": "bottom", "toSide": "top" },
|
||||
{ "from": "vault", "to": "hub", "fromSide": "right", "toSide": "left", "label": "Events" }
|
||||
]
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 994 KiB After Width: | Height: | Size: 91 KiB |
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 694 KiB After Width: | Height: | Size: 95 KiB |
+1
-4363
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 2.1 MiB After Width: | Height: | Size: 83 KiB |
+44
-3
@@ -15,7 +15,7 @@ deploy, configure and observe Agents (one Deployment + Service per camera).
|
||||
|
||||
| File | Kind | Purpose |
|
||||
| ---- | ---- | ------- |
|
||||
| [`kerberos-factory-deployment.yaml`](./kerberos-factory-deployment.yaml) | `Deployment` | The Factory web app/API (`uugai/factory`), container port `80`. |
|
||||
| [`kerberos-factory-deployment.yaml`](./kerberos-factory-deployment.yaml) | `Deployment` | Hardened `ghcr.io/uug-ai/factory:v2.0.13`, pinned to its verified multi-architecture digest, container port `8080`. |
|
||||
| [`kerberos-factory-service.yaml`](./kerberos-factory-service.yaml) | `Service` | Exposes Factory on `NodePort` **30079** (a `LoadBalancer` variant is included, commented out). |
|
||||
| [`kerberos-factory-clusterrole.yaml`](./kerberos-factory-clusterrole.yaml) | `ClusterRole` + `ClusterRoleBinding` | Grants the `default` ServiceAccount in `kerberos-factory` the API access Factory needs to manage Agents. |
|
||||
|
||||
@@ -50,7 +50,47 @@ Other relevant environment variables:
|
||||
| `KERBEROS_AGENT_IMAGE` | `kerberos/agent:latest` | Image used when Factory creates an Agent. |
|
||||
| `KERBEROS_AGENT_MEMORY_LIMIT` | `256Mi` | Default memory limit for created Agents. |
|
||||
| `NAMESPACE` | `kerberos-factory` | Namespace Factory schedules Agents into. |
|
||||
| `K8S_PROXY` | `http://localhost:80` | Internal proxy address Factory calls for the `/kubernetes` API. |
|
||||
| `PORT` | `8080` | Unprivileged HTTP listener used by the hardened image. |
|
||||
| `K8S_PROXY` | `http://localhost:8080` | Internal proxy address Factory calls for the `/kubernetes` API. |
|
||||
|
||||
## Hardened runtime and upgrades
|
||||
|
||||
The image runs as UID/GID `65532:65532`, with a read-only root filesystem,
|
||||
all Linux capabilities dropped, privilege escalation disabled and the
|
||||
`RuntimeDefault` seccomp profile. The UI login named `root` is independent
|
||||
of the container's operating-system user.
|
||||
|
||||
Two disk-backed `emptyDir` volumes are writable:
|
||||
|
||||
- `/home/factory/config` receives missing seed configuration files.
|
||||
- `/tmp` is scratch space, including multipart uploads.
|
||||
|
||||
The pod's `fsGroup: 65532` makes these volumes writable without a root
|
||||
init container. They survive a container restart but are replaced with the
|
||||
pod. In this base's `configmap` mode, the global configuration is restored
|
||||
from the existing Kubernetes ConfigMap on startup; existing global/template
|
||||
ConfigMaps are not overwritten by image defaults. Keep the existing
|
||||
ServiceAccount token and RBAC: Factory manages Agents through the Kubernetes
|
||||
API even though its process is non-root.
|
||||
|
||||
Apply the Deployment and Service together when upgrading from a legacy
|
||||
port-80 image. The external Service port `80` and NodePort `30079` are unchanged;
|
||||
the Service now targets the named `http` port on container port `8080`.
|
||||
Startup, readiness and liveness probes use `/healthz`; this endpoint checks
|
||||
the HTTP process, not all downstream Kubernetes dependencies.
|
||||
|
||||
Back up any legacy configuration stored only in the old container before
|
||||
replacing its pod. For `FACTORY_CONFIGURATION=json`, replace the config
|
||||
`emptyDir` with a writable PVC and preserve its existing JSON files before
|
||||
upgrading. A PVC must support access by UID/GID `65532`; storage backends that
|
||||
do not honor `fsGroup` need matching permissions provisioned separately.
|
||||
|
||||
CI upgrades the last legacy release (`v2.0.11`) to these actual base manifests
|
||||
on kind. It checks the restricted runtime, Service routing, UI/login,
|
||||
ConfigMap bootstrap, saving settings and persistence after pod replacement.
|
||||
The [smoke test](../../scripts/check-factory.sh) changes settings and restarts
|
||||
Factory, so it refuses non-CI invocation and is intended only for disposable
|
||||
test clusters.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
@@ -122,7 +162,8 @@ supports other stores via `FACTORY_CONFIGURATION`:
|
||||
- `configmap` *(default here)* — config in ConfigMaps, no MongoDB.
|
||||
- `secret` — same as `configmap` but sensitive values are kept in Kubernetes Secrets
|
||||
(add `secrets` to the ClusterRole resources for this mode).
|
||||
- `json` — config in local JSON files on the pod, no MongoDB.
|
||||
- `json` — config in local JSON files, no MongoDB. Use a PVC at
|
||||
`/home/factory/config`; the default `emptyDir` is not durable across pods.
|
||||
- `mongodb` — legacy behaviour: Factory and Agents read config from MongoDB. For this
|
||||
you also need a reachable MongoDB and the corresponding `MONGODB_*` environment
|
||||
variables (e.g. via a `mongodb` ConfigMap mounted with `envFrom`).
|
||||
|
||||
@@ -18,9 +18,21 @@ spec:
|
||||
labels:
|
||||
app: factory
|
||||
spec:
|
||||
securityContext:
|
||||
fsGroup: 65532
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
containers:
|
||||
- name: factory
|
||||
image: ghcr.io/uug-ai/factory:v2.0.4
|
||||
image: ghcr.io/uug-ai/factory:v2.0.13@sha256:ade073660d911ca66d75b2abc298f1ddcbfbfe43aeed44e60fc1984b49b73d95
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
runAsUser: 65532
|
||||
runAsGroup: 65532
|
||||
readOnlyRootFilesystem: true
|
||||
allowPrivilegeEscalation: false
|
||||
capabilities:
|
||||
drop: ["ALL"]
|
||||
resources:
|
||||
requests:
|
||||
memory: 128Mi
|
||||
@@ -29,8 +41,36 @@ spec:
|
||||
memory: 128Mi
|
||||
cpu: 100m
|
||||
ports:
|
||||
- containerPort: 80
|
||||
- name: http
|
||||
containerPort: 8080
|
||||
protocol: TCP
|
||||
startupProbe:
|
||||
httpGet:
|
||||
path: /healthz
|
||||
port: http
|
||||
failureThreshold: 30
|
||||
periodSeconds: 2
|
||||
timeoutSeconds: 2
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /healthz
|
||||
port: http
|
||||
periodSeconds: 5
|
||||
timeoutSeconds: 2
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /healthz
|
||||
port: http
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 2
|
||||
volumeMounts:
|
||||
- name: factory-config
|
||||
mountPath: /home/factory/config
|
||||
- name: factory-tmp
|
||||
mountPath: /tmp
|
||||
env:
|
||||
- name: PORT
|
||||
value: "8080"
|
||||
- name: GIN_MODE
|
||||
value: release
|
||||
- name: KERBEROS_LOGIN_USERNAME
|
||||
@@ -55,5 +95,9 @@ spec:
|
||||
- name: FACTORY_ENVIRONMENT
|
||||
value: "kubernetes"
|
||||
- name: K8S_PROXY
|
||||
value: http://localhost:80
|
||||
|
||||
value: http://localhost:8080
|
||||
volumes:
|
||||
- name: factory-config
|
||||
emptyDir: {}
|
||||
- name: factory-tmp
|
||||
emptyDir: {}
|
||||
|
||||
@@ -10,7 +10,7 @@ spec:
|
||||
type: NodePort
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 80
|
||||
targetPort: http
|
||||
nodePort: 30079 # You can specify a port in the range 30000-32767 or let Kubernetes assign one automatically
|
||||
name: frontend
|
||||
protocol: TCP
|
||||
@@ -27,7 +27,7 @@ spec:
|
||||
# type: LoadBalancer
|
||||
# ports:
|
||||
# - port: 80
|
||||
# targetPort: 80
|
||||
# targetPort: http
|
||||
# name: frontend
|
||||
# protocol: TCP
|
||||
# selector:
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
# Garage S3 for local Kubernetes deployments
|
||||
|
||||
The default Kubernetes stack uses [Garage](https://garagehq.deuxfleurs.fr/),
|
||||
not the MinIO operator. The pinned multi-architecture `dxflrs/garage:v2.5.0`
|
||||
image runs as a single non-root node with SQLite metadata and object data on
|
||||
the same 10Gi `ssd-hostpath` PVC. This is a local/edge/CI example with **no
|
||||
replication or high availability**, not a production multi-node layout.
|
||||
Use Garage's [production deployment guide](https://garagehq.deuxfleurs.fr/documentation/cookbook/real-world/)
|
||||
for replicated storage. Choose capacity and a backup policy before storing
|
||||
recordings; resizing a bound PVC depends on your storage provisioner.
|
||||
|
||||
## Install
|
||||
|
||||
First install your storage provisioner and create the `ssd-hostpath`
|
||||
StorageClass (the same prerequisite used by MongoDB and RabbitMQ). Run commands
|
||||
from the deployment repository root:
|
||||
|
||||
```sh
|
||||
bash scripts/install-garage.sh
|
||||
bash scripts/check-garage.sh
|
||||
```
|
||||
|
||||
The installer generates an RPC secret and S3 credentials in the Kubernetes
|
||||
Secret `garage/garage-credentials`, and reuses them on subsequent runs. No
|
||||
credentials are committed to the repository. Garage's `--single-node` and
|
||||
`--default-bucket` startup flags initialize the layout and `mybucket`.
|
||||
The installer refuses to generate new credentials if the PVC already exists
|
||||
but its Secret is missing: restore the original Secret instead.
|
||||
|
||||
The installer requires `kubectl`, `jq` and `openssl`. The smoke test also
|
||||
requires AWS CLI and `curl` (provided by the GitHub-hosted CI runners).
|
||||
|
||||
For a full Kustomize installation, prepare credentials before applying the
|
||||
overlay; the default base already includes Garage:
|
||||
|
||||
```sh
|
||||
bash scripts/install-garage.sh --prepare-only
|
||||
kubectl kustomize overlays/microk8s --enable-helm --load-restrictor LoadRestrictionsNone | kubectl apply -f -
|
||||
kubectl -n garage rollout status statefulset/garage --timeout=300s
|
||||
```
|
||||
|
||||
The `configure.sh apply` helper also prepares the Secret before applying its
|
||||
overlay. Back up the Secret and the PVC together. Do not delete the namespace,
|
||||
Secret or PVC as an upgrade/recovery step.
|
||||
|
||||
## Configure Vault
|
||||
|
||||
Add a storage provider using Vault's existing **MinIO/S3-compatible provider
|
||||
type**. The provider *name* identifies the instance and is distinct from its
|
||||
implementation type:
|
||||
|
||||
| Setting | Value |
|
||||
| --- | --- |
|
||||
| Provider type | MinIO (`minio`) |
|
||||
| Provider name | `garage` |
|
||||
| Bucket | `mybucket` |
|
||||
| Region | `garage` |
|
||||
| Internal hostname | `garage.garage:3900` (no URL scheme) |
|
||||
| SSL | Disabled for this local HTTP example |
|
||||
| Access key | Secret field `access-key` |
|
||||
| Secret key | Secret field `secret-key` |
|
||||
|
||||
Retrieve credentials locally when configuring Vault; do not paste them into
|
||||
logs, issues, or committed values:
|
||||
|
||||
```sh
|
||||
kubectl -n garage get secret garage-credentials -o jsonpath='{.data.access-key}' | base64 --decode
|
||||
kubectl -n garage get secret garage-credentials -o jsonpath='{.data.secret-key}' | base64 --decode
|
||||
```
|
||||
|
||||
The S3 endpoint is exposed at `http://NODE_IP:30090`. If browsers or remote
|
||||
clients consume provider-native presigned URLs, configure Vault's external
|
||||
hostname as `NODE_IP:30090` with external SSL disabled (or a real TLS endpoint).
|
||||
Cluster-only DNS names cannot be resolved by external clients. Protect exposed
|
||||
ports with firewall rules and use TLS outside a trusted local network. Garage's
|
||||
RPC port is bound to loopback; no admin API or web console is exposed.
|
||||
|
||||
Set the Vault account's main provider to `garage`. The supplied Hub values
|
||||
also use that name for recording, archive, thumbnail and sprite access.
|
||||
**Vault account credentials are separate from Garage S3 credentials**: keep
|
||||
the existing Agent/Hub account credentials aligned with the Vault account,
|
||||
not with the generated S3 key.
|
||||
|
||||
## Verification
|
||||
|
||||
`scripts/check-garage.sh` uses AWS CLI for an authenticated Signature V4 PUT/GET
|
||||
through the Kubernetes Service and compares object bytes. It retains a small,
|
||||
uniquely named object under `mybucket/ci-smoke/`; it never deletes existing
|
||||
objects. The optional `--restart` flag restarts the Garage pod between upload
|
||||
and download to verify persistence; use it only in CI or a maintenance window.
|
||||
CI also verifies that reinstalling Garage preserves its credential Secret.
|
||||
|
||||
## Existing MinIO installations
|
||||
|
||||
The [MinIO manifests](../minio/) remain available as an explicit legacy option.
|
||||
This change does **not** copy recordings, modify Vault's stored provider
|
||||
records, or delete MinIO resources. Do not use prune/apply cleanup to remove
|
||||
the old backend while it contains recordings.
|
||||
|
||||
When upgrading an existing deployment, keep its existing Vault provider names
|
||||
in the Hub values (`kerberosvault.provider`, `archive.provider`,
|
||||
`thumbnail.provider`, `sprite.provider`) until recordings have been explicitly
|
||||
migrated and reads verified. Add Garage as a separate provider/account as
|
||||
needed. Treat object migration and retirement of MinIO as a separate,
|
||||
backed-up operation; this installer only provisions the new backend.
|
||||
@@ -0,0 +1,128 @@
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: garage
|
||||
data:
|
||||
garage.toml: |
|
||||
metadata_dir = "/var/lib/garage/meta"
|
||||
data_dir = "/var/lib/garage/data"
|
||||
db_engine = "sqlite"
|
||||
replication_factor = 1
|
||||
rpc_bind_addr = "127.0.0.1:3901"
|
||||
rpc_public_addr = "127.0.0.1:3901"
|
||||
|
||||
[s3_api]
|
||||
s3_region = "garage"
|
||||
api_bind_addr = "[::]:3900"
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: garage
|
||||
spec:
|
||||
type: NodePort
|
||||
selector:
|
||||
app: garage
|
||||
ports:
|
||||
- name: s3
|
||||
port: 3900
|
||||
targetPort: s3
|
||||
nodePort: 30090
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: garage
|
||||
spec:
|
||||
serviceName: garage
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: garage
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: garage
|
||||
spec:
|
||||
automountServiceAccountToken: false
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
runAsUser: 1000
|
||||
runAsGroup: 1000
|
||||
fsGroup: 1000
|
||||
fsGroupChangePolicy: OnRootMismatch
|
||||
containers:
|
||||
- name: garage
|
||||
image: dxflrs/garage:v2.5.0@sha256:677e5b758e4425a325b811c425c026bf35a4bf42f7ddbaa773de3f4fd779a5a5
|
||||
command: ["/garage"]
|
||||
args: ["server", "--single-node", "--default-bucket"]
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
readOnlyRootFilesystem: true
|
||||
capabilities:
|
||||
drop: ["ALL"]
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
env:
|
||||
- name: GARAGE_RPC_SECRET
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: garage-credentials
|
||||
key: rpc-secret
|
||||
- name: GARAGE_DEFAULT_ACCESS_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: garage-credentials
|
||||
key: access-key
|
||||
- name: GARAGE_DEFAULT_SECRET_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: garage-credentials
|
||||
key: secret-key
|
||||
- name: GARAGE_DEFAULT_BUCKET
|
||||
value: mybucket
|
||||
ports:
|
||||
- name: s3
|
||||
containerPort: 3900
|
||||
startupProbe:
|
||||
tcpSocket:
|
||||
port: s3
|
||||
periodSeconds: 2
|
||||
failureThreshold: 60
|
||||
readinessProbe:
|
||||
exec:
|
||||
command: ["/garage", "health"]
|
||||
livenessProbe:
|
||||
tcpSocket:
|
||||
port: s3
|
||||
resources:
|
||||
requests:
|
||||
cpu: 100m
|
||||
memory: 128Mi
|
||||
limits:
|
||||
memory: 512Mi
|
||||
volumeMounts:
|
||||
- name: config
|
||||
mountPath: /etc/garage.toml
|
||||
subPath: garage.toml
|
||||
readOnly: true
|
||||
- name: data
|
||||
mountPath: /var/lib/garage
|
||||
- name: tmp
|
||||
mountPath: /tmp
|
||||
volumes:
|
||||
- name: config
|
||||
configMap:
|
||||
name: garage
|
||||
- name: tmp
|
||||
emptyDir:
|
||||
sizeLimit: 16Mi
|
||||
volumeClaimTemplates:
|
||||
- metadata:
|
||||
name: data
|
||||
spec:
|
||||
accessModes: ["ReadWriteOnce"]
|
||||
storageClassName: ssd-hostpath
|
||||
resources:
|
||||
requests:
|
||||
storage: 10Gi
|
||||
@@ -0,0 +1,4 @@
|
||||
namespace: garage
|
||||
resources:
|
||||
- namespace.yaml
|
||||
- garage.yaml
|
||||
@@ -0,0 +1,4 @@
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: garage
|
||||
@@ -9,7 +9,7 @@ spec:
|
||||
type: NodePort
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 80
|
||||
targetPort: http
|
||||
nodePort: 32080 # You can specify a port in the range 30000-32767 or let Kubernetes assign one automatically
|
||||
name: frontend
|
||||
protocol: TCP
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
# Declare variables to be passed into your templates.
|
||||
|
||||
###########################################################################
|
||||
# LICENSING information: you will a license to run Kerberos Hub.
|
||||
# LICENSING information: you will a license to run Hub.
|
||||
# ----
|
||||
# Get your license from support@kerberos.io
|
||||
#license: "---ENTER-YOUR-LICENSE-HERE---"
|
||||
@@ -11,7 +11,7 @@
|
||||
license: "L/+DAwEBB2xpY2Vuc2UB/4QAAQIBB1BheWxvYWQBCgABCVNpZ25hdHVyZQEKAAAA/gMk/4QB/gEZ/8sQACxnaXRodWIuY29tL3V1Zy1haS9odWItbGljZW5zZS9tb2RlbHMuTGljZW5zZX8DAQEHTGljZW5zZQH/gAABDAECSWQB/4IAAQNLZXkBDAABB0NvbXBhbnkBDAABB0V4cFRpbWUBBAABBERheXMBBAABB0NhbWVyYXMBBAABBVNpdGVzAQQAAQZWYXVsdHMBBAABCk1lZGlhTGltaXQBBAABCVBlcnBldHVhbAECAAEGQWN0aXZlAQIAAQlJcEFkZHJlc3MBDAAAABj/gQEBAQhPYmplY3RJRAH/ggABBgEYAAAy/4AvAQwAAAAAAAAAAAAAAAACDGZyZWUtbGljZW5zZQH81iZi6gH+AtoBEAEUARQDAQAB/gIAfeXxQb6kaPfAgOWeSAE6qEiQviFD6sciNmNfMel1mEL53FeV0GQe4cYBip9wyJag35az8A1yppxSymZD5V4my2FckyN2zmEW4E2sO/v+8eKepiAGYEzrKtfNCLxdWLmrHd0zjYQ3qk+PNfoPyzCOefeulw3aFsqBlzg9wDkF8cRx6tUW0qNTzki6sFGOuLoxS49cWqsftAvZmt+CRWa8u0VArIAjOpywN0RIZCkEYzp5RYF3LSVyWYEyvVhjE19DDnevzpJyCHRsIHTRcpTQkhboeapOdlEz8cx+PaOvxktN8hBWceTAH+nw96FARG7y6Cpjw3xo+NV1xb0tvRXGaGoK77JnErKLhd/haXji98rGvMakDt18WSbQfTVS84+Fw+/gKGsW3uS3fROAaZw1kZj4PgsEPZDvbVkCVyuS0O87UoYqpxH8S4by8cTF3wDP7FwyIRZbEbYjN2wzHSmlADYOBtdsdb1VGm7wvtB85vML9n7ZSlIpJdqfci06mGks102mDyG2LRMhUEvpUW3D/weErIvj2WiAwf6r0EUj+LO8VmAsYkME9da7FXEN6Vg/5f1u485LOpYki332RaDOhDn2eMG9DVb/HnmQSFagX+XXc/QwfsWiehCgKYGk4jQpyklTqoGu8BAt6Sm8CaoH8ngZ3cHLQT5DcZElV36/N/wA"
|
||||
licenseServer:
|
||||
url: "https://license.kerberos.io/verify"
|
||||
token: "214%ˆ#ddfsf@#3rfdsgl_)23sffeqasSwefDSFNBM" # do not change otherwise Kerberos Hub will not work.
|
||||
token: "214%ˆ#ddfsf@#3rfdsgl_)23sffeqasSwefDSFNBM" # do not change otherwise Hub will not work.
|
||||
# Private Docker Registry: The registry secret is required if you have your Docker images behind a private registry.
|
||||
# By default it will pull from Docker hub (https://hub.docker.com/r/kerberos).
|
||||
#imagePullSecrets:
|
||||
@@ -19,14 +19,14 @@ licenseServer:
|
||||
|
||||
# When using a private registry, you can specify the registry here.
|
||||
global:
|
||||
imageRegistry: "docker.io/"
|
||||
imageRegistry: ""
|
||||
# Environment: set to 'production', 'develop', 'demo', 'staging' or 'acceptance'.
|
||||
# Set to 'true' if this is a private deployment.
|
||||
environment: "production"
|
||||
# Set to 'true' if this is a private deployment.
|
||||
isPrivate: true
|
||||
# If you plan a migration or doing maintenance, you can enable readonly.
|
||||
# This will stop any write process to mongodb or any processing done in the Kerberos Hub pipeline.
|
||||
# This will stop any write process to mongodb or any processing done in the Hub pipeline.
|
||||
readOnly: false
|
||||
# Which network ingress you are using in your Kubernetes Cluster
|
||||
# Leaving the ingress empty will disable the ingress.
|
||||
@@ -42,10 +42,10 @@ mongodb:
|
||||
username: "root"
|
||||
password: "yourpassword"
|
||||
# A MQTT broker (vernemq or other like mosquitto) is used to have a bi-directional
|
||||
# communication between Agents and Kerberos Hub.
|
||||
# communication between Agents and Hub.
|
||||
# we recommend to use vernemq (as part of this installation), but a stand-alone mosquitto broker is also possible.
|
||||
mqtt:
|
||||
host: "mqtt.yourdomain.com" # this needs to be a public accessible DNS name (it's used to communicate between Agents and Kerberos Hub)
|
||||
host: "mqtt.yourdomain.com" # this needs to be a public accessible DNS name (it's used to communicate between Agents and Hub)
|
||||
port: "31443"
|
||||
protocol: "wss"
|
||||
username: "yourusername"
|
||||
@@ -85,29 +85,29 @@ turn:
|
||||
openai:
|
||||
enabled: false
|
||||
apikey: "xxx"
|
||||
# We have a kerberos vault component installed which contains all the
|
||||
# recordings. Kerberos vault is queried to retrieve the recordings
|
||||
# We have a Vault component installed which contains all the
|
||||
# recordings. Vault is queried to retrieve the recordings
|
||||
# from the appropriate provider.
|
||||
|
||||
kerberosvault:
|
||||
#uri: "http://vault-lb.kerberos-vault" # this needs to be a public accessible DNS name.
|
||||
uri: http://vault-nodeport.kerberos-vault:80/api
|
||||
provider: "minio"
|
||||
provider: "garage"
|
||||
accesskey: "XJoi2@bgSOvOYBy#"
|
||||
secretkey: "OGGqat4lXRpL@9XBYc8FUaId@5"
|
||||
# Archiving is used when creating a task. The underlying recording of the task will be copied from its
|
||||
# existing provider to the below archived provider. Seperate credentials are used, as it makes possible to
|
||||
# specify another retention period.
|
||||
archive:
|
||||
provider: "minio"
|
||||
provider: "garage"
|
||||
accesskey: "XJoi2@bgSOvOYBy#"
|
||||
secretkey: "OGGqat4lXRpL@9XBYc8FUaId@5"
|
||||
thumbnail:
|
||||
provider: "minio"
|
||||
provider: "garage"
|
||||
accessKey: "XJoi2@bgSOvOYBy#"
|
||||
secretKey: "OGGqat4lXRpL@9XBYc8FUaId@5"
|
||||
sprite:
|
||||
provider: "minio"
|
||||
provider: "garage"
|
||||
accessKey: "XJoi2@bgSOvOYBy#"
|
||||
secretKey: "OGGqat4lXRpL@9XBYc8FUaId@5"
|
||||
email:
|
||||
@@ -124,23 +124,23 @@ email:
|
||||
password: "yourpassword"
|
||||
templates:
|
||||
welcome: "welcome"
|
||||
welcomeTitle: "Welcome to Kerberos Hub"
|
||||
welcomeTitle: "Welcome to Hub"
|
||||
activate: "activate"
|
||||
activateTitle: "Wonderful! Your Kerberos Hub is now active"
|
||||
activateTitle: "Wonderful! Your Hub is now active"
|
||||
forgot: "forgot"
|
||||
forgotTitle: "Password reset Kerberos Hub. You forgot your password"
|
||||
forgotTitle: "Password reset Hub. You forgot your password"
|
||||
share: "share"
|
||||
shareTitle: "[Action] You received a recording from Kerberos Hub"
|
||||
shareTitle: "[Action] You received a recording from Hub"
|
||||
caseShare: "share_case"
|
||||
caseShareTitle: "[Action] A case has been shared with you on Kerberos Hub"
|
||||
caseShareTitle: "[Action] A case has been shared with you on Hub"
|
||||
detection: "detection"
|
||||
disabled: "disabled"
|
||||
highupload: "highupload"
|
||||
device: "device"
|
||||
alertTitle: "[Alert] Kerberos Hub detected something an event"
|
||||
alertTitle: "[Alert] Hub detected something an event"
|
||||
deviceTitle: "[Device] An Agent's status has been changed"
|
||||
# Following are all the different deployments needed to make
|
||||
# Kerberos hub properly working.
|
||||
# Hub properly working.
|
||||
kerberoshub:
|
||||
admin:
|
||||
repository: uugai/admin
|
||||
@@ -155,6 +155,8 @@ kerberoshub:
|
||||
memory: 100Mi
|
||||
cpu: 100m
|
||||
api:
|
||||
# Chart 0.170.1 supplies non-root security contexts and writable /tmp.
|
||||
# Retain hub-api-tmp when overriding the chart's volume/mount lists.
|
||||
repository: ghcr.io/uug-ai/hub-api
|
||||
pullPolicy: IfNotPresent
|
||||
tag: "v1.11.31"
|
||||
@@ -182,8 +184,8 @@ kerberoshub:
|
||||
#legacyUrl: "api.legacy.yourdomain.com"
|
||||
|
||||
# MFA issuer name
|
||||
mfaIssuer: "Kerberos.io"
|
||||
# Admin API's are made available for automation of Kerberos Hub.
|
||||
mfaIssuer: "Hub"
|
||||
# Admin API's are made available for automation of Hub.
|
||||
# To access those API's (e.g. creation of owner users), an API key needs to be provided.
|
||||
apiKey: "Z6GPfDdYj8mxLyy6iUJVf9yBlri9lhsW"
|
||||
## Certificates
|
||||
@@ -199,20 +201,20 @@ kerberoshub:
|
||||
# secretName: kerberoshub-admin
|
||||
language: "english"
|
||||
fallbackLanguage: "english"
|
||||
# Legacy (reseller) it is possible to link to AWS S3 and IAM (however Kerberos Vault is now the recommended option).
|
||||
# This is primarily used for creation of subscriptions, and not needed if you are using mainly Kerberos Vault.
|
||||
# Legacy (reseller) it is possible to link to AWS S3 and IAM (however Vault is now the recommended option).
|
||||
# This is primarily used for creation of subscriptions, and not needed if you are using mainly Vault.
|
||||
aws:
|
||||
region: "xxx"
|
||||
bucket: "xxx"
|
||||
accessKey: "xxx"
|
||||
secretKey: "xxx"
|
||||
stripe: # We use stripe for billing, so it's possible to resell Kerberos Hub if agreed.
|
||||
stripe: # We use stripe for billing, so it's possible to resell Hub if agreed.
|
||||
privateKey: "xxx"
|
||||
slack: # Slack is used in the api, to send logs to a specific Slack channel.
|
||||
enabled: "true"
|
||||
hook: "yourslackhook" # https://hooks.slack.com/services/T08Q2Q9V5/xxKT/JALxxAk26bHtuqTfZ
|
||||
username: "Kerberos Hub" # The slack username
|
||||
elasticsearch: # Logs of the kerberos hub will be send to an elastic search cluster.
|
||||
username: "Hub" # The slack username
|
||||
elasticsearch: # Logs of the Hub will be send to an elastic search cluster.
|
||||
enabled: "false"
|
||||
protocol: "http"
|
||||
host: "yourelasticsearchinstance.com"
|
||||
@@ -241,6 +243,8 @@ kerberoshub:
|
||||
repository: ghcr.io/uug-ai/hub-frontend
|
||||
pullPolicy: IfNotPresent
|
||||
tag: "v1.19.28"
|
||||
# Requires Hub chart 0.170.0+ for the matching hardened runtime defaults.
|
||||
containerPort: 8080
|
||||
replicas: 1
|
||||
schema: "http"
|
||||
url: "yourdomain.com"
|
||||
@@ -273,7 +277,7 @@ kerberoshub:
|
||||
apikey: "xxx"
|
||||
sentry: # We can trace errors in Sentry
|
||||
url: "https://xxx@sentry.io/xxx"
|
||||
stripe: # We use stripe for billing, so it's possible to resell Kerberos Hub if agreed.
|
||||
stripe: # We use stripe for billing, so it's possible to resell Hub if agreed.
|
||||
publicKey: ""
|
||||
googlemaps: # Google maps is used inside the application to visualise cameras and sites.
|
||||
apikey: "xxxx"
|
||||
@@ -286,15 +290,15 @@ kerberoshub:
|
||||
# in a white-label setup, or where you are managing the Agents for your customers.
|
||||
hideAddAgent: "true"
|
||||
# Multi tenancy (domains)
|
||||
# By default the Kerberos Hub allows multi-tenancy through the concept
|
||||
# By default the Hub allows multi-tenancy through the concept
|
||||
# of accounts and subaccounts. However through the concept of domains, you
|
||||
# take it a step further. Within a domain, user accounts are unique, and are prefixed by a (domain\).
|
||||
#multiTenant: true
|
||||
#tenantBaseDomain: "yourdomain.com" # this would resolve in following sub domain "https://domain.kerberos.io"
|
||||
|
||||
# Page title (browser)
|
||||
title: "Kerberos Hub - Video surveillance as it should be"
|
||||
# You can style Kerberos hub as you wish.
|
||||
title: "Hub - Video surveillance as it should be"
|
||||
# You can style Hub as you wish.
|
||||
# 1. we do the styling on our side and bake it in the Docker image (change the logo attribute to your company name)
|
||||
# 2. you bring your own logo (set logo to 'custom'), and mount the css file and favicons.
|
||||
# we will need to include your logo in the Docker image, so please reach out to us.
|
||||
@@ -310,7 +314,7 @@ kerberoshub:
|
||||
# persistentVolumeClaim:
|
||||
# claimName: custom-layout-claim
|
||||
# By specifying the below environments variables, you can tweak the
|
||||
# headings and paragraphs of Kerberos Hub front-end.
|
||||
# headings and paragraphs of Hub front-end.
|
||||
# Login page
|
||||
loginDescription: ""
|
||||
loginCopyright: ""
|
||||
@@ -533,7 +537,7 @@ kerberospipeline:
|
||||
width: "600"
|
||||
height: "-1"
|
||||
kerberosvault:
|
||||
enabled: true # If you want to use Kerberos Vault to store the thumbnails
|
||||
enabled: true # If you want to use Vault to store the thumbnails
|
||||
resources:
|
||||
requests:
|
||||
memory: 50Mi
|
||||
|
||||
@@ -6,4 +6,4 @@ resources:
|
||||
- factory
|
||||
- vault
|
||||
- hub
|
||||
- minio
|
||||
- garage
|
||||
|
||||
+80
-1
@@ -3,7 +3,7 @@
|
||||
# Vault base manifests
|
||||
|
||||
This directory holds the raw Kubernetes manifests for **Vault**. Vault receives
|
||||
recordings from Kerberos Agents, stores recording metadata in MongoDB, and sends
|
||||
recordings from Agents, stores recording metadata in MongoDB, and sends
|
||||
recording bytes to storage providers configured through the Vault UI.
|
||||
|
||||
> **Scope of this README.** At the top level of this repository Vault is normally
|
||||
@@ -28,6 +28,85 @@ recording bytes to storage providers configured through the Vault UI.
|
||||
The matching `kerberos-vault` namespace is defined in
|
||||
[`../namespaces/kerberos-vault.yaml`](../namespaces/kerberos-vault.yaml).
|
||||
|
||||
## Hardened Vault image
|
||||
|
||||
Both deployment variants use the hardened Vault image
|
||||
`ghcr.io/uug-ai/vault:v1.7.19`. The Vault container runs as non-root UID/GID
|
||||
`65532`, drops Linux capabilities, disables privilege escalation, uses the
|
||||
`RuntimeDefault` seccomp profile, and has a read-only root filesystem.
|
||||
|
||||
The image listens on container port `8080`. The Service keeps its existing
|
||||
port `80` and NodePort `30080`, forwarding to the named `http` container port.
|
||||
Startup, readiness, and liveness probes use `/api/health`.
|
||||
|
||||
The image uses `/run/vault` for temporary upload/finalization files. Each
|
||||
Deployment mounts a writable, disk-backed `emptyDir` there, limited to `1Gi`;
|
||||
the pod `fsGroup` grants the non-root Vault process access. Size this scratch
|
||||
limit for expected concurrent uploads and available node ephemeral storage.
|
||||
|
||||
### Size the writable scratch volume
|
||||
|
||||
There is no one-size-fits-all volume size: estimate how many full recordings
|
||||
Vault may be writing to scratch at the same time, and the maximum size of each.
|
||||
|
||||
- A regular HTTP upload is spooled to a temporary file. The default
|
||||
`VAULT_MAX_PUBLISH_FILE_BYTES` limit is **1 GiB per upload**. If you change
|
||||
this limit, use the new value in your sizing estimate.
|
||||
- Resumable tus chunks are stored in the configured object-storage provider,
|
||||
not in this volume. When an upload is finalized, Vault downloads the completed
|
||||
recording to a temporary file, so count concurrent **tus finalizations** and
|
||||
their maximum recording sizes.
|
||||
- Set `TUS_MAX_SIZE_BYTES` to a positive byte limit to cap tus upload size. It is
|
||||
unlimited when unset. For example, `1073741824` limits each tus upload to 1
|
||||
GiB. Keep this cap within the scratch capacity you have planned.
|
||||
|
||||
Use this conservative estimate, then round up to a convenient GiB value:
|
||||
|
||||
```text
|
||||
scratch size >= 1.5 x (
|
||||
concurrent HTTP uploads x maximum HTTP upload size
|
||||
+ concurrent tus finalizations x maximum tus upload size
|
||||
)
|
||||
```
|
||||
|
||||
The `1.5` multiplier allows roughly 50% headroom. For example, allowing two
|
||||
simultaneous 1 GiB HTTP uploads and two simultaneous 1 GiB tus finalizations
|
||||
uses up to 4 GiB for those temporary files; choose a scratch limit of at least
|
||||
**6 GiB**. If you only expect two full-file operations at once in total, a
|
||||
**3 GiB** limit is a reasonable starting point. Increase it for larger files or
|
||||
more concurrent operations.
|
||||
|
||||
To apply the 6 GiB example, set the tus cap and scratch limit in the Vault
|
||||
container and pod template of the Deployment you use. Make the same changes to
|
||||
the Secret-backed Deployment if you use that variant:
|
||||
|
||||
```yaml
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: vault
|
||||
env:
|
||||
- name: TUS_MAX_SIZE_BYTES
|
||||
value: "1073741824"
|
||||
volumeMounts:
|
||||
- name: vault-tmp
|
||||
mountPath: /run/vault
|
||||
volumes:
|
||||
- name: vault-tmp
|
||||
emptyDir:
|
||||
sizeLimit: 6Gi
|
||||
```
|
||||
|
||||
Keep the existing `GIN_MODE` and other environment variables and the
|
||||
`vault-tmp` mount; merge these entries rather than replacing them. The disk-backed
|
||||
`emptyDir` is charged to node ephemeral storage: its `sizeLimit` is a ceiling,
|
||||
not a reservation. Make sure the node and your pod's ephemeral-storage
|
||||
requests/limits can accommodate scratch use as well as container logs and other
|
||||
temporary files. If the limit is exhausted, uploads or finalizations can fail.
|
||||
Apply the updated Deployment and check that the Vault pod becomes Ready before
|
||||
relying on the new limits.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- A running Kubernetes cluster and `kubectl` configured to reach it.
|
||||
|
||||
@@ -18,13 +18,32 @@ spec:
|
||||
labels:
|
||||
app: vault
|
||||
spec:
|
||||
securityContext:
|
||||
fsGroup: 65532
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
initContainers:
|
||||
- name: wait-for-mongodb-before-starup
|
||||
image: busybox
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
runAsUser: 65532
|
||||
runAsGroup: 65532
|
||||
allowPrivilegeEscalation: false
|
||||
capabilities:
|
||||
drop: ["ALL"]
|
||||
command: ["sh", "-c", "until nc -z mongodb.mongodb 27017 > /dev/null; do echo Waiting for master.; sleep 2; done;"]
|
||||
containers:
|
||||
- name: vault
|
||||
image: ghcr.io/uug-ai/vault:v1.4.9
|
||||
image: ghcr.io/uug-ai/vault:v1.7.19
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
runAsUser: 65532
|
||||
runAsGroup: 65532
|
||||
readOnlyRootFilesystem: true
|
||||
allowPrivilegeEscalation: false
|
||||
capabilities:
|
||||
drop: ["ALL"]
|
||||
resources:
|
||||
requests:
|
||||
memory: 128Mi
|
||||
@@ -33,7 +52,33 @@ spec:
|
||||
memory: 128Mi
|
||||
cpu: 100m
|
||||
ports:
|
||||
- containerPort: 80
|
||||
- name: http
|
||||
containerPort: 8080
|
||||
protocol: TCP
|
||||
startupProbe:
|
||||
httpGet:
|
||||
path: /api/health
|
||||
port: http
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 3
|
||||
failureThreshold: 30
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /api/health
|
||||
port: http
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 3
|
||||
failureThreshold: 3
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /api/health
|
||||
port: http
|
||||
periodSeconds: 30
|
||||
timeoutSeconds: 3
|
||||
failureThreshold: 3
|
||||
volumeMounts:
|
||||
- name: vault-tmp
|
||||
mountPath: /run/vault
|
||||
envFrom:
|
||||
- configMapRef:
|
||||
name: mongodb
|
||||
@@ -45,3 +90,7 @@ spec:
|
||||
env:
|
||||
- name: GIN_MODE
|
||||
value: release
|
||||
volumes:
|
||||
- name: vault-tmp
|
||||
emptyDir:
|
||||
sizeLimit: 1Gi
|
||||
|
||||
@@ -18,13 +18,32 @@ spec:
|
||||
labels:
|
||||
app: vault
|
||||
spec:
|
||||
securityContext:
|
||||
fsGroup: 65532
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
initContainers:
|
||||
- name: wait-for-mongodb-before-starup
|
||||
image: busybox
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
runAsUser: 65532
|
||||
runAsGroup: 65532
|
||||
allowPrivilegeEscalation: false
|
||||
capabilities:
|
||||
drop: ["ALL"]
|
||||
command: ["sh", "-c", "until nc -z mongodb.mongodb 27017 > /dev/null; do echo Waiting for master.; sleep 2; done;"]
|
||||
containers:
|
||||
- name: vault
|
||||
image: ghcr.io/uug-ai/vault:v1.7.19
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
runAsUser: 65532
|
||||
runAsGroup: 65532
|
||||
readOnlyRootFilesystem: true
|
||||
allowPrivilegeEscalation: false
|
||||
capabilities:
|
||||
drop: ["ALL"]
|
||||
resources:
|
||||
requests:
|
||||
memory: 128Mi
|
||||
@@ -33,7 +52,33 @@ spec:
|
||||
memory: 128Mi
|
||||
cpu: 100m
|
||||
ports:
|
||||
- containerPort: 80
|
||||
- name: http
|
||||
containerPort: 8080
|
||||
protocol: TCP
|
||||
startupProbe:
|
||||
httpGet:
|
||||
path: /api/health
|
||||
port: http
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 3
|
||||
failureThreshold: 30
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /api/health
|
||||
port: http
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 3
|
||||
failureThreshold: 3
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /api/health
|
||||
port: http
|
||||
periodSeconds: 30
|
||||
timeoutSeconds: 3
|
||||
failureThreshold: 3
|
||||
volumeMounts:
|
||||
- name: vault-tmp
|
||||
mountPath: /run/vault
|
||||
envFrom:
|
||||
- configMapRef:
|
||||
name: mongodb
|
||||
@@ -44,3 +89,7 @@ spec:
|
||||
env:
|
||||
- name: GIN_MODE
|
||||
value: release
|
||||
volumes:
|
||||
- name: vault-tmp
|
||||
emptyDir:
|
||||
sizeLimit: 1Gi
|
||||
|
||||
@@ -10,7 +10,7 @@ spec:
|
||||
type: NodePort
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 80
|
||||
targetPort: http
|
||||
nodePort: 30080 # You can specify a port in the range 30000-32767 or let Kubernetes assign one automatically
|
||||
name: frontend
|
||||
protocol: TCP
|
||||
@@ -27,7 +27,7 @@ spec:
|
||||
# type: LoadBalancer
|
||||
# ports:
|
||||
# - port: 80
|
||||
# targetPort: 80
|
||||
# targetPort: http
|
||||
# name: frontend
|
||||
# protocol: TCP
|
||||
# selector:
|
||||
|
||||
@@ -12,8 +12,8 @@ stringData:
|
||||
MQTT_USERNAME: ""
|
||||
MQTT_PASSWORD: ""
|
||||
VAULT_STORAGE_PROVIDERS: >-
|
||||
[{"name":"archive","provider":"minio","host":"minio.minio.svc:9000","region":"us-east-1","bucket":"recordings","access_key":"example-key","secret":"example-secret","use_ssl":"false"}]
|
||||
[{"name":"garage","provider":"minio","host":"garage.garage:3900","region":"garage","bucket":"mybucket","access_key":"replace-with-garage-access-key","secret":"replace-with-garage-secret-key","use_ssl":"false"}]
|
||||
VAULT_INTEGRATIONS: >-
|
||||
[{"name":"events","queue":"rabbitmq","broker":"amqp://rabbitmq.rabbitmq.svc:5672","topic":"recordings","username":"example-user","password":"example-password"}]
|
||||
VAULT_ACCOUNTS: >-
|
||||
[{"account":"camera-fleet","directory":"fleet","provider":"archive","access_key":"example-account-key","secret_access_key":"example-account-secret","limit":"30","queues":["events"]}]
|
||||
[{"account":"camera-fleet","directory":"fleet","provider":"garage","access_key":"example-account-key","secret_access_key":"example-account-secret","limit":"30","queues":["events"]}]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "Kerberos.io",
|
||||
"short_name": "Kerberos.io",
|
||||
"name": "Hub",
|
||||
"short_name": "Hub",
|
||||
"icons": [
|
||||
{
|
||||
"src": "/favicons/android-chrome-192x192.png?v=1",
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
name="viewport"
|
||||
content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1"
|
||||
/>
|
||||
<meta name="description" content="Kerberos.io Mailing">
|
||||
<meta name="description" content="Hub notifications">
|
||||
<style type="text/css">
|
||||
|
||||
@font-face {
|
||||
@@ -150,7 +150,7 @@ margin-bottom: 36px!important;
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="corner-td" align="left"></td>
|
||||
<td width="48" height="36" align="left"><img alt="Kerberos.io" width="36" height="36" src="https://kerberos.io/images/email/kerberos.png"/></td>
|
||||
<td width="48" height="36" align="left"><img alt="Hub" width="36" height="36" src="https://kerberos.io/images/email/kerberos.png"/></td>
|
||||
<td height="36" align="left" class="company-name-td">
|
||||
<h3 width="36" height="36" style=" font-family: Inter;
|
||||
font-size: 20px;
|
||||
@@ -160,7 +160,7 @@ line-height: 24px;
|
||||
mso-line-height-rule:exactly;
|
||||
letter-spacing: 0em;
|
||||
text-align: left;
|
||||
color: #262424;">Kerberos.io</h3>
|
||||
color: #262424;">Hub</h3>
|
||||
</td>
|
||||
<td height="36" width="36" style="padding-left: 36px;" class="tab-td" align="right">
|
||||
<a style="text-decoration: none;color: none;" href={{tab1_href}}>
|
||||
@@ -260,7 +260,7 @@ mso-line-height-rule:exactly;
|
||||
letter-spacing: 0em;
|
||||
text-align: left;
|
||||
color: #6D6666;
|
||||
margin-top: 12px;">You're ready. Go ahead and <a href='{{link}}'>login to your Kerberos Hub account</a>. Start exploring the different features and functions to support your business usecases.</p>
|
||||
margin-top: 12px;">You're ready. Go ahead and <a href='{{link}}'>login to your Hub account</a>. Start exploring the different features and functions to support your business usecases.</p>
|
||||
<p style=" font-family: Inter;
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
@@ -356,7 +356,7 @@ line-height: 36px;
|
||||
mso-line-height-rule:exactly;
|
||||
letter-spacing: 0em;
|
||||
text-align: left;
|
||||
color:#6D6666;">About Kerberos</h4>
|
||||
color:#6D6666;">About the ecosystem</h4>
|
||||
<p style=" font-family: Inter;
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
Kerberos.io
|
||||
Hub
|
||||
------------
|
||||
|
||||
Hey, {{user}}
|
||||
Welcome to Kerberos Hub
|
||||
Welcome to Hub
|
||||
Activate your account
|
||||
{{link}}
|
||||
|
||||
Kerberos Hub in a nutshell
|
||||
With Kerberos Hub you can access your surveillance media remotely. By subscribing to a plan, you get access to a set of features, from advanced filtering, notifications to machine learning.
|
||||
Hub in a nutshell
|
||||
With Hub you can access your surveillance media remotely. By subscribing to a plan, you get access to a set of features, from advanced filtering, notifications to machine learning.
|
||||
|
||||
However before you get started this amazing applications, please activate your account.
|
||||
|
||||
@@ -17,6 +17,6 @@ support@kerberos.io
|
||||
9000 Ghent, BE
|
||||
https://kerberos.io
|
||||
|
||||
About Kerberos
|
||||
About the ecosystem
|
||||
------------
|
||||
Welcome to the revolutionary video analytics and video management platform. Open, modular, and extensible for everyone, anywhere.
|
||||
@@ -1,16 +1,16 @@
|
||||
package templates
|
||||
|
||||
var TEMPLATE_DETECTION_TEXT = `
|
||||
Kerberos.io
|
||||
Hub
|
||||
------------
|
||||
|
||||
Hey, {{user}}
|
||||
Welcome to Kerberos Hub
|
||||
Welcome to Hub
|
||||
Activate your account ->
|
||||
{{link}}
|
||||
|
||||
Kerberos Hub in a nutshell
|
||||
With Kerberos Hub you can access your surveillance media remotely. By subscribing to a plan, you get access to a set of features, from advanced filtering, notifications to machine learning.
|
||||
Hub in a nutshell
|
||||
With Hub you can access your surveillance media remotely. By subscribing to a plan, you get access to a set of features, from advanced filtering, notifications to machine learning.
|
||||
|
||||
However before you get started this amazing applications, please activate your account.
|
||||
|
||||
@@ -20,7 +20,7 @@ support@kerberos.io
|
||||
9000 Ghent, BE
|
||||
https://kerberos.io
|
||||
|
||||
About Kerberos
|
||||
About the ecosystem
|
||||
------------
|
||||
Welcome to the revolutionary video analytics and video management platform. Open, modular, and extensible for everyone, anywhere.
|
||||
`
|
||||
@@ -35,7 +35,7 @@ var TEMPLATE_DETECTION = `
|
||||
name="viewport"
|
||||
content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1"
|
||||
/>
|
||||
<meta name="description" content="Kerberos.io Mailing">
|
||||
<meta name="description" content="Hub notifications">
|
||||
<style type="text/css">
|
||||
|
||||
@font-face {
|
||||
@@ -178,7 +178,7 @@ var TEMPLATE_DETECTION = `
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="corner-td" align="left"></td>
|
||||
<td width="48" height="36" align="left"><img alt="Kerberos.io" width="36" height="36" src="https://kerberos.io/images/email/kerberos.png"/></td>
|
||||
<td width="48" height="36" align="left"><img alt="Hub" width="36" height="36" src="https://kerberos.io/images/email/kerberos.png"/></td>
|
||||
<td height="36" align="left" class="company-name-td">
|
||||
<h3 width="36" height="36" style=" font-family: Inter;
|
||||
font-size: 20px;
|
||||
@@ -188,7 +188,7 @@ var TEMPLATE_DETECTION = `
|
||||
mso-line-height-rule:exactly;
|
||||
letter-spacing: 0em;
|
||||
text-align: left;
|
||||
color: #262424;">Kerberos.io</h3>
|
||||
color: #262424;">Hub</h3>
|
||||
</td>
|
||||
<td height="36" width="36" style="padding-left: 36px;" class="tab-td" align="right">
|
||||
<a style="text-decoration: none;color: none;" href={{tab1_href}}>
|
||||
@@ -304,7 +304,7 @@ var TEMPLATE_DETECTION = `
|
||||
text-align: left;
|
||||
color: #6D6666;
|
||||
margin-top: 12px;">An alert was send to your e-mail as one of the conditions was triggered for your device <b>{{devicename}}</b>. Please watch the recording, by clicking on below button.
|
||||
If you believe this event is a false positive, go to your Kerberos Hub account and change the alert settings accordingly.</p>
|
||||
If you believe this event is a false positive, go to your Hub account and change the alert settings accordingly.</p>
|
||||
|
||||
|
||||
<p style=" font-family: Inter;
|
||||
@@ -426,7 +426,7 @@ If you believe this event is a false positive, go to your Kerberos Hub account a
|
||||
mso-line-height-rule:exactly;
|
||||
letter-spacing: 0em;
|
||||
text-align: left;
|
||||
color:#6D6666;">About Kerberos</h4>
|
||||
color:#6D6666;">About the ecosystem</h4>
|
||||
<p style=" font-family: Inter;
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
Kerberos.io
|
||||
Hub
|
||||
------------
|
||||
|
||||
Hey, {{user}}
|
||||
Welcome to Kerberos Hub
|
||||
Welcome to Hub
|
||||
Activate your account ->
|
||||
{{link}}
|
||||
|
||||
Kerberos Hub in a nutshell
|
||||
With Kerberos Hub you can access your surveillance media remotely. By subscribing to a plan, you get access to a set of features, from advanced filtering, notifications to machine learning.
|
||||
Hub in a nutshell
|
||||
With Hub you can access your surveillance media remotely. By subscribing to a plan, you get access to a set of features, from advanced filtering, notifications to machine learning.
|
||||
|
||||
However before you get started this amazing applications, please activate your account.
|
||||
|
||||
@@ -17,6 +17,6 @@ support@kerberos.io
|
||||
9000 Ghent, BE
|
||||
https://kerberos.io
|
||||
|
||||
About Kerberos
|
||||
About the ecosystem
|
||||
------------
|
||||
Welcome to the revolutionary video analytics and video management platform. Open, modular, and extensible for everyone, anywhere.
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
name="viewport"
|
||||
content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1"
|
||||
/>
|
||||
<meta name="description" content="Kerberos.io Mailing">
|
||||
<meta name="description" content="Hub notifications">
|
||||
<style type="text/css">
|
||||
|
||||
@font-face {
|
||||
@@ -150,7 +150,7 @@
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="corner-td" align="left"></td>
|
||||
<td width="48" height="36" align="left"><img alt="Kerberos.io" width="36" height="36" src="https://kerberos.io/images/email/kerberos.png"/></td>
|
||||
<td width="48" height="36" align="left"><img alt="Hub" width="36" height="36" src="https://kerberos.io/images/email/kerberos.png"/></td>
|
||||
<td height="36" align="left" class="company-name-td">
|
||||
<h3 width="36" height="36" style=" font-family: Inter;
|
||||
font-size: 20px;
|
||||
@@ -160,7 +160,7 @@
|
||||
mso-line-height-rule:exactly;
|
||||
letter-spacing: 0em;
|
||||
text-align: left;
|
||||
color: #262424;">Kerberos.io</h3>
|
||||
color: #262424;">Hub</h3>
|
||||
</td>
|
||||
<td height="36" width="36" style="padding-left: 36px;" class="tab-td" align="right">
|
||||
<a style="text-decoration: none;color: none;" href={{tab1_href}}>
|
||||
@@ -276,7 +276,7 @@
|
||||
text-align: left;
|
||||
color: #6D6666;
|
||||
margin-top: 12px;">Agents go offline due to a variety of reasons. The machine, node, micro controller on which your Agent runs, gets corrupted or disconnected from the internet.
|
||||
The camera itself is broken, damaged or in the worst case tampered. Have a look into your Kerberos Hub account for the latest recordings and/or verify the connection and status of your Agent.</p>
|
||||
The camera itself is broken, damaged or in the worst case tampered. Have a look into your Hub account for the latest recordings and/or verify the connection and status of your Agent.</p>
|
||||
|
||||
<a style="text-decoration: none;color: none;" href="{{link}}">
|
||||
<p style="font-family: Inter;
|
||||
@@ -295,7 +295,7 @@ The camera itself is broken, damaged or in the worst case tampered. Have a look
|
||||
width: 160px;
|
||||
border-radius: 4px;
|
||||
text-align: center;
|
||||
cursor: pointer;">Go to Kerberos Hub -></p>
|
||||
cursor: pointer;">Go to Hub -></p>
|
||||
</a>
|
||||
</td>
|
||||
<td class="corner-td" align="right"></td>
|
||||
@@ -382,7 +382,7 @@ The camera itself is broken, damaged or in the worst case tampered. Have a look
|
||||
mso-line-height-rule:exactly;
|
||||
letter-spacing: 0em;
|
||||
text-align: left;
|
||||
color:#6D6666;">About Kerberos</h4>
|
||||
color:#6D6666;">About the ecosystem</h4>
|
||||
<p style=" font-family: Inter;
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
Kerberos.io
|
||||
Hub
|
||||
------------
|
||||
|
||||
Hey, {{user}}
|
||||
Welcome to Kerberos Hub
|
||||
Welcome to Hub
|
||||
Activate your account ->
|
||||
{{link}}
|
||||
|
||||
Kerberos Hub in a nutshell
|
||||
With Kerberos Hub you can access your surveillance media remotely. By subscribing to a plan, you get access to a set of features, from advanced filtering, notifications to machine learning.
|
||||
Hub in a nutshell
|
||||
With Hub you can access your surveillance media remotely. By subscribing to a plan, you get access to a set of features, from advanced filtering, notifications to machine learning.
|
||||
|
||||
However before you get started this amazing applications, please activate your account.
|
||||
|
||||
@@ -17,6 +17,6 @@ support@kerberos.io
|
||||
9000 Ghent, BE
|
||||
https://kerberos.io
|
||||
|
||||
About Kerberos
|
||||
About the ecosystem
|
||||
------------
|
||||
Welcome to the revolutionary video analytics and video management platform. Open, modular, and extensible for everyone, anywhere.
|
||||
@@ -7,7 +7,7 @@
|
||||
name="viewport"
|
||||
content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1"
|
||||
/>
|
||||
<meta name="description" content="Kerberos.io Mailing">
|
||||
<meta name="description" content="Hub notifications">
|
||||
<style type="text/css">
|
||||
|
||||
@font-face {
|
||||
@@ -150,7 +150,7 @@
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="corner-td" align="left"></td>
|
||||
<td width="48" height="36" align="left"><img alt="Kerberos.io" width="36" height="36" src="https://kerberos.io/images/email/kerberos.png"/></td>
|
||||
<td width="48" height="36" align="left"><img alt="Hub" width="36" height="36" src="https://kerberos.io/images/email/kerberos.png"/></td>
|
||||
<td height="36" align="left" class="company-name-td">
|
||||
<h3 width="36" height="36" style=" font-family: Inter;
|
||||
font-size: 20px;
|
||||
@@ -160,7 +160,7 @@
|
||||
mso-line-height-rule:exactly;
|
||||
letter-spacing: 0em;
|
||||
text-align: left;
|
||||
color: #262424;">Kerberos.io</h3>
|
||||
color: #262424;">Hub</h3>
|
||||
</td>
|
||||
<td height="36" width="36" style="padding-left: 36px;" class="tab-td" align="right">
|
||||
<a style="text-decoration: none;color: none;" href={{tab1_href}}>
|
||||
@@ -275,8 +275,8 @@
|
||||
letter-spacing: 0em;
|
||||
text-align: left;
|
||||
color: #6D6666;
|
||||
margin-top: 12px;">The daily limit of your account was reached (<b>{{dataUsage}} GB</b>), therefore we have disabled your account. This means that no new recordings will be uploaded to your Kerberos Hub agents until tomorrow.
|
||||
Tomorrow your account will be reset, and recordings will be uploaded again to your Kerberos Hub account.</p>
|
||||
margin-top: 12px;">The daily limit of your account was reached (<b>{{dataUsage}} GB</b>), therefore we have disabled your account. This means that no new recordings will be uploaded to your Hub agents until tomorrow.
|
||||
Tomorrow your account will be reset, and recordings will be uploaded again to your Hub account.</p>
|
||||
<p style=" font-family: Inter;
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
@@ -286,7 +286,7 @@ Tomorrow your account will be reset, and recordings will be uploaded again to yo
|
||||
letter-spacing: 0em;
|
||||
text-align: left;
|
||||
color: #6D6666;
|
||||
margin-top: 12px;">If you are hitting your daily limits a lot, you might consider upgrading your Kerberos Hub subscription, or fine-tune your Agents so they record less recordings.</p>
|
||||
margin-top: 12px;">If you are hitting your daily limits a lot, you might consider upgrading your Hub subscription, or fine-tune your Agents so they record less recordings.</p>
|
||||
|
||||
<a style="text-decoration: none;color: none;" href="{{link}}">
|
||||
<p style="font-family: Inter;
|
||||
@@ -305,7 +305,7 @@ Tomorrow your account will be reset, and recordings will be uploaded again to yo
|
||||
width: 160px;
|
||||
border-radius: 4px;
|
||||
text-align: center;
|
||||
cursor: pointer;">Go to Kerberos Hub -></p>
|
||||
cursor: pointer;">Go to Hub -></p>
|
||||
</a>
|
||||
</td>
|
||||
<td class="corner-td" align="right"></td>
|
||||
@@ -392,7 +392,7 @@ Tomorrow your account will be reset, and recordings will be uploaded again to yo
|
||||
mso-line-height-rule:exactly;
|
||||
letter-spacing: 0em;
|
||||
text-align: left;
|
||||
color:#6D6666;">About Kerberos</h4>
|
||||
color:#6D6666;">About the ecosystem</h4>
|
||||
<p style=" font-family: Inter;
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
Kerberos.io
|
||||
Hub
|
||||
------------
|
||||
|
||||
Hey, {{user}}
|
||||
Welcome to Kerberos Hub
|
||||
Welcome to Hub
|
||||
Activate your account ->
|
||||
{{link}}
|
||||
|
||||
Kerberos Hub in a nutshell
|
||||
With Kerberos Hub you can access your surveillance media remotely. By subscribing to a plan, you get access to a set of features, from advanced filtering, notifications to machine learning.
|
||||
Hub in a nutshell
|
||||
With Hub you can access your surveillance media remotely. By subscribing to a plan, you get access to a set of features, from advanced filtering, notifications to machine learning.
|
||||
|
||||
However before you get started this amazing applications, please activate your account.
|
||||
|
||||
@@ -17,6 +17,6 @@ support@kerberos.io
|
||||
9000 Ghent, BE
|
||||
https://kerberos.io
|
||||
|
||||
About Kerberos
|
||||
About the ecosystem
|
||||
------------
|
||||
Welcome to the revolutionary video analytics and video management platform. Open, modular, and extensible for everyone, anywhere.
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
name="viewport"
|
||||
content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1"
|
||||
/>
|
||||
<meta name="description" content="Kerberos.io Mailing">
|
||||
<meta name="description" content="Hub notifications">
|
||||
<style type="text/css">
|
||||
|
||||
@font-face {
|
||||
@@ -150,7 +150,7 @@
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="corner-td" align="left"></td>
|
||||
<td width="48" height="36" align="left"><img alt="Kerberos.io" width="36" height="36" src="https://kerberos.io/images/email/kerberos.png"/></td>
|
||||
<td width="48" height="36" align="left"><img alt="Hub" width="36" height="36" src="https://kerberos.io/images/email/kerberos.png"/></td>
|
||||
<td height="36" align="left" class="company-name-td">
|
||||
<h3 width="36" height="36" style=" font-family: Inter;
|
||||
font-size: 20px;
|
||||
@@ -160,7 +160,7 @@
|
||||
mso-line-height-rule:exactly;
|
||||
letter-spacing: 0em;
|
||||
text-align: left;
|
||||
color: #262424;">Kerberos.io</h3>
|
||||
color: #262424;">Hub</h3>
|
||||
</td>
|
||||
<td height="36" width="36" style="padding-left: 36px;" class="tab-td" align="right">
|
||||
<a style="text-decoration: none;color: none;" href={{tab1_href}}>
|
||||
@@ -224,7 +224,7 @@
|
||||
padding-top: 12px;
|
||||
padding-bottom: 24px;
|
||||
padding-left: 0;
|
||||
padding-right: 0;">You forgot your Kerberos Hub password!</h2>
|
||||
padding-right: 0;">You forgot your Hub password!</h2>
|
||||
|
||||
<p style="font-family: Inter;
|
||||
font-size: 14px;
|
||||
@@ -368,7 +368,7 @@
|
||||
mso-line-height-rule:exactly;
|
||||
letter-spacing: 0em;
|
||||
text-align: left;
|
||||
color:#6D6666;">About Kerberos</h4>
|
||||
color:#6D6666;">About the ecosystem</h4>
|
||||
<p style=" font-family: Inter;
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
Kerberos.io
|
||||
Hub
|
||||
------------
|
||||
|
||||
Hey, {{user}}
|
||||
Welcome to Kerberos Hub
|
||||
Welcome to Hub
|
||||
Activate your account
|
||||
{{link}}
|
||||
|
||||
Kerberos Hub in a nutshell
|
||||
With Kerberos Hub you can access your surveillance media remotely. By subscribing to a plan, you get access to a set of features, from advanced filtering, notifications to machine learning.
|
||||
Hub in a nutshell
|
||||
With Hub you can access your surveillance media remotely. By subscribing to a plan, you get access to a set of features, from advanced filtering, notifications to machine learning.
|
||||
|
||||
However before you get started this amazing applications, please activate your account.
|
||||
|
||||
@@ -17,6 +17,6 @@ support@kerberos.io
|
||||
9000 Ghent, BE
|
||||
https://kerberos.io
|
||||
|
||||
About Kerberos
|
||||
About the ecosystem
|
||||
------------
|
||||
Welcome to the revolutionary video analytics and video management platform. Open, modular, and extensible for everyone, anywhere.
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
name="viewport"
|
||||
content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1"
|
||||
/>
|
||||
<meta name="description" content="Kerberos.io Mailing">
|
||||
<meta name="description" content="Hub notifications">
|
||||
<style type="text/css">
|
||||
|
||||
@font-face {
|
||||
@@ -150,7 +150,7 @@
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="corner-td" align="left"></td>
|
||||
<td width="48" height="36" align="left"><img alt="Kerberos.io" width="36" height="36" src="https://kerberos.io/images/email/kerberos.png"/></td>
|
||||
<td width="48" height="36" align="left"><img alt="Hub" width="36" height="36" src="https://kerberos.io/images/email/kerberos.png"/></td>
|
||||
<td height="36" align="left" class="company-name-td">
|
||||
<h3 width="36" height="36" style=" font-family: Inter;
|
||||
font-size: 20px;
|
||||
@@ -160,7 +160,7 @@
|
||||
mso-line-height-rule:exactly;
|
||||
letter-spacing: 0em;
|
||||
text-align: left;
|
||||
color: #262424;">Kerberos.io</h3>
|
||||
color: #262424;">Hub</h3>
|
||||
</td>
|
||||
<td height="36" width="36" style="padding-left: 36px;" class="tab-td" align="right">
|
||||
<a style="text-decoration: none;color: none;" href={{tab1_href}}>
|
||||
@@ -262,7 +262,7 @@
|
||||
text-align: left;
|
||||
color: #6D6666;
|
||||
margin-top: 12px;">You receive this alert as a lot of recordings have been uploaded during the last x minutes. This alert might indicate something is happening unusual, please have a look.
|
||||
If you believe this is a false positive go to the alerts section of your Kerberos Hub account and update the setting accordingly.</p>
|
||||
If you believe this is a false positive go to the alerts section of your Hub account and update the setting accordingly.</p>
|
||||
|
||||
|
||||
<a style="text-decoration: none;color: none;" href="{{link}}">
|
||||
@@ -282,7 +282,7 @@ If you believe this is a false positive go to the alerts section of your Kerbero
|
||||
width: 160px;
|
||||
border-radius: 4px;
|
||||
text-align: center;
|
||||
cursor: pointer;">Go to Kerberos Hub -></p>
|
||||
cursor: pointer;">Go to Hub -></p>
|
||||
</a>
|
||||
</td>
|
||||
<td class="corner-td" align="right"></td>
|
||||
@@ -369,7 +369,7 @@ If you believe this is a false positive go to the alerts section of your Kerbero
|
||||
mso-line-height-rule:exactly;
|
||||
letter-spacing: 0em;
|
||||
text-align: left;
|
||||
color:#6D6666;">About Kerberos</h4>
|
||||
color:#6D6666;">About the ecosystem</h4>
|
||||
<p style=" font-family: Inter;
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
Kerberos.io
|
||||
Hub
|
||||
------------
|
||||
|
||||
Hey, {{user}}
|
||||
Welcome to Kerberos Hub
|
||||
Welcome to Hub
|
||||
Activate your account ->
|
||||
{{link}}
|
||||
|
||||
Kerberos Hub in a nutshell
|
||||
With Kerberos Hub you can access your surveillance media remotely. By subscribing to a plan, you get access to a set of features, from advanced filtering, notifications to machine learning.
|
||||
Hub in a nutshell
|
||||
With Hub you can access your surveillance media remotely. By subscribing to a plan, you get access to a set of features, from advanced filtering, notifications to machine learning.
|
||||
|
||||
However before you get started this amazing applications, please activate your account.
|
||||
|
||||
@@ -17,6 +17,6 @@ support@kerberos.io
|
||||
9000 Ghent, BE
|
||||
https://kerberos.io
|
||||
|
||||
About Kerberos
|
||||
About the ecosystem
|
||||
------------
|
||||
Welcome to the revolutionary video analytics and video management platform. Open, modular, and extensible for everyone, anywhere.
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
name="viewport"
|
||||
content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1"
|
||||
/>
|
||||
<meta name="description" content="Kerberos.io Mailing">
|
||||
<meta name="description" content="Hub notifications">
|
||||
<style type="text/css">
|
||||
|
||||
@font-face {
|
||||
@@ -150,7 +150,7 @@
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="corner-td" align="left"></td>
|
||||
<td width="48" height="36" align="left"><img alt="Kerberos.io" width="36" height="36" src="https://kerberos.io/images/email/kerberos.png"/></td>
|
||||
<td width="48" height="36" align="left"><img alt="Hub" width="36" height="36" src="https://kerberos.io/images/email/kerberos.png"/></td>
|
||||
<td height="36" align="left" class="company-name-td">
|
||||
<h3 width="36" height="36" style=" font-family: Inter;
|
||||
font-size: 20px;
|
||||
@@ -160,7 +160,7 @@
|
||||
mso-line-height-rule:exactly;
|
||||
letter-spacing: 0em;
|
||||
text-align: left;
|
||||
color: #262424;">Kerberos.io</h3>
|
||||
color: #262424;">Hub</h3>
|
||||
</td>
|
||||
<td height="36" width="36" style="padding-left: 36px;" class="tab-td" align="right">
|
||||
<a style="text-decoration: none;color: none;" href={{tab1_href}}>
|
||||
@@ -261,7 +261,7 @@
|
||||
letter-spacing: 0em;
|
||||
text-align: left;
|
||||
color: #6D6666;
|
||||
margin-top: 12px;">Someone, we hope it was you ({{ipaddress}}), signed in to your account. If this was not you, please go to Kerberos Hub and change your password ASAP.</p>
|
||||
margin-top: 12px;">Someone, we hope it was you ({{ipaddress}}), signed in to your account. If this was not you, please go to Hub and change your password ASAP.</p>
|
||||
|
||||
<a style="text-decoration: none;color: none;" href="{{link}}">
|
||||
<p style="font-family: Inter;
|
||||
@@ -367,7 +367,7 @@
|
||||
mso-line-height-rule:exactly;
|
||||
letter-spacing: 0em;
|
||||
text-align: left;
|
||||
color:#6D6666;">About Kerberos</h4>
|
||||
color:#6D6666;">About the ecosystem</h4>
|
||||
<p style=" font-family: Inter;
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
Kerberos.io
|
||||
Hub
|
||||
------------
|
||||
|
||||
Hey, {{user}}
|
||||
Welcome to Kerberos Hub
|
||||
Welcome to Hub
|
||||
Activate your account ->
|
||||
{{link}}
|
||||
|
||||
Kerberos Hub in a nutshell
|
||||
With Kerberos Hub you can access your surveillance media remotely. By subscribing to a plan, you get access to a set of features, from advanced filtering, notifications to machine learning.
|
||||
Hub in a nutshell
|
||||
With Hub you can access your surveillance media remotely. By subscribing to a plan, you get access to a set of features, from advanced filtering, notifications to machine learning.
|
||||
|
||||
However before you get started this amazing applications, please activate your account.
|
||||
|
||||
@@ -17,6 +17,6 @@ support@kerberos.io
|
||||
9000 Ghent, BE
|
||||
https://kerberos.io
|
||||
|
||||
About Kerberos
|
||||
About the ecosystem
|
||||
------------
|
||||
Welcome to the revolutionary video analytics and video management platform. Open, modular, and extensible for everyone, anywhere.
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
name="viewport"
|
||||
content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1"
|
||||
/>
|
||||
<meta name="description" content="Kerberos.io Mailing">
|
||||
<meta name="description" content="Hub notifications">
|
||||
<style type="text/css">
|
||||
|
||||
@font-face {
|
||||
@@ -151,7 +151,7 @@
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="corner-td" align="left"></td>
|
||||
<td width="48" height="36" align="left"><img alt="Kerberos.io" width="36" height="36" src="https://kerberos.io/images/email/kerberos.png"/></td>
|
||||
<td width="48" height="36" align="left"><img alt="Hub" width="36" height="36" src="https://kerberos.io/images/email/kerberos.png"/></td>
|
||||
<td height="36" align="left" class="company-name-td">
|
||||
<h3 width="36" height="36" style=" font-family: Inter;
|
||||
font-size: 20px;
|
||||
@@ -161,7 +161,7 @@
|
||||
mso-line-height-rule:exactly;
|
||||
letter-spacing: 0em;
|
||||
text-align: left;
|
||||
color: #262424;">Kerberos.io</h3>
|
||||
color: #262424;">Hub</h3>
|
||||
</td>
|
||||
<td height="36" width="36" style="padding-left: 36px;" class="tab-td" align="right">
|
||||
<a style="text-decoration: none;color: none;" href={{tab1_href}}>
|
||||
@@ -369,7 +369,7 @@
|
||||
mso-line-height-rule:exactly;
|
||||
letter-spacing: 0em;
|
||||
text-align: left;
|
||||
color:#6D6666;">About Kerberos</h4>
|
||||
color:#6D6666;">About the ecosystem</h4>
|
||||
<p style=" font-family: Inter;
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Kerberos.io
|
||||
Hub
|
||||
------------
|
||||
|
||||
We've something interesting for you
|
||||
@@ -14,6 +14,6 @@ support@kerberos.io
|
||||
9000 Ghent, BE
|
||||
https://kerberos.io
|
||||
|
||||
About Kerberos
|
||||
About the ecosystem
|
||||
------------
|
||||
Welcome to the revolutionary video analytics and video management platform. Open, modular, and extensible for everyone, anywhere.
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
name="viewport"
|
||||
content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1"
|
||||
/>
|
||||
<meta name="description" content="Kerberos.io Mailing">
|
||||
<meta name="description" content="Hub notifications">
|
||||
<style type="text/css">
|
||||
|
||||
@font-face {
|
||||
@@ -151,7 +151,7 @@
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="corner-td" align="left"></td>
|
||||
<td width="48" height="36" align="left"><img alt="Kerberos.io" width="36" height="36" src="https://kerberos.io/images/email/kerberos.png"/></td>
|
||||
<td width="48" height="36" align="left"><img alt="Hub" width="36" height="36" src="https://kerberos.io/images/email/kerberos.png"/></td>
|
||||
<td height="36" align="left" class="company-name-td">
|
||||
<h3 width="36" height="36" style=" font-family: Inter;
|
||||
font-size: 20px;
|
||||
@@ -161,7 +161,7 @@
|
||||
mso-line-height-rule:exactly;
|
||||
letter-spacing: 0em;
|
||||
text-align: left;
|
||||
color: #262424;">Kerberos.io</h3>
|
||||
color: #262424;">Hub</h3>
|
||||
</td>
|
||||
<td height="36" width="36" style="padding-left: 36px;" class="tab-td" align="right">
|
||||
<a style="text-decoration: none;color: none;" href={{tab1_href}}>
|
||||
@@ -369,7 +369,7 @@
|
||||
mso-line-height-rule:exactly;
|
||||
letter-spacing: 0em;
|
||||
text-align: left;
|
||||
color:#6D6666;">About Kerberos</h4>
|
||||
color:#6D6666;">About the ecosystem</h4>
|
||||
<p style=" font-family: Inter;
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Kerberos.io
|
||||
Hub
|
||||
------------
|
||||
|
||||
A case has been shared with you
|
||||
@@ -16,6 +16,6 @@ support@kerberos.io
|
||||
9000 Ghent, BE
|
||||
https://kerberos.io
|
||||
|
||||
About Kerberos
|
||||
About the ecosystem
|
||||
------------
|
||||
Welcome to the revolutionary video analytics and video management platform. Open, modular, and extensible for everyone, anywhere.
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
name="viewport"
|
||||
content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1"
|
||||
/>
|
||||
<meta name="description" content="Kerberos.io Mailing">
|
||||
<meta name="description" content="Hub notifications">
|
||||
<style type="text/css">
|
||||
|
||||
@font-face {
|
||||
@@ -150,7 +150,7 @@
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="corner-td" align="left"></td>
|
||||
<td width="48" height="36" align="left"><img alt="Kerberos.io" width="36" height="36" src="https://kerberos.io/images/email/kerberos.png"/></td>
|
||||
<td width="48" height="36" align="left"><img alt="Hub" width="36" height="36" src="https://kerberos.io/images/email/kerberos.png"/></td>
|
||||
<td height="36" align="left" class="company-name-td">
|
||||
<h3 width="36" height="36" style=" font-family: Inter;
|
||||
font-size: 20px;
|
||||
@@ -160,7 +160,7 @@
|
||||
mso-line-height-rule:exactly;
|
||||
letter-spacing: 0em;
|
||||
text-align: left;
|
||||
color: #262424;">Kerberos.io</h3>
|
||||
color: #262424;">Hub</h3>
|
||||
</td>
|
||||
<td height="36" width="36" style="padding-left: 36px;" class="tab-td" align="right">
|
||||
<a style="text-decoration: none;color: none;" href={{tab1_href}}>
|
||||
@@ -224,7 +224,7 @@
|
||||
padding-top: 12px;
|
||||
padding-bottom: 24px;
|
||||
padding-left: 0;
|
||||
padding-right: 0;">Welcome to Kerberos Hub</h2>
|
||||
padding-right: 0;">Welcome to Hub</h2>
|
||||
<a style="text-decoration: none;color: none;" href="{{link}}">
|
||||
<p style="font-family: Inter;
|
||||
font-size: 14px;
|
||||
@@ -268,7 +268,7 @@
|
||||
letter-spacing: 0em;
|
||||
text-align: left;
|
||||
color: #262424;
|
||||
width: 280px">Kerberos Hub in a nutshell</h3>
|
||||
width: 280px">Hub in a nutshell</h3>
|
||||
<p style=" font-family: Inter;
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
@@ -278,7 +278,7 @@
|
||||
letter-spacing: 0em;
|
||||
text-align: left;
|
||||
color: #6D6666;
|
||||
margin-top: 12px;">With Kerberos Hub you can access your surveillance media remotely. By subscribing to a plan, you get access to a set of features, from advanced filtering, notifications to machine learning.</p>
|
||||
margin-top: 12px;">With Hub you can access your surveillance media remotely. By subscribing to a plan, you get access to a set of features, from advanced filtering, notifications to machine learning.</p>
|
||||
<p style=" font-family: Inter;
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
@@ -374,7 +374,7 @@
|
||||
mso-line-height-rule:exactly;
|
||||
letter-spacing: 0em;
|
||||
text-align: left;
|
||||
color:#6D6666;">About Kerberos</h4>
|
||||
color:#6D6666;">About the ecosystem</h4>
|
||||
<p style=" font-family: Inter;
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
Kerberos.io
|
||||
Hub
|
||||
------------
|
||||
|
||||
Hey, {{user}}
|
||||
Welcome to Kerberos Hub
|
||||
Welcome to Hub
|
||||
Activate your account ->
|
||||
{{link}}
|
||||
|
||||
Kerberos Hub in a nutshell
|
||||
With Kerberos Hub you can access your surveillance media remotely. By subscribing to a plan, you get access to a set of features, from advanced filtering, notifications to machine learning.
|
||||
Hub in a nutshell
|
||||
With Hub you can access your surveillance media remotely. By subscribing to a plan, you get access to a set of features, from advanced filtering, notifications to machine learning.
|
||||
|
||||
However before you get started this amazing applications, please activate your account.
|
||||
|
||||
@@ -17,6 +17,6 @@ support@kerberos.io
|
||||
9000 Ghent, BE
|
||||
https://kerberos.io
|
||||
|
||||
About Kerberos
|
||||
About the ecosystem
|
||||
------------
|
||||
Welcome to the revolutionary video analytics and video management platform. Open, modular, and extensible for everyone, anywhere.
|
||||
|
||||
@@ -39,6 +39,8 @@ if [ "$command" == "apply" ]; then
|
||||
# Adjust the base path reference
|
||||
sed -i "s|../../base|./base|g" ./kustomization.yaml
|
||||
|
||||
bash scripts/install-garage.sh --prepare-only || exit 1
|
||||
|
||||
# Apply kustomize installation
|
||||
kubectl kustomize ./ --enable-helm --load-restrictor LoadRestrictionsNone | kubectl apply -f -
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
# Amazon DocumentDB
|
||||
|
||||
[Amazon DocumentDB](https://aws.amazon.com/documentdb/) is a managed, MongoDB
|
||||
compatible database. It can be used as the metadata store for Kerberos Hub
|
||||
compatible database. It can be used as the metadata store for Hub
|
||||
instead of a self-hosted MongoDB.
|
||||
|
||||
## Things to know
|
||||
|
||||
- **Not reachable from outside its VPC.** DocumentDB has no public endpoint, so
|
||||
the Kerberos Hub services must run inside (or be peered with) the same VPC.
|
||||
the Hub services must run inside (or be peered with) the same VPC.
|
||||
- **TLS is enabled by default.** Clients must trust the Amazon RDS certificate
|
||||
authority bundle:
|
||||
`https://truststore.pki.rds.amazonaws.com/global/global-bundle.pem`.
|
||||
@@ -23,7 +23,7 @@ The [`amazon-eks-documentdb`](../amazon-eks-documentdb/README.md) Terraform
|
||||
stack creates a VPC, an EKS cluster and a DocumentDB cluster with TLS enforced,
|
||||
and outputs a ready to paste `mongodb` values block for the hub helm chart.
|
||||
|
||||
## Connecting Kerberos Hub
|
||||
## Connecting Hub
|
||||
|
||||
Configure the database through `mongodb.uri` (not `mongodb.host`) and point the
|
||||
chart at the CA bundle:
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
Terraform stack that creates a **basic Kubernetes cluster (EKS) and a managed
|
||||
MongoDB-compatible database (Amazon DocumentDB) on AWS**, wired together so
|
||||
Kerberos Hub can be installed on it straight away.
|
||||
Hub can be installed on it straight away.
|
||||
|
||||
It is primarily meant as a **reproducible test environment** for the DocumentDB
|
||||
support in the [`hub` helm chart](https://github.com/kerberos-io/helm-charts),
|
||||
@@ -110,7 +110,7 @@ $(terraform output -raw update_kubeconfig_command)
|
||||
kubectl get nodes
|
||||
```
|
||||
|
||||
## Installing Kerberos Hub against DocumentDB
|
||||
## Installing Hub against DocumentDB
|
||||
|
||||
### 1. Create the certificate authority secret
|
||||
|
||||
@@ -370,6 +370,6 @@ for the full list; the ones you are most likely to change:
|
||||
|
||||
## Related
|
||||
|
||||
- [`../amazon-documentdb`](../amazon-documentdb/README.md) — using DocumentDB as the Kerberos Hub metadata store
|
||||
- [`../../overlays/documentdb`](../../overlays/documentdb) — Kustomize overlay that deploys Kerberos Hub against DocumentDB
|
||||
- [`../amazon-documentdb`](../amazon-documentdb/README.md) — using DocumentDB as the Hub metadata store
|
||||
- [`../../overlays/documentdb`](../../overlays/documentdb) — Kustomize overlay that deploys Hub against DocumentDB
|
||||
- [`../../README.k8s-managed.md`](../../README.k8s-managed.md) — installing on managed Kubernetes
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#
|
||||
# curl -O https://truststore.pki.rds.amazonaws.com/global/global-bundle.pem
|
||||
#
|
||||
# For Kerberos Hub that bundle is mounted through the helm chart's
|
||||
# For Hub that bundle is mounted through the helm chart's
|
||||
# `mongodb.tls` values, see the README next to this file.
|
||||
###############################################################################
|
||||
|
||||
@@ -28,7 +28,7 @@ locals {
|
||||
|
||||
resource "aws_security_group" "docdb" {
|
||||
name = "${local.name}-docdb"
|
||||
description = "MongoDB wire protocol access to the Kerberos Hub DocumentDB cluster"
|
||||
description = "MongoDB wire protocol access to the Hub DocumentDB cluster"
|
||||
vpc_id = module.vpc.vpc_id
|
||||
|
||||
tags = merge(local.tags, { Name = "${local.name}-docdb" })
|
||||
@@ -58,7 +58,7 @@ resource "aws_vpc_security_group_ingress_rule" "docdb_from_cidrs" {
|
||||
|
||||
resource "aws_docdb_subnet_group" "this" {
|
||||
name = local.docdb_subnet_group_name
|
||||
description = "Private subnets of the Kerberos Hub VPC"
|
||||
description = "Private subnets of the Hub VPC"
|
||||
subnet_ids = module.vpc.private_subnets
|
||||
|
||||
tags = local.tags
|
||||
@@ -71,7 +71,7 @@ resource "aws_docdb_subnet_group" "this" {
|
||||
resource "aws_docdb_cluster_parameter_group" "this" {
|
||||
name = "${local.name}-docdb"
|
||||
family = var.docdb_parameter_group_family
|
||||
description = "Kerberos Hub DocumentDB parameters"
|
||||
description = "Hub DocumentDB parameters"
|
||||
|
||||
parameter {
|
||||
name = "tls"
|
||||
|
||||
@@ -48,7 +48,7 @@ module "eks" {
|
||||
###############################################################################
|
||||
# EBS CSI driver
|
||||
#
|
||||
# Kerberos Hub's supporting components (RabbitMQ, VerneMQ, MinIO, ...) claim
|
||||
# Hub's supporting components (RabbitMQ, VerneMQ, MinIO, ...) claim
|
||||
# persistent volumes, so the cluster needs a working CSI driver.
|
||||
###############################################################################
|
||||
|
||||
|
||||
@@ -73,12 +73,12 @@ output "docdb_tls_enabled" {
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
# Kerberos Hub wiring
|
||||
# Hub wiring
|
||||
###############################################################################
|
||||
|
||||
output "mongodb_uri" {
|
||||
description = <<-EOT
|
||||
Connection string for the Kerberos Hub helm chart (`mongodb.uri`).
|
||||
Connection string for the Hub helm chart (`mongodb.uri`).
|
||||
The chart appends `tls=true` and `tlsCAFile=...` itself when
|
||||
`mongodb.tls.enabled=true`, so no TLS parameters are included here.
|
||||
Read it with: terraform output -raw mongodb_uri
|
||||
@@ -97,7 +97,7 @@ output "mongodb_uri" {
|
||||
|
||||
output "hub_values_snippet" {
|
||||
description = <<-EOT
|
||||
Ready to paste values for the Kerberos Hub helm chart. Write it to a file with:
|
||||
Ready to paste values for the Hub helm chart. Write it to a file with:
|
||||
terraform output -raw hub_values_snippet > hub-documentdb-values.yaml
|
||||
It expects the Amazon RDS CA bundle to be available as the `mongodb-ca` secret:
|
||||
curl -O https://truststore.pki.rds.amazonaws.com/global/global-bundle.pem
|
||||
|
||||
@@ -36,7 +36,7 @@ helmCharts:
|
||||
releaseName: hub
|
||||
namespace: kerberos-hub
|
||||
repo: https://charts.kerberos.io
|
||||
version: 0.84.0
|
||||
version: 0.170.1
|
||||
valuesFile: ../../base/hub/kerberos-hub-values.yaml
|
||||
valuesInline:
|
||||
license: "L/+FAwEBB2xpY2Vuc2UB/4YAAQIBB1BheWxvYWQBCgABCVNpZ25hdHVyZQEKAAAA/gMw/4YB/gEl/8wQACxnaXRodWIuY29tL3V1Zy1haS9odWItbGljZW5zZS9tb2RlbHMuTGljZW5zZf+BAwEBB0xpY2Vuc2UB/4IAAQwBAklkAf+EAAEDS2V5AQwAAQdDb21wYW55AQwAAQdFeHBUaW1lAQQAAQREYXlzAQQAAQdDYW1lcmFzAQQAAQVTaXRlcwEEAAEGVmF1bHRzAQQAAQpNZWRpYUxpbWl0AQQAAQlQZXJwZXR1YWwBAgABBkFjdGl2ZQECAAEJSXBBZGRyZXNzAQwAAAAY/4MBAQEIT2JqZWN0SUQB/4QAAQYBGAAAPf+COgEMAAAAAAAAAAAAAAAAAg9nZW5lcmljLWxpY2Vuc2UB+AJl6LAHsRMYAfoB0alKIAABEAEUARQDAQAB/gIAFlQqo9yJj1a3OH1+5iGjCPcz9VtrRuGfz/iuQEFohbCfSiZGAdHh16gEc59Z2kPaey+eJcwY0BQsBoipW7SwFRmcHkrWLuxt+Yzi2kvwmL4TN0quWqM4xxBzH1sejS6kZpPm7bw11JBsBuaNOYMbl5lgpPCFajWUH6GzfmuQlptNQKosocacI/9PaaqEUUM0ALjDZNSqqFwZPPsFh9WTeaHGbRbmwQRMPFDgaPCxiHnCCUagbvuVZeOQbKaR5gPTUfPQY/L4mrN9QnMxdzwUJgqm7FbTH4UhoZn6EEzNGTN6DbHhpx8lezzCRW8dzMNuK8R1igiORV5gdWOPzBMZlTgodIZRD07e8iAo2XqT/BWcqaJXutdqXltaiJKshh2QzStdv2WZUynVTguYIQJyBNhrXEkewKZA0UftcSemDPkCmp6VovMMveV4X3Cpzkm7ZHtE7j39At/kpuqY/icTEzRWYuQqEDtqXMVar84VOpgVhxeNrrqZniLq8o3ezRdwy0BJG5xT9cuMxq13ZB3Am9iqTSjx2mh5VZZeB33GjLVAtLscj8NoKWy7BThchXB9xwoiy2RLO8nE+EI8wPbg+ajb2Ta7AFyxHgJJU6cea+zEpiBMARwjPKqk2nn02xdfdqMzQ+E9e115sIqhotBM5RI7uBIf8DDwT93HLsJZRBAA"
|
||||
|
||||
@@ -26,7 +26,7 @@ helmCharts:
|
||||
releaseName: hub
|
||||
namespace: kerberos-hub
|
||||
repo: https://charts.kerberos.io
|
||||
version: 0.84.0
|
||||
version: 0.170.1
|
||||
valuesFile: ../../base/hub/kerberos-hub-values.yaml
|
||||
valuesInline:
|
||||
mqtt:
|
||||
|
||||
@@ -8,7 +8,7 @@ helmCharts:
|
||||
releaseName: hub
|
||||
namespace: kerberos-hub
|
||||
repo: https://charts.kerberos.io
|
||||
version: 0.84.0
|
||||
version: 0.170.1
|
||||
valuesFile: ../../base/hub/kerberos-hub-values.yaml
|
||||
valuesInline:
|
||||
kerberoshub:
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
if [[ "${CI:-false}" != true ]]; then
|
||||
echo "This smoke test changes Factory settings and restarts its pod. Run it only in a disposable CI cluster (CI=true)." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
temporary="$(mktemp -d)"
|
||||
pid=""
|
||||
stop_forward() {
|
||||
if [[ -n "$pid" ]]; then
|
||||
if kill -0 "$pid" 2>/dev/null; then
|
||||
kill "$pid"
|
||||
wait "$pid" || [[ "$?" == 143 ]]
|
||||
fi
|
||||
pid=""
|
||||
fi
|
||||
}
|
||||
cleanup() {
|
||||
stop_forward
|
||||
rm -f "$temporary/port-forward.log" "$temporary/login.json" "$temporary/config.json" "$temporary/saved.json" "$temporary/index.html"
|
||||
rmdir "$temporary"
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
kubectl -n kerberos-factory rollout status deployment/factory --timeout=300s
|
||||
kubectl -n kerberos-factory get deployment factory -o json | jq -e '
|
||||
.spec.template.spec as $pod |
|
||||
$pod.securityContext.fsGroup == 65532 and
|
||||
$pod.securityContext.seccompProfile.type == "RuntimeDefault" and
|
||||
($pod.containers[] | select(.name == "factory") |
|
||||
.securityContext.runAsNonRoot == true and
|
||||
.securityContext.runAsUser == 65532 and .securityContext.runAsGroup == 65532 and
|
||||
.securityContext.readOnlyRootFilesystem == true and
|
||||
.securityContext.allowPrivilegeEscalation == false and
|
||||
.securityContext.capabilities.drop == ["ALL"] and
|
||||
.ports == [{"name":"http","containerPort":8080,"protocol":"TCP"}] and
|
||||
any(.volumeMounts[]; .mountPath == "/home/factory/config") and
|
||||
any(.volumeMounts[]; .mountPath == "/tmp") and
|
||||
.startupProbe.httpGet.path == "/healthz" and
|
||||
.readinessProbe.httpGet.port == "http" and
|
||||
.livenessProbe.httpGet.port == "http")'
|
||||
kubectl -n kerberos-factory get service factory-nodeport -o json |
|
||||
jq -e '.spec.ports | any(.port == 80 and .targetPort == "http" and .nodePort == 30079)'
|
||||
kubectl -n kerberos-factory get configmap agent-global-config agent-template-config
|
||||
kubectl -n kerberos-factory exec deployment/factory -- /app/main healthcheck
|
||||
|
||||
forward() {
|
||||
kubectl -n kerberos-factory port-forward service/factory-nodeport 13979:80 > "$temporary/port-forward.log" 2>&1 &
|
||||
pid=$!
|
||||
for attempt in {1..30}; do
|
||||
if curl --fail --silent http://127.0.0.1:13979/healthz >/dev/null; then return; fi
|
||||
if ! kill -0 "$pid" 2>/dev/null; then break; fi
|
||||
sleep 1
|
||||
done
|
||||
cat "$temporary/port-forward.log" >&2
|
||||
echo "Factory Service port-forward did not become healthy." >&2
|
||||
exit 1
|
||||
}
|
||||
login() {
|
||||
curl --fail --silent --show-error -H 'Content-Type: application/json' \
|
||||
-d '{"username":"root","password":"kerberos"}' \
|
||||
http://127.0.0.1:13979/api/login > "$temporary/login.json"
|
||||
token="$(jq -er '.token | select(length > 0)' "$temporary/login.json")"
|
||||
if [[ "${GITHUB_ACTIONS:-false}" == true ]]; then echo "::add-mask::$token"; fi
|
||||
}
|
||||
forward
|
||||
curl --fail --silent --show-error http://127.0.0.1:13979/ > "$temporary/index.html"
|
||||
grep -qi '<html' "$temporary/index.html"
|
||||
test "$(curl --silent --output /dev/null --write-out '%{http_code}' http://127.0.0.1:13979/api/config)" = 401
|
||||
login
|
||||
curl --fail --silent --show-error -H "Authorization: Bearer $token" \
|
||||
http://127.0.0.1:13979/api/config > "$temporary/config.json"
|
||||
jq -e '.data.type == "global"' "$temporary/config.json"
|
||||
jq '.data | .timezone = (if .timezone == "UTC" then "Etc/GMT+1" else "UTC" end)' \
|
||||
"$temporary/config.json" > "$temporary/saved.json"
|
||||
timezone="$(jq -r '.timezone' "$temporary/saved.json")"
|
||||
curl --fail --silent --show-error -H "Authorization: Bearer $token" \
|
||||
-H 'Content-Type: application/json' --data-binary "@$temporary/saved.json" \
|
||||
http://127.0.0.1:13979/api/config | jq -e --arg timezone "$timezone" '.data.timezone == $timezone'
|
||||
kubectl -n kerberos-factory get configmap agent-global-config -o json |
|
||||
jq -e --arg timezone "$timezone" '.data["_source.json"] | fromjson | .timezone == $timezone'
|
||||
|
||||
pod_uid() {
|
||||
kubectl -n kerberos-factory get pods -l app=factory -o json |
|
||||
jq -er '[.items[] | select(.metadata.deletionTimestamp == null)][0].metadata.uid'
|
||||
}
|
||||
old_pod="$(pod_uid)"
|
||||
stop_forward
|
||||
kubectl -n kerberos-factory rollout restart deployment/factory
|
||||
kubectl -n kerberos-factory rollout status deployment/factory --timeout=300s
|
||||
test "$old_pod" != "$(pod_uid)"
|
||||
forward
|
||||
login
|
||||
curl --fail --silent --show-error -H "Authorization: Bearer $token" \
|
||||
http://127.0.0.1:13979/api/config | jq -e --arg timezone "$timezone" '.data.timezone == $timezone'
|
||||
kubectl -n kerberos-factory exec deployment/factory -- /app/main healthcheck
|
||||
echo "Factory passed: restricted runtime, Service routing, UI/auth/config, ConfigMap bootstrap and persisted settings after pod replacement."
|
||||
@@ -0,0 +1,64 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
if [[ $# -gt 1 || ( $# -eq 1 && "$1" != --restart ) ]]; then
|
||||
echo "Usage: bash scripts/check-garage.sh [--restart]" >&2
|
||||
exit 1
|
||||
fi
|
||||
if ! command -v aws > /dev/null; then
|
||||
echo "AWS CLI is required for the Garage S3 smoke test." >&2
|
||||
exit 1
|
||||
fi
|
||||
temporary="$(mktemp -d)"
|
||||
pid=""
|
||||
cleanup() {
|
||||
if [[ -n "$pid" ]]; then kill "$pid"; fi
|
||||
rm -f "$temporary/upload" "$temporary/download" "$temporary/port-forward.log" "$temporary/aws-config"
|
||||
rmdir "$temporary"
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
access_key="$(kubectl -n garage get secret garage-credentials -o jsonpath='{.data.access-key}' | base64 --decode)"
|
||||
secret_key="$(kubectl -n garage get secret garage-credentials -o jsonpath='{.data.secret-key}' | base64 --decode)"
|
||||
if [[ "${GITHUB_ACTIONS:-false}" == true ]]; then
|
||||
echo "::add-mask::$access_key"
|
||||
echo "::add-mask::$secret_key"
|
||||
fi
|
||||
forward() {
|
||||
kubectl -n garage port-forward service/garage 13900:3900 > "$temporary/port-forward.log" 2>&1 &
|
||||
pid=$!
|
||||
for attempt in {1..30}; do
|
||||
if curl --silent --output /dev/null http://127.0.0.1:13900/; then return; fi
|
||||
if ! kill -0 "$pid"; then break; fi
|
||||
sleep 1
|
||||
done
|
||||
cat "$temporary/port-forward.log" >&2
|
||||
echo "Garage port-forward did not become ready." >&2
|
||||
exit 1
|
||||
}
|
||||
forward
|
||||
|
||||
export AWS_ACCESS_KEY_ID="$access_key" AWS_SECRET_ACCESS_KEY="$secret_key"
|
||||
export AWS_DEFAULT_REGION=garage AWS_EC2_METADATA_DISABLED=true
|
||||
export AWS_PAGER=""
|
||||
unset AWS_SESSION_TOKEN AWS_PROFILE AWS_DEFAULT_PROFILE
|
||||
export AWS_REQUEST_CHECKSUM_CALCULATION=when_required AWS_RESPONSE_CHECKSUM_VALIDATION=when_required
|
||||
export AWS_CONFIG_FILE="$temporary/aws-config"
|
||||
printf '[default]\ns3 =\n addressing_style = path\n' > "$AWS_CONFIG_FILE"
|
||||
object="ci-smoke/$(openssl rand -hex 16)"
|
||||
openssl rand -hex 128 > "$temporary/upload"
|
||||
endpoint="http://127.0.0.1:13900"
|
||||
aws --endpoint-url "$endpoint" s3api put-object \
|
||||
--bucket mybucket --key "$object" --body "$temporary/upload"
|
||||
if [[ $# -eq 1 ]]; then
|
||||
kill "$pid"
|
||||
wait "$pid" || [[ "$?" == 143 ]]
|
||||
pid=""
|
||||
kubectl -n garage rollout restart statefulset/garage
|
||||
kubectl -n garage rollout status statefulset/garage --timeout=300s
|
||||
forward
|
||||
fi
|
||||
aws --endpoint-url "$endpoint" s3api get-object \
|
||||
--bucket mybucket --key "$object" "$temporary/download"
|
||||
cmp "$temporary/upload" "$temporary/download"
|
||||
echo "Garage S3 authenticated PUT/GET passed through the Kubernetes Service (object mybucket/$object retained)."
|
||||
@@ -0,0 +1,62 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
CHART="${1:-kerberos/hub}"
|
||||
version=()
|
||||
if [[ "$CHART" == kerberos/hub ]]; then version=(--version 0.170.1); fi
|
||||
|
||||
assert_contains() {
|
||||
if ! grep -Eq -- "$2" <<< "$1"; then
|
||||
printf 'Missing expected deployment runtime setting: %s\n' "$2" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
nodeport="$(awk '
|
||||
/^---/ { selected=0 }
|
||||
/name: hub-frontend-nodeport$/ { selected=1 }
|
||||
selected { print }
|
||||
' "$ROOT/base/hub/kerberos-hub-nodeports.yaml")"
|
||||
assert_contains "$nodeport" 'targetPort: http$'
|
||||
assert_contains "$nodeport" 'nodePort: 32080'
|
||||
|
||||
rendered="$(helm template hub "$CHART" "${version[@]}" --values "$ROOT/base/hub/kerberos-hub-values.yaml" \
|
||||
--set mode=ui --set kerberoshub.frontend.demoEnabled=true)"
|
||||
if grep -q 'image: "docker.io/ghcr.io/' <<< "$rendered"; then
|
||||
echo "Fully qualified GHCR image was prefixed with docker.io" >&2
|
||||
exit 1
|
||||
fi
|
||||
for name in hub-frontend hub-frontend-demo; do
|
||||
deployment="$(awk -v name="$name" '
|
||||
function emit() { if (deployment && matched) printf "%s", block }
|
||||
/^---$/ { emit(); block=""; deployment=0; matched=0 }
|
||||
{ block=block $0 "\n" }
|
||||
/^kind: Deployment$/ { deployment=1 }
|
||||
$0 == " name: " name { matched=1 }
|
||||
END { emit() }
|
||||
' <<< "$rendered")"
|
||||
for setting in 'containerPort: 8080' 'runAsNonRoot: true' 'runAsUser: 65532' \
|
||||
'readOnlyRootFilesystem: true' 'mountPath: /tmp' 'name: frontend-tmp'; do
|
||||
assert_contains "$deployment" "^[[:space:]]*(- )?$setting$"
|
||||
done
|
||||
assert_contains "$deployment" 'image: "ghcr.io/uug-ai/hub-frontend:v1.19.28"$'
|
||||
echo "OK: $name uses the promoted image and matching hardened runtime"
|
||||
done
|
||||
api="$(awk '
|
||||
function emit() { if (deployment && matched) printf "%s", block }
|
||||
/^---$/ { emit(); block=""; deployment=0; matched=0 }
|
||||
{ block=block $0 "\n" }
|
||||
/^kind: Deployment$/ { deployment=1 }
|
||||
/^ name: hub-api$/ { matched=1 }
|
||||
END { emit() }
|
||||
' <<< "$rendered")"
|
||||
for setting in 'runAsNonRoot: true' 'runAsUser: 65532' 'runAsGroup: 65532' \
|
||||
'fsGroup: 65532' 'readOnlyRootFilesystem: true' 'allowPrivilegeEscalation: false' \
|
||||
'type: RuntimeDefault' 'drop:' '- ALL' 'name: hub-api-tmp' \
|
||||
'emptyDir: \{\}' 'mountPath: /tmp'; do
|
||||
assert_contains "$api" "^[[:space:]]*(- )?$setting$"
|
||||
done
|
||||
assert_contains "$api" 'image: "ghcr.io/uug-ai/hub-api:v1.11.31"$'
|
||||
echo "OK: hub-api uses the promoted image, hardened security and writable scratch"
|
||||
echo "Deployment Hub runtime preflight passed."
|
||||
@@ -0,0 +1,19 @@
|
||||
#!/usr/bin/env bash
|
||||
set -uo pipefail
|
||||
|
||||
kubectl get pods,pvc -A -o wide
|
||||
kubectl get events -A --sort-by=.lastTimestamp
|
||||
for namespace in garage mongodb rabbitmq vernemq kerberos-vault kerberos-agent kerberos-hub kerberos-factory; do
|
||||
if ! pods="$(kubectl -n "$namespace" get pods -o name)"; then
|
||||
echo "::warning::Could not list pods in $namespace."
|
||||
continue
|
||||
fi
|
||||
for pod in $pods; do
|
||||
if ! kubectl -n "$namespace" describe "$pod"; then
|
||||
echo "::warning::Could not describe $namespace/$pod."
|
||||
fi
|
||||
if ! kubectl -n "$namespace" logs "$pod" --all-containers=true --tail=80 --prefix; then
|
||||
echo "::warning::Logs unavailable for $namespace/$pod."
|
||||
fi
|
||||
done
|
||||
done
|
||||
@@ -0,0 +1,39 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
if [[ $# -gt 1 || ( $# -eq 1 && "$1" != --prepare-only ) ]]; then
|
||||
echo "Usage: bash scripts/install-garage.sh [--prepare-only]" >&2
|
||||
exit 1
|
||||
fi
|
||||
kubectl apply -f "$ROOT/base/garage/namespace.yaml"
|
||||
|
||||
secret="$(kubectl -n garage get secret garage-credentials --ignore-not-found -o name)"
|
||||
if [[ -z "$secret" ]]; then
|
||||
pvc="$(kubectl -n garage get pvc data-garage-0 --ignore-not-found -o name)"
|
||||
if [[ -n "$pvc" ]]; then
|
||||
echo "Garage data already exists without its credentials. Restore garage-credentials from backup; refusing to generate replacement keys." >&2
|
||||
exit 1
|
||||
fi
|
||||
kubectl -n garage create secret generic garage-credentials \
|
||||
--from-literal="rpc-secret=$(openssl rand -hex 32)" \
|
||||
--from-literal="access-key=GK$(openssl rand -hex 16)" \
|
||||
--from-literal="secret-key=$(openssl rand -hex 32)"
|
||||
fi
|
||||
|
||||
if ! kubectl -n garage get secret garage-credentials -o json |
|
||||
jq -e '.data |
|
||||
(."rpc-secret" | @base64d | test("^[0-9a-f]{64}$")) and
|
||||
(."access-key" | @base64d | test("^GK[0-9a-f]{32}$")) and
|
||||
(."secret-key" | @base64d | test("^[0-9a-f]{64}$"))' > /dev/null; then
|
||||
echo "Garage credentials are missing or invalid; restore a valid garage-credentials Secret." >&2
|
||||
exit 1
|
||||
fi
|
||||
if [[ $# -eq 1 ]]; then
|
||||
echo "Garage credentials are ready; apply your Kustomize overlay next."
|
||||
exit 0
|
||||
fi
|
||||
kubectl apply -k "$ROOT/base/garage"
|
||||
kubectl -n garage rollout status statefulset/garage --timeout=300s
|
||||
kubectl -n garage exec garage-0 -- /garage bucket info mybucket > /dev/null
|
||||
echo "Garage is available at garage.garage:3900 (region garage, bucket mybucket). Credentials are in Secret garage/garage-credentials."
|
||||
@@ -0,0 +1,16 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
if [[ $# != 1 ]]; then
|
||||
echo "Usage: bash scripts/notify-slack.sh MESSAGE" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ -z "${SLACK_WEBHOOK_URL:-}" ]]; then
|
||||
echo "::warning::SLACK_WEBHOOK_URL is not configured; skipping optional Slack notification."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
jq -n --arg text "$1" '{text: $text}' |
|
||||
curl --fail-with-body --silent --show-error --retry 3 \
|
||||
-H 'Content-Type: application/json' --data-binary @- "$SLACK_WEBHOOK_URL"
|
||||
@@ -0,0 +1,45 @@
|
||||
import assert from 'node:assert/strict'
|
||||
import { readFile, writeFile } from 'node:fs/promises'
|
||||
|
||||
const root = new URL('../', import.meta.url)
|
||||
const names = ['how-it-works', 'deployment-self-hosted', 'deployment-managed']
|
||||
const check = process.argv.includes('--check')
|
||||
assert(process.argv.slice(2).every(arg => arg === '--check'), 'Usage: node scripts/update-diagram-links.mjs [--check]')
|
||||
|
||||
const links = []
|
||||
for (const name of names) {
|
||||
const diagram = JSON.parse(await readFile(new URL(`assets/diagrams/${name}.json`, root), 'utf8'))
|
||||
assert(Array.isArray(diagram.groups) && Array.isArray(diagram.nodes) && Array.isArray(diagram.connections), `${name}: missing diagram arrays`)
|
||||
const ids = new Set()
|
||||
for (const node of diagram.nodes) {
|
||||
assert(typeof node.id === 'string' && node.id && !ids.has(node.id), `${name}: invalid or duplicate node id`)
|
||||
ids.add(node.id)
|
||||
}
|
||||
for (const item of [...diagram.groups, ...diagram.nodes]) {
|
||||
assert([item.x, item.y, item.w, item.h].every(Number.isFinite) && item.w > 0 && item.h > 0, `${name}: invalid bounds`)
|
||||
}
|
||||
for (const connection of diagram.connections) {
|
||||
assert(ids.has(connection.from) && ids.has(connection.to), `${name}: dangling connection`)
|
||||
for (const side of [connection.fromSide, connection.toSide]) {
|
||||
assert(['left', 'right', 'top', 'bottom'].includes(side), `${name}: invalid connection side`)
|
||||
}
|
||||
}
|
||||
const preview = await readFile(new URL(`assets/images/${name}.svg`, root), 'utf8')
|
||||
assert(preview.startsWith('<svg') && !/<(?:script|foreignObject)\b/i.test(preview), `${name}: expected a GitHub-safe SVG export`)
|
||||
const payload = Buffer.from(JSON.stringify(diagram), 'utf8').toString('base64')
|
||||
links.push(`[draw-${name}]: https://draw.uug.ai/#diagram=${payload}`)
|
||||
}
|
||||
|
||||
const file = new URL('README.md', root)
|
||||
const readme = await readFile(file, 'utf8')
|
||||
const start = '<!-- BEGIN GENERATED DRAW LINKS -->'
|
||||
const end = '<!-- END GENERATED DRAW LINKS -->'
|
||||
assert(readme.split(start).length === 2 && readme.split(end).length === 2, 'Expected one Draw links section in README.md')
|
||||
const section = `${start}\n${links.join('\n')}\n${end}`
|
||||
const updated = readme.replace(/<!-- BEGIN GENERATED DRAW LINKS -->[\s\S]*?<!-- END GENERATED DRAW LINKS -->/, section)
|
||||
if (check) {
|
||||
assert.equal(updated, readme, 'Draw links are stale. Run node scripts/update-diagram-links.mjs')
|
||||
} else if (updated !== readme) {
|
||||
await writeFile(file, updated)
|
||||
}
|
||||
console.log(`${check ? 'Verified' : 'Updated'} ${names.length} editable Draw links and checked their sources/previews.`)
|
||||
Reference in New Issue
Block a user