Skip to main content

Bookstack déploiement

#

Déploiement de BookStack avec Podman Compose

Contexte

## 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**
  • BookStack : Wiki de documentation
  • - **MariaDB**
  • MariaDB : Base de données
  • - **Nginx**
  • Nginx : Reverse proxy avec SSL
  • - **Podman**
  • 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**Problème : Communication réseau entre pods impossible

-
    **Erreur**
  • Erreur : SQLSTATE\SQLSTATE[HY000] [HY000\] \[2002\]2002] No such file or directory
  • - **Cause**
  • Cause : Module kernel nf\_conntracknf_conntrack manquant
  • - **
  • Erreur K3s**K3s : Extension conntrack is not supported, missing kernel module?

**Tentative de solution**solution :

sudo modprobe nf\_conntracknf_conntrack
sudo modprobe br\_netfilterbr_netfilter  # Module non disponible sur AlmaLinux 10

**Décision**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**Erreur : nc: getaddrinfo for host "bookstack-mariadb" port 3306: Try again

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

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

\# Trouver le subnet Podman
podman network inspect bookstack\_defaultbookstack_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**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**Erreur : ERROR 1045 (28000): Access denied for user 'bookstack'@'10.89.0.5' (using password: YES)

**Causes multiples**multiples :

1.
  1. Volumes persistants gardant les anciens mots de passe
  2. 2.
  3. Incohérence entre MYSQL\_USERMYSQL_USER et DB\_USERNAMEDB_USERNAME
  4. 3.
  5. Caractères spéciaux (!) mal échappés dans les mots de passe

**Solution finale**finale :

\# 1. Arrêter et supprimer complètement les volumes
cd ~/bookstack
podman-compose down
podman volume rm -f bookstack\_bookstack-bookstack_bookstack-db-data bookstack\_bookstack-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**Erreur : The application key is missing, halting init!

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

\# Générer la clé
APP\_KEY=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: $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**Erreur : SSL: no alternative certificate subject name matches target hostname

**Solution**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**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:container_name: bookstack-db
    environment:
      MYSQL\_ROOT\_PASSWORD:MYSQL_ROOT_PASSWORD: RootPassword123
      MYSQL\_DATABASE:MYSQL_DATABASE: bookstack
      MYSQL\_USER:MYSQL_USER: bookstack
      MYSQL\_PASSWORD:MYSQL_PASSWORD: BookStackPass123
    volumes:
      \- bookstack-db-data:/var/lib/mysql
    restart: unless-stopped

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

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

**Points importants**importants :

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

  • ---

###


Configuration Nginx

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

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

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

    ssl\_certificatessl_certificate /etc/letsencrypt/live/sanjyasz.pro/fullchain.pem;
    ssl\_certificate\_keyssl_certificate_key /etc/letsencrypt/live/sanjyasz.pro/privkey.pem;
    
    ssl\_protocolsssl_protocols TLSv1.2 TLSv1.3;
    ssl\_ciphersssl_ciphers HIGH:!aNULL:!MD5;
    ssl\_prefer\_server\_ciphersssl_prefer_server_ciphers on;
    
    add\_headeradd_header Strict-Transport-Security "max-age=31536000" always;

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

**Appliquer la configuration**configuration :

sudo nginx -t
sudo systemctl reload nginx

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

sudo setsebool -P httpd\_can\_network\_connecthttpd_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=APP_KEY=$(podman run --rm --entrypoint /bin/bash lscr.io/linuxserver/bookstack:latest appkey | tr -d '\\r')
echo "APP\_KEYAPP_KEY généré: $APP\_KEY"APP_KEY"

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

###

3. Configuration DNS (OVH)

Ajouter un enregistrement A :

Type: A
Sous-domaine: wiki
Cible: \[IP du VPS\]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\_defaultbookstack_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.

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

  5. ---

##


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-bookstack_bookstack-config

\# Backup du volume
sudo tar -czf bookstack-config-backup-$(date +%Y%m%d).tar.gz \\
  $(podman volume inspect bookstack\_bookstack-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

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-bookstack_bookstack-db-data bookstack\_bookstack-bookstack_bookstack-config
podman-compose up -d

###

Erreur d'authentification MariaDB

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

podman-compose down
podman volume rm -f bookstack\_bookstack-bookstack_bookstack-db-data bookstack\_bookstack-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\_connecthttpd_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. 1. **Kubernetes (K3s) est overkill pour un seul service**service : Podman Compose est plus simple et consomme moins de ressources

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

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

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

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

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

    ---

  7. ##


Ressources

-

##


Changelog

-

    **
  • 2024-11-22**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**sur : VPS OVH - AlmaLinux 10
**URL**URL : https://wiki.sanjyasz.pro
**Auteur**Auteur : Sanjy Andriamiseza