Archives de la liste h​e​b​e​r​g​e​m​e​n​t​@p​a​h​e​k​o​.c​l​o​u​d​

Installation de Paheko en multi-sites

emmanuel.courcelle at zaclys.net via hebergement

22/12/2023 21:10:40

Bonjour Bohwaz

Je suis Emmanuel, du Pic. Nous nous sommes rencontrés au camp chatons 
début Août, et nous avions évoqué la possibilité d'installer paheko en 
multi-sites chez nous. Je m'y suis finalement attelé, et je crois que je 
suis arrivé à quelque chose qui fonctionne. Mais bien sûr j'ai quelques 
questions...


          1/ les caches

Notre architecture est décrite ici: 
https://framagit.org/pic-manu/houaibe Tous les services tournent dans 
des conteneurs qui se trouvent derrière un reverse proxy. Paheko ne fait 
pas exception à la règle, il se trouve donc dans un conteneur, dans le 
même conteneur on a un serveur web apache. Par sécurité, le volume 
système du conteneur (le /) est monté en read-only, et les quelques 
répertoires dans lesquels apache a besoin d'écrire montent des volumes 
"tmpfs". Paheko est dans le répertoire /src, qui est donc readonly. Du 
coup, j'ai rencontré quelques soucis avec les caches:

  * Le shared cache se trouve dans /tmp, j'ai simplement modifié la
    constante SHARED_CACHE_ROOT de config.local.php pour le mettre sur
    /tmp (un tmpfs en rw) et ça marche très bien
  * Par contre lors de la première connexion sur la première association
    (appelons-la asso1), paheko essaie de créer un répertoire
    */src/www/.cache*, qui est en fait un lien symbolique vers
    */src/data/users/asso1/cache* comme je l'ai vu en retirant
    l'attribut read-only du volume système. Je trouve cela un peu
    bizarre, car du coup toutes les assos utilisent le cache de asso1.
    Et si plus tard asso1 disparaît, tout le monde se retrouvera en
    rade. Et ça ne pouvait pas marcher chez nous (à cause du read-only),
    donc j'ai monté un tmpfs sur */src/www/.cache* Un second cache
    partagé, donc.

Bon, ça fonctionne, mais est-ce bien comme ça qu'on est censé faire ? 
Pourquoi ce répertoire .cache, alors qu'il y a déjà un cache partagé et 
un cache par association ?


          2/ Les urls:

Actuellement, une asso appelée asso1 a obligatoirement comme url un truc 
genre *https://asso1.le-pic.org* Or, je pense que certaines associations 
qui disposent de leur nom de domaine aimeraient bien avoir plutôt 
quelque chose dans le genre *https://paheko.asso1.org* Est-ce qu'il est 
possible d'avoir des urls quelconques à l'intérieur d'une installation 
paheko multisites ?


          3/ Les sauvegardes:

Nous sauvegardons le serveur quotidiennement. Pour sauvegarder les bases 
de données mariadb, nous commençons par faire un dump, ensuite nous 
sauvegardons le dump. Mais nous ne sauvegardons jamais les fichiers de 
la base de données eux-mêmes, car il faudrait pour cela arrêter le 
moteur sous peine d'avoir des soucis en copiant des fichiers ouverts et 
donc incohérents. D'autres applications (Nextcloud notamment) sont mises 
en maintenance le temps de la sauvegarde. Faut-il prendre des 
précautions similaires lors des sauvegardes de Paheko, ou est-ce que 
nous pouvons simplement sauvegarder les fichiers .sqlite sans risque 
d'avoir des fichiers corrompus si quelqu'un travaille au moment de la 
sauvegarde ? Pareil pour les mises à jour: mon idée serait de faire un 
tar de */src/data/users* avant de mettre à jour afin de pouvoir revenir 
en arrière ne cas de souci. Mais est-ce que effectivement on pourra 
revenir en arrière ?

Voilà, c'est tout pour l'instant !

En te souhaitant de bonnes fêtes de fin d'année

Emmanuel

Installation de Paheko en multi-sites

BohwaZ/Paheko

22/12/2023 22:39:52

>   * Le shared cache se trouve dans /tmp, j'ai simplement modifié la
>     constante SHARED_CACHE_ROOT de config.local.php pour le mettre sur
>     /tmp (un tmpfs en rw) et ça marche très bien

Non dans la config par défaut du multi-user, le cache partagé est bien
dans un répertoire "cache" à la racine de l'hébergement.

Tu peux mettre ça n'importe où, mais si tu met dans un tmpfs, le cache
devra être reconstruit quand ton tmpfs sera vidé (par exemple après un
reboot). Pas très grave. L'intérêt du shared cache c'est que
normalement il reste dans l'opcache, donc moins de RAM/CPU utilisé pour
tout le monde :)

>   * Par contre lors de la première connexion sur la première
> association (appelons-la asso1), paheko essaie de créer un répertoire
>     */src/www/.cache*, qui est en fait un lien symbolique vers
>     */src/data/users/asso1/cache* comme je l'ai vu en retirant
>     l'attribut read-only du volume système. Je trouve cela un peu
>     bizarre, car du coup toutes les assos utilisent le cache de asso1.
>     Et si plus tard asso1 disparaît, tout le monde se retrouvera en
>     rade. Et ça ne pouvait pas marcher chez nous (à cause du
> read-only), donc j'ai monté un tmpfs sur */src/www/.cache* Un second
> cache partagé, donc.
> 
> Bon, ça fonctionne, mais est-ce bien comme ça qu'on est censé faire ? 
> Pourquoi ce répertoire .cache, alors qu'il y a déjà un cache partagé
> et un cache par association ?

Le cache partagé mentionné plus haut stocke des fichiers PHP, générés à
partir du code Smarty ou Brindille. Cela évite de re-parser les
templates à chaque fois.

Le répertoire .cache stocke le cache statique du site web.

Par défaut, si tu utilise Apache, quand tu consulte une page du site
web en mode visiteur (sans être connecté à l'admin), la page générée
(le HTML) est stocké dans le cache web, par défaut /data/cache/web/[hash
du host]/[hash de l'URL].html

Si tu consulte un fichier public (image, document, etc.), un lien
symbolique est créé dans /data/cache/web/[hash du host]/[hash de l'URL]

Ensuite via le .htaccess, Apache va détecter que la page HTML, ou le
fichier en lien symbolique, existe dans le cache, et le renvoyer
directement, sans faire appel à PHP.

Ça permet à Paheko d'être extrêmement rapide et léger, si une
association voit un afflux soudain de visites sur son site, ton serveur
ne sera pas aussi surchargé.

En effet utiliser le cache web permet de diviser la charge par 10 à 20.

Pour que ça fonctionne cependant, il faut que Apache puisse accéder au
fichier, et pour cela il faut qu'il soit dans le DOCUMENT_ROOT. D'où le
lien symbolique dans /www/.cache/

Note : le cache ne concerne pas les utilisateurs connectés, et le cache
des pages web est mis à jour toutes les heures.

La configuration par défaut de Paheko est conçue pour fonctionner "sans
rien faire" sur un hébergement mutualisé type Ouvaton, OVH, etc. D'où
le fait que Paheko essaye de créer le lien symbolique par lui-même s'il
n'existe pas.

Si tu héberge plusieurs instances Paheko, alors il est plus intéressant
d'utiliser un cache web partagé, en configurant la constante
WEB_CACHE_ROOT :

const WEB_CACHE_ROOT = '/path/to/hosted/pahekos/cache/web/%host%';

À toi de créer le lien symbolique ensuite, si tu ne donne pas le droit
à Paheko de le faire automatiquement.

Donc ta config fonctionne, mais du coup si ton cache web partagé est
monté sur …/src/www/.cache/ alors il faut le dire aussi à Paheko, qu'il
écrive au bon endroit :

const WEB_CACHE_ROOT = '…/src/www/.cache/%host';

Pourquoi ça n'est pas un sous-répertoire du cache shared ? Car lors
d'une mise à jour, on efface le cache shared, pour être sûr que si un
template à changé, on n'utilise pas une ancienne version encore en
cache qui provoquerait éventuellement des erreurs. Donc on ne veut pas
forcément effacer le cache web en même temps.

>           2/ Les urls:
> 
> Actuellement, une asso appelée asso1 a obligatoirement comme url un
> truc genre *https://asso1.le-pic.org* Or, je pense que certaines
> associations qui disposent de leur nom de domaine aimeraient bien
> avoir plutôt quelque chose dans le genre *https://paheko.asso1.org*
> Est-ce qu'il est possible d'avoir des urls quelconques à
l'intérieur
> d'une installation paheko multisites ?

Oui tu fait comme tu veux, c'est exactement ça qu'on fait sur
Paheko.cloud : on rajoute juste un vhost qui pointe au bon endroit pour
chaque domaine "custom". Exemple :

<VirtualHost *:443>
ServerName kd2.org

DocumentRoot ${PAHEKO_ROOT}/src/paheko/src/www
DirectoryIndex index.php

SSLEngine On
SSLUseStapling On
SSLCertificateFile ${PAHEKO_ROOT}/conf/certs/certs/kd2.org/fullchain.pem
SSLCertificateKeyFile
${PAHEKO_ROOT}/conf/certs/certs/kd2.org/privkey.pem
</VirtualHost>

>           3/ Les sauvegardes:
> 
> Nous sauvegardons le serveur quotidiennement. Pour sauvegarder les
> bases de données mariadb, nous commençons par faire un dump, ensuite
> nous sauvegardons le dump. Mais nous ne sauvegardons jamais les
> fichiers de la base de données eux-mêmes, car il faudrait pour cela
> arrêter le moteur sous peine d'avoir des soucis en copiant des
> fichiers ouverts et donc incohérents. D'autres applications
> (Nextcloud notamment) sont mises en maintenance le temps de la
> sauvegarde. Faut-il prendre des précautions similaires lors des
> sauvegardes de Paheko, ou est-ce que nous pouvons simplement
> sauvegarder les fichiers .sqlite sans risque d'avoir des fichiers
> corrompus si quelqu'un travaille au moment de la sauvegarde ?

La théorie : il ne faut pas faire juste une copie du fichier .sqlite
car il peut être écrit en même temps et donc tu peux copier un fichier
corrompu.

C'est documenté dans la doc SQLite :
https://www.sqlite.org/howtocorrupt.html

Et ici : https://litestream.io/alternatives/cron/

Donc tu es censé créer une copie via l'API de backup de SQLite :
sqlite3 association.sqlite "VACUUM INTO 'backup.sqlite'"
Et ensuite faire un backup de ce fichier "backup.sqlite".

Tu peux aussi préférer faire un dump :
sqlite3 association.sqlite .dump > backup.sql

Qui te donnera toutes les commandes SQL pour re-créer la BDD.

De cette manière tu aura 100% de chances que ton "backup.sqlite" n'est
pas corrompu.

Si tu fait un snapshot (par exemple avec btrfs, ZFS ou LVM) et non un
"cp" (ou rsync/borg/etc.) alors ce n'est pas nécessaire, le risque étant
qu'avec une copie normale, tu commence à copier le fichier, mais avant
que tu n'ait finit de copier jusqu'à la fin, un process modifie le
reste du fichier : tu te retrouve avec des bouts de l'ancienne version
et des bouts de la nouvelle version.

Avec un snapshot instantané type copy-on-write, le problème n'existe
pas.

Donc une autre solution c'est de faire un snapshot et de faire un
backup de ce snapshot, vu qu'il ne peut plus être modifié.

Ça t'évite de faire un script qui fait un "VACUUM INTO" de chaque base
de données.

Je conseille de toutes façons le snapshot, car tu peux aussi avoir des
problèmes de synchro avec les fichier du cache, ou les fichiers de
l'association si tu as choisis de les stocker en dehors de SQLite.

Il est à noter que tout cela ne concerne que les fichier
"association.sqlite".

Tous les autres fichiers ".sqlite" sont des sauvegardes créées par
Paheko, aucun processus n'écrit dedans, donc il est possible de juste
les copier/rsync/etc. sans risque.

> Pareil
> pour les mises à jour: mon idée serait de faire un tar de
> */src/data/users* avant de mettre à jour afin de pouvoir revenir en
> arrière ne cas de souci. Mais est-ce que effectivement on pourra
> revenir en arrière ?

Ce que je viens de développer vaut également pour le tar.

Si tu veux faire ton tar, la seule solution est de t'assurer qu'aucun
autre process n'écrit dedans, par exemple en arrêtant Apache.

Sur Paheko.cloud ce que je fait c'est que je met les associations en
mode "maintenance" :

<IfDefine PAHEKO_MAINTENANCE>
    # Maintenance mode
    <Directory ${PAHEKO_ROOT}>
        RedirectMatch 503 ^(?!/_maintenance\.html$).*
        ErrorDocument 503 /_maintenance.html
    </Directory>
</IfDefine>

En sachant que dans chacun des vhosts j'ai déjà :

Alias /_maintenance.html ${PAHEKO_ROOT}/www/_maintenance.html

Il me suffit donc de définir la variable d'environnement
"PAHEKO_MAINTENANCE", de recharger Apache (apache2ctl graceful ou
systemctl reload apache2), et toutes les instances hébergées ne servent
plus qu'un fichier HTML statique.

Je peux ensuite attendre quelques minutes et arrêter FPM, pour être sûr
qu'aucun process PHP n'écrit dans une base de données.

Et après faire un tar sans souci.

Mais je ne fait généralement pas ça, sauf grosse migration, car Paheko
a plusieurs mécanismes pour que la mise à jour soit la plus sûre
possible :

- avant la mise à jour, un fichier de lock est créé, ce qui fait qu'une
  seule mise à jour peut être effectuée en même temps
- avant la mise à jour, un backup de la base de données est effectué
  proprement (association.pre-upgrade-1.3.4.sqlite par exemple),
  permettant de revenir en arrière juste en recopiant ce fichier à la
  place de association.sqlite, ce fichier est conservé après la mise à
  jour même si elle s'est bien passé (du coup prévoir de supprimer les
  fichiers trop vieux de temps en temps pour libérer de l'espace disque)
- si la mise à jour échoue, le backup (...pre-upgrade...sqlite) est
  restauré à la place de association.sqlite : tu peux donc ré-essayer
  la mise à jour sans souci
- à la fin de la mise à jour, une vérification de l'intégrité de la
  base de données est réalisée, s'il y a le moindre souci la mise à
  jour échoue, la sauvegarde est restaurée.

Il est donc très difficile de corrompre une mise à jour. Dans le pire
des cas, il y a un bug dans le code qui empêche la mise à jour de
s'effectuer : tu es bloqué, mais tu peux revenir à la version d'avant,
et tu n'as perdu aucune donnée.

Mon conseil : si tu peux faire des snapshots c'est le mieux :)

J'ai noté tous ces points dans la doc, merci.

Installation de Paheko en multi-sites

emmanuel.courcelle at zaclys.net via hebergement

27/12/2023 16:21:39

Bonjour

Merci de ta réponse super-précise ! Du coup je me suis remis au boulot....

1/ Pour les caches ils sont maintenant dans un volume pérenne, et j'ai 
vérifié que lors d'une mise à jour - c-à-d lorsque je redémarre le 
conteneur avec une nouvelle version de paheko, le cache est bien vidé et 
remplacé. Et le lien symbolique est créé au niveau Dockerfile, le cache 
web se remplit comme prévu.

2/ Pour les urls, je ne fais pas plusieurs vhosts en fait je n'en ai 
qu'un avec des ServerAlias et ça marche très bien... sauf que, avec le 
config.local.php fourni (version multisites) les différentes url sont 
obligatoirement de la forme monasso.le-pic.org. Comme je voulais avoir 
la possibilité d'avoir *en plus* des trucs genre paheko.monasso.fr, j'ai 
modifié config.local.php au niveau du code "magique":

La version originale (ici: 
https://fossil.kd2.org/paheko/file?name=tools/factory/config.local.php&ci=trunk)

////////////////////////////////////////////////////////////////
// Code 'magique' qui va configurer Paheko selon les réglages

$login = null;

// Un sous-domaine ne peut pas faire plus de 63 caractères
$login_regexp = '([a-z0-9_-]{1,63})';
$domain_regexp = sprintf('/^%s\.%s$/', $login_regexp, 
preg_quote(FACTORY_DOMAIN, '/'));

if (isset($_SERVER['SERVER_NAME']) && preg_match($domain_regexp, 
$_SERVER['SERVER_NAME'], $match)) {
     $login = $match[1];
}
elseif (PHP_SAPI == 'cli' &&
!empty($_SERVER['PAHEKO_FACTORY_USER']) && 
preg_match('/^' . $login_regexp . '$/',
$_SERVER['PAHEKO_FACTORY_USER'])) {
     $login = $_SERVER['PAHEKO_FACTORY_USER'];
}
else {
     // Login invalide ou non fourni
     http_response_code(404);
     die('<h1>Page non trouvée</h1>');
}

$user_data_dir = rtrim(FACTORY_USER_DIRECTORY, '/') . '/' . $login;

La version modifiée (en gras le passage modifié):

///////////////////////////////////////////////////////////////
// Code 'magique' qui va configurer Paheko selon les réglages

$login = null;

// Un sous-domaine ne peut pas faire plus de 63 caractères
$login_regexp = '([a-z0-9_-]{1,63})';
$domain_regexp = sprintf('/^%s\.%s$/', $login_regexp, 
preg_quote(FACTORY_DOMAIN, '/'));

if (isset($_SERVER['SERVER_NAME']) && preg_match($domain_regexp, 
$_SERVER['SERVER_NAME'], $match)) {
     $login = $match[1];

*    // Définir l'URL
     define('Paheko\WWW_URL', 'https://' . $login . '.' .
FACTORY_DOMAIN 
. '/');
     define('Paheko\WWW_URI', '/');
*}
elseif (PHP_SAPI == 'cli' &&
!empty($_SERVER['PAHEKO_FACTORY_USER']) && 
preg_match('/^' . $login_regexp . '$/',
$_SERVER['PAHEKO_FACTORY_USER'])) {
     $login = $_SERVER['PAHEKO_FACTORY_USER'];

*    // Définir l'URL
     define('Paheko\WWW_URL', 'https://' . $login . '.' .
FACTORY_DOMAIN 
. '/');
     define('Paheko\WWW_URI', '/');
*}
else {
     $login = $_SERVER['SERVER_NAME'];

*    // Définir l'URL
     define('Paheko\WWW_URL', 'https://' . $login . '/');
     define('Paheko\WWW_URI', '/');
*}

Il suffit d'ajouter un ServerAlias paheko.monasso.fr et un répertoire 
/src/data/user/paheko.monasso.fr  pour démarrer paheko  pour monasso.fr

3/ Pour les sauvegardes j'ai choisi la copie VACCUM INTO (nous 
n'utilisons pas pour l'instant btrfs), et pour être sûr de ne pas 
laisser les fichiers corrompus lors de l'arrêt du conteneur, j'ai mis la 
ligne:
STOPSIGNAL SIGWINCH

dans le Dockerfile, ce qui signifie que Docker envoie un signal SIGWINCH 
à apache lors de l'arrêt du conteneur, et cela veut dire qu'apache 
attend que les requêtes en cours soient terminées pour s'arrêter. J'ai 
aussi mis un timeout de 300s.

4/ Une question supplémentaire pour la route: je pense faire les mises à 
jour en construisant une nouvelle image avec la nouvelle version, puis 
redémarrage du conteneur. J'ai fait quelques essais, et le workflow que 
tu décris a l'air de très bien fonctionner, la mise à jour (avec 
sauvegardes et mise à jour de la BD ) se fait au démarrage. Mais faut-il 
suivre l'ordre des versions (1.3.4, 1.3.5, 1.3.6 etc) ou peut-on 
"sauter" des versions ?

Amicalement,
Emmanuel

Le 22/12/2023 à 22:39, BohwaZ/Paheko a écrit :
>>    * Le shared cache se trouve dans /tmp, j'ai simplement modifié la
>>      constante SHARED_CACHE_ROOT de config.local.php pour le mettre sur
>>      /tmp (un tmpfs en rw) et ça marche très bien
> Non dans la config par défaut du multi-user, le cache partagé est bien
> dans un répertoire "cache" à la racine de l'hébergement.
>
> Tu peux mettre ça n'importe où, mais si tu met dans un tmpfs, le cache
> devra être reconstruit quand ton tmpfs sera vidé (par exemple après un
> reboot). Pas très grave. L'intérêt du shared cache c'est que
> normalement il reste dans l'opcache, donc moins de RAM/CPU utilisé pour
> tout le monde :)
>
>>    * Par contre lors de la première connexion sur la première
>> association (appelons-la asso1), paheko essaie de créer un répertoire
>>      */src/www/.cache*, qui est en fait un lien symbolique vers
>>      */src/data/users/asso1/cache* comme je l'ai vu en retirant
>>      l'attribut read-only du volume système. Je trouve cela un peu
>>      bizarre, car du coup toutes les assos utilisent le cache de asso1.
>>      Et si plus tard asso1 disparaît, tout le monde se retrouvera en
>>      rade. Et ça ne pouvait pas marcher chez nous (à cause du
>> read-only), donc j'ai monté un tmpfs sur */src/www/.cache* Un second
>> cache partagé, donc.
>>
>> Bon, ça fonctionne, mais est-ce bien comme ça qu'on est censé faire
?
>> Pourquoi ce répertoire .cache, alors qu'il y a déjà un cache
partagé
>> et un cache par association ?
> Le cache partagé mentionné plus haut stocke des fichiers PHP, générés à
> partir du code Smarty ou Brindille. Cela évite de re-parser les
> templates à chaque fois.
>
> Le répertoire .cache stocke le cache statique du site web.
>
> Par défaut, si tu utilise Apache, quand tu consulte une page du site
> web en mode visiteur (sans être connecté à l'admin), la page
générée
> (le HTML) est stocké dans le cache web, par défaut /data/cache/web/[hash
> du host]/[hash de l'URL].html
>
> Si tu consulte un fichier public (image, document, etc.), un lien
> symbolique est créé dans /data/cache/web/[hash du host]/[hash de l'URL]
>
> Ensuite via le .htaccess, Apache va détecter que la page HTML, ou le
> fichier en lien symbolique, existe dans le cache, et le renvoyer
> directement, sans faire appel à PHP.
>
> Ça permet à Paheko d'être extrêmement rapide et léger, si une
> association voit un afflux soudain de visites sur son site, ton serveur
> ne sera pas aussi surchargé.
>
> En effet utiliser le cache web permet de diviser la charge par 10 à 20.
>
> Pour que ça fonctionne cependant, il faut que Apache puisse accéder au
> fichier, et pour cela il faut qu'il soit dans le DOCUMENT_ROOT. D'où
le
> lien symbolique dans /www/.cache/
>
> Note : le cache ne concerne pas les utilisateurs connectés, et le cache
> des pages web est mis à jour toutes les heures.
>
> La configuration par défaut de Paheko est conçue pour fonctionner "sans
> rien faire" sur un hébergement mutualisé type Ouvaton, OVH, etc.
D'où
> le fait que Paheko essaye de créer le lien symbolique par lui-même s'il
> n'existe pas.
>
> Si tu héberge plusieurs instances Paheko, alors il est plus intéressant
> d'utiliser un cache web partagé, en configurant la constante
> WEB_CACHE_ROOT :
>
> const WEB_CACHE_ROOT = '/path/to/hosted/pahekos/cache/web/%host%';
>
> À toi de créer le lien symbolique ensuite, si tu ne donne pas le droit
> à Paheko de le faire automatiquement.
>
> Donc ta config fonctionne, mais du coup si ton cache web partagé est
> monté sur …/src/www/.cache/ alors il faut le dire aussi à Paheko,
qu'il
> écrive au bon endroit :
>
> const WEB_CACHE_ROOT = '…/src/www/.cache/%host';
>
> Pourquoi ça n'est pas un sous-répertoire du cache shared ? Car lors
> d'une mise à jour, on efface le cache shared, pour être sûr que si un
> template à changé, on n'utilise pas une ancienne version encore en
> cache qui provoquerait éventuellement des erreurs. Donc on ne veut pas
> forcément effacer le cache web en même temps.
>
>>            2/ Les urls:
>>
>> Actuellement, une asso appelée asso1 a obligatoirement comme url un
>> truc genre *https://asso1.le-pic.org* Or, je pense que certaines
>> associations qui disposent de leur nom de domaine aimeraient bien
>> avoir plutôt quelque chose dans le genre *https://paheko.asso1.org*
>> Est-ce qu'il est possible d'avoir des urls quelconques à
l'intérieur
>> d'une installation paheko multisites ?
> Oui tu fait comme tu veux, c'est exactement ça qu'on fait sur
> Paheko.cloud : on rajoute juste un vhost qui pointe au bon endroit pour
> chaque domaine "custom". Exemple :
>
> <VirtualHost *:443>
> ServerName kd2.org
>
> DocumentRoot ${PAHEKO_ROOT}/src/paheko/src/www
> DirectoryIndex index.php
>
> SSLEngine On
> SSLUseStapling On
> SSLCertificateFile ${PAHEKO_ROOT}/conf/certs/certs/kd2.org/fullchain.pem
> SSLCertificateKeyFile
> ${PAHEKO_ROOT}/conf/certs/certs/kd2.org/privkey.pem
> </VirtualHost>
>
>>            3/ Les sauvegardes:
>>
>> Nous sauvegardons le serveur quotidiennement. Pour sauvegarder les
>> bases de données mariadb, nous commençons par faire un dump, ensuite
>> nous sauvegardons le dump. Mais nous ne sauvegardons jamais les
>> fichiers de la base de données eux-mêmes, car il faudrait pour cela
>> arrêter le moteur sous peine d'avoir des soucis en copiant des
>> fichiers ouverts et donc incohérents. D'autres applications
>> (Nextcloud notamment) sont mises en maintenance le temps de la
>> sauvegarde. Faut-il prendre des précautions similaires lors des
>> sauvegardes de Paheko, ou est-ce que nous pouvons simplement
>> sauvegarder les fichiers .sqlite sans risque d'avoir des fichiers
>> corrompus si quelqu'un travaille au moment de la sauvegarde ?
> La théorie : il ne faut pas faire juste une copie du fichier .sqlite
> car il peut être écrit en même temps et donc tu peux copier un fichier
> corrompu.
>
> C'est documenté dans la doc SQLite :
> https://www.sqlite.org/howtocorrupt.html
>
> Et ici :https://litestream.io/alternatives/cron/
>
> Donc tu es censé créer une copie via l'API de backup de SQLite :
> sqlite3 association.sqlite "VACUUM INTO 'backup.sqlite'"
> Et ensuite faire un backup de ce fichier "backup.sqlite".
>
> Tu peux aussi préférer faire un dump :
> sqlite3 association.sqlite .dump > backup.sql
>
> Qui te donnera toutes les commandes SQL pour re-créer la BDD.
>
> De cette manière tu aura 100% de chances que ton "backup.sqlite"
n'est
> pas corrompu.
>
> Si tu fait un snapshot (par exemple avec btrfs, ZFS ou LVM) et non un
> "cp" (ou rsync/borg/etc.) alors ce n'est pas nécessaire, le risque
étant
> qu'avec une copie normale, tu commence à copier le fichier, mais avant
> que tu n'ait finit de copier jusqu'à la fin, un process modifie le
> reste du fichier : tu te retrouve avec des bouts de l'ancienne version
> et des bouts de la nouvelle version.
>
> Avec un snapshot instantané type copy-on-write, le problème n'existe
> pas.
>
> Donc une autre solution c'est de faire un snapshot et de faire un
> backup de ce snapshot, vu qu'il ne peut plus être modifié.
>
> Ça t'évite de faire un script qui fait un "VACUUM INTO" de chaque
base
> de données.
>
> Je conseille de toutes façons le snapshot, car tu peux aussi avoir des
> problèmes de synchro avec les fichier du cache, ou les fichiers de
> l'association si tu as choisis de les stocker en dehors de SQLite.
>
> Il est à noter que tout cela ne concerne que les fichier
> "association.sqlite".
>
> Tous les autres fichiers ".sqlite" sont des sauvegardes créées par
> Paheko, aucun processus n'écrit dedans, donc il est possible de juste
> les copier/rsync/etc. sans risque.
>
>> Pareil
>> pour les mises à jour: mon idée serait de faire un tar de
>> */src/data/users* avant de mettre à jour afin de pouvoir revenir en
>> arrière ne cas de souci. Mais est-ce que effectivement on pourra
>> revenir en arrière ?
> Ce que je viens de développer vaut également pour le tar.
>
> Si tu veux faire ton tar, la seule solution est de t'assurer
qu'aucun
> autre process n'écrit dedans, par exemple en arrêtant Apache.
>
> Sur Paheko.cloud ce que je fait c'est que je met les associations en
> mode "maintenance" :
>
> <IfDefine PAHEKO_MAINTENANCE>
>      # Maintenance mode
>      <Directory ${PAHEKO_ROOT}>
>          RedirectMatch 503 ^(?!/_maintenance\.html$).*
>          ErrorDocument 503 /_maintenance.html
>      </Directory>
> </IfDefine>
>
> En sachant que dans chacun des vhosts j'ai déjà :
>
> Alias /_maintenance.html ${PAHEKO_ROOT}/www/_maintenance.html
>
> Il me suffit donc de définir la variable d'environnement
> "PAHEKO_MAINTENANCE", de recharger Apache (apache2ctl graceful ou
> systemctl reload apache2), et toutes les instances hébergées ne servent
> plus qu'un fichier HTML statique.
>
> Je peux ensuite attendre quelques minutes et arrêter FPM, pour être sûr
> qu'aucun process PHP n'écrit dans une base de données.
>
> Et après faire un tar sans souci.
>
> Mais je ne fait généralement pas ça, sauf grosse migration, car Paheko
> a plusieurs mécanismes pour que la mise à jour soit la plus sûre
> possible :
>
> - avant la mise à jour, un fichier de lock est créé, ce qui fait
qu'une
>    seule mise à jour peut être effectuée en même temps
> - avant la mise à jour, un backup de la base de données est effectué
>    proprement (association.pre-upgrade-1.3.4.sqlite par exemple),
>    permettant de revenir en arrière juste en recopiant ce fichier à la
>    place de association.sqlite, ce fichier est conservé après la mise à
>    jour même si elle s'est bien passé (du coup prévoir de supprimer
les
>    fichiers trop vieux de temps en temps pour libérer de l'espace
disque)
> - si la mise à jour échoue, le backup (...pre-upgrade...sqlite) est
>    restauré à la place de association.sqlite : tu peux donc ré-essayer
>    la mise à jour sans souci
> - à la fin de la mise à jour, une vérification de l'intégrité de la
>    base de données est réalisée, s'il y a le moindre souci la mise à
>    jour échoue, la sauvegarde est restaurée.
>
> Il est donc très difficile de corrompre une mise à jour. Dans le pire
> des cas, il y a un bug dans le code qui empêche la mise à jour de
> s'effectuer : tu es bloqué, mais tu peux revenir à la version
d'avant,
> et tu n'as perdu aucune donnée.
>
> Mon conseil : si tu peux faire des snapshots c'est le mieux :)
>
> J'ai noté tous ces points dans la doc, merci.
>

Installation de Paheko en multi-sites

BohwaZ/Paheko

28/12/2023 12:51:02

> 1/ Pour les caches ils sont maintenant dans un volume pérenne, et
> j'ai vérifié que lors d'une mise à jour - c-à-d lorsque je
redémarre
> le conteneur avec une nouvelle version de paheko, le cache est bien
> vidé et remplacé. Et le lien symbolique est créé au niveau
> Dockerfile, le cache web se remplit comme prévu.

Cool.

Après c'est pas vraiment une obligation, comme tout cache, si tu le
vide c'est pas grave, il va se reconstituer tout seul. Juste si tu as
un truc fort sollicité tu va avoir un peu plus de charge le temps que
le cache soit constitué…

> 2/ Pour les urls, je ne fais pas plusieurs vhosts en fait je n'en ai 
> qu'un avec des ServerAlias et ça marche très bien... sauf que, avec
> le config.local.php fourni (version multisites) les différentes url
> sont obligatoirement de la forme monasso.le-pic.org. Comme je voulais
> avoir la possibilité d'avoir *en plus* des trucs genre
> paheko.monasso.fr, j'ai modifié config.local.php au niveau du code
> "magique":

Oui tu fait un peu comme tu veux, mais si tu veux avoir un certificat
SSL pour chaque domaine il te faudra un vHost pour chaque domaine du
coup, à moins de faire du proxy https devant Apache.

> 4/ Une question supplémentaire pour la route: je pense faire les
> mises à jour en construisant une nouvelle image avec la nouvelle
> version, puis redémarrage du conteneur. J'ai fait quelques essais, et
> le workflow que tu décris a l'air de très bien fonctionner, la mise à
> jour (avec sauvegardes et mise à jour de la BD ) se fait au
> démarrage. Mais faut-il suivre l'ordre des versions (1.3.4, 1.3.5,
> 1.3.6 etc) ou peut-on "sauter" des versions ?

Tu peux sauter des versions sans souci.

Normalement la dernière version de Paheko supporte les mise à jour
depuis toutes les anciennes versions des 1 ou 2 dernières années. Dans
le cas contraire, c'est indiqué dans les notes de version.

Actuellement les 1.3.x supportent toutes les anciennes versions jusqu'à
1.1.19 (janvier 2022).

C'est notamment parce que tu peux restaurer des sauvegardes de la base
de données depuis la gestion des sauvegardes, si nécessaire.