diff --git a/fleet/lib/netbox/README.md b/fleet/lib/netbox/README.md
new file mode 100644
index 000000000..e7f56b0d7
--- /dev/null
+++ b/fleet/lib/netbox/README.md
@@ -0,0 +1,59 @@
+# NetBox Kubernetes Deployment
+
+## Overview
+
+NetBox is an Infrastructure Resource Modeling (IRM) application designed to empower network automation. This deployment provides a production-ready NetBox instance on Kubernetes using Helm charts and Fleet configuration management.
+
+## Architecture
+
+- **Chart**: netbox v6.1.5 from
+- **Namespace**: netbox
+- **Components**: Web application, worker processes, PostgreSQL database, Valkey cache
+- **Ingress**: NGINX with Let's Encrypt TLS certificates
+
+## Configuration
+
+### Core Settings
+
+- **Timezone**: America/Santiago
+- **Superuser**:
+- **Change Log Retention**: 90 days
+- **Job Retention**: 90 days
+- **GraphQL**: Enabled
+- **Login Required**: False
+
+### Security
+
+- Non-root container execution (UID/GID: 1000)
+- Read-only root filesystem
+- Dropped capabilities
+- Runtime security profile enabled
+- External secret management via Kubernetes secrets
+
+### Storage
+
+- **Persistence**: Disabled (ephemeral storage)
+- **PostgreSQL**: 20Gi persistent storage (rook-ceph-block)
+- **Media/Reports/Scripts**: Stored in ephemeral volumes
+
+### Resources
+
+| Component | CPU Request | Memory Request | CPU Limit | Memory Limit |
+|-----------|-------------|----------------|-----------|--------------|
+| NetBox | 500m | 1Gi | 1000m | 2Gi |
+| Worker | 500m | 1Gi | 1000m | 2Gi |
+| PostgreSQL| 250m | 512Mi | 500m | 1Gi |
+
+## Access
+
+NetBox is accessible via dynamically generated hostnames based on cluster configuration:
+
+```bash
+https://netbox.{cluster-name}.{site}.lsst.org
+```
+
+## Maintenance
+
+- **Housekeeping**: Daily automated cleanup (00:00 UTC)
+- **Job History**: 5 successful/failed jobs retained
+- **Monitoring**: Available via cluster monitoring stack
diff --git a/fleet/lib/netbox/base/externalsecret-netbox-keycloak.yaml b/fleet/lib/netbox/base/externalsecret-netbox-keycloak.yaml
new file mode 100644
index 000000000..d33fc204e
--- /dev/null
+++ b/fleet/lib/netbox/base/externalsecret-netbox-keycloak.yaml
@@ -0,0 +1,21 @@
+apiVersion: external-secrets.io/v1
+kind: ExternalSecret
+metadata:
+ name: netbox-keycloak
+ namespace: netbox
+spec:
+ secretStoreRef:
+ kind: ClusterSecretStore
+ name: onepassword
+ target:
+ name: netbox-keycloak
+ creationPolicy: Owner
+ data:
+ - secretKey: SOCIAL_AUTH_KEYCLOAK_KEY
+ remoteRef:
+ key: &item netbox-keycloak-sso
+ property: client-id
+ - secretKey: SOCIAL_AUTH_KEYCLOAK_SECRET
+ remoteRef:
+ key: *item
+ property: client-secret
diff --git a/fleet/lib/netbox/base/externalsecret-netbox-postgresql.yaml b/fleet/lib/netbox/base/externalsecret-netbox-postgresql.yaml
new file mode 100644
index 000000000..6a137bb18
--- /dev/null
+++ b/fleet/lib/netbox/base/externalsecret-netbox-postgresql.yaml
@@ -0,0 +1,21 @@
+apiVersion: external-secrets.io/v1
+kind: ExternalSecret
+metadata:
+ name: netbox-postgresql
+ namespace: netbox
+spec:
+ secretStoreRef:
+ kind: ClusterSecretStore
+ name: onepassword
+ target:
+ name: netbox-postgresql
+ creationPolicy: Owner
+ data:
+ - secretKey: password
+ remoteRef:
+ key: &item netbox-postgresql
+ property: password
+ - secretKey: postgres-password
+ remoteRef:
+ key: *item
+ property: postgres-password
diff --git a/fleet/lib/netbox/base/externalsecret-netbox-secrets.yaml b/fleet/lib/netbox/base/externalsecret-netbox-secrets.yaml
new file mode 100644
index 000000000..a6e25c74d
--- /dev/null
+++ b/fleet/lib/netbox/base/externalsecret-netbox-secrets.yaml
@@ -0,0 +1,33 @@
+apiVersion: external-secrets.io/v1
+kind: ExternalSecret
+metadata:
+ name: netbox-secrets
+ namespace: netbox
+spec:
+ secretStoreRef:
+ kind: ClusterSecretStore
+ name: onepassword
+ target:
+ name: netbox-secrets
+ creationPolicy: Owner
+ data:
+ - secretKey: username
+ remoteRef:
+ key: &item netbox-secrets
+ property: username
+ - secretKey: password
+ remoteRef:
+ key: *item
+ property: password
+ - secretKey: email
+ remoteRef:
+ key: *item
+ property: email
+ - secretKey: api_token
+ remoteRef:
+ key: *item
+ property: apiToken
+ - secretKey: secret-key
+ remoteRef:
+ key: *item
+ property: secretKey
diff --git a/fleet/lib/netbox/base/externalsecret-netbox-valkey.yaml b/fleet/lib/netbox/base/externalsecret-netbox-valkey.yaml
new file mode 100644
index 000000000..e91338163
--- /dev/null
+++ b/fleet/lib/netbox/base/externalsecret-netbox-valkey.yaml
@@ -0,0 +1,17 @@
+apiVersion: external-secrets.io/v1
+kind: ExternalSecret
+metadata:
+ name: netbox-valkey
+ namespace: netbox
+spec:
+ secretStoreRef:
+ kind: ClusterSecretStore
+ name: onepassword
+ target:
+ name: netbox-valkey
+ creationPolicy: Owner
+ data:
+ - secretKey: valkey-password
+ remoteRef:
+ key: &item netbox-valkey
+ property: password
diff --git a/fleet/lib/netbox/base/kustomization.yaml b/fleet/lib/netbox/base/kustomization.yaml
new file mode 100644
index 000000000..3aaa5138a
--- /dev/null
+++ b/fleet/lib/netbox/base/kustomization.yaml
@@ -0,0 +1,12 @@
+---
+resources:
+ - externalsecret-netbox-secrets.yaml
+ - externalsecret-netbox-valkey.yaml
+ - externalsecret-netbox-postgresql.yaml
+ - externalsecret-netbox-keycloak.yaml
+
+patches:
+ - path: netbox-plugin-init-patch.yaml
+ target:
+ kind: Deployment
+ name: netbox
diff --git a/fleet/lib/netbox/base/netbox-plugin-init-patch.yaml b/fleet/lib/netbox/base/netbox-plugin-init-patch.yaml
new file mode 100644
index 000000000..0d1aa42a2
--- /dev/null
+++ b/fleet/lib/netbox/base/netbox-plugin-init-patch.yaml
@@ -0,0 +1,51 @@
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: netbox
+spec:
+ template:
+ spec:
+ # Add shared volume for plugins
+ volumes:
+ - name: plugins-volume
+ emptyDir: {}
+ # Init container to install slurpit_netbox plugin
+ initContainers:
+ - name: install-plugins
+ image: python:3.11-slim
+ command:
+ - /bin/bash
+ - -c
+ - |
+ set -e
+ echo "Installing slurpit_netbox plugin..."
+
+ # Install pip if not available
+ python -m ensurepip --upgrade
+
+ # Install the slurpit_netbox plugin to shared volume
+ pip install --target /opt/plugins slurpit_netbox
+
+ echo "Plugin installation completed"
+ ls -la /opt/plugins/
+ volumeMounts:
+ - name: plugins-volume
+ mountPath: /opt/plugins
+ resources:
+ requests:
+ cpu: 100m
+ memory: 256Mi
+ limits:
+ cpu: 500m
+ memory: 512Mi
+ containers:
+ - name: netbox
+ # Mount the plugins volume
+ volumeMounts:
+ - name: plugins-volume
+ mountPath: /opt/netbox/plugins
+ # Update PYTHONPATH to include plugins directory
+ env:
+ - name: PYTHONPATH
+ value: "/opt/netbox/plugins:/opt/netbox"
\ No newline at end of file
diff --git a/fleet/lib/netbox/fleet.yaml b/fleet/lib/netbox/fleet.yaml
new file mode 100644
index 000000000..fc970ed7d
--- /dev/null
+++ b/fleet/lib/netbox/fleet.yaml
@@ -0,0 +1,17 @@
+---
+defaultNamespace: &name netbox
+labels:
+ bundle: *name
+namespaceLabels:
+ lsst.io/discover: "true"
+kustomize:
+ dir: base
+helm:
+ chart: &chart netbox
+ releaseName: *chart
+ repo: https://charts.netbox.oss.netboxlabs.com/
+ version: 6.1.5
+ timeoutSeconds: 600
+ waitForJobs: true
+ valuesFiles:
+ - values.yaml
diff --git a/fleet/lib/netbox/values.yaml b/fleet/lib/netbox/values.yaml
new file mode 100644
index 000000000..edae054f6
--- /dev/null
+++ b/fleet/lib/netbox/values.yaml
@@ -0,0 +1,205 @@
+nameOverride: netbox
+clusterDomain: cluster.local
+
+superuser:
+ name: admin
+ email: admin@lsst.org
+ existingSecret: netbox-secrets
+
+
+allowedHosts:
+ - netbox.${ get .ClusterLabels "management.cattle.io/cluster-display-name" }.${ .ClusterLabels.site }.lsst.org
+ - netbox.kueyen.dev.lsst.org
+
+allowedHostsIncludesPodIP: false
+
+admins:
+ - [Admin User, admin@tudominio.com]
+
+internalIPs: [127.0.0.1]
+
+timeZone: America/Santiago
+
+# Disable persistent volumes to avoid multi-attach issues with ReadWriteOnce storage
+# Media files will be stored in ephemeral storage
+persistence:
+ enabled: false
+ # storageClass: rook-ceph-block
+ # accessMode: ReadWriteOnce
+ # size: 10Gi
+ # annotations: {}
+
+reportsPersistence:
+ enabled: false
+ # storageClass: rook-ceph-block
+ # accessMode: ReadWriteOnce
+ # size: 1Gi
+ # annotations: {}
+
+scriptsPersistence:
+ enabled: false
+ # storageClass: rook-ceph-block
+ # accessMode: ReadWriteOnce
+ # size: 1Gi
+ # annotations: {}
+
+resourcesPreset: medium
+resources:
+ requests:
+ cpu: 500m
+ memory: 1Gi
+ limits:
+ cpu: 1000m
+ memory: 2Gi
+
+## @section Traffic Exposure Parameters
+
+ingress:
+ enabled: true
+ className: nginx
+ annotations:
+ cert-manager.io/cluster-issuer: letsencrypt
+ nginx.ingress.kubernetes.io/backend-protocol: HTTP
+ nginx.ingress.kubernetes.io/client-body-buffer-size: 10m
+ nginx.ingress.kubernetes.io/proxy-read-timeout: "60"
+ nginx.ingress.kubernetes.io/proxy-send-timeout: "60"
+ hosts:
+ - host: netbox.${ get .ClusterLabels "management.cattle.io/cluster-display-name" }.${ .ClusterLabels.site }.lsst.org
+ paths:
+ - /
+ tls:
+ - secretName: netbox-tls
+ hosts:
+ - netbox.${ get .ClusterLabels "management.cattle.io/cluster-display-name" }.${ .ClusterLabels.site }.lsst.org
+
+postgresql:
+ enabled: true
+ # Use default PostgreSQL version from chart (bitnami image tags are inconsistent)
+ auth:
+ username: netbox
+ database: netbox
+ # Dummy passwords - these are overridden by existingSecret
+ # Required by Bitnami chart to prevent upgrade errors
+ password: "unused"
+ postgresPassword: "unused"
+ existingSecret: netbox-postgresql
+ secretKeys:
+ adminPasswordKey: postgres-password
+ userPasswordKey: password
+ # Use external secret passwords for consistency
+ usePasswordFiles: false
+ # Ensure PostgreSQL is ready before Netbox starts
+ primary:
+ persistence:
+ enabled: true
+ storageClass: rook-ceph-block
+ size: 20Gi
+ resources:
+ requests:
+ cpu: 250m
+ memory: 512Mi
+ limits:
+ cpu: 500m
+ memory: 1Gi
+ # Prevent automatic restarts during upgrades
+ podDisruptionBudget:
+ create: true
+ minAvailable: 1
+ # Use RollingUpdate strategy (Recreate is not valid for StatefulSets)
+ updateStrategy:
+ type: RollingUpdate
+ # Global PostgreSQL configuration to prevent credential mismatch
+ global:
+ postgresql:
+ auth:
+ # Dummy passwords - overridden by existingSecret
+ password: "unused"
+ postgresPassword: "unused"
+ existingSecret: netbox-postgresql
+ secretKeys:
+ adminPasswordKey: postgres-password
+ userPasswordKey: password
+ # Disable automatic version upgrades
+ upgradeRepmgrExtension: false
+
+valkey:
+ enabled: true
+ auth:
+ existingSecret: netbox-valkey
+ existingSecretPasswordKey: valkey-password
+
+## @section Worker for Netbox parameters
+
+worker:
+ enabled: true
+ replicaCount: 1
+ # Fix kubectl image version - 1.33.3 doesn't exist
+ initContainer:
+ image:
+ registry: docker.io
+ repository: bitnami/kubectl
+ tag: 1.31-debian-12
+ resources:
+ requests:
+ cpu: 500m
+ memory: 1Gi
+ limits:
+ cpu: 1000m
+ memory: 2Gi
+
+## @section Cron housekeeping job parameters
+
+housekeeping:
+ enabled: true
+ schedule: 0 0 * * *
+ successfulJobsHistoryLimit: 5
+ failedJobsHistoryLimit: 5
+ resourcesPreset: medium
+ resources:
+ requests:
+ cpu: 500m
+ memory: 1Gi
+ limits:
+ cpu: 1000m
+ memory: 2Gi
+
+# Database configuration using external secrets
+extraEnvs:
+ - name: DB_WAIT_DEBUG
+ value: "1"
+ - name: SECRET_KEY
+ valueFrom:
+ secretKeyRef:
+ name: netbox-secrets
+ key: secret-key
+ - name: SOCIAL_AUTH_KEYCLOAK_KEY
+ valueFrom:
+ secretKeyRef:
+ name: netbox-keycloak
+ key: SOCIAL_AUTH_KEYCLOAK_KEY
+ - name: SOCIAL_AUTH_KEYCLOAK_SECRET
+ valueFrom:
+ secretKeyRef:
+ name: netbox-keycloak
+ key: SOCIAL_AUTH_KEYCLOAK_SECRET
+ - name: SOCIAL_AUTH_KEYCLOAK_AUTHORIZATION_URL
+ value: "https://keycloak.ls.lsst.org/realms/master/protocol/openid-connect/auth"
+ - name: SOCIAL_AUTH_KEYCLOAK_ACCESS_TOKEN_URL
+ value: "https://keycloak.ls.lsst.org/realms/master/protocol/openid-connect/token"
+ - name: SOCIAL_AUTH_KEYCLOAK_ID_KEY
+ value: "preferred_username"
+
+
+# Plugin configuration
+plugins: []
+
+## @section Remote Authentication (SSO) Parameters
+
+remoteAuth:
+ enabled: true
+ backends:
+ - social_core.backends.keycloak.KeycloakOAuth2
+
+# All Keycloak configuration is now done via environment variables in extraEnvs
+# NetBox will automatically read SOCIAL_AUTH_* environment variables
+
diff --git a/fleet/s/dev/c/kueyen/netbox b/fleet/s/dev/c/kueyen/netbox
new file mode 120000
index 000000000..ccfcf159f
--- /dev/null
+++ b/fleet/s/dev/c/kueyen/netbox
@@ -0,0 +1 @@
+../../../../lib/netbox
\ No newline at end of file