From 3d41dafba6e72586dabb3bef1ec13793e57f6ba1 Mon Sep 17 00:00:00 2001 From: Chris Date: Sun, 20 Sep 2026 14:34:03 +0100 Subject: [PATCH] Photoprism, wolf, and jellyfin --- docker-compose.yml | 189 +++++++++++++- photoprism/vision.yml | 22 ++ wolf/config.toml | 572 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 780 insertions(+), 3 deletions(-) create mode 100644 photoprism/vision.yml create mode 100644 wolf/config.toml diff --git a/docker-compose.yml b/docker-compose.yml index a6cec54..bc957dd 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -131,6 +131,9 @@ services: - VIRTUAL_HOST=vault.${DOMAIN} - LETSENCRYPT_HOST=vault.${DOMAIN} - VIRTUAL_PORT=80 + - SIGNUPS_ALLOWED=false + networks: + - nginx volumes: - /mnt/tower/containers/vaultwarden:/data/ @@ -353,7 +356,6 @@ services: ################################### dawarich_app: image: freikin/dawarich:latest - container_name: dawarich_app volumes: - /mnt/tower/containers/dawarich/public:/var/app/public - /mnt/tower/containers/dawarich/watched:/var/app/tmp/imports/watched @@ -402,7 +404,6 @@ services: dawarich_sidekiq: image: freikin/dawarich:latest - container_name: dawarich_sidekiq volumes: - /mnt/tower/containers/dawarich/public:/var/app/public - /mnt/tower/containers/dawarich/watched:/var/app/tmp/imports/watched @@ -443,7 +444,6 @@ services: dawarich_db: image: postgis/postgis:17-3.5-alpine shm_size: 1G - container_name: dawarich_db volumes: - /mnt/tower/containers/dawarich/db:/var/lib/postgresql/data networks: @@ -526,6 +526,140 @@ services: networks: - sure + ################################### + # WOLF # + ################################### + wolf: + image: ghcr.io/games-on-whales/wolf:stable + <<: *logging + environment: + - NVIDIA_DRIVER_VOLUME_NAME=nvidia-driver-vol + volumes: + - /mnt/tower/containers/wolf/etc/wolf/:/etc/wolf:rw + - ./wolf/config.toml:/etc/wolf/cfg/config.toml:ro + - /var/run/docker.sock:/var/run/docker.sock:rw + - /dev/:/dev/:rw + - /run/udev:/run/udev:rw + - nvidia-driver-vol:/usr/nvidia:rw + devices: + - /dev/dri + - /dev/uinput + - /dev/uhid + - /dev/nvidia-uvm + - /dev/nvidia-uvm-tools + - /dev/nvidia-caps/nvidia-cap1 + - /dev/nvidia-caps/nvidia-cap2 + - /dev/nvidiactl + - /dev/nvidia0 + - /dev/nvidia-modeset + device_cgroup_rules: + - 'c 13:* rmw' + network_mode: host + restart: unless-stopped + + ################################### + # JELLYFIN # + # https://media.scarif.space # + ################################### + jellyfin: + image: jellyfin/jellyfin + <<: *logging + ports: + - 8096:8096/tcp + - 7359:7359/udp + volumes: + - ./jellyfin/config:/config + - /mnt/tower/containers/jellyfin/cache:/cache + - type: bind + source: /mnt/tower/stardust/chris/files/Library/Movies + target: /movies + - type: bind + source: /mnt/tower/stardust/chris/files/Library/Shows + target: /shows + restart: 'unless-stopped' + # Optional - alternative address used for autodiscovery + environment: + - JELLYFIN_PublishedServerUrl=http://media.${DOMAIN} + - VIRTUAL_HOST=media.${DOMAIN} + - VIRTUAL_PORT=8096 + - LETSENCRYPT_HOST=media.${DOMAIN} + extra_hosts: + - 'host.docker.internal:host-gateway' + networks: + - nginx + + ################################### + # PHOTOPRISM # + # https://holo.scarif.space # + ################################### + photoprism: + image: photoprism/photoprism:latest + <<: *logging + # restart: unless-stopped + stop_grace_period: 15s + depends_on: + - db + security_opt: + - seccomp:unconfined + - apparmor:unconfined + ports: + - "2342:2342" + environment: + PHOTOPRISM_ADMIN_USER: "${PHOTOPRISM_USER}" + PHOTOPRISM_ADMIN_PASSWORD: "${PHOTOPRISM_PASSWORD}" + PHOTOPRISM_AUTH_MODE: "password" + PHOTOPRISM_DISABLE_TLS: "true" + PHOTOPRISM_DEFAULT_TLS: "false" + PHOTOPRISM_SITE_URL: "http://holo.${DOMAIN}" + PHOTOPRISM_SITE_TITLE: "Holo" + PHOTOPRISM_SITE_CAPTION: "Photo library" + PHOTOPRISM_READONLY: "false" + PHOTOPRISM_EXPERIMENTAL: "true" + PHOTOPRISM_DISABLE_CHOWN: "false" + PHOTOPRISM_DISABLE_WEBDAV: "true" + PHOTOPRISM_DISABLE_MCP: "true" + PHOTOPRISM_SIDECAR_YAML: "true" + PHOTOPRISM_BACKUP_ALBUMS: "true" + PHOTOPRISM_BACKUP_DATABASE: "false" + PHOTOPRISM_INDEX_SCHEDULE: "@every 3h" + PHOTOPRISM_UPLOAD_LIMIT: 50000 + PHOTOPRISM_ORIGINALS_LIMIT: 50000 + PHOTOPRISM_HTTP_COMPRESSION: "zstd,gzip" + PHOTOPRISM_DATABASE_DRIVER: "sqlite" + PHOTOPRISM_INIT: "https tensorflow" + OLLAMA_BASE_URL: "http://ollama:11434" + OLLAMA_API_KEY: "" + PHOTOPRISM_FFMPEG_ENCODER: "nvidia" + PHOTOPRISM_FFMPEG_BITRATE: "64" + NVIDIA_VISIBLE_DEVICES: "all" + NVIDIA_DRIVER_CAPABILITIES: "all" + PHOTOPRISM_UID: 1000 + PHOTOPRISM_GID: 1000 + PHOTOPRISM_UMASK: 0000 + VIRTUAL_HOST: "holo.${DOMAIN}" + VIRTUAL_PORT: 2342 + LETSENCRYPT_HOST: "holo.${DOMAIN}" + user: "1000:1000" + devices: + - "/dev/dri:/dev/dri" + working_dir: "/photoprism" # do not change or remove + volumes: + - "/mnt/tower/stardust/chris/files/Memories:/photoprism/originals" + - "/mnt/tower/stardust/chris/files/Unsorted/Memories:/photoprism/import" + - "/mnt/tower/containers/photoprism/storage:/photoprism/storage" + - "./photoprism/vision.yml:/photoprism/storage/config/vision.yml:ro" + networks: + - nginx + - db + - ollama + deploy: + resources: + reservations: + devices: + - driver: "nvidia" + capabilities: [ gpu ] + count: "all" + ################################### # UTILITIES # ################################### @@ -577,6 +711,51 @@ services: - ./backup/exclude.txt:/config/exclude.txt:ro restart: unless-stopped + ## Ollama Large-Language Model Runner (optional) + ## run "ollama pull [name]:[version]" to download a vision model + ## listed at , for example: + ## docker compose exec ollama ollama pull gemma4:latest + ollama: + image: ollama/ollama:latest + <<: *logging + restart: unless-stopped + stop_grace_period: 15s + # ports: + # - "11434:11434" + environment: + OLLAMA_HOST: "0.0.0.0:11434" + OLLAMA_MODELS: "/root/.ollama" + OLLAMA_MAX_QUEUE: "100" + OLLAMA_NUM_PARALLEL: "1" + OLLAMA_MAX_LOADED_MODELS: "1" + OLLAMA_LOAD_TIMEOUT: "5m" + OLLAMA_KEEP_ALIVE: "5m" + OLLAMA_CONTEXT_LENGTH: "4096" + OLLAMA_MULTIUSER_CACHE: "false" + OLLAMA_NOPRUNE: "false" + OLLAMA_NOHISTORY: "true" + OLLAMA_FLASH_ATTENTION: "true" + OLLAMA_KV_CACHE_TYPE: "f16" + OLLAMA_SCHED_SPREAD: "false" + DO_NOT_TRACK: "true" + HF_HUB_DISABLE_TELEMETRY: "1" + OLLAMA_NO_CLOUD: "1" # uncomment to disable Ollama Cloud models/features + ## NVIDIA GPU Hardware Acceleration (see https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html): + NVIDIA_VISIBLE_DEVICES: "all" + NVIDIA_DRIVER_CAPABILITIES: "compute,utility" + volumes: + - "ollama:/root/.ollama" + networks: + - ollama + ## NVIDIA GPU Hardware Acceleration (see https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html): + deploy: + resources: + reservations: + devices: + - driver: "nvidia" + capabilities: [ gpu ] + count: "all" + nginx: <<: *logging profiles: ["prod", "dev"] @@ -639,6 +818,9 @@ volumes: html: vhost: acme: + ollama: + nvidia-driver-vol: + external: true networks: db: @@ -647,4 +829,5 @@ networks: sure: dawarich: meet.jitsi: + ollama: diff --git a/photoprism/vision.yml b/photoprism/vision.yml new file mode 100644 index 0000000..02cd434 --- /dev/null +++ b/photoprism/vision.yml @@ -0,0 +1,22 @@ +Models: +- Type: caption + Model: qwen3.5:9b + Engine: ollama + Run: auto + Options: + Temperature: 0.05 + Service: + Uri: http://ollama:11434/api/generate + Think: "false" +- Type: labels + Model: qwen3.5:9b + Engine: ollama + Run: auto + Service: + Uri: http://ollama:11434/api/generate + Think: "false" +Thresholds: + Confidence: 10 + Topicality: 0 + NSFW: 75 + diff --git a/wolf/config.toml b/wolf/config.toml new file mode 100644 index 0000000..2ac23a1 --- /dev/null +++ b/wolf/config.toml @@ -0,0 +1,572 @@ +config_version = 7 +hostname = 'Wolf' +uuid = '9a0c0dc9-1bf3-43b6-a6aa-a12e504177ad' + +[gstreamer.audio] +default_audio_params = 'queue max-size-buffers=3 leaky=downstream ! audiorate ! audioconvert' +default_opus_encoder = 'opusenc bitrate={bitrate} bitrate-type=cbr frame-size={packet_duration} bandwidth=fullband audio-type=restricted-lowdelay max-payload-size=1400' +default_sink = '''queue ! rtpmoonlightpay_audio name=moonlight_pay packet_duration={packet_duration} encrypt={encrypt} aes_key="{aes_key}" aes_iv="{aes_iv}" ! +appsink name=wolf_udp_sink''' +default_source = 'interpipesrc name=interpipesrc_{}_audio listen-to={session_id}_audio is-live=true stream-sync=restart-ts max-bytes=0 max-buffers=3 block=false' + +[gstreamer.video] +default_sink = '''queue ! rtpmoonlightpay_video name=moonlight_pay payload_size={payload_size} fec_percentage={fec_percentage} min_required_fec_packets={min_required_fec_packets} ! +appsink sync=false max-buffers=1 drop=true name=wolf_udp_sink +''' +default_source = 'interpipesrc name=interpipesrc_{}_video listen-to={session_id}_video is-live=true stream-sync=restart-ts max-bytes=0 max-buffers=1 leaky-type=downstream' + + [gstreamer.video.defaults.nvcodec] + video_params = '''cudaupload ! +cudaconvertscale add-borders=true ! +video/x-raw(memory:CUDAMemory), width={width}, height={height}, chroma-site={color_range}, format=NV12, colorimetry={color_space}, pixel-aspect-ratio=1/1''' + video_params_zero_copy = '''cudaupload ! +cudaconvertscale add-borders=true ! +video/x-raw(memory:CUDAMemory),format=NV12, width={width}, height={height}, pixel-aspect-ratio=1/1 +''' + + [gstreamer.video.defaults.qsv] + video_params = '''videoconvertscale ! +video/x-raw, chroma-site={color_range}, width={width}, height={height}, format=NV12, +colorimetry={color_space}, pixel-aspect-ratio=1/1''' + video_params_zero_copy = '''vapostproc add-borders=true ! +video/x-raw(memory:VAMemory), format=NV12, width={width}, height={height}, pixel-aspect-ratio=1/1''' + + [gstreamer.video.defaults.va] + video_params = '''vapostproc add-borders=true ! +video/x-raw, chroma-site={color_range}, width={width}, height={height}, format=NV12, +colorimetry={color_space}, pixel-aspect-ratio=1/1''' + video_params_zero_copy = '''vapostproc add-borders=true ! +video/x-raw(memory:VAMemory), format=NV12, width={width}, height={height}, pixel-aspect-ratio=1/1''' + + [[gstreamer.video.av1_encoders]] + check_elements = [ 'nvav1enc', 'cudaconvertscale', 'cudaupload' ] + encoder_pipeline = '''nvav1enc gop-size=-1 bitrate={bitrate} vbv-buffer-size={vbv_buffer_size} rc-mode=cbr zerolatency=true preset=p1 tune=ultra-low-latency multi-pass=two-pass-quarter ! +av1parse ! +video/x-av1, stream-format=obu-stream, alignment=frame, profile=main''' + plugin_name = 'nvcodec' + + [[gstreamer.video.av1_encoders]] + check_elements = [ 'vaav1enc', 'vapostproc' ] + encoder_pipeline = '''vaav1enc ref-frames=1 bitrate={bitrate} cpb-size={vbv_buffer_size} key-int-max=1024 rate-control=cbr min-qp=20 target-usage=6 ! +av1parse ! +video/x-av1, stream-format=obu-stream, alignment=frame, profile=main''' + plugin_name = 'va' + + [[gstreamer.video.av1_encoders]] + check_elements = [ 'vaav1lpenc', 'vapostproc' ] + encoder_pipeline = '''vaav1lpenc ref-frames=1 bitrate={bitrate} cpb-size={vbv_buffer_size} key-int-max=1024 rate-control=cbr min-qp=20 target-usage=6 ! +av1parse ! +video/x-av1, stream-format=obu-stream, alignment=frame, profile=main''' + plugin_name = 'va' + + [[gstreamer.video.av1_encoders]] + check_elements = [ 'qsvav1enc', 'vapostproc' ] + encoder_pipeline = '''qsvav1enc gop-size=0 ref-frames=1 bitrate={bitrate} rate-control=cbr low-latency=1 target-usage=6 ! +av1parse ! +video/x-av1, stream-format=obu-stream, alignment=frame, profile=main''' + plugin_name = 'qsv' + + [[gstreamer.video.av1_encoders]] + check_elements = [ 'av1enc' ] + encoder_pipeline = '''av1enc usage-profile=realtime end-usage=vbr target-bitrate={bitrate} ! +av1parse ! +video/x-av1, stream-format=obu-stream, alignment=frame, profile=main''' + plugin_name = 'aom' + video_params = '''videoconvertscale ! +videorate ! +video/x-raw, width={width}, height={height}, framerate={fps}/1, format=I420, +chroma-site={color_range}, colorimetry={color_space}''' + video_params_zero_copy = '''videoconvertscale ! +videorate ! +video/x-raw, width={width}, height={height}, framerate={fps}/1, format=I420, +chroma-site={color_range}, colorimetry={color_space}''' + + [[gstreamer.video.h264_encoders]] + check_elements = [ 'nvh264enc', 'cudaconvertscale', 'cudaupload' ] + encoder_pipeline = '''nvh264enc preset=low-latency-hq zerolatency=true gop-size=0 rc-mode=cbr-ld-hq bitrate={bitrate} vbv-buffer-size={vbv_buffer_size} aud=false ! +h264parse ! +video/x-h264, profile=main, stream-format=byte-stream''' + plugin_name = 'nvcodec' + + [[gstreamer.video.h264_encoders]] + check_elements = [ 'vah264enc', 'vapostproc' ] + encoder_pipeline = '''vah264enc aud=false b-frames=0 ref-frames=1 num-slices={slices_per_frame} bitrate={bitrate} cpb-size={vbv_buffer_size} min-qp=20 key-int-max=1024 rate-control=cbr target-usage=6 ! +h264parse ! +video/x-h264, profile=main, stream-format=byte-stream''' + plugin_name = 'va' + + [[gstreamer.video.h264_encoders]] + check_elements = [ 'vah264lpenc', 'vapostproc' ] + encoder_pipeline = '''vah264lpenc aud=false b-frames=0 ref-frames=1 num-slices={slices_per_frame} bitrate={bitrate} cpb-size={vbv_buffer_size} min-qp=20 key-int-max=1024 rate-control=cbr target-usage=6 ! +h264parse ! +video/x-h264, profile=main, stream-format=byte-stream''' + plugin_name = 'va' + + [[gstreamer.video.h264_encoders]] + check_elements = [ 'qsvh264enc', 'vapostproc' ] + encoder_pipeline = '''qsvh264enc b-frames=0 gop-size=0 idr-interval=1 ref-frames=1 bitrate={bitrate} rate-control=cbr target-usage=6 ! +h264parse ! +video/x-h264, profile=main, stream-format=byte-stream''' + plugin_name = 'qsv' + + [[gstreamer.video.h264_encoders]] + check_elements = [ 'x264enc' ] + encoder_pipeline = '''x264enc pass=qual tune=zerolatency speed-preset=superfast b-adapt=false bframes=0 ref=1 +sliced-threads=true threads={slices_per_frame} option-string="slices={slices_per_frame}:keyint=infinite:open-gop=0" +b-adapt=false bitrate={bitrate} aud=false ! +video/x-h264, profile=high, stream-format=byte-stream''' + plugin_name = 'x264' + + [[gstreamer.video.hevc_encoders]] + check_elements = [ 'nvh265enc', 'cudaconvertscale', 'cudaupload' ] + encoder_pipeline = '''nvh265enc gop-size=-1 bitrate={bitrate} vbv-buffer-size={vbv_buffer_size} aud=false rc-mode=cbr zerolatency=true preset=p1 tune=ultra-low-latency multi-pass=two-pass-quarter ! +h265parse ! +video/x-h265, profile=main, stream-format=byte-stream''' + plugin_name = 'nvcodec' + + [[gstreamer.video.hevc_encoders]] + check_elements = [ 'vah265enc', 'vapostproc' ] + encoder_pipeline = '''vah265enc aud=false b-frames=0 ref-frames=1 num-slices={slices_per_frame} bitrate={bitrate} cpb-size={vbv_buffer_size} min-qp=20 key-int-max=1024 rate-control=cbr target-usage=6 ! +h265parse ! +video/x-h265, profile=main, stream-format=byte-stream''' + plugin_name = 'va' + + [[gstreamer.video.hevc_encoders]] + check_elements = [ 'qsvh265enc', 'vapostproc' ] + encoder_pipeline = '''qsvh265enc b-frames=0 gop-size=0 idr-interval=1 ref-frames=1 bitrate={bitrate} rate-control=cbr low-latency=1 target-usage=6 ! +h265parse ! +video/x-h265, profile=main, stream-format=byte-stream''' + plugin_name = 'qsv' + + [[gstreamer.video.hevc_encoders]] + check_elements = [ 'vah265lpenc', 'vapostproc' ] + encoder_pipeline = '''vah265lpenc aud=false b-frames=0 ref-frames=1 num-slices={slices_per_frame} bitrate={bitrate} cpb-size={vbv_buffer_size} min-qp=20 key-int-max=1024 rate-control=cbr target-usage=6 ! +h265parse ! +video/x-h265, profile=main, stream-format=byte-stream''' + plugin_name = 'va' + + [[gstreamer.video.hevc_encoders]] + check_elements = [ 'x265enc' ] + encoder_pipeline = '''x265enc tune=zerolatency speed-preset=superfast bitrate={bitrate} +option-string="info=0:keyint=-1:qp=28:repeat-headers=1:slices={slices_per_frame}:aud=0:annexb=1:log-level=3:open-gop=0:bframes=0:intra-refresh=0" ! +video/x-h265, profile=main, stream-format=byte-stream''' + plugin_name = 'x265' + video_params = '''videoconvertscale ! +videorate ! +video/x-raw, width={width}, height={height}, framerate={fps}/1, format=I420, +chroma-site={color_range}, colorimetry={color_space}''' + video_params_zero_copy = '''videoconvertscale ! +videorate ! +video/x-raw, width={width}, height={height}, framerate={fps}/1, format=I420, +chroma-site={color_range}, colorimetry={color_space}''' + +[[paired_clients]] +app_state_folder = '4253397947964014983' +client_cert = '''-----BEGIN CERTIFICATE----- +MIICvzCCAaegAwIBAgIBADANBgkqhkiG9w0BAQsFADAjMSEwHwYDVQQDDBhOVklE +SUEgR2FtZVN0cmVhbSBDbGllbnQwHhcNMjYwOTExMjI0NzU0WhcNNDYwOTA2MjI0 +NzU0WjAjMSEwHwYDVQQDDBhOVklESUEgR2FtZVN0cmVhbSBDbGllbnQwggEiMA0G +CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDJon8BGgFYZQGYAFbhkBI30aAt0HXV +vSPoDko+fzr+AKDACLtOIlk0I5rYzCxO0egTq4TtODABOcSCAIhVwhlnm4D8vGeC +HyMqt2XhxCraGhq/cntyS38FLCD4/3kCbTFGswYNsma7r53DEMs1G0HMhvmKWaXm +CJEnZu1/Q/WltRyWgW+J9GHpz5c65WDmdPfUQZBgPiA+v6jOcztEpMSc8yPo/mdB +Rj/otWZp8gJUWMDj37lNX3xZXBx2W1WD6DLaYx3AQxaEJlE2cxsMHV6pWLbaFye5 +dPScERWBXW8ScOc71lmZ6zfxICGK38m1t9SCRFFEW74e6R6UYwcaoguPAgMBAAEw +DQYJKoZIhvcNAQELBQADggEBAEeN9/B9kl/oObF7HlDId6ijMpEPaKws4sHp3H09 +oI3uObLS56Y+MP/jwHldxL5yzY5sAzXRblgwIFj/5xwPohKzCJM+q7UEHlLkNUO/ +gpCBdUDxMcw428YgJzvLLiTBO6pQJuY2GfeR99JNGr2em3q4waDQzZpC6mLbMJAi +ZQHQJntN0yv2AtK5mTMLWB3+yI4MLLqvTYKAQLS1Gsoedq+w5l8nkyugWkQNtUup +iVFFuHxyRk+72tfjxOWoziCJ67YIcC5foSDzJvEopUN6xzVRH0iZhEN3PzXqAM/a +xgimS4jRyDQ4Y8UeT2T4stEDz1+fqwosq/kpbBcXctx38ac= +-----END CERTIFICATE----- +''' + + [paired_clients.settings] + controllers_override = [] + h_scroll_acceleration = 1.0 + motion_controller_override = 'AUTO' + mouse_acceleration = 1.0 + run_gid = 1000 + run_uid = 1000 + v_scroll_acceleration = 1.0 + +[[paired_clients]] +app_state_folder = '832565367026934083' +client_cert = '''-----BEGIN CERTIFICATE----- +MIICxjCCAa6gAwIBAgIIUYQpYpwoyMwwDQYJKoZIhvcNAQELBQAwIzEhMB8GA1UE +AwwYTlZJRElBIEdhbWVTdHJlYW0gQ2xpZW50MB4XDTI2MDkxMTIzMDI1MFoXDTQ2 +MDkxMTIzMDI1MFowIzEhMB8GA1UEAwwYTlZJRElBIEdhbWVTdHJlYW0gQ2xpZW50 +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArddXC2/Uu2FTVmfTaTBJ +kB2v5MFkgQ0MY3cxQWZ9oHyR0f5YTR1IJEs5MoLJ4jH8wnVK/HcB5rlhzUVTU/1r +3eXZX9umXZzhq6UmUaqRdHG4SqHiYElIRr50a8Z/Hc9NlyM8xKPWhjPGtp4hoyBE +UreyPVvnswhz7tIjikomfTIWgo+X2MFMMM03niavYyrrOIiOFweYMuv+tgVgdWsu +cTleev6SDWajw7YBuoPQZBa+/W+DD887rv5aYKfTobE56FsUyzCmXKv01rZhUQ08 +AJTGProNqUUD84zUk078Du6LQ9jcIeRg0En9WeSeAuDfQ+viRidyGNJ1WQi4v6OI +HwIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQAfebSCETh109HJ6p1gw3aNOY14fulm +JTjxsUmWSEhvZvgNSkWU0VavILzI0LYTDM1M3uCkEuEOXPebAqYTp90l6l9eq2xj +hNm1H5I8LHUmqfvXG5eCHECKBlZPjWdWCl9PX1orqKyv4NF3+J3IkYE/qGCTb+Vl +xjYzea40uXL9zZtLBr/iymDjZhwdowJZqx/b23um/7rLdA0/7ouMbKEeYIpGKrga +TgGXxifbnL5CaJdZmJKyaM0gbfq4+AyU0BG2tRphcakdYtCYIjLI6qiJGy8a4e37 +5aY1ioMHJOQB1nEUiCUdEBdG7aTkizg7TmR8aTK2xz4Ww7S1eEKpGULn +-----END CERTIFICATE----- +''' + + [paired_clients.settings] + controllers_override = [] + h_scroll_acceleration = 1.0 + motion_controller_override = 'AUTO' + mouse_acceleration = 1.0 + run_gid = 1000 + run_uid = 1000 + v_scroll_acceleration = 1.0 + +[[paired_clients]] +app_state_folder = '4148551118029650770' +client_cert = '''-----BEGIN CERTIFICATE----- +MIICvzCCAaegAwIBAgIBADANBgkqhkiG9w0BAQsFADAjMSEwHwYDVQQDDBhOVklE +SUEgR2FtZVN0cmVhbSBDbGllbnQwHhcNMjYwOTEyMDYzOTE1WhcNNDYwOTA3MDYz +OTE1WjAjMSEwHwYDVQQDDBhOVklESUEgR2FtZVN0cmVhbSBDbGllbnQwggEiMA0G +CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDBM8aFF4g0XVJ8MLhk0NmWzUB01Hts +m/OSzYTryXP/FYikoosml1oVE4LylSOKfjqPUeF8p19TQe22zqDTAOt4y11sqySX +CjQw3lChtWO3ifeFtTPXxsa1yuGPa09dUC+rbjG58tExSRrxbAZ0qbuVRO3I2gRh +7q5aWLEE5r26WPhGCLWdsnmwSg86lH3zkfGhDBzBnxT6snbEOTaZ6xnK5MaNlKmQ +B2Ou8Tw6ZGkmNQw4NL3AIeV9cVR29bawoCio0xpg5TIxxWSDREhWgiPoZKoXFVwB +y5ofWQ336JxAQpaZuHTYy2Ag092K4IvUNlZ+JNTMjQELoA+OA3q8tMHrAgMBAAEw +DQYJKoZIhvcNAQELBQADggEBABtbpKpW7NjWQIDwzPJcUFyevkLVFFxQTfcs+ACX +m3eJKU7JI2SraOELalenYpf3gG+0wgJfF4uVDS7F1SjhAMlKV9qxsmpOrIms/9JF +8eTGHau4E4GtOKdiy5OX+y4P/fcsK/RlNCWqSvkHupZcfyzUJsD6N4ZNtB9YRvNs +Ukr59LVJFo7a4L75zjMAHwuZypJC+l53YZPmCNo/szhetMpEsmEub0dcBMRi3V9j +rxvyvHgSsIpIBPjUsvszV70G1+r/IhohjAHML6g5f67Z5loinEgpDBvtfEnodOc4 +BGSCR6i1K5ZKmGmlZj8MFlOvhwFo3TqQ565HBlnVQthp6Cc= +-----END CERTIFICATE----- +''' + + [paired_clients.settings] + controllers_override = [] + h_scroll_acceleration = 1.0 + motion_controller_override = 'AUTO' + mouse_acceleration = 1.0 + run_gid = 1000 + run_uid = 1000 + v_scroll_acceleration = 1.0 + +[[paired_clients]] +app_state_folder = '1973283391930839926' +client_cert = '''-----BEGIN CERTIFICATE----- +MIICxjCCAa6gAwIBAgIIRowDEPfuiYgwDQYJKoZIhvcNAQELBQAwIzEhMB8GA1UE +AwwYTlZJRElBIEdhbWVTdHJlYW0gQ2xpZW50MB4XDTI2MDkxMjA3MTQ0MloXDTQ2 +MDkxMjA4MTQ0MlowIzEhMB8GA1UEAwwYTlZJRElBIEdhbWVTdHJlYW0gQ2xpZW50 +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8ZAwIlh4qbJAkIcby2us +CRLKHycxhmk3Nl5ZQFGX682O25u3F91dMNvXD+3r4U7/fG0speoq4vEMYVEjinZs +CRnew7JDZsHsFxnlLc9tWb99vATdDQKNCjRhAiVAJK7U7fBcq7YKEE4uZD1raBFz +R5lnODsUWFgA6niijrn5SPyjJdMLN3z7H+A3cI1qpBQS1Oufv9eHDqDyFyEQIGuH +dQviIPPeETvs1m3qaD2HPIqYyZne4AnwPizzdWI54FPzpJzbM/pdUIUAigwToQor +aUaBCEuolX60KDVnj/uXBvVGTrmopH4ppNghyuVp9pPdD+8WYLFuKjIIaj6WZPSs +0QIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQAjBOuHAi31Sj0mnp+7iBjYFWZw9T3h +C6EJwX8990VTywRpa8cDpyVqI1Y5Zo+ZQ2lM9fTyFn6AHgko478RWyTyoWazUYZ+ +yJ2C1h69wM9JDlY0Qwn67wLx/+4I1jMpxMiNFJTbKUtuOYuQpLa2gOIo316njgLW +FrqyjdL93A8jy+kaRCuVh085SQ+Vt3hY37w0zKREACxP/pYR7yasXZWf9HUEoJW4 +9Nn1GGwK2j06hBfaCAURryhIN3N5FDW3eJsrx+iFhL4pAv28LvZNcHo+XoDJ3xFR +QgpG1CD/h9NmhUPn7VRUlPoxWvkcbuc49BiEhW8SGXNWSBnEH4IXJtB4 +-----END CERTIFICATE----- +''' + + [paired_clients.settings] + controllers_override = [] + h_scroll_acceleration = 1.0 + motion_controller_override = 'AUTO' + mouse_acceleration = 1.0 + run_gid = 1000 + run_uid = 1000 + v_scroll_acceleration = 1.0 + +[[paired_clients]] +app_state_folder = '13843269076185421004' +client_cert = '''-----BEGIN CERTIFICATE----- +MIICvzCCAaegAwIBAgIBADANBgkqhkiG9w0BAQsFADAjMSEwHwYDVQQDDBhOVklE +SUEgR2FtZVN0cmVhbSBDbGllbnQwHhcNMjYwOTEyMDcxMTU4WhcNNDYwOTA3MDcx +MTU4WjAjMSEwHwYDVQQDDBhOVklESUEgR2FtZVN0cmVhbSBDbGllbnQwggEiMA0G +CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC6tHRbbkjPilFN+MhroO71BbF0JMQ7 +Nzf9rfihPdDDpyPEwKR/11ozJ/Hu6SrAR0hZTKMpPF0vtVG2ceQY99/rfAwgIdXa +FpL5neEedRpLAS41qx9RNBXSBbFekSoNIx1/LBGtQyetOZrv4UeWwivb3Q/ClFUa +z005wcD7qQRNVBjbjgOhbL7tREeMdgkZwUzIVwCuWQhHJ5CZjhFLGq8kSGSkc2eZ +/VtQ+Ou6TbD7aZUQQfGykEaiy71aMoEwnmCCDAkhqBvu0zP1CEf1tZKUbUIm5lj1 +P8uWbdp/GuHYALnAAzrvhYhxVU3PSDGy4YxsE9IR/aj8SAugPd2LE1zLAgMBAAEw +DQYJKoZIhvcNAQELBQADggEBAE7xMQllGhw44ea+QFuo23ZsGSb/soGQ84J0dnjQ +yOasQVNSHTsax3uLMTh1Ar9cL2wQWugPe42fEGwj84KQ6+stArhSmbvJ95BVjAec +tdg4gwAATjCie+UYLGu60HxGXJsz3VhijRUh5W7Blssv0EX8qwDupKfHZv9HvSPo +0Pqu0oULPfKXtv0thNFo8F0YT9YQgNnz4WU20zbiB5eS0eh1meCblMcRhdW8dNng +ZCez0e3GQRbpF6nuo0dgAQQ9c+/gvs01qZ9dFaorJwmO7uEydje6j0FpPWkrYx7L +556HrbC4pKmAvCNcZXbyGC5HTHPtf0pGthhPkB6UCCzlLkQ= +-----END CERTIFICATE----- +''' + + [paired_clients.settings] + controllers_override = [] + h_scroll_acceleration = 1.0 + motion_controller_override = 'AUTO' + mouse_acceleration = 1.0 + run_gid = 1000 + run_uid = 1000 + v_scroll_acceleration = 1.0 + +[[profiles]] +id = 'moonlight-profile-id' + + [[profiles.apps]] + icon_png_path = 'https://raw.githubusercontent.com/games-on-whales/wolf-ui/refs/heads/main/src/Icons/wolf_ui_icon.png' + start_virtual_compositor = true + title = 'Wolf UI' + + [profiles.apps.runner] + base_create_json = '''{ + "HostConfig": { + "IpcMode": "host", + "CapAdd": ["NET_RAW", "MKNOD", "NET_ADMIN", "SYS_ADMIN", "SYS_NICE"], + "Privileged": false, + "DeviceCgroupRules": ["c 13:* rmw", "c 244:* rmw"] + } + }''' + devices = [] + env = [ + 'GOW_REQUIRED_DEVICES=/dev/input/event* /dev/dri/* /dev/nvidia*', + 'WOLF_SOCKET_PATH=/var/run/wolf/wolf.sock', + 'WOLF_UI_AUTOUPDATE=False', + 'LOGLEVEL=INFO' + ] + image = 'ghcr.io/games-on-whales/wolf-ui:main' + mounts = [ '/var/run/wolf/wolf.sock:/var/run/wolf/wolf.sock' ] + name = 'Wolf-UI' + ports = [] + type = 'docker' + + [[profiles.apps]] + icon_png_path = 'https://raw.githubusercontent.com/games-on-whales/wolf/refs/heads/stable/docs/images/test_ball_icon.png' + start_audio_server = false + start_virtual_compositor = false + title = 'Test ball' + + [profiles.apps.audio] + source = 'audiotestsrc wave=ticks is-live=true' + + [profiles.apps.runner] + run_cmd = "sh -c \"while :; do echo 'running...'; sleep 10; done\"" + type = 'process' + + [profiles.apps.video] + source = '''videotestsrc pattern=ball flip=true is-live=true ! +video/x-raw, framerate={fps}/1 +''' + +[[profiles]] +id = 'user' +name = 'User' + + [[profiles.apps]] + icon_png_path = 'https://games-on-whales.github.io/wildlife/apps/firefox/assets/icon.png' + start_virtual_compositor = true + title = 'Firefox' + + [profiles.apps.runner] + base_create_json = '''{ + "HostConfig": { + "IpcMode": "host", + "Privileged": false, + "CapAdd": ["NET_RAW", "MKNOD", "NET_ADMIN"], + "DeviceCgroupRules": ["c 13:* rmw", "c 244:* rmw"] + } +} +''' + devices = [] + env = [ 'RUN_SWAY=1', 'MOZ_ENABLE_WAYLAND=1', 'GOW_REQUIRED_DEVICES=/dev/input/* /dev/dri/* /dev/nvidia*' ] + image = 'ghcr.io/games-on-whales/firefox:edge' + mounts = [] + name = 'WolfFirefox' + ports = [] + type = 'docker' + + [[profiles.apps]] + icon_png_path = 'https://games-on-whales.github.io/wildlife/apps/retroarch/assets/icon.png' + start_virtual_compositor = true + title = 'RetroArch' + + [profiles.apps.runner] + base_create_json = '''{ + "HostConfig": { + "IpcMode": "host", + "CapAdd": ["NET_RAW", "MKNOD", "NET_ADMIN", "SYS_ADMIN", "SYS_NICE"], + "Privileged": false, + "DeviceCgroupRules": ["c 13:* rmw", "c 244:* rmw"] + } +} +''' + devices = [] + env = [ 'RUN_SWAY=true', 'GOW_REQUIRED_DEVICES=/dev/input/* /dev/dri/* /dev/nvidia*' ] + image = 'ghcr.io/games-on-whales/retroarch:edge' + mounts = [] + name = 'WolfRetroarch' + ports = [] + type = 'docker' + + [[profiles.apps]] + icon_png_path = 'https://games-on-whales.github.io/wildlife/apps/steam/assets/icon.png' + start_virtual_compositor = true + title = 'Steam' + + [profiles.apps.runner] + base_create_json = '''{ + "HostConfig": { + "IpcMode": "host", + "CapAdd": ["SYS_ADMIN", "SYS_NICE", "SYS_PTRACE", "NET_RAW", "MKNOD", "NET_ADMIN"], + "SecurityOpt": ["seccomp=unconfined", "apparmor=unconfined"], + "Ulimits": [{"Name":"nofile", "Hard":10240, "Soft":10240}], + "Privileged": false, + "DeviceCgroupRules": ["c 13:* rmw", "c 244:* rmw"] + } +} +''' + devices = [] + env = [ 'PROTON_LOG=1', 'RUN_SWAY=true', 'GOW_REQUIRED_DEVICES=/dev/input/* /dev/dri/* /dev/nvidia*' ] + image = 'ghcr.io/games-on-whales/steam:edge' + mounts = [ '/mnt/games/:/mnt/games:rw' ] + name = 'WolfSteam' + ports = [] + type = 'docker' + + [[profiles.apps]] + icon_png_path = 'https://games-on-whales.github.io/wildlife/apps/pegasus/assets/icon.png' + start_virtual_compositor = true + title = 'Pegasus' + + [profiles.apps.runner] + base_create_json = '''{ + "HostConfig": { + "IpcMode": "host", + "CapAdd": ["NET_RAW", "MKNOD", "NET_ADMIN", "SYS_ADMIN", "SYS_NICE"], + "Privileged": false, + "DeviceCgroupRules": ["c 13:* rmw", "c 244:* rmw"] + } +} +''' + devices = [] + env = [ 'RUN_SWAY=1', 'GOW_REQUIRED_DEVICES=/dev/input/event* /dev/dri/* /dev/nvidia*' ] + image = 'ghcr.io/games-on-whales/pegasus:edge' + mounts = [] + name = 'WolfPegasus' + ports = [] + type = 'docker' + + [[profiles.apps]] + icon_png_path = 'https://games-on-whales.github.io/wildlife/apps/lutris/assets/icon.png' + start_virtual_compositor = true + title = 'Lutris' + + [profiles.apps.runner] + base_create_json = '''{ + "HostConfig": { + "IpcMode": "host", + "CapAdd": ["SYS_ADMIN", "SYS_NICE", "SYS_PTRACE", "NET_RAW", "MKNOD", "NET_ADMIN"], + "SecurityOpt": ["seccomp=unconfined", "apparmor=unconfined"], + "Ulimits": [{"Name":"nofile", "Hard":524288, "Soft":524288}], + "Privileged": false, + "DeviceCgroupRules": ["c 13:* rmw", "c 244:* rmw"] + } +} +''' + devices = [] + env = [ 'RUN_SWAY=1', 'GOW_REQUIRED_DEVICES=/dev/input/event* /dev/dri/* /dev/nvidia* /var/lutris/' ] + image = 'ghcr.io/games-on-whales/lutris:edge' + mounts = [ 'lutris:/var/lutris/:rw' ] + name = 'WolfLutris' + ports = [] + type = 'docker' + + [[profiles.apps]] + icon_png_path = 'https://games-on-whales.github.io/wildlife/apps/prismlauncher/assets/icon.png' + start_virtual_compositor = true + title = 'Prismlauncher' + + [profiles.apps.runner] + base_create_json = '''{ + "HostConfig": { + "IpcMode": "host", + "CapAdd": ["NET_RAW", "MKNOD", "NET_ADMIN", "SYS_ADMIN", "SYS_NICE"], + "Privileged": false, + "DeviceCgroupRules": ["c 13:* rmw", "c 244:* rmw"] + } +} +''' + devices = [] + env = [ 'RUN_SWAY=1', 'GOW_REQUIRED_DEVICES=/dev/input/event* /dev/dri/* /dev/nvidia* /var/lutris/' ] + image = 'ghcr.io/games-on-whales/prismlauncher:edge' + mounts = [] + name = 'Prismlauncher' + ports = [] + type = 'docker' + + [[profiles.apps]] + icon_png_path = 'https://games-on-whales.github.io/wildlife/apps/xfce/assets/icon.png' + title = 'Desktop (xfce)' + + [profiles.apps.runner] + base_create_json = '''{ + "HostConfig": { + "IpcMode": "host", + "Privileged": false, + "CapAdd": ["SYS_ADMIN", "SYS_NICE", "SYS_PTRACE", "NET_RAW", "MKNOD", "NET_ADMIN"], + "SecurityOpt": ["seccomp=unconfined", "apparmor=unconfined"], + "DeviceCgroupRules": ["c 13:* rmw", "c 244:* rmw"] + } +} +''' + devices = [] + env = [ 'GOW_REQUIRED_DEVICES=/dev/input/* /dev/dri/* /dev/nvidia*' ] + image = 'ghcr.io/games-on-whales/xfce:edge' + mounts = [] + name = 'WolfXFCE' + ports = [] + type = 'docker' + + [[profiles.apps]] + icon_png_path = 'https://games-on-whales.github.io/wildlife/apps/es-de/assets/icon.png' + title = 'EmulationStation' + + [profiles.apps.runner] + base_create_json = '''{ + "HostConfig": { + "IpcMode": "host", + "Privileged": false, + "CapAdd": ["NET_RAW", "MKNOD", "NET_ADMIN"], + "DeviceCgroupRules": ["c 13:* rmw", "c 244:* rmw"] + } +} +''' + devices = [] + env = [ 'RUN_SWAY=1', 'MOZ_ENABLE_WAYLAND=1', 'GOW_REQUIRED_DEVICES=/dev/input/* /dev/dri/* /dev/nvidia*' ] + image = 'ghcr.io/games-on-whales/es-de:edge' + mounts = [] + name = 'WolfES-DE' + ports = [] + type = 'docker' + + [[profiles.apps]] + icon_png_path = 'https://games-on-whales.github.io/wildlife/apps/kodi/assets/icon.png' + title = 'Kodi' + + [profiles.apps.runner] + base_create_json = '''{ + "HostConfig": { + "IpcMode": "host", + "Privileged": false, + "CapAdd": ["NET_RAW", "MKNOD", "NET_ADMIN"], + "DeviceCgroupRules": ["c 13:* rmw", "c 244:* rmw"] + } +} +''' + devices = [] + env = [ 'RUN_SWAY=true', 'GOW_REQUIRED_DEVICES=/dev/input/* /dev/dri/* /dev/nvidia*' ] + image = 'ghcr.io/games-on-whales/kodi:edge' + mounts = [] + name = 'WolfKodi' + ports = [] + type = 'docker'