- Jinja 41.2%
- Python 27.1%
- JavaScript 12.9%
- CSS 8.3%
- HTML 6.1%
- Other 4.4%
| files | ||
| group_vars | ||
| host_vars | ||
| inventory | ||
| publickeys | ||
| templates | ||
| .gitignore | ||
| ansible.cfg | ||
| coordinator_proxy.yml | ||
| filebrowser.yml | ||
| firewall.yml | ||
| landing_page.yml | ||
| LICENSE | ||
| monit.yml | ||
| motd.yml | ||
| mpd.yml | ||
| musikgulli_web.yml | ||
| nfs-setup.yml | ||
| nginx.yml | ||
| packages.yml | ||
| README.md | ||
| requirements.yml | ||
| site.yml | ||
| speaker-volume.yml | ||
| wireguard.yml | ||
Musikgulli Ansible Project
Dieses Repository enthält die Ansible-Konfiguration für die technische Infrastruktur des Musikgullys am Ernst-August-Platz vor dem Hauptbahnhof Hannover.
Der Musikgully, auch als „DJ Gullyman“ bekannt, ist eine Klanginstallation im öffentlichen Raum: Aus einem scheinbaren Gully vor dem Hauptbahnhof spielt tagsüber und nachts Musik aus dem Untergrund. Das Projekt geht auf die Umgestaltung des Ernst-August-Platzes um das Jahr 2000 zurück und ist als spielerische, bewusst leicht zu übersehende Kunst im Stadtraum gedacht. Weitere Informationen beschreibt Hannover.de im Artikel „Wo die Musik spielt – und warum“.
Die Software in diesem Repository betreibt die Player-Systeme hinter der
Installation. Sie installiert und konfiguriert MPD, verteilt die
musikgulli-web Steuerung, richtet Netzwerkzugriff per WireGuard ein und
überwacht die Player mit Monit. Im Betrieb schaltet der Web-Daemon automatisch
zwischen Tag-, Nacht- und Sonder-Playlisten um und stellt eine einfache
Web-Oberfläche für Status, Lautstärke und Zeitpläne bereit.
Lizenz und Public Code
Dieses Projekt wurde mit öffentlichen Geldern finanziert und wird deshalb im Einklang mit der Smart-City-Strategie der Landeshauptstadt Hannover als Open Source veröffentlicht. Damit folgt sie dem Grundsatz „Public Money, Public Code“: Software, die von der Allgemeinheit bezahlt wird, soll auch der Allgemeinheit zur Verfügung stehen.
Der Code steht unter der GNU General Public License v3.0. Details stehen in
LICENSE.
Python-Hinweis: Für einige Ansible-Netzwerkfilter muss das Paket netaddr
installiert sein.
Project Structure
ansible/
├── inventory/
│ └── hosts.yml # Inventory file containing host definitions
├── group_vars/
│ └── players.yml # Variables for all players
├── host_vars/
│ └── coordinator.yml # Variables for coordinator
├── files/
│ ├── musikgulli-web/ # Web daemon (webplayers)
│ │ ├── app.py # Flask app + control loop
│ │ ├── requirements.txt # Python dependencies
│ │ ├── templates/index.html # Web UI
│ │ └── static/ # JS/CSS for the web UI
│ ├── monit-mpd-playing.sh # Monit helper: MPD playing and queue check
│ └── monit-check-music-files.sh # Monit helper: Music files check
├── templates/
│ ├── mpd.conf.j2 # MPD configuration template
│ ├── filebrowser.service.j2 # Filebrowser systemd service
│ ├── musikgulli-web.service.j2 # musikgulli-web systemd service
│ ├── nginx-webplayers.conf.j2 # nginx location blocks (coordinator)
│ ├── nginx-monit.conf.j2 # nginx location blocks for Monit (coordinator)
│ └── monitrc-players.j2 # Monit configuration template
├── site.yml # Main playbook
├── packages.yml # Package management playbook
├── mpd.yml # MPD installation and configuration
├── musikgulli_web.yml # musikgulli-web daemon deployment (webplayers)
├── coordinator_proxy.yml # nginx reverse proxy config on the coordinator
├── monit.yml # Monit monitoring setup
├── firewall.yml # Firewall configuration
├── nfs-setup.yml # NFS server/client setup
├── wireguard.yml # Wireguard VPN configuration
└── README.md # This file
Inventory
The inventory contains the following hosts and groups:
-
Host:
coordinator -
Group:
players(parent group, targeted by mpd/firewall/monit/nfs playbooks)- Group:
webplayers– Player, gesteuert durch den dauerhaft laufendenmusikgulli-webDaemon mit Web-UI
- Group:
Player mit Web-Steuerung werden unter webplayers eingetragen.
Playbooks
site.yml
Main playbook for general system configuration. Includes:
packages.yml- Package managementwireguard.yml- WireGuard VPN setup (before firewall/UFW, since other playbooks open ports onwg0)firewall.yml- Firewall configuration (before playbooks that open UFW ports)mpd.yml- MPD installation and configurationmusikgulli_web.yml- musikgulli-web daemon (webplayers)coordinator_proxy.yml- nginx reverse proxy config (coordinator)monit.yml- Monit monitoring setup
musikgulli_web.yml
Deployt den musikgulli-web Daemon auf Hosts der Gruppe webplayers:
- Installiert die Anwendung nach
/opt/musikgulli-web(venv + App-Dateien) - Richtet den systemd-Service
musikgulli-web.serviceein (Userplayer,Restart=always) - Öffnet Port 8080 auf dem Wireguard-Interface
coordinator_proxy.yml
Deployt nginx Location-Blöcke nach /etc/nginx/snippets/webplayers/ auf
dem Coordinator (nginx ist dort bereits installiert, der bestehende
server-Block inkludiert dieses Verzeichnis):
- Web-UI der
webplayers: erreichbar unter/players/<hostname>/ - Monit Web-Interface aller
players: erreichbar unter/monit/<hostname>/(proxied auf die Wireguard-IP des Players, Port 2812)
packages.yml
Manages package installation:
- Installs
mpcpackage on all hosts - Installs
mpdpackage on all hosts in theplayersgroup
monit.yml
Installs and configures Monit monitoring on players:
- Monit package installation
- Monitoring configuration deployment
- Web interface setup (Port 2812, Wireguard only)
- Helper scripts for complex checks
Abspiel-Logik
Der musikgulli-web Daemon läuft dauerhaft auf den webplayers und übernimmt
die Steuerung des MPD-Players.
musikgulli-web (webplayers)
Der Daemon verbindet Web-UI und Steuerung in einem Prozess:
- Control-Loop: prüft alle 10 Sekunden, welche Playlist laufen soll, und
schaltet bei Bedarf um. Prioritäten:
- Für heute zugewiesene Sonder-Playlist (läuft ganztägig)
- Feiertag in Niedersachsen: aktuelle Playlist wird beibehalten
- Tag/Nacht anhand der konfigurierten Umschaltzeiten
- Web-UI (Port 8080, HTTP, ohne Authentifizierung – Zugriff nur über
Wireguard bzw. den Reverse-Proxy auf dem Coordinator):
- Anzeige des aktuellen Tracks und Play-Status
- Lautstärke-Regler (eine globale Lautstärke, unabhängig von der Playlist)
- Konfiguration der Umschaltzeiten Tag/Nacht (Default 08:00 / 20:00)
- Sonder-Playlisten: Unterordner von
/srv/music/Sonderkönnen einem Datum zugewiesen werden (die Ordnernamen sind frei wählbar, das Datumsformat im Ordnernamen wird nicht mehr benötigt)
- Konfiguration:
/etc/musikgulli/config.json(wird vom Daemon über die Web-UI geschrieben) - Zustand:
/var/lib/musikgulli/state.json(aktive Playlist; die Erkennung über die Lautstärke entfällt) - Logs: journald (
journalctl -u musikgulli-web)
Usage
To run the main playbook:
ansible-playbook -i inventory/hosts.yml site.yml
To run against specific groups:
ansible-playbook -i inventory/hosts.yml site.yml --limit players
To manage packages:
ansible-playbook -i inventory/hosts.yml packages.yml
Monit Monitoring
Monit überwacht alle kritischen Komponenten auf den Playern und stellt ein Web-Interface zur Verfügung.
Überwachte Komponenten
System-Monitoring
- CPU-Auslastung (Warnung > 80%, kritisch > 95%)
- Memory-Auslastung (Warnung > 85%, kritisch > 95%)
- Disk Space für
/(Warnung < 20%, kritisch < 10%) - Disk Space für
/srv/music(Warnung < 10%, kritisch < 5%) - System Load (Warnung > Anzahl CPUs * 1.5)
MPD Service
- Prozess-Überwachung mit automatischem Restart
- TCP Port 6600 Erreichbarkeit
- MPD Playing Check (prüft ob Musik abgespielt wird und Titel in der Queue sind)
musikgulli-web
- systemd Service
musikgulli-web.serviceStatus - HTTP-Erreichbarkeit auf Port 8080
Netzwerk & Services
- Wireguard Interface
wg0Status - Verbindung zum Coordinator (Ping)
- NFS Server (falls aktiv)
Musik-Ordner
- Existenz von
/srv/music/Tagund/srv/music/Nacht - Prüfung ob Dateien in den Ordnern vorhanden sind
- Audio-Device Verfügbarkeit
Weitere Checks
- Systemd Health (failed units)
- Zeit-Synchronisation (NTP)
Web-Interface
Das Monit Web-Interface jedes Players ist auf zwei Wegen erreichbar:
- Reverse Proxy (empfohlen):
http://<coordinator>/monit/<hostname>/– der Coordinator proxied die Anfrage über Wireguard an den Player (siehecoordinator_proxy.yml) - Direkt:
http://<player-wireguard-ip>:2812(nur aus dem Wireguard-Netzwerk 10.199.0.0/24) - Authentifizierung: Keine Passwort-Authentifizierung erforderlich (Zugriff bereits durch Wireguard-Netzwerk beschränkt)
Inventory-Variablen
Player-Gruppe (group_vars/players.yml)
E-Mail-Alerts (optional):
monit_email_enabled: false # E-Mail-Alerts aktivieren/deaktivieren
monit_smtp_host: "localhost" # SMTP-Server
monit_smtp_port: 587 # SMTP-Port
monit_smtp_username: "{{ vault_monit_smtp_username | default('') }}"
monit_smtp_password: "{{ vault_monit_smtp_password | default('') }}"
monit_smtp_tls: true # TLS verwenden
monit_email_recipient: "{{ vault_monit_email_recipient | default('admin@localhost') }}"
NFS-Konfiguration:
nfs_enabled: true # NFS-Server-Monitoring aktivieren/deaktivieren
Player-Hosts (inventory/hosts.yml)
Jeder Player benötigt folgende Variablen:
ansible_host: 10.199.0.101 # IP-Adresse des Players
ansible_user: player # SSH-User
mpd_bind_address: 10.199.0.101 # MPD Bind-Adresse
mpd_audio_output_type: alsa # Audio-Output-Typ
mpd_audio_output_device: hw:CARD=Device,DEV=0 # Audio-Device
wireguard_addresses:
- "10.199.0.101/24" # Wireguard-IP-Adresse(n)
E-Mail-Alerts konfigurieren
- Variablen in
group_vars/players.ymlsetzen:
monit_email_enabled: true
monit_smtp_host: "smtp.example.com"
monit_smtp_port: 587
monit_smtp_username: "{{ vault_monit_smtp_username }}"
monit_smtp_password: "{{ vault_monit_smtp_password }}"
monit_email_recipient: "alerts@example.com"
- Sensible Daten in Ansible Vault speichern:
ansible-vault encrypt_string 'your_password' --name 'vault_monit_smtp_password'
ansible-vault encrypt_string 'your_username' --name 'vault_monit_smtp_username'
- Playbook erneut ausführen:
ansible-playbook -i inventory/hosts.yml site.yml
Monit-Befehle
Auf dem Player direkt:
# Monit-Status anzeigen
monit status
# Alle Services überwachen
monit monitor all
# Service neu starten
monit restart <service-name>
# Konfiguration testen
monit -t
# Log anzeigen
tail -f /var/log/monit.log
Automatische Aktionen
Monit führt automatisch folgende Aktionen aus:
- MPD down: Automatischer Restart (max. 3x pro Zyklus)
- Disk Space kritisch: Alert
- Systemressourcen kritisch: Alert
- Netzwerk-Probleme: Alert