Commit e75ae200 authored by Angedestenebres's avatar Angedestenebres 🐈

Documentation not linked to our services

parent afb28924
Pipeline #1256 passed with stages
in 41 seconds
---
title: Administration
---
Cette section est découpée en plusieurs catégories, elles-mêmes déclinées en plusieurs pages. Cliquez sur la catégorie de votre choix pour voir la listes des pages disponibles :
---
title: Conception de l'infrastructure
---
Voici les sujets traités dans cette section :
---
title: Docker
---
# Gestion des conteneurs
L'ensemble des données spécifiques aux applications, donc l'ensemble des données des conteneurs est stocké dans `/srv` sur une partition chiffrée.
## Orchestration
L'organisation des conteneurs repose sur les concepts de Compose. Les conteneurs sont organisés par application, le moins de mutualisation possible es# Gestion des conteneurs
L'ensemble des données spécifiques aux applications, donc l'ensemble des données des conteneurs est stocké dans `/srv` sur une partition chiffrée.
Le `/srv` lui-même est découpé en fonction des usages :
- `/srv/conf` : configurations générales
- `/srv/docker` : données internes de Docker
- `/srv/templates` : modèles de configuration de services
- `/srv/core` : projets compose d'infrastructure
- `/srv/apps` : projets compose des applications
- `/srv/users` : projets compose des services hébergés pour les utilisateurs
## Orchestration
L'organisation des conteneurs repose sur les concepts de Compose. Les conteneurs sont organisés par application, le moins de mutualisation possible est effectuée. Par exemple, chaque application dispose de son serveur de bases de données, de son serveur Redis si besoin, etc.
La configuration et les données de chaque application est stockée dans un dossier dédié dans `/srv/apps` ou `/srv/users`. Par exemple, `/srv/apps/mastodon`, `/srv/apps/mumble`. Ce dossier abrite ensuite idéalement un fichier compose `docker-compose.yml`, un dossier pour les éventuels fichiers de configuration `./conf` et un dossier de données, `./data`. Les applications plus complexes disposent d'une arborescence adaptée.
Le fichier `docker-compose.yml` ne doit pas contenir de données spécifiques à TeDomum et doit être publiable. Les données spécifiques sont importées par variables depuis un fichier `.env` situé dans le dossier de l'application.
# Documentation
La documentation est effectuée *in situ*, ou bien dans les fichiers `.yml`, de configuration, etc. ou bien dans des fichiers README.md, pour l'arborescence et les choix locaux de conception par exemple.
L'ensemble des fichiers `docker-compose.yml`, des fichiers de documentation, et des fichiers de configuration ne contenant pas de données sensibles, sont versionnés sur un dépôt Git public et commun à l'ensemble des hôtes.
# Services centraux
Les services mutualisés sont regroupés dans des projets compose dans `/srv/core`. A titre d'exemple, les services `traefik` (reverse proxy Web) et `fw` (gestion du firewall) sont dans `/srv/core/front`. Ils doivent être démarrés avant le reste de l'infrastructure.
---
title: Principes
---
Cette page décrit les principes de conception de l'infrastructure, les choix adoptés et leurs raisons. La description de l'installation ou de la configuration d'un hôte sont décrits séparément.
# Contraintes
## Libertés fondamentales
L'infrastructure doit exploiter exclusivement du logiciel libre : tous les OS doivent être libres, les paquets déployés libres, les logiciels utilisés libres, et les services administrables avec du logiciel libre.
Tous les services doivent être respectueux de la vie privée. Les logiciels employés ne doivent pas contenir de code de tracking par une tierce partie, et tous les outils de rapport de bug ou suivi par tiers doivent être désactivables, et désactivés.
## Sécurité de l'infrastructure
La confidentialité des données est essentielle. Toutes les données échangées, entre les clients et serveurs, entre les serveurs, et vers d'autres infrastructures (fédérations, sauvegarde, etc.) doivent être chiffrées en transport, ainsi que les interlocuteurs authentifiés.
Aucune garantie forte d'intégrité n'est requise en dehors des bonnes pratiques raisonnables. Concernant les services proposant d'éventuels outils de trésorerie ou comptabilité, l'intégrité doit être garantie au sens de la loi Finance. A ce titre, des sauvegardes plus régulières sont effectuées, avec une historisation des sauvegardes, pour assurer la confirmation au besoin d'un défaut d'intégrité ; aucune détection automatique n'est en place.
La disponibilité des données est une contrainte modérée. Aucune haute disponibilité au sens de la continuité d'activité n'est requise. La perte de données sur plus de 4h est toutefois inacceptable et doit être traitée par un plan de sauvegarde. La reprise d'activité doit pouvoir être effectuée en assurant du 99.9 (jusqu'à une journée d'indisponibilité) en cas de perte d'un hôte ou de défaillance d'un service et en assurant du 99. (jusqu'à trois jours d'indisponibilité) en cas d'incident majeur.
# Généralités
## Type d'hébergement
Idéalement, pour répondre à ces objectifs, TeDomum devrait s'auto-héberger jusqu'au niveau physique et exploiter la
connexion de FAI respectueux. La faisabilité technique n'est toutefois pas évidente et le choix est fait de louer de
l'infrastructure.
Afin de limiter les intervention en centre de données et le besoin de disponibilité ne justifiant pas une infrastructure
réseau et une redondance en dessous de la couche 3, le choix d'un prestataire IaaS baremetal est fait.
Afin de garder une indépendance en cas d'incident, un serveur demeure auto-hébergé et assure la sauvegarde régulière de l'ensemble du parc.
## Virtualisation
L'utilisation de la virtualisation pour isoler à des fins de maintenabilité et de sécurité n'est pas discutée. La technologie de virtualisation a évolué avec l'infrastructure. En l'état, afin de limiter les ressources consommées, le budget, et la maintenabilité, le choix de Docker est fait, accompagné de Docker Compose pour l'administration.
Pour assurer la confidentialité des données critiques en cas de compromission d'un service retenant moins d'attention, les services sont isolés sur des hôtes séparés par niveau de criticité : « administration », « sensible », « générique ».
## Réseau
L'infrastructure réseau repose essentiellement sur le modèle des fournisseurs IaaS choisis. Par serveur, une adresse IP d'administration permet la connexion à l'hôte par l'équipe TeDomum. D'autres adresses sont configurées pour exposer les services, en limitant toutefois le nombre d'adresse afin de borner les coûts.
Le routage est laissé au soin du fournisseur, même entre les hôtes. Les hôtes de l'infrastructure communiquent entre eux via des tunnels IPSec.
## Stockage
L'ensemble du stockage est local aux serveurs. Les données autres que les paquets système de l'hôte sont stockées dans une partition chiffrées par LUKS et déchiffrée manuellement au démarrage de l'hôte.
---
title: Réseau et filtrage
---
# Adressage
L'ensemble de l'infrastructure est dual stack IPv4 et IPv6, les communications internes privilégient IPv6, notamment les tunnels IPSec entre hôtes routent les préfixes IPv6.
Chaque hôte dispose d'une adresse IPv4 d'administration, d'une ou plusieurs adresses IPv4 exposant des services, et d'un `/56` IPv6. Sur ce préfixe sont choisies une adresse d'administration, autant d'adresses exposant des services qu'en IPv4, et chaque conteneur dispose d'une adresse globale routable.
## Plan DNS
Trois domaines principaux sont exploités par l'infrastructure :
- `tedomum.in` pour le coeur de l'infrastructure ;
- `tedomum.net` pour les services ;
- `tedomum.org` pour le reste.
`tedomum.in` contient :
- une paire d'enregistrements `A` et `AAAA` par machine physique, avec les adresses d'administration ;
- une paire d'enregistrements `A` et `AAAA` par adresse exposant des services ;
- des enregistrements NS avec GLUE pour le bootstraping DNS.
`tedomum.net` contient un enregistrement `CNAME` par service, pointant vers l'enregistrment `tedomum.in` correspondant. Pour les services ne supportant pas l'emploi de `CNAME` (MX, Matrix, Jabber, etc.) les enregistrements `A` et `AAAA` sont répliqués dans `tedomum.net`.
`tedomum.org` contient les enregistrements accessoires, tels que les reverse DNS de bouncers IRC, les noms de services non publics, etc.
# Exposition des services
L'exposition des services a fait l'objet de nombreuses expérimentations. L'exposition de ports utilisant le proxy userland de Docker est exclue car les conteneurs ne disposent plus de l'adresse source de la connexion ; l'apport pour la privée est intéressant mais plusieurs conteneurs font usage de cette adresse, notamment l'antispam à la réception des mails.
L'exposition grâce aux règles `iptables` configurées par Docker n'est pas satisfaisante car ne couvrant pas IPv6. La doctrine classique consiste à assigner des adresses fixes IPv6 par conteneur, l'approche nécessiterait toutefois une maintenance alourdie, en termes d'assignation d'adresses, de DNS, etc.
Le support des règles d'exposition Docker Compose incluant des adresses IPv6 a été contribué au projet et publié dans la version 1.15. Ce support est couplé à un script `docker-jinja` parcourant régulièrement la liste des conteneurs pour mettre à jour une configuration `nftables` et l'appliquer. La configuration complète est documentée dans `core/front`.
# Filtrage
Le filtrage déployé est modérément strict : les hôtes sont limités aux flux légitimes entrants et sortants. Les conteneurs peuvent établir des flux entre eux et vers Internet.
Les connexions entrantes sont autorisées exclusivement à destination des ports exposés explicitement par chaque conteneur. L'ensemble du filtrage est assuré par le script `nftables` décrit ci-dessus.
---
title: Sauvegardes
---
# Plan de sauvegarde
Les données sont catégorisées comme suit :
- génériques, il s'agit de notre configuration partagée sur Gitlab, elle est versionnée et copiée sur nos postes, ainsi que conservée dans l'archive Gitlab ;
- spécifiques, il s'agit des configurations spécifiques éditées directement sur les serveurs, elles sont sauvegardées en incrémental ;
- applicatives, il s'agit des données fichiers générées par les applications, elles sont sauvegardées en incrémental ;
- bases de données, il s'agit des données stockée en MySQL, PGSQL, etc. elles sont sauvegardées en continu et incrémental.
Les sauvegardes incrémentales reposent sur une synchronisation régulière et un élagage de l'historique, les règles sont les suivantes :
- 1 backup / 6h (soit 4 backups par jour)
- 5 quotidiens / semaines, au delà backups quotidiens élagués
- 4 hebdomadaires / mois, au delà backups hebdomadaires élagués
- 3 mensuels, au delà les backups mensuels sont élagués
Il est donc possible de restorer jusqu'à J-3 mois, avec une granularité journalière dans la semaine, hebdomadaire dans le mois, puis mensuelle.
Les sauvegardes de bases de données reposent sur les journaux d'écriture des bases. L'ensemble des journaux d'écriture est synchronisé avant d'être supprimé des serveurs. Une sauvegarde complète est effectuée mensuellement pour améliorer les performances de restoration.
# Réalisation des sauvegardes
## Sauvegardes incrémentales
Toutes les sauvegardes incrémentales sont réalisées par `restic`. L'outil est déployé sur chaque serveur, et l'ensemble des serveurs dépose ses sauvegardes dans un dépôt dédié, sur un serveur hébergé par un des membres.
Les sauvegardes sont toutes chiffrées avant envoi, aucune donnée en clair ne quitte donc les serveurs.
Les clés de déchiffrement des sauvegardes sont conservées par les administrateurs dans une archive chiffrée personnelle.
## Sauvegardes de bases de données
Les journaux binaires des bases de données sont stockés dans un dossier `wal` par projet. Ce dossier est sauvegardé par borg avec une configuration de rétention spécifique.
Pour MySQL, les lignes suivantes sont ajoutées à la configuration des projets :
```
volumes:
- ./wal:/wal
command: --log-bin=/wal
```
Pour PostgreSQL, les lignes suivantes sont ajoutées à la configuration des projets :
```
volumes:
- ./wal:/wal
- ./postgresql.conf:/var/lib/postgresql/data/postgresql.conf
```
Un script exécuté par `crontab` parcourt une fois par mois l'ensemble des projets déployés dans `/srv/apps` et `/srv/users`. Lorsqu'il rencontre une base de données Mysql ou Postgresql, il déclenche les actions de sauvegarde.
Pour MySQL : ``mysqldump --all-databases --master-data --single-transaction | gzip > /wal/$BACKUPNAME.sql.gz``
Pour PostGres : ``pg_basebackup -Ft -z -D /wal/$BACKUPNAME -U postgres``
---
title: Versions
---
A force de faire évoluer l'infrastructure, on s'aperçoit que les évolutions de fond sont des évolutions lentes, et qu'avec plus de 20 services, on ne les migre pas tous en même temps, ni même les serveurs eux-mêmes. Sans versionner précisément chaque changement, cette page résume l'historique des concepts d'infrastructure et les versions associées. Ainsi, pour chaque service on peut faire référence à la version d'infrastructure associée.
# Versions de services
## Tifa
- Hôtes : Anakin
- Déploiement : Compose v2, v3
- Configuration : environnement et manuelle
- Version : fork git, branche tedomum-prod, rebase depuis l'upstream
- Build : images Docker par Gitlab CI
## Reno
- Hôtes : Anakin
- Déploiement : Compose v2
- Configuration : environnement et manuelle
- Version : fork git, tag par version, rebase depuis l'upstream
- Build : images Docker par Gitlab CI
## Aeris
- Hôtes : Leia, Vador, Jabba, Anakin
- Déploiement : Compose v2
- Configuration : environnement et manuelle
- Version : gérée à la main
- Build : images Docker officielles et internes
## Sephi
- Hôtes : Luke
- Déploiement : Docker et source montées en volume
- Configuration : manuelle
- Version : gérée à la main
- Build : images Docker officielles
## Cloud
- Hôtes : Choubaka, Obiwan, Han
- Déploiement : manuellement depuis les sources
- Configuration : manuelle
- Version : gérée à la main
- Build : manuellement depuis les sources
# Versions d'hôtes
## TODO (développement)
Hôtes : ???
Conteneurs : ??? (containerd, Docker)
Clustering : ??? (k3s, Swarm)
Déploiement : ??? (helm, stack)
Frontaux : traefik 2
Réseau : ???
Backups : borg
Industrialisation : git
## TODO (tests)
Hôtes : Debian 10
Conteneurs : Docker
Clustering : aucun
Frontaux : traefik 2
Réseau : jinja nftables et wireguard entre hôtes
Backups : borg
Industrialisation : git
## Anakin (04-2019 - aujourd'hui)
- Hôtes : Debian 10
- Conteneurs : Docker
- Clustering : aucun
- Déploiement : Compose v2
- Frontaux : traefik 1
- Réseau : jinja nftables et wireguard entre hôtes
- Backups : borg
- Industrialisation : git
## Jabba (06-2018 - aujourd'hui)
- Hôtes : Debian 10
- Conteneurs : Docker
- Clustering : aucun
- Déploiement : Compose v2
- Frontaux : traefik 1
- Réseau : jinja nftables et wireguard entre hôtes
- Backups : borg
- Industrialisation : git
## Vador (2017-2018)
- Hôtes : Debian 9
- Conteneurs : Docker
- Clustering : aucun
- Déploiement : Compose v2
- Frontaux : traefik 1
- Réseau : jinja nftables et wireguard entre hôtes
- Backups : rsnapshot
- Industrialisation : git
## Leia (2015-2016)
- Hôtes : Debian 9
- Conteneurs : Docker
- Clustering : aucun
- Déploiement : Compose v2
- Frontaux : nginx jwilder
- Réseau : jinja nftables et ipsec entre hôtes
- Backups : rsnapshot
- Industrialisation : git
## Luke (2013-2014)
- Hôtes : Debian 9
- Conteneurs : Docker
- Clustering : aucun
- Déploiement : manuel (bash)
- Frontaux : nginx jwilder
- Réseau : natif Docker
- Backups : rsync
- Industrialisation : git
## Han (2011-2013)
- Hôtes : Debian 7 puis 8
- Conteneurs : OpenVZ
- Clustering : Proxmox
- Déploiement : manuel (ssh)
- Frontaux : nginx manuel
- Réseau : IP par service, RP nginx
- Backups : Proxmox + scp
- Industrialisation : git + salt
## Obinwan (2009-2010)
- Hôtes : Debian 6 puis 7
- Conteneurs : LXC
- Clustering : aucun
- Déploiement : manuel (ssh + bash)
- Frontaux : nginx manuel
- Réseau : IP par service, RP nginx
- Backups : rsync
- Industrialisation : git + puppet
## Choubaka (2008-2009)
- Hôtes : Debian 6
- Conteneurs : vServer
- Clustering : aucun
- Déploiement : manuel (ssh)
- Frontaux : Apache manuel
- Réseau : IP par service, RP Apache
- Backups : scp
- Industrialisation : aucune
---
title: Fiches administrateur
---
Voici les sujets traités dans cette section :
---
title: Démarrage d'un serveur
---
Fiche réflexe pour le démarrage d'un hyperviseur. Ces opérations n'ont pas
vocation à être automatisées puisqu'une intervention humaine est requise quoi
qu'il arrive.
Monter les systèmes de fichiers
-------------------------------
1. déchiffrer le LUKS : ``cryptsetup luksOpen /dev/mdX data``
2. monter le volume métier : ``mount /srv``
3. vérifier : ``ls /srv``
Démarrer Docker et vérifier l'état
----------------------------------
1. démarrer Docker ``systemctl start docker``
2. par service : ``cd /srv/<service>`` (`core` en priorité)
3. vérifier l'état ``docker-compose ps``
---
title: Installation d'un service
---
Lorsqu'une application est ajoutée, on vérifie d'abord qu'elle n'est pas déjà configurée (par exemple, une application
DNS dispose déjà d'une configuration qu'il suffit d'activer).
# Configurer une application existante
On ajoute l'application à la liste du checkout et mettre à jour :
```
cd /srv
echo app >> .git/info/sparse-checkout
git pull origin master
```
On configure les éléments nécessaires à l'application, sans éditer le `docker-compose.yml` ou les autres fichiers génériques du dépôt.
# Ajouter une nouvelle application
## Structure
On choisit le nom de l'application pour ne pas coïncider avec celui d'une application existante. On créer le dossier de l'application dans `/srv` :
```
cd /srv/app
```
Enfin, on crée le fichier `docker-compose.yml`, les éventuels dossiers de données et de configuration associés :
```
mkdir /srv/app/conf
mkdir /srv/app/data
vim /srv/app/docker-compose.yml
```
Au besoin, on ajoute des répertoires de données par service, ou pour plusieurs types de données, en employant des noms significatifs, par exemple : `uploads`, `attachments`, `db`, etc.
En fin de configuration, ces fichiers sont commités sur le dépôt Git :
```
cd /srv
echo app >> .git/info/sparse-checkout
git add app/docker-compose.yml
git commit
git push origin master
```
## Configuration Compose
Dans le fichier `docker-compose`, on choisit des noms de service Docker Compose significatifs, tels que `db`, `web`, `backend`, etc. On n'inclut que des données génériques dans le `docker-compose.yml`, voué à être publié.
Toutes les données non génériques seront importées depuis un fichier `.env`, soit par passage explicite de variable :
```
ports:
$ipv4:25:25
$ipv6:25:25
```
Soit par passage implicite directement dans l'environnement du conteneur :
```
environment:
- DATABASE_USER
- DATABASE_PASSWORD
```
Le fichier `.env` contient alors :
```
ipv4=1.2.3.4
ipv6=2101:f8c2:4401::1
DATABASE_USER=myuser
DATABASE_PASSWORD=mypassword
```
## Exposition de services
Pour exposer un service directement via UDP ou TCP, on choisit une des paires d'adresses publiques de la machine, et on configure dans le `docker-compose.yml` les ports exposés, en utilisant des variables pour la généricité.
Pour exposer un service Web, on configure les labels `traefik`, comme suit :
```
labels:
- traefik.enable=true
- traefik.frontend.rule=Host:domain.tedomum.net
- traefik.frontend.contentSecurityPolicy=default-src 'self'; style-src 'self' 'unsafe-inline'
- traefik.port=8081
```
La configuration CSP est optionnelle mais conseillée ; le contenu du header doit être adapté à l'application.
---
title: Installation d'un système
---
Les hôtes sont basés sur Debian stretch, dont le guide d'installation sert
de base à ce document.
Contrainte non négligeable : les machines employées sont nécessairement
préinstallées par le fournisseur de services IaaS. En conséquence, les
options d'installation ne correspondent pas exactement aux attentes et des
ajustements doivent être effectués.
Partitionnement
---------------
Le partitionnement par défaut convient plutôt :
- un RAID1 software entre les deux disques ;
- une partition système de 25G ;
- une partition de données pour le reste ;
- pas de swap (par sécurité).
Première connexion, gestion des utilisateurs
--------------------------------------------
A la première connexion, on s'assure :
- que seul l'utilisateur root est activé ;
- que la connexion SSH est autorisée exclusivement grâce aux clés ;
- que le mot de passe de root est réinitialisé pour l'accès console.
Chez online par exemple, après s'être connecté en tant qu'utilisateur :
```
sudo su
mkdir ~/.ssh
echo "..." > ~/.ssh/authorized_keys
userdel tedomum
rm -rf /home/tedomum
```
... puis reconnexion directement en tant que root.
Gestion des paquets et nettoyage du système
-------------------------------------------
Mettre à jour le sources.list :
```
deb http://ftp.fr.debian.org/debian stretch main
deb http://security.debian.org/ stretch/updates main
deb http://apt.dockerproject.org/repo debian-stretch main
```
Puis supprimer les paquets superflus :
```
apt autoremove -y exim4-base exim4-config bind9 exim4-config nfs-common pinentry-gtk2
```
Enfin, installer les outils de base :
```
apt install docker-engine cryptsetup btrfs-tools
```
On désactive le démon Docker par défaut afin que celui-ci ne démarre pas avant que LUKS ne soit monté :
```
systemctl disable docker
```
On installe Docker Compose depuis le site officiel (téléchargement via Github).
Partition de données
--------------------
On complète en chiffrant la partition de données :
```
cryptsetup luksFormat /dev/md1
cryptsetup luksOpen /dev/md1 data
mkfs.btrfs /dev/mapper/data
```
On adapte en conséquence le fstab :
```
# /etc/fstab: static file system information.
# <file system> <mount point> <type> <options> <dump> <pass>
/dev/md0 / ext4 errors=remount-ro 0 1
/dev/mapper/data /srv btrfs defaults,noauto 0 2
```
Récupération de la configuration
--------------------------------
La configuration est stockée sur un dépôt Git. On génère d'abord les clés SSH de l'hôte :
```
ssh-keygen -b 4096
```
On installe la clé publique sur le dépôt Git et on clône le dépôt en activant le sparse-checkout :
```
mount /srv
cd /srv
git init .
git remote add origin git@git.tedomum.net:tedomum/documentation.git
git config core.sparseCheckout true
echo core >> .git/info/sparse-checkout
echo other >> .git/info/sparse-checkout
git pull origin master
```
Configuration réseau
--------------------
La configuration réseau est particulièrement simple. Les bridges sont créés par Docker. On copie et on adapte le fichier de configuration fourni :
```
cp /srv/other/interfaces /etc/network/interfaces
vim /etc/network/interfaces
```
Le fichier hôtes doit contenir quelques références :
```