alpinux-owni/README.md
Cédrix cf89adbe7d Compléter le README : messagerie, relais sortant, bases, sauvegardes (#2)
Quatre absences, toutes révélées en travaillant sur la messagerie le
27/09/2026.

**messagerie.alpinux.org** n'y figurait pas, alors que le service tourne
depuis le 22/09 — 256 abonnés, un worker chaque minute, trois boîtes relevées
en IMAP. Elle rejoint le tableau des projets sortis, avec un avertissement :
owni n'en est pas un clone, la mise à jour s'y fait par copie de fichiers,
base d'abord. Quelqu'un qui appliquerait la méthode de `home` — un `git pull`
sur le serveur — se tromperait.

**Le relais sortant** n'était nulle part. Depuis les 25-26/09, tout le
courrier de la machine passe par `mail.acemail.fr`, et l'IP qui parle aux
destinataires n'est plus celle d'owni. Trois conséquences écrites : la
réputation devient partagée, un plafond inconnu s'ajoute à celui de Postfix,
et l'enveloppe VERP doit survivre au relais — vérifié, mais à revérifier après
tout changement, la panne serait silencieuse.

**Les bases** ne figuraient pas davantage : six applicatives, avec le service
auquel chacune appartient.

**Les sauvegardes** non plus. L'état y est écrit tel qu'il est, pas tel qu'on
l'imagine : une base sur six, une seule copie, rien hors de la machine. C'est
le genre d'information qu'on cherche le jour où l'on en a besoin, c'est-à-dire
trop tard.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SFbwnJurBwTs7x7t93ecku
2026-09-27 09:06:01 +02:00

9.6 KiB

org.alpinux.owni

Accueil des projets de l'association Alpinux (le LUG de Savoie).

Chaque sous-dossier est un dépôt git indépendant avec son propre remote sur Gitea.
Ce dossier racine est l'espace de travail : son dépôt alpinux-owni ne versionne que ce README.md et le .gitignore — le contenu des sous-dossiers appartient à leur dépôt.


Projets

Dossier Domaine Technologie Dépôt Gitea
feedback/ feedback.alpinux.org à construire alpinux-feedback
home/ alpinux.org HTML statique alpinux-home
portail/ portail.alpinux.org en construction alpinux-portail
infra/ — Configs Apache + systemd alpinux-infra

Sortis de cet espace

Ces projets ont leur propre dossier, au même niveau que celui-ci — un dépôt, un dossier :

Dossier Domaine Dépôt Gitea
~/Projects/alpinux.wiki wiki.alpinux.org alpinux-wiki
~/Projects/alpinux.admin admin.alpinux.org alpinux-admin
~/Projects/alpinux.dynamic dynamic.alpinux.org alpinux-dynamic
~/Projects/alpinux.static static.alpinux.org alpinux-static
~/Projects/alpinux.gitea gitea.alpinux.org alpinux-gitea
~/Projects/alpinux.messagerie messagerie.alpinux.org alpinux.messagerie

Leurs procédures de déploiement sont décrites dans leur propre README.

La messagerie ne se déploie pas comme les autres. owni n'en est pas un clone : la mise à jour s'y fait par copie de fichiers, base d'abord, code ensuite, et non par git pull. La procédure et les pièges qu'elle désamorce sont dans docs/installation.md de ce dépôt. En service depuis le 22/09/2026 — 256 abonnés, un worker appelé chaque minute, trois boîtes relevées en IMAP : ce qui casse casse pour de vrai.

Gitea : https://gitea.alpinux.org/alpinux.cedrica5l
ISPConfig : https://owni.alpinux.org:8080
AlpID (SSO) : https://alpid.alpinux.org — realm master


Procédure de déploiement

Vue d'ensemble

Projet Méthode Commande
home git pull sur serveur ssh alpinux.org "cd <web root> && git pull"
static (app) rsync local + restart cd ~/Projects/alpinux.static && scripts/deploy-app.sh
static (assets) rsync local cd ~/Projects/alpinux.static && scripts/push-assets.sh

Dans tous les cas : versionner avec git push avant de déployer.

static.alpinux.org

Le détail (app Flask et assets CDN) est dans ~/Projects/alpinux.static/README.md.

cd ~/Projects/alpinux.static
git push origin main         # versionner d'abord
scripts/deploy-app.sh        # app Flask → /opt/static-cdn + restart service
scripts/push-assets.sh       # logo/, wiki/, stats/, error/ → web root ISPConfig

Wiki

Rien à faire : un webhook Gitea construit et met en ligne à chaque push sur main. Voir https://wiki.alpinux.org/technique/deploiement-wiki/


Développement local

Projet Commande URL
~/Projects/alpinux.static python app/app.py http://localhost:5003
cd <projet>
python3 -m venv venv && source venv/bin/activate
pip install -r requirements.txt
cp .env.example .env && nano .env
flask run --port <port>

Authentification AlpID

Tous les projets Flask utilisent AlpID (SSO Keycloak).

  • Chaque projet a son propre client Keycloak (admin, dynamic, static-cdn, …)
  • Scopes : openid profile email
  • Autorisation : claim groups → sinon ADMIN_EMAILS → sinon tout utilisateur AlpID
  • Discovery URL : https://alpid.alpinux.org/realms/master/.well-known/openid-configuration

Credentials locaux

Le fichier .credentials (ignoré par git) centralise les accès à renseigner localement :

.credentials          ← à compléter manuellement, jamais commité

Il contient : token Gitea API, accès ISPConfig, accès AlpID admin, secrets clients Keycloak.
Utiliser source .credentials dans un script pour charger les variables.


Règle Claude Code

Lancer Claude depuis le sous-dossier du projet pour limiter le contexte :

cd ~/Projects/alpinux.static  && claude
cd ~/Projects/alpinux.wiki    && claude

Comptes personnels vs comptes de service

Alias SSH : alpinux.org → compte abonnelc.

Règle absolue

Un compte personnel (abonnelc ou tout autre) ne doit jouer aucun rôle dans le fonctionnement à long terme des services :

  • pas User= dans un unit systemd
  • pas propriétaire des fichiers de l'app ou des logs
  • pas dans la liste des groupes dont dépend un service en production
  • pas référencé dans un chown, setfacl, ou cron de production

Si un service dépend d'un compte personnel, sa disparition (départ, suppression du compte, changement de login) fait tomber le service en production.

Rôle d'abonnelc

abonnelc est un compte d'administration ponctuelle, limité à :

  • créer ou modifier les fichiers .env sur le serveur
  • redémarrer un service après un déploiement
  • effectuer des opérations admin exceptionnelles

Comptes de service

Chaque service tourne sous son propre utilisateur système dédié (ex. static-cdn pour static-cdn.service).
C'est ce compte qui possède les fichiers, les logs, et les droits nécessaires — pas abonnelc.


Serveur

Hostname owni.alpinux.org
OS Debian 12 (bookworm)
IPv4 51.91.79.148
IPv6 2001:41d0:404:200::3f85/128
Passerelle IPv6 2001:41d0:404:200::1
SSH ssh alpinux.org (alias → abonnelc@owni.alpinux.org)

Config IPv6 persistante : /etc/network/interfaces.d/60-ipv6.cfg
Cloud-init réseau désactivé : /etc/cloud/cloud.cfg.d/99-disable-network-config.cfg


Courrier sortant : tout passe par un relais

Depuis les 25-26 septembre 2026, Postfix ne remet plus directement aux destinataires : relayhost = [mail.acemail.fr]:587, en soumission authentifiée.

IP qui parle aux destinataires 176.9.125.188 (le relais), et non plus 51.91.79.148
SPF v=spf1 a mx include:_spf.acemail.fr -all
DKIM signé par owni avant la remise au relais
DMARC p=quarantine, rua=mailto:postmaster@alpinux.org

Trois conséquences qu'il vaut mieux connaître avant de chercher ailleurs :

  • La réputation d'expéditeur n'est plus la nôtre seule. Un rejet de plus compte contre une IP partagée avec les autres clients de l'hébergeur.
  • Un plafond d'envoi s'ajoute à celui de Postfix, celui du relais, et il n'est pas connu à ce jour. Le franchir se verrait en status=deferred dans /var/log/mail.log, avec un code 4.x.x venu du relais.
  • L'enveloppe doit survivre au relais. La messagerie utilise des adresses de retour variables (bounce+<référence>@alpinux.org) pour identifier les non-remises. Vérifié le 27/09 : le relais les préserve. À revérifier après tout changement chez l'hébergeur — la panne serait silencieuse, les rebonds cessant simplement d'arriver.

Bases de données

Six bases applicatives, déclarées dans ISPConfig, plus celles du système.

Base Service Sauvegarde
c1_messagerie_db messagerie.alpinux.org quotidienne, 1 copie
c1dolibarr dolibarr.alpinux.org — fichier des adhérents aucune
c1gitea gitea.alpinux.org — tous les dépôts aucune
c1alpid alpid.alpinux.org — le SSO aucune
c1_installparty installparty.alpinux.org aucune
c1_evenements événements aucune

S'y ajoutent dbispconfig, roundcube et phpmyadmin.

sudo mysql passe par le socket unix, sans mot de passe.


Sauvegardes : ce qui est couvert, et ce qui ne l'est pas

État au 27/09/2026, à corriger — voir le ticket #1.

  • Une base sur six est sauvegardée quotidiennement, la messagerie, dans /var/backup/web21/. Les cinq autres ne le sont pas, Dolibarr et Gitea compris.
  • Une seule copie conservée (backup_copies = 1) : une corruption remarquée deux jours plus tard n'est plus récupérable.
  • Les 14 sites sont à backup_interval = none côté fichiers.
  • Tout reste sur owni. Un disque perdu emporte les données et leurs copies. Ce que contient /var/backup/ispconfig/ ne concerne qu'ISPConfig lui-même.

Une sauvegarde qu'on n'a jamais restaurée est une hypothèse, pas une garantie.


Infra

infra/ est un dépôt git indépendant (alpinux-infra).
Il contient les configurations de référence pour audit et reconstruction :

infra/
├── conf/      → VirtualHost Apache par service
├── services/  → Units systemd
└── docs/      → Documentation déploiement par service

ne pas mentionner "sonnet" ou "claude"