39 Commits

Author SHA1 Message Date
cjones 67eb815b98 First attempt at diarization (with custom Dockerfile extension). 2026-07-19 12:09:28 -04:00
cjones b0bb5782b9 preparing to build custom image. Remove obsolete environment file 2026-07-18 16:53:26 -04:00
cjones 8631fa42b3 Tuning changes to command inside the container. 2026-07-18 16:12:52 -04:00
cjones 29ce85ce0c Change to OpenVINO backend 2026-07-16 21:54:24 -04:00
cjones 543af6f9ba Original version of WhisperLive compose.yaml & whisper-live.env 2026-07-07 15:51:04 -04:00
cjones b75e6bb2ab Removing obsolete local directories (since replaced by ZFS datasets). 2026-04-20 17:25:32 -04:00
cjones f0832b9dd7 Complete version-by-version upgrade of Immich from v2.3.1 to v2.7.5. 2026-04-18 23:45:17 -04:00
cjones e1804d38b6 upgrade immich to v2.4.0 2026-04-18 19:13:37 -04:00
cjones e785743580 Upgrade Nextcloud to v33 Nextcloud Hub 26 Winter 2026-04-18 17:44:08 -04:00
cjones 42d9e628b7 reset GCM token 2026-04-17 12:38:36 -04:00
cjones 9cf54273e5 testing git credential configuration 2026-04-16 23:05:50 -04:00
cjones c5df925cb5 added a dot to test GCM 2026-04-16 22:05:46 -04:00
cjones e0d80dba34 Merge branch 'ZFSMigrate': Migrate Nextcloud to per-service ZFS datasets. 2026-04-01 10:07:26 -04:00
cjones 5390ef62e9 Migrate Nextcloud to per-service ZFS datasets 2026-04-01 10:06:39 -04:00
cjones 39c9221d00 Merge branch 'ZFSMigrate': Migrate immich to per-service ZFS datasets 2026-03-31 11:25:27 -04:00
cjones a1c2266436 Migrate immich to per-service ZFS datasets 2026-03-31 11:24:49 -04:00
cjones 3e02ee89b9 Merge branch 'ZFSMigrate': migrate Jellyfin to per-service ZFS datasets 2026-03-30 21:58:49 -04:00
cjones 315c4cd61e Add JELLYFIN_PublishedServerUrl in an attempt to fix Jellyfin failing to resolve in client browsers 2026-03-30 21:57:41 -04:00
cjones 9abd0aa20e Migrate jellyfin to per-service ZFS datasets 2026-03-29 12:16:17 -04:00
cjones ad1c1912aa Merge gitea migration from branch 'ZFSMigrate' 2026-03-28 12:40:15 -04:00
cjones 0b60f122b9 Migrate gitea to per-service ZFS datasets 2026-03-28 12:39:26 -04:00
cjones 787847292b Remove unneeded no-new-privileges option. Remove unused proxy network. 2026-03-28 00:29:38 -04:00
cjones 102f9d2b33 update compose yaml to move to latest portainer 2026-03-28 00:21:42 -04:00
cjones 12486de442 Migrating portainer to per-service ZFS datasets 2026-03-27 10:47:55 -04:00
cjones f398779055 Change to bind mounts mapped to per-microservice ZFS datasets 2026-03-27 10:46:57 -04:00
cjones 05b8eaf353 Merge branch 'ZFSMigrate' after Vaultwarden successfully migrated to per-service ZFS datasets 2026-03-27 10:01:02 -04:00
cjones 8126c9a101 Change to bind mounts mapped to per-microservice ZFS datasets 2026-03-27 10:00:23 -04:00
cjones 27c1e01476 Archiving bookstack 2026-03-24 23:32:40 -04:00
cjones 7eac2b12f8 'compose.hubonly' and 'compose.full' were needed only on initial install of Beszel and its agent. Removing them. 2026-03-24 10:53:54 -04:00
cjones 9cb9fa628b Update bind mounts to point to /var/lib/beszel 2026-03-24 10:45:46 -04:00
cjones e9e5a1fec2 correcting git copy of vaultwarden compose.yaml to match production 2026-03-23 23:09:29 -04:00
cjones 6235dea03a Abandoning Prometheus (for now) 2026-03-23 22:19:56 -04:00
cjones 8d0d65ccc3 adding .gitignore for beszel data directories 2026-03-23 13:33:00 -04:00
cjones 64da99bc92 Change to bind mounts mapped to per-microservice ZFS datasets 2026-03-23 13:23:36 -04:00
cjones 355c456327 compose.yaml WIP 2026-03-22 22:52:20 -04:00
cjones f1a5b8afe9 fix Alloy configuration after 'help' from Claude 2026-03-22 10:05:41 -04:00
cjones 22efffdbe7 fix alloy configuration 2026-03-20 14:51:42 -04:00
cjones 676e159e34 Adding AI-generated compose/config files for alloy/loki/grafana stack 2026-03-19 21:51:38 -04:00
cjones 203c8a15ba Adding compose.yaml and related files for Beszel 2026-03-19 21:46:54 -04:00
17 changed files with 287 additions and 143 deletions
+1 -1
View File
@@ -1,3 +1,3 @@
# containers # containers
compose.yaml and other configuration data for Docker containers compose.yaml and other configuration data for Docker containers.
+3
View File
@@ -0,0 +1,3 @@
/beszel_agent_data/
/beszel_data/
+27
View File
@@ -0,0 +1,27 @@
services:
beszel:
image: henrygd/beszel:latest
container_name: beszel
restart: unless-stopped
environment:
APP_URL: http://localhost:8090
ports:
- 8090:8090
volumes:
- /var/lib/beszel/beszel_data:/beszel_data
- /var/lib/beszel/beszel_socket:/beszel_socket
beszel-agent:
image: henrygd/beszel-agent:latest
container_name: beszel-agent
restart: unless-stopped
network_mode: host
volumes:
- /var/lib/beszel/beszel_agent_data:/var/lib/beszel-agent
- /var/lib/beszel/beszel_socket:/beszel_socket
- /var/run/docker.sock:/var/run/docker.sock:ro
environment:
LISTEN: /beszel_socket/beszel.sock
HUB_URL: http://localhost:8090
TOKEN: da52524a-fa93-47ef-908c-dd001c9e8e18
KEY: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFgDayLLA8JOzQ7fZtqTlUaRIQvhtoYSZvkUC9PrdQJG"
+2 -2
View File
@@ -18,7 +18,7 @@ services:
networks: networks:
- gitea - gitea
volumes: volumes:
- /mnt/storage/appdata/gitea/data:/data - /var/lib/gitea/data:/data
- /etc/timezone:/etc/timezone:ro - /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro - /etc/localtime:/etc/localtime:ro
ports: ports:
@@ -38,6 +38,6 @@ services:
networks: networks:
- gitea - gitea
volumes: volumes:
- /mnt/storage/appdata/gitea/mysql:/var/lib/mysql - /var/lib/gitea/db:/var/lib/mysql
+4 -3
View File
@@ -1,15 +1,16 @@
# You can find documentation for all the supported env variables at https://immich.app/docs/install/environment-variables # You can find documentation for all the supported env variables at https://immich.app/docs/install/environment-variables
# The location where your uploaded files are stored # The location where your uploaded files are stored
UPLOAD_LOCATION=/mnt/storage/appdata/immich/library UPLOAD_LOCATION=/var/lib/immich/data
# The location where your database files are stored # The location where your database files are stored
DB_DATA_LOCATION=/mnt/storage/appdata/immich/postgres DB_DATA_LOCATION=/var/lib/immich/db
# To set a timezone, uncomment the next line and change Etc/UTC to a TZ identifier from this list: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones#List # To set a timezone, uncomment the next line and change Etc/UTC to a TZ identifier from this list: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones#List
TZ=America/New_York TZ=America/New_York
# The Immich version to use. You can pin this to a specific version like "v1.71.0" # The Immich version to use. You can pin this to a specific version like "v1.71.0"
IMMICH_VERSION=v2.3.1 IMMICH_VERSION=v2.7.5
# Connection secret for postgres. You should change it to a random password # Connection secret for postgres. You should change it to a random password
DB_PASSWORD=postgres DB_PASSWORD=postgres
+6 -6
View File
@@ -4,18 +4,18 @@ services:
container_name: jellyfin container_name: jellyfin
network_mode: 'host' network_mode: 'host'
volumes: volumes:
- /mnt/storage/appdata/jellyfin/config:/config - /etc/jellyfin:/config
- /mnt/storage/appdata/jellyfin/config/web-config.json:/jellyfin/jellyfin-web/config.json # - /etc/jellyfin/web-config.json:/jellyfin/jellyfin-web/config.json
- /mnt/storage/appdata/jellyfin/cache:/cache - /var/lib/jellyfin/cache:/cache
- /mnt/cygnus:/cygnus:ro - /mnt/cygnus:/cygnus:ro
- type: bind - type: bind
source: /mnt/storage/appdata/jellyfin/media source: /var/lib/jellyfin/media
target: /media target: /media
read_only: true read_only: true
restart: 'unless-stopped' restart: 'unless-stopped'
# Optional - alternative address used for autodiscovery # Optional - alternative address used for autodiscovery
# environment: environment:
# - JELLYFIN_PublishedServerUrl=http://example.com - JELLYFIN_PublishedServerUrl=http://127.0.0.1:8096
# Optional - may be necessary for docker healthcheck to pass if running in host network mode # Optional - may be necessary for docker healthcheck to pass if running in host network mode
# extra_hosts: # extra_hosts:
# - 'host.docker.internal:host-gateway' # - 'host.docker.internal:host-gateway'
+121
View File
@@ -0,0 +1,121 @@
# Homelab Log Aggregation Stack
Grafana Alloy + Loki + Grafana, configured for:
- **MikroTik RB5009** (and other network devices) via syslog
- **Docker container logs** on the host machine
## Quick Start
```bash
# (Optional) load secrets first if using the Vaultwarden secrets workflow
# ./secrets-load.sh docker/loki-stack .env
docker compose up -d
```
Grafana will be available at **http://\<host-ip\>:3098**
Default login: `admin` / `admin` — you will be prompted to change this.
---
## MikroTik RB5009 Configuration
In RouterOS (Winbox or SSH), run:
```routeros
# Create a remote logging action pointing at this Docker host
/system logging action
add name=remote-loki \
target=remote \
remote=<YOUR-DOCKER-HOST-IP> \
remote-port=514 \
bsd-syslog=yes \
syslog-facility=local0 \
syslog-severity=auto
# Send all log topics to Loki
/system logging
add action=remote-loki topics=all
```
To verify it's working, SSH into the RB5009 and run:
```routeros
/log print follow
```
...then in Grafana, open Explore → Loki and query `{source="network"}`.
You should see entries appearing within a few seconds.
---
## Useful LogQL Queries
**All RB5009 logs:**
```logql
{job="syslog", source="network"}
```
**RB5009 interface/link events only:**
```logql
{job="syslog", source="network"} |= "link"
```
**All logs from a specific Docker container:**
```logql
{job="docker", container="myapp"}
```
**Errors across all Docker containers:**
```logql
{job="docker"} |= "error" | logfmt | level="error"
```
**Everything in the last 24 hours, newest first:**
```logql
{job=~"syslog|docker"} | line_format "{{.source}} {{.container}} {{.message}}"
```
---
## File Layout
```
loki-stack/
├── docker-compose.yml
├── alloy/
│ └── config.alloy # Alloy pipeline config (syslog + Docker)
├── loki/
│ └── loki-config.yml # Loki storage and retention config
└── grafana/
└── provisioning/
└── datasources/
└── loki.yml # Auto-provisions Loki as default datasource
```
## Retention
Logs are kept for **90 days** by default. To change this, edit `loki/loki-config.yml`:
```yaml
limits_config:
retention_period: 30d # or 180d, etc.
```
Then restart Loki: `docker compose restart loki`
## Adding More Syslog Sources
Any device that can send syslog (UDP/TCP 514) will work automatically —
the `host` label will be set from the syslog hostname field, so you can
filter per-device in Grafana with `{host="my-device-hostname"}`.
---
## Integrating with the Vaultwarden Secrets Workflow
If you're using the `secrets-load.sh` script, store the Grafana admin
password as a custom field named `GF_SECURITY_ADMIN_PASSWORD` in a
Vaultwarden item called `docker/loki-stack`, then replace the hardcoded
value in `docker-compose.yml` with:
```yaml
env_file:
- .env
```
+69
View File
@@ -0,0 +1,69 @@
---
# Loki + Alloy + Grafana log aggregation stack
# Place this file in a directory e.g. ~/docker/loki-stack/
# Run with: docker compose up -d
networks:
logging:
driver: bridge
services:
# ── Loki: log storage and query engine ──────────────────────────────────────
loki:
image: grafana/loki:3.4.2
container_name: loki
restart: unless-stopped
networks:
- logging
ports:
- "3100:3100" # Loki HTTP API (Alloy pushes here; Grafana queries here)
volumes:
- /var/lib/loki:/loki
- /etc/loki:/etc/loki:ro
command: -config.file=/etc/loki/loki.yml
healthcheck:
test: ["CMD-SHELL", "wget -q --spider http://localhost:3100/ready || exit 1"]
interval: 30s
timeout: 5s
retries: 5
# ── Alloy: log collector / syslog receiver ───────────────────────────────────
alloy:
image: grafana/alloy:v1.7.5
container_name: alloy
restart: unless-stopped
networks:
- logging
ports:
- "5140:5140/udp" # Syslog UDP (for MikroTik and other network devices)
- "5140:5140/tcp" # Syslog TCP
- "12345:12345" # Alloy UI (optional, useful for debugging)
volumes:
- /etc/alloy/alloy.alloy:/etc/alloy/config.alloy:ro
- /var/lib/docker/containers:/var/lib/docker/containers:ro # Docker log access
- /var/run/docker.sock:/var/run/docker.sock:ro # Docker metadata
command: run /etc/alloy/config.alloy --server.http.listen-addr=0.0.0.0:12345
depends_on:
loki:
condition: service_healthy
# ── Grafana: log query UI ────────────────────────────────────────────────────
grafana:
image: grafana/grafana:11.5.2
container_name: grafana
restart: unless-stopped
networks:
- logging
ports:
- "3098:3000"
volumes:
- /var/lib/grafana:/var/lib/grafana
- /etc/grafana/grafana-datasources.yml:/etc/grafana/provisioning/datasources/loki.yml:ro
environment:
- GF_AUTH_ANONYMOUS_ENABLED=true # Remove if you want login
- GF_AUTH_ANONYMOUS_ORG_ROLE=Admin # Remove if you want login
- GF_SECURITY_ADMIN_PASSWORD=changeme # Change this
depends_on:
loki:
condition: service_healthy
+3 -3
View File
@@ -4,7 +4,7 @@ services:
restart: always restart: always
command: --transaction-isolation=READ-COMMITTED --log-bin=binlog --binlog-format=ROW command: --transaction-isolation=READ-COMMITTED --log-bin=binlog --binlog-format=ROW
volumes: volumes:
- /mnt/storage/appdata/nextcloud/mysql:/var/lib/mysql - /var/lib/nextcloud/db:/var/lib/mysql
networks: networks:
- default - default
environment: environment:
@@ -16,12 +16,12 @@ services:
app: app:
depends_on: depends_on:
- db - db
image: nextcloud:32 image: nextcloud:33
restart: always restart: always
ports: ports:
- 8080:80 - 8080:80
volumes: volumes:
- /mnt/storage/appdata/nextcloud/www/html:/var/www/html - /var/lib/nextcloud/data/www/html:/var/www/html
networks: networks:
- default - default
environment: environment:
+7 -24
View File
@@ -1,33 +1,16 @@
services: services:
portainer: portainer:
image: portainer/portainer:latest image: portainer/portainer-ce:lts
container_name: portainer container_name: portainer
restart: unless-stopped restart: unless-stopped
security_opt:
- no-new-privileges:true
networks:
- proxy
volumes: volumes:
- /etc/localtime:/etc/localtime:ro - /etc/localtime:/etc/localtime:ro
- /var/run/docker.sock:/var/run/docker.sock:ro - /var/run/docker.sock:/var/run/docker.sock
- /mnt/storage/appdata/portainer/data:/data - /var/lib/portainer:/data
ports: ports:
- 9000:9000 - 9443:9443
labels: - 8000:8000
- "traefik.enable=false"
- "traefik.http.routers.portainer.entrypoints=http"
- "traefik.http.routers.portainer.rule=Host(`portainer.objectbrokers.com`)"
- "traefik.http.middlewares.portainer-https-redirect.redirectscheme.scheme=https"
- "traefik.http.routers.portainer.middlewares=portainer-https-redirect"
- "traefik.http.routers.portainer-secure.entrypoints=https"
- "traefik.http.routers.portainer-secure.rule=Host(`portainer.objectbrokers.com`)"
- "traefik.http.routers.portainer-secure.tls=true"
- "traefik.http.routers.portainer-secure.tls.certresolver=http"
- "traefik.http.routers.portainer-secure.service=portainer"
- "traefik.http.services.portainer.loadbalancer.server.port=9000"
- "traefik.docker.network=proxy"
networks: networks:
proxy: default:
external: true name: portainer_network
-88
View File
@@ -1,88 +0,0 @@
volumes:
prometheus_data: {}
grafana_data: {}
networks:
monitoring:
driver: bridge
services:
prometheus:
image: prom/prometheus:latest
container_name: prometheus
volumes:
- ./prometheus:/etc/prometheus
- prometheus_data:/prometheus
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'
- '--web.console.libraries=/usr/share/prometheus/console_libraries'
- '--web.console.templates=/usr/share/prometheus/consoles'
- '--web.enable-lifecycle'
ports:
- "9098:9090"
networks:
- monitoring
restart: unless-stopped
node-exporter:
image: prom/node-exporter:latest
container_name: node-exporter
volumes:
- /proc:/host/proc:ro
- /sys:/host/sys:ro
- /:/rootfs:ro
command:
- '--path.procfs=/host/proc'
- '--path.sysfs=/host/sys'
- '--collector.filesystem.ignored-mount-points=^/(sys|proc|dev|host|etc)($|/)'
ports:
- "9100:9100"
networks:
- monitoring
restart: unless-stopped
cadvisor:
image: gcr.io/cadvisor/cadvisor:latest
container_name: cadvisor
volumes:
- /:/rootfs:ro
- /var/run:/var/run:rw
- /sys:/sys:ro
- /var/lib/docker/:/var/lib/docker:ro
- /dev/disk/:/dev/disk:ro
ports:
- "8080:8080"
networks:
- monitoring
restart: unless-stopped
grafana:
image: grafana/grafana:latest
container_name: grafana
volumes:
- grafana_data:/var/lib/grafana
- ./grafana/provisioning:/etc/grafana/provisioning
environment:
- GF_SECURITY_ADMIN_USER=admin
- GF_SECURITY_ADMIN_PASSWORD=admin
- GF_USERS_ALLOW_SIGN_UP=false
ports:
- "3000:3000"
networks:
- monitoring
restart: unless-stopped
alertmanager:
image: prom/alertmanager:latest
container_name: alertmanager
volumes:
- ./alertmanager:/etc/alertmanager
command:
- '--config.file=/etc/alertmanager/config.yml'
- '--storage.path=/alertmanager'
ports:
- "9093:9093"
networks:
- monitoring
restart: unless-stopped
-13
View File
@@ -1,13 +0,0 @@
global:
scrape_interval: 15s
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9098']
- job_name: 'docker'
static_configs:
- targets: ['172.17.0.1:9323']
+2 -2
View File
@@ -8,10 +8,10 @@ services:
- 8030:80 - 8030:80
environment: environment:
# - DOMAIN='https://vaultwarden.objectbrokers.com' # - DOMAIN='https://vaultwarden.objectbrokers.com'
- ADMIN_TOKEN="llanfairpwll" - ADMIN_TOKEN=mfLzuPlsXDqtIwTGSN/oZ3cgmFKWXY/zv+hO94gtqsJeHdl7+O+tJeMZrTzQNMfI
# DOMAIN: "https://vaultwarden.objectbrokers.com" # Your domain; vaultwarden needs to know it's https to work properly with attachments # DOMAIN: "https://vaultwarden.objectbrokers.com" # Your domain; vaultwarden needs to know it's https to work properly with attachments
# ADMIN_TOKEN: ADMIN_TOKEN=${VAULTWARDEN_ADMIN_TOKEN} # ADMIN_TOKEN: ADMIN_TOKEN=${VAULTWARDEN_ADMIN_TOKEN}
volumes: volumes:
- /mnt/storage/appdata/bitwarden:/data - /var/lib/vaultwarden:/data
+1
View File
@@ -0,0 +1 @@
whisper-live.env
+5
View File
@@ -0,0 +1,5 @@
FROM ghcr.io/collabora/whisperlive-openvino:latest
# Install pyannote.audio and its dependencies.
# --no-cache-dir keeps the image layer smaller.
RUN pip install --no-cache-dir pyannote.audio
+35
View File
@@ -0,0 +1,35 @@
services:
whisper-live:
image: whisper-live-diarization:latest
container_name: whisper-live
restart: unless-stopped
ports:
- "9097:9090"
volumes:
- whisper-live-data:/var/lib/whisper-live
- whisper-pyannote-cache:/root/.cache/huggingface/hub
env_file:
- whisper-live.env # contains HUGGING_FACE_HUB_TOKEN — not in git
command:
- "python3"
- "run_server.py"
- "--port"
- "9090"
- "--backend"
- "openvino"
- "--omp_num_threads"
- "4"
- "--max_clients"
- "1"
- "--max_connection_time"
- "7200"
- "--raw_pcm_input"
devices:
- /dev/dri/renderD128:/dev/dri/renderD128
- /dev/dri/card1:/dev/dri/card1
cpuset: "0-7"
mem_limit: 10g
volumes:
whisper-live-data:
whisper-pyannote-cache: