Une infra avec Nomad, Consul, Vault, Tailscale et Tricot : S02E01
Thu, 27 Feb 2025 22:05:12 +0100Il y a un peu plus de 1 an je dĂ©marrais une suite d’articles sur une infra architecturĂ©e autour de Nomad, Consul et Tailscale
S’en suivi des mises Ă jour Ă mesure des amĂ©liorations jusqu’au remplacement de Caddy par Tricot
Il est temps de commencer la saison 2 en ajoutant Vault
Il y a quelques semaines j’ai migrĂ© mon infra cloud (2 VMs) vers Hetzner. Scaleway est un trĂšs bon opĂ©rateur mais pour un usage personnel j’ai 3 VMs chez Hetzner avec plus de CPU/RAM et pour moins cher (17,26âŹ/mois).
Cette fois-ci j’ai :
La VM front contient le reverse proxy Tricot, un client Nomad, Consul, Tailscale et des conteneurs Docker.
La VM nomad contient 1 serveur Nomad, un client Consul et Tailscale
La VM consul contient 1 serveur Consul, un serveur Vault et un client Tailscale
Seul front possĂšde une IP public, les 3 sont reliĂ©es par un rĂ©seau interne crĂ©Ă© par l’interface web Hetzner. Il suffit d’attacher les VMs Ă ce rĂ©seau pour qu’elles obtiennent une IP interne :
pour me connecter sur les 2 VMs privĂ©es j’utilise un rebond ssh par le front :
~/.ssh/config
Host consul
HostName consul
User root
# variable utile avec le terminal Ghostty
SetEnv TERM=xterm-256color
ProxyCommand ssh -i .ssh/id_ed25519-sk root@IP_PUBLIC nc 10.0.0.3 %p
Host nomad
HostName nomad
User root
# variable utile avec le terminal Ghostty
SetEnv TERM=xterm-256color
ProxyCommand ssh -i .ssh/id_ed25519-sk root@IP_PUBLIC nc 10.0.0.4 %p
j’ai installĂ© le proxy Squid sur front pour permettre aux 2 autres VMs d’accĂ©der Ă Internet.
apt install squid
Dans /etc/squid/conf.d/debian.conf ajouter
acl localnet src 10.0.0.0/8 # RFC1918 possible internal network
acl localnet src 172.16.0.0/12 # RFC1918 possible internal network
acl localnet src 192.168.0.0/16 # RFC1918 possible internal network
acl localnet src 100.64.0.0/10 # RFC1918 possible internal network
acl localnet src fc00::/7 # RFC 4193 local private network range
acl localnet src fe80::/10 # RFC 4291 link-local (directly plugged) machines
auth_param basic program /usr/lib/squid/basic_ncsa_auth /etc/squid/users
auth_param basic realm proxy
acl authenticated proxy_auth REQUIRED
http_access allow authenticated
http_access allow localnet
http_access allow localhost
# And finally deny all other access to this proxy
http_access deny all
Créer un utilisateur
htpasswd -c /etc/squid/users un_user
relancer
systemctl restart squid
Sur nomad et consul ajouter:
/etc/environment
export http_proxy=http://un_user:PASS@10.0.0.2:3128
export https_proxy=http://un_user:PASS@10.0.0.2:3128
/etc/apt/apt.conf.d/proxy
Acquire::http::Proxy "http://un_user:PASS@10.0.0.2:3128";
Cela permet Ă APT de sortir pour mettre Ă jour le systĂšme et installer des paquets.
Docker n’est installĂ© que sur la VM front. Nomad, Consul et Vault sont installĂ©s directement dans les VMs.
Doc d’installation sur Ubuntu : Install Docker Engine on Ubuntu
Tailscale est le tuyau de cette infra en reliant toutes les VMs cloud et auto-hébergés.
Ainsi les services Nomad/Consul pourront communiquer entre eux que cela soit sur des VMs hĂ©bergĂ©es que vers des PC/raspberry Ă la maison. Rien de compliquĂ© pour l’installation il y a tout ici : https://tailscale.com/download/
Attention pour pouvoir lancer le service il faut ajouter le proxy
Sur les 2 VMs nomad et consul il faut ajouter le proxy dans le fichier
/etc/default/tailscaled
https_proxy=http://un_user:PASS@10.0.0.2:3128
sinon le tailscale up
ne fonctionnera pas depuis ces VMs privés. Ensuite affichez le status de vos noeuds Tailscale : tailscale status
Si votre infra est uniquement en cloud, Tailscale est bien entendu facultatif.
Avant d’aller plus loin on va devoir gĂ©nĂ©rer un certificat pour Vault. Pour cela on utilise le programme mkcert
# installation sur son PC Manjaro/Arch
sudo pacman -S mkcert
mkcert -cert-file IP_TAILSCALE_CONSUL.crt -key-file IP_TAILSCALE_CONSUL.key IP_TAILSCALE_CONSUL
Comme je n’utilise pas un nom de domaine je gĂ©nĂšre le certificat en utilisant l’IP Tailscale de consul. Si vous utilisez un nom remplacez l’IP par le FQDN du serveur Consul/Vault. Il faudra copier ces 2 fichiers dans le rĂ©pertoire /opt/vault/tls
mais aussi sur les serveurs et clients Nomad dans /opt/nomad/certs/
.
DĂ©ployer aussi le certificat Root ~/.local/share/mkcert/rootCA.pem
dans /usr/local/share/ca-certificates/vault-local.crt
sur les serveurs Ubuntu et dans /etc/ca-certificates/trust-source/anchors/vault-local.crt
sur Manjaro.
Puis mettre à jour la base de données : update-ca-trust
Vault permet de stocker les secrets (mots de passe, token, etc). Ainsi ils ne sont plus exposés dans les fichiers HCL.
Pour l’installation il suffit d’ajouter les dĂ©pĂŽts d’Hashicorp sur la VM consul et d’installer le paquet vault : apt install vault
La configuration
/etc/vault.d/vault.hcl
ui = true
api_addr = "https://TAILSCALE_IP_CONSUL:8200"
# le storage peut ĂȘtre aussi Consul
storage "file" {
path = "/opt/vault/data"
}
# HTTPS listener
listener "tcp" {
address = "TAILSCALE_IP_CONSUL:8200"
tls_cert_file = "/opt/vault/tls/IP_TAILSCALE_CONSUL.crt"
tls_key_file = "/opt/vault/tls/IP_TAILSCALE_CONSUL.key"
}
systemctl start vault
Sur son PC il faut ajouter la variable d’environnement VAULT_ADDR=https://TAILSCALE_IP_VAULT:8200
, ensuite on peut initialiser Vault
# ici on génÚre 5 clés de descellement et il en faudra 3 pour desceller
vault operator init -key-shares=5 -key-threshold=3
# on stocke les tokens générées dans un gestionnaire de mot de passe
# on descelle vault 3 fois avec 3 des 5 clés
vault operator unseal
# on se connecte avec la root token
vault login
# on check
vault status
# on active les secrets en version 2
vault secrets enable -version '2' 'kv'
# ou si vous préférez un path qui indique la version
# vault secrets enable -path=kv2 -version=2 kv
Maintenant que l’on a un Vault fonctionnel il faut le configurer pour que Nomad puisse y accĂ©der. On active les Workload identities qui utilisent les jwt (l’authentification avec une token est dĂ©prĂ©ciĂ©e).
Il faut préparer 3 fichiers
vault-auth-method-jwt-nomad.json
{
"jwks_url": "http://IP_TAILSCALE_NOMAD_SERVER:4646/.well-known/jwks.json",
"jwt_supported_algs": ["RS256", "EdDSA"],
"default_role": "nomad-workloads"
}
vault-role-nomad-workloads.json
{
"role_type": "jwt",
"bound_audiences": ["vault.io"],
"user_claim": "/nomad_job_id",
"user_claim_json_pointer": true,
"claim_mappings": {
"nomad_namespace": "nomad_namespace",
"nomad_job_id": "nomad_job_id",
"nomad_task": "nomad_task"
},
"token_type": "service",
"token_policies": ["nomad-workloads"],
"token_period": "30m",
"token_explicit_max_ttl": 0
}
Pour le dernier fichier il faut avant lister les mĂ©thodes d’auth
vault auth list
Path Type Accessor Description Version
---- ---- -------- ----------- -------
jwt-nomad/ jwt auth_jwt_d34481ad n/a n/a
token/ token auth_token_510d42ca token based credentials n/a
RĂ©cupĂ©rer l’accessor du jwt-nomad et le mettre dans le hcl
vault-policy-nomad-workloads.hcl
path "kv/data/{{identity.entity.aliases.auth_jwt_d34481ad.metadata.nomad_namespace}}/{{identity.entity.aliases.auth_jwt_d34481ad.metadata.nomad_job_id}}/*" {
capabilities = ["read"]
}
path "kv/data/{{identity.entity.aliases.auth_jwt_d34481ad.metadata.nomad_namespace}}/{{identity.entity.aliases.auth_jwt_d34481ad.metadata.nomad_job_id}}" {
capabilities = ["read"]
}
path "kv/metadata/{{identity.entity.aliases.auth_jwt_d34481ad.metadata.nomad_namespace}}/*" {
capabilities = ["list"]
}
path "kv/metadata/*" {
capabilities = ["list"]
}
Enfin ajoute la mĂ©thode d’auth jwt et on applique les 3 fichiers dans le Vault
vault auth enable -path 'jwt-nomad' 'jwt'
vault write auth/jwt-nomad/config '@vault-auth-method-jwt-nomad.json'
vault write auth/jwt-nomad/role/nomad-workloads '@vault-role-nomad-workloads.json'
vault policy write 'nomad-workloads' 'vault-policy-nomad-workloads.hcl'
Consul d’Hashicorp est un service qui permet entre autres d’enregistrer un nom de service (comme un DNS interne) et stocker des donnĂ©es. Sur chaque VM qui contiendra des conteneurs Docker il faut installer un client Consul et un client Nomad.
On installe le serveur Consul sur la VM consul apt install consul
, voici la configuration :
consul: /etc/consul.d/consul.hcl
datacenter = "hetzner"
data_dir = "/opt/consul"
client_addr = "IP_TAILSCALE_CONSUL"
ui_config{
enabled = true
}
server = true
bind_addr = "IP_TAILSCALE_CONSUL"
advertise_addr = "IP_TAILSCALE_CONSUL"
bootstrap_expect=1
retry_join = ["IP_TAILSCALE_CONSUL"]
ports {
grpc = 8502
}
connect {
enabled = true
}
La configuration sur front
front: /etc/consul.d/consul.hcl
datacenter = "hetzner"
data_dir = "/opt/consul"
bind_addr = "IP_TAILSCALE_FRONT"
retry_join = ["IP_TAILSCALE_CONSUL"]
nomad: /etc/consul.d/consul.hcl
datacenter = "hetzner"
data_dir = "/opt/consul"
bind_addr = "IP_TAILSCALE_NOMAD"
retry_join = ["IP_TAILSCALE_CONSUL"]
systemctl start consul
Consul propose une interface web ici : http://IP_TAILSCALE_CONSUL:8500/ui/
Une capture qui affiche mes services en cours :
On installe Nomad avec apt install nomad
(voir la doc : https://developer.hashicorp.com/nomad/install).
nomad: /etc/nomad.d/nomad.hcl
datacenter = "hetzner"
data_dir = "/opt/nomad/data"
bind_addr = "IP_TAILSCALE_NOMAD"
server {
# license_path is required for Nomad Enterprise as of Nomad v1.1.1+
#license_path = "/etc/nomad.d/license.hclic"
enabled = true
bootstrap_expect = 1
}
client {
enabled = false
servers = ["IP_TAILSCALE_NOMAD"]
}
consul {
address = "127.0.0.1:8500"
}
acl {
enabled = true
}
vault {
enabled = true
address = "https://IP_TAILSCALE_CONSUL:8200"
jwt_auth_backend_path = "jwt-nomad"
cert_file = "/opt/nomad/certs/IP_TAILSCALE_CONSUL.crt"
key_file = "/opt/nomad/certs/IP_TAILSCALE_CONSUL.key"
# Only needed in servers when transioning from the token-based flow to
# workload identities.
# create_from_role = "nomad-cluster"
create_from_role = "nomad-workloads"
# Provide a default workload identity configuration so jobs don't need to
# specify one.
default_identity {
aud = ["vault.io"]
env = true
change_mode = "restart"
file = true
ttl = "1h"
}
}
telemetry {
collection_interval = "5s",
publish_allocation_metrics = true,
publish_node_metrics = true,
prometheus_metrics = true
}
La derniÚre section active la télémétrie si on veut monitorer le serveur Nomad avec Grafana.
systemctl start nomad
lancer ensuite le bootstrap des ACL afin de gĂ©nĂ©rer des tokens d’accĂšs au serveur Nomad
nomad acl bootstrap
cette commande sort :
Accessor ID = e02bd587-1f96-f60f-c79b-4c5beadae911
Secret ID = 3fffa295-5f90-acb2-3d47-8ac7add477a6
Name = Bootstrap Token
Type = management
Global = true
Policies = n/a
Create Time = 2021-08-29 13:41:08.988749307 +0000 UTC
Create Index = 5651
Modify Index = 5651
Le secret ID est Ă sauvegarder et Ă ajouter en tant que variable d’environnement dans votre .bashrc ou .zshrc sur votre PC pour que la commande nomad puisse accĂ©der au serveur
NOMAD_ADDR=http://IP_TAILSCALE_NOMAD:4646
NOMAD_TOKEN=3fffa295-5f90-acb2-3d47-8ac7add477a6
Nomad est à installer et configurer en tant que client sur les VMs et serveurs qui devront héberger des conteneurs Docker.
front: /etc/nomad.d/nomad.hcl
datacenter = "hetzner"
data_dir = "/opt/nomad/data"
bind_addr = "IP_TAILSCALE_FRONT"
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_NOMAD"]
host_network "public" {
interface = "eth0"
}
host_network "tailscale" {
cidr = "100.64.0.0/10"
}
}
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"
}
vault {
enabled = true
address = "https://IP_TAILSCALE_CONSUL:8200"
cert_file = "/opt/nomad/certs/IP_TAILSCALE_CONSUL.crt"
key_file = "/opt/nomad/certs/IP_TAILSCALE_CONSUL.key"
}
Nomad propose une interface web qui permet de consulter les jobs en cours et l’Ă©tat des noeuds. Il suffit de se connecter sur http://IP_TAILSCALE_NOMAD:4646/ui/ et de saisir la token gĂ©nĂ©rĂ©e plus haut.
Une capture qui affiche mes conteneurs en cours
Depuis son PC on peut piloter le serveur, par exemple :
nomad node status
ID Node Pool DC Name Class Drain Eligibility Status
d89a983a default dc1 node2 <none> false eligible ready
6348bbae default dc1 node1 <none> false eligible ready
Vous verrez dans les logs des Nomad clients une erreur car il ne trouve pas le répertoire /opt/cni/bin
. En effet il a besoin de ces fichiers binaires pour déployer correctement les conteneurs notamment pour la configuration réseau. Il faut donc récupérer ici le targz selon votre plateforme https://github.com/containernetworking/plugins/releases et le décompresser dans ce répertoire sur chaque VM cliente de Nomad (inutile sur le serveur Nomad).
Plus d’infos sur la page dĂ©diĂ©e chez Hashicorp : CNI
J’ai un mini PC de type NUC sur lequel j’hĂ©berge un grand nombre de service dans des conteneurs.
Sur le NUC j’ai installĂ© Manjaro qui diffĂšre un peu d’une Ubuntu. Les fichiers de configuration ne sont pas au mĂȘme endroit.
/etc/nomad.d/defaults.hcl
datacenter = "hetzner"
Data_dir = "/var/lib/nomad"
bind_addr = "IP_TAILCALE_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_NOMAD"]
host_network "tailscale" {
cidr = "IP_TAILSCALE_NUC/32"
}
}
plugin "docker" {
config {
allow_privileged = true
# allow_caps = ["all"]
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"
}
vault {
enabled = true
address = "https://IP_TAILSCALE_CONSUL:8200"
cert_file = "/var/lib/nomad/certs/IP_TAILSCALE_CONSUL.crt"
key_file = "/var/lib/nomad/certs/IP_TAILSCALE_CONSUL.key"
}
En théorie on devrait changer la valeur de datacenter = "hetzner"
et mettre par exemple datacenter = "home"
. Mais pour cela il faudrait un serveur ou une VM dĂ©diĂ©e et configurer ce Nomad en serveur. C’est ce que j’ai fait en environnement professionnel avec 1 serveur Nomad par site et qui forment un cluster. Pour un usage personnel pour simplfier je n’utilise qu’un datacenter pour tous mes sites et donc 1 unique serveur Nomad.
Idem pour Consul qui est configuré ici comme client
/etc/consul.d/consul.hcl
datacenter = "hetzner"
data_dir = "/var/lib/consul"
bind_addr = "IP_TAILSCALE_NUC"
retry_join = ["IP_TAILSCALE_CONSUL"]
Avant de lancer des services il faut un serveur web sur front. Tricot est un reverse proxy qui utilise Consul pour automatiquement faire un reverse HTTPS vers un service enregistré dans Consul. Pour cela il scrute les nouveaux tags qui commencent par tricot
, gĂ©nĂšre un certificat Let’s Encrypt et applique le reverse.
A savoir que Tricot ne gĂšre pas les autres certificats, achetĂ©s ou gĂ©nĂ©rĂ©s. Dans un environnement oĂč Let’s Encrypt n’est pas utilisĂ© j’utilise Caddy.
tricot.hcl
job "tricot" {
datacenters = ["hetzner"]
type = "service"
group "proxy" {
count = 1
network {
mode = "bridge"
port "internal" {
static = 9334
to = 9334
host_network = "tailscale"
}
port "http-public" {
static = 80
to = 80
host_network = "public"
}
port "https-public" {
static = 443
to = 443
host_network = "public"
}
}
restart {
attempts = 2
interval = "2m"
delay = "30s"
mode = "fail"
}
task "tricot" {
driver = "docker"
constraint {
attribute = "${attr.unique.hostname}"
value = "front"
}
config {
image = "fredix/tricot"
volumes = [
"secrets:/etc/tricot",
]
ports = ["internal", "http-public", "https-public"]
}
resources {
cpu = 1000
memory = 2000
}
template {
data = <<EOH
TRICOT_NODE_NAME={{ env "attr.unique.hostname" }}
TRICOT_LETSENCRYPT_EMAIL=fredix@protonmail.com
TRICOT_ENABLE_COMPRESSION=true
TRICOT_CONSUL_HOST=http://IP_TAILSCALE_CONSUL:8500
TRICOT_CONSUL_TLS_SKIP_VERIFY=true
TRICOT_HTTP_BIND_ADDR=[::]:80
TRICOT_HTTPS_BIND_ADDR=[::]:443
TRICOT_METRICS_BIND_ADDR=[::]:9334
RUST_LOG=tricot=info
EOH
destination = "secrets/env"
env = true
}
service {
name = "tricot-http"
provider = "consul"
port = "http-public"
}
service {
name = "tricot-https"
provider = "consul"
port = "https-public"
}
service {
name = "tricot-metrics"
provider = "consul"
port = "internal"
}
}
}
}
nomad job run tricot.hcl
Tricot est lancĂ© sur la VM front et utilise l’interface publique et l’interface de Tailscale ce qui lui permet d’accĂ©der aux services dans le rĂ©seau Tailscale.
Si tout va bien votre infra est prĂȘte (sinon postez vos commentaires). Voici 4 exemples de services et les 2 derniers qui utilisent Vault.
Un premier exemple avec un service auto-hébergé : Navidrome
navidrome.hcl
job "navidrome" {
datacenters = ["hetzner"]
type = "service"
group "home" {
count = 1
network {
port "http" {
to = 4533 # container port the app runs on
# static = 4533 # host port to expose
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 = 200
memory = 500
}
service {
name = "navidrome"
provider = "consul"
port = "http"
tags = ["tricot navi.fredix.xyz"]
}
}
}
}
nomad job run navidrome.hcl
: le job est lancé et le service est aussitÎt en prod.
Autre exemple avec Uptime Kuma qui est lui lancé dans la VM front
uptimekuma.hcl
job "uptimekuma" {
datacenters = ["hetzner"]
type = "service"
group "app" {
count = 1
network {
port "http" {
to = 3001 # container port the app runs on
}
}
task "uptimekuma" {
driver = "docker"
constraint {
attribute = "${attr.unique.hostname}"
value = "front"
}
config {
image = "louislam/uptime-kuma"
volumes = [
"/data/nomad/uptimekuma:/app/data"
]
ports = [
"http"
]
}
resources {
cpu = 500
memory = 512
}
service {
name = "uptimekuma"
provider = "consul"
port = "http"
tags = ["tricot uptimekuma.fredix.xyz"]
check {
type = "http"
name = "app_health"
path = "/"
interval = "20s"
timeout = "10s"
}
}
}
}
}
Premier exemple Vault avec Radicle (forge logicielle en P2P).
job "radicle" {
datacenters = ["hetzner"]
type = "service"
group "app" {
count = 1
network {
port "node" {
to = 8776 # container port the app runs on
static = 8776 # host port to expose
}
port "http" {
to = 8080 # container port the app runs on
# static = 8181 # host port to expose
}
}
task "node" {
driver = "docker"
constraint {
attribute = "${attr.unique.hostname}"
value = "front"
}
vault {}
template {
data = <<EOF
{{ with secret "kv/data/default/radicle" }}
RAD_PASSPHRASE = "{{ .Data.data.RAD_PASSPHRASE }}"
{{ end }}
RUST_LOG = "info"
RUST_BACKTRACE = 1
GIT_TRACE = 1
GIT_TRACE_PACKET = 1
EOF
destination = "secrets/file.env"
env = true
}
config {
image = "fredix/radicle-node:1.1.0"
volumes = [
"/data/nomad/radicle/node:/root"
]
ports = [
"node"
]
}
resources {
cpu = 500
memory = 500
}
service {
name = "radicle-node"
tags = ["global", "app"]
provider = "consul"
port = "node"
}
}
task "httpd" {
driver = "docker"
constraint {
attribute = "${attr.unique.hostname}"
value = "front"
}
env {
RUST_LOG = "info"
RUST_BACKTRACE = 1
}
config {
image = "fredix/radicle-httpd:0.18.0"
mounts = [
{
type = "bind"
target = "/root"
source = "/data/nomad/radicle/node"
readonly = true
bind_options = {
propagation = "rshared"
}
}
]
ports = [
"http"
]
}
resources {
cpu = 256
memory = 64
}
service {
name = "radicle"
provider = "consul"
port = "http"
tags = ["tricot seed.fredix.xyz"]
check {
type = "http"
name = "app_health"
path = "/api/v1"
interval = "20s"
timeout = "10s"
}
}
}
}
}
Mon noeud Radicle a besoin d’une passphrase pour dĂ©marrer. J’ai d’abord ajoutĂ© le passe en ligne de commande dans Vault
vault kv put -mount 'kv' 'default/radicle' 'RAD_PASSPHRASE=PASS'
vault kv get kv/default/radicle
nomad job run radicle.hcl
Dans le template j’extrait le mot de passe de Vault et le stocke dans la variable d’environnement RAD_PASSPHRASE
LND est un service basĂ© sur Bitcoin (pour simplifier). Peu importe si cela ne vous intĂ©resse pas, c’est un 2Ăšme exemple avec Vault.
Au démarrage LND a besoin de mot de passe pour ouvrir son coffre sinon le service reste scellé et ne peut pas effecturer de transaction.
lnd.hcl
job "lnd" {
datacenters = ["hetzner"]
type = "service"
group "app" {
count = 1
network {
port "tcp" {
to = 9735 # container port the app runs on
static = 9735 # host port to expose
}
port "rest" {
to = 8081 # container port the app runs on
static = 8081 # host port to expose
host_network = "tailscale"
}
port "grpc" {
to = 10009 # container port the app runs on
static = 10009 # host port to expose
host_network = "tailscale"
}
dns {
servers = ["172.17.0.1", "8.8.8.8", "8.8.4.4"]
}
}
task "lnd" {
driver = "docker"
constraint {
attribute = "${attr.unique.hostname}"
value = "front"
}
vault {}
template {
data = <<EOH
#!/bin/bash
chmod 400 /secrets/file.env
CONTAINER_IP=$(ip route get 1.2.3.4 | awk '{print $7}')
lnd --bitcoin.mainnet --bitcoin.node=neutrino --neutrino.addpeer=btcd0.lightning.engineering
--fee.url=https://nodes.lightning.computer/fees/v1/btc-fee-estimates.json --restlisten=${CONTAINER_IP}:8081
--rpclisten=${CONTAINER_IP}:10009 --tlsextraip=IP_TAILSCALE_FRONT --tlsextradomain=lnd --externalip=IP_PUBLIC_VM
--alias=fredix.xyz --protocol.zero-conf --protocol.option-scid-alias --wallet-unlock-password-file=/secrets/file.env
EOH
destination = "local/file.sh"
}
template {
data = <<EOF
{{ with secret "kv/data/default/lnd" }}{{ .Data.data.unlock }}{{ end }}
EOF
destination = "secrets/file.env"
change_mode = "restart"
}
config {
image = "lightninglabs/lnd:v0.18.5-beta"
entrypoint = [
"bash",
"-c",
"chmod 777 /local/file.sh && ./local/file.sh",
]
volumes = [
"/data/nomad/lnd:/root/.lnd"
]
ports = [
"tcp", "rest", "grpc"
]
}
resources {
cpu = 500
memory = 600
}
service {
name = "lnd"
tags = ["global", "app"]
provider = "nomad"
port = "tcp"
}
service {
name = "lnd"
tags = ["global", "app"]
provider = "nomad"
port = "rest"
}
service {
name = "lnd"
tags = ["global", "app"]
provider = "nomad"
port = "grpc"
}
}
}
}
Avant de lancer le service j’ajoute le mot de passe du service LND
vault kv put -mount 'kv' 'default/lnd' 'unlock=PASS
vault kv get kv/default/lnd
nomad job run lnd.hcl
GrĂące au template with secret
Nomad rĂ©cupĂšre le mot de passe et l’Ă©crit dans le fichier secrets/file.env
. Ensuite le premier template a accĂšs Ă ce fichier et le fourni en paramĂštre de LND : --wallet-unlock-password-file=/secrets/file.env
Pour dĂ©ployer automatiquement n’importe quel service en sous-domaine j’ai positionnĂ© que 2 lignes dans ma configuration DNS de mon domaine chez bookmyname
* 10800 A IP_PUBLIC_HETZNER
@ 10800 A IP_PUBLIC_HETZNER
C’Ă©tait un condensĂ© de mes prĂ©cĂ©dents Ă©pisodes de la saison 1.
Vous trouverez sur codeberg mes scripts hcl (bientĂŽt Ă jour) : https://codeberg.org/fredix/nomad
quelques liens :
Introduction to HashiCorp Nomad
Why you should take a look at Nomad before jumping on Kubernetes
How and why to use Nomad for orchestration at your startup
Nomad vs Kubernetes without the complexity
The Two Million Container Challenge