Skip to main content

Bookstack déploiement

# Déploiement de BookStack avec Podman Compose

## Contexte
Déploiement d'un wiki BookStack sur VPS AlmaLinux 10 avec Podman (au lieu de Docker), Nginx comme reverse proxy, et nftables comme firewall.

---

## Architecture finale

Internet → Nginx (443) → Podman (localhost:30080) → BookStack → MariaDB  
 ↓  
 Let's Encrypt SSL  

- **BookStack** : Wiki de documentation
- **MariaDB** : Base de données
- **Nginx** : Reverse proxy avec SSL
- **Podman** : Alternative à Docker (rootless, sans daemon)

---

## Prérequis

\# Installer Podman et podman-compose  
sudo dnf install podman podman-compose -y

\# Vérifier l'installation  
podman --version  
podman-compose --version  

---

## Problèmes rencontrés et solutions

### 1. ❌ Tentative initiale : Kubernetes (K3s)

**Problème** : Communication réseau entre pods impossible
- **Erreur** : SQLSTATE\[HY000\] \[2002\] No such file or directory
- **Cause** : Module kernel nf\_conntrack manquant
- **Erreur K3s** : Extension conntrack is not supported, missing kernel module?

**Tentative de solution** :

sudo modprobe nf\_conntrack  
sudo modprobe br\_netfilter # Module non disponible sur AlmaLinux 10  

**Décision** : Abandon de K3s au profit de Podman Compose (plus simple, moins de ressources)

---

### 2. ❌ Problème : Communication réseau entre containers Podman

**Erreur** : nc: getaddrinfo for host "bookstack-mariadb" port 3306: Try again

**Cause** : nftables bloque le trafic entre containers

**Solution** : Ajouter des règles nftables pour autoriser le subnet Podman

\# Trouver le subnet Podman  
podman network inspect bookstack\_default | grep -i subnet  
\# Exemple de résultat : 10.89.0.0/24

\# Ajouter les règles nftables  
sudo nft add rule inet filter input ip saddr 10.89.0.0/24 accept  
sudo nft add rule inet filter forward ip saddr 10.89.0.0/24 accept  
sudo nft add rule inet filter forward ip daddr 10.89.0.0/24 accept

\# Sauvegarder  
sudo nft list ruleset | sudo tee /etc/nftables/ruleset.nft  

**Note importante** : Docker et nftables ont des conflits connus. Podman gère mieux nftables mais nécessite quand même des règles explicites.

---

### 3. ❌ Problème : Erreurs d'authentification MariaDB

**Erreur** : ERROR 1045 (28000): Access denied for user 'bookstack'@'10.89.0.5' (using password: YES)

**Causes multiples** :
1. Volumes persistants gardant les anciens mots de passe
2. Incohérence entre MYSQL\_USER et DB\_USERNAME
3. Caractères spéciaux (!) mal échappés dans les mots de passe

**Solution finale** :

\# 1. Arrêter et supprimer complètement les volumes  
cd ~/bookstack  
podman-compose down  
podman volume rm -f bookstack\_bookstack-db-data bookstack\_bookstack-config

\# 2. Vérifier que les volumes sont supprimés  
podman volume ls | grep bookstack

\# 3. Utiliser des mots de passe simples (sans caractères spéciaux)  
\# Voir docker-compose.yml ci-dessous  

---

### 4. ❌ Problème : APP_KEY manquant

**Erreur** : The application key is missing, halting init!

**Solution** : Générer et ajouter l'APP_KEY

\# Générer la clé  
APP\_KEY=$(podman run --rm --entrypoint /bin/bash lscr.io/linuxserver/bookstack:latest appkey | tr -d '\\r')

\# Afficher pour vérification  
echo "APP\_KEY: $APP\_KEY"

\# L'ajouter dans docker-compose.yml sous environment de bookstack  

---

### 5. ❌ Problème : Certificat SSL ne couvre pas wiki.sanjyasz.pro

**Erreur** : SSL: no alternative certificate subject name matches target hostname

**Solution** : Étendre le certificat existant

sudo certbot certonly --nginx \\  
 -d sanjyasz.pro \\  
 -d www.sanjyasz.pro \\  
 -d jenkins.sanjyasz.pro \\  
 -d wiki.sanjyasz.pro \\  
\--expand  

**Alternative** : Certificat wildcard (recommandé pour plusieurs sous-domaines)

sudo certbot certonly --manual --preferred-challenges dns \\  
 -d "\*.sanjyasz.pro" -d "sanjyasz.pro"  

---

## Configuration finale qui fonctionne

### Structure des dossiers

~/bookstack/  
├── docker-compose.yml  

### docker-compose.yml

version: '3.8'

services:  
 bookstack-db:  
 image: mariadb:10.11  
 container\_name: bookstack-db  
 environment:  
 MYSQL\_ROOT\_PASSWORD: RootPassword123  
 MYSQL\_DATABASE: bookstack  
 MYSQL\_USER: bookstack  
 MYSQL\_PASSWORD: BookStackPass123  
 volumes:  
\- bookstack-db-data:/var/lib/mysql  
 restart: unless-stopped

 bookstack:  
 image: lscr.io/linuxserver/bookstack:latest  
 container\_name: bookstack  
 environment:  
 PUID: 1000  
 PGID: 1000  
 TZ: Europe/Paris  
 APP\_URL: https://wiki.sanjyasz.pro  
 DB\_HOST: bookstack-db  
 DB\_PORT: 3306  
 DB\_DATABASE: bookstack  
 DB\_USERNAME: bookstack  
 DB\_PASSWORD: BookStackPass123  
 APP\_KEY: base64:VOTRE\_CLE\_GENEREE\_ICI  
 volumes:  
\- bookstack-config:/config  
 ports:  
\- "30080:80"  
 depends\_on:  
\- bookstack-db  
 restart: unless-stopped

volumes:  
 bookstack-db-data:  
 bookstack-config:  

**Points importants** :
- Pas de guillemets autour des variables (évite les problèmes d'échappement)
- Mots de passe simples sans caractères spéciaux
- depends\_on assure que MariaDB démarre avant BookStack
- Port 30080 choisi pour éviter les conflits

---

### Configuration Nginx

**Fichier** : /etc/nginx/conf.d/wiki.conf

server {  
 listen 80;  
 listen \[::\]:80;  
 server\_name wiki.sanjyasz.pro;  
 return 301 https://$server\_name$request\_uri;  
}

server {  
 listen 443 ssl http2;  
 listen \[::\]:443 ssl http2;  
 server\_name wiki.sanjyasz.pro;

 ssl\_certificate /etc/letsencrypt/live/sanjyasz.pro/fullchain.pem;  
 ssl\_certificate\_key /etc/letsencrypt/live/sanjyasz.pro/privkey.pem;  
   
 ssl\_protocols TLSv1.2 TLSv1.3;  
 ssl\_ciphers HIGH:!aNULL:!MD5;  
 ssl\_prefer\_server\_ciphers on;  
   
 add\_header Strict-Transport-Security "max-age=31536000" always;

 location / {  
 proxy\_pass http://localhost:30080;  
 proxy\_set\_header Host $host;  
 proxy\_set\_header X-Real-IP $remote\_addr;  
 proxy\_set\_header X-Forwarded-For $proxy\_add\_x\_forwarded\_for;  
 proxy\_set\_header X-Forwarded-Proto $scheme;  
   
 # Important pour les uploads de fichiers  
 client\_max\_body\_size 100M;  
 }  
}  

**Appliquer la configuration** :

sudo nginx -t  
sudo systemctl reload nginx  

**SELinux** : Autoriser Nginx à se connecter au réseau

sudo setsebool -P httpd\_can\_network\_connect 1  

---

## Déploiement complet - Procédure pas à pas

### 1. Préparation

\# Créer le dossier  
mkdir -p ~/bookstack  
cd ~/bookstack

\# Créer le docker-compose.yml (voir ci-dessus)  
nano docker-compose.yml  

### 2. Générer l'APP_KEY

APP\_KEY=$(podman run --rm --entrypoint /bin/bash lscr.io/linuxserver/bookstack:latest appkey | tr -d '\\r')  
echo "APP\_KEY généré: $APP\_KEY"

\# Éditer docker-compose.yml et remplacer APP\_KEY  
nano docker-compose.yml  

### 3. Configuration DNS (OVH)

Ajouter un enregistrement A :

Type: A  
Sous-domaine: wiki  
Cible: \[IP du VPS\]  
TTL: 3600  

### 4. Règles firewall nftables

\# Trouver le subnet après le premier lancement  
podman-compose up -d  
SUBNET=$(podman network inspect bookstack\_default | grep -i subnet | awk '{print $2}' | tr -d '",')

\# Ajouter les règles  
sudo nft add rule inet filter input ip saddr $SUBNET accept  
sudo nft add rule inet filter forward ip saddr $SUBNET accept  
sudo nft add rule inet filter forward ip daddr $SUBNET accept

\# Sauvegarder  
sudo nft list ruleset | sudo tee /etc/nftables/ruleset.nft  

### 5. Lancer BookStack

cd ~/bookstack  
podman-compose up -d

\# Vérifier les logs  
podman-compose logs -f  

Attendre 30 secondes que MariaDB s'initialise complètement.

### 6. Vérifier le bon fonctionnement

\# Vérifier les containers  
podman-compose ps

\# Tester la connexion réseau  
podman exec -it bookstack nc -zv bookstack-db 3306

\# Tester l'accès web  
curl http://localhost:30080  

### 7. Configuration Nginx et SSL

\# Créer la config Nginx  
sudo nano /etc/nginx/conf.d/wiki.conf  
\# (Voir configuration ci-dessus)

\# Étendre le certificat SSL  
sudo certbot certonly --nginx \\  
 -d sanjyasz.pro \\  
 -d www.sanjyasz.pro \\  
 -d jenkins.sanjyasz.pro \\  
 -d wiki.sanjyasz.pro \\  
\--expand

\# Recharger Nginx  
sudo nginx -t  
sudo systemctl reload nginx  

### 8. Première connexion

1. Accéder à https://wiki.sanjyasz.pro
2. Se connecter avec :
- Email: admin@admin.com
- Password: password
3. **Changer immédiatement le mot de passe !**

---

## Commandes de gestion quotidienne

\# Démarrer  
cd ~/bookstack  
podman-compose up -d

\# Arrêter  
podman-compose down

\# Redémarrer  
podman-compose restart

\# Voir les logs  
podman-compose logs -f bookstack  
podman-compose logs -f bookstack-db

\# Voir le statut  
podman-compose ps

\# Mettre à jour les images  
podman-compose pull  
podman-compose up -d --force-recreate  

---

## Backup et restauration

### Backup de la base de données

\# Backup automatique  
podman exec bookstack-db mysqldump -u bookstack -pBookStackPass123 bookstack > backup-$(date +%Y%m%d).sql

\# Ou avec root  
podman exec bookstack-db mysqldump -u root -pRootPassword123 --all-databases > backup-full-$(date +%Y%m%d).sql  

### Backup des fichiers BookStack

\# Les fichiers sont dans le volume bookstack-config  
podman volume inspect bookstack\_bookstack-config

\# Backup du volume  
sudo tar -czf bookstack-config-backup-$(date +%Y%m%d).tar.gz \\  
 $(podman volume inspect bookstack\_bookstack-config -f '{{.Mountpoint}}')  

### Restauration

\# Restaurer la base de données  
cat backup-20241122.sql | podman exec -i bookstack-db mysql -u root -pRootPassword123 bookstack

\# Restaurer les fichiers  
sudo tar -xzf bookstack-config-backup-20241122.tar.gz -C /  

---

## Troubleshooting

### Les containers ne démarrent pas

\# Vérifier les logs  
podman-compose logs

\# Vérifier les volumes  
podman volume ls

\# Supprimer et recréer  
podman-compose down  
podman volume rm bookstack\_bookstack-db-data bookstack\_bookstack-config  
podman-compose up -d  

### Erreur d'authentification MariaDB

**Solution** : Supprimer complètement les volumes et recréer

podman-compose down  
podman volume rm -f bookstack\_bookstack-db-data bookstack\_bookstack-config  
podman-compose up -d  

### Erreur 502 Bad Gateway sur Nginx

\# Vérifier que BookStack tourne  
podman-compose ps

\# Vérifier SELinux  
sudo setsebool -P httpd\_can\_network\_connect 1

\# Vérifier les logs Nginx  
sudo tail -f /var/log/nginx/error.log  

### Problème de réseau entre containers

\# Vérifier les règles nftables  
sudo nft list ruleset | grep 10.89

\# Tester la connexion  
podman exec -it bookstack ping bookstack-db  
podman exec -it bookstack nc -zv bookstack-db 3306  

---

## Améliorations possibles

### 1. Service systemd pour auto-start

cd ~/bookstack  
podman generate systemd --new --files --name bookstack  
mkdir -p ~/.config/systemd/user/  
mv \*.service ~/.config/systemd/user/  
systemctl --user enable container-bookstack.service  
loginctl enable-linger $USER  

### 2. Backups automatiques avec cron

\# Éditer crontab  
crontab -e

\# Ajouter backup quotidien à 2h du matin  
0 2 \* \* \* cd ~/bookstack && podman exec bookstack-db mysqldump -u root -pRootPassword123 bookstack > ~/backups/bookstack-$(date +\\%Y\\%m\\%d).sql  

### 3. Monitoring

Intégrer BookStack dans Prometheus/Grafana pour surveiller :
- Uptime des containers
- Utilisation CPU/RAM
- Taille de la base de données

---

## Leçons apprises

1. **Kubernetes (K3s) est overkill pour un seul service** : Podman Compose est plus simple et consomme moins de ressources

2. **nftables et containers nécessitent des règles explicites** : Contrairement à iptables, nftables ne crée pas automatiquement les règles pour les containers

3. **Les volumes Podman persistent même après podman-compose down** : Toujours supprimer explicitement les volumes pour repartir à zéro

4. **Les caractères spéciaux dans les variables d'environnement causent des problèmes** : Utiliser des mots de passe alphanumériques simples dans docker-compose.yml

5. **SELinux doit être configuré pour Nginx → Containers** : httpd\_can\_network\_connect est essentiel

6. **Let's Encrypt ne renouvelle que les domaines dans le certificat** : Utiliser --expand pour ajouter de nouveaux sous-domaines

---

## Ressources

- [BookStack Documentation](https://www.bookstackapp.com/docs/)
- [Podman Documentation](https://docs.podman.io/)
- [LinuxServer.io BookStack Image](https://docs.linuxserver.io/images/docker-bookstack)
- [Let's Encrypt Documentation](https://letsencrypt.org/docs/)

---

## Changelog

- **2024-11-22** : Déploiement initial avec Podman Compose
- Abandon de K3s pour Podman
- Configuration nftables pour communication inter-containers
- Résolution problèmes authentification MariaDB
- Configuration SSL avec Let's Encrypt

---

**Déployé sur** : VPS OVH - AlmaLinux 10
**URL** : https://wiki.sanjyasz.pro
**Auteur** : Sanjy Andriamiseza