Compare commits

..
23 Commits
Author SHA1 Message Date
renovate-bot 7282f69530 chore(deps): update container patch updates
deploy / validate (push) Skipped
renovate-ci / validate-renovate (push) Skipped
ci / lint-prettier (push) Successful in 3s
ci / lint-ruff (push) Successful in 1s
ci / lint-yaml (push) Successful in 2s
ci / lint-dockerfiles (push) Successful in 1s
ci / validate (push) Successful in 3s
ci / build (push) Skipped
ci / lint-prettier (pull_request) Successful in 3s
ci / lint-ruff (pull_request) Successful in 1s
ci / lint-yaml (pull_request) Successful in 2s
ci / lint-dockerfiles (pull_request) Successful in 1s
ci / validate (pull_request) Successful in 2s
ci / build (pull_request) Skipped
renovate-ci / validate-renovate (pull_request) Successful in 15s
2026-09-26 15:55:54 +00:00
forust 1d9a85bef9 fix(edu-master): stop 20722d false alert on zeroed last_success gauge
ci / validate (push) Successful in 2s
ci / lint-prettier (push) Successful in 3s
ci / lint-ruff (push) Successful in 1s
ci / lint-yaml (push) Successful in 2s
ci / lint-dockerfiles (push) Successful in 1s
deploy / preflight (push) Successful in 2s
renovate-ci / validate-renovate (push) Successful in 14s
ci / build (push) Successful in 2s
deploy / validate (push) Successful in 1m52s
deploy / apply-k8s (push) Successful in 1m48s
deploy / apply-compose (push) Successful in 13s
checker.py initialises last_success to 0, so right after a pod restart
`time() - last_success` equals the current epoch. The rule compared that
against 300, went firing instantly, and humanizeDuration rendered the raw
epoch delta as ~20722d. The last_run > 0 guard did not help because a run
happens long before the first success.

Guard the duration rule on last_success > 0, keeping the duration
expression on the left of `and` so $value stays the real gap, and add a
separate WebinarCheckerNeverSucceeded rule for the zeroed-gauge case so a
checker that has never succeeded is still caught.
2026-09-26 17:50:45 +02:00
forust b625d30568 ci(deploy): cancel superseded deploys on new push
deploy / preflight (push) Successful in 1s
deploy / validate (push) Successful in 1m53s
deploy / apply-k8s (push) Successful in 1m48s
ci / lint-prettier (push) Successful in 3s
ci / lint-ruff (push) Successful in 2s
ci / lint-yaml (push) Successful in 3s
ci / lint-dockerfiles (push) Successful in 6s
ci / validate (push) Successful in 1s
renovate-ci / validate-renovate (push) Successful in 13s
ci / build (push) Successful in 1s
deploy / apply-compose (push) Successful in 12s
Queued deploy runs were deploying origin/main at start anyway (preflight reset), so waiting runs duplicated the newest deploy instead of their own commit. Cancel them.
2026-09-26 17:42:36 +02:00
forust d018a441af fix(deploy): move netbox from compose to k8s
ci / lint-dockerfiles (push) Successful in 1s
ci / validate (push) Successful in 2s
renovate-ci / validate-renovate (push) Successful in 17s
deploy / preflight (push) Successful in 2s
ci / build (push) Successful in 1s
deploy / apply-k8s (push) Canceled after 0s
deploy / apply-compose (push) Canceled after 0s
ci / lint-prettier (push) Successful in 3s
ci / lint-ruff (push) Successful in 1s
ci / lint-yaml (push) Successful in 3s
deploy / validate (push) Canceled after 4s
compose.yaml is a local-only stand on 127.0.0.1:8000 per README; the live service runs in-cluster. The root active marker made apply-compose fail on gitignored .env vars.
2026-09-26 17:38:20 +02:00
forust ecb254017d fix(searxng): use existing image tag 2026.9.25-12f8b6515
ci / validate (push) Successful in 2s
ci / build (push) Successful in 1s
deploy / apply-k8s (push) Successful in 2m23s
deploy / apply-compose (push) Failing after 8s
ci / lint-prettier (push) Successful in 3s
ci / lint-ruff (push) Successful in 1s
ci / lint-yaml (push) Successful in 2s
ci / lint-dockerfiles (push) Successful in 1s
deploy / preflight (push) Successful in 2s
renovate-ci / validate-renovate (push) Successful in 18s
deploy / validate (push) Successful in 1m46s
2026.09.13-d4ce87c23 was never published (upstream tags month without leading zero); rollout stuck in ImagePullBackOff. Verified replacement tag exists on Docker Hub.
2026-09-26 17:37:20 +02:00
forust 41f18ea993 fix(deploy): move netbird from compose to k8s
ci / lint-prettier (push) Successful in 3s
ci / lint-ruff (push) Successful in 1s
ci / lint-yaml (push) Successful in 3s
ci / lint-dockerfiles (push) Successful in 1s
ci / validate (push) Successful in 2s
deploy / preflight (push) Successful in 2s
renovate-ci / validate-renovate (push) Successful in 19s
ci / build (push) Successful in 2s
deploy / validate (push) Successful in 1m45s
deploy / apply-k8s (push) Successful in 1m52s
deploy / apply-compose (push) Failing after 24s
netbird runs in-cluster; the root active marker made apply-compose pick up netbird/compose.yaml and fail on gitignored .env vars. Drop the compose marker and enable k8s/active instead.
2026-09-26 17:24:03 +02:00
forust 91c344fe2c fix(monitoring): disable control-plane alerts and scrapes on k0s
ci / lint-prettier (push) Successful in 3s
ci / lint-ruff (push) Successful in 1s
ci / lint-yaml (push) Successful in 2s
ci / lint-dockerfiles (push) Successful in 1s
ci / validate (push) Successful in 3s
deploy / preflight (push) Successful in 2s
renovate-ci / validate-renovate (push) Successful in 24s
deploy / validate (push) Successful in 1m42s
deploy / apply-k8s (push) Successful in 1m45s
ci / build (push) Successful in 2s
deploy / apply-compose (push) Failing after 9s
k0s runs kube-controller-manager, kube-scheduler and etcd inside its own
process rather than as pods, so the chart's Services never get endpoints
and the targets stay permanently absent. Drop the matching ServiceMonitors
and their Down/HighCommitDurations rules; kube-proxy and kubelet do get
endpoints on k0s and stay enabled.
2026-09-26 17:16:55 +02:00
forust cab6ef2102 Merge branch 'feat/netbird'
ci / lint-prettier (push) Successful in 3s
ci / lint-ruff (push) Successful in 1s
ci / lint-yaml (push) Successful in 2s
ci / lint-dockerfiles (push) Successful in 1s
ci / validate (push) Successful in 2s
deploy / preflight (push) Successful in 2s
deploy / validate (push) Successful in 1m43s
renovate-ci / validate-renovate (push) Successful in 14s
ci / build (push) Successful in 1s
deploy / apply-k8s (push) Successful in 3m15s
deploy / apply-compose (push) Failing after 41s
2026-09-26 17:05:55 +02:00
forust 62d39ee4f1 Merge pull request 'chore(deps): update netbirdio/dashboard docker tag to v2.93.0' (#53) from renovate/netbirdio-dashboard-2.x into main
ci / lint-dockerfiles (push) Successful in 1s
deploy / preflight (push) Successful in 2s
renovate-ci / validate-renovate (push) Successful in 9s
deploy / validate (push) Failing after 2s
deploy / apply-k8s (push) Skipped
deploy / apply-compose (push) Skipped
ci / lint-prettier (push) Successful in 3s
ci / lint-ruff (push) Successful in 1s
ci / lint-yaml (push) Successful in 3s
ci / validate (push) Successful in 1s
ci / build (push) Successful in 1s
Reviewed-on: #53
2026-09-25 22:27:21 +00:00
renovate-bot f1f7dd4a0a chore(deps): update netbirdio/dashboard docker tag to v2.93.0
deploy / validate (push) Skipped
renovate-ci / validate-renovate (push) Skipped
ci / lint-prettier (pull_request) Successful in 4s
ci / lint-ruff (pull_request) Successful in 2s
ci / lint-yaml (pull_request) Successful in 2s
ci / lint-dockerfiles (pull_request) Successful in 1s
ci / validate (pull_request) Successful in 2s
ci / build (pull_request) Skipped
renovate-ci / validate-renovate (pull_request) Successful in 9s
ci / lint-prettier (push) Successful in 2s
ci / lint-ruff (push) Successful in 1s
ci / lint-yaml (push) Successful in 2s
ci / lint-dockerfiles (push) Successful in 1s
ci / validate (push) Successful in 1s
ci / build (push) Skipped
2026-09-25 22:26:10 +00:00
forust f4df6d4437 Merge pull request 'chore(deps): update container patch updates' (#38) from renovate/container-patch-updates into main
renovate-ci / validate-renovate (push) Skipped
deploy / preflight (push) Successful in 3s
deploy / validate (push) Failing after 2s
deploy / apply-k8s (push) Skipped
deploy / apply-compose (push) Skipped
ci / lint-prettier (push) Successful in 3s
ci / lint-ruff (push) Successful in 1s
ci / lint-yaml (push) Successful in 2s
ci / lint-dockerfiles (push) Successful in 1s
ci / validate (push) Successful in 2s
ci / lint-prettier (pull_request) Successful in 3s
ci / lint-ruff (pull_request) Successful in 1s
ci / lint-yaml (pull_request) Successful in 2s
ci / validate (pull_request) Successful in 1s
ci / build (pull_request) Skipped
ci / build (push) Skipped
ci / lint-dockerfiles (pull_request) Successful in 1s
renovate-ci / validate-renovate (pull_request) Successful in 21s
Reviewed-on: #38
2026-09-25 22:18:21 +00:00
renovate-bot 987a89f022 chore(deps): update container patch updates
deploy / validate (push) Skipped
renovate-ci / validate-renovate (push) Skipped
ci / lint-prettier (push) Successful in 3s
ci / lint-ruff (push) Successful in 1s
ci / lint-yaml (push) Successful in 2s
ci / lint-dockerfiles (push) Successful in 1s
ci / validate (push) Successful in 1s
ci / build (push) Skipped
ci / lint-prettier (pull_request) Canceled after 0s
ci / lint-yaml (pull_request) Canceled after 0s
ci / lint-dockerfiles (pull_request) Canceled after 0s
ci / validate (pull_request) Canceled after 0s
ci / lint-ruff (pull_request) Canceled after 0s
ci / build (pull_request) Canceled after 0s
renovate-ci / validate-renovate (pull_request) Successful in 18s
2026-09-25 22:18:07 +00:00
forust b423119632 Merge pull request 'chore(deps): update renovate/renovate docker tag to v44.115.9' (#47) from renovate/renovate-renovate-44.x into main
ci / lint-prettier (push) Successful in 3s
ci / lint-ruff (push) Successful in 1s
ci / lint-yaml (push) Successful in 2s
ci / lint-dockerfiles (push) Successful in 1s
ci / validate (push) Successful in 3s
ci / build (push) Canceled after 0s
deploy / preflight (push) Successful in 3s
deploy / validate (push) Canceled after 0s
deploy / apply-k8s (push) Canceled after 0s
deploy / apply-compose (push) Canceled after 0s
renovate-ci / validate-renovate (push) Successful in 1m30s
Reviewed-on: #47
2026-09-25 22:17:46 +00:00
renovate-bot ddbc0cc7e6 chore(deps): update renovate/renovate docker tag to v44.115.9 2026-09-25 22:17:46 +00:00
forust 6ad33d75e6 Merge pull request 'chore(deps): update prom/prometheus docker tag to v3.15.0' (#48) from renovate/prom-prometheus-3.x into main
ci / lint-prettier (push) Successful in 3s
ci / lint-yaml (push) Successful in 2s
ci / lint-dockerfiles (push) Successful in 1s
ci / validate (push) Successful in 2s
ci / lint-ruff (push) Successful in 1s
deploy / preflight (push) Successful in 2s
ci / build (push) Canceled after 0s
deploy / validate (push) Canceled after 0s
deploy / apply-k8s (push) Canceled after 0s
deploy / apply-compose (push) Canceled after 0s
renovate-ci / validate-renovate (push) Successful in 24s
Reviewed-on: #48
2026-09-25 22:17:15 +00:00
renovate-bot 11bfb426c0 chore(deps): update prom/prometheus docker tag to v3.15.0 2026-09-25 22:17:15 +00:00
forust b7a1835adb Merge pull request 'feat(netbird): add tailscale-alternative' (#50) from feat/netbird into main
ci / lint-dockerfiles (push) Successful in 1s
ci / validate (push) Successful in 1s
deploy / preflight (push) Successful in 2s
ci / lint-prettier (push) Successful in 3s
ci / lint-ruff (push) Successful in 1s
ci / lint-yaml (push) Successful in 3s
ci / build (push) Canceled after 0s
deploy / validate (push) Canceled after 0s
deploy / apply-k8s (push) Canceled after 0s
deploy / apply-compose (push) Canceled after 0s
renovate-ci / validate-renovate (push) Successful in 21s
Reviewed-on: #50
2026-09-25 22:16:51 +00:00
forust ad4bb8750d chore(deploy): enable netbird
deploy / validate (push) Skipped
renovate-ci / validate-renovate (push) Skipped
ci / lint-prettier (push) Successful in 3s
ci / lint-ruff (push) Successful in 1s
ci / lint-yaml (push) Successful in 2s
ci / lint-dockerfiles (push) Successful in 1s
ci / validate (push) Successful in 2s
ci / build (push) Skipped
ci / lint-prettier (pull_request) Successful in 3s
ci / lint-ruff (pull_request) Successful in 1s
ci / lint-yaml (pull_request) Successful in 2s
ci / lint-dockerfiles (pull_request) Successful in 1s
ci / validate (pull_request) Successful in 1s
ci / build (pull_request) Skipped
renovate-ci / validate-renovate (pull_request) Successful in 8s
2026-09-25 22:16:02 +00:00
forust f1e00b946f Merge pull request 'Feat/documenting services' (#51) from feat/documenting-services into main
ci / lint-prettier (push) Successful in 3s
ci / lint-ruff (push) Successful in 0s
ci / lint-yaml (push) Successful in 3s
ci / lint-dockerfiles (push) Successful in 1s
ci / validate (push) Successful in 1s
deploy / preflight (push) Successful in 2s
renovate-ci / validate-renovate (push) Successful in 9s
ci / build (push) Successful in 1s
deploy / validate (push) Failing after 1s
deploy / apply-k8s (push) Skipped
deploy / apply-compose (push) Skipped
Reviewed-on: #51
2026-09-25 22:15:45 +00:00
forust 7ee7d0c961 Update README.md
deploy / validate (push) Skipped
renovate-ci / validate-renovate (push) Skipped
ci / lint-dockerfiles (push) Successful in 1s
ci / validate (push) Successful in 1s
ci / build (push) Skipped
ci / lint-prettier (pull_request) Successful in 3s
ci / lint-ruff (pull_request) Successful in 0s
ci / lint-yaml (pull_request) Successful in 2s
ci / validate (pull_request) Successful in 1s
ci / build (pull_request) Skipped
renovate-ci / validate-renovate (pull_request) Successful in 8s
ci / lint-prettier (push) Successful in 2s
ci / lint-ruff (push) Successful in 1s
ci / lint-yaml (push) Successful in 2s
ci / lint-dockerfiles (pull_request) Successful in 1s
2026-09-26 00:15:01 +02:00
forust 71e769c002 chore(deploy): disable checkmk, enable netbox and rackpeek
deploy / validate (push) Skipped
renovate-ci / validate-renovate (push) Skipped
ci / lint-prettier (push) Failing after 3s
ci / lint-ruff (push) Successful in 1s
ci / lint-yaml (push) Successful in 2s
ci / lint-dockerfiles (push) Successful in 1s
ci / validate (push) Successful in 2s
ci / build (push) Skipped
ci / lint-prettier (pull_request) Failing after 3s
ci / lint-ruff (pull_request) Successful in 1s
ci / lint-yaml (pull_request) Successful in 3s
ci / lint-dockerfiles (pull_request) Successful in 1s
ci / validate (pull_request) Successful in 1s
ci / build (pull_request) Skipped
renovate-ci / validate-renovate (pull_request) Successful in 21s
2026-09-26 00:04:37 +02:00
forust 16dd67c2c0 feat(rackpeek): add internal-only rack visualization service
Compose and k8s manifests behind workstation/gigaforust internal hosts.
2026-09-26 00:00:49 +02:00
forust c536a16a2a feat(netbox): add enterprise-grade server documenting app w/ shared postgres 2026-09-25 23:24:21 +02:00
48 changed files with 986 additions and 23 deletions

No files matched your search

+1 -1
View File
@@ -8,7 +8,7 @@ on:
concurrency:
group: deploy-main
cancel-in-progress: false
cancel-in-progress: true
env:
DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }}
+1 -1
View File
@@ -16,7 +16,7 @@ spec:
spec:
containers:
- name: cloudflared
image: cloudflare/cloudflared:2026.9.1
image: cloudflare/cloudflared:2026.9.3
imagePullPolicy: IfNotPresent
args:
- tunnel
+1 -1
View File
@@ -1,6 +1,6 @@
services:
redis:
image: redis:8.10.1-alpine
image: redis:8.10.2-alpine
restart: unless-stopped
volumes:
- redis-data:/data
+20 -1
View File
@@ -11,9 +11,14 @@ spec:
rules:
# No successful webinar check for 5m (~2-3 missed 2-min checks).
# Catches: playwright hangs/timeouts, version skew, site changes, hung job.
# The last_success > 0 guard is mandatory: checker.py initialises
# last_success to 0, so without it `time() - 0` equals the current epoch
# and humanizeDuration renders ~20722d on every pod restart. Keep the
# duration expression on the left so $value stays the real gap.
- alert: WebinarCheckerNoSuccessfulCheck
expr: |
(time() - webinar_check_last_success_timestamp_seconds > 300)
((time() - webinar_check_last_success_timestamp_seconds) > 300)
and (webinar_check_last_success_timestamp_seconds > 0)
and (webinar_check_last_run_timestamp_seconds > 0)
for: 2m
labels:
@@ -22,6 +27,20 @@ spec:
summary: "Webinar checker has no successful check for 5m"
description: "edu-master/webinar-checker: last successful webinar check was {{ $value | humanizeDuration }} ago. Checks are failing or hanging (see consecutive failures alert). Notifications about new webinars are NOT being sent."
# Checks are running but none has ever succeeded since pod start.
# Split out from the rule above so a zeroed gauge never feeds
# humanizeDuration.
- alert: WebinarCheckerNeverSucceeded
expr: |
(webinar_check_last_success_timestamp_seconds == 0)
and (webinar_check_last_run_timestamp_seconds > 0)
for: 10m
labels:
severity: critical
annotations:
summary: "Webinar checker has never completed a successful check"
description: 'edu-master/webinar-checker: checks have been running for 10m but not one has ever succeeded since the pod started, so every check is failing. Check pod logs (Loki: {namespace="edu-master", container="webinar-checker"}).'
# Fast path: 3 consecutive failures (~6+ min at 2-min interval).
- alert: WebinarCheckerConsecutiveFailures
expr: |
+1 -1
View File
@@ -18,7 +18,7 @@ spec:
spec:
containers:
- name: redis
image: redis:8.10.1-alpine
image: redis:8.10.2-alpine
imagePullPolicy: IfNotPresent
ports:
- containerPort: 6379
+1 -1
View File
@@ -17,7 +17,7 @@ spec:
spec:
initContainers:
- name: wait-redis
image: redis:8.10.1-alpine
image: redis:8.10.2-alpine
command:
- /bin/sh
- -ec
+1 -1
View File
@@ -19,7 +19,7 @@ spec:
# redis healthy -> session-keeper healthy (EXISTS EDU_PHPSESSID) -> playwright started
initContainers:
- name: wait-deps
image: redis:8.10.1-alpine
image: redis:8.10.2-alpine
command:
- /bin/sh
- -ec
+1 -1
View File
@@ -1,6 +1,6 @@
services:
headscale:
image: headscale/headscale:0.29.3
image: headscale/headscale:v0.29.4
restart: unless-stopped
container_name: headscale-server
command: serve
+1 -1
View File
@@ -36,7 +36,7 @@ services:
- proxy
- kener
redis:
image: redis:8.10.1-alpine
image: redis:8.10.2-alpine
container_name: kener-redis
restart: unless-stopped
volumes:
+1 -1
View File
@@ -30,7 +30,7 @@ spec:
spec:
containers:
- name: redis
image: redis:8.10.1-alpine
image: redis:8.10.2-alpine
ports:
- containerPort: 6379
volumeMounts:
+1 -1
View File
@@ -1,6 +1,6 @@
services:
metube:
image: ghcr.io/alexta69/metube:2026.09.15
image: ghcr.io/alexta69/metube:2026.09.26
container_name: metube
restart: unless-stopped
# ports:
+1 -1
View File
@@ -27,7 +27,7 @@ spec:
spec:
containers:
- name: metube
image: ghcr.io/alexta69/metube:2026.09.15
image: ghcr.io/alexta69/metube:2026.09.26
envFrom:
- configMapRef:
name: metube-config
+1 -1
View File
@@ -1,6 +1,6 @@
services:
n8n:
image: docker.n8n.io/n8nio/n8n:2.41.0
image: docker.n8n.io/n8nio/n8n:2.41.3
container_name: n8n
restart: unless-stopped
environment:
+1 -1
View File
@@ -27,7 +27,7 @@ spec:
spec:
containers:
- name: n8n
image: docker.n8n.io/n8nio/n8n:2.41.0
image: docker.n8n.io/n8nio/n8n:2.41.3
envFrom:
- configMapRef:
name: n8n-config
+1 -1
View File
@@ -87,7 +87,7 @@ services:
- proxy
dashboard:
image: netbirdio/dashboard:v2.90.10
image: netbirdio/dashboard:v2.93.0
container_name: netbird-dashboard
restart: unless-stopped
environment:
File renamed without changes.
+1 -1
View File
@@ -137,7 +137,7 @@ spec:
spec:
containers:
- name: dashboard
image: netbirdio/dashboard:v2.90.10
image: netbirdio/dashboard:v2.93.0
envFrom:
- configMapRef:
name: netbird-config
+32
View File
@@ -0,0 +1,32 @@
POSTGRES_DB=netbox
POSTGRES_USER=netbox
POSTGRES_PASSWORD=CHANGE_ME_POSTGRES_PASSWORD
DB_NAME=netbox
DB_USER=netbox
DB_PASSWORD=CHANGE_ME_POSTGRES_PASSWORD
DB_HOST=postgres
DB_PORT=5432
DB_SSLMODE=disable
REDIS_HOST=redis
REDIS_PORT=6379
REDIS_PASSWORD=CHANGE_ME_REDIS_PASSWORD
REDIS_DATABASE=0
REDIS_CACHE_HOST=redis-cache
REDIS_CACHE_PORT=6379
REDIS_CACHE_PASSWORD=CHANGE_ME_REDIS_CACHE_PASSWORD
REDIS_CACHE_DATABASE=1
ALLOWED_HOSTS=localhost,127.0.0.1,[::1],netbox.forust.xyz,netbox.workstation.internal
CSRF_TRUSTED_ORIGINS=https://netbox.forust.xyz,https://netbox.workstation.internal
SECRET_KEY=CHANGE_ME_DJANGO_SECRET_KEY
API_TOKEN_PEPPER_1=CHANGE_ME_API_TOKEN_PEPPER
TIME_ZONE=Europe/Bratislava
TZ=Europe/Bratislava
SKIP_SUPERUSER=false
SUPERUSER_NAME=admin
SUPERUSER_EMAIL=admin@example.com
SUPERUSER_PASSWORD=CHANGE_ME_SUPERUSER_PASSWORD
+96
View File
@@ -0,0 +1,96 @@
# NetBox
NetBox for homelab documentation and visualization. Two runtimes are available:
| Runtime | Manifest | Purpose |
| ------- | -------------- | -------------------------------------------------------------- |
| Docker | `compose.yaml` | Local stand on `127.0.0.1:8000` (no public exposure) |
| k8s | `k8s/` | Homelab service on `netbox.forust.xyz` (and the internal name) |
Both use the same image (`netboxcommunity/netbox:v4.7-5.1.1`) and Valkey for tasks
plus a second logical database for caching. The Docker stand keeps its own
PostgreSQL container, while the k8s deployment uses the shared `database` cluster
(`postgres.database.svc.cluster.local:5432`, role/database `netbox`); only Valkey
stays a per-service StatefulSet.
## Docker Compose
```bash
cp .env.example .env
# replace CHANGE_ME
docker compose up -d
```
The UI is available at <http://localhost:8000>. The port is bound to `127.0.0.1`
intentionally, so this stand is not exposed on the LAN or public interfaces.
The `netbox` service is also attached to the external `proxy` network and carries
Traefik labels for `netbox.forust.xyz` and `netbox.workstation.internal`. Those
labels only take effect while the Docker Traefik stack is running; it is currently
stopped, and the live ingress path in this homelab is the k8s Traefik.
Inspect startup and health with:
```bash
docker compose ps
docker compose logs -f netbox
```
Stop it with `docker compose down`; data is kept in the named volumes
`netbox-postgres`, `netbox-media-files`, `netbox-reports-files`,
`netbox-scripts-files` and `netbox-redis-data`.
## Kubernetes
`k8s/` is deployed in the homelab cluster and serves `netbox.forust.xyz` publicly
plus `netbox.workstation.internal` / `netbox.gigaforust.internal` internally. To
rebuild it from scratch:
```bash
# 1. shared PostgreSQL: the password lives in the shared secret, NetBox keeps a copy
kubectl -n database patch secret postgres-shared-secrets \
--type merge -p '{"stringData":{"NETBOX_DB_PASSWORD":"<same value>"}}'
kubectl -n database exec postgres17-0 -- psql -U postgres -d postgres \
-c 'CREATE ROLE netbox LOGIN PASSWORD ...' -c 'CREATE DATABASE netbox OWNER netbox'
# 2. secrets first: the deploy workflow never applies *secret*.yaml
cp k8s/secrets.yaml.example k8s/secrets.yaml # replace CHANGE_ME
kubectl apply -f k8s/secrets.yaml
# 3. manifests
kubectl apply -f k8s/
```
The shared cluster is reached at `postgres.database.svc.cluster.local:5432`. Its
NetworkPolicy (`postgres/k8s/network-policy.yaml`) must list the `netbox` namespace
or connections are dropped, and `postgres/initdb/01-create-databases.sh` already
creates the role and database on a fresh data directory. NetBox has no PostgreSQL
StatefulSet of its own — only `netbox-valkey`.
`netbox.forust.xyz` resolves to this host (`78.98.72.122`) through the `DOMAINS`
list in the `default/cfddns` secret. cert-manager issues `netbox-prod-tls` with the
`letsencrypt-prod` issuer, the internal route uses `internal-wildcard-tls`.
Resources are permanent again now that the first-boot migrations are complete:
the web container reserves `100m`/`512Mi` and is capped at `2` CPU/`2Gi`, the
worker reserves `50m`/`256Mi` and is capped at `1` CPU/`1Gi`, and Valkey reserves
`25m`/`64Mi` and is capped at `250m`/`256Mi`. The deliberately generous CPU caps
leave enough headroom for future schema migrations without letting one process
consume the whole node.
The first start applies ~810 migrations, each in its own transaction with DDL and
a commit; every later start is a no-op. The startup probe allows 15 minutes and
`progressDeadlineSeconds` is 1800 for the same reason. Probes run inside the pod
and explicitly set `Host: netbox.forust.xyz`; a kubelet `httpGet.host` field would
replace the probe destination with that public hostname and bypass the pod.
## Secrets
- `netbox/.env` (compose) and `netbox/k8s/secrets.yaml` (k8s) are gitignored. Only
`.env.example` and `k8s/secrets.yaml.example` are committed.
- `netbox/configuration/configuration.py` is env-driven: hosts, database, Redis and
the Django keys all come from the environment, so the same settings file works in
both runtimes. The k8s copy lives in the `netbox-settings` ConfigMap
(`k8s/settings.yaml`) and must be kept in sync with the file.
- Rotating `SECRET_KEY` invalidates all sessions; rotating `API_TOKEN_PEPPER_1`
invalidates every API token.
+137
View File
@@ -0,0 +1,137 @@
services:
netbox:
image: docker.io/netboxcommunity/netbox:v4.7-5.1.1
container_name: netbox
restart: unless-stopped
user: "netbox:root"
ports:
- "127.0.0.1:8000:8080"
env_file:
- .env
environment:
GRANIAN_WORKERS: "2"
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
redis-cache:
condition: service_healthy
volumes:
- ./configuration:/etc/netbox/config:z,ro
- netbox-media-files:/opt/netbox/netbox/media
- netbox-reports-files:/opt/netbox/netbox/reports
- netbox-scripts-files:/opt/netbox/netbox/scripts
networks:
- default
- proxy
labels:
- "traefik.enable=true"
- "traefik.http.services.netbox.loadbalancer.server.port=8080"
# Prod Router
- "traefik.http.routers.netbox.rule=Host(`netbox.forust.xyz`)"
- "traefik.http.routers.netbox.entrypoints=websecure"
- "traefik.http.routers.netbox.middlewares=security-headers@file"
- "traefik.http.routers.netbox.tls.certresolver=letsencrypt"
# Local Router
- "traefik.http.routers.netbox-local.rule=Host(`netbox.workstation.internal`)"
- "traefik.http.routers.netbox-local.entrypoints=websecure"
- "traefik.http.routers.netbox-local.tls=true"
healthcheck:
test: ["CMD", "/opt/netbox/health.sh"]
start_period: 600s
timeout: 5s
interval: 15s
retries: 10
netbox-worker:
image: docker.io/netboxcommunity/netbox:v4.7-5.1.1
container_name: netbox-worker
restart: unless-stopped
user: "netbox:root"
command:
- /opt/netbox/venv/bin/python
- /opt/netbox/netbox/manage.py
- rqworker
env_file:
- .env
depends_on:
netbox:
condition: service_healthy
volumes:
- ./configuration:/etc/netbox/config:z,ro
- netbox-media-files:/opt/netbox/netbox/media
- netbox-reports-files:/opt/netbox/netbox/reports
- netbox-scripts-files:/opt/netbox/netbox/scripts
healthcheck:
test: ["CMD-SHELL", "ps -ef | grep -q '[r]qworker'"]
start_period: 30s
timeout: 5s
interval: 15s
retries: 10
postgres:
image: docker.io/postgres:18.6-alpine
container_name: netbox-postgres
restart: unless-stopped
environment:
POSTGRES_DB: "${POSTGRES_DB:?POSTGRES_DB must be set}"
POSTGRES_USER: "${POSTGRES_USER:?POSTGRES_USER must be set}"
POSTGRES_PASSWORD: "${POSTGRES_PASSWORD:?POSTGRES_PASSWORD must be set}"
volumes:
- netbox-postgres:/var/lib/postgresql
healthcheck:
test: ["CMD-SHELL", 'pg_isready -q -t 2 -d "$${POSTGRES_DB}" -U "$${POSTGRES_USER}"']
start_period: 20s
timeout: 5s
interval: 10s
retries: 10
redis:
image: docker.io/valkey/valkey:9.1.2-alpine
container_name: netbox-redis
restart: unless-stopped
command:
- sh
- -c
- valkey-server --appendonly yes --requirepass "$$REDIS_PASSWORD"
environment:
REDIS_PASSWORD: "${REDIS_PASSWORD:?REDIS_PASSWORD must be set}"
volumes:
- netbox-redis-data:/data
healthcheck:
test: ["CMD-SHELL", 'valkey-cli --pass "$${REDIS_PASSWORD}" ping | grep -q PONG']
start_period: 5s
timeout: 5s
interval: 5s
retries: 10
redis-cache:
image: docker.io/valkey/valkey:9.1.2-alpine
container_name: netbox-redis-cache
restart: unless-stopped
command:
- sh
- -c
- valkey-server --requirepass "$$REDIS_CACHE_PASSWORD"
environment:
REDIS_CACHE_PASSWORD: "${REDIS_CACHE_PASSWORD:?REDIS_CACHE_PASSWORD must be set}"
healthcheck:
test: ["CMD-SHELL", 'valkey-cli --pass "$${REDIS_CACHE_PASSWORD}" ping | grep -q PONG']
start_period: 5s
timeout: 5s
interval: 5s
retries: 10
volumes:
netbox-media-files:
netbox-reports-files:
netbox-scripts-files:
netbox-postgres:
netbox-redis-data:
networks:
default:
proxy:
external: true
+48
View File
@@ -0,0 +1,48 @@
import os
def _csv(name, default=""):
return [item.strip() for item in os.environ.get(name, default).split(",") if item.strip()]
ALLOWED_HOSTS = _csv("ALLOWED_HOSTS", "localhost,127.0.0.1,[::1]")
CSRF_TRUSTED_ORIGINS = _csv("CSRF_TRUSTED_ORIGINS")
USE_X_FORWARDED_HOST = True
SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")
DATABASES = {
"default": {
"NAME": os.environ["DB_NAME"],
"USER": os.environ["DB_USER"],
"PASSWORD": os.environ["DB_PASSWORD"],
"HOST": os.environ["DB_HOST"],
"PORT": os.environ.get("DB_PORT", "5432"),
"OPTIONS": {"sslmode": os.environ.get("DB_SSLMODE", "disable")},
"CONN_MAX_AGE": int(os.environ.get("DB_CONN_MAX_AGE", "300")),
}
}
REDIS = {
"tasks": {
"HOST": os.environ["REDIS_HOST"],
"PORT": int(os.environ.get("REDIS_PORT", "6379")),
"PASSWORD": os.environ["REDIS_PASSWORD"],
"DATABASE": int(os.environ.get("REDIS_DATABASE", "0")),
"SSL": False,
},
"caching": {
"HOST": os.environ["REDIS_CACHE_HOST"],
"PORT": int(os.environ.get("REDIS_CACHE_PORT", "6379")),
"PASSWORD": os.environ["REDIS_CACHE_PASSWORD"],
"DATABASE": int(os.environ.get("REDIS_CACHE_DATABASE", "1")),
"SSL": False,
},
}
SECRET_KEY = os.environ["SECRET_KEY"]
API_TOKEN_PEPPERS = {1: os.environ["API_TOKEN_PEPPER_1"]}
TIME_ZONE = os.environ.get("TIME_ZONE", "UTC")
MEDIA_ROOT = "/opt/netbox/netbox/media"
REPORTS_ROOT = "/opt/netbox/netbox/reports"
SCRIPTS_ROOT = "/opt/netbox/netbox/scripts"
CENSUS_REPORTING_ENABLED = False
File renamed without changes.
+28
View File
@@ -0,0 +1,28 @@
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: netbox-prod-tls
namespace: netbox
spec:
secretName: netbox-prod-tls
dnsNames:
- netbox.forust.xyz
issuerRef:
name: letsencrypt-prod
kind: ClusterIssuer
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: internal-wildcard-tls
namespace: netbox
spec:
secretName: internal-wildcard-tls
dnsNames:
- "*.workstation.internal"
- "*.gigaforust.internal"
- workstation.internal
- gigaforust.internal
issuerRef:
name: internal-ca
kind: ClusterIssuer
+21
View File
@@ -0,0 +1,21 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: netbox-config
namespace: netbox
data:
DB_HOST: "postgres.database.svc.cluster.local"
DB_PORT: "5432"
DB_SSLMODE: "disable"
REDIS_HOST: "netbox-valkey"
REDIS_PORT: "6379"
REDIS_DATABASE: "0"
REDIS_CACHE_HOST: "netbox-valkey"
REDIS_CACHE_PORT: "6379"
REDIS_CACHE_DATABASE: "1"
TIME_ZONE: "Europe/Bratislava"
TZ: "Europe/Bratislava"
GRANIAN_WORKERS: "2"
ALLOWED_HOSTS: "netbox.forust.xyz,netbox.workstation.internal,netbox.gigaforust.internal"
CSRF_TRUSTED_ORIGINS: "https://netbox.forust.xyz,https://netbox.workstation.internal,https://netbox.gigaforust.internal"
SKIP_SUPERUSER: "false"
+36
View File
@@ -0,0 +1,36 @@
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: netbox-prod
namespace: netbox
spec:
entryPoints:
- websecure
routes:
- match: Host(`netbox.forust.xyz`)
kind: Rule
middlewares:
- name: crowdsec-bouncer
namespace: crowdsec
services:
- name: netbox-service
port: 8080
tls:
secretName: netbox-prod-tls
---
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: netbox-local
namespace: netbox
spec:
entryPoints:
- websecure
routes:
- match: Host(`netbox.workstation.internal`) || Host(`netbox.gigaforust.internal`)
kind: Rule
services:
- name: netbox-service
port: 8080
tls:
secretName: internal-wildcard-tls
+4
View File
@@ -0,0 +1,4 @@
apiVersion: v1
kind: Namespace
metadata:
name: netbox
+204
View File
@@ -0,0 +1,204 @@
apiVersion: v1
kind: Service
metadata:
name: netbox-service
namespace: netbox
spec:
selector:
app: netbox
ports:
- name: http
port: 8080
targetPort: http
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: netbox-deployment
namespace: netbox
labels:
app: netbox
spec:
replicas: 1
progressDeadlineSeconds: 300
selector:
matchLabels:
app: netbox
strategy:
# ReadWriteOnce PVC
type: Recreate
template:
metadata:
labels:
app: netbox
spec:
containers:
- name: netbox
image: docker.io/netboxcommunity/netbox:v4.7-5.1.1
ports:
- name: http
containerPort: 8080
envFrom:
- configMapRef:
name: netbox-config
- secretRef:
name: netbox-secrets
volumeMounts:
- name: netbox-config
mountPath: /etc/netbox/config
readOnly: true
- name: netbox-media
mountPath: /opt/netbox/netbox/media
- name: netbox-reports
mountPath: /opt/netbox/netbox/reports
- name: netbox-scripts
mountPath: /opt/netbox/netbox/scripts
startupProbe:
exec:
command:
- /opt/netbox/venv/bin/python
- -c
- >-
exec /usr/bin/curl --fail --silent --show-error --max-time 4
--header 'Host: netbox.forust.xyz'
http://127.0.0.1:8080/login/ >/dev/null
failureThreshold: 90
periodSeconds: 10
readinessProbe:
exec:
command:
- /opt/netbox/venv/bin/python
- -c
- >-
exec /usr/bin/curl --fail --silent --show-error --max-time 4
--header 'Host: netbox.forust.xyz'
http://127.0.0.1:8080/login/ >/dev/null
periodSeconds: 10
livenessProbe:
exec:
command:
- /opt/netbox/venv/bin/python
- -c
- >-
exec /usr/bin/curl --fail --silent --show-error --max-time 4
--header 'Host: netbox.forust.xyz'
http://127.0.0.1:8080/login/ >/dev/null
initialDelaySeconds: 30
periodSeconds: 30
resources:
requests:
cpu: "100m"
memory: "512Mi"
limits:
cpu: "2"
memory: "2Gi"
volumes:
- name: netbox-config
configMap:
name: netbox-settings
- name: netbox-media
persistentVolumeClaim:
claimName: netbox-media-pvc
- name: netbox-reports
persistentVolumeClaim:
claimName: netbox-reports-pvc
- name: netbox-scripts
persistentVolumeClaim:
claimName: netbox-scripts-pvc
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: netbox-worker-deployment
namespace: netbox
labels:
app: netbox-worker
spec:
replicas: 1
progressDeadlineSeconds: 300
selector:
matchLabels:
app: netbox-worker
strategy:
type: Recreate
template:
metadata:
labels:
app: netbox-worker
spec:
containers:
- name: netbox-worker
image: docker.io/netboxcommunity/netbox:v4.7-5.1.1
command:
- /opt/netbox/venv/bin/python
- netbox/manage.py
- rqworker
workingDir: /opt/netbox
envFrom:
- configMapRef:
name: netbox-config
- secretRef:
name: netbox-secrets
volumeMounts:
- name: netbox-config
mountPath: /etc/netbox/config
readOnly: true
- name: netbox-media
mountPath: /opt/netbox/netbox/media
- name: netbox-reports
mountPath: /opt/netbox/netbox/reports
- name: netbox-scripts
mountPath: /opt/netbox/netbox/scripts
resources:
requests:
cpu: "50m"
memory: "256Mi"
limits:
cpu: "1"
memory: "1Gi"
volumes:
- name: netbox-config
configMap:
name: netbox-settings
- name: netbox-media
persistentVolumeClaim:
claimName: netbox-media-pvc
- name: netbox-reports
persistentVolumeClaim:
claimName: netbox-reports-pvc
- name: netbox-scripts
persistentVolumeClaim:
claimName: netbox-scripts-pvc
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: netbox-media-pvc
namespace: netbox
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 2Gi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: netbox-reports-pvc
namespace: netbox
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 1Gi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: netbox-scripts-pvc
namespace: netbox
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 1Gi
+18
View File
@@ -0,0 +1,18 @@
apiVersion: v1
kind: Secret
metadata:
name: netbox-secrets
namespace: netbox
type: Opaque
stringData:
DB_NAME: "netbox"
DB_USER: "netbox"
DB_PASSWORD: "CHANGE_ME_POSTGRES_PASSWORD"
REDIS_PASSWORD: "CHANGE_ME_VALKEY_PASSWORD"
REDIS_CACHE_PASSWORD: "CHANGE_ME_VALKEY_PASSWORD"
VALKEY_PASSWORD: "CHANGE_ME_VALKEY_PASSWORD"
SECRET_KEY: "CHANGE_ME_DJANGO_SECRET_KEY"
API_TOKEN_PEPPER_1: "CHANGE_ME_API_TOKEN_PEPPER"
SUPERUSER_NAME: "admin"
SUPERUSER_EMAIL: "admin@example.com"
SUPERUSER_PASSWORD: "CHANGE_ME_SUPERUSER_PASSWORD"
+56
View File
@@ -0,0 +1,56 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: netbox-settings
namespace: netbox
data:
# Sync wit netbox/configuration/configuration.py (the Docker mounts that file).
configuration.py: |
import os
def _csv(name, default=""):
return [item.strip() for item in os.environ.get(name, default).split(",") if item.strip()]
ALLOWED_HOSTS = _csv("ALLOWED_HOSTS", "localhost,127.0.0.1,[::1]")
CSRF_TRUSTED_ORIGINS = _csv("CSRF_TRUSTED_ORIGINS")
USE_X_FORWARDED_HOST = True
SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")
DATABASES = {
"default": {
"NAME": os.environ["DB_NAME"],
"USER": os.environ["DB_USER"],
"PASSWORD": os.environ["DB_PASSWORD"],
"HOST": os.environ["DB_HOST"],
"PORT": os.environ.get("DB_PORT", "5432"),
"OPTIONS": {"sslmode": os.environ.get("DB_SSLMODE", "disable")},
"CONN_MAX_AGE": int(os.environ.get("DB_CONN_MAX_AGE", "300")),
}
}
REDIS = {
"tasks": {
"HOST": os.environ["REDIS_HOST"],
"PORT": int(os.environ.get("REDIS_PORT", "6379")),
"PASSWORD": os.environ["REDIS_PASSWORD"],
"DATABASE": int(os.environ.get("REDIS_DATABASE", "0")),
"SSL": False,
},
"caching": {
"HOST": os.environ["REDIS_CACHE_HOST"],
"PORT": int(os.environ.get("REDIS_CACHE_PORT", "6379")),
"PASSWORD": os.environ["REDIS_CACHE_PASSWORD"],
"DATABASE": int(os.environ.get("REDIS_CACHE_DATABASE", "1")),
"SSL": False,
},
}
SECRET_KEY = os.environ["SECRET_KEY"]
API_TOKEN_PEPPERS = {1: os.environ["API_TOKEN_PEPPER_1"]}
TIME_ZONE = os.environ.get("TIME_ZONE", "UTC")
MEDIA_ROOT = "/opt/netbox/netbox/media"
REPORTS_ROOT = "/opt/netbox/netbox/reports"
SCRIPTS_ROOT = "/opt/netbox/netbox/scripts"
CENSUS_REPORTING_ENABLED = False
+82
View File
@@ -0,0 +1,82 @@
apiVersion: v1
kind: Service
metadata:
name: netbox-valkey
namespace: netbox
labels:
app: netbox-valkey
spec:
clusterIP: None
selector:
app: netbox-valkey
ports:
- name: valkey
port: 6379
targetPort: valkey
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: netbox-valkey
namespace: netbox
labels:
app: netbox-valkey
spec:
serviceName: netbox-valkey
replicas: 1
selector:
matchLabels:
app: netbox-valkey
template:
metadata:
labels:
app: netbox-valkey
spec:
containers:
- name: valkey
image: docker.io/valkey/valkey:9.1.2-alpine
command:
- sh
- -c
- valkey-server --appendonly yes --save 30 1 --loglevel warning --requirepass "$VALKEY_PASSWORD"
env:
- name: VALKEY_PASSWORD
valueFrom:
secretKeyRef:
name: netbox-secrets
key: VALKEY_PASSWORD
ports:
- name: valkey
containerPort: 6379
volumeMounts:
- name: valkey-data
mountPath: /data
startupProbe:
exec:
command: ["sh", "-c", 'valkey-cli --pass "$VALKEY_PASSWORD" ping | grep -q PONG']
failureThreshold: 20
periodSeconds: 5
readinessProbe:
exec:
command: ["sh", "-c", 'valkey-cli --pass "$VALKEY_PASSWORD" ping | grep -q PONG']
periodSeconds: 10
livenessProbe:
exec:
command: ["sh", "-c", 'valkey-cli --pass "$VALKEY_PASSWORD" ping | grep -q PONG']
initialDelaySeconds: 20
periodSeconds: 20
resources:
requests:
cpu: "25m"
memory: "64Mi"
limits:
cpu: "250m"
memory: "256Mi"
volumeClaimTemplates:
- metadata:
name: valkey-data
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 1Gi
+1 -1
View File
@@ -1,6 +1,6 @@
services:
netronome:
image: ghcr.io/autobrr/netronome:v0.14.0
image: ghcr.io/autobrr/netronome:v0.14.1
restart: unless-stopped
container_name: netronome
ports:
+1 -1
View File
@@ -30,7 +30,7 @@ spec:
spec:
containers:
- name: netronome
image: ghcr.io/autobrr/netronome:v0.14.0
image: ghcr.io/autobrr/netronome:v0.14.1
ports:
- name: netronome-port
protocol: TCP
+2 -1
View File
@@ -1,7 +1,7 @@
# Shared PostgreSQL
This directory contains the shared PostgreSQL 17 deployment for Authentik,
Gitea, Netronome, and Statuspage. It creates one database and one login role
Gitea, NetBox, Netronome, and Statuspage. It creates one database and one login role
per service. Per-service standalone databases were removed after the
migration (Sep 2026); Penpot stays on its own compose PostgreSQL (archived,
not part of the shared instance).
@@ -12,6 +12,7 @@ not part of the shared instance).
| ---------- | ------------------- | -------------------------------------- |
| Authentik | 2025.10.x | Supported (Authentik requires 14+) |
| Gitea | 1.27.3 | Supported (Gitea requires 12+) |
| NetBox | 4.7.x | Supported (NetBox 4.x requires 13+) |
| Netronome | 0.14.0 | Supported (upstream's example uses 17) |
| Statuspage | custom | Supported |
+2
View File
@@ -3,6 +3,7 @@ set -euo pipefail
: "${AUTHENTIK_DB_PASSWORD:?AUTHENTIK_DB_PASSWORD is required}"
: "${GITEA_DB_PASSWORD:?GITEA_DB_PASSWORD is required}"
: "${NETBOX_DB_PASSWORD:?NETBOX_DB_PASSWORD is required}"
: "${NETRONOME_DB_PASSWORD:?NETRONOME_DB_PASSWORD is required}"
: "${PENPOT_DB_PASSWORD:?PENPOT_DB_PASSWORD is required}"
: "${STATUSPAGE_DB_PASSWORD:?STATUSPAGE_DB_PASSWORD is required}"
@@ -23,6 +24,7 @@ SQL
create_role_and_database authentik authentik "$AUTHENTIK_DB_PASSWORD"
create_role_and_database gitea gitea "$GITEA_DB_PASSWORD"
create_role_and_database netbox netbox "$NETBOX_DB_PASSWORD"
create_role_and_database netronome netronome "$NETRONOME_DB_PASSWORD"
create_role_and_database penpot penpot "$PENPOT_DB_PASSWORD"
create_role_and_database statuspage statuspage "$STATUSPAGE_DB_PASSWORD"
+3
View File
@@ -17,6 +17,9 @@ spec:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: gitea
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: netbox
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: netronome
+2
View File
@@ -113,6 +113,7 @@ data:
: "${AUTHENTIK_DB_PASSWORD:?AUTHENTIK_DB_PASSWORD is required}"
: "${GITEA_DB_PASSWORD:?GITEA_DB_PASSWORD is required}"
: "${NETBOX_DB_PASSWORD:?NETBOX_DB_PASSWORD is required}"
: "${NETRONOME_DB_PASSWORD:?NETRONOME_DB_PASSWORD is required}"
: "${PENPOT_DB_PASSWORD:?PENPOT_DB_PASSWORD is required}"
: "${STATUSPAGE_DB_PASSWORD:?STATUSPAGE_DB_PASSWORD is required}"
@@ -133,6 +134,7 @@ data:
create_role_and_database authentik authentik "$AUTHENTIK_DB_PASSWORD"
create_role_and_database gitea gitea "$GITEA_DB_PASSWORD"
create_role_and_database netbox netbox "$NETBOX_DB_PASSWORD"
create_role_and_database netronome netronome "$NETRONOME_DB_PASSWORD"
create_role_and_database penpot penpot "$PENPOT_DB_PASSWORD"
create_role_and_database statuspage statuspage "$STATUSPAGE_DB_PASSWORD"
+1
View File
@@ -8,6 +8,7 @@ stringData:
POSTGRES_ADMIN_PASSWORD: ""
AUTHENTIK_DB_PASSWORD: ""
GITEA_DB_PASSWORD: ""
NETBOX_DB_PASSWORD: ""
NETRONOME_DB_PASSWORD: ""
PENPOT_DB_PASSWORD: ""
STATUSPAGE_DB_PASSWORD: ""
+1 -1
View File
@@ -30,7 +30,7 @@ services:
- proxy
prometheus:
image: prom/prometheus:v3.14.0
image: prom/prometheus:v3.15.0
container_name: prometheus-prometheus
restart: unless-stopped
command:
+15
View File
@@ -69,3 +69,18 @@ alertmanager:
defaultRules:
disabled:
CPUThrottlingHigh: true
KubeControllerManagerDown: true
KubeSchedulerDown: true
KubeEtcdDown: true
KubeEtcdHighCommitDurations: true
# k0s runs controller-manager/scheduler/etcd internally, not as pods with
# component=kube-controller-manager/kube-scheduler/k8s-app=kube-etcd labels.
# Their Services get no endpoints, so the targets are permanently down.
# kube-proxy and kubelet have endpoints on k0s, keep them enabled.
kubeControllerManager:
enabled: false
kubeScheduler:
enabled: false
kubeEtcd:
enabled: false
+34
View File
@@ -0,0 +1,34 @@
services:
rackpeek:
image: docker.io/aptacode/rackpeek:v2.1.0
container_name: rackpeek
restart: unless-stopped
ports:
- "127.0.0.1:8080:8080"
environment:
TZ: "Europe/Bratislava"
volumes:
- rackpeek-config:/app/config
networks:
- proxy
labels:
- "traefik.enable=true"
- "traefik.http.services.rackpeek.loadbalancer.server.port=8080"
# Local Router
- "traefik.http.routers.rackpeek-local.rule=Host(`rackpeek.workstation.internal`) || Host(`rack.workstation.internal`) || Host(`rackpeek.gigaforust.internal`) || Host(`rack.gigaforust.internal`)"
- "traefik.http.routers.rackpeek-local.entrypoints=websecure"
- "traefik.http.routers.rackpeek-local.tls=true"
healthcheck:
test: ["CMD-SHELL", "curl -fsS http://localhost:8080/health || exit 1"]
start_period: 15s
timeout: 5s
interval: 30s
retries: 3
volumes:
rackpeek-config:
networks:
proxy:
external: true
View File
Whitespace-only changes.
+15
View File
@@ -0,0 +1,15 @@
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: internal-wildcard-tls
namespace: rackpeek
spec:
secretName: internal-wildcard-tls
dnsNames:
- "*.workstation.internal"
- "*.gigaforust.internal"
- workstation.internal
- gigaforust.internal
issuerRef:
name: internal-ca
kind: ClusterIssuer
+16
View File
@@ -0,0 +1,16 @@
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: rackpeek-local
namespace: rackpeek
spec:
entryPoints:
- websecure
routes:
- match: Host(`rackpeek.workstation.internal`) || Host(`rack.workstation.internal`) || Host(`rackpeek.gigaforust.internal`) || Host(`rack.gigaforust.internal`)
kind: Rule
services:
- name: rackpeek-service
port: 8080
tls:
secretName: internal-wildcard-tls
+4
View File
@@ -0,0 +1,4 @@
apiVersion: v1
kind: Namespace
metadata:
name: rackpeek
+89
View File
@@ -0,0 +1,89 @@
apiVersion: v1
kind: Service
metadata:
name: rackpeek-service
namespace: rackpeek
spec:
selector:
app: rackpeek
ports:
- name: http
port: 8080
targetPort: http
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: rackpeek-deployment
namespace: rackpeek
labels:
app: rackpeek
spec:
replicas: 1
selector:
matchLabels:
app: rackpeek
strategy:
type: Recreate
template:
metadata:
labels:
app: rackpeek
spec:
securityContext:
# Image runs as uid/gid 1654
fsGroup: 1654
containers:
- name: rackpeek
image: docker.io/aptacode/rackpeek:v2.1.0
ports:
- name: http
containerPort: 8080
env:
- name: RPK_YAML_DIR
value: "/app/config"
- name: TZ
value: "Europe/Bratislava"
volumeMounts:
- name: rackpeek-config
mountPath: /app/config
startupProbe:
httpGet:
path: /health
port: http
failureThreshold: 30
periodSeconds: 5
readinessProbe:
httpGet:
path: /health
port: http
periodSeconds: 10
livenessProbe:
httpGet:
path: /health
port: http
initialDelaySeconds: 20
periodSeconds: 30
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "500m"
volumes:
- name: rackpeek-config
persistentVolumeClaim:
claimName: rackpeek-pvc
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: rackpeek-pvc
namespace: rackpeek
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: local-path-retain
resources:
requests:
storage: 2Gi
+1 -1
View File
@@ -16,7 +16,7 @@ spec:
restartPolicy: Never
containers:
- name: renovate
image: renovate/renovate:44.106.0
image: renovate/renovate:44.115.10
env:
- name: RENOVATE_PLATFORM
value: gitea
+1 -1
View File
@@ -3,7 +3,7 @@
services:
core:
container_name: searxng-core
image: docker.io/searxng/searxng:${SEARXNG_VERSION:-2026.09.13-d4ce87c23}
image: docker.io/searxng/searxng:${SEARXNG_VERSION:-2026.9.25-12f8b6515}
restart: unless-stopped
# ports:
# - ${SEARXNG_PORT:-8080}
+1 -1
View File
@@ -27,7 +27,7 @@ spec:
spec:
containers:
- name: searxng
image: docker.io/searxng/searxng:2026.09.13-d4ce87c23
image: docker.io/searxng/searxng:2026.9.25-12f8b6515
envFrom:
- configMapRef:
name: searxng-config