Piwigo, une galerie d'images libre

Piwigo

Cela faisait quelques temps que j'étais à la recherche d'une galerie pour y publier quelques photos de temps en temps. Plume a un gestionnaire de médias faisant le taff, mais il a encore besoin de s'améliorer et j'ai donc opté pour un outil plus spécialisé.

D'anciens bricolages je connaissais surtout Gallery, projet depuis à l'abandon mais qui était pas mal. Dommage.

J'ai d'abord regardé du côté de Piwigo mais le fait qu'il ne supporte que MySQL en base de données m'a rebuté. En effet, j'utilise plutôt du Postgres et cela me dérangeait de devoir installer un autre serveur de BDD uniquement pour un outil.

Je me suis donc tourné dans un premier temps vers MediaGoblin qui lui gère cette base de données. Mais après deux soirées passées dessus à essayer de le faire tomber en marche, j'ai abandonné. J'ai eu la GUI, serveur paramétré, etc, mais les formulaires renvoyaient vers localhost et je n'arrivais pas à trouver comment paramétrer son adresse publique. La documentation est hélas très incomplète et je n'arrivais pas à me représenter l'architecture du logiciel entre ce qui était dit et ce que je constatais.

Plutôt que de m'acharner, j'ai donc décidé d'ajouter MariaDB sur le serveur qui héberge déjà mon Postgres et de donner sa chance à Piwigo. Certes c'est pas top niveau perfs d'avoir ces deux outils sur le même serveur, mais bon, je n'héberge pas non plus la Terre entière donc ça fera le job.

Présentation

Piwigo est né sous le nom PhpWebGallery, écrit en 2001 par Pierrick Le Gall et inspiré par le projet phpBB en tant que travail personnel. Il est finalement publié en 2002 sous licence GPL et s'enrichi continuellement tout en supportant de nouvelles langues. Le projet est renommé Piwigo en 2009 et vie à la fois de donations et contributions, mais aussi d'une offre d'hébergement SaaS basée dessus. Comme son premier nom l'indique, il est écrit en PHP et a donc besoin d'une base de données MySQL/MariaDB.

En cherchant néanmoins au début, j'avais cru voir qu'il gérait le support de Postgresql, mais finalement celui-ci fut abandonné.

L'outil vit également avec son temps car il s'est progressivement enrichi d'API et dispose d'une application mobile sur iOS et Android. Le logiciel est traduit en 56 langues et le site web possède une douzaine de localisations différentes.

Installation

Déploiement des sources PHP

Le site propose un démarrage rapide qui est très simple à mettre en oeuvre. Etant codé en PHP, l'installation de l'outil n'est qu'un simple déploiement de scripts. J'avoue être assez nostalgique de ces méthodes car au final on a juste besoin de déployer une archive et ça marche... Quand je vois la plupart des applis web où désormais il faut installer 15 runtimes différents et multiplier les couches techniques, je reconnais devenir de plus en plus feignant et prendre l'image Docker par facilité parfois.

A noter qu'il dispose aussi d'une netinstall demandant d'envoyer un seul PHP qui fait tout le reste.

J'ai donc téléchargé l'archive sur mon serveur web.

Par facilité, les actions sont réalisées en root.

wget https://piwigo.org/download/dlcounter.php?code=latest -o piwigo.zip
unzip piwigo.zip -d /srv/www/
chown -R apache:apache /srv/www/piwigo

En allant ensuite dans le dossier piwigo, j'ai constaté quelque chose de déplaisant. Les dossiers à la racine avaient la totalité des permissions et des scripts php étaient exécutables.

Je change donc tout cela :

find . -type d -exec chmod 755 {} \;
find . -type f -exec chmod -x {} \;

Je préfère.

Ensuite, ayant SELinux activé, il faut donner l'autorisation au daemon Web d'aller écrire dans les dossiers médias pour les upload.

semanage fcontext -a -t httpd_sys_rw_content_t '/srv/www/piwigo/upload(/.*)?'
semanage fcontext -a -t httpd_sys_rw_content_t '/srv/www/piwigo/_data(/.*)?'
restorecon -R /srv/www/piwigo/

Voyons ce que ça donne.

ls -lZ

total 352
-rw-r--r--.  1 apache apache unconfined_u:object_r:httpd_sys_content_t:s0     1823 26 mars  19:53 about.php
-rw-r--r--.  1 apache apache unconfined_u:object_r:httpd_sys_content_t:s0     5723 26 mars  19:53 action.php
drwxr-xr-x.  4 apache apache unconfined_u:object_r:httpd_sys_content_t:s0     4096 26 mars  19:53 admin
-rw-r--r--.  1 apache apache unconfined_u:object_r:httpd_sys_content_t:s0    10567 26 mars  19:53 admin.php
-rw-r--r--.  1 apache apache unconfined_u:object_r:httpd_sys_content_t:s0    15758 26 mars  19:53 comments.php
-rw-r--r--.  1 apache apache unconfined_u:object_r:httpd_sys_content_t:s0      467 26 mars  19:53 COPYING.txt
drwxr-xr-x.  6 apache apache unconfined_u:object_r:httpd_sys_rw_content_t:s0  4096  9 sept. 21:56 _data
drwxr-xr-x.  2 apache apache unconfined_u:object_r:httpd_sys_content_t:s0     4096 26 mars  19:53 doc
drwxr-xr-x.  2 apache apache unconfined_u:object_r:httpd_sys_content_t:s0     4096 26 mars  19:53 docs
-rw-r--r--.  1 apache apache unconfined_u:object_r:httpd_sys_content_t:s0     5548 26 mars  19:53 feed.php
drwxr-xr-x.  2 apache apache unconfined_u:object_r:httpd_sys_content_t:s0     4096 26 mars  19:53 galleries
-rw-r--r--.  1 apache apache unconfined_u:object_r:httpd_sys_content_t:s0     4443 26 mars  19:53 identification.php
drwxr-xr-x. 10 apache apache unconfined_u:object_r:httpd_sys_content_t:s0     4096 26 mars  19:53 include
-rw-r--r--.  1 apache apache unconfined_u:object_r:httpd_sys_content_t:s0    10749 26 mars  19:53 index.php
drwxr-xr-x.  3 apache apache unconfined_u:object_r:httpd_sys_content_t:s0     4096 26 mars  19:53 install
-rw-r--r--.  1 apache apache unconfined_u:object_r:httpd_sys_content_t:s0    15461 26 mars  19:53 install.php
-rw-r--r--.  1 apache apache unconfined_u:object_r:httpd_sys_content_t:s0    17203 26 mars  19:53 i.php
drwxr-xr-x. 72 apache apache unconfined_u:object_r:httpd_sys_content_t:s0     4096 26 mars  19:53 language
-rw-r--r--.  1 apache apache unconfined_u:object_r:httpd_sys_content_t:s0    18092 26 mars  19:53 LICENSE.txt
drwxr-xr-x.  5 apache apache unconfined_u:object_r:httpd_sys_content_t:s0     4096 26 mars  19:53 local
-rw-r--r--.  1 apache apache unconfined_u:object_r:httpd_sys_content_t:s0     2776 26 mars  19:53 nbm.php
-rw-r--r--.  1 apache apache unconfined_u:object_r:httpd_sys_content_t:s0     3346 26 mars  19:53 notification.php
-rw-r--r--.  1 apache apache unconfined_u:object_r:httpd_sys_content_t:s0    10252 26 mars  19:53 password.php
-rw-r--r--.  1 apache apache unconfined_u:object_r:httpd_sys_content_t:s0    28545 26 mars  19:53 picture.php
drwxr-xr-x.  6 apache apache unconfined_u:object_r:httpd_sys_content_t:s0     4096 26 mars  19:53 plugins
-rw-r--r--.  1 apache apache unconfined_u:object_r:httpd_sys_content_t:s0     2112 26 mars  19:53 popuphelp.php
-rw-r--r--.  1 apache apache unconfined_u:object_r:httpd_sys_content_t:s0    10933 26 mars  19:53 profile.php
-rw-r--r--.  1 apache apache unconfined_u:object_r:httpd_sys_content_t:s0     1562 26 mars  19:53 qsearch.php
-rw-r--r--.  1 apache apache unconfined_u:object_r:httpd_sys_content_t:s0     2013 26 mars  19:53 random.php
-rw-r--r--.  1 apache apache unconfined_u:object_r:httpd_sys_content_t:s0     1905 26 mars  19:53 README.md
-rw-r--r--.  1 apache apache unconfined_u:object_r:httpd_sys_content_t:s0     3514 26 mars  19:53 register.php
-rw-r--r--.  1 apache apache unconfined_u:object_r:httpd_sys_content_t:s0     7433 26 mars  19:53 search.php
-rw-r--r--.  1 apache apache unconfined_u:object_r:httpd_sys_content_t:s0     6321 26 mars  19:53 search_rules.php
-rw-r--r--.  1 apache apache unconfined_u:object_r:httpd_sys_content_t:s0     4860 26 mars  19:53 tags.php
drwxr-xr-x.  4 apache apache unconfined_u:object_r:httpd_sys_content_t:s0     4096 26 mars  19:53 template-extension
drwxr-xr-x.  6 apache apache unconfined_u:object_r:httpd_sys_content_t:s0     4096 26 mars  19:53 themes
drwxr-xr-x.  3 apache apache unconfined_u:object_r:httpd_sys_content_t:s0     4096 26 mars  19:53 tools
-rw-r--r--.  1 apache apache unconfined_u:object_r:httpd_sys_content_t:s0     3159 26 mars  19:53 upgrade_feed.php
-rw-r--r--.  1 apache apache unconfined_u:object_r:httpd_sys_content_t:s0    15218 26 mars  19:53 upgrade.php
drwxr-xr-x.  4 apache apache unconfined_u:object_r:httpd_sys_rw_content_t:s0  4096  9 sept. 21:56 upload
-rw-r--r--.  1 apache apache unconfined_u:object_r:httpd_sys_content_t:s0    41950 26 mars  19:53 ws.php

Veuillez noter que je n'ai donné aucun droit d'écriture au dossier locale qui est là où la config générée à la prochaine étape sera stockée. Ceci empêchera l'installeur de créer le fichier, il faudra donc le faire à la main.

Création de la base de données et de son utilisateur

Connectez-vous à votre serveur MySQL/MariaDB avec un compte admin.

mysql -u root -p
Enter password: 
-- creation de la BDD
create database piwigo;

-- Dans le cas où votre BDD est sur un autre serveur, mettez @'%'. Si MySQL est sur la même serveur, mettez localhost pour en faire un utilisateur restreint au domaine local.
CREATE USER 'piwigo'@'%' IDENTIFIED  BY '<un mot de passe fort>';

-- On donne les droits à l'utilisateur sur la base. Adaptez 'piwigo'@'%' avec localhost à la place de % si besoin
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, INDEX, DROP, ALTER, CREATE TEMPORARY TABLES, LOCK TABLES ON db_piwigo.* to 'piwigo'@'%'

Création du vhost Apache

Je ferai simple ici car le but est juste d'accéder à l'application. A adapter selon votre serveur web et la façon dont vous hébergez (si reverse proxy en frontal, etc). Dans ma conf complète, je me suis permis d'y ajouter quelques directives issues du fichier .htaccess de Nextcloud. Notamment celles de sécurité et de gestion de cache.

<VirtualHost *:80>
        ServerName piwigo
        CustomLog /var/log/httpd/pwigo_access.log common
        ErrorLog /var/log/httpd/piwigo_error.log
        DocumentRoot /srv/www/piwigo
        ServerAdmin admin@example.com

        # Encoded slashes need to be allowed
        AllowEncodedSlashes             On
        <Directory />
                Options MultiViews FollowSymLinks
                AllowOverride All
                Require all granted
        </Directory>

</VirtualHost>

Premier démarrage

En se connectant à l'adresse de Piwigo sur votre serveur Web, vous serez directement redirigé à l'écran d'installation. Celui-ci vous demandera de fournir les identifiants de connexion à la base de données et de créer un compte admin sur l'appli.

Dans le cas où SELinux fait des misères, il suffit de générer les règles d'accès à partir des logs d'audit.

grep php-fpm /var/log/audit/audit.log | audit2allow -M rulesPiwigo

Puis de les appliquer :

semodule -i rulesPiwigo.pp

Dans tous les cas, avec les restrictions que j'ai mises ici, la config ne pourra être écrite par le site. Récupérez donc les instructions générées et reportez les dans /srv/www/piwigo/local/config/database.inc.php

Côté droits, je me suis assuré que le fichier est en lecture uniquement.

chown apache:apache /srv/www/piwigo/local/config/database.inc.php
chmod 400 /srv/www/piwigo/local/config/database.inc.php

Ceci fait, vous pouvez accéder à l'application et vous y connecter avec le profil créé précédemment.

Premiers pas

Une fois Piwigo disponible, j'ai surtout commencé à parcourir les diverses options d'admin pour voir le niveau de personnalisation. Il y a pas mal de choses notamment au niveau des thèmes de l'interface qui permettent de définir le nombre de vignettes par pages, la taille, les éléments à afficher, etc.

piwigo2

On commence d'abord par se créer un album dans lequel on va pouvoir ensuite envoyer des photos. Il est possible de créer des albums publics et privés au choix. Un système d'héritage de droits facilite la gestion avec les sous albums.

En ayant mis les options de caches que j'ai cité plus haut, les temps de chargement sont corrects et les imports ne m'ont pas pris trop de temps. Il convient de modifier la conf PHP pour envoyer des fichiers de grande taille au niveau des entrées, notamment les valeurs de post_max_size et upload_max_filesize.

Piwigo permet de créer ses propres filigranes, mais pour ma part je gère ça avec Darktable.

Outre l'envoi par le site, vous pouvez aussi faire des imports directement en envoyant les fichiers sur le serveur ou bien en passant par les applications mobiles. Piwigo dispose d'une appli Android et iOS pour se synchro avec sa propre galerie. Je n'ai pas été bien loin dans l'utilisation de cette version mobile car au moment où j'écris ce billet, elle possède un bug à cause duquel les images ne s'affichent pas lorsqu'on utilise un reverse proxy.

A voir avec l'usage, mais cette première approche m'a bien plu et l'outil semble vraiment bien foutu. Il faut dire qu'étant assez âgé, il dispose d'une certaine maturité et expérience. La documentation est correcte pour une prise en main initiale et possède des chapitres avancés intéressants.