/
/
/
Ansible role that deployes services on my runner machine
1---
2# Runner Services Role Defaults
3# Multi-service container deployment with NFS integration
4
5# ==============================================================================
6# GENERAL SETTINGS
7# ==============================================================================
8runner_enabled: true
9# Legacy variables - no longer used with consolidated structure
10# runner_docker_dir: "/docker/runner" # Now each service uses /docker/[service]
11# runner_data_dir: "/docker/runner-data" # Now consolidated into each service directory
12runner_nfs_mount_dir: "/mnt/docker"
13runner_snapshot_dir: "{{ runner_nfs_mount_dir }}/frigate/snapshots"
14runner_user: "{{ ansible_user }}"
15runner_group: "users"
16runner_uid: 1000
17runner_gid: 1000
18
19# Timezone configuration
20runner_timezone: "{{ system_timezone }}"
21
22# Docker network for runner services
23runner_docker_network: "runner-network"
24runner_network_subnet: "172.20.0.0/16"
25
26# NFS Configuration
27runner_nfs_enabled: true
28runner_nas_host: "{{ vault_storage.nas_host | default('storage.home') }}"
29runner_nfs_options: "nfsvers=4.1,proto=tcp,hard,timeo=600,retrans=2,rsize=16777216,wsize=16777216,nconnect=8,noatime,_netdev"
30
31# ==============================================================================
32# NFS MOUNT CONFIGURATION
33# ==============================================================================
34runner_nfs_mounts:
35 - name: "frigate"
36 local_path: "{{ runner_nfs_mount_dir }}/frigate"
37 nfs_path: "/mnt/rstorage/cctv-data"
38 host: "{{ runner_nas_host }}"
39 options: "{{ runner_nfs_options }}"
40
41 - name: "immich"
42 local_path: "{{ runner_nfs_mount_dir }}/immich"
43 nfs_path: "/mnt/rstorage/media/pictures"
44 host: "{{ runner_nas_host }}"
45 options: "{{ runner_nfs_options }}"
46
47 - name: "forgejo"
48 local_path: "{{ runner_nfs_mount_dir }}/forgejo"
49 nfs_path: "/mnt/rstorage/code-repo"
50 host: "{{ runner_nas_host }}"
51 options: "{{ runner_nfs_options }}"
52
53 - name: "harbor"
54 local_path: "{{ runner_nfs_mount_dir }}/harbor"
55 nfs_path: "/mnt/rstorage/registry-data"
56 host: "{{ runner_nas_host }}"
57 options: "{{ runner_nfs_options }}"
58
59 - name: "cvat"
60 local_path: "{{ runner_nfs_mount_dir }}/cvat"
61 nfs_path: "/mnt/rstorage/cvat-datasets"
62 host: "{{ runner_nas_host }}"
63 options: "{{ runner_nfs_options }}"
64
65# ==============================================================================
66# SERVICE CONFIGURATIONS
67# ==============================================================================
68
69# LLM Stack - Unified Local AI Infrastructure
70llm_stack_enabled: true
71llm_stack_config_dir: "/docker/llm-stack"
72
73# Unified LLM Stack Configuration
74llm_stack_ollama_port: 9000
75llm_stack_openwebui_port: 9001
76llm_stack_litellm_port: 9002
77
78# Ollama - Local LLM Server
79llm_stack_ollama_data_dir: "{{ llm_stack_config_dir }}/ollama/data"
80# GPU configuration uses global gpu_enabled parameter
81llm_stack_ollama_default_model: "qwen3.5:9b"
82llm_stack_ollama_keep_alive: "1h"
83llm_stack_ollama_log_level: "info"
84
85# Model lineup
86llm_stack_models:
87 - name: "qwen3.5:9b"
88 role: "default"
89 description: "General-purpose daily driver"
90 - name: "phi4:14b"
91 role: "coder"
92 description: "Coding and analytical tasks"
93 - name: "qwen2.5-coder:14b"
94 role: "coder"
95 description: "Coding specialist (Qwen 2.5 generation)"
96 - name: "deepseek-r1:14b"
97 role: "reasoning"
98 description: "Complex reasoning and chain-of-thought"
99 - name: "qwen3:8b"
100 role: "fast"
101 description: "Lightweight fast tasks"
102 - name: "qwen3:4b"
103 role: "minimal"
104 description: "Quick lightweight tasks"
105
106# OpenWebUI - Web Interface for Ollama
107llm_stack_openwebui_data_dir: "{{ llm_stack_config_dir }}/openwebui/data"
108llm_stack_openwebui_name: "Local AI Assistant"
109llm_stack_openwebui_description: "Self-hosted AI chat interface"
110llm_stack_openwebui_author: "Home Assistant"
111llm_stack_openwebui_default_models: "qwen3.5:9b"
112llm_stack_openwebui_log_level: "info"
113
114# LiteLLM - Unified LLM Proxy
115llm_stack_litellm_data_dir: "{{ llm_stack_config_dir }}/litellm/data"
116llm_stack_litellm_streaming_enabled: true
117llm_stack_litellm_log_level: "info"
118
119# Frigate - AI NVR System
120frigate_enabled: true
121frigate_port: 5000
122frigate_rtmp_port: 1935
123frigate_rtsp_port: 8554
124frigate_go2rtc_port: 1984
125frigate_config_dir: "/docker/frigate"
126frigate_data_dir: "{{ runner_nfs_mount_dir }}/frigate"
127frigate_mqtt_enabled: true
128mqtt_host: "homeassistant.home"
129mqtt_port: 1883
130frigate_hardware_acceleration: "vaapi" # vaapi, nvdec, nvenc, qsv, or none
131
132# Frigate ONVIF default settings
133frigate_onvif_autotracking: false
134
135# Frigate cameras configuration (from vault)
136frigate_cameras:
137 - name: "dining-room"
138 host: "{{ vault_runner.dining_room_camera_host | default('') }}"
139 username: "{{ vault_runner.dining_room_camera_user | default('') }}"
140 password: "{{ vault_runner.dining_room_camera_pass | default('') }}"
141 path: "/stream1"
142 port: 554
143 onvif_port: 2020
144 enabled: true
145
146 - name: "living-room"
147 host: "{{ vault_runner.living_room_camera_host | default('') }}"
148 username: "{{ vault_runner.living_room_camera_user | default('') }}"
149 password: "{{ vault_runner.living_room_camera_pass | default('') }}"
150 path: "/stream1"
151 port: 554
152 onvif_port: 2020
153 enabled: true
154
155 - name: "bed-room"
156 host: "{{ vault_runner.bed_room_camera_host | default('') }}"
157 username: "{{ vault_runner.bed_room_camera_user | default('') }}"
158 password: "{{ vault_runner.bed_room_camera_pass | default('') }}"
159 path: "/stream1"
160 port: 554
161 onvif_port: 2020
162 enabled: true
163
164 - name: "alina-office"
165 host: "{{ vault_runner.alina_office_camera_host | default('') }}"
166 username: "{{ vault_runner.alina_office_camera_user | default('') }}"
167 password: "{{ vault_runner.alina_office_camera_pass | default('') }}"
168 path: "/stream1"
169 port: 554
170 onvif_port: 2020
171 enabled: true
172
173 - name: "street-cam"
174 host: "{{ vault_runner.street_cam_host | default('') }}"
175 username: "{{ vault_runner.street_cam_user | default('') }}"
176 password: "{{ vault_runner.street_cam_pass | default('') }}"
177 path: "/stream1"
178 port: 554
179 onvif_port: 2020
180 enabled: true
181
182 - name: "pi-cam"
183 host: "{{ vault_runner.pi_cam_host | default('') }}"
184 username: "{{ vault_runner.pi_cam_user | default('') }}"
185 password: "{{ vault_runner.pi_cam_pass | default('') }}"
186 path: "{{ vault_runner.pi_cam_path | default('/doorbell') }}"
187 port: 8554
188 enabled: true
189
190# Cameras with ONVIF support (for PTZ control)
191frigate_onvif_cameras:
192 - name: "dining-room"
193 host: "{{ vault_runner.dining_room_camera_host | default('') }}"
194 port: 2020
195 username: "{{ vault_runner.dining_room_camera_user | default('') }}"
196 password: "{{ vault_runner.dining_room_camera_pass | default('') }}"
197 - name: "living-room"
198 host: "{{ vault_runner.living_room_camera_host | default('') }}"
199 port: 2020
200 username: "{{ vault_runner.living_room_camera_user | default('') }}"
201 password: "{{ vault_runner.living_room_camera_pass | default('') }}"
202 - name: "bed-room"
203 host: "{{ vault_runner.bed_room_camera_host | default('') }}"
204 port: 2020
205 username: "{{ vault_runner.bed_room_camera_user | default('') }}"
206 password: "{{ vault_runner.bed_room_camera_pass | default('') }}"
207 - name: "alina-office"
208 host: "{{ vault_runner.alina_office_camera_host | default('') }}"
209 port: 2020
210 username: "{{ vault_runner.alina_office_camera_user | default('') }}"
211 password: "{{ vault_runner.alina_office_camera_pass | default('') }}"
212 - name: "street-cam"
213 host: "{{ vault_runner.street_cam_host | default('') }}"
214 port: 2020
215 username: "{{ vault_runner.street_cam_user | default('') }}"
216 password: "{{ vault_runner.street_cam_pass | default('') }}"
217
218# Cameras for snapshot capture
219frigate_snapshot_cameras:
220 - "living-room"
221 - "dining-room"
222 - "bed-room"
223 - "alina-office"
224 - "street-cam"
225 - "pi-cam"
226
227# Per-camera record override (cameras listed here have recording disabled)
228frigate_cameras_record_disabled:
229 - "bed-room"
230
231# Frigate profile system (home=record-only, away=full detection)
232frigate_profiles:
233 home:
234 detect_enabled: false
235 detectors_enabled: false
236 cameras:
237 - street-cam
238 - pi-cam
239 hwaccel_override_cameras:
240 - street-cam
241 - pi-cam
242 default_profile: false
243 away:
244 detect_enabled: true
245 detectors_enabled: true
246 cameras:
247 - living-room
248 - dining-room
249 - bed-room
250 - alina-office
251 - street-cam
252 - pi-cam
253 default_profile: true
254
255# Frigate manager service
256frigate_manager_enabled: true
257frigate_snapshot_interval_minutes: 30
258frigate_profile_switch_timeout: 120
259
260# Immich - Photo Management
261immich_enabled: true
262immich_server_port: 2283
263immich_ml_port: 3003
264immich_config_dir: "/docker/immich"
265immich_data_dir: "/docker/immich"
266immich_upload_dir: "{{ runner_nfs_mount_dir }}/immich/library"
267immich_db_name: "{{ vault_runner.postgres_db | default('') }}"
268immich_db_user: "{{ vault_runner.postgres_user | default('') }}"
269immich_redis_enabled: true
270immich_ml_enabled: true
271immich_facial_recognition: true
272immich_hardware_acceleration: "none" # none, vaapi, nvdec, nvenc, or qsv
273
274# External library mounts (read-only photo libraries from NFS)
275immich_external_libraries:
276 - name: "yannick"
277 host_path: "{{ runner_nfs_mount_dir }}/immich/yannick"
278 container_path: "/yannick"
279 - name: "alina"
280 host_path: "{{ runner_nfs_mount_dir }}/immich/alina"
281 container_path: "/alina"
282
283# Forgejo - Git Server
284forgejo_enabled: true
285forgejo_http_port: 3010
286forgejo_ssh_port: 2222
287forgejo_config_dir: "/docker/forgejo"
288forgejo_data_dir: "{{ runner_nfs_mount_dir }}/forgejo"
289forgejo_db_type: "sqlite3"
290forgejo_app_name: "Forgejo Git Service"
291forgejo_domain: "forgejo.home"
292forgejo_ssh_domain: "{{ ansible_default_ipv4.address }}"
293
294# Forgejo Runner Configuration
295forgejo_runner_enabled: true
296forgejo_runner_token: "{{ vault_runner.forgejo_runner_token | default('changeme') }}"
297forgejo_runner_name: "default-runner"
298forgejo_runner_capacity: 2
299forgejo_runner_loglevel: info
300forgejo_runner_base_image: ubuntu:22.04
301forgejo_runner_user: runner
302forgejo_runner_uid: 1000
303forgejo_runner_version: 9.1.1
304
305# Forgejo Ansible Runner (for running Ansible playbooks in CI)
306forgejo_ansible_runner_enabled: true
307forgejo_ansible_runner_token: "{{ vault_runner.forgejo_ansible_runner_token | default('changeme') }}"
308forgejo_ansible_runner_name: "ansible-runner"
309forgejo_ansible_runner_capacity: 1
310forgejo_ansible_runner_version: 9.1.1
311
312# Web Tools - PDF Processing, File Conversion, Data Analysis, Developer Utilities
313web_tools_enabled: true
314web_tools_config_dir: "/docker/web-tools"
315web_tools_data_dir: "/docker/web-tools"
316
317# Stirling-PDF
318web_tools_stirling_port: 8090
319web_tools_stirling_max_file_size: 100
320
321# ConvertX
322web_tools_convertx_port: 8091
323web_tools_convertx_jwt_secret: "{{ vault_runner.web_tools_convertx_jwt_secret | default('changeme-generate-a-real-secret') }}"
324web_tools_convertx_auto_delete_hours: 24
325
326# CyberChef
327web_tools_cyberchef_port: 8092
328
329# IT-Tools
330web_tools_it_tools_port: 8093
331
332# Tandoor - Recipe Manager
333tandoor_enabled: true
334tandoor_port: 8010
335tandoor_config_dir: "/docker/tandoor"
336tandoor_data_dir: "/docker/tandoor"
337tandoor_media_dir: "{{ tandoor_data_dir }}/media"
338tandoor_static_dir: "{{ tandoor_data_dir }}/static"
339tandoor_db_engine: "django.db.backends.postgresql"
340
341# Ghost CMS - Headless CMS
342ghost_enabled: true
343ghost_port: 2368
344ghost_config_dir: "/docker/ghost"
345ghost_data_dir: "/docker/ghost"
346ghost_content_dir: "{{ ghost_data_dir }}/content"
347ghost_db_client: "mysql"
348ghost_db_host: "ghost-mysql"
349ghost_db_name: "ghost"
350ghost_db_user: "ghost"
351ghost_url: "http://ghost.home"
352
353# ==============================================================================
354# LIVEKIT - WebRTC Conferencing (SFU) + Meet frontend
355# ==============================================================================
356# LiveKit is a WebRTC SFU. Unlike the other runner services it runs on
357# network_mode: host because Docker's userland proxy rewrites UDP source
358# addresses, which breaks ICE candidate resolution and silently kills media.
359livekit_enabled: true
360livekit_config_dir: "/docker/livekit"
361livekit_data_dir: "{{ livekit_config_dir }}/data"
362
363# Signaling / API (HTTP + WebSocket)
364livekit_port: 7880
365# WebRTC over TCP (ICE/TCP fallback for restrictive networks)
366livekit_tcp_port: 7881
367# WebRTC over UDP - single-port mux, avoids the 50000-60000 range entirely
368livekit_udp_port: 7882
369# Meet frontend (bridge network, normal published port)
370livekit_meet_port: 7883
371
372# Public hostnames handed to browser clients. When fronted by a reverse proxy
373# these are the proxy's names; otherwise they resolve straight to this host.
374livekit_domain: "livekit.home"
375livekit_sfu_domain: "{{ livekit_domain }}"
376
377# Set true when a reverse proxy terminates TLS in front of both hostnames.
378# Browsers require a secure context for getUserMedia, and a page served over
379# HTTPS may not open a ws:// socket, so this must be on for any non-localhost
380# browser access.
381livekit_tls_enabled: false
382
383# Behind a proxy the public URLs carry no port (443 is implied). Direct access
384# needs the explicit container ports.
385livekit_public_url: >-
386 {{ 'https://' ~ livekit_domain
387 if livekit_tls_enabled
388 else 'http://' ~ livekit_domain ~ ':' ~ livekit_meet_port }}
389livekit_public_ws_url: >-
390 {{ 'wss://' ~ livekit_sfu_domain
391 if livekit_tls_enabled
392 else 'ws://' ~ livekit_sfu_domain ~ ':' ~ livekit_port }}
393
394# API credentials (from vault). Generate with:
395# docker run --rm livekit/livekit-server generate-keys
396livekit_api_key: "{{ vault_runner.livekit_api_key | default('') }}"
397livekit_api_secret: "{{ vault_runner.livekit_api_secret | default('') }}"
398
399livekit_log_level: "info"
400
401# Room behaviour
402livekit_room_auto_create: true
403livekit_room_empty_timeout: 300 # seconds before an empty room closes
404livekit_room_departure_timeout: 20
405
406# Meet frontend build. Upstream publishes no release tags, so this is pinned to
407# a specific commit SHA rather than tracking the main branch. Bump deliberately.
408livekit_meet_repo_url: "https://github.com/livekit-examples/meet.git"
409livekit_meet_repo_version: "665e1cb7841ab872de0d8e5c310744009a763b08"
410# Matches the packageManager field in Meet's package.json
411livekit_meet_pnpm_version: "10.18.2"
412livekit_meet_node_version: "20-alpine"
413
414# Resource limits
415livekit_memory_limit: "2g"
416livekit_cpu_limit: "2"
417livekit_meet_memory_limit: "1g"
418livekit_meet_cpu_limit: "1"
419
420cvat_config_dir: "/docker/cvat"
421# CVAT - Data labeling
422cvat_enabled: true
423
424cvat_repo_url: "https://github.com/cvat-ai/cvat.git"
425cvat_repo_version: "{{ cvat_image_tag }}"
426
427cvat_admin_username: admin
428cvat_admin_password: "{{ vault_runner.cvat_admin_password | default('change-me') }}"
429cvat_admin_email: "{{ vault_runner.cvat_admin_email | default('change-me') }}"
430
431# Networking / access
432cvat_domain: "cvat.home" # used by Traefik routing in CVAT compose
433cvat_http_port: 8990 # Traefik "web" entrypoint in the default compose
434cvat_https_enabled: false # add CVAT's https overlay when true
435
436cvat_share_dir: >-
437 {{ (runner_nfs_mounts
438 | selectattr('name','equalto','cvat')
439 | map(attribute='local_path')
440 | first)
441 | default(runner_nfs_mount_dir ~ '/cvat', true) }}
442
443# Versioning / images
444cvat_image_tag: "v2.44.3" # pulled via CVAT_VERSION; align with the git tag you run
445
446# Optional: serverless auto-annotation overlay (Nuclio/SAM/YOLO assist in CVAT)
447cvat_serverless_enabled: false
448
449# Optional: use an external Postgres instead of the bundled one
450cvat_external_db_enabled: false
451cvat_db_host: "postgres.internal"
452cvat_db_port: 5432
453cvat_db_name: "cvat"
454cvat_db_user: "cvat_user"
455cvat_db_password: "{{ vault_runner.cvat_db_password | default('change-me') }}"
456
457# Optional: expose Traefik dashboard (binds host port below)
458cvat_traefik_dashboard_enabled: false
459cvat_dashboard_port: 8899
460
461# Optional: GPU reservation for CVAT server container (you must have host GPU runtime ready)
462cvat_gpu_enabled: false
463cvat_gpu_driver: "nvidia"
464cvat_gpu_count: "all" # or a number like "1"
465
466# ==============================================================================
467# DATABASE CONFIGURATIONS
468# ==============================================================================
469
470# PostgreSQL (Immich)
471postgres_enabled: "{{ immich_enabled }}"
472postgres_config_dir: "/docker/immich/postgres"
473postgres_db: "{{ vault_runner.postgres_db | default('') }}"
474postgres_user: "{{ vault_runner.postgres_user | default('') }}"
475postgres_version: "14"
476
477# Redis (Immich)
478redis_enabled: "{{ immich_redis_enabled }}"
479redis_config_dir: "/docker/immich/redis"
480redis_port: 6379
481
482# MySQL (Ghost CMS)
483mysql_enabled: "{{ ghost_enabled }}"
484mysql_config_dir: "/docker/ghost/mysql"
485mysql_db: "{{ ghost_db_name }}"
486mysql_user: "{{ ghost_db_user }}"
487mysql_version: "8.0"
488
489# ==============================================================================
490# SECURITY SETTINGS (FROM VAULT)
491# ==============================================================================
492
493# Database passwords
494postgres_password: "{{ vault_runner.postgres_password | default('') }}"
495mysql_password: "{{ vault_runner.mysql_password | default('') }}"
496mysql_root_password: "{{ vault_runner.mysql_root_password | default('') }}"
497
498# Service secrets
499immich_jwt_secret: "{{ vault_runner.immich_jwt_secret | default('') }}"
500ghost_database_password: "{{ vault_runner.ghost_database_password | default('') }}"
501tandoor_secret_key: "{{ vault_runner.tandoor_secret_key | default('') }}"
502
503# MQTT credentials (from vault - top-level, shared across all roles)
504mqtt_username: ""
505mqtt_password: ""
506
507# ==============================================================================
508# DIRECTORY STRUCTURE
509# ==============================================================================
510
511# Local configuration directories
512runner_config_directories:
513 - "{{ llm_stack_config_dir }}"
514 - "{{ llm_stack_ollama_data_dir }}"
515 - "{{ llm_stack_openwebui_data_dir }}"
516 - "{{ llm_stack_litellm_data_dir }}"
517 - "{{ frigate_config_dir }}"
518 - "{{ immich_config_dir }}"
519 - "{{ immich_config_dir }}/postgres"
520 - "{{ immich_config_dir }}/redis"
521 - "{{ immich_config_dir }}/library"
522 - "{{ immich_config_dir }}/cache"
523 - "{{ immich_config_dir }}/model-cache"
524 - "{{ immich_config_dir }}/postgres-init"
525 - "{{ forgejo_config_dir }}"
526 - "{{ forgejo_config_dir }}/forgejo-runner-data"
527 - "{{ forgejo_config_dir }}/forgejo-ansible-runner-data"
528 - "{{ web_tools_config_dir }}"
529 - "{{ tandoor_config_dir }}"
530 - "{{ tandoor_data_dir }}/db"
531 - "{{ tandoor_data_dir }}/media"
532 - "{{ tandoor_data_dir }}/static"
533 - "{{ ghost_config_dir }}/config"
534 - "{{ ghost_config_dir }}/content"
535 - "{{ ghost_config_dir }}/mysql"
536
537# NFS mount directories
538runner_nfs_directories:
539 - "{{ runner_nfs_mount_dir }}"
540 - "{{ runner_nfs_mount_dir }}/frigate"
541 - "{{ runner_nfs_mount_dir }}/immich"
542 - "{{ runner_nfs_mount_dir }}/forgejo"
543 - "{{ runner_nfs_mount_dir }}/harbor"
544 - "{{ runner_nfs_mount_dir }}/cvat"
545
546# ==============================================================================
547# PERFORMANCE SETTINGS
548# ==============================================================================
549
550# Network performance tuning for NFS
551runner_performance_tuning_enabled: true
552runner_sysctl_settings:
553 # Extreme performance network buffers for Ryzen 7 + 32GB RAM
554 net.core.rmem_max: 268435456 # 256MB socket receive buffer
555 net.core.wmem_max: 268435456 # 256MB socket send buffer
556 net.core.rmem_default: 33554432 # 32MB default receive buffer
557 net.core.wmem_default: 33554432 # 32MB default send buffer
558 net.ipv4.tcp_rmem: "4096 131072 268435456" # TCP receive: 4KB min, 128KB default, 256MB max
559 net.ipv4.tcp_wmem: "4096 131072 268435456" # TCP send: 4KB min, 128KB default, 256MB max
560 net.core.netdev_max_backlog: 30000 # Handle high connection burst (32 connections)
561 net.ipv4.tcp_congestion_control: "bbr" # BBR congestion control
562 net.ipv4.tcp_window_scaling: 1 # Enable TCP window scaling
563 net.ipv4.tcp_timestamps: 1 # Enable TCP timestamps for RTT calculation
564 net.ipv4.tcp_sack: 1 # Enable selective acknowledgments
565 # NFS client cache tuning for 32GB RAM
566 vm.dirty_background_ratio: 3 # Start writeback at 3% (more aggressive)
567 vm.dirty_ratio: 8 # Force writeback at 8% (more aggressive)
568 vm.vfs_cache_pressure: 25 # Keep even more file cache (25% vs 50%)
569 vm.min_free_kbytes: 131072 # Keep 128MB free for network buffers
570
571# Harbor Configuration (external deployment)
572harbor_enabled: true
573harbor_config_dir: "/docker/harbor"
574harbor_version: "2.13.2"
575harbor_hostname: "{{ vault_runner.harbor_hostname | default('registry.local') }}"
576harbor_http_port: 8080
577harbor_registry_port: 5000
578harbor_admin_password: "{{ vault_runner.harbor_admin_password | default('changeme') }}"
579harbor_db_password: "{{ vault_runner.harbor_db_password | default('changeme') }}"
580harbor_data_volume: "{{ runner_nfs_mount_dir }}/harbor"
581
582# Docker resource limits
583default_memory_limit: "1g"
584default_cpu_limit: "1"
585
586# Health check configuration
587health_check_interval: "30s"
588health_check_timeout: "30s"
589health_check_retries: 5
590health_check_start_period: "60s"
591
592# ==============================================================================
593# SERVICE HEALTH ENDPOINTS
594# ==============================================================================
595service_endpoints:
596 ollama: "http://localhost:{{ llm_stack_ollama_port }}/api/tags"
597 openwebui: "http://localhost:{{ llm_stack_openwebui_port }}/api/health"
598 litellm: "http://localhost:{{ llm_stack_litellm_port }}/"
599 frigate: "http://localhost:{{ frigate_port }}/api/config"
600 immich: "http://localhost:{{ immich_server_port }}/api/server-info/ping"
601 forgejo: "http://localhost:{{ forgejo_http_port }}/api/v1/version"
602 stirling_pdf: "http://localhost:{{ web_tools_stirling_port }}/api/v1/info/status"
603 convertx: "http://localhost:{{ web_tools_convertx_port }}/"
604 cyberchef: "http://localhost:{{ web_tools_cyberchef_port }}/"
605 it_tools: "http://localhost:{{ web_tools_it_tools_port }}/"
606 tandoor: "http://localhost:{{ tandoor_port }}/accounts/login/"
607 ghost: "http://localhost:{{ ghost_port }}/ghost/api/admin/site/"
608 livekit: "http://localhost:{{ livekit_port }}/"
609 livekit_meet: "http://localhost:{{ livekit_meet_port }}/"
610
611# ==============================================================================
612# LOGGING CONFIGURATION
613# ==============================================================================
614logging_driver: "json-file"
615logging_max_size: "10m"
616logging_max_file: "3"
617
618# Service-specific logging levels (unified LLM stack uses llm_stack_* variables)
619# ollama_log_level: "info" # Now uses llm_stack_ollama_log_level
620# openwebui_log_level: "info" # Now uses llm_stack_openwebui_log_level
621# litellm_log_level: "info" # Now uses llm_stack_litellm_log_level
622frigate_log_level: "info"
623immich_log_level: "log"
624forgejo_log_level: "Info"
625ghost_logging: "info"
626
627