From 301529271dfdf6ab4be82a5c2d8d2788e1acbc13 Mon Sep 17 00:00:00 2001 From: polyfloyd Date: Wed, 14 May 2025 17:40:30 +0200 Subject: [PATCH 1/3] music: Use nginx role --- group_vars/music.yaml | 4 ++ music.yaml | 2 +- roles/music/tasks/main.yaml | 9 ---- roles/music/templates/nginx-site.conf | 70 --------------------------- snippets/music-nginx.j2 | 49 +++++++++++++++++++ 5 files changed, 54 insertions(+), 80 deletions(-) delete mode 100644 roles/music/templates/nginx-site.conf create mode 100644 snippets/music-nginx.j2 diff --git a/group_vars/music.yaml b/group_vars/music.yaml index 8f0cc7c..457597a 100644 --- a/group_vars/music.yaml +++ b/group_vars/music.yaml @@ -11,6 +11,10 @@ root_access: - polyfloyd nginx_client_max_body_size: 512M +nginx_sites: + - server_name: "music.bitlair.nl" + snippets: + - "music-nginx.j2" music_domain: music.bitlair.nl acme_san_domains: diff --git a/music.yaml b/music.yaml index 17666f3..015c769 100644 --- a/music.yaml +++ b/music.yaml @@ -6,5 +6,5 @@ - { role: "acme", tags: [ "acme" ] } - { role: "deb_forgejo", tags: [ "deb_forgejo" ] } - { role: "go", tags: [ "go" ] } -# - { role: "nginx", tags: [ "nginx" ] } + - { role: "nginx", tags: [ "nginx" ] } - { role: "music", tags: [ "music" ] } diff --git a/roles/music/tasks/main.yaml b/roles/music/tasks/main.yaml index e8a751c..537746a 100644 --- a/roles/music/tasks/main.yaml +++ b/roles/music/tasks/main.yaml @@ -23,12 +23,3 @@ file: soundboard.yaml tags: - music_soundboard - -- name: Install nginx config - ansible.builtin.template: - src: nginx-site.conf - dest: /etc/nginx/sites-enabled/trollibox - owner: root - group: root - mode: 0644 - notify: Reload nginx diff --git a/roles/music/templates/nginx-site.conf b/roles/music/templates/nginx-site.conf deleted file mode 100644 index 185d689..0000000 --- a/roles/music/templates/nginx-site.conf +++ /dev/null @@ -1,70 +0,0 @@ -# {{ ansible_managed }} - -server { - listen 80 default_server; - listen [::]:80 default_server; - listen 443 ssl default_server; - listen [::]:443 ssl default_server; - - server_name {{ music_domain }}; - - {% if acme_bootstrap_certs %} - include "snippets/snakeoil.conf"; - {% else %} - ssl_certificate "/var/lib/dehydrated/certs/{{ music_domain }}/fullchain.pem"; - ssl_certificate_key "/var/lib/dehydrated/certs/{{ music_domain }}/privkey.pem"; - {% endif %} - - {% for range in trusted_ranges %} - allow {{ range.cidr }}; - {% endfor %} - deny all; - - location / { - rewrite ^/(.*) https://{{ music_domain }}/trollibox/player/space?; - } - - location /trollibox/ { - proxy_pass http://[::1]:3000/; - client_max_body_size 512M; - include proxy_params; - } - - location ~ ^/trollibox/(.+/events)$ { - proxy_pass http://[::1]:3000/$1; - include proxy_params; - proxy_http_version 1.1; - chunked_transfer_encoding off; - add_header X-Test "123"; - proxy_set_header Connection ''; - proxy_buffering off; - proxy_read_timeout 7d; - } - - location ~ ^/trollibox/(.+/listen)$ { - proxy_pass http://[::1]:3000/$1; - include proxy_params; - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "upgrade"; - proxy_read_timeout 7d; - } - - location /bobdsp/ { - proxy_pass http://[::1]:8081/; - include proxy_params; - } - - location /vis/ { - allow all; - proxy_pass http://[::1]:13378/; - include proxy_params; - } - - location = /vis/ { - rewrite ^(.*)$ /vis/index.html; - include proxy_params; - } - - include "snippets/acme.conf"; -} diff --git a/snippets/music-nginx.j2 b/snippets/music-nginx.j2 new file mode 100644 index 0000000..d179b23 --- /dev/null +++ b/snippets/music-nginx.j2 @@ -0,0 +1,49 @@ +{% for range in trusted_ranges %} +allow {{ range.cidr }}; +{% endfor %} +deny all; + +location / { + rewrite ^/(.*) https://{{ music_domain }}/trollibox/player/space?; +} + +location /trollibox/ { + proxy_pass http://[::1]:3000/; + include proxy_params; +} + +location ~ ^/trollibox/(.+/events)$ { + proxy_pass http://[::1]:3000/$1; + include proxy_params; + proxy_http_version 1.1; + chunked_transfer_encoding off; + add_header X-Test "123"; + proxy_set_header Connection ''; + proxy_buffering off; + proxy_read_timeout 7d; +} + +location ~ ^/trollibox/(.+/listen)$ { + proxy_pass http://[::1]:3000/$1; + include proxy_params; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_read_timeout 7d; +} + +location /bobdsp/ { + proxy_pass http://[::1]:8081/; + include proxy_params; +} + +location /vis/ { + allow all; + proxy_pass http://[::1]:13378/; + include proxy_params; +} + +location = /vis/ { + rewrite ^(.*)$ /vis/index.html; + include proxy_params; +} From 43075d27fea1a786ff04bbd8f0cc6ab84d5d7f88 Mon Sep 17 00:00:00 2001 From: polyfloyd Date: Wed, 14 May 2025 19:57:30 +0200 Subject: [PATCH 2/3] music/librespot: Various tweaks * Use pulseaudio backend * Run as separate librespot user * Use linear volume mixer --- roles/music/defaults/main.yaml | 3 +++ roles/music/handlers/main.yaml | 6 +++--- roles/music/tasks/librespot.yaml | 19 ++++++++++++------- roles/music/templates/librespot.service | 9 ++++----- 4 files changed, 22 insertions(+), 15 deletions(-) diff --git a/roles/music/defaults/main.yaml b/roles/music/defaults/main.yaml index fa95b47..5db2f4c 100644 --- a/roles/music/defaults/main.yaml +++ b/roles/music/defaults/main.yaml @@ -1,2 +1,5 @@ music_audio_user: audio +music_audio_group: audio +music_librespot_user: librespot + music_mqtt_mpd_volume: bitlair/music/space/volume diff --git a/roles/music/handlers/main.yaml b/roles/music/handlers/main.yaml index 2d77dbb..faf76f9 100644 --- a/roles/music/handlers/main.yaml +++ b/roles/music/handlers/main.yaml @@ -8,13 +8,13 @@ state: restarted daemon_reload: true -- name: Rebuild librespot +- name: rebuild librespot ansible.builtin.command: - cmd: /root/.cargo/bin/cargo build --release --features jackaudio-backend + cmd: /root/.cargo/bin/cargo build --release --features pulseaudio-backend args: chdir: /opt/librespot -- name: Restart librespot +- name: restart librespot ansible.builtin.systemd: name: librespot state: restarted diff --git a/roles/music/tasks/librespot.yaml b/roles/music/tasks/librespot.yaml index 2a8d19b..9d062ce 100644 --- a/roles/music/tasks/librespot.yaml +++ b/roles/music/tasks/librespot.yaml @@ -1,8 +1,11 @@ --- -- name: Install dependencies - ansible.builtin.apt: - name: libjack-jackd2-dev - state: present +- name: Create librespot user + user: + name: "{{ music_librespot_user }}" + system: true + home: /var/lib/librespot + groups: + - "{{ music_audio_group }}" - name: Clone librespot source ansible.builtin.git: @@ -11,8 +14,8 @@ dest: /opt/librespot accept_hostkey: yes notify: - - Rebuild librespot - - Restart librespot + - rebuild librespot + - restart librespot - name: Install service file ansible.builtin.template: @@ -21,7 +24,7 @@ owner: root group: root mode: 0644 - notify: Restart librespot + notify: restart librespot - name: Enable Librespot ansible.builtin.systemd: @@ -29,3 +32,5 @@ state: started enabled: true daemon_reload: true + +- meta: flush_handlers diff --git a/roles/music/templates/librespot.service b/roles/music/templates/librespot.service index 8d3b683..c6d8c4a 100644 --- a/roles/music/templates/librespot.service +++ b/roles/music/templates/librespot.service @@ -3,16 +3,15 @@ [Unit] Description=Spotify through Librespot After=network.target -Requires=jackd.service [Service] Type=simple Restart=always RestartSec=2s -ExecStart=/opt/librespot/target/release/librespot --name Trollibox --backend jackaudio -User={{ music_audio_user }} -Group={{ music_audio_user }} -AmbientCapabilities=CAP_IPC_LOCK,CAP_SYS_NICE +ExecStart=/opt/librespot/target/release/librespot --name Trollibox --backend pulseaudio --volume-ctrl linear +Environment="PULSE_SERVER=/tmp/pipewire-pulse-socket" +Environment="XDG_RUNTIME_DIR=/run/user/0" +User={{ music_librespot_user }} [Install] WantedBy=multi-user.target From 7cd44bbe53622c6569eda33aeee8b1dde356ea3f Mon Sep 17 00:00:00 2001 From: polyfloyd Date: Wed, 14 May 2025 21:26:36 +0200 Subject: [PATCH 3/3] music: Add MPD --- roles/music/handlers/main.yaml | 6 +++++ roles/music/tasks/mpd.yaml | 37 +++++++++++++++++++++++----- roles/music/templates/mpd.conf | 40 +++++++++++++++++++++++++++++++ roles/music/templates/mpd.service | 21 ++++++++++++++++ roles/music/templates/mpd_state | 17 +++++++++++++ 5 files changed, 115 insertions(+), 6 deletions(-) create mode 100644 roles/music/templates/mpd.conf create mode 100644 roles/music/templates/mpd.service create mode 100644 roles/music/templates/mpd_state diff --git a/roles/music/handlers/main.yaml b/roles/music/handlers/main.yaml index faf76f9..19193d6 100644 --- a/roles/music/handlers/main.yaml +++ b/roles/music/handlers/main.yaml @@ -2,6 +2,12 @@ - ansible.builtin.import_tasks: file: ../../common/handlers/main.yaml +- name: restart mpd + ansible.builtin.systemd: + name: mpd + state: restarted + daemon_reload: true + - name: Restart trollibox ansible.builtin.systemd: name: trollibox diff --git a/roles/music/tasks/mpd.yaml b/roles/music/tasks/mpd.yaml index eb88133..317df4e 100644 --- a/roles/music/tasks/mpd.yaml +++ b/roles/music/tasks/mpd.yaml @@ -1,14 +1,32 @@ --- - - name: Install MPD ansible.builtin.apt: - name: - - jackd - - mpd - - python3-mpd - - python3-serial + name: mpd state: present +- name: Add mpd user to the {{ music_audio_group }} group + user: + name: mpd + groups: + - "{{ music_audio_group }}" + notify: restart mpd + +- name: Install mpd file + ansible.builtin.template: + src: "{{ item.src }}" + dest: "{{ item.dest }}" + owner: root + group: root + mode: 0644 + notify: restart mpd + with_items: + - src: mpd.conf + dest: /etc/mpd.conf + - src: mpd.service + dest: /etc/systemd/system/mpd.service + - src: mpd_state + dest: /var/lib/mpd/state.default + - name: Install mpd-volume-to-mqtt script ansible.builtin.template: src: mpd-volume-to-mqtt.sh @@ -34,6 +52,13 @@ enabled: true daemon_reload: true +- name: Install skipbutton depedencies + ansible.builtin.apt: + name: + - python3-mpd + - python3-serial + state: present + - name: Clone skipbutton source ansible.builtin.git: repo: https://github.com/bitlair/skipbutton.git diff --git a/roles/music/templates/mpd.conf b/roles/music/templates/mpd.conf new file mode 100644 index 0000000..efa28f7 --- /dev/null +++ b/roles/music/templates/mpd.conf @@ -0,0 +1,40 @@ +# {{ ansible_managed }} + +user "mpd" +group "{{ music_audio_group }}" + +bind_to_address "any" +port "6600" +max_connections "20" + +zeroconf_enabled "yes" +zeroconf_name "MPD @ %h" + +music_directory "/srv/media/music" +auto_update "yes" +filesystem_charset "UTF-8" + +playlist_directory "/var/lib/mpd/playlists" +db_file "/var/lib/mpd/tag_cache" +state_file "/var/lib/mpd/state" +sticker_file "/var/lib/mpd/sticker.sql" + +input { + plugin "curl" # Required for web streams. +} + +decoder { + plugin "hybrid_dsd" + enabled "no" +} + +decoder { + plugin "wildmidi" + enabled "no" +} + +audio_output { + type "pulse" + name "Pulse" + server "/tmp/pipewire-pulse-socket" +} diff --git a/roles/music/templates/mpd.service b/roles/music/templates/mpd.service new file mode 100644 index 0000000..fb9808d --- /dev/null +++ b/roles/music/templates/mpd.service @@ -0,0 +1,21 @@ +# {{ ansible_managed }} + +[Unit] +Description=Music Player Daemon +After=network.target + +[Service] +Type=simple +ExecStartPre=/bin/mkdir -p /run/mpd +ExecStartPre=/bin/chown -R mpd:nogroup /run/mpd +ExecStartPre=/bin/touch /var/log/mpd.log +ExecStartPre=/bin/chown mpd:nogroup /var/log/mpd.log +ExecStartPre=/usr/bin/cp /var/lib/mpd/state.default /var/lib/mpd/state +ExecStart=/usr/bin/mpd --no-daemon /etc/mpd.conf +# MDP will fork itself to the user defined in its config +User=root +LimitMEMLOCK=infinity +LimitRTPRIO=99 + +[Install] +WantedBy=multi-user.target diff --git a/roles/music/templates/mpd_state b/roles/music/templates/mpd_state new file mode 100644 index 0000000..27b059b --- /dev/null +++ b/roles/music/templates/mpd_state @@ -0,0 +1,17 @@ +sw_volume: 20 +audio_device_state:1:Pulse +state: play +current: 0 +time: 0 +random: 0 +repeat: 0 +single: 0 +consume: 0 +crossfade: 0 +mixrampdb: 0.000000 +mixrampdelay: -1.000000 +playlist_begin +song_begin: http://ice4.somafm.com/groovesalad-256-mp3 +Name: SomaFM Groove Salad +song_end +playlist_end