Peertube dans une jail FreeBSD


Suite des aventures au pays des Jails

Ce billet sera, c’est exceptionel, bilingue. Je l’ai tout d’abord écris pour le wiki du projet Peertube.

🇫🇷 En voici une version française

🇬🇧 The English version could be find here.

Une information complémentaire

 nous supposons que nous partons d’une jail fonctionnelle, avec accès au réseau et en particulier à l’extérieur du réseau local.

 si vous avez une poudriere NE L’UTILISEZ PAS. Dans notre ce cas il est préférable d’utiliser des paquets prē-compilés.

Lisez et appliquez les instructions sur les dépendances.

Veuillez lire attentivement et appliquer avec autant d’attention les instructions sur les dépendances que vous trouverez sur cette page.

Passez à la page production

La page principale pour les instructions d’installation se trouve sur cette page.

La plupart des instructions doivent être avoir exécutées avec succès avant de voir les particularités.

  • créer l’utlisateur peertube :
  • créer la base de données.

 La commande utilisée pour connaître la dernière version de Peertube fonctionne avec bash, mais pas avec csh qui est le shell par défaut de l’utilisateur root sous FreeBSD. Nous devons donc utiiser une version modifiée, que voici.

# set VERSION=`curl -s https://api.github.com/repos/chocobozzz/peertube/releases/latest | grep tag\_name | cut -d '"' -f 4` && echo "Latest Peertube version is $VERSION"
1

Puis nous utilisons la commande de téléchargement et d’extraction de la page production.

Configuration de Peertube

Rien ne change dans cette phase, lisez la documentation d’origine.

 En cas de problème avec vips8/vips.h, il va falloir compiler vips par vous même. C’est long, mais ce n’est pas compilqué. Les explications sont . Vous aurez des dépendances à installer à chaque fois que le compilation butera.

 msgfmt fait partie du paquet gettext, c’est donc lui que vous devrez installer pour résoudre cette dépendances. Une fois vips terminée, reprenez l’installation su - peertube && cd peertube-latest; npm install

Serveur web

 Voici la partie qui diffère le plus. Les répertoires /usr/local/etc/nginx/sites_available et /usr/local/etc/nginx/sites_enabled n’existe pas par défaut. Nous allons devoir les créer.

# mkdir /usr/local/etc/ngnix/sites-{available,enabled}

Puis nous copions la configuration donnée en exemple, comme cela est expliqué dans la documentation officielle.

Le problème du certificat

Imaginons que vous désirez, à terme, avoir plusieurs jail qui nécessite l’utilisation de certificats (une jail par site web par exemple). Il va être difficile de maintenir pour chacune des jails, une configuration let’s_encrypt spécifique. Nous allons plutôt laisser l’hôte gérer cela pour nous et y centraliser la gestion des certificats.

Merci de lire la documentation de dehydraded pour la génération du certificat de votre instance Peertube.  j’ai créé mes certificats avec l’ancienne commande certbot, ma configuration est légèrement différente.

Sur la machine hôte

Nous allons créer une configuration nginx. J’ai nommé la mienne peertube-jail.conf et elle se trouve dans le répertoire sites-available.  veillez à remplacer example.com par votre FQDN  veillez à remplacer w.x.y.z par l’adresse IP de votre jail

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
server {

    # First, as for all webserver, we listen to 80 port
    listen 80;

    # give our server_name
    server_name peertube.example.com;

    # create some logfiles
    access_log /var/log/nginx/peertube_access.log;
    error_log /var/log/nginx/peertube_error.log;

    # redirect permantly to https
    rewrite ^ https://$server_name/$request_uri permanent;
}

server{

    # The https part
    listen 443 ssl http2;

    # The server-name again
    server_name peertube.example.com;

    # We use the same log files as below
    access_log /var/log/nginx/peertube_access.log;
    error_log /var/log/nginx/peertube_error.log;

    # We activate the ssl engine and give it the path to the fullchain certificate
    # and the private key
    ssl on;
    ssl_certificate /usr/local/etc/letsencrypt/live/peertube.example.com/fullchain.pem;
    ssl_certificate_key /usr/local/etc/letsencrypt/live/peertube.example.com/privkey.pem;

    # The root location (/) will be redirect
    # We add some header and VERY IMPORTANT, the client_max_body_size
    # set to 4G (the maximum size peertube video)
    location / {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_pass http://w.x.y.z/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        client_max_body_size 4G;
    }

Nous déplaçons une partie de la configuration nginx DEPUIS la jail VERS la configuration nginx de l’hôte (lignes 106 à 117) :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
  # We also let the host to deal with the websocket
    # and transfer it to the jail on port 9000 (the peertube port)

    location /tracker/socket {
        # Peers send a message to the tracker every 15 minutes
        # Don't close the websocket before this time
        proxy_read_timeout 1200s;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_http_version 1.1;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;
        proxy_pass http://w.x.y.z:9000;
    }

}

Sauvegarde le fichier et faites un lien symbolique vers le répertoire sites-enabled.

# ln -s /usr/local/etc/nginx/sites_available/peertube-jail.conf /usr/local/etc/nginx/sites_enabled

Nous vérifions que la syntax du fichier de configruation est correcte :

# nginx -t
nginx: the configuration file /usr/local/etc/nginx/nginx.conf syntax is ok
nginx: configuration file /usr/local/etc/nginx/nginx.conf test is successful

On peut maintenant recharger la configuration nginx :

# nginx reload

Retour sur la jail

Nous allons faire beaucoup de modification au fichier de configuration de nginx sur la jail.

  • suppression de la configuration SSL (lignes 16 à 34) :
server {
  listen 443 ssl http2;
  listen [::]:443 ssl http2;
  server_name peertube.example.com;

  # For example with certbot (you need a certificate to run https)
  ssl_certificate      /etc/letsencrypt/live/peertube.example.com/fullchain.pem;
  ssl_certificate_key  /etc/letsencrypt/live/peertube.example.com/privkey.pem;

  # Security hardening (as of 11/02/2018)
  ssl_protocols TLSv1.2; # TLSv1.3, TLSv1.2 if nginx >= 1.13.0
  ssl_prefer_server_ciphers on;
  ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';
  # ssl_ecdh_curve secp384r1; # Requires nginx >= 1.1.0, not compatible with import-videos script
  ssl_session_timeout  10m;
  ssl_session_cache shared:SSL:10m;
  ssl_session_tickets off; # Requires nginx >= 1.5.9
  ssl_stapling on; # Requires nginx >= 1.3.7
  ssl_stapling_verify on; # Requires nginx => 1.3.7
  • suppression du bloc de la configuration des websockets (souvenez-vous, nous avons migré cette partie dans la conférence de l’hôte, lignes 106 à 117) :
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# Websocket tracker
  location /tracker/socket {
    # Peers send a message to the tracker every 15 minutes
    # Don't close the websocket before this time
    proxy_read_timeout 1200s;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_http_version 1.1;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $host;
    proxy_pass http://localhost:9000;
  }

Le fichier de configuration de nginx sur la jail est plus petit que celui initialement proposé. Le voici en intégralité.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
server {
 listen 80;
 server_name peertube.example.com;

 access_log /var/log/nginx/peertube.access.log;
 error_log /var/log/nginx/peertube.error.log;

 add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";
 add_header X-Content-Type-Options nosniff;
 add_header X-XSS-Protection "1; mode=block";
 add_header X-Robots-Tag none;

 location ^~ '/.well-known/acme-challenge' {
  default_type "text/plain";
  root /var/www/certbot;
 }

 location ~ ^/client/(.*\.(js|css|woff2|otf|ttf|woff|eot))$ {
   add_header Cache-Control "public, max-age=31536000, immutable";

   alias /var/www/peertube/peertube-latest/client/dist/$1;
 }

 location ~ ^/static/(thumbnails|avatars)/(.*)$ {
   add_header Cache-Control "public, max-age=31536000, immutable";

   alias /var/www/peertube/storage/$1/$2;
 }

 location / {
   proxy_pass http://localhost:9000;
   proxy_set_header X-Real-IP $remote_addr;
   proxy_set_header Host $host;
   proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

   # Hard limit, PeerTube does not support videos > 4GB
   client_max_body_size 4G;
   proxy_connect_timeout       600;
   proxy_send_timeout          600;
   proxy_read_timeout          600;
   send_timeout                600;
 }

 # Bypass PeerTube webseed route for better performances
 location /static/webseed {
   # Clients usually have 4 simultaneous webseed connections, so the real limit is 3MB/s per client
   limit_rate 800k;

   if ($request_method = 'OPTIONS') {
     add_header 'Access-Control-Allow-Origin' '*';
     add_header 'Access-Control-Allow-Methods' 'GET, OPTIONS';
     add_header 'Access-Control-Allow-Headers' 'Range,DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
     add_header 'Access-Control-Max-Age' 1728000;
     add_header 'Content-Type' 'text/plain charset=UTF-8';
     add_header 'Content-Length' 0;
     return 204;
   }

   if ($request_method = 'GET') {
     add_header 'Access-Control-Allow-Origin' '*';
     add_header 'Access-Control-Allow-Methods' 'GET, OPTIONS';
     add_header 'Access-Control-Allow-Headers' 'Range,DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';

     # Don't spam access log file with byte range requests
     access_log off;
   }

   alias /var/www/peertube/storage/videos;
 }

 # Websocket tracker

 ## Moved in host nginx config
}

Derniers mots

Pensez à sauvegarder vos fichiers de configuration, une mise à jour de Peertube pourrait les écraser.

Remerciments

Merci à Chocobozzz, le créateur de Peertube, à Framasoft qui porte le projet Peertube et lui donne de la visibilité, aux copines et copains m’ont aidé à comprendre certains trucs sur les jails et qui ont relu·es cet article.

Ajout du 19/06/2018

Framasoft, l’association Lyonnaise qui supporte Peertube, à lancé un crowfounding pour développer la verson 1.0 qui apportera de très nombreuses nouveautés. Si cet article vous à été utile, merci de participer à la cagnote.

  A friend wrote a how-to for OpenBSD

 we’re going to start with a working jail, with network up and access to pkg archive.

 if you have a poudriere, DON’T USE IT. It’s better to use pre-compiled package in this case.

Read and apply the dependencies instructions.

Please read and apply the instructions provided in dependencies page.

Go to the production page

The main instructions are available in the production page.

Most of the instruction MUST be done before we continue with specific instructions:

  • create the peertube user
  • create the database

 the command for knowing the latest available version works with bash, but not with csh, which is the default root shell on FreeBSD. We have to use a different method (changes are very small).

set VERSION=`curl -s https://api.github.com/repos/chocobozzz/peertube/releases/latest | grep tag\_name | cut -d '"' -f 4` && echo "Latest Peertube version is $VERSION"
2

Then we use the command to download and extract Peertube as visible in the production page.

Peertube configuration

Nothing change in this part, please read the documentation.

 In case of troubel with vips8/vips.h, you will nedd to compile it by yourself. It takes time, but it’s not so complicated. This page explain how-to. You will need to install dependencises each time the compilation will failed.

 msgfmt is part of the gettext package. You’ll need to install it to solve this depence. Once vips installation succeded, go back to peertube installation: su - peertube && cd peertube-latest; npm install

Webserver

 this is the most different part.

The /usr/local/etc/nginx/sites_available and /usr/local/etc/nginx/sites_enabled does not exist by default, we have to create them:

# mkdir /usr/local/etc/nginx/sites_{available,enabled}
Then we copy the sample nginx configuration file exactly as explained in the official documentation.

The certificate problem

We are going to suppose that you want to host several web services, each of them in a jail. It will be very difficult to maintain the let’s encrypt certificates for each of those jail. We let the main host to deal with the certificate for ALL the jails.

Please read the dehydraded documentation in order to generate your Peertube instance certificate.

 I used to use certbot. My configuration is a little bit different from the dehydraded one.

ON THE HOST

We need to create a nginx configuration. I named it peertube-jail.conf and put it in the sites_available folder..

 remember to replace example.com by your own FQDN.

 remember to replace w.x.y.z by your jail IP address.

server {

    # First, as for all webserver, we listen to 80 port
    listen 80;

    # give our server_name
    server_name peertube.example.com;

    # create some logfiles
    access_log /var/log/nginx/peertube_access.log;
    error_log /var/log/nginx/peertube_error.log;

    # redirect permantly to https
    rewrite ^ https://$server_name/$request_uri permanent;
}

server{

    # The https part
    listen 443 ssl http2;

    # The server-name again
    server_name peertube.example.com;

    # We use the same log files as below
    access_log /var/log/nginx/peertube_access.log;
    error_log /var/log/nginx/peertube_error.log;

    # We activate the ssl engine and give it the path to the fullchain certificate
    # and the private key
    ssl on;
    ssl_certificate /usr/local/etc/letsencrypt/live/peertube.example.com/fullchain.pem;
    ssl_certificate_key /usr/local/etc/letsencrypt/live/peertube.example.com/privkey.pem;

    # The root location (/) will be redirect
    # We add some header and VERY IMPORTANT, the client_max_body_size
    # set to 4G (the maximum size peertube video)
    location / {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_pass http://w.x.y.z/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        client_max_body_size 4G;
    }

We move a part of the jail FROM nginx configuration file TO the host configuration file (line 106 to 117):

    # We also let the host to deal with the websocket
    # and transfer it to the jail on port 9000 (the peertube port)

    location /tracker/socket {
        # Peers send a message to the tracker every 15 minutes
        # Don't close the websocket before this time
        proxy_read_timeout 1200s;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_http_version 1.1;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;
        proxy_pass http://w.x.y.z:9000;
    }

}

Save the file, make the link to have it in sites_enabled folder:

# ln -s /usr/local/etc/nginx/sites_available/peertube-jail.conf /usr/local/etc/nginx/sites_enabled

Check the nginx configuration (nginx do a check when restarting. but I prefer do it before)

# nginx -t
nginx: the configuration file /usr/local/etc/nginx/nginx.conf syntax is ok
nginx: configuration file /usr/local/etc/nginx/nginx.conf test is successful

If it’s you can reload nginx configuration:

# nginx -s reload

BACK TO THE JAIL

On the jails we are going to make a lot of changes in the nginx configuration.

  • remove all the ssl configuration (line 16 to 34):
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
server {
  listen 443 ssl http2;
  listen [::]:443 ssl http2;
  server_name peertube.example.com;

  # For example with certbot (you need a certificate to run https)
  ssl_certificate      /etc/letsencrypt/live/peertube.example.com/fullchain.pem;
  ssl_certificate_key  /etc/letsencrypt/live/peertube.example.com/privkey.pem;

  # Security hardening (as of 11/02/2018)
  ssl_protocols TLSv1.2; # TLSv1.3, TLSv1.2 if nginx >= 1.13.0
  ssl_prefer_server_ciphers on;
  ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';
  # ssl_ecdh_curve secp384r1; # Requires nginx >= 1.1.0, not compatible with import-videos script
  ssl_session_timeout  10m;
  ssl_session_cache shared:SSL:10m;
  ssl_session_tickets off; # Requires nginx >= 1.5.9
  ssl_stapling on; # Requires nginx >= 1.3.7
  ssl_stapling_verify on; # Requires nginx => 1.3.7
  • remove the websocket block too (line 106 to 117). Remember, we already moved this part in the host nginx configuration file.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
  # Websocket tracker
  location /tracker/socket {
    # Peers send a message to the tracker every 15 minutes
    # Don't close the websocket before this time
    proxy_read_timeout 1200s;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_http_version 1.1;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $host;
    proxy_pass http://localhost:9000;
  }

Our nginx configuration file is now a little bit smaller and will only listen on port 80. Here is mine:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
server {
  listen 80;
  server_name peertube.example.com;

  access_log /var/log/nginx/peertube.access.log;
  error_log /var/log/nginx/peertube.error.log;

  add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";
  add_header X-Content-Type-Options nosniff;
  add_header X-XSS-Protection "1; mode=block";
  add_header X-Robots-Tag none;

  location ^~ '/.well-known/acme-challenge' {
   default_type "text/plain";
   root /var/www/certbot;
  }

  location ~ ^/client/(.*\.(js|css|woff2|otf|ttf|woff|eot))$ {
    add_header Cache-Control "public, max-age=31536000, immutable";

    alias /var/www/peertube/peertube-latest/client/dist/$1;
  }

  location ~ ^/static/(thumbnails|avatars)/(.*)$ {
    add_header Cache-Control "public, max-age=31536000, immutable";

    alias /var/www/peertube/storage/$1/$2;
  }

  location / {
    proxy_pass http://localhost:9000;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

    # Hard limit, PeerTube does not support videos > 4GB
    client_max_body_size 4G;
    proxy_connect_timeout       600;
    proxy_send_timeout          600;
    proxy_read_timeout          600;
    send_timeout                600;
  }

  # Bypass PeerTube webseed route for better performances
  location /static/webseed {
    # Clients usually have 4 simultaneous webseed connections, so the real limit is 3MB/s per client
    limit_rate 800k;

    if ($request_method = 'OPTIONS') {
      add_header 'Access-Control-Allow-Origin' '*';
      add_header 'Access-Control-Allow-Methods' 'GET, OPTIONS';
      add_header 'Access-Control-Allow-Headers' 'Range,DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
      add_header 'Access-Control-Max-Age' 1728000;
      add_header 'Content-Type' 'text/plain charset=UTF-8';
      add_header 'Content-Length' 0;
      return 204;
    }

    if ($request_method = 'GET') {
      add_header 'Access-Control-Allow-Origin' '*';
      add_header 'Access-Control-Allow-Methods' 'GET, OPTIONS';
      add_header 'Access-Control-Allow-Headers' 'Range,DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';

      # Don't spam access log file with byte range requests
      access_log off;
    }

    alias /var/www/peertube/storage/videos;
  }

  # Websocket tracker

  ## Moved in host nginx config
}

Last words

Be sure to save and keep your configuration files, a Peertube update could crush them.

Thanks

Thanks to Chocobozzz who created Peertube, to Framasoft for being part of Peertube popularity, to friends who help me to understand some tricky with jail network and to reread actors.

Added on June 19th 2018

Framasoft, the French non-profit organization who support Peertube, launched a crowfounding do develop the 1.0 version with may new features If you lked this article please take time to participate.


  1. si vous voulez utiliser la commande décrite dans la documentation officielle, installez et lancez bash↩︎

  2. if you want to use the offcial documentation commande line, install and use bash↩︎

powered by FreeBSD