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
255 lines
9.6 KiB
Markdown
255 lines
9.6 KiB
Markdown
# 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](https://gitea.alpinux.org/alpinux.cedrica5l/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](https://gitea.alpinux.org/alpinux.cedrica5l/alpinux-feedback) |
|
|
| `home/` | alpinux.org | HTML statique | [alpinux-home](https://gitea.alpinux.org/alpinux.cedrica5l/alpinux-home) |
|
|
| `portail/` | portail.alpinux.org | en construction | [alpinux-portail](https://gitea.alpinux.org/alpinux.cedrica5l/alpinux-portail) |
|
|
| `infra/` | — | Configs Apache + systemd | [alpinux-infra](https://gitea.alpinux.org/alpinux.cedrica5l/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](https://gitea.alpinux.org/alpinux.cedrica5l/alpinux-wiki) |
|
|
| `~/Projects/alpinux.admin` | admin.alpinux.org | [alpinux-admin](https://gitea.alpinux.org/alpinux.cedrica5l/alpinux-admin) |
|
|
| `~/Projects/alpinux.dynamic` | dynamic.alpinux.org | [alpinux-dynamic](https://gitea.alpinux.org/alpinux.cedrica5l/alpinux-dynamic) |
|
|
| `~/Projects/alpinux.static` | static.alpinux.org | [alpinux-static](https://gitea.alpinux.org/alpinux.cedrica5l/alpinux-static) |
|
|
| `~/Projects/alpinux.gitea` | gitea.alpinux.org | [alpinux-gitea](https://gitea.alpinux.org/alpinux.cedrica5l/alpinux-gitea) |
|
|
| `~/Projects/alpinux.messagerie` | messagerie.alpinux.org | [alpinux.messagerie](https://gitea.alpinux.org/alpinux.cedrica5l/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`.
|
|
|
|
```bash
|
|
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 |
|
|
|
|
```bash
|
|
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 :
|
|
|
|
```bash
|
|
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](https://gitea.alpinux.org/alpinux.cedrica5l/alpinux-owni/issues/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](https://gitea.alpinux.org/alpinux.cedrica5l/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"
|