[Update 09.24]
Suite Ă cet article, Thereâs endless choice, but youâre not listeningâ: fans quitting Spotify to save their love of music, j’ai re-dĂ©couvert Navidrome que j’avais dĂ©couvert via le trĂšs bien informĂ© Korben comme souvent.
Je me suis dit que c’Ă©tait l’occasion de tester en auto-hĂ©bergĂ©, car mes musiques sont Ă©videment chez moi et surtout c’Ă©tait l’occasion de mettre en oeuvre ma nouvelle stack favorite Nomad.
Pour rappel j’avais fais une doc sur l’auto-hĂ©bergement hybride en 2017 avec Docker swarm, VPNcloud, syncthing, traefik, etc. Il faut avouer que c’Ă©tait une usine Ă gaz de l’enfer â ïž.
Heureusement si vous avez suivi mon article Une infra avec Nomad, Consul et Tailscale vous devriez pouvoir mettre en place cette V2 rapidement.
Je souhaite bĂ©nĂ©ficier des fonctionnalitĂ©s anti-DDOS des hĂ©bergeurs cloud et ainsi ne pas exposer l’IP fournie par mon FAI qui de toute façon n’est pas garantie fixe. Aussi je souhaite pouvoir hĂ©berger sur le cloud quelques services (typiquement Uptime Kuma).
Cette présentation nécessite donc deux VMs chez un hébergeur, une pour Nomad en mode serveur et client avec une IP publique, et une VM pour un serveur Consul. Leurs configurations sont indiquées dans mon précédent article.
Vous pouvez toutefois ĂȘtre en mode full auto-hĂ©bergĂ©, il suffira de faire pointer le DNS de votre domaine vers votre IP fixe et faire en sorte qu’un serveur avec caddy-docker-proxy puisse rĂ©pondre aux requĂȘtes HTTPS.
Depuis 2017 j’ai investi dans un mini PC NUC (core I3/16Go RAM, 1To SSD) qui fait l’affaire, mais un RaspberryPi avec un disque externe le fera aussi sous condition.
En effet un RaspberryPi a une architecture ARM et non pas x86, cela imposera donc des images Docker sous ce format. Navidrome a le bon goĂ»t de proposer des images Docker ARM (merci Go), il faudra choisir une des images ARM selon la version et l’OS de votre RaspberryPi (Ă priori linux/arm64 Ă partir du 4 si l’OS est en 64 bits).
Mon NUC il est installĂ© avec Manjaro car il est connectĂ© Ă la TV et sert aussi Ă voir des vidĂ©os. Aussi j’ai du appliquer la configuration suivante pour Ă©viter qu’il mette le NUC en veille au bout d’un certain temps. Bien sĂ»r si vous avez installĂ© une distribution serveur cela ne s’applique pas.
avec un terminal exécutez les commandes suivantes (source):
sudo su - gdm -s /bin/bash
dbus-launch gsettings set org.gnome.settings-daemon.plugins.power sleep-inactive-ac-type 'nothing'
exit
sudo shutdown -r now
J’utilise les paquets de Manjaro (pour d’autres OS voir l’article prĂ©cĂ©dent) :
sudo pacman -S tailscale nomad consul docker cni-plugins
tailscale login
renseignez les informations de votre compte tailscale puis vérifier avec tailscale status
récupérez votre IP tailscale avec tailscale ip
/etc/consul.d/consul.hcl
data_dir = "/var/lib/consul"
# sur Manjaro, le paquet consul créé le répertoire /var/lib/consul
# sur Ubuntu serveur c'est en général dans /opt/consul
bind_addr = "IP_TAILSCALE_NUC"
retry_join = ["IP_TAILSCALE_NODE3"]
Pour rappel selon ma précédente doc le serveur consul est installé sur le node3.
sudo systemctl enable consul
sudo systemctl start consul
/etc/nomad.d/defaults.hcl
### https://www.nomadproject.io/docs/agent/configuration/index.html
# state directory
data_dir = "/var/lib/nomad"
# sur Manjaro, le paquet nomad créé le répertoire /var/lib/nomad
# sur Ubuntu serveur c'est en général dans /opt/nomad
bind_addr = "IP_TAILSCALE_NUC"
# binaries shouldn't go in /var/lib
plugin_dir = "/usr/lib/nomad/plugins"
server {
# license_path is required for Nomad Enterprise as of Nomad v1.1.1+
#license_path = "/etc/nomad.d/license.hclic"
enabled = false
bootstrap_expect = 1
}
client {
enabled = true
servers = ["IP_TAILSCALE_NODE1"]
host_network "tailscale" {
cidr = "IP_TAILSCALE_NUC/32"
}
}
plugin "docker" {
config {
volumes {
enabled = true
}
extra_labels = ["job_name", "job_id", "task_group_name", "task_name", "namespace", "node_name", "node_id"]
}
}
consul {
address = "127.0.0.1:8500"
}
on lance Nomad
sudo systemctl enable nomad
sudo systemctl start nomad
Si tout est ok, vous devriez voir sur les interfaces web de consul et nomad votre serveur :
http://IP_TAILSCALE_NODE3:8500/ui/dc1/nodes
http://IP_TAILSCALE_NODE1:4646/ui/clients
La configuration de votre cluster Nomad est terminĂ©e, votre serveur est prĂȘt Ă recevoir des conteneurs.
Leur configuration Docker est ici. On va transformer le docker-compose au format HCL :
docker-compose:
version: "3"
services:
navidrome:
image: deluan/navidrome:latest
user: 1000:1000 # should be owner of volumes
ports:
- "4533:4533"
restart: unless-stopped
environment:
# Optional: put your config options customization here. Examples:
ND_SCANSCHEDULE: 1h
ND_LOGLEVEL: info
ND_SESSIONTIMEOUT: 24h
ND_BASEURL: ""
volumes:
- "/path/to/data:/data"
- "/path/to/your/music/folder:/music:ro"
navidrome.hcl
job "navidrome" {
datacenters = ["dc1"]
type = "service"
group "home" {
count = 1
network {
port "http" {
to = 4533 # container port the app runs on
host_network = "tailscale"
}
}
task "navidrome" {
driver = "docker"
constraint {
attribute = "${attr.unique.hostname}"
value = "nuc"
}
env {
ND_SCANSCHEDULE= "1h"
ND_LOGLEVEL = "info"
ND_SESSIONTIMEOUT = "24h"
ND_BASEURL = ""
}
config {
image = "deluan/navidrome:latest"
volumes = [
"/data/volumes/navidrome/:/data",
"/data/musiques:/music"
]
ports = [
"http"
]
}
resources {
cpu = 500
memory = 500
}
service {
name = "navidrome"
provider = "consul"
port = "http"
tags = ["allocport=${NOMAD_HOST_PORT_http}"]
}
}
}
}
datacenters = ["dc1"]
indique le nom de mon datacenter, par simplicitĂ© c’est le mĂȘme entre mes VMs sur le cloud et chez moi. Si vous avez un usage professionnel, vous pouvez indiquer un autre datacenter, mais en pratique cela nĂ©cessitera un autre serveur consul et nomad dans ce DC.
host_network = "tailscale"
cette directive force Consul a enregistrer votre service sur L’IP de Tailscale. Sans celle-ci le serveur Consul rĂ©soudrait le service navidrome.service.consul vers l’IP locale du NUC, c’est Ă dire 192.168.X.X ce qui ne fonctionnerait Ă©videmment pas.
value = "nuc"
correspond au nom de votre serveur, tapez la commande hostname
pour connaitre le votre. Cela force ainsi Nomad a déployer le conteneur Navidrome sur ce serveur.
volumes = [
"/data/volumes/navidrome/:/data",
"/data/musiques:/music"
]
indique Ă Navidrome oĂč sont les donnĂ©es. J’ai un rĂ©pertoire /data attachĂ© Ă un disque dĂ©diĂ©. Attention comme prĂ©cisĂ© dans leur doc le rĂ©pertoire /data/volumes/navidrome doit appartenir Ă l’utilisateur id 1000, donc bien exĂ©cuter cette commande avant de lancer le conteneur: sudo chown 1000:1000 /data/volumes/navidrome/
resources {
cpu = 500
memory = 500
}
indique à Nomad les ressources allouées au conteneur. A priori 500Mhz de CPU et 500Mo de RAM devraient suffir, à adapter selon votre config matériel et votre usage.
Vous pouvez maintenant lancer le job depuis votre PC perso si vous avez installĂ© tailscale, Nomad et configurĂ© la variable d’environnement NOMAD_ADDR=http://IP_TAILSCALE_NODE1:4646
. Ajouter la variable NOMAD_TOKEN
si vous avez activé les ACL sur Nomad.
nomad job run navidrome.hcl
En cas de soucis il faut aller sur l’interface web du serveur Nomad pour consulter le job :
http://IP_TAILSCALE_NODE1:4646/ui/jobs
Si tout va bien, voici l’URL pour crĂ©er votre compte Navidrome admin :
http://IP_TAILSCALE_NUC:4533/
Vous devriez avoir une joli interface web avec vos musiques prĂȘtes Ă jouer.
Une interface web c’est bien gentil mais rien de vaut un bon client natif. Navidrome propose une liste d’Apps, j’ai testĂ© Supersonic et Sublime Music disponibles tous les 2 sur Manjaro :
yay -S supersonic-desktop-bin
et yay -S sublime-music
Une petite préférence pour Supersonic en Go plutÎt que Sublime Music en python mais ce dernier est mieux intégré grùce à GTK.
Pour la connexion au service utilisez l’URL http://IP_TAILSCALE_NUC:4533/
ou celle publique (que l’on va voir maintenant) si vous vous dĂ©placez Ă l’extĂ©rieur.
Il y aurait peu d’intĂ©rĂȘt Ă utiliser cette stack si le service n’Ă©tait pas accessible depuis l’extĂ©rieur via un smartphone par exemple ou mĂȘme depuis votre laptop. On va donc crĂ©er un conteneur qui va ajouter des labels pour votre caddy-docker-proxy
job "navidrome-caddy" {
datacenters = ["dc1"]
type = "service"
group "app" {
count = 1
task "navidrome-caddy" {
driver = "docker"
constraint {
attribute = "${attr.unique.hostname}"
value = "node1"
}
template {
data = <<EOH
# as service 'navidrome' is registered in Consul
# we want to grab its 'allocport' tag
{{- range $tag, $services := service "navidrome" | byTag -}}
{{if $tag | contains "allocport"}}
{{$allocId := index ($tag | split "=") 1}}
SERVICE_PORT="{{ $allocId }}"
{{end}}
{{end}}
EOH
destination = "secrets/file.env"
env = true
}
config {
image = "fredix/sleep"
labels = {
"caddy" = "navi.fredix.xyz"
"caddy.reverse_proxy" = "http://navidrome.service.consul:${SERVICE_PORT}"
# remove the following line when you have verified your setup
# Otherwise you risk being rate limited by let's encrypt
"caddy.tls.ca" = "https://acme-v02.api.letsencrypt.org/directory"
}
}
resources {
cpu = 10
memory = 10
}
service {
name = "navidrome-caddy"
tags = ["global", "app"]
provider = "consul"
}
}
}
}
Modifiez value = "node1"
avec le hostname de votre serveur Nomad et modifiez le label caddy
vers votre domaine puis lancez le job :
nomad job run navidrome-caddy.hcl
Et voilà , votre service Navidrome est exposé sur Internet.
Pour Android j’ai testĂ© le client Ultrasonic logiciel libre en lui donnant comme URL de connexion https://navi.fredix.xyz
Vous savez maintenant auto-hĂ©berger un grand nombre de services chez vous sans devoir montez en gamme cĂŽtĂ© cloud, car les conteneurs ajoutant des labels Ă caddy-docker-proxy sont positionnĂ©s au minimum acceptĂ© par Nomad : 10Mhz et 10Mo đ
PS : Vous retrouvez mes fichiers HCL ici : https://codeberg.org/fredix/nomad
(Ce texte a été écrit avec Ghostwriter)