Linux things 🐧

un blog sur les technologies des logiciels libres et autres digressions

Peertube

Installation d'une instance Peertube

Thu, 19 Sep 2024 12:09:30 +0200
# peertube   # nomad   # postmarketOS   # auto-hebergement  

Introduction

Je voulais publier une vidéo de 42Mo de mon ancien smartphone Google pixel 3a sous postmarketOS, un système Linux dédié aux smartphone, mais où ça ?
Dans un précédent article sur mon serveur de blog Gibson j’ai utilisé un bucket S3 pour stocker de la vidéo, j’aurais pu utiliser cela mais cela peut revenir cher si j’ai d’autres vidéos à stocker. Or il existe un logiciel libre qui permet d’auto-héberger ses vidéos et les rendre public façon Youtube : PeerTube

PeerTube

Ce projet est développé depuis 6 ans et financé par l’association Framasoft grâce à des dons. Techniquement il a le gros avantage de supporter le protocole Bittorrent afin que chaque spectateur participe au streaming d’une vidéo, sans cela un instance Peertube pourrait s’écrouler sous la charge (petite correction, PeerTube n’utilise plus Bittorrent mais du HLS with P2P).

Il faut bien comprendre qu’il n’y a qu’un Google (ou Amazon) qui peut absorber l’énorme charge que peut générer le succès d’une vidéo grâce à leurs fermes de millions de serveurs (Plateforme Google).

Après le streaming audio avec Navidrome pourquoi pas tester sur mon NUC le streaming vidéo ?

Nomad

Comme d’habitude l’installation a été rapidement déployée grâce à Nomad hormis quelques paramétrages pour migrer le docker-compose vers un fichier hcl (merci à @Chocobozzz pour son aide).

peertube.hcl

job "peertube" {
  datacenters = ["dc1"]
  type = "service" 
  group "home" {
     count = 1

     network {
        mode = "bridge"
        port "http" {
            to     = 9000 # container port the app runs on
            host_network = "tailscale"
        }
      	port "postgresql" {
        	to = 5432 # container port the app runs on
      	}
      	port "redis" {
      	    to     = 6379 # container port the app runs on
      	}
      }


     task "peertube" {
     		driver = "docker"

		constraint {
			attribute = "${attr.unique.hostname}"
			value     = "nuc"
		}

		env {
			PEERTUBE_WEBSERVER_HOSTNAME = "video.fredix.xyz"
			PEERTUBE_WEBSERVER_PORT = 443
			PEERTUBE_WEBSERVER_HTTPS = true
			PEERTUBE_TRUST_PROXY = "['127.0.0.1', 'loopback', 'TAILSCALE_IP_NUC', 'TAILSCALE_IP_NODE1']"
			PEERTUBE_SECRET =	"SECRET_A_CHANGER"
			PEERTUBE_DB_USERNAME = "peertube"
			PEERTUBE_DB_PASSWORD = "PASSWORD_A_CHANGER"
			PEERTUBE_DB_HOSTNAME = "127.0.0.1"
			PEERTUBE_ADMIN_EMAIL = "fredix@protonmail.com"
			PEERTUBE_REDIS_HOSTNAME = "127.0.0.1"								
		}

		config {
			image = "chocobozzz/peertube:production-bookworm"
			force_pull = true

			volumes = [
				"/data/volumes/peertube/data:/data",
				"/data/volumes/peertube/config:/config"					 
			]				

			ports = [
				"http"
			]
		}

		resources {
				cpu = 1000
				memory = 2048
		}

		service {
			name = "peertube-web"
			provider = "consul"
			port = "http"

			tags = ["allocport=${NOMAD_HOST_PORT_http}"]

			check {
				type = "http"
				name = "app_health"
				path = "/"
				interval = "120s"
				timeout = "10s"
			}
		}
     	}


    task "postgresql" {
      driver = "docker"

      constraint {
        attribute = "${attr.unique.hostname}"
        value     = "nuc"
      }

      env {
        POSTGRES_USER = "peertube"
        POSTGRES_PASSWORD = "PASSWORD_A_CHANGER"
        POSTGRES_DB = "peertube"
      }


      config {
        image = "postgres:13-alpine"

        mounts = [
          {
                type = "bind"
                target = "/var/lib/postgresql/data"
                source = "/data/volumes/peertube/postgresql"
                readonly = false
                bind_options = {
                  propagation = "rshared"
                }
            },
          {
                type = "bind"
                target = "/dump"
                source = "/data/volumes/peertube/dump"
                readonly = false
                bind_options = {
                  propagation = "rshared"
                }
            }
        ]

        ports = ["postgresql"]
      }

        resources {
          cpu = 1000
          memory = 1000
        }


        service {
          name = "peertube-postgresql"
          provider = "consul"
          port = "postgresql"

          tags = ["alloc=${NOMAD_ALLOC_ID}"]
        }

    }

     task "redis" {
     		driver = "docker"

				constraint {
				 attribute = "${attr.unique.hostname}"
				 value     = "nuc"
				}

				config {
					image = "redis:6-alpine"

					mounts = [
						{
						    type = "bind"
						    target = "/data"
						    source = "/data/volumes/peertube/redis"
						    readonly = false
						    bind_options = {
						        propagation = "rshared"
						    }
						}
					]

				   ports = [
				      "redis"
				   ]			   								
				}

				resources {
				   cpu = 400
				   memory = 254
				}

				service {
					name     = "peertube-redis"
					provider = "consul"
					port     = "redis"
				}      
     	}


#     task "peertube-postfix" {
#     		driver = "docker"

#				constraint {
#				 attribute = "${attr.unique.hostname}"
#				 value     = "nuc"
#				}

#				config {
#						image = "mwader/postfix-relay"

#						mounts = [
#						  {
#						        type = "bind"
#						        target = "/etc/opendkim/keys"
#						        source = "/data/volumes/peertube/opendkim/keys"
#						        readonly = false
#						        bind_options = {
#						          propagation = "rshared"
#						        }
#						    }
#						]
#
#				   ports = [
#				      "redis"
#				   ]			   								
#				}
#
#				resources {
#				   cpu = 400
#				   memory = 128
#				}
#
#				service {
#					name     = "peertube-postfix"
#					provider = "consul"
#				}      
#     	}


  }
}

nomad job run peertube.hcl

Si vous avez suivi les précédents épisodes de mes articles sur Nomad cela devrait être clair. J’ai laissé en commentaire la partie qui concerne Postfix car j’ai une instance perso qui n’a pas vocation à envoyer des emails et de toute manière j’ai aucune envie de mettre les mains dans la gestion d’un relai mail 🤮
Les 3 variables suivantes sont importantes :

PEERTUBE_WEBSERVER_HOSTNAME = "video.fredix.xyz"
PEERTUBE_WEBSERVER_PORT = 443
PEERTUBE_WEBSERVER_HTTPS = true

car elles sont utilisés par le javascript dans le navigateur du visiteur pour se connecter à votre instance Peertube. Ne pas oublier PEERTUBE_ADMIN_EMAIL sinon Peertube plantera à l’installation. A noter la présence de la directive force_pull = true qui va imposer un téléchargement de l’image docker au lancement du job. Ou bien utilisez le tag v6.3.0-bookworm plutôt que production-bookworm sinon votre instance ne se mettra pas à jour s’il y a un changement de version car elle prendra l’image en locale. Évidemment je n’utilise pas le serveur web nginx du docker-compose car Caddy fait le travail.

peertube-caddy.hcl

job "peertube-caddy" {
  datacenters = ["dc1"]
  type = "service" 
  group "app" {
     count = 1

     task "peertube-caddy" {
     		driver = "docker"

			constraint {
			 attribute = "${attr.unique.hostname}"
			 value     = "node1"
			}

      template {
        data = <<EOH
				# as service 'peertube-web' is registered in Consul
				# we want to grab its 'allocport' tag
				# set a default value
				SERVICE_PORT=0				
				{{- range $tag, $services := service "peertube-web" | 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" = "video.fredix.xyz"
					"caddy.reverse_proxy" = "http://peertube-web.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 = "peertube-caddy"
			    tags = ["global", "app"]
			    provider = "consul"
			}
     	}
  }
}

nomad job run peertube-caddy.hcl

Cette configuration utilise la méthode de gestion automatique des ports entre Nomad et Caddy, voir Nomad et Caddy. Cela implique que si vous devez relancer les conteneurs de Peertube, il faudra avant stopper le conteneur peertube-caddy et le relancer après, car sinon il ne verra plus la variable SERVICE_PORT.
Si vous souhaitez rester simple utilisez l’ancienne méthode qui fixe un port à l’intance Peertube, pour cela remplacez dans la section network de peertube.hcl

port "http" {
            to     = 9000 # container port the app runs on
            host_network = "tailscale"
            }

par

port "http" {
            to     = 9000 # container port the app runs on
            static = 9000 # Ou un autre port si le 9000 est déjà occupé chez vous
            host_network = "tailscale"
            }

Et dans peertube-caddy.hcl

remplacez

"caddy.reverse_proxy" = "http://peertube-web.service.consul:${SERVICE_PORT}"

par

"caddy.reverse_proxy" = "http://peertube-web.service.consul:9000"

supprimez au passage la section template devenue inutile.

postmarketOS

Et voici ma première vidéo embarquée de mon instance Peertube video.fredix.xyz avec un Google Pixel 3a

Ici j’ai installé l’environnement de bureau Phosh mais d’autres interfaces sont disponibles.

Comme on peut le voir le boot est long et l’interface pas très fluide, mais ça reste impressionnant ! Je sais que certains l’utilisent depuis plusieurs années sur leur smartphone principal 😎
Le store d’applications GNOME est disponible mais toutes les applications ne sont pas encore adaptées à un écran de smartphone.

A savoir que postmarketOS est un système pur Linux basé sur Alpine et n’a rien à voir avec d’autres projets comme LineageOS et murena basés sur Android. C’est à mon avis prometteur et peut devenir une réelle alternative à Android. On peut malgré tout installer des applications Android provenant de F-Droid en installant Waydroid.
Évidemment tout cela est complexe à installer et hors de portée du néophite pour le moment, mais comme Linux sur PC dans les années 2000 😅

Liens

(Ce texte a été écrit avec VNote)