From f3b7e90693bf2b51a53a23d98a60bbf04065103a Mon Sep 17 00:00:00 2001 From: Quentin Dufour Date: Wed, 1 Mar 2023 19:45:01 +0100 Subject: rework infrastructures --- content/operations/_index.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'content/operations') diff --git a/content/operations/_index.md b/content/operations/_index.md index 7ab49f2..5ccc5a2 100644 --- a/content/operations/_index.md +++ b/content/operations/_index.md @@ -1,9 +1,9 @@ -+++ -title = "Opérations" -description = "Opérations" -weight = 100 -sort_by = "weight" -+++ +--- +title: "Opérations" +description: "Opérations" +weight: 100 +sort_by: "weight" +--- Ce manuel recense notre savoir-faire technique, il a pour but d'accompagner nos opérateur·ices dans la réalisation de leurs tâches. -- cgit v1.2.3 From 58951873b23624332bde25fa88099e02203277a7 Mon Sep 17 00:00:00 2001 From: Quentin Dufour Date: Wed, 1 Mar 2023 21:18:40 +0100 Subject: reorg operations --- content/operations/2020-01-20-changement-ip.md | 55 ++++ .../2021-07-12-synapse-bdd-rempli-disque.md | 24 ++ .../operations/2022-01-xx-glusterfs-corruption.md | 38 +++ content/operations/2023-02-xx.md | 28 ++ "content/operations/SSH_sans_\303\251cran.md" | 53 ++++ content/operations/_index.md | 2 + content/operations/acces.md | 10 + content/operations/acces/_index.md | 8 - content/operations/acces/pass.md | 197 ------------ content/operations/acces/ssh.md | 9 - content/operations/courantes.md | 8 + content/operations/courantes/_index.md | 6 - content/operations/courantes/email.md | 31 -- content/operations/create_database.md | 36 +++ content/operations/debogage.md | 9 + content/operations/debogage/_index.md | 7 - content/operations/debogage/jitsi.md | 103 ------- content/operations/debogage/plume.md | 32 -- content/operations/deploiement/_index.md | 7 - content/operations/deploiement/app/_index.md | 33 -- .../operations/deploiement/app/create_database.md | 34 --- content/operations/deploiement/grappe/_index.md | 19 -- content/operations/deploiement/grappe/stolon.md | 95 ------ .../deploiement/noeud/SSH_sans_\303\251cran.md" | 51 ---- content/operations/deploiement/noeud/_index.md | 14 - .../noeud/guide_cr\303\251ation_n\305\223ud.md" | 102 ------- .../deploiement/noeud/pr\303\251requis.md" | 39 --- content/operations/deployer.md | 35 +++ content/operations/email.md | 33 ++ .../guide_cr\303\251ation_n\305\223ud.md" | 104 +++++++ content/operations/jitsi.md | 105 +++++++ content/operations/maintien_en_condition.md | 12 + content/operations/maintien_en_condition/_index.md | 10 - content/operations/maintien_en_condition/matrix.md | 101 ------ content/operations/matrix.md | 103 +++++++ content/operations/nixcfg.md | 21 ++ content/operations/noeud.md | 16 + content/operations/pannes.md | 15 + .../operations/pannes/2020-01-20-changement-ip.md | 53 ---- .../pannes/2021-07-12-synapse-bdd-rempli-disque.md | 22 -- .../pannes/2022-01-xx-glusterfs-corruption.md | 36 --- content/operations/pannes/_index.md | 6 - content/operations/pannes/petits-incidents.md | 27 -- content/operations/pass.md | 199 ++++++++++++ content/operations/petits-incidents.md | 29 ++ content/operations/pg_basebackup.md | 338 +++++++++++++++++++++ content/operations/plume.md | 34 +++ content/operations/prestataires.md | 27 ++ content/operations/prestataires/_index.md | 25 -- "content/operations/pr\303\251requis.md" | 41 +++ content/operations/rclone.md | 78 +++++ content/operations/restic.md | 179 +++++++++++ content/operations/sauvegardes.md | 47 +++ content/operations/sauvegardes/_index.md | 45 --- content/operations/sauvegardes/pg_basebackup.md | 336 -------------------- content/operations/sauvegardes/rclone.md | 76 ----- content/operations/sauvegardes/restic.md | 177 ----------- content/operations/ssh.md | 11 + content/operations/stolon.md | 97 ++++++ content/operations/supervision.md | 23 ++ content/operations/supervision/_index.md | 12 - content/operations/vue_ensemble.md | 62 ++++ content/operations/vue_ensemble/_index.md | 60 ---- 63 files changed, 1872 insertions(+), 1773 deletions(-) create mode 100644 content/operations/2020-01-20-changement-ip.md create mode 100644 content/operations/2021-07-12-synapse-bdd-rempli-disque.md create mode 100644 content/operations/2022-01-xx-glusterfs-corruption.md create mode 100644 content/operations/2023-02-xx.md create mode 100644 "content/operations/SSH_sans_\303\251cran.md" create mode 100644 content/operations/acces.md delete mode 100644 content/operations/acces/_index.md delete mode 100644 content/operations/acces/pass.md delete mode 100644 content/operations/acces/ssh.md create mode 100644 content/operations/courantes.md delete mode 100644 content/operations/courantes/_index.md delete mode 100644 content/operations/courantes/email.md create mode 100644 content/operations/create_database.md create mode 100644 content/operations/debogage.md delete mode 100644 content/operations/debogage/_index.md delete mode 100644 content/operations/debogage/jitsi.md delete mode 100644 content/operations/debogage/plume.md delete mode 100644 content/operations/deploiement/_index.md delete mode 100644 content/operations/deploiement/app/_index.md delete mode 100644 content/operations/deploiement/app/create_database.md delete mode 100644 content/operations/deploiement/grappe/_index.md delete mode 100644 content/operations/deploiement/grappe/stolon.md delete mode 100644 "content/operations/deploiement/noeud/SSH_sans_\303\251cran.md" delete mode 100644 content/operations/deploiement/noeud/_index.md delete mode 100644 "content/operations/deploiement/noeud/guide_cr\303\251ation_n\305\223ud.md" delete mode 100644 "content/operations/deploiement/noeud/pr\303\251requis.md" create mode 100644 content/operations/deployer.md create mode 100644 content/operations/email.md create mode 100644 "content/operations/guide_cr\303\251ation_n\305\223ud.md" create mode 100644 content/operations/jitsi.md create mode 100644 content/operations/maintien_en_condition.md delete mode 100644 content/operations/maintien_en_condition/_index.md delete mode 100644 content/operations/maintien_en_condition/matrix.md create mode 100644 content/operations/matrix.md create mode 100644 content/operations/nixcfg.md create mode 100644 content/operations/noeud.md create mode 100644 content/operations/pannes.md delete mode 100644 content/operations/pannes/2020-01-20-changement-ip.md delete mode 100644 content/operations/pannes/2021-07-12-synapse-bdd-rempli-disque.md delete mode 100644 content/operations/pannes/2022-01-xx-glusterfs-corruption.md delete mode 100644 content/operations/pannes/_index.md delete mode 100644 content/operations/pannes/petits-incidents.md create mode 100644 content/operations/pass.md create mode 100644 content/operations/petits-incidents.md create mode 100644 content/operations/pg_basebackup.md create mode 100644 content/operations/plume.md create mode 100644 content/operations/prestataires.md delete mode 100644 content/operations/prestataires/_index.md create mode 100644 "content/operations/pr\303\251requis.md" create mode 100644 content/operations/rclone.md create mode 100644 content/operations/restic.md create mode 100644 content/operations/sauvegardes.md delete mode 100644 content/operations/sauvegardes/_index.md delete mode 100644 content/operations/sauvegardes/pg_basebackup.md delete mode 100644 content/operations/sauvegardes/rclone.md delete mode 100644 content/operations/sauvegardes/restic.md create mode 100644 content/operations/ssh.md create mode 100644 content/operations/stolon.md create mode 100644 content/operations/supervision.md delete mode 100644 content/operations/supervision/_index.md create mode 100644 content/operations/vue_ensemble.md delete mode 100644 content/operations/vue_ensemble/_index.md (limited to 'content/operations') diff --git a/content/operations/2020-01-20-changement-ip.md b/content/operations/2020-01-20-changement-ip.md new file mode 100644 index 0000000..9b6ce23 --- /dev/null +++ b/content/operations/2020-01-20-changement-ip.md @@ -0,0 +1,55 @@ +--- +title: "Janvier 2020" +description: "Janvier 2020: changement imprévu d'adresses IP" +date: 2022-12-22 +dateCreated: 2022-12-22 +weight: 10 +extra: + parent: 'operations/pannes.md' +--- + +Le 20 janvier free a changé mon IP, un peu comme partout en France. +Ça concerne l'IPv4 et le préfixe IPv6. +Ici le bon vieux Bortzmoinsbien qui tweet : https://twitter.com/bortzmeyer/status/1351434290916155394 + +Max a update tout de suite l'IPv4 mais avec un TTL de 4h le temps de propagation est grand. +J'ai réduit les entrées sur les IP à 300 secondes, soit 5 minutes, le minimum chez Gandi, à voir si c'est une bonne idée. +Reste à update les IPv6, moins critiques pour le front facing mais utilisées pour le signaling en interne... + +## Le fameux signaling +Ça pose un gros problème avec Nomad (et en moindre mesure avec Consul). +En effet, Nomad utilise l'IPv6 pour communiquer, il faut donc changer les IPs de tous les noeuds. +Problème ! On peut pas faire la migration au fur et à mesure car, changeant d'IP, les noeuds ne seront plus en mesure de communiquer. +On n'a pas envie de supprimer le cluster et d'en créer un nouveau car ça voudrait dire tout redéployer ce qui est long également (tous les fichiers HCL pour Nomad, tout le KV pour consul). +On ne peut pas non plus la faire à la bourrin en stoppant tous les cluster, changer son IP, puis redémarrer. +Enfin si, Consul accepte mais pas Nomad, qui lui va chercher à communiquer avec les anciennes IP et n'arrivera jamais à un consensus. + +Au passage j'en ai profité pour changer le nom des noeuds car la dernière fois, Nomad n'avait PAS DU TOUT apprécié qu'un noeud ayant le même nom change d'IP. Ceci dit, si on utilise de facto le `peers.json` c'est peut être pas problématique. À tester. + +Du coup, après moult réflexions, la silver bullet c'est la fonction outage recovery de nomad (consul l'a aussi au besoin). +Elle est ici : https://learn.hashicorp.com/tutorials/consul/recovery-outage +En gros, il faut arrêter tous les nodes. +Ensuite créer un fichier à ce path : `/var/lib/nomad/server/raft/peers.json` +Ne vous laissez pas perturber par le fichier `peers.info` à côté, il ne faut pas le toucher. +Après la grande question c'est de savoir si le cluster est en Raft v2 ou Raft v3. +Bon ben nous on était en Raft v2. Si vous vous trompez, au redémarrage Nomad va crasher avec une sale erreur : + +``` +nomad: failed to start Raft: error="recovery failed to parse peers.json: json: cannot unmarshal string into Go value of type raft.configEntry" +``` + +(je me suis trompé bien sûr). +Voilà, après il ne vous reste plus qu'à redémarrer et suivre les logs, cherchez bien la ligne où il dit qu'il a trouvé le peers.json. + +## Les trucs à pas oublier + + - Reconfigurer le backend KV de traefik (à voir à utiliser des DNS plutôt du coup) + - Reconfigurer l'IPv4 publique annoncée à Jitsi + +## Ce qui reste à faire + + - Mettre à jour les entrées DNS IPv6, ce qui devrait créer : + - digitale.machine.deuxfleurs.fr + - datura.machine.deuxfleurs.fr + - drosera.machine.deuxfleurs.fr + - Mettre à jour l'instance garage sur io diff --git a/content/operations/2021-07-12-synapse-bdd-rempli-disque.md b/content/operations/2021-07-12-synapse-bdd-rempli-disque.md new file mode 100644 index 0000000..d907705 --- /dev/null +++ b/content/operations/2021-07-12-synapse-bdd-rempli-disque.md @@ -0,0 +1,24 @@ +--- +title: "Juillet 2021" +description: "Juillet 2021: la BDD Synapse remplit nos disques" +date: 2022-12-22 +dateCreated: 2022-12-22 +weight: 20 +extra: + parent: 'operations/pannes.md' +--- + +# La BDD synapse rempli nos disques + +Todo: finir ce blog post et le dupliquer ici https://quentin.dufour.io/blog/2021-07-12/chroniques-administration-synapse/ + +Le WAL qui grossissait à l'infini était également du à un SSD défaillant dont les écritures était abyssalement lentes. + +Actions mises en place : + - Documentation de comment ajouter de l'espace sur un disque différent avec les tablespaces + - Interdiction de rejoindre les rooms avec une trop grande complexité + - nettoyage de la BDD à la main (rooms vides, comptes non utilisés, etc.) + - Remplacement du SSD défaillant + +Actions à mettre en place : + - Utiliser les outils de maintenance de base de données distribuées par le projet matrix diff --git a/content/operations/2022-01-xx-glusterfs-corruption.md b/content/operations/2022-01-xx-glusterfs-corruption.md new file mode 100644 index 0000000..734b2d8 --- /dev/null +++ b/content/operations/2022-01-xx-glusterfs-corruption.md @@ -0,0 +1,38 @@ +--- +title: "Janvier 2022" +description: "Janvier 2022: Corruptions GlusterFS" +date: 2022-12-22 +dateCreated: 2022-12-22 +weight: 30 +extra: + parent: 'operations/pannes.md' +--- + +# Corruption GlusterFS + +Suite au redémarrage d'un serveur, les emails ne sont plus disponibles. +Il apparait que GlusterFS ne répliquait plus correctement les données depuis un certain temps. +Suite à ce problème, il a renvoyé des dossiers Dovecot corrompu. +Dovecot a reconstruit un index sans les emails, ce qui a désynchronisé les bàl des gens. +À la fin, certaines boites mails ont perdu tous leurs emails. +Aucune sauvegarde des emails n'était réalisée. +Le problème a été créé cet été quand j'ai réinstallé un serveur. +J'ai installé sur une version de Debian différente. +La version de GlusterFS était pinnée dans un sources.list, en pointant vers le repo du projet gluster +Mais le pinning était pour la version de debian précédente. +Le sources.list a été ignoré, et c'est le gluster du projet debian plus récent qui a été installé. +Ces versions étaient incompatibles mais silencieusement. +GlusterFS n'informe pas proactivement non plus que les volumes sont désynchronisées. +Il n'y a aucune commande pour connaitre l'état du cluster. +Après plusieurs jours de travail, il m'a été impossible de remonter les emails. + +Action mise en place : + - Suppression de GlusterFS + - Sauvegardes journalière des emails + - Les emails sont maintenant directement sur le disque (pas de haute dispo) + +Action en cours de mise en place : + - Développement d'un serveur IMAP sur Garage + + + diff --git a/content/operations/2023-02-xx.md b/content/operations/2023-02-xx.md new file mode 100644 index 0000000..a612060 --- /dev/null +++ b/content/operations/2023-02-xx.md @@ -0,0 +1,28 @@ +--- +title: "Février 2023" +description: "Février 2023: perte de 2 zones" +date: 2022-12-22 +dateCreated: 2022-12-22 +weight: 30 +extra: + parent: 'operations/pannes.md' +--- + +En février 2023, garage a été inaccessible car io à Rennes +était cassé depuis une semaine sans qu'on s'en rende compte, +et qu'ensuite neptune a subi une coupure fibre. + +On a pu remonter garage assez rapidement car Trinity +a pu reconfigurer io dès que le problème a été identifié. +La discussion a été rendue plus compliqué que prévu +car on a eu des problèmes de déchiffrement des messages sur matrix. + +Mais la coupure fibre de neptune nous a fait nous rendre +compte qu'on ne pouvait pas tout reschedule à Lyon. +Et à Bruxelles, impossible de schedule car la conf +routeur ne permet pas (encore) de prendre du trafic entrant. + +Voici les changements qu'on a décidé de mettre en oeuvre à la suite de ce problème : + - Alerting sur les serveurs (pas encore fait) + - Conversations en clair sur deuxfleurs::infra + - Accepter du trafic entrant à BRX (pas encore fait) diff --git "a/content/operations/SSH_sans_\303\251cran.md" "b/content/operations/SSH_sans_\303\251cran.md" new file mode 100644 index 0000000..610daae --- /dev/null +++ "b/content/operations/SSH_sans_\303\251cran.md" @@ -0,0 +1,53 @@ +--- +title: "Installer NixOS en SSH" +description: "Installer NixOS en SSH sans écran ni clavier" +date: 2022-08-24 +dateCreated: 2021-08-24 +weight: 12 +extra: + parent: 'operations/noeud.md' +--- + +Quick tip avant d'oublier pour installer une de nos machines ThinkCentre via SSH sous NixOS ; c'est la seule solution quand on a pas d'écran ni de clavier sous la main. +Pré-requis : une clé USB, un ordi sous NixOS. + +On va créer une image d'installation nous même qui démarre le SSH et configure root avec notre clé. On créer un fichier `iso.nix` : + +```nix +{config, pkgs, ...}: +{ + imports = [ + + + # Provide an initial copy of the NixOS channel so that the user + # doesn't need to run "nix-channel --update" first. + + ]; + + systemd.services.sshd.wantedBy = pkgs.lib.mkForce [ "multi-user.target" ]; + users.users.root.openssh.authorizedKeys.keys = [ + "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDT1+H08FdUSvdPpPKdcafq4+JRHvFVjfvG5Id97LAoROmFRUb/ZOMTLdNuD7FqvW0Da5CPxIMr8ZxfrFLtpGyuG7qdI030iIRZPlKpBh37epZHaV+l9F4ZwJQMIBO9cuyLPXgsyvM/s7tDtrdK1k7JTf2EVvoirrjSzBaMhAnhi7//to8zvujDtgDZzy6aby75bAaDetlYPBq2brWehtrf9yDDG9WAMYJqp//scje/WmhbRR6eSdim1HaUcWk5+4ZPt8sQJcy8iWxQ4jtgjqTvMOe5v8ZPkxJNBine/ZKoJsv7FzKem00xEH7opzktaGukyEqH0VwOwKhmBiqsX2yN quentin@dufour.io" + ]; +} +``` + +On construit l'image à partir de ce fichier de conf : + +```bash +nix-build '' -A config.system.build.isoImage -I nixos-config=iso.nix + +``` + +On le copie sur la clé USB : + +``` +dd if=result/iso/*.iso of=/dev/??? status=progress +sync +``` + +On branche la clé sur le serveur, on branche le serveur sur le réseau, on démarre le serveur et on surveille le routeur pour connaitre son IP (nom de domaine `nixos`). +Ensuite on se connecte dessus : + +``` +ssh root@192.168.1.X +``` diff --git a/content/operations/_index.md b/content/operations/_index.md index 5ccc5a2..7f64bcd 100644 --- a/content/operations/_index.md +++ b/content/operations/_index.md @@ -3,6 +3,8 @@ title: "Opérations" description: "Opérations" weight: 100 sort_by: "weight" +extra: + parent: 'operations/_index.md' --- Ce manuel recense notre savoir-faire technique, il a pour but d'accompagner nos opérateur·ices dans la réalisation de leurs tâches. diff --git a/content/operations/acces.md b/content/operations/acces.md new file mode 100644 index 0000000..76ea226 --- /dev/null +++ b/content/operations/acces.md @@ -0,0 +1,10 @@ +--- +title: "Accès" +description: "Accès" +sort_by: "weight" +weight: 5 +extra: + parent: 'operations/_index.md' +--- + +Ici l'on traite de comment gagner accès au cluster de Deuxfleurs, quand on a reçu la _terrible responsabilité_ de sysadmin. Vous êtes prêt⋅e ? Alors entrez dans [le dépôt des secrets](./pass/). diff --git a/content/operations/acces/_index.md b/content/operations/acces/_index.md deleted file mode 100644 index 08824bc..0000000 --- a/content/operations/acces/_index.md +++ /dev/null @@ -1,8 +0,0 @@ -+++ -title = "Accès" -description = "Accès" -sort_by = "weight" -weight = 5 -+++ - -Ici l'on traite de comment gagner accès au cluster de Deuxfleurs, quand on a reçu la _terrible responsabilité_ de sysadmin. Vous êtes prêt⋅e ? Alors entrez dans [le dépôt des secrets](./pass/). \ No newline at end of file diff --git a/content/operations/acces/pass.md b/content/operations/acces/pass.md deleted file mode 100644 index 357db2e..0000000 --- a/content/operations/acces/pass.md +++ /dev/null @@ -1,197 +0,0 @@ -+++ -title = "Le dépôt des secrets" -description = "Le dépôt des secrets" -weight = 10 -+++ - -We use [pass, 'the standard unix password manager'](https://www.passwordstore.org/), to manage our key store securely at Deuxfleurs. Getting access to our production involves publishing one's GPG key (through Gitea) and importing/verifying/signing every other sysadmin's key, before setting up `pass`. Lastly, you will be able to set your shell password on the desired cluster (`prod` or `staging`, at the time of writing). - -Our process was adapted from [this Medium article](https://medium.com/@davidpiegza/using-pass-in-a-team-1aa7adf36592) — thanks, David! - -## You are new and want to access the secrets repository - -You need a GPG key to start with. -If you do not already have one, you can generate a new one with: - -```bash -gpg2 --expert --full-gen-key -# Personnaly I use `9) ECC and ECC`, `1) Curve 25519`, and `5y` -``` - -In any case, you need to export your public key. Upload the output (public key) of the following command to [your Gitea account](https://git.deuxfleurs.fr/user/settings/keys). - - -```bash -gpg2 --export --armor -``` - -It is now publicly accessible at `https://git.deuxfleurs.fr/.gpg` - -Inform all the other sysadmins that you have published your key for them to import/verify/sign it. - -### Import/verify/sign every other sysadmin's key into your keychain - -You now need to import and sign every other sysadmin's GPG key. For example, import Quentin's key to your keychain as follow: - -```bash -gpg2 --import <(curl https://git.deuxfleurs.fr/quentin.gpg) -gpg2 --list-keys -# pub ed25519/0xE9602264D639FF68 2022-04-19 [SC] [expire : 2027-04-18] -# Empreinte de la clef = 8023 E27D F1BB D52C 559B 054C E960 2264 D639 FF68 -# uid [ ultime ] Quentin Dufour -# sub cv25519/0xA40574404FF72851 2022-04-19 [E] [expire : 2027-04-18] -``` - -> How to read this snippet: -> - the key id: `E9602264D639FF68` -> - the key fingerprint: `8023 E27D F1BB D52C 559B 054C E960 2264 D639 FF68` - -To perform the check, you need another communication channel (ideally physically, otherwise through the phone, Matrix if you already trusted the other person, or else). Compare the signature you read with the sysadmin's. If they match, you good. - -Now that you have verified the key, sign it: - -```bash -gpg --edit-key quentin@deuxfleurs.fr # by email -# or -gpg --edit-key E9602264D639FF68 # by key id -# gpg> lsign -# (say yes, maybe several times) -# gpg> save -``` - -Once you signed every sysadmin, ask an administrator to add your key to the secrets keystore. They will need to [Add a sysadmin](#add-a-sysadmin). - -Once your fellow admin has finished their job, you are ready to install `pass`: - -```bash -sudo apt-get install pass # Debian + Ubuntu -sudo yum install pass # Fedora + RHEL -sudo zypper in password-store # OpenSUSE -sudo emerge -av pass # Gentoo -sudo pacman -S pass # Arch Linux -brew install pass # macOS -pkg install password-store # FreeBSD -``` - -*Go to [passwordstore.org](https://www.passwordstore.org/) for more information about pass*. - -Download the repository: - -``` -mkdir -p ~/.password-store -cd ~/.password-store -git clone git@git.deuxfleurs.fr:Deuxfleurs/secrets.git deuxfleurs -``` - -Finally check that everything works: - -```bash -pass show deuxfleurs -``` - -If you see a listing, it worked. Last step is to select a shell password for yourself on the cluster you are now in charge of (`prod` or `staging`, at the time of writing). - - -Clone the nixcfg repository: - -``` -git clone git@git.deuxfleurs.fr:Deuxfleurs/nixcfg.git -cd nixcfg -``` - -Use the passwd utility to set your shell password: -``` -./passwd -> Usage: ./passwd -> The cluster name must be the name of a subdirectory of cluster/ -``` - -This commited changes to Deuxfleurs' password store, do verify your modifications before pushing them: -``` -cd ~/.password-store/deuxfleurs -git diff -git push -``` - -You should now be able to `ssh` into our infrastructure with a unified shell password. This is explicated in `nixcfg` repo's [README](https://git.deuxfleurs.fr/Deuxfleurs/nixcfg#how-to-operate-a-node). Be cautious, and enjoy! - -> With great power comes great responsibility. - ---- - ---- - -## You are a sysadmin and want to operate the secrets repository - -## Initialise the pass store - -> These instructions are for _bootstrapping_ the pass store. **Don't do it on Deuxfleurs' secrets repository** (don't be like ADRN). You would override the existing sysadmins and generally have a bad time. - -Generate a new password store named deuxfleurs for you: - -``` -pass init -p deuxfleurs you@example.com -``` - -Add a password in this store, it will be encrypted with your gpg key: - -```bash -pass generate deuxfleurs/backup_nextcloud 20 -# or -pass insert deuxfleurs/backup_nextcloud -``` - -## Add a sysadmin - -Edit `~/.password-store/acme/.gpg-id` and add the id of the newbie: - -``` -alice@example.com -jane@example.com -bob@example.com -``` - -Make sure that you trust the keys of your new sysadmin: - -``` -$ gpg --edit-key jane@example.com -gpg> lsign -gpg> y -gpg> save -``` - -Now re-encrypt the secrets and push your modifications: - -``` -pass init -p deuxfleurs $(cat ~/.password-store/deuxfleurs/.gpg-id) -cd ~/.password-store/deuxfleurs -git commit -git push -``` - -They will now be able to decrypt any password: - -``` -pass deuxfleurs/backup_nextcloud -``` - -## Sharing with git - -To create the repo _on bootstrap exclusively_: - -```bash -cd ~/.password-store/deuxfleurs -git init -git add . -git commit -m "Initial commit" -# Set up remote -git push -``` - -To retrieve the repo: - -```bash -mkdir -p ~/.password-store -cd ~/.password-store -git clone https://git.example.com/org/repo.git deuxfleurs -``` diff --git a/content/operations/acces/ssh.md b/content/operations/acces/ssh.md deleted file mode 100644 index e053934..0000000 --- a/content/operations/acces/ssh.md +++ /dev/null @@ -1,9 +0,0 @@ -+++ -title = "SSH" -description = "SSH" -weight = 100 -+++ - -Voir si on documente comment gérer SSH depuis GPG - -# Ajout de la clé au cluster diff --git a/content/operations/courantes.md b/content/operations/courantes.md new file mode 100644 index 0000000..d3da720 --- /dev/null +++ b/content/operations/courantes.md @@ -0,0 +1,8 @@ +--- +title: "Opérations courantes" +description: "Opérations courantes" +weight: 35 +sort_by: "weight" +extra: + parent: 'operations/_index.md' +--- diff --git a/content/operations/courantes/_index.md b/content/operations/courantes/_index.md deleted file mode 100644 index 1cf3b95..0000000 --- a/content/operations/courantes/_index.md +++ /dev/null @@ -1,6 +0,0 @@ -+++ -title = "Opérations courantes" -description = "Opérations courantes" -weight = 15 -sort_by = "weight" -+++ diff --git a/content/operations/courantes/email.md b/content/operations/courantes/email.md deleted file mode 100644 index d28608e..0000000 --- a/content/operations/courantes/email.md +++ /dev/null @@ -1,31 +0,0 @@ -+++ -title = "Emails" -description = "Emails" -weight = 10 -+++ - -# Support d'un nom de domaine personnalisé - - 1. xxx - 1. Communiquez lui votre nom de domaine pour qu'il l'ajoute dans `ou=domains,ou=groups,dc=deuxfleurs,dc=fr` - 2. Communiquez lui l'adresse email que vous souhaitez pour qu'il change l'entrée `mail` dans votre profil utilisateur - 3. Si vous souhaitez avoir une boite mais plusieurs alias, demandez un champs `uid` dans votre profil utilisateur - - 2. Vous devez ensuite rajouter les entrées pour votre nom de domaine en éditant votre zone : - 1. L'entrée MX pour recevoir les emails -```bind -@ MX 10 email-in.deuxfleurs.fr -``` - 2. L'entrée SPF pour autoriser notre IP à délivrer des emails en votre nom : -```bind -@ TXT "v=spf1 mx:out.deuxfleurs.fr -all" -``` - 3. L'entrée DKIM pour autoriser notre postfix+opendkim à délivrer des emails en votre nom : -``` -smtp._domainkey TXT "v=DKIM1; h=sha256; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtdZp4qrgZR+6R7HeAkuLGJ/3L/6Ungvf5zwrMq6T8Tu931j2G4lYuPtsxyn9fZkT4y7DlX0waktLDBOCwf7X78nLEWjAFWiJTeWGRGhRdYRUFpscs9NUN0P+46jKlabibG3XTKd1DeAmywTu6o1oO03yiolrgKD1zgyDRFeUTfSwZIdPrdbcBSA1arda4WFtcBIrSygM9b4jtlqfQwGDrsMLbCBfVHDn4WfmDWyNg0gDAkuLrYClNETk6aqIyj9fC8srKri0Qp3cRagCn+fjBvuxP35qWWJH7Rnnh/tuEDr1ufuNYO2KgJZ7JdMidUotxXE8cfU+OrEWQf4mIYeJ4wIDAQAB" -``` - 4. L'entrée DMARC pour indiquer le comportement à adopter si les contraintes précédentes ne sont pas satisfaites : -``` -_dmarc TXT "v=DMARC1; p=reject; sp=reject; adkim=s; aspf=s; rua=mailto:contact@deuxfleurs.fr!10m; ruf=mailto:contact@deuxfleurs.fr!10m; rf=afrf; pct=100; ri=86400" -``` - 3. C'est tout ! Vous devrez probablement attendre 24/48h que les changements se propagent. diff --git a/content/operations/create_database.md b/content/operations/create_database.md new file mode 100644 index 0000000..5c46d63 --- /dev/null +++ b/content/operations/create_database.md @@ -0,0 +1,36 @@ +--- +title: "Créer une BDD" +description: "Création d'une base de données pour une nouvelle application" +date: 2022-12-22 +dateCreated: 2022-12-22 +weight: 11 +extra: + parent: 'operations/deployer.md' +--- + +## 1. Create a LDAP user and assign a password for your service + +Go to guichet.deuxfleurs.fr + + 1. Everything takes place in `ou=services,ou=users,dc=deuxfleurs,dc=fr` + 2. Create a new user, like `johny` + 3. Generate a random password with `openssl rand -base64 32` + 4. Hash it with `slappasswd` + 5. Add a `userpassword` entry with the hash + +This step can also be done using the automated tool `secretmgr.py` in the app folder. + +## 2. Connect to postgres with the admin users + +```bash +# 1. Launch ssh tunnel given in the README +# 2. Make sure you have postregsql client installed locally +psql -h localhost -U postgres -W postgres +``` + +## 3. Create the binded users with LDAP in postgres + the database + +```sql +CREATE USER sogo; +Create database sogodb with owner sogo encoding 'utf8' LC_COLLATE = 'C' LC_CTYPE = 'C' TEMPLATE template0; +``` diff --git a/content/operations/debogage.md b/content/operations/debogage.md new file mode 100644 index 0000000..467a760 --- /dev/null +++ b/content/operations/debogage.md @@ -0,0 +1,9 @@ +--- +title: "Débogage" +description: "Débogage" +weight: 60 +sort_by: "weight" +extra: + parent: 'operations/_index.md' +--- + diff --git a/content/operations/debogage/_index.md b/content/operations/debogage/_index.md deleted file mode 100644 index 5afe881..0000000 --- a/content/operations/debogage/_index.md +++ /dev/null @@ -1,7 +0,0 @@ -+++ -title = "Débogage" -description = "Débogage" -weight = 60 -sort_by = "weight" -+++ - diff --git a/content/operations/debogage/jitsi.md b/content/operations/debogage/jitsi.md deleted file mode 100644 index 1ca45be..0000000 --- a/content/operations/debogage/jitsi.md +++ /dev/null @@ -1,103 +0,0 @@ -+++ -title = "Jitsi" -description = "" -date = 2021-11-09T12:53:23.811Z -dateCreated = 2021-11-09T12:46:50.731Z -weight = 20 -+++ - -## 2020-04-02 Campagne de debug Jitsi - -Contact: Quentin - -### Description du problème - -Les conversations à 3+ donc relayées par le serveur ne fonctionnent pas bien. -Louison m'a rapporté que ça avait marché pour lui (3 utilisateurs avec un Webkit). -Mais moi ça a échoué hier soir (01/04/2020) avec des participants sous Firefox. -Le bug est toujours le même : on entend 2 personnes sur 3 ou on voit 2 personnes sur 3, on recharge la page et c'est quelqu'un d'autre pour qui ça ne fonctionne plus. Souvent c'est que dans un sens. -À chaque fois en passant sur Facebook Messenger, le problème est résolu instantanément. -Par contre Facebook Messenger impose Google Chrome/Chromium pour les visio de groupe (et ne supporte donc pas Firefox). - -D'où mes 2 suspicions : - -- Firefox a un bug quelconque dans sa pile WebRTC déclenché par le mode conversation de groupe -- Jitsi a un problème avec les déconnexions/changement de connexion/petit hoquets du réseau et n'arrive pas à se reconnecter. Ça pourrait être rendu pire à certain moment de la journée comme le soir où le réseau est plus sollicité. Et ce serait provoqué lors du reload on repasse de 3 à 2, en P2P donc puis de nouveau de 2 à 3. - -### Approfondissement - -Avant d'aller plus loin, nous avons voulu prendre le temps d'identifier précisément les problèmes d'expérience utilisateurs et leur corrélation avec la plateforme de l'utilisateur (navigateur, OS). - -Pour celà, nous avons suivi deux approches : -1. Mener nos propres tests -2. Chercher d'autres retours - -#### Mener nos propres tests - -Nous avons effectué deux appels : un avec Firefox seulement et un avec Chrome/Chromium seulement. -Merci à Alex, Adrien et Maximilien pour leur participation. - -Voilà les conclusions que nous avons tirées de nos tests : - -- L'appel avec Firefox a déclenché le bug immédiatement, peu importe la version de Firefox ou de l'OS (firefox stable/nightly, fedora stable/beta, etc.) -- Le passage de tout le monde sous Chrome/Chromium a permis d'avoir une conversation stable. -- Adrien avait sa Livebox avec pare-feu configuré en mode "élevé" et a dû ajouter dans sa liste blanche les ports utilisés par Jitsi (`4443/tcp` et `10000/udp` au moment du test, seul un des deux a besoin d'être accessible) - -Nous avons donc demandé à Adrien quels étaient les ports ouverts par défaut dans le mode élevé de sa box : - -![Livebox Parefeu Personnalisé](/img/operations/livebox_parefeu_personnalise.png) - -Nous avons dans un premier temps retenu le port `995/tcp` pour Jitsi, le port UDP ne pouvant être changé (limitation de Jitsi). -Cependant, pour des raisons de sécurité, les navigateurs ne peuvent pas utiliser les ports en dessous de `1024/*`, à l'exception des ports `80/tcp` et `443/tcp` comme l'indique ;'issue [#3583](https://bugs.chromium.org/p/webrtc/issues/detail?id=3583) de Chromium. - -La capture n'indique pas de port TCP supérieur à 1024, nous ne pouvons donc pas résoudre ce problème de notre côté, car à l'heure actuelle, nos ports `80/tcp` et `443/tcp` sont utilisés et nous n'avons qu'une seule IP publique. -Les utilisateurs activant le parefeu en mode élevé devront ajouter une exception dans leur parefeu eux-mêmes. - -#### Chercher d'autres retours - -[Tedomum](https://tedomum.net/) a eu connaissance de problèmes similaires. -Ils ont également identifié Firefox et assurent qu'avec l'application Android ça marche bien. -Ils me confirment que le problème vient bien du logiciel et non pas de notre déploiement. -Ils m'ont pointé entre autres vers cette issue github [#4758](https://github.com/jitsi/jitsi-meet/issues/4758) -Apparemment une issue est dédiée en particulier au problème que nous rencontrons de déconnexion partielle d'un participant, mais nous ne l'avons pas encore retrouvée. - -### Correctifs - - 1. Notre instance Jitsi a été reconfigurée pour refuser Firefox. Suivre l'avancée du développement de Jitsi pour Firefox - * [#4758](https://github.com/jitsi/jitsi-meet/issues/4758) - * [#5439](https://github.com/jitsi/jitsi-meet/issues/5439) - * _À compléter_ - 2. Pour relayer la vidéo à travers la plupart des parefeux, notre `videobridge` Jitsi devait écouter sur le port `443/tcp`. Or ce port est déjà utilisé par notre frontal HTTPS. À défaut, Jitsi est maintenant configuré avec `8080/tcp` et `10000/udp` (contre `4443/tcp` et `10000/udp` avant). - * Un déploiement en IPv6 pourrait résoudre le problème pour une partie des utilisateurs - * Avoir un cluster géo-distribué avec plusieurs IPv4 pourrait également résoudre le problème - * Avoir un frontend layer 4 (niveau TCP) qui trouve une signature pour router du DTLS vers videobridge et du TLS vers traefik - -### À propos du control/data plane de Jitsi - -Notre videobridge écoute donc sur les ports `8080/tcp` et `10000/udp`. - -WebRTC fonctionne en deux étapes : -- Des offres doivent être échangées via un serveur de signaling quelconque -- Ensuite, ces offres servent à connecter des clients directement via un protocole TCP ou UDP avec un thin layer propre à WebRTC - -#### Le control plane de Jitsi : Prosody sur HTTPS via Bosh/XMPP - -Le serveur de signaling Jitsi n'est autre que le serveur de chat prosody. -Pour ça, prosody est exposé à travers HTTP grâce au protocole BOSH (XMPP overs HTTPS). -Une fois l'offre reçue ([exemple](/assets/operations/exemple_offre.txt)), elle est enregistrée dans le navigateur à l'aide de `setRemoteDescription` pour initialiser le data plane. -On peut débugger le signaling WebRTC sous Chromium avec [chrome://webrtc-internarls](chrome://webrtc-internals/). - - -Quand plus de deux participants sont connectés dans la conversation, Jitsi n'envoie pas les offres de chaque participant aux autres participants. À la place, elle envoie qu'une seule offre, celle de son VideoBridge. - -Ainsi, le VideoBridge est une sorte de client WebRTC particulier, qui récolte et redispatche à travers WebRTC tous les flux video/audio. - -#### Le data plane de Jitsi : videobridge sur DTLS/SCTP via WebRTC - -WebRTC utilise deux formats de paquets selon [Mozilla Developer Network|RTCDataChannel|DataFormat](https://developer.mozilla.org/en-US/docs/Web/API/RTCDataChannel#Data_format) : -- `UDP/DTLS/SCTP` -- `TCP/DTLS/SCTP` - -On a donc un format de données arbitraire encapsulé dans du SCTP lui-même encapsulé dans du DTLS. -DTLS est prévu pour les datagrammes à l'origine, car WebRTC est prévu d'abord pour fonctionner sous UDP. -Le TCP est là en mode dégradé, en secours, il sert juste de tunnel pour relayer des datagrammes. diff --git a/content/operations/debogage/plume.md b/content/operations/debogage/plume.md deleted file mode 100644 index c256a45..0000000 --- a/content/operations/debogage/plume.md +++ /dev/null @@ -1,32 +0,0 @@ -+++ -title = "Plume" -description = "Plume" -date = 2022-12-22 -dateCreated = 2022-12-22 -weight = 11 -+++ - -## Bug and debug - -If you can't follow a new user and have this error: - -``` -2022-04-23T19:26:12.639285Z WARN plume::routes::errors: Db(DatabaseError(UniqueViolation, "duplicate key value violates unique constraint \"follows_unique_ap_url\"")) -``` - -You might have an empty field in your database: - -``` -plume=> select * from follows where ap_url=''; - id | follower_id | following_id | ap_url -------+-------------+--------------+-------- - 2118 | 20 | 238 | -(1 row) -``` - -Simply set the `ap_url` as follows: - -``` -plume=> update follows set ap_url='https://plume.deuxfleurs.fr/follows/2118' where id=2118; -UPDATE 1 -``` diff --git a/content/operations/deploiement/_index.md b/content/operations/deploiement/_index.md deleted file mode 100644 index 4986c67..0000000 --- a/content/operations/deploiement/_index.md +++ /dev/null @@ -1,7 +0,0 @@ -+++ -title = "Déploiement" -description = "Déploiement" -weight = 10 -sort_by = "weight" -+++ - diff --git a/content/operations/deploiement/app/_index.md b/content/operations/deploiement/app/_index.md deleted file mode 100644 index 710e2e5..0000000 --- a/content/operations/deploiement/app/_index.md +++ /dev/null @@ -1,33 +0,0 @@ -+++ -title = "Applications" -description = "Déploiement d'une application" -sort_by = "weight" -date = 2022-12-22 -weight = 30 -+++ - - -# Empaqueter - -Packager avec nix un conteneur Docker, le publier - -# Secrets - -Créer les secrets avec `secretmgr` - -# Service - -Créer un service Nomad - -Voir les différentes déclarations : - - diplonat - - tricot - -# Sauvegardes - -Voir la section appropriée - -# Surveillance - -Voir la section appropriée - diff --git a/content/operations/deploiement/app/create_database.md b/content/operations/deploiement/app/create_database.md deleted file mode 100644 index e5f8a72..0000000 --- a/content/operations/deploiement/app/create_database.md +++ /dev/null @@ -1,34 +0,0 @@ -+++ -title = "Créer une BDD" -description = "Création d'une base de données pour une nouvelle application" -date = 2022-12-22 -dateCreated = 2022-12-22 -weight = 11 -+++ - -## 1. Create a LDAP user and assign a password for your service - -Go to guichet.deuxfleurs.fr - - 1. Everything takes place in `ou=services,ou=users,dc=deuxfleurs,dc=fr` - 2. Create a new user, like `johny` - 3. Generate a random password with `openssl rand -base64 32` - 4. Hash it with `slappasswd` - 5. Add a `userpassword` entry with the hash - -This step can also be done using the automated tool `secretmgr.py` in the app folder. - -## 2. Connect to postgres with the admin users - -```bash -# 1. Launch ssh tunnel given in the README -# 2. Make sure you have postregsql client installed locally -psql -h localhost -U postgres -W postgres -``` - -## 3. Create the binded users with LDAP in postgres + the database - -```sql -CREATE USER sogo; -Create database sogodb with owner sogo encoding 'utf8' LC_COLLATE = 'C' LC_CTYPE = 'C' TEMPLATE template0; -``` diff --git a/content/operations/deploiement/grappe/_index.md b/content/operations/deploiement/grappe/_index.md deleted file mode 100644 index 80de97d..0000000 --- a/content/operations/deploiement/grappe/_index.md +++ /dev/null @@ -1,19 +0,0 @@ -+++ -title = "Grappe" -description = "Grappe" -weight = 20 -date = 2022-12-22 -sort_by = "weight" -+++ - -# Installation - -Pointer vers le dépot nixcfg (précédemment le ansible de Deuxfleurs/infrastructure). - -Passer sur Wireguard, Nomad, Consul, Diplonat, (Tricot, Garage), etc. - -# Les secrets - -# Découverte des noeuds - - diff --git a/content/operations/deploiement/grappe/stolon.md b/content/operations/deploiement/grappe/stolon.md deleted file mode 100644 index 4a683f4..0000000 --- a/content/operations/deploiement/grappe/stolon.md +++ /dev/null @@ -1,95 +0,0 @@ -+++ -title = "Stolon" -description = "Comment déployer Stolon" -date = 2022-12-22 -dateCreated = 2022-12-22 -weight = 11 -+++ - -Spawn container: - -```bash -docker run \ - -ti --rm \ - --name stolon-config \ - --user root \ - -v /var/lib/consul/pki/:/certs \ - superboum/amd64_postgres:v11 -``` - - -Init with: - -``` -stolonctl \ - --cluster-name chelidoine \ - --store-backend=consul \ - --store-endpoints https://consul.service.prod.consul:8501 \ - --store-ca-file /certs/consul-ca.crt \ - --store-cert-file /certs/consul2022-client.crt \ - --store-key /certs/consul2022-client.key \ - init \ - '{ "initMode": "new", - "usePgrewind" : true, - "proxyTimeout" : "120s", - "pgHBA": [ - "host all postgres all md5", - "host replication replicator all md5", - "host all all all ldap ldapserver=bottin.service.prod.consul ldapbasedn=\"ou=users,dc=deuxfleurs, dc=fr\" ldapbinddn=\"\" ldapbindpasswd=\"\" ldapsearchattribute=\"cn\"" - ] - }' - -``` - -Then set appropriate permission on host: - -``` -mkdir -p /mnt/{ssd,storage}/postgres/ -chown -R 999:999 /mnt/{ssd,storage}/postgres/ -``` - -(102 is the id of the postgres user used in Docker) -It might be improved by staying with root, then chmoding in an entrypoint and finally switching to user 102 before executing user's command. -Moreover it would enable the usage of the user namespace that shift the UIDs. - - - -## Upgrading the cluster - -To retrieve the current stolon config: - -``` -stolonctl spec --cluster-name chelidoine --store-backend consul --store-ca-file ... --store-cert-file ... --store-endpoints https://consul.service.prod.consul:8501 -``` - -The important part for the LDAP: - -``` -{ - "pgHBA": [ - "host all postgres all md5", - "host replication replicator all md5", - "host all all all ldap ldapserver=bottin.service.2.cluster.deuxfleurs.fr ldapbasedn=\"ou=users,dc=deuxfleurs,dc=fr\" ldapbinddn=\"cn=admin,dc=deuxfleurs,dc=fr\" ldapbindpasswd=\"\" ldapsearchattribute=\"cn\"" - ] -} -``` - -Once a patch is writen: - -``` -stolonctl --cluster-name pissenlit --store-backend consul --store-endpoints http://consul.service.2.cluster.deuxfleurs.fr:8500 update --patch -f /tmp/patch.json -``` - -## Log - -- 2020-12-18 Activate pg\_rewind in stolon - -``` -stolonctl --cluster-name pissenlit --store-backend consul --store-endpoints http://consul.service.2.cluster.deuxfleurs.fr:8500 update --patch '{ "usePgrewind" : true }' -``` - -- 2021-03-14 Increase proxy timeout to cope with consul latency spikes - -``` -stolonctl --cluster-name pissenlit --store-backend consul --store-endpoints http://consul.service.2.cluster.deuxfleurs.fr:8500 update --patch '{ "proxyTimeout" : "120s" }' -``` diff --git "a/content/operations/deploiement/noeud/SSH_sans_\303\251cran.md" "b/content/operations/deploiement/noeud/SSH_sans_\303\251cran.md" deleted file mode 100644 index 41a19f7..0000000 --- "a/content/operations/deploiement/noeud/SSH_sans_\303\251cran.md" +++ /dev/null @@ -1,51 +0,0 @@ -+++ -title = "Installer NixOS en SSH" -description = "Installer NixOS en SSH sans écran ni clavier" -date = 2022-08-24 -dateCreated = 2021-08-24 -weight = 12 -+++ - -Quick tip avant d'oublier pour installer une de nos machines ThinkCentre via SSH sous NixOS ; c'est la seule solution quand on a pas d'écran ni de clavier sous la main. -Pré-requis : une clé USB, un ordi sous NixOS. - -On va créer une image d'installation nous même qui démarre le SSH et configure root avec notre clé. On créer un fichier `iso.nix` : - -```nix -{config, pkgs, ...}: -{ - imports = [ - - - # Provide an initial copy of the NixOS channel so that the user - # doesn't need to run "nix-channel --update" first. - - ]; - - systemd.services.sshd.wantedBy = pkgs.lib.mkForce [ "multi-user.target" ]; - users.users.root.openssh.authorizedKeys.keys = [ - "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDT1+H08FdUSvdPpPKdcafq4+JRHvFVjfvG5Id97LAoROmFRUb/ZOMTLdNuD7FqvW0Da5CPxIMr8ZxfrFLtpGyuG7qdI030iIRZPlKpBh37epZHaV+l9F4ZwJQMIBO9cuyLPXgsyvM/s7tDtrdK1k7JTf2EVvoirrjSzBaMhAnhi7//to8zvujDtgDZzy6aby75bAaDetlYPBq2brWehtrf9yDDG9WAMYJqp//scje/WmhbRR6eSdim1HaUcWk5+4ZPt8sQJcy8iWxQ4jtgjqTvMOe5v8ZPkxJNBine/ZKoJsv7FzKem00xEH7opzktaGukyEqH0VwOwKhmBiqsX2yN quentin@dufour.io" - ]; -} -``` - -On construit l'image à partir de ce fichier de conf : - -```bash -nix-build '' -A config.system.build.isoImage -I nixos-config=iso.nix - -``` - -On le copie sur la clé USB : - -``` -dd if=result/iso/*.iso of=/dev/??? status=progress -sync -``` - -On branche la clé sur le serveur, on branche le serveur sur le réseau, on démarre le serveur et on surveille le routeur pour connaitre son IP (nom de domaine `nixos`). -Ensuite on se connecte dessus : - -``` -ssh root@192.168.1.X -``` \ No newline at end of file diff --git a/content/operations/deploiement/noeud/_index.md b/content/operations/deploiement/noeud/_index.md deleted file mode 100644 index d44044a..0000000 --- a/content/operations/deploiement/noeud/_index.md +++ /dev/null @@ -1,14 +0,0 @@ -+++ -title = "Noeud" -description = "Déploiement d'un noeud" -date = 2022-08-23 -dateCreated = 2021-08-23 -sort_by = "weight" -+++ - -# Déployer un nœud au sein de l'infrastructure Deuxfleurs -Déployer un nœud au sein de l'infrastructure Deuxfleurs demande un certaine préparation et représente un processus particulier. - -Avant de se lancer, [mieux vaut vérifier les prérequis pour y parvenir](./prerequis/). Une fois ceci fait, on peut suivre [le guide décrivant la procédure](./guide-creation-noeud/). - -Si vous avez une machine à installer, mais aucun écran & clavier à brancher dessus pour la configurer, référez-vous au [guide d'installation de NixOs en SSH](./ssh-sans-ecran/). diff --git "a/content/operations/deploiement/noeud/guide_cr\303\251ation_n\305\223ud.md" "b/content/operations/deploiement/noeud/guide_cr\303\251ation_n\305\223ud.md" deleted file mode 100644 index 907d4a8..0000000 --- "a/content/operations/deploiement/noeud/guide_cr\303\251ation_n\305\223ud.md" +++ /dev/null @@ -1,102 +0,0 @@ -+++ -title = "Guide de création d'un nœud" -description = "Guide de création d'un nœud" -date = 2022-08-23 -dateCreated = 2022-08-23 -weight = 11 -+++ - -# Guide d'initialisation de nœud Deuxfleurs -Ce guide explique comment initialiser un nœud pour l'infrastructure de Deuxfleurs. Nous partons de zéro, c'est-à-dire avec une machine que nous venons de récupérer, avec une mémoire vide, et que nous venons de brancher. À titre d'exemple, nous illustrerons de temps en temps les opérations avec une de nos machines (un Thinkcentre de Lenovo). - -## Configuration de l'UEFI -Configurons d'abord quelques paramètres dans l'UEFI de la machine. Démarrez-là et appuyez sur la touche pour accéder à ce menu. Chez nous, il s'agit de F1. Si le PXE est activé, désactivons-le : un attaquant présent sur le réseau local pourrait faire démarrer une machine sur une installation malveillante. Vérifions que les *C-States* sont pris en charge, cela permet une meilleure gestion de l'énergie. Configurons également la machine pour qu'elle démarre après avoir subi une coupure électrique, cela se révèlera pratique lorsqu'il y en aura une. Si l'option est là, autorisons le démarrage sans clavier branché, pour ne pas être embêté lorsque nous démarrons une machine pour SSH dessus. Enfin, dans le cadre de l'infrastructure Deuxfleurs, nous supporterons uniquement l'UEFI, nous pouvons donc désactiver les options de compatibilité BIOS. - -## Installation de NixOS - -> Aucun écran ou clavier n'est disponible pour l'ordinateur cible ? NixOS peut être installé en SSH. Suivre les instructions sur [cette page](/operations/deploiement/noeud/ssh-sans-ecran). - -Pour installer NixOS, nous aurons besoin d'une clé USB avec une image amorçable (*live*) de NixOS dessus. Nous pouvons télécharger la distribution linux en 64 bits et en version minimale (sans interface graphique et avec moins d'utilitaires) sur le [site officiel](https://nixos.org/download.html). Pour écrire l'image sur le support USB, on peut faire `dd if=chemin-vers-le-fichier-iso of=/dev/sdX status=progress; sync`, en remplaçant `sdX` par le fichier périphérique correspondant à la clé, trouvé avec `lsblk` par exemple. -Alternativement, cela peut être l'occasion de créer une clé USB formatée avec [Ventoy](https://ventoy.net), un utilitaire très pratique -qui permet d'avoir plusieurs images ISO bootables depuis une même clef USB (utile si vous n'arrêtez pas de reformater vos clefs pour passer d'une distribution à une autre!) - -Branchons la clé USB et démarrons dessus. Chez nous, c'est possible grâce à un menu accessible via la touche F12. Lançons NixOS sans option particulière. Accordons-nous tous les droits et configurons un clavier habituel. On peut également vérifier la connexion internet : -``` -$ sudo su -# loadkeys fr-latin9 -# ping deuxfleurs.fr -``` -Nous pouvons faire `lsblk` pour examiner les disques de la machine. Chez nous, nous avons simplement un disque dur complètement vide de 500Go associé à `/dev/sda`. Nous allons formater le disque avec `cgdisk` : -``` -# cgdisk /dev/sda -``` -Nous créons d'abord, avec l'option `New`, une partition qui commence au début, fait 512Mo, avec un code hexadécimal `EF00`, et que nous appelerons «EFI» : c'est le secteur de démarrage. -Puis nous créons à la suite une partition de 8Go, avec un code hexadécimal `8200`, nommée «swap» : c'est l'espace d'échange. -Enfin sur tout le reste, nous créons une partition avec un code hexadécimal `8300`, que nous appelerons par exemple «root» : c'est la racine du système linux. -Pour appliquer les changements, nous utilisons l'option `Write`. Nous pouvons ensuite quitter avec `Quit`, et éventuellement vérifier le résultat avec `lsblk`. - -Finalisons les partitions. Dans notre cas, nous devons créer les systèmes avec : -``` -# mkfs.fat -F 32 /dev/sda1 -# mkswap /dev/sda2 -# mkfs.xfs /dev/sda3 -``` -Nous utilisons ici xfs car nous sommes équipés d'un disque rotatif. - -Montons les partitions fraîchement créées. -``` -# mount /dev/sda3 /mnt -# mkdir /mnt/boot -# mount /dev/sda1 /mnt/boot -# swapon /dev/sda2 -``` -Le résultat est vérifiable avec `df -h`. À ce stade, nous pouvons générer la configuration de NixOS dans cette arborescence, et l'éditer par exemple avec `nano` : -``` -# nixos-generate-config --root /mnt -# nano /mnt/etc/nixos/configuration.nix -``` -Ce fichier décrit la configuration du système de manière générale. NixOS le versionne, et à l'utilisation, chaque modification génère une nouvelle «génération». En cas d'erreur par exemple, nous pourrons revenir facilement à une génération précédente. Ainsi nous décrivons ici la première génération de notre système à venir. Nous n'allons en réalité modifier que quelques choses par rapport à la configuration par défaut. Décommentons et définissons le nom d'hôte et le fuseau horaire : -``` -networking.hostName = "nomDeLaMachine"; -``` -``` -time.timeZone = "Europe/Paris"; -``` -Pour les propriétés d'internationalisation, nous pouvons par exemple définir ceci : -``` -i18n.defaultLocale = "fr_FR.UTF-8"; -console = { - font = "Lat2-Terminus16"; - keyMap = "fr-latin9"; -}; -``` -Attention en tout cas à ne pas définir en même temps `keyMap` et `useXkbConfig`, ces deux options peuvent se contredire. Pour l'utilisateur et les paquets du système, nous pouvons par exemple partir sur : -``` -users.users.nomUtilisateur = { - isNormalUser = true; - extraGroups = [ "wheel" ]; -}; -``` -``` -environment.systemPackages = with pkgs; [ - vim - git - wget - emacs -]; -``` -L'installation de git est nécessaire pour rejoindre un cluster Deuxfleurs. - -Enfin activons le serveur SSH en décommentant : -``` -services.openssh.enable = true; -``` -Nous pouvons enregistrer et fermer le fichier, puis lancer l'installation avec : -``` -# nixos-install -``` -Au bout d'un certain temps, le processus va nous demander le mot de passe pour le compte root. Une fois donné, l'installation devrait être terminée. Nous pouvons redémarrer sur la machine, et nous connecter en tant que root. Définissons le mot de passe de l'utilisateur spécifié dans la configuration auparavant (nomUtilisateur) avec : -``` -# passwd nomUtilisateur -``` -Nous pouvons si nous le voulons nous déconnecter avec `exit` et tester la connexion sur nomUtilisateur en local ou en SSH. diff --git "a/content/operations/deploiement/noeud/pr\303\251requis.md" "b/content/operations/deploiement/noeud/pr\303\251requis.md" deleted file mode 100644 index 27dc414..0000000 --- "a/content/operations/deploiement/noeud/pr\303\251requis.md" +++ /dev/null @@ -1,39 +0,0 @@ -+++ -title = "Prérequis pour un nœud" -description = "Prérequis pour un nœud" -date = 2022-01-09T13:29:29.710Z -dateCreated = 2021-12-28T14:33:59.088Z -weight = 10 -+++ - - -Dans ce guide, nous allons expliquer comment installer une grappe de serveurs, en vue d'un hébergement pour Deuxfleurs. - - - -# Choix des ordinateurs - -Héberger des services web est une tâche à la portée de la plupart des ordinateurs des 10 dernières années. Néanmoins, essayer de faire tourner correctement des applications lourdes sur une toute petite machine n'est pas une partie de plaisir. Alors, quitte à installer une nouvelle grappe, la vie sera plus agréable si ses machines disposent d'au moins : - -* 4 Go de RAM -* 1 To de disque (dur ou SSD) - -# Choix d'un site géographique - -Dans un *site géographique*, on installe une *grappe d'ordinateurs* au sein d'un *réseau local*, qu'on connecte au cluster de Deuxfleurs. - -On peut distinguer deux types de sites : - -* _Dans un centre de données_ : chaque ordinateur de la grappe appartient au même centre de données, dispose d'une adresse IP fixe qui le connecte directement à Internet. - - Dans ce cas-ci, **l'installation et l'administration sont assez simples** (on a moins de concepts à avaler que chez un particulier). - Par contre, **nous ne sommes pas chez nous** : le propriétaire du centre de données peut accéder aux disques, et voit ce qui passe sur le réseau. **Chiffrement du disque vivement conseillé.** - -* _Chez un particulier_ : la grappe est reliée à Internet par une *box*, qui filtre le trafic réseau selon des règles variables. La grappe se partage l'adresse IP de la box (qui peut changer régulièrement, être en IPv4 ou en IPv6). - - Dans ce cas de figure, **l'installation comme l'administration demandent plus de connaissances** : pour caricaturer, on doit installer et administrer la grappe **malgré le Fournisseur d'Accès Internet** (FAI), qui considère *a priori* que son abonnement ne sert pas à héberger des services web. - - On aura affaire à sa box (NAT, pare-feu...), au manque de garanties concernant notre adressabilité (IPv4 dynamique, IPv6 ? ...), ce qui va nous mener à devoir faire du routage. Le nœud du problème, c'est que chaque ordinateur de la grappe n'aura pas pignon sur rue (pas d'adresse IP publique et fixe par machine). - - Néanmoins, **on est chez nous !** Votre disque dur - qui contient les données personnelles de vos usagers chéris - est sous vos yeux, bien au chaud. Le seul curieux qui voit passer votre trafic réseau est votre FAI : *rien de nouveau sous le soleil*. - \ No newline at end of file diff --git a/content/operations/deployer.md b/content/operations/deployer.md new file mode 100644 index 0000000..02ef0bd --- /dev/null +++ b/content/operations/deployer.md @@ -0,0 +1,35 @@ +--- +title: "Déployer du logiciel" +description: "Déploiement du logiciel" +sort_by: "weight" +date: 2022-12-22 +weight: 30 +extra: + parent: 'operations/_index.md' +--- + + +# Empaqueter + +Packager avec nix un conteneur Docker, le publier + +# Secrets + +Créer les secrets avec `secretmgr` + +# Service + +Créer un service Nomad + +Voir les différentes déclarations : + - diplonat + - tricot + +# Sauvegardes + +Voir la section appropriée + +# Surveillance + +Voir la section appropriée + diff --git a/content/operations/email.md b/content/operations/email.md new file mode 100644 index 0000000..ac5dfe5 --- /dev/null +++ b/content/operations/email.md @@ -0,0 +1,33 @@ +--- +title: "Emails" +description: "Emails" +weight: 10 +extra: + parent: 'operations/courantes.md' +--- + +# Support d'un nom de domaine personnalisé + + 1. xxx + 1. Communiquez lui votre nom de domaine pour qu'il l'ajoute dans `ou=domains,ou=groups,dc=deuxfleurs,dc=fr` + 2. Communiquez lui l'adresse email que vous souhaitez pour qu'il change l'entrée `mail` dans votre profil utilisateur + 3. Si vous souhaitez avoir une boite mais plusieurs alias, demandez un champs `uid` dans votre profil utilisateur + + 2. Vous devez ensuite rajouter les entrées pour votre nom de domaine en éditant votre zone : + 1. L'entrée MX pour recevoir les emails +```bind +@ MX 10 email-in.deuxfleurs.fr +``` + 2. L'entrée SPF pour autoriser notre IP à délivrer des emails en votre nom : +```bind +@ TXT "v=spf1 mx:out.deuxfleurs.fr -all" +``` + 3. L'entrée DKIM pour autoriser notre postfix+opendkim à délivrer des emails en votre nom : +``` +smtp._domainkey TXT "v=DKIM1; h=sha256; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtdZp4qrgZR+6R7HeAkuLGJ/3L/6Ungvf5zwrMq6T8Tu931j2G4lYuPtsxyn9fZkT4y7DlX0waktLDBOCwf7X78nLEWjAFWiJTeWGRGhRdYRUFpscs9NUN0P+46jKlabibG3XTKd1DeAmywTu6o1oO03yiolrgKD1zgyDRFeUTfSwZIdPrdbcBSA1arda4WFtcBIrSygM9b4jtlqfQwGDrsMLbCBfVHDn4WfmDWyNg0gDAkuLrYClNETk6aqIyj9fC8srKri0Qp3cRagCn+fjBvuxP35qWWJH7Rnnh/tuEDr1ufuNYO2KgJZ7JdMidUotxXE8cfU+OrEWQf4mIYeJ4wIDAQAB" +``` + 4. L'entrée DMARC pour indiquer le comportement à adopter si les contraintes précédentes ne sont pas satisfaites : +``` +_dmarc TXT "v=DMARC1; p=reject; sp=reject; adkim=s; aspf=s; rua=mailto:contact@deuxfleurs.fr!10m; ruf=mailto:contact@deuxfleurs.fr!10m; rf=afrf; pct=100; ri=86400" +``` + 3. C'est tout ! Vous devrez probablement attendre 24/48h que les changements se propagent. diff --git "a/content/operations/guide_cr\303\251ation_n\305\223ud.md" "b/content/operations/guide_cr\303\251ation_n\305\223ud.md" new file mode 100644 index 0000000..11cbc27 --- /dev/null +++ "b/content/operations/guide_cr\303\251ation_n\305\223ud.md" @@ -0,0 +1,104 @@ +--- +title: "Guide de création d'un nœud" +description: "Guide de création d'un nœud" +date: 2022-08-23 +dateCreated: 2022-08-23 +weight: 11 +extra: + parent: 'operations/noeud.md' +--- + +# Guide d'initialisation de nœud Deuxfleurs +Ce guide explique comment initialiser un nœud pour l'infrastructure de Deuxfleurs. Nous partons de zéro, c'est-à-dire avec une machine que nous venons de récupérer, avec une mémoire vide, et que nous venons de brancher. À titre d'exemple, nous illustrerons de temps en temps les opérations avec une de nos machines (un Thinkcentre de Lenovo). + +## Configuration de l'UEFI +Configurons d'abord quelques paramètres dans l'UEFI de la machine. Démarrez-là et appuyez sur la touche pour accéder à ce menu. Chez nous, il s'agit de F1. Si le PXE est activé, désactivons-le : un attaquant présent sur le réseau local pourrait faire démarrer une machine sur une installation malveillante. Vérifions que les *C-States* sont pris en charge, cela permet une meilleure gestion de l'énergie. Configurons également la machine pour qu'elle démarre après avoir subi une coupure électrique, cela se révèlera pratique lorsqu'il y en aura une. Si l'option est là, autorisons le démarrage sans clavier branché, pour ne pas être embêté lorsque nous démarrons une machine pour SSH dessus. Enfin, dans le cadre de l'infrastructure Deuxfleurs, nous supporterons uniquement l'UEFI, nous pouvons donc désactiver les options de compatibilité BIOS. + +## Installation de NixOS + +> Aucun écran ou clavier n'est disponible pour l'ordinateur cible ? NixOS peut être installé en SSH. Suivre les instructions sur [cette page](/operations/deploiement/noeud/ssh-sans-ecran). + +Pour installer NixOS, nous aurons besoin d'une clé USB avec une image amorçable (*live*) de NixOS dessus. Nous pouvons télécharger la distribution linux en 64 bits et en version minimale (sans interface graphique et avec moins d'utilitaires) sur le [site officiel](https://nixos.org/download.html). Pour écrire l'image sur le support USB, on peut faire `dd if=chemin-vers-le-fichier-iso of=/dev/sdX status=progress; sync`, en remplaçant `sdX` par le fichier périphérique correspondant à la clé, trouvé avec `lsblk` par exemple. +Alternativement, cela peut être l'occasion de créer une clé USB formatée avec [Ventoy](https://ventoy.net), un utilitaire très pratique +qui permet d'avoir plusieurs images ISO bootables depuis une même clef USB (utile si vous n'arrêtez pas de reformater vos clefs pour passer d'une distribution à une autre!) + +Branchons la clé USB et démarrons dessus. Chez nous, c'est possible grâce à un menu accessible via la touche F12. Lançons NixOS sans option particulière. Accordons-nous tous les droits et configurons un clavier habituel. On peut également vérifier la connexion internet : +``` +$ sudo su +# loadkeys fr-latin9 +# ping deuxfleurs.fr +``` +Nous pouvons faire `lsblk` pour examiner les disques de la machine. Chez nous, nous avons simplement un disque dur complètement vide de 500Go associé à `/dev/sda`. Nous allons formater le disque avec `cgdisk` : +``` +# cgdisk /dev/sda +``` +Nous créons d'abord, avec l'option `New`, une partition qui commence au début, fait 512Mo, avec un code hexadécimal `EF00`, et que nous appelerons «EFI» : c'est le secteur de démarrage. +Puis nous créons à la suite une partition de 8Go, avec un code hexadécimal `8200`, nommée «swap» : c'est l'espace d'échange. +Enfin sur tout le reste, nous créons une partition avec un code hexadécimal `8300`, que nous appelerons par exemple «root» : c'est la racine du système linux. +Pour appliquer les changements, nous utilisons l'option `Write`. Nous pouvons ensuite quitter avec `Quit`, et éventuellement vérifier le résultat avec `lsblk`. + +Finalisons les partitions. Dans notre cas, nous devons créer les systèmes avec : +``` +# mkfs.fat -F 32 /dev/sda1 +# mkswap /dev/sda2 +# mkfs.xfs /dev/sda3 +``` +Nous utilisons ici xfs car nous sommes équipés d'un disque rotatif. + +Montons les partitions fraîchement créées. +``` +# mount /dev/sda3 /mnt +# mkdir /mnt/boot +# mount /dev/sda1 /mnt/boot +# swapon /dev/sda2 +``` +Le résultat est vérifiable avec `df -h`. À ce stade, nous pouvons générer la configuration de NixOS dans cette arborescence, et l'éditer par exemple avec `nano` : +``` +# nixos-generate-config --root /mnt +# nano /mnt/etc/nixos/configuration.nix +``` +Ce fichier décrit la configuration du système de manière générale. NixOS le versionne, et à l'utilisation, chaque modification génère une nouvelle «génération». En cas d'erreur par exemple, nous pourrons revenir facilement à une génération précédente. Ainsi nous décrivons ici la première génération de notre système à venir. Nous n'allons en réalité modifier que quelques choses par rapport à la configuration par défaut. Décommentons et définissons le nom d'hôte et le fuseau horaire : +``` +networking.hostName = "nomDeLaMachine"; +``` +``` +time.timeZone = "Europe/Paris"; +``` +Pour les propriétés d'internationalisation, nous pouvons par exemple définir ceci : +``` +i18n.defaultLocale = "fr_FR.UTF-8"; +console = { + font = "Lat2-Terminus16"; + keyMap = "fr-latin9"; +}; +``` +Attention en tout cas à ne pas définir en même temps `keyMap` et `useXkbConfig`, ces deux options peuvent se contredire. Pour l'utilisateur et les paquets du système, nous pouvons par exemple partir sur : +``` +users.users.nomUtilisateur = { + isNormalUser = true; + extraGroups = [ "wheel" ]; +}; +``` +``` +environment.systemPackages = with pkgs; [ + vim + git + wget + emacs +]; +``` +L'installation de git est nécessaire pour rejoindre un cluster Deuxfleurs. + +Enfin activons le serveur SSH en décommentant : +``` +services.openssh.enable = true; +``` +Nous pouvons enregistrer et fermer le fichier, puis lancer l'installation avec : +``` +# nixos-install +``` +Au bout d'un certain temps, le processus va nous demander le mot de passe pour le compte root. Une fois donné, l'installation devrait être terminée. Nous pouvons redémarrer sur la machine, et nous connecter en tant que root. Définissons le mot de passe de l'utilisateur spécifié dans la configuration auparavant (nomUtilisateur) avec : +``` +# passwd nomUtilisateur +``` +Nous pouvons si nous le voulons nous déconnecter avec `exit` et tester la connexion sur nomUtilisateur en local ou en SSH. diff --git a/content/operations/jitsi.md b/content/operations/jitsi.md new file mode 100644 index 0000000..07bfcf9 --- /dev/null +++ b/content/operations/jitsi.md @@ -0,0 +1,105 @@ +--- +title: "Jitsi" +description: "" +date: 2021-11-09T12:53:23.811Z +dateCreated: 2021-11-09T12:46:50.731Z +weight: 20 +extra: + parent: 'operations/debogage.md' +--- + +## 2020-04-02 Campagne de debug Jitsi + +Contact: Quentin + +### Description du problème + +Les conversations à 3+ donc relayées par le serveur ne fonctionnent pas bien. +Louison m'a rapporté que ça avait marché pour lui (3 utilisateurs avec un Webkit). +Mais moi ça a échoué hier soir (01/04/2020) avec des participants sous Firefox. +Le bug est toujours le même : on entend 2 personnes sur 3 ou on voit 2 personnes sur 3, on recharge la page et c'est quelqu'un d'autre pour qui ça ne fonctionne plus. Souvent c'est que dans un sens. +À chaque fois en passant sur Facebook Messenger, le problème est résolu instantanément. +Par contre Facebook Messenger impose Google Chrome/Chromium pour les visio de groupe (et ne supporte donc pas Firefox). + +D'où mes 2 suspicions : + +- Firefox a un bug quelconque dans sa pile WebRTC déclenché par le mode conversation de groupe +- Jitsi a un problème avec les déconnexions/changement de connexion/petit hoquets du réseau et n'arrive pas à se reconnecter. Ça pourrait être rendu pire à certain moment de la journée comme le soir où le réseau est plus sollicité. Et ce serait provoqué lors du reload on repasse de 3 à 2, en P2P donc puis de nouveau de 2 à 3. + +### Approfondissement + +Avant d'aller plus loin, nous avons voulu prendre le temps d'identifier précisément les problèmes d'expérience utilisateurs et leur corrélation avec la plateforme de l'utilisateur (navigateur, OS). + +Pour celà, nous avons suivi deux approches : +1. Mener nos propres tests +2. Chercher d'autres retours + +#### Mener nos propres tests + +Nous avons effectué deux appels : un avec Firefox seulement et un avec Chrome/Chromium seulement. +Merci à Alex, Adrien et Maximilien pour leur participation. + +Voilà les conclusions que nous avons tirées de nos tests : + +- L'appel avec Firefox a déclenché le bug immédiatement, peu importe la version de Firefox ou de l'OS (firefox stable/nightly, fedora stable/beta, etc.) +- Le passage de tout le monde sous Chrome/Chromium a permis d'avoir une conversation stable. +- Adrien avait sa Livebox avec pare-feu configuré en mode "élevé" et a dû ajouter dans sa liste blanche les ports utilisés par Jitsi (`4443/tcp` et `10000/udp` au moment du test, seul un des deux a besoin d'être accessible) + +Nous avons donc demandé à Adrien quels étaient les ports ouverts par défaut dans le mode élevé de sa box : + +![Livebox Parefeu Personnalisé](/img/operations/livebox_parefeu_personnalise.png) + +Nous avons dans un premier temps retenu le port `995/tcp` pour Jitsi, le port UDP ne pouvant être changé (limitation de Jitsi). +Cependant, pour des raisons de sécurité, les navigateurs ne peuvent pas utiliser les ports en dessous de `1024/*`, à l'exception des ports `80/tcp` et `443/tcp` comme l'indique ;'issue [#3583](https://bugs.chromium.org/p/webrtc/issues/detail?id=3583) de Chromium. + +La capture n'indique pas de port TCP supérieur à 1024, nous ne pouvons donc pas résoudre ce problème de notre côté, car à l'heure actuelle, nos ports `80/tcp` et `443/tcp` sont utilisés et nous n'avons qu'une seule IP publique. +Les utilisateurs activant le parefeu en mode élevé devront ajouter une exception dans leur parefeu eux-mêmes. + +#### Chercher d'autres retours + +[Tedomum](https://tedomum.net/) a eu connaissance de problèmes similaires. +Ils ont également identifié Firefox et assurent qu'avec l'application Android ça marche bien. +Ils me confirment que le problème vient bien du logiciel et non pas de notre déploiement. +Ils m'ont pointé entre autres vers cette issue github [#4758](https://github.com/jitsi/jitsi-meet/issues/4758) +Apparemment une issue est dédiée en particulier au problème que nous rencontrons de déconnexion partielle d'un participant, mais nous ne l'avons pas encore retrouvée. + +### Correctifs + + 1. Notre instance Jitsi a été reconfigurée pour refuser Firefox. Suivre l'avancée du développement de Jitsi pour Firefox + * [#4758](https://github.com/jitsi/jitsi-meet/issues/4758) + * [#5439](https://github.com/jitsi/jitsi-meet/issues/5439) + * _À compléter_ + 2. Pour relayer la vidéo à travers la plupart des parefeux, notre `videobridge` Jitsi devait écouter sur le port `443/tcp`. Or ce port est déjà utilisé par notre frontal HTTPS. À défaut, Jitsi est maintenant configuré avec `8080/tcp` et `10000/udp` (contre `4443/tcp` et `10000/udp` avant). + * Un déploiement en IPv6 pourrait résoudre le problème pour une partie des utilisateurs + * Avoir un cluster géo-distribué avec plusieurs IPv4 pourrait également résoudre le problème + * Avoir un frontend layer 4 (niveau TCP) qui trouve une signature pour router du DTLS vers videobridge et du TLS vers traefik + +### À propos du control/data plane de Jitsi + +Notre videobridge écoute donc sur les ports `8080/tcp` et `10000/udp`. + +WebRTC fonctionne en deux étapes : +- Des offres doivent être échangées via un serveur de signaling quelconque +- Ensuite, ces offres servent à connecter des clients directement via un protocole TCP ou UDP avec un thin layer propre à WebRTC + +#### Le control plane de Jitsi : Prosody sur HTTPS via Bosh/XMPP + +Le serveur de signaling Jitsi n'est autre que le serveur de chat prosody. +Pour ça, prosody est exposé à travers HTTP grâce au protocole BOSH (XMPP overs HTTPS). +Une fois l'offre reçue ([exemple](/assets/operations/exemple_offre.txt)), elle est enregistrée dans le navigateur à l'aide de `setRemoteDescription` pour initialiser le data plane. +On peut débugger le signaling WebRTC sous Chromium avec [chrome://webrtc-internarls](chrome://webrtc-internals/). + + +Quand plus de deux participants sont connectés dans la conversation, Jitsi n'envoie pas les offres de chaque participant aux autres participants. À la place, elle envoie qu'une seule offre, celle de son VideoBridge. + +Ainsi, le VideoBridge est une sorte de client WebRTC particulier, qui récolte et redispatche à travers WebRTC tous les flux video/audio. + +#### Le data plane de Jitsi : videobridge sur DTLS/SCTP via WebRTC + +WebRTC utilise deux formats de paquets selon [Mozilla Developer Network|RTCDataChannel|DataFormat](https://developer.mozilla.org/en-US/docs/Web/API/RTCDataChannel#Data_format) : +- `UDP/DTLS/SCTP` +- `TCP/DTLS/SCTP` + +On a donc un format de données arbitraire encapsulé dans du SCTP lui-même encapsulé dans du DTLS. +DTLS est prévu pour les datagrammes à l'origine, car WebRTC est prévu d'abord pour fonctionner sous UDP. +Le TCP est là en mode dégradé, en secours, il sert juste de tunnel pour relayer des datagrammes. diff --git a/content/operations/maintien_en_condition.md b/content/operations/maintien_en_condition.md new file mode 100644 index 0000000..8a89a2b --- /dev/null +++ b/content/operations/maintien_en_condition.md @@ -0,0 +1,12 @@ +--- +title: "Maintien en condition" +description: "Maintien en condition" +sort_by: "weight" +weight: 40 +extra: + parent: 'operations/_index.md' +--- + +# En condition opérationnele + +# En condition de sécurité diff --git a/content/operations/maintien_en_condition/_index.md b/content/operations/maintien_en_condition/_index.md deleted file mode 100644 index 73d8812..0000000 --- a/content/operations/maintien_en_condition/_index.md +++ /dev/null @@ -1,10 +0,0 @@ -+++ -title = "Maintien en condition" -description = "Maintien en condition" -sort_by = "weight" -weight = 20 -+++ - -# En condition opérationnele - -# En condition de sécurité diff --git a/content/operations/maintien_en_condition/matrix.md b/content/operations/maintien_en_condition/matrix.md deleted file mode 100644 index 534bfb8..0000000 --- a/content/operations/maintien_en_condition/matrix.md +++ /dev/null @@ -1,101 +0,0 @@ -+++ -title = "MàJ Matrix" -description = "Mise à jour de Matrix (Synapse/Element)" -date = 2022-12-22 -dateCreated = 2022-12-22 -weight = 11 -+++ - -How to update Matrix? -===================== - -## 1. Build the new containers - -Often, I update Riot Web and Synapse at the same time. - - -* Open `app/docker-compose.yml` and locate `riot` (the Element Web service) and `synapse` (the Matrix Synapse server). There are two things you need to do for each service: - - * Set the `VERSION` argument to the target service version (e.g. `1.26.0` for Synapse). This argument is then used to template the Dockerfile. - - The `VERSION` value should match a github release, the link to the corresponding release page is put as a comment next to the variable in the compose file; - - * Tag the image with a new incremented version tag. For example: `superboum/amd64_riotweb:v17` will become `superboum/amd64_riotweb:v18`. - - We use the docker hub to store our images. So, if you are not `superboum` you must change the name with your own handle, eg. `john/amd64_riotweb:v18`. This requires that you registered an account (named `john`) on https://hub.docker.com. - - -So, from now we expect you have: - -* changed the `VERSION` value and `image` name/tag of `riot` -* changed the `VERSION` value and `image` name/tag of `synapse` - -From the `/app` folder, you can now simply build and push the new images: - -```bash -docker-compose build riot synapse -``` - -And then send them to the docker hub: - -``` -docker-compose push riot synapse -``` - -Don't forget to commit and push your changes before doing anything else! - -## 2. Deploy the new containers - -Now, we will edit the deployment file `app/im/deploy/im.hcl`. - -Find where the image is defined in the file, for example Element-web will look like that: - - -```hcl - group "riotweb" { - count = 1 - - task "server" { - driver = "docker" - config { - image = "superboum/amd64_riotweb:v17" - port_map { - web_port = 8043 - } -``` - -And replace the `image =` entry with its new version created above. -Do the same thing for the `synapse` service. - -Now, you need a way to access the cluster to deploy this file. -To do this, you must bind nomad on your machine through a SSH tunnel. -Check the end of [the parent `README.md`](../README.md) to do it. -If you have access to the Nomad web UI when entering http://127.0.0.1:4646 -you are ready to go. - -You must have installed the Nomad command line tool on your machine (also explained in [the parent `README.md`](../README.md)). - -Now, on your machine and from the `app/im/deploy` folder, you must be able to run: - -``` -nomad plan im.hcl -``` - -Check that the proposed diff corresponds to what you have in mind. -If it seems OK, just copy paste the `nomad job run ... im.hcl` command proposed as part of the output of the `nomad plan` command. - -From now, it will take around ~2 minutes to deploy the new images. -You can follow the deployment from the Nomad UI. -Bear in mind that, once the deployment is done on Nomad, you may still need to wait some minutes that Traefik refreshes its configuration. - -If everythings worked as intended, you can commit and push your deployment file. - -If something went wrong, you must rollback your deployment. - - 1. First, find a working deployment with [nomad job history](https://www.nomadproject.io/docs/commands/job/history) - 2. Revert to this deployment with [nomad job revert](https://www.nomadproject.io/docs/commands/job/revert) - -Now, if the deployment failed, you should probably investigate what went wrong offline. -I built a test stack with docker-compose in `app//integration` that should help you out (for now, test suites are only written for plume and jitsi). - - diff --git a/content/operations/matrix.md b/content/operations/matrix.md new file mode 100644 index 0000000..ab1c255 --- /dev/null +++ b/content/operations/matrix.md @@ -0,0 +1,103 @@ +--- +title: "MàJ Matrix" +description: "Mise à jour de Matrix (Synapse/Element)" +date: 2022-12-22 +dateCreated: 2022-12-22 +weight: 11 +extra: + parent: 'operations/maintien_en_condition.md' +--- + +How to update Matrix? +===================== + +## 1. Build the new containers + +Often, I update Riot Web and Synapse at the same time. + + +* Open `app/docker-compose.yml` and locate `riot` (the Element Web service) and `synapse` (the Matrix Synapse server). There are two things you need to do for each service: + + * Set the `VERSION` argument to the target service version (e.g. `1.26.0` for Synapse). This argument is then used to template the Dockerfile. + + The `VERSION` value should match a github release, the link to the corresponding release page is put as a comment next to the variable in the compose file; + + * Tag the image with a new incremented version tag. For example: `superboum/amd64_riotweb:v17` will become `superboum/amd64_riotweb:v18`. + + We use the docker hub to store our images. So, if you are not `superboum` you must change the name with your own handle, eg. `john/amd64_riotweb:v18`. This requires that you registered an account (named `john`) on https://hub.docker.com. + + +So, from now we expect you have: + +* changed the `VERSION` value and `image` name/tag of `riot` +* changed the `VERSION` value and `image` name/tag of `synapse` + +From the `/app` folder, you can now simply build and push the new images: + +```bash +docker-compose build riot synapse +``` + +And then send them to the docker hub: + +``` +docker-compose push riot synapse +``` + +Don't forget to commit and push your changes before doing anything else! + +## 2. Deploy the new containers + +Now, we will edit the deployment file `app/im/deploy/im.hcl`. + +Find where the image is defined in the file, for example Element-web will look like that: + + +```hcl + group "riotweb" { + count = 1 + + task "server" { + driver = "docker" + config { + image = "superboum/amd64_riotweb:v17" + port_map { + web_port = 8043 + } +``` + +And replace the `image =` entry with its new version created above. +Do the same thing for the `synapse` service. + +Now, you need a way to access the cluster to deploy this file. +To do this, you must bind nomad on your machine through a SSH tunnel. +Check the end of [the parent `README.md`](../README.md) to do it. +If you have access to the Nomad web UI when entering http://127.0.0.1:4646 +you are ready to go. + +You must have installed the Nomad command line tool on your machine (also explained in [the parent `README.md`](../README.md)). + +Now, on your machine and from the `app/im/deploy` folder, you must be able to run: + +``` +nomad plan im.hcl +``` + +Check that the proposed diff corresponds to what you have in mind. +If it seems OK, just copy paste the `nomad job run ... im.hcl` command proposed as part of the output of the `nomad plan` command. + +From now, it will take around ~2 minutes to deploy the new images. +You can follow the deployment from the Nomad UI. +Bear in mind that, once the deployment is done on Nomad, you may still need to wait some minutes that Traefik refreshes its configuration. + +If everythings worked as intended, you can commit and push your deployment file. + +If something went wrong, you must rollback your deployment. + + 1. First, find a working deployment with [nomad job history](https://www.nomadproject.io/docs/commands/job/history) + 2. Revert to this deployment with [nomad job revert](https://www.nomadproject.io/docs/commands/job/revert) + +Now, if the deployment failed, you should probably investigate what went wrong offline. +I built a test stack with docker-compose in `app//integration` that should help you out (for now, test suites are only written for plume and jitsi). + + diff --git a/content/operations/nixcfg.md b/content/operations/nixcfg.md new file mode 100644 index 0000000..921f635 --- /dev/null +++ b/content/operations/nixcfg.md @@ -0,0 +1,21 @@ +--- +title: "nixcfg" +description: "Le dépôt nixcfg" +weight: 20 +date: 2022-12-22 +sort_by: "weight" +extra: + parent: 'operations/noeud.md' +--- + +# Installation + +Pointer vers le dépot nixcfg (précédemment le ansible de Deuxfleurs/infrastructure). + +Passer sur Wireguard, Nomad, Consul, Diplonat, (Tricot, Garage), etc. + +# Les secrets + +# Découverte des noeuds + + diff --git a/content/operations/noeud.md b/content/operations/noeud.md new file mode 100644 index 0000000..8e07f74 --- /dev/null +++ b/content/operations/noeud.md @@ -0,0 +1,16 @@ +--- +title: "Installer un noeud" +description: "Déploiement d'un noeud" +date: 2022-08-23 +dateCreated: 2021-08-23 +weight: 20 +extra: + parent: 'operations/_index.md' +--- + +# Déployer un nœud au sein de l'infrastructure Deuxfleurs +Déployer un nœud au sein de l'infrastructure Deuxfleurs demande un certaine préparation et représente un processus particulier. + +Avant de se lancer, [mieux vaut vérifier les prérequis pour y parvenir](./prerequis/). Une fois ceci fait, on peut suivre [le guide décrivant la procédure](./guide-creation-noeud/). + +Si vous avez une machine à installer, mais aucun écran & clavier à brancher dessus pour la configurer, référez-vous au [guide d'installation de NixOs en SSH](./ssh-sans-ecran/). diff --git a/content/operations/pannes.md b/content/operations/pannes.md new file mode 100644 index 0000000..dc8042c --- /dev/null +++ b/content/operations/pannes.md @@ -0,0 +1,15 @@ +--- +title: "Pannes" +description: "Pannes" +weight: 70 +sort_by: "weight" +extra: + parent: 'operations/_index.md' +--- + +Nous aimerions mettre en place une culture du postmortem. +C'est très important pour s'améliorer et apprendre de ses erreurs, +pour prendre le temps de se questionner sur ce qui a disfonctionné, +et réfléchir à comment changer en profondeur nos pratiques. +Et puis, plus simplement, si le problème venait à arriver +de nouveau, nous aurions alors déjà documenté comment le résoudre ! diff --git a/content/operations/pannes/2020-01-20-changement-ip.md b/content/operations/pannes/2020-01-20-changement-ip.md deleted file mode 100644 index c86eb85..0000000 --- a/content/operations/pannes/2020-01-20-changement-ip.md +++ /dev/null @@ -1,53 +0,0 @@ -+++ -title = "Janvier 2020" -description = "Janvier 2020: changement imprévu d'adresses IP" -date = 2022-12-22 -dateCreated = 2022-12-22 -weight = 10 -+++ - -Le 20 janvier free a changé mon IP, un peu comme partout en France. -Ça concerne l'IPv4 et le préfixe IPv6. -Ici le bon vieux Bortzmoinsbien qui tweet : https://twitter.com/bortzmeyer/status/1351434290916155394 - -Max a update tout de suite l'IPv4 mais avec un TTL de 4h le temps de propagation est grand. -J'ai réduit les entrées sur les IP à 300 secondes, soit 5 minutes, le minimum chez Gandi, à voir si c'est une bonne idée. -Reste à update les IPv6, moins critiques pour le front facing mais utilisées pour le signaling en interne... - -## Le fameux signaling -Ça pose un gros problème avec Nomad (et en moindre mesure avec Consul). -En effet, Nomad utilise l'IPv6 pour communiquer, il faut donc changer les IPs de tous les noeuds. -Problème ! On peut pas faire la migration au fur et à mesure car, changeant d'IP, les noeuds ne seront plus en mesure de communiquer. -On n'a pas envie de supprimer le cluster et d'en créer un nouveau car ça voudrait dire tout redéployer ce qui est long également (tous les fichiers HCL pour Nomad, tout le KV pour consul). -On ne peut pas non plus la faire à la bourrin en stoppant tous les cluster, changer son IP, puis redémarrer. -Enfin si, Consul accepte mais pas Nomad, qui lui va chercher à communiquer avec les anciennes IP et n'arrivera jamais à un consensus. - -Au passage j'en ai profité pour changer le nom des noeuds car la dernière fois, Nomad n'avait PAS DU TOUT apprécié qu'un noeud ayant le même nom change d'IP. Ceci dit, si on utilise de facto le `peers.json` c'est peut être pas problématique. À tester. - -Du coup, après moult réflexions, la silver bullet c'est la fonction outage recovery de nomad (consul l'a aussi au besoin). -Elle est ici : https://learn.hashicorp.com/tutorials/consul/recovery-outage -En gros, il faut arrêter tous les nodes. -Ensuite créer un fichier à ce path : `/var/lib/nomad/server/raft/peers.json` -Ne vous laissez pas perturber par le fichier `peers.info` à côté, il ne faut pas le toucher. -Après la grande question c'est de savoir si le cluster est en Raft v2 ou Raft v3. -Bon ben nous on était en Raft v2. Si vous vous trompez, au redémarrage Nomad va crasher avec une sale erreur : - -``` -nomad: failed to start Raft: error="recovery failed to parse peers.json: json: cannot unmarshal string into Go value of type raft.configEntry" -``` - -(je me suis trompé bien sûr). -Voilà, après il ne vous reste plus qu'à redémarrer et suivre les logs, cherchez bien la ligne où il dit qu'il a trouvé le peers.json. - -## Les trucs à pas oublier - - - Reconfigurer le backend KV de traefik (à voir à utiliser des DNS plutôt du coup) - - Reconfigurer l'IPv4 publique annoncée à Jitsi - -## Ce qui reste à faire - - - Mettre à jour les entrées DNS IPv6, ce qui devrait créer : - - digitale.machine.deuxfleurs.fr - - datura.machine.deuxfleurs.fr - - drosera.machine.deuxfleurs.fr - - Mettre à jour l'instance garage sur io diff --git a/content/operations/pannes/2021-07-12-synapse-bdd-rempli-disque.md b/content/operations/pannes/2021-07-12-synapse-bdd-rempli-disque.md deleted file mode 100644 index 17650fa..0000000 --- a/content/operations/pannes/2021-07-12-synapse-bdd-rempli-disque.md +++ /dev/null @@ -1,22 +0,0 @@ -+++ -title = "Juillet 2021" -description = "Juillet 2021: la BDD Synapse remplit nos disques" -date = 2022-12-22 -dateCreated = 2022-12-22 -weight = 20 -+++ - -# La BDD synapse rempli nos disques - -Todo: finir ce blog post et le dupliquer ici https://quentin.dufour.io/blog/2021-07-12/chroniques-administration-synapse/ - -Le WAL qui grossissait à l'infini était également du à un SSD défaillant dont les écritures était abyssalement lentes. - -Actions mises en place : - - Documentation de comment ajouter de l'espace sur un disque différent avec les tablespaces - - Interdiction de rejoindre les rooms avec une trop grande complexité - - nettoyage de la BDD à la main (rooms vides, comptes non utilisés, etc.) - - Remplacement du SSD défaillant - -Actions à mettre en place : - - Utiliser les outils de maintenance de base de données distribuées par le projet matrix diff --git a/content/operations/pannes/2022-01-xx-glusterfs-corruption.md b/content/operations/pannes/2022-01-xx-glusterfs-corruption.md deleted file mode 100644 index bbd94af..0000000 --- a/content/operations/pannes/2022-01-xx-glusterfs-corruption.md +++ /dev/null @@ -1,36 +0,0 @@ -+++ -title = "Janvier 2022" -description = "Janvier 2022: Corruptions GlusterFS" -date = 2022-12-22 -dateCreated = 2022-12-22 -weight = 30 -+++ - -# Corruption GlusterFS - -Suite au redémarrage d'un serveur, les emails ne sont plus disponibles. -Il apparait que GlusterFS ne répliquait plus correctement les données depuis un certain temps. -Suite à ce problème, il a renvoyé des dossiers Dovecot corrompu. -Dovecot a reconstruit un index sans les emails, ce qui a désynchronisé les bàl des gens. -À la fin, certaines boites mails ont perdu tous leurs emails. -Aucune sauvegarde des emails n'était réalisée. -Le problème a été créé cet été quand j'ai réinstallé un serveur. -J'ai installé sur une version de Debian différente. -La version de GlusterFS était pinnée dans un sources.list, en pointant vers le repo du projet gluster -Mais le pinning était pour la version de debian précédente. -Le sources.list a été ignoré, et c'est le gluster du projet debian plus récent qui a été installé. -Ces versions étaient incompatibles mais silencieusement. -GlusterFS n'informe pas proactivement non plus que les volumes sont désynchronisées. -Il n'y a aucune commande pour connaitre l'état du cluster. -Après plusieurs jours de travail, il m'a été impossible de remonter les emails. - -Action mise en place : - - Suppression de GlusterFS - - Sauvegardes journalière des emails - - Les emails sont maintenant directement sur le disque (pas de haute dispo) - -Action en cours de mise en place : - - Développement d'un serveur IMAP sur Garage - - - diff --git a/content/operations/pannes/_index.md b/content/operations/pannes/_index.md deleted file mode 100644 index 474558b..0000000 --- a/content/operations/pannes/_index.md +++ /dev/null @@ -1,6 +0,0 @@ -+++ -title = "Pannes" -description = "Pannes" -weight = 70 -sort_by = "weight" -+++ diff --git a/content/operations/pannes/petits-incidents.md b/content/operations/pannes/petits-incidents.md deleted file mode 100644 index 658757f..0000000 --- a/content/operations/pannes/petits-incidents.md +++ /dev/null @@ -1,27 +0,0 @@ -+++ -title = "Petits incidents" -description = "Petits incidents" -date = 2022-12-22 -dateCreated = 2022-12-22 -weight = 1000 -+++ - -- **2020** Publii efface le disque dur d'un de nos membres. Il a changé le dossier de sortie vers /home qui a été effacé - -- **2021-07-27** Panne de courant à Rennes - 40 000 personnes sans électricité pendant une journée - nos serveurs de prod étant dans la zone coupée, deuxfleurs.fr est dans le noir - https://www.francebleu.fr/infos/faits-divers-justice/rennes-plusieurs-quartiers-prives-d-electricite-1627354121 - -- **2021-12:** Tentative de migration un peu trop hâtive vers Tricot pour remplacer Traefik qui pose des soucis. Downtime et manque de communication sur les causes, confusion généralisée. - - *Actions à envisager:* prévoir à l'avance toute intervention de nature à impacter la qualité de service sur l'infra Deuxfleurs. Tester en amont un maximum pour éviter de devoir tester en prod. Lorsque le test en prod est inévitable, s'organiser pour impacter le moins de monde possible. - -- **2022-03-28:** Coupure d'électricité au site Jupiter, `io` ne redémarre pas toute seule. T est obligée de la rallumer manuellement. `io` n'est pas disponible durant quelques heures. - - *Actions à envisager:* reconfigurer `io` pour s'allumer toute seule quand le courant démarre. - -- **2022-03-28:** Grafana (hébergé par M) n'est pas disponible. M est le seul à pouvoir intervenir. - - *Actions à envisager:* cartographier l'infra de monitoring et s'assurer que plusieurs personnes ont les accès. - -- **2022-12-23:** Les backups de la production ne s'effectuaient pas correctement car Nomad ne voulait pas lancer les jobs pour cause de ressources épuisées (pas assez de CPU). - - *Action menée:* La préemption des jobs a été activée pour tous les schedulers Nomad, ce qui permet aux jobs de backup de virer les jobs de plus faible priorité pour pouvoir se lancer (ces derniers seront relancés sur une autre machine automatiquement). diff --git a/content/operations/pass.md b/content/operations/pass.md new file mode 100644 index 0000000..795da1f --- /dev/null +++ b/content/operations/pass.md @@ -0,0 +1,199 @@ +--- +title: "Le dépôt des secrets" +description: "Le dépôt des secrets" +weight: 10 +extra: + parent: 'operations/acces.md' +--- + +We use [pass, 'the standard unix password manager'](https://www.passwordstore.org/), to manage our key store securely at Deuxfleurs. Getting access to our production involves publishing one's GPG key (through Gitea) and importing/verifying/signing every other sysadmin's key, before setting up `pass`. Lastly, you will be able to set your shell password on the desired cluster (`prod` or `staging`, at the time of writing). + +Our process was adapted from [this Medium article](https://medium.com/@davidpiegza/using-pass-in-a-team-1aa7adf36592) — thanks, David! + +## You are new and want to access the secrets repository + +You need a GPG key to start with. +If you do not already have one, you can generate a new one with: + +```bash +gpg2 --expert --full-gen-key +# Personnaly I use `9) ECC and ECC`, `1) Curve 25519`, and `5y` +``` + +In any case, you need to export your public key. Upload the output (public key) of the following command to [your Gitea account](https://git.deuxfleurs.fr/user/settings/keys). + + +```bash +gpg2 --export --armor +``` + +It is now publicly accessible at `https://git.deuxfleurs.fr/.gpg` + +Inform all the other sysadmins that you have published your key for them to import/verify/sign it. + +### Import/verify/sign every other sysadmin's key into your keychain + +You now need to import and sign every other sysadmin's GPG key. For example, import Quentin's key to your keychain as follow: + +```bash +gpg2 --import <(curl https://git.deuxfleurs.fr/quentin.gpg) +gpg2 --list-keys +# pub ed25519/0xE9602264D639FF68 2022-04-19 [SC] [expire : 2027-04-18] +# Empreinte de la clef = 8023 E27D F1BB D52C 559B 054C E960 2264 D639 FF68 +# uid [ ultime ] Quentin Dufour +# sub cv25519/0xA40574404FF72851 2022-04-19 [E] [expire : 2027-04-18] +``` + +> How to read this snippet: +> - the key id: `E9602264D639FF68` +> - the key fingerprint: `8023 E27D F1BB D52C 559B 054C E960 2264 D639 FF68` + +To perform the check, you need another communication channel (ideally physically, otherwise through the phone, Matrix if you already trusted the other person, or else). Compare the signature you read with the sysadmin's. If they match, you good. + +Now that you have verified the key, sign it: + +```bash +gpg --edit-key quentin@deuxfleurs.fr # by email +# or +gpg --edit-key E9602264D639FF68 # by key id +# gpg> lsign +# (say yes, maybe several times) +# gpg> save +``` + +Once you signed every sysadmin, ask an administrator to add your key to the secrets keystore. They will need to [Add a sysadmin](#add-a-sysadmin). + +Once your fellow admin has finished their job, you are ready to install `pass`: + +```bash +sudo apt-get install pass # Debian + Ubuntu +sudo yum install pass # Fedora + RHEL +sudo zypper in password-store # OpenSUSE +sudo emerge -av pass # Gentoo +sudo pacman -S pass # Arch Linux +brew install pass # macOS +pkg install password-store # FreeBSD +``` + +*Go to [passwordstore.org](https://www.passwordstore.org/) for more information about pass*. + +Download the repository: + +``` +mkdir -p ~/.password-store +cd ~/.password-store +git clone git@git.deuxfleurs.fr:Deuxfleurs/secrets.git deuxfleurs +``` + +Finally check that everything works: + +```bash +pass show deuxfleurs +``` + +If you see a listing, it worked. Last step is to select a shell password for yourself on the cluster you are now in charge of (`prod` or `staging`, at the time of writing). + + +Clone the nixcfg repository: + +``` +git clone git@git.deuxfleurs.fr:Deuxfleurs/nixcfg.git +cd nixcfg +``` + +Use the passwd utility to set your shell password: +``` +./passwd +> Usage: ./passwd +> The cluster name must be the name of a subdirectory of cluster/ +``` + +This commited changes to Deuxfleurs' password store, do verify your modifications before pushing them: +``` +cd ~/.password-store/deuxfleurs +git diff +git push +``` + +You should now be able to `ssh` into our infrastructure with a unified shell password. This is explicated in `nixcfg` repo's [README](https://git.deuxfleurs.fr/Deuxfleurs/nixcfg#how-to-operate-a-node). Be cautious, and enjoy! + +> With great power comes great responsibility. + +--- + +--- + +## You are a sysadmin and want to operate the secrets repository + +## Initialise the pass store + +> These instructions are for _bootstrapping_ the pass store. **Don't do it on Deuxfleurs' secrets repository** (don't be like ADRN). You would override the existing sysadmins and generally have a bad time. + +Generate a new password store named deuxfleurs for you: + +``` +pass init -p deuxfleurs you@example.com +``` + +Add a password in this store, it will be encrypted with your gpg key: + +```bash +pass generate deuxfleurs/backup_nextcloud 20 +# or +pass insert deuxfleurs/backup_nextcloud +``` + +## Add a sysadmin + +Edit `~/.password-store/acme/.gpg-id` and add the id of the newbie: + +``` +alice@example.com +jane@example.com +bob@example.com +``` + +Make sure that you trust the keys of your new sysadmin: + +``` +$ gpg --edit-key jane@example.com +gpg> lsign +gpg> y +gpg> save +``` + +Now re-encrypt the secrets and push your modifications: + +``` +pass init -p deuxfleurs $(cat ~/.password-store/deuxfleurs/.gpg-id) +cd ~/.password-store/deuxfleurs +git commit +git push +``` + +They will now be able to decrypt any password: + +``` +pass deuxfleurs/backup_nextcloud +``` + +## Sharing with git + +To create the repo _on bootstrap exclusively_: + +```bash +cd ~/.password-store/deuxfleurs +git init +git add . +git commit -m "Initial commit" +# Set up remote +git push +``` + +To retrieve the repo: + +```bash +mkdir -p ~/.password-store +cd ~/.password-store +git clone https://git.example.com/org/repo.git deuxfleurs +``` diff --git a/content/operations/petits-incidents.md b/content/operations/petits-incidents.md new file mode 100644 index 0000000..d14e91c --- /dev/null +++ b/content/operations/petits-incidents.md @@ -0,0 +1,29 @@ +--- +title: "Petits incidents" +description: "Petits incidents" +date: 2022-12-22 +dateCreated: 2022-12-22 +weight: 1000 +extra: + parent: 'operations/pannes.md' +--- + +- **2020** Publii efface le disque dur d'un de nos membres. Il a changé le dossier de sortie vers /home qui a été effacé + +- **2021-07-27** Panne de courant à Rennes - 40 000 personnes sans électricité pendant une journée - nos serveurs de prod étant dans la zone coupée, deuxfleurs.fr est dans le noir - https://www.francebleu.fr/infos/faits-divers-justice/rennes-plusieurs-quartiers-prives-d-electricite-1627354121 + +- **2021-12:** Tentative de migration un peu trop hâtive vers Tricot pour remplacer Traefik qui pose des soucis. Downtime et manque de communication sur les causes, confusion généralisée. + + *Actions à envisager:* prévoir à l'avance toute intervention de nature à impacter la qualité de service sur l'infra Deuxfleurs. Tester en amont un maximum pour éviter de devoir tester en prod. Lorsque le test en prod est inévitable, s'organiser pour impacter le moins de monde possible. + +- **2022-03-28:** Coupure d'électricité au site Jupiter, `io` ne redémarre pas toute seule. T est obligée de la rallumer manuellement. `io` n'est pas disponible durant quelques heures. + + *Actions à envisager:* reconfigurer `io` pour s'allumer toute seule quand le courant démarre. + +- **2022-03-28:** Grafana (hébergé par M) n'est pas disponible. M est le seul à pouvoir intervenir. + + *Actions à envisager:* cartographier l'infra de monitoring et s'assurer que plusieurs personnes ont les accès. + +- **2022-12-23:** Les backups de la production ne s'effectuaient pas correctement car Nomad ne voulait pas lancer les jobs pour cause de ressources épuisées (pas assez de CPU). + + *Action menée:* La préemption des jobs a été activée pour tous les schedulers Nomad, ce qui permet aux jobs de backup de virer les jobs de plus faible priorité pour pouvoir se lancer (ces derniers seront relancés sur une autre machine automatiquement). diff --git a/content/operations/pg_basebackup.md b/content/operations/pg_basebackup.md new file mode 100644 index 0000000..f680108 --- /dev/null +++ b/content/operations/pg_basebackup.md @@ -0,0 +1,338 @@ +--- +title: "pg_basebackup" +description: "pg_basebackup" +weight: 15 +extra: + parent: 'operations/sauvegardes.md' +--- + +## Disclaimer + +Do **NOT** use the following backup methods on the Stolon Cluster: + 1. copying the data directory + 2. `pg_dump` + 3. `pg_dumpall` + +The first one will lead to corrupted/inconsistent files. +The second and third ones put too much pressure on the cluster. +Basically, you will destroy it, in the following ways: + - Load will increase, requests will timeout + - RAM will increase, the daemon will be OOM (Out Of Memory) killed by Linux + - Potentially, the WAL log will grow a lot + + +## A binary backup with `pg_basebackup` + +The only acceptable solution is `pg_basebackup` with **some throttling configured**. +Later, if you want a SQL dump, you can inject this binary backup on an ephemeral database you spawned solely for this purpose on a non-production machine. + +First, start by fetching from Consul the identifiers of the replication account. +Do not use the root account setup in Stolon, it will not work. + +First setup a SSH tunnel on your machine that bind postgresql, eg: + +```bash +ssh -L 5432:psql-proxy.service.2.cluster.deuxfleurs.fr:5432 ... +``` + +*Later, we will use `/tmp/sql` as our working directory. Depending on your distribution, this +folder may be a `tmpfs` and thus mounted on RAM. If it is the case, choose another folder, that is not a `tmpfs`, otherwise you will fill your RAM +and fail your backup. I am using NixOS and the `/tmp` folder is a regular folder, persisted on disk, which explain why I am using it.* + +Then export your password in `PGPASSWORD` and launch the backup: + +```bash +export PGPASSWORD=xxx + +mkdir -p /tmp/sql +cd /tmp/sql + +pg_basebackup \ + --host=127.0.0.1 \ + --username=replicator \ + --pgdata=/tmp/sql \ + --format=tar \ + --wal-method=stream \ + --gzip \ + --compress=6 \ + --progress \ + --max-rate=5M +``` + +*Something you should now: while it seems optional, fetching the WAL is mandatory. At first, I thought it was a way to have a "more recent backup". +But after some reading, it appears that the base backup is corrupted because it is not a snapshot at all, but a copy of the postgres folder with no specific state. +The whole point of the WAL is, in fact, to fix this corrupted archive...* + +*Take a cup of coffe, it will take some times...* + +The result I get (the important file is `base.tar.gz`, `41921.tar.gz` will probably be missing as it is a secondary tablespace I will deactivate soon): + +``` +[nix-shell:/tmp/sql]$ ls +41921.tar.gz backup_manifest base.tar.gz pg_wal.tar.gz +``` + +From now, disconnect from the production to continue your work. +You don't need it anymore and it will prevent some disaster if you fail a command. + + +## Importing the backup + +> The backup taken with `pg_basebckup` is an exact copy of your data directory so, all you need to do to restore from that backup is to point postgres at that directory and start it up. + +```bash +mkdir -p /tmp/sql/pg_data && cd /tmp/sql/pg_data +tar xzfv ../base.tar.gz +``` + +Now you should have something like that: + +``` +[nix-shell:/tmp/sql/pg_data]$ ls +backup_label base pg_commit_ts pg_hba.conf pg_logical pg_notify pg_serial pg_stat pg_subtrans pg_twophase pg_wal postgresql.conf tablespace_map +backup_label.old global pg_dynshmem pg_ident.conf pg_multixact pg_replslot pg_snapshots pg_stat_tmp pg_tblspc PG_VERSION pg_xact stolon-temp-postgresql.conf +``` + +Now we will extract the WAL: + +```bash +mkdir -p /tmp/sql/wal && cd /tmp/sql/wal +tar xzfv ../pg_wal.tar.gz +``` + +You should have something like that: + +``` +[nix-shell:/tmp/sql/wal]$ ls +00000003000014AF000000C9 00000003000014AF000000CA 00000003.history archive_status +``` + +Before restoring our backup, we want to check it: + +```bash +cd /tmp/sql/pg_data +cp ../backup_manifest . +# On ne vérifie pas le WAL car il semblerait que ça marche pas trop +# Cf ma référence en bas capdata.fr +# pg_verifybackup -w ../wal . +pg_verifybackup -n . + +``` + +Now, We must edit/read some files before launching our ephemeral server: + - Set `listen_addresses = '0.0.0.0'` in `postgresql.conf` + - Add `restore_command = 'cp /mnt/wal/%f %p' ` in `postgresql.conf` + - Check `port` in `postgresql.conf`, in our case it is `5433`. + - Create an empty file named `recovery.signal` + +*Do not create a `recovery.conf` file, it might be written on the internet but this is a deprecated method and your postgres daemon will refuse to boot if it finds one.* + +*Currently, we use port 5433 in oour postgresql configuration despite 5432 being the default port. Indeed, in production, clients access the cluster transparently through the Stolon Proxy that listens on port 5432 and redirect the requests to the correct PostgreSQL instance, listening secretly on port 5433! To export our binary backup in text, we will directly query our postgres instance without passing through the proxy, which is why you must note this port.* + +Now we will start our postgres container on our machine. + +At the time of writing the live version is `superboum/amd64_postgres:v9`. +We must start by getting `postgres` user id. Our container are run by default with this user, so you only need to run: + +```bash +docker run --rm -it superboum/amd64_postgres:v9 id +``` + +And we get: + +``` +uid=999(postgres) gid=999(postgres) groups=999(postgres),101(ssl-cert) +``` + +Now `chown` your `pg_data`: + +```bash +chown 999:999 -R /tmp/sql/{pg_data,wal} +chmod 700 -R /tmp/sql/{pg_data,wal} +``` + +And finally: + +``` +docker run \ + --rm \ + -it \ + -p 5433:5433 \ + -v /tmp/sql/:/mnt/ \ + superboum/amd64_postgres:v9 \ + postgres -D /mnt/pg_data +``` + +I have the following output: + +``` +2022-01-28 14:46:39.750 GMT [1] LOG: skipping missing configuration file "/mnt/pg_data/postgresql.auto.conf" +2022-01-28 14:46:39.763 UTC [1] LOG: starting PostgreSQL 13.3 (Debian 13.3-1.pgdg100+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 8.3.0-6) 8.3.0, 64-bit +2022-01-28 14:46:39.764 UTC [1] LOG: listening on IPv4 address "0.0.0.0", port 5433 +2022-01-28 14:46:39.767 UTC [1] LOG: listening on Unix socket "/tmp/.s.PGSQL.5433" +2022-01-28 14:46:39.773 UTC [7] LOG: database system was interrupted; last known up at 2022-01-28 14:33:13 UTC +cp: cannot stat '/mnt/wal/00000004.history': No such file or directory +2022-01-28 14:46:40.318 UTC [7] LOG: starting archive recovery +2022-01-28 14:46:40.321 UTC [7] LOG: restored log file "00000003.history" from archive +2022-01-28 14:46:40.336 UTC [7] LOG: restored log file "00000003000014AF000000C9" from archive +2022-01-28 14:46:41.426 UTC [7] LOG: could not open directory "pg_tblspc/41921/PG_13_202007201": No such file or directory +2022-01-28 14:46:41.445 UTC [7] LOG: could not open directory "pg_tblspc/41921/PG_13_202007201": No such file or directory +2022-01-28 14:46:41.457 UTC [7] LOG: redo starts at 14AF/C9000028 +2022-01-28 14:46:41.500 UTC [7] LOG: restored log file "00000003000014AF000000CA" from archive +2022-01-28 14:46:42.461 UTC [7] LOG: consistent recovery state reached at 14AF/CA369AB0 +2022-01-28 14:46:42.461 UTC [1] LOG: database system is ready to accept read only connections +cp: cannot stat '/mnt/wal/00000003000014AF000000CB': No such file or directory +2022-01-28 14:46:42.463 UTC [7] LOG: redo done at 14AF/CA369AB0 +2022-01-28 14:46:42.463 UTC [7] LOG: last completed transaction was at log time 2022-01-28 14:35:04.698438+00 +2022-01-28 14:46:42.480 UTC [7] LOG: could not open directory "pg_tblspc/41921/PG_13_202007201": No such file or directory +2022-01-28 14:46:42.493 UTC [7] LOG: restored log file "00000003000014AF000000CA" from archive +cp: cannot stat '/mnt/wal/00000004.history': No such file or directory +2022-01-28 14:46:43.462 UTC [7] LOG: selected new timeline ID: 4 +2022-01-28 14:46:44.441 UTC [7] LOG: archive recovery complete +2022-01-28 14:46:44.444 UTC [7] LOG: restored log file "00000003.history" from archive +2022-01-28 14:46:45.614 UTC [1] LOG: database system is ready to accept connections +``` + +*Notes: the missing tablespace is a legacy tablesplace used in the past to debug Matrix. It will be removed soon, we can safely ignore it. Other errors on cp seems to be intended as postgres might want to know how far it can rewind with the WAL but I a not 100% sure.* + +Your ephemeral instance should work: + +```bash +export PGPASSWORD=xxx # your postgres (admin) account password + +psql -h 127.0.0.1 -p 5433 -U postgres postgres +``` + +And your databases should appear: + +``` +[nix-shell:~/Documents/dev/infrastructure]$ psql -h 127.0.0.1 -p 5433 -U postgres postgres +psql (13.5, server 13.3 (Debian 13.3-1.pgdg100+1)) +Type "help" for help. + +postgres=# \l + List of databases + Name | Owner | Encoding | Collate | Ctype | Access privileges +-----------+----------+----------+------------+------------+----------------------- + xxxxx | xxxxx | UTF8 | en_US.utf8 | en_US.utf8 | + xxxxx | xxxxx | UTF8 | en_US.utf8 | en_US.utf8 | + xxxxx | xxxxx | UTF8 | en_US.utf8 | en_US.utf8 | + postgres | postgres | UTF8 | en_US.utf8 | en_US.utf8 | + xxxx | xxxxx | UTF8 | en_US.utf8 | en_US.utf8 | + xxxx | xxxxx | UTF8 | en_US.utf8 | en_US.utf8 | + template0 | postgres | UTF8 | en_US.utf8 | en_US.utf8 | =c/postgres + + | | | | | postgres=CTc/postgres + template1 | postgres | UTF8 | en_US.utf8 | en_US.utf8 | =c/postgres + + | | | | | postgres=CTc/postgres +(8 rows) +``` + +## Dump your ephemeral database as SQL + +Now we can do a SQL export of our ephemeral database. +We use zstd to automatically compress the outputed file. +We use multiple parameters: + - `-vv` gives use some idea on the progress + - `-9` is a quite high value and should compress efficiently. Decrease it if your machine is low powered + - `-T0` asks zstd to use all your cores. By default, zstd uses only one core. + +```bash +pg_dumpall -h 127.0.0.1 -p 5433 -U postgres \ + | zstd -vv -9 -T0 --format=zstd > dump-`date --rfc-3339=seconds | sed 's/ /T/'`.sql.zstd +``` + +I get the following result: + +``` +[nix-shell:/tmp/sql]$ ls -lah dump* +-rw-r--r-- 1 quentin users 749M janv. 28 16:07 dump-2022-01-28T16:06:29+01:00.sql.zstd +``` + +Now you can stop your ephemeral server. + +## Restore your SQL file + +First, start a blank server: + +```bash +docker run \ + --rm -it \ + --name postgres \ + -p 5433:5432 \ + superboum/amd64_postgres:v9 \ + bash -c ' + set -ex + mkdir /tmp/psql + initdb -D /tmp/psql --no-locale --encoding=UTF8 + echo "host all postgres 0.0.0.0/0 md5" >> /tmp/psql/pg_hba.conf + postgres -D /tmp/psql + ' +``` + +Then set the same password as your prod for the `posgtgres` user (it will be required as part of the restore): + +```bash +docker exec -ti postgres bash -c "echo \"ALTER USER postgres WITH PASSWORD '$PGPASSWORD';\" | psql" +echo '\l' | psql -h 127.0.0.1 -p 5433 -U postgres postgres +# the database should have no entry (except `posgtres`, `template0` and `template1`) otherwise ABORT EVERYTHING, YOU ARE ON THE WRONG DB +``` + +And finally, restore your SQL backup: + +```bash +zstdcat -vv dump-* | \ + grep -P -v '^(CREATE|DROP) ROLE postgres;' | \ + psql -h 127.0.0.1 -p 5433 -U postgres --set ON_ERROR_STOP=on postgres +``` + +*Note: we must skip CREATE/DROP ROLE postgres during the restore as it aready exists and would generate an error. +Because we want to be extra careful, we specifically asked to crash on every error and do not want to change this behavior. +So, instead, we simply remove any entry that contains the specific regex stated in the previous command.* + +Check that the backup has been correctly restored. +For example: + +```bash +docker exec -ti postgres psql +#then type "\l", "\c db-name", "select ..." +``` + +## Finally, store it safely + +```bash +rsync --progress -av /tmp/sql/{*.tar.gz,backup_manifest,dump-*} backup/target +``` + +## Garbage collect old backups + +``` +mc ilm import deuxfleurs/${BUCKET_NAME} < select * from follows where ap_url=''; + id | follower_id | following_id | ap_url +------+-------------+--------------+-------- + 2118 | 20 | 238 | +(1 row) +``` + +Simply set the `ap_url` as follows: + +``` +plume=> update follows set ap_url='https://plume.deuxfleurs.fr/follows/2118' where id=2118; +UPDATE 1 +``` diff --git a/content/operations/prestataires.md b/content/operations/prestataires.md new file mode 100644 index 0000000..ab1f796 --- /dev/null +++ b/content/operations/prestataires.md @@ -0,0 +1,27 @@ +--- +title: "Prestataires" +description: "Prestataires" +weight: 80 +extra: + parent: 'operations/_index.md' +--- + +# DNS + +Gandi + +# Pont IPv6 + +FDN + +# Paquets + +Docker Hub + +# FAI + +Free, SFR, et autres + +# Électricité + +EDF diff --git a/content/operations/prestataires/_index.md b/content/operations/prestataires/_index.md deleted file mode 100644 index 31d83fc..0000000 --- a/content/operations/prestataires/_index.md +++ /dev/null @@ -1,25 +0,0 @@ -+++ -title = "Prestataires" -description = "Prestataires" -weight = 80 -+++ - -# DNS - -Gandi - -# Pont IPv6 - -FDN - -# Paquets - -Docker Hub - -# FAI - -Free, SFR, et autres - -# Électricité - -EDF diff --git "a/content/operations/pr\303\251requis.md" "b/content/operations/pr\303\251requis.md" new file mode 100644 index 0000000..37d5179 --- /dev/null +++ "b/content/operations/pr\303\251requis.md" @@ -0,0 +1,41 @@ +--- +title: "Prérequis pour un nœud" +description: "Prérequis pour un nœud" +date: 2022-01-09T13:29:29.710Z +dateCreated: 2021-12-28T14:33:59.088Z +weight: 10 +extra: + parent: 'operations/noeud.md' +--- + + +Dans ce guide, nous allons expliquer comment installer une grappe de serveurs, en vue d'un hébergement pour Deuxfleurs. + + + +# Choix des ordinateurs + +Héberger des services web est une tâche à la portée de la plupart des ordinateurs des 10 dernières années. Néanmoins, essayer de faire tourner correctement des applications lourdes sur une toute petite machine n'est pas une partie de plaisir. Alors, quitte à installer une nouvelle grappe, la vie sera plus agréable si ses machines disposent d'au moins : + +* 4 Go de RAM +* 1 To de disque (dur ou SSD) + +# Choix d'un site géographique + +Dans un *site géographique*, on installe une *grappe d'ordinateurs* au sein d'un *réseau local*, qu'on connecte au cluster de Deuxfleurs. + +On peut distinguer deux types de sites : + +* _Dans un centre de données_ : chaque ordinateur de la grappe appartient au même centre de données, dispose d'une adresse IP fixe qui le connecte directement à Internet. + + Dans ce cas-ci, **l'installation et l'administration sont assez simples** (on a moins de concepts à avaler que chez un particulier). + Par contre, **nous ne sommes pas chez nous** : le propriétaire du centre de données peut accéder aux disques, et voit ce qui passe sur le réseau. **Chiffrement du disque vivement conseillé.** + +* _Chez un particulier_ : la grappe est reliée à Internet par une *box*, qui filtre le trafic réseau selon des règles variables. La grappe se partage l'adresse IP de la box (qui peut changer régulièrement, être en IPv4 ou en IPv6). + + Dans ce cas de figure, **l'installation comme l'administration demandent plus de connaissances** : pour caricaturer, on doit installer et administrer la grappe **malgré le Fournisseur d'Accès Internet** (FAI), qui considère *a priori* que son abonnement ne sert pas à héberger des services web. + + On aura affaire à sa box (NAT, pare-feu...), au manque de garanties concernant notre adressabilité (IPv4 dynamique, IPv6 ? ...), ce qui va nous mener à devoir faire du routage. Le nœud du problème, c'est que chaque ordinateur de la grappe n'aura pas pignon sur rue (pas d'adresse IP publique et fixe par machine). + + Néanmoins, **on est chez nous !** Votre disque dur - qui contient les données personnelles de vos usagers chéris - est sous vos yeux, bien au chaud. Le seul curieux qui voit passer votre trafic réseau est votre FAI : *rien de nouveau sous le soleil*. + diff --git a/content/operations/rclone.md b/content/operations/rclone.md new file mode 100644 index 0000000..1352aaf --- /dev/null +++ b/content/operations/rclone.md @@ -0,0 +1,78 @@ +--- +title: "rclone" +description: "rclone" +weight: 20 +sort_by: "weight" +extra: + parent: 'operations/sauvegardes.md' +--- + +Script de backup brut, on planifie une approche plus élégante à l'avenir : + +``` +#!/bin/bash + +cd $(dirname $0) + +if [ "$(hostname)" != "io" ]; then + echo "Please run this script on io" + exit 1 +fi + +if [ ! -d "buckets" ]; then + btrfs subvolume create $(pwd)/buckets +fi + + +AK=$1 +SK=$2 + +function gctl { + docker exec garage /garage $@ +} + +gctl status +BUCKETS=$(gctl bucket list | tail -n +2 | cut -d " " -f 3 | cut -d "," -f 1) + +for BUCKET in $BUCKETS; do + case $BUCKET in + *backup*) + echo "Skipping $BUCKET (not doing backup of backup)" + ;; + *cache*) + echo "Skipping $BUCKET (not doing backup of cache)" + ;; + *) + echo "Backing up $BUCKET" + + if [ ! -d $(pwd)/buckets/$BUCKET ]; then + mkdir $(pwd)/buckets/$BUCKET + fi + + gctl bucket allow --key $AK --read $BUCKET + rclone sync --s3-endpoint http://localhost:3900 \ + --s3-access-key-id $AK \ + --s3-secret-access-key $SK \ + --s3-region garage \ + --s3-force-path-style \ + --transfers 32 \ + --fast-list \ + --stats-one-line \ + --stats 10s \ + --stats-log-level NOTICE \ + :s3:$BUCKET $(pwd)/buckets/$BUCKET + ;; + esac +done + +# Remove duplicates +#duperemove -dAr $(pwd)/buckets + +if [ ! -d "$(pwd)/snapshots" ]; then + mkdir snapshots +fi + +SNAPSHOT=$(pwd)/snapshots/buckets-$(date +%F) +echo "Making snapshot: $SNAPSHOT" +btrfs subvolume snapshot $(pwd)/buckets $SNAPSHOT +``` diff --git a/content/operations/restic.md b/content/operations/restic.md new file mode 100644 index 0000000..099d011 --- /dev/null +++ b/content/operations/restic.md @@ -0,0 +1,179 @@ +--- +title: "restic" +description: "restic" +weight: 10 +extra: + parent: 'operations/sauvegardes.md' +--- + + +Add the admin account as `deuxfleurs` to your `~/.mc/config` file + +You need to choose some names/identifiers: + +```bash +export ENDPOINT="https://s3.garage.tld" +export SERVICE_NAME="example" + + +export BUCKET_NAME="backups-${SERVICE_NAME}" +export NEW_ACCESS_KEY_ID="key-${SERVICE_NAME}" +export NEW_SECRET_ACCESS_KEY=$(openssl rand -base64 32) +export POLICY_NAME="policy-$BUCKET_NAME" +``` + +Create a new bucket: + +```bash +mc mb deuxfleurs/$BUCKET_NAME +``` + +Create a new user: + +```bash +mc admin user add deuxfleurs $NEW_ACCESS_KEY_ID $NEW_SECRET_ACCESS_KEY +``` + +Add this new user to your `~/.mc/config.json`, run this command before to generate the snippet to copy/paste: + +``` +cat > /dev/stdout < /tmp/policy.json </secrets/`: + +```bash +echo "USER Backup AWS access key ID" > backup_aws_access_key_id +echo "USER Backup AWS secret access key" > backup_aws_secret_access_key +echo "USER Restic repository, eg. s3:https://s3.garage.tld" > backup_restic_repository +echo "USER Restic password to encrypt backups" > backup_restic_password +``` + +Then run secretmgr: + +```bash +# Spawning a nix shell is an easy way to get all the dependencies you need +nix-shell + +# Check that secretmgr works for you +python3 secretmgr.py check + +# Now interactively feed the secrets +python3 secretmgr.py gen +``` + +--- + +Now we need a service that runs: + +``` +restic backup . +``` + +And also that garbage collect snapshots. +I propose: + +``` +restic forget --prune --keep-within 1m1d --keep-within-weekly 3m --keep-within-monthly 1y +``` + +Also try to restore a snapshot: + +``` +restic restore --target /tmp/$SERVICE_NAME +``` diff --git a/content/operations/sauvegardes.md b/content/operations/sauvegardes.md new file mode 100644 index 0000000..860733d --- /dev/null +++ b/content/operations/sauvegardes.md @@ -0,0 +1,47 @@ +--- +title: "Sauvegardes" +description: "Sauvegardes" +weight: 50 +sort_by: "weight" +extra: + parent: 'operations/_index.md' +--- + +# Données sauvegardées + + +[restic](./restic/) - Nous utilisons restic pour sauvegarder les logiciels +qui utilisent le système de fichier (Cryptpad, Dovecot, et Plume) ainsi que Consul. +À terme, nous aimerions être en mesure de tout pouvoir stocker directement sur Garage +et rendre obsolète ce mode de sauvegarde. + +[pg\_basebackup](./pg_basebackup/) - Nous utilisons cet outils pour sauvegarder l'ensemble +des tables gérées par notre base de données SQL sans impacter trop les performances. +Le tout est réalisé par un script python qui chiffre avec [age](https://github.com/FiloSottile/age) et envoie le backup via S3. +À terme, nous aimerions utiliser [wal-g](https://github.com/wal-g/wal-g) à la place. + +[rclone](./rclone/) - Combiné avec btrfs, nous copions sur un système de fichier à plat +le contenu de notre cluster afin de faire face en cas de corruption. +À terme, nous aimerions remplacer cet outil par quelque chose de similaire à [s3s3mirror](https://github.com/cobbzilla/s3s3mirror). + +# Localisation des sauvegardes + +[Suresnes](/infrastructures/machines/support/#suresnes-mercure) - À Suresnes, nous avons une instance Minio +dédiée aux sauvegardes de données. Elle reçoit les sauvegardes du système de fichier, de consul et de Postgres. + +[Rennes 2](/infrastructures/machines/support/#rennes-2-jupiter) - À Rennes, nous avons un simple serveur Debian +avec une partition en BTRFS. Il se charge de sauvegarder toutes les nuits le contenu de notre instance de production de Garage. +À terme il est possible qu'on décide de rationaliser nos sauvegardes et de choisir +de sauvegarder S3. + +# Durée de rétention et fréquence + +Les sauvegardes doivent être configurées avec les options suivantes : + +**Fréquence** - 1 fois par jour (toutes les nuits) +**Durée de rétention** - 1 an +**Politique de conservation des instantanés** - 1 instantané par jour pendant 1 mois, 1 instantané par semaine pendant 3 mois, 1 instantané par mois pendant 1 an + +**Exceptions** +Les sauvegardes de Postgres sont faites une fois par semaine seulement pour le moment +Le nombre d'instantané est de 1 par jour pendant 1 an pour Garage diff --git a/content/operations/sauvegardes/_index.md b/content/operations/sauvegardes/_index.md deleted file mode 100644 index b4d2c79..0000000 --- a/content/operations/sauvegardes/_index.md +++ /dev/null @@ -1,45 +0,0 @@ -+++ -title = "Sauvegardes" -description = "Sauvegardes" -weight = 30 -sort_by = "weight" -+++ - -# Données sauvegardées - - -[restic](./restic/) - Nous utilisons restic pour sauvegarder les logiciels -qui utilisent le système de fichier (Cryptpad, Dovecot, et Plume) ainsi que Consul. -À terme, nous aimerions être en mesure de tout pouvoir stocker directement sur Garage -et rendre obsolète ce mode de sauvegarde. - -[pg\_basebackup](./pg_basebackup/) - Nous utilisons cet outils pour sauvegarder l'ensemble -des tables gérées par notre base de données SQL sans impacter trop les performances. -Le tout est réalisé par un script python qui chiffre avec [age](https://github.com/FiloSottile/age) et envoie le backup via S3. -À terme, nous aimerions utiliser [wal-g](https://github.com/wal-g/wal-g) à la place. - -[rclone](./rclone/) - Combiné avec btrfs, nous copions sur un système de fichier à plat -le contenu de notre cluster afin de faire face en cas de corruption. -À terme, nous aimerions remplacer cet outil par quelque chose de similaire à [s3s3mirror](https://github.com/cobbzilla/s3s3mirror). - -# Localisation des sauvegardes - -[Suresnes](/infrastructures/machines/support/#suresnes-mercure) - À Suresnes, nous avons une instance Minio -dédiée aux sauvegardes de données. Elle reçoit les sauvegardes du système de fichier, de consul et de Postgres. - -[Rennes 2](/infrastructures/machines/support/#rennes-2-jupiter) - À Rennes, nous avons un simple serveur Debian -avec une partition en BTRFS. Il se charge de sauvegarder toutes les nuits le contenu de notre instance de production de Garage. -À terme il est possible qu'on décide de rationaliser nos sauvegardes et de choisir -de sauvegarder S3. - -# Durée de rétention et fréquence - -Les sauvegardes doivent être configurées avec les options suivantes : - -**Fréquence** - 1 fois par jour (toutes les nuits) -**Durée de rétention** - 1 an -**Politique de conservation des instantanés** - 1 instantané par jour pendant 1 mois, 1 instantané par semaine pendant 3 mois, 1 instantané par mois pendant 1 an - -**Exceptions** -Les sauvegardes de Postgres sont faites une fois par semaine seulement pour le moment -Le nombre d'instantané est de 1 par jour pendant 1 an pour Garage diff --git a/content/operations/sauvegardes/pg_basebackup.md b/content/operations/sauvegardes/pg_basebackup.md deleted file mode 100644 index 357e11f..0000000 --- a/content/operations/sauvegardes/pg_basebackup.md +++ /dev/null @@ -1,336 +0,0 @@ -+++ -title = "pg_basebackup" -description = "pg_basebackup" -weight=15 -+++ - -## Disclaimer - -Do **NOT** use the following backup methods on the Stolon Cluster: - 1. copying the data directory - 2. `pg_dump` - 3. `pg_dumpall` - -The first one will lead to corrupted/inconsistent files. -The second and third ones put too much pressure on the cluster. -Basically, you will destroy it, in the following ways: - - Load will increase, requests will timeout - - RAM will increase, the daemon will be OOM (Out Of Memory) killed by Linux - - Potentially, the WAL log will grow a lot - - -## A binary backup with `pg_basebackup` - -The only acceptable solution is `pg_basebackup` with **some throttling configured**. -Later, if you want a SQL dump, you can inject this binary backup on an ephemeral database you spawned solely for this purpose on a non-production machine. - -First, start by fetching from Consul the identifiers of the replication account. -Do not use the root account setup in Stolon, it will not work. - -First setup a SSH tunnel on your machine that bind postgresql, eg: - -```bash -ssh -L 5432:psql-proxy.service.2.cluster.deuxfleurs.fr:5432 ... -``` - -*Later, we will use `/tmp/sql` as our working directory. Depending on your distribution, this -folder may be a `tmpfs` and thus mounted on RAM. If it is the case, choose another folder, that is not a `tmpfs`, otherwise you will fill your RAM -and fail your backup. I am using NixOS and the `/tmp` folder is a regular folder, persisted on disk, which explain why I am using it.* - -Then export your password in `PGPASSWORD` and launch the backup: - -```bash -export PGPASSWORD=xxx - -mkdir -p /tmp/sql -cd /tmp/sql - -pg_basebackup \ - --host=127.0.0.1 \ - --username=replicator \ - --pgdata=/tmp/sql \ - --format=tar \ - --wal-method=stream \ - --gzip \ - --compress=6 \ - --progress \ - --max-rate=5M -``` - -*Something you should now: while it seems optional, fetching the WAL is mandatory. At first, I thought it was a way to have a "more recent backup". -But after some reading, it appears that the base backup is corrupted because it is not a snapshot at all, but a copy of the postgres folder with no specific state. -The whole point of the WAL is, in fact, to fix this corrupted archive...* - -*Take a cup of coffe, it will take some times...* - -The result I get (the important file is `base.tar.gz`, `41921.tar.gz` will probably be missing as it is a secondary tablespace I will deactivate soon): - -``` -[nix-shell:/tmp/sql]$ ls -41921.tar.gz backup_manifest base.tar.gz pg_wal.tar.gz -``` - -From now, disconnect from the production to continue your work. -You don't need it anymore and it will prevent some disaster if you fail a command. - - -## Importing the backup - -> The backup taken with `pg_basebckup` is an exact copy of your data directory so, all you need to do to restore from that backup is to point postgres at that directory and start it up. - -```bash -mkdir -p /tmp/sql/pg_data && cd /tmp/sql/pg_data -tar xzfv ../base.tar.gz -``` - -Now you should have something like that: - -``` -[nix-shell:/tmp/sql/pg_data]$ ls -backup_label base pg_commit_ts pg_hba.conf pg_logical pg_notify pg_serial pg_stat pg_subtrans pg_twophase pg_wal postgresql.conf tablespace_map -backup_label.old global pg_dynshmem pg_ident.conf pg_multixact pg_replslot pg_snapshots pg_stat_tmp pg_tblspc PG_VERSION pg_xact stolon-temp-postgresql.conf -``` - -Now we will extract the WAL: - -```bash -mkdir -p /tmp/sql/wal && cd /tmp/sql/wal -tar xzfv ../pg_wal.tar.gz -``` - -You should have something like that: - -``` -[nix-shell:/tmp/sql/wal]$ ls -00000003000014AF000000C9 00000003000014AF000000CA 00000003.history archive_status -``` - -Before restoring our backup, we want to check it: - -```bash -cd /tmp/sql/pg_data -cp ../backup_manifest . -# On ne vérifie pas le WAL car il semblerait que ça marche pas trop -# Cf ma référence en bas capdata.fr -# pg_verifybackup -w ../wal . -pg_verifybackup -n . - -``` - -Now, We must edit/read some files before launching our ephemeral server: - - Set `listen_addresses = '0.0.0.0'` in `postgresql.conf` - - Add `restore_command = 'cp /mnt/wal/%f %p' ` in `postgresql.conf` - - Check `port` in `postgresql.conf`, in our case it is `5433`. - - Create an empty file named `recovery.signal` - -*Do not create a `recovery.conf` file, it might be written on the internet but this is a deprecated method and your postgres daemon will refuse to boot if it finds one.* - -*Currently, we use port 5433 in oour postgresql configuration despite 5432 being the default port. Indeed, in production, clients access the cluster transparently through the Stolon Proxy that listens on port 5432 and redirect the requests to the correct PostgreSQL instance, listening secretly on port 5433! To export our binary backup in text, we will directly query our postgres instance without passing through the proxy, which is why you must note this port.* - -Now we will start our postgres container on our machine. - -At the time of writing the live version is `superboum/amd64_postgres:v9`. -We must start by getting `postgres` user id. Our container are run by default with this user, so you only need to run: - -```bash -docker run --rm -it superboum/amd64_postgres:v9 id -``` - -And we get: - -``` -uid=999(postgres) gid=999(postgres) groups=999(postgres),101(ssl-cert) -``` - -Now `chown` your `pg_data`: - -```bash -chown 999:999 -R /tmp/sql/{pg_data,wal} -chmod 700 -R /tmp/sql/{pg_data,wal} -``` - -And finally: - -``` -docker run \ - --rm \ - -it \ - -p 5433:5433 \ - -v /tmp/sql/:/mnt/ \ - superboum/amd64_postgres:v9 \ - postgres -D /mnt/pg_data -``` - -I have the following output: - -``` -2022-01-28 14:46:39.750 GMT [1] LOG: skipping missing configuration file "/mnt/pg_data/postgresql.auto.conf" -2022-01-28 14:46:39.763 UTC [1] LOG: starting PostgreSQL 13.3 (Debian 13.3-1.pgdg100+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 8.3.0-6) 8.3.0, 64-bit -2022-01-28 14:46:39.764 UTC [1] LOG: listening on IPv4 address "0.0.0.0", port 5433 -2022-01-28 14:46:39.767 UTC [1] LOG: listening on Unix socket "/tmp/.s.PGSQL.5433" -2022-01-28 14:46:39.773 UTC [7] LOG: database system was interrupted; last known up at 2022-01-28 14:33:13 UTC -cp: cannot stat '/mnt/wal/00000004.history': No such file or directory -2022-01-28 14:46:40.318 UTC [7] LOG: starting archive recovery -2022-01-28 14:46:40.321 UTC [7] LOG: restored log file "00000003.history" from archive -2022-01-28 14:46:40.336 UTC [7] LOG: restored log file "00000003000014AF000000C9" from archive -2022-01-28 14:46:41.426 UTC [7] LOG: could not open directory "pg_tblspc/41921/PG_13_202007201": No such file or directory -2022-01-28 14:46:41.445 UTC [7] LOG: could not open directory "pg_tblspc/41921/PG_13_202007201": No such file or directory -2022-01-28 14:46:41.457 UTC [7] LOG: redo starts at 14AF/C9000028 -2022-01-28 14:46:41.500 UTC [7] LOG: restored log file "00000003000014AF000000CA" from archive -2022-01-28 14:46:42.461 UTC [7] LOG: consistent recovery state reached at 14AF/CA369AB0 -2022-01-28 14:46:42.461 UTC [1] LOG: database system is ready to accept read only connections -cp: cannot stat '/mnt/wal/00000003000014AF000000CB': No such file or directory -2022-01-28 14:46:42.463 UTC [7] LOG: redo done at 14AF/CA369AB0 -2022-01-28 14:46:42.463 UTC [7] LOG: last completed transaction was at log time 2022-01-28 14:35:04.698438+00 -2022-01-28 14:46:42.480 UTC [7] LOG: could not open directory "pg_tblspc/41921/PG_13_202007201": No such file or directory -2022-01-28 14:46:42.493 UTC [7] LOG: restored log file "00000003000014AF000000CA" from archive -cp: cannot stat '/mnt/wal/00000004.history': No such file or directory -2022-01-28 14:46:43.462 UTC [7] LOG: selected new timeline ID: 4 -2022-01-28 14:46:44.441 UTC [7] LOG: archive recovery complete -2022-01-28 14:46:44.444 UTC [7] LOG: restored log file "00000003.history" from archive -2022-01-28 14:46:45.614 UTC [1] LOG: database system is ready to accept connections -``` - -*Notes: the missing tablespace is a legacy tablesplace used in the past to debug Matrix. It will be removed soon, we can safely ignore it. Other errors on cp seems to be intended as postgres might want to know how far it can rewind with the WAL but I a not 100% sure.* - -Your ephemeral instance should work: - -```bash -export PGPASSWORD=xxx # your postgres (admin) account password - -psql -h 127.0.0.1 -p 5433 -U postgres postgres -``` - -And your databases should appear: - -``` -[nix-shell:~/Documents/dev/infrastructure]$ psql -h 127.0.0.1 -p 5433 -U postgres postgres -psql (13.5, server 13.3 (Debian 13.3-1.pgdg100+1)) -Type "help" for help. - -postgres=# \l - List of databases - Name | Owner | Encoding | Collate | Ctype | Access privileges ------------+----------+----------+------------+------------+----------------------- - xxxxx | xxxxx | UTF8 | en_US.utf8 | en_US.utf8 | - xxxxx | xxxxx | UTF8 | en_US.utf8 | en_US.utf8 | - xxxxx | xxxxx | UTF8 | en_US.utf8 | en_US.utf8 | - postgres | postgres | UTF8 | en_US.utf8 | en_US.utf8 | - xxxx | xxxxx | UTF8 | en_US.utf8 | en_US.utf8 | - xxxx | xxxxx | UTF8 | en_US.utf8 | en_US.utf8 | - template0 | postgres | UTF8 | en_US.utf8 | en_US.utf8 | =c/postgres + - | | | | | postgres=CTc/postgres - template1 | postgres | UTF8 | en_US.utf8 | en_US.utf8 | =c/postgres + - | | | | | postgres=CTc/postgres -(8 rows) -``` - -## Dump your ephemeral database as SQL - -Now we can do a SQL export of our ephemeral database. -We use zstd to automatically compress the outputed file. -We use multiple parameters: - - `-vv` gives use some idea on the progress - - `-9` is a quite high value and should compress efficiently. Decrease it if your machine is low powered - - `-T0` asks zstd to use all your cores. By default, zstd uses only one core. - -```bash -pg_dumpall -h 127.0.0.1 -p 5433 -U postgres \ - | zstd -vv -9 -T0 --format=zstd > dump-`date --rfc-3339=seconds | sed 's/ /T/'`.sql.zstd -``` - -I get the following result: - -``` -[nix-shell:/tmp/sql]$ ls -lah dump* --rw-r--r-- 1 quentin users 749M janv. 28 16:07 dump-2022-01-28T16:06:29+01:00.sql.zstd -``` - -Now you can stop your ephemeral server. - -## Restore your SQL file - -First, start a blank server: - -```bash -docker run \ - --rm -it \ - --name postgres \ - -p 5433:5432 \ - superboum/amd64_postgres:v9 \ - bash -c ' - set -ex - mkdir /tmp/psql - initdb -D /tmp/psql --no-locale --encoding=UTF8 - echo "host all postgres 0.0.0.0/0 md5" >> /tmp/psql/pg_hba.conf - postgres -D /tmp/psql - ' -``` - -Then set the same password as your prod for the `posgtgres` user (it will be required as part of the restore): - -```bash -docker exec -ti postgres bash -c "echo \"ALTER USER postgres WITH PASSWORD '$PGPASSWORD';\" | psql" -echo '\l' | psql -h 127.0.0.1 -p 5433 -U postgres postgres -# the database should have no entry (except `posgtres`, `template0` and `template1`) otherwise ABORT EVERYTHING, YOU ARE ON THE WRONG DB -``` - -And finally, restore your SQL backup: - -```bash -zstdcat -vv dump-* | \ - grep -P -v '^(CREATE|DROP) ROLE postgres;' | \ - psql -h 127.0.0.1 -p 5433 -U postgres --set ON_ERROR_STOP=on postgres -``` - -*Note: we must skip CREATE/DROP ROLE postgres during the restore as it aready exists and would generate an error. -Because we want to be extra careful, we specifically asked to crash on every error and do not want to change this behavior. -So, instead, we simply remove any entry that contains the specific regex stated in the previous command.* - -Check that the backup has been correctly restored. -For example: - -```bash -docker exec -ti postgres psql -#then type "\l", "\c db-name", "select ..." -``` - -## Finally, store it safely - -```bash -rsync --progress -av /tmp/sql/{*.tar.gz,backup_manifest,dump-*} backup/target -``` - -## Garbage collect old backups - -``` -mc ilm import deuxfleurs/${BUCKET_NAME} < /dev/stdout < /tmp/policy.json </secrets/`: - -```bash -echo "USER Backup AWS access key ID" > backup_aws_access_key_id -echo "USER Backup AWS secret access key" > backup_aws_secret_access_key -echo "USER Restic repository, eg. s3:https://s3.garage.tld" > backup_restic_repository -echo "USER Restic password to encrypt backups" > backup_restic_password -``` - -Then run secretmgr: - -```bash -# Spawning a nix shell is an easy way to get all the dependencies you need -nix-shell - -# Check that secretmgr works for you -python3 secretmgr.py check - -# Now interactively feed the secrets -python3 secretmgr.py gen -``` - ---- - -Now we need a service that runs: - -``` -restic backup . -``` - -And also that garbage collect snapshots. -I propose: - -``` -restic forget --prune --keep-within 1m1d --keep-within-weekly 3m --keep-within-monthly 1y -``` - -Also try to restore a snapshot: - -``` -restic restore --target /tmp/$SERVICE_NAME -``` diff --git a/content/operations/ssh.md b/content/operations/ssh.md new file mode 100644 index 0000000..83b09bd --- /dev/null +++ b/content/operations/ssh.md @@ -0,0 +1,11 @@ +--- +title: "SSH" +description: "SSH" +weight: 100 +extra: + parent: 'operations/acces.md' +--- + +Voir si on documente comment gérer SSH depuis GPG + +# Ajout de la clé au cluster diff --git a/content/operations/stolon.md b/content/operations/stolon.md new file mode 100644 index 0000000..de20f09 --- /dev/null +++ b/content/operations/stolon.md @@ -0,0 +1,97 @@ +--- +title: "Stolon" +description: "Comment déployer Stolon" +date: 2022-12-22 +dateCreated: 2022-12-22 +weight: 11 +extra: + parent: 'operations/deployer.md' +--- + +Spawn container: + +```bash +docker run \ + -ti --rm \ + --name stolon-config \ + --user root \ + -v /var/lib/consul/pki/:/certs \ + superboum/amd64_postgres:v11 +``` + + +Init with: + +``` +stolonctl \ + --cluster-name chelidoine \ + --store-backend=consul \ + --store-endpoints https://consul.service.prod.consul:8501 \ + --store-ca-file /certs/consul-ca.crt \ + --store-cert-file /certs/consul2022-client.crt \ + --store-key /certs/consul2022-client.key \ + init \ + '{ "initMode": "new", + "usePgrewind" : true, + "proxyTimeout" : "120s", + "pgHBA": [ + "host all postgres all md5", + "host replication replicator all md5", + "host all all all ldap ldapserver=bottin.service.prod.consul ldapbasedn=\"ou=users,dc=deuxfleurs, dc=fr\" ldapbinddn=\"\" ldapbindpasswd=\"\" ldapsearchattribute=\"cn\"" + ] + }' + +``` + +Then set appropriate permission on host: + +``` +mkdir -p /mnt/{ssd,storage}/postgres/ +chown -R 999:999 /mnt/{ssd,storage}/postgres/ +``` + +(102 is the id of the postgres user used in Docker) +It might be improved by staying with root, then chmoding in an entrypoint and finally switching to user 102 before executing user's command. +Moreover it would enable the usage of the user namespace that shift the UIDs. + + + +## Upgrading the cluster + +To retrieve the current stolon config: + +``` +stolonctl spec --cluster-name chelidoine --store-backend consul --store-ca-file ... --store-cert-file ... --store-endpoints https://consul.service.prod.consul:8501 +``` + +The important part for the LDAP: + +``` +{ + "pgHBA": [ + "host all postgres all md5", + "host replication replicator all md5", + "host all all all ldap ldapserver=bottin.service.2.cluster.deuxfleurs.fr ldapbasedn=\"ou=users,dc=deuxfleurs,dc=fr\" ldapbinddn=\"cn=admin,dc=deuxfleurs,dc=fr\" ldapbindpasswd=\"\" ldapsearchattribute=\"cn\"" + ] +} +``` + +Once a patch is writen: + +``` +stolonctl --cluster-name pissenlit --store-backend consul --store-endpoints http://consul.service.2.cluster.deuxfleurs.fr:8500 update --patch -f /tmp/patch.json +``` + +## Log + +- 2020-12-18 Activate pg\_rewind in stolon + +``` +stolonctl --cluster-name pissenlit --store-backend consul --store-endpoints http://consul.service.2.cluster.deuxfleurs.fr:8500 update --patch '{ "usePgrewind" : true }' +``` + +- 2021-03-14 Increase proxy timeout to cope with consul latency spikes + +``` +stolonctl --cluster-name pissenlit --store-backend consul --store-endpoints http://consul.service.2.cluster.deuxfleurs.fr:8500 update --patch '{ "proxyTimeout" : "120s" }' +``` diff --git a/content/operations/supervision.md b/content/operations/supervision.md new file mode 100644 index 0000000..5b76a2b --- /dev/null +++ b/content/operations/supervision.md @@ -0,0 +1,23 @@ +--- +title: "Supervision" +description: "Supervision" +weight: 58 +sort_by: "weight" +extra: + parent: 'operations/_index.md' +--- + +# Métriques + +Grafana est accessible à l'adresse suivante : https://grafana.deuxfleurs.fr + +Vous pouvez obtenir le mot de passe admin en allant le chercher dans consul KV + +# Journaux + +Les journaux ne sont pas centralisés aujourd'hui. +Vous pouvez les consulter avec `docker logs`, `nomad` et `journalctl`. + +# Alertes + +Nous n'avons pas de système d'alerte aujourd'hui. diff --git a/content/operations/supervision/_index.md b/content/operations/supervision/_index.md deleted file mode 100644 index ee71625..0000000 --- a/content/operations/supervision/_index.md +++ /dev/null @@ -1,12 +0,0 @@ -+++ -title = "Supervision" -description = "Supervision" -weight = 40 -sort_by = "weight" -+++ - -# Métriques - -# Journaux - -# Alertes diff --git a/content/operations/vue_ensemble.md b/content/operations/vue_ensemble.md new file mode 100644 index 0000000..cbd337d --- /dev/null +++ b/content/operations/vue_ensemble.md @@ -0,0 +1,62 @@ +--- +title: "Vue d'ensemble" +description: "Vue d'ensemble" +sort_by: "weight" +weight: 0 +extra: + parent: 'operations/_index.md' +--- + +*Ajouter un schéma* + +# Les composants + +**Orchestrateur** - L'orchestrateur est en charge de placer les applications +sur les serveurs de sorte qu'en cas de crash, une application soit relancée ailleurs. +En fonctionnement nominal, l'orchestrateur se charge de placer les applications de sorte +à ce que les ressources soient utilisées au mieux. Nous utilison le logiciel Nomad à ces fins. + +[↣ Accéder au code source de Nomad](https://github.com/hashicorp/nomad) + +**Catalogue de service** - Le catalogue de service permet aux services ayant des dépendances, par exemple +Matrix a une dépendance sur PostgreSQL et Garage, de savoir comment contacter ces dépendances. +Pour ce faire, nous utilisons Consul, qui nous sert également à gérer nos secrets. + +[↣ Accéder au code source de Consul](https://github.com/hashicorp/consul/) + +**Base de données relationnelle** - Les bases de données relationnelles sont au coeur de +la plupart des applications web car elles permettent de requêter efficacement des données structurées. +Nous utilisons PostgreSQL qui est un des standard du libre, et afin de le distribuer, nous utilisons +Stolon. + +[↣ Accéder au code source de PostgreSQL](https://git.postgresql.org/gitweb/?p=postgresql.git;a=summary) +[↣ Accéder au code source de Stolon](https://github.com/sorintlab/stolon) + +**Base de données NoSQL** - Nous prévoyions certains développements spécifiques, +pour lesquels nous avons le loisir de définir la structure de données. +Dans ce cas, nous pouvons l'optimiser pour Garage K2V qui est bien plus facile à opérer que PostgreSQL. + + +[↣ Accéder au code source de Garage](https://git.deuxfleurs.fr/Deuxfleurs/garage) + +**Stockage objet** - De nombreuses applications ont besoin de stocker des fichiers également, +des données considérées non structurées dans ce cas. Ici l'enjeu n'est plus tant de pouvoir +requêter les données avec souplesse que de pouvoir stocker de grands volumes. +On peut prendre comme exemple les médias (photo, vidéo) partagés sur Matrix. +Nous utilisons l'API S3 de Garage pour ces besoins. + +[↣ Accéder au code source de Garage](https://git.deuxfleurs.fr/Deuxfleurs/garage) + +**Authentification** - Afin de faciliter la vie des usager-es, il est possible de proposer un système d'authentification unique. +Pour commencer, nous avons choisi le protocole LDAP qui a pour principal avantage d'être largement installé et compatible, +principalement grâce à son ancienneté. Nous utilisons notre propre implémentation, nommée Bottin. + +[↣ Accéder au code source de Bottin](https://git.deuxfleurs.fr/Deuxfleurs/bottin) + +**Conteneurs** - Afin de packager, publier et isoler les différentes applications qui fonctionnent sur nos serveurs, +nous utilisons des conteneurs Linux, et plus précisément, Docker. Afin de créer des images les plus petites possibles, +nous utilisons NixOS. Pour certaines vieilles images, nous utilisons encore Debian. + +[↣ Accéder au code source de Docker](https://github.com/moby/moby) +[↣ Accéder au code source de Nix](https://github.com/NixOS/nixpkgs) +[↣ Accéder au code source de Debian](https://www.debian.org/distrib/packages) diff --git a/content/operations/vue_ensemble/_index.md b/content/operations/vue_ensemble/_index.md deleted file mode 100644 index acd5d28..0000000 --- a/content/operations/vue_ensemble/_index.md +++ /dev/null @@ -1,60 +0,0 @@ -+++ -title = "Vue d'ensemble" -description = "Vue d'ensemble" -sort_by = "weight" -weight = 2 -+++ - -*Ajouter un schéma* - -# Les composants - -**Orchestrateur** - L'orchestrateur est en charge de placer les applications -sur les serveurs de sorte qu'en cas de crash, une application soit relancée ailleurs. -En fonctionnement nominal, l'orchestrateur se charge de placer les applications de sorte -à ce que les ressources soient utilisées au mieux. Nous utilison le logiciel Nomad à ces fins. - -[↣ Accéder au code source de Nomad](https://github.com/hashicorp/nomad) - -**Catalogue de service** - Le catalogue de service permet aux services ayant des dépendances, par exemple -Matrix a une dépendance sur PostgreSQL et Garage, de savoir comment contacter ces dépendances. -Pour ce faire, nous utilisons Consul, qui nous sert également à gérer nos secrets. - -[↣ Accéder au code source de Consul](https://github.com/hashicorp/consul/) - -**Base de données relationnelle** - Les bases de données relationnelles sont au coeur de -la plupart des applications web car elles permettent de requêter efficacement des données structurées. -Nous utilisons PostgreSQL qui est un des standard du libre, et afin de le distribuer, nous utilisons -Stolon. - -[↣ Accéder au code source de PostgreSQL](https://git.postgresql.org/gitweb/?p=postgresql.git;a=summary) -[↣ Accéder au code source de Stolon](https://github.com/sorintlab/stolon) - -**Base de données NoSQL** - Nous prévoyions certains développements spécifiques, -pour lesquels nous avons le loisir de définir la structure de données. -Dans ce cas, nous pouvons l'optimiser pour Garage K2V qui est bien plus facile à opérer que PostgreSQL. - - -[↣ Accéder au code source de Garage](https://git.deuxfleurs.fr/Deuxfleurs/garage) - -**Stockage objet** - De nombreuses applications ont besoin de stocker des fichiers également, -des données considérées non structurées dans ce cas. Ici l'enjeu n'est plus tant de pouvoir -requêter les données avec souplesse que de pouvoir stocker de grands volumes. -On peut prendre comme exemple les médias (photo, vidéo) partagés sur Matrix. -Nous utilisons l'API S3 de Garage pour ces besoins. - -[↣ Accéder au code source de Garage](https://git.deuxfleurs.fr/Deuxfleurs/garage) - -**Authentification** - Afin de faciliter la vie des usager-es, il est possible de proposer un système d'authentification unique. -Pour commencer, nous avons choisi le protocole LDAP qui a pour principal avantage d'être largement installé et compatible, -principalement grâce à son ancienneté. Nous utilisons notre propre implémentation, nommée Bottin. - -[↣ Accéder au code source de Bottin](https://git.deuxfleurs.fr/Deuxfleurs/bottin) - -**Conteneurs** - Afin de packager, publier et isoler les différentes applications qui fonctionnent sur nos serveurs, -nous utilisons des conteneurs Linux, et plus précisément, Docker. Afin de créer des images les plus petites possibles, -nous utilisons NixOS. Pour certaines vieilles images, nous utilisons encore Debian. - -[↣ Accéder au code source de Docker](https://github.com/moby/moby) -[↣ Accéder au code source de Nix](https://github.com/NixOS/nixpkgs) -[↣ Accéder au code source de Debian](https://www.debian.org/distrib/packages) -- cgit v1.2.3 From 0c1783e6c69a130b500e6c9452f800562b7e5fd2 Mon Sep 17 00:00:00 2001 From: Quentin Dufour Date: Thu, 2 Mar 2023 13:11:08 +0100 Subject: fix links --- content/operations/acces.md | 2 +- "content/operations/guide_cr\303\251ation_n\305\223ud.md" | 2 +- content/operations/matrix.md | 3 --- content/operations/noeud.md | 4 ++-- content/operations/sauvegardes.md | 10 +++++----- 5 files changed, 9 insertions(+), 12 deletions(-) (limited to 'content/operations') diff --git a/content/operations/acces.md b/content/operations/acces.md index 76ea226..4885e47 100644 --- a/content/operations/acces.md +++ b/content/operations/acces.md @@ -7,4 +7,4 @@ extra: parent: 'operations/_index.md' --- -Ici l'on traite de comment gagner accès au cluster de Deuxfleurs, quand on a reçu la _terrible responsabilité_ de sysadmin. Vous êtes prêt⋅e ? Alors entrez dans [le dépôt des secrets](./pass/). +Ici l'on traite de comment gagner accès au cluster de Deuxfleurs, quand on a reçu la _terrible responsabilité_ de sysadmin. Vous êtes prêt⋅e ? Alors entrez dans [le dépôt des secrets](@/operations/pass.md). diff --git "a/content/operations/guide_cr\303\251ation_n\305\223ud.md" "b/content/operations/guide_cr\303\251ation_n\305\223ud.md" index 11cbc27..4115aef 100644 --- "a/content/operations/guide_cr\303\251ation_n\305\223ud.md" +++ "b/content/operations/guide_cr\303\251ation_n\305\223ud.md" @@ -16,7 +16,7 @@ Configurons d'abord quelques paramètres dans l'UEFI de la machine. Démarrez-l ## Installation de NixOS -> Aucun écran ou clavier n'est disponible pour l'ordinateur cible ? NixOS peut être installé en SSH. Suivre les instructions sur [cette page](/operations/deploiement/noeud/ssh-sans-ecran). +> Aucun écran ou clavier n'est disponible pour l'ordinateur cible ? NixOS peut être installé en SSH, une page y est dédiée : [Installer NixOS sans écran](@/operations/SSH_sans_écran.md). Pour installer NixOS, nous aurons besoin d'une clé USB avec une image amorçable (*live*) de NixOS dessus. Nous pouvons télécharger la distribution linux en 64 bits et en version minimale (sans interface graphique et avec moins d'utilitaires) sur le [site officiel](https://nixos.org/download.html). Pour écrire l'image sur le support USB, on peut faire `dd if=chemin-vers-le-fichier-iso of=/dev/sdX status=progress; sync`, en remplaçant `sdX` par le fichier périphérique correspondant à la clé, trouvé avec `lsblk` par exemple. Alternativement, cela peut être l'occasion de créer une clé USB formatée avec [Ventoy](https://ventoy.net), un utilitaire très pratique diff --git a/content/operations/matrix.md b/content/operations/matrix.md index ab1c255..bfcde55 100644 --- a/content/operations/matrix.md +++ b/content/operations/matrix.md @@ -71,12 +71,9 @@ Do the same thing for the `synapse` service. Now, you need a way to access the cluster to deploy this file. To do this, you must bind nomad on your machine through a SSH tunnel. -Check the end of [the parent `README.md`](../README.md) to do it. If you have access to the Nomad web UI when entering http://127.0.0.1:4646 you are ready to go. -You must have installed the Nomad command line tool on your machine (also explained in [the parent `README.md`](../README.md)). - Now, on your machine and from the `app/im/deploy` folder, you must be able to run: ``` diff --git a/content/operations/noeud.md b/content/operations/noeud.md index 8e07f74..31604d4 100644 --- a/content/operations/noeud.md +++ b/content/operations/noeud.md @@ -11,6 +11,6 @@ extra: # Déployer un nœud au sein de l'infrastructure Deuxfleurs Déployer un nœud au sein de l'infrastructure Deuxfleurs demande un certaine préparation et représente un processus particulier. -Avant de se lancer, [mieux vaut vérifier les prérequis pour y parvenir](./prerequis/). Une fois ceci fait, on peut suivre [le guide décrivant la procédure](./guide-creation-noeud/). +Avant de se lancer, [mieux vaut vérifier les prérequis pour y parvenir](@/operations/prérequis.md). Une fois ceci fait, on peut suivre [le guide décrivant la procédure](@/operations/guide_création_nœud.md). -Si vous avez une machine à installer, mais aucun écran & clavier à brancher dessus pour la configurer, référez-vous au [guide d'installation de NixOs en SSH](./ssh-sans-ecran/). +Si vous avez une machine à installer, mais aucun écran & clavier à brancher dessus pour la configurer, référez-vous au [guide d'installation de NixOs en SSH](@/operations/SSH_sans_écran.md). diff --git a/content/operations/sauvegardes.md b/content/operations/sauvegardes.md index 860733d..5c62980 100644 --- a/content/operations/sauvegardes.md +++ b/content/operations/sauvegardes.md @@ -10,26 +10,26 @@ extra: # Données sauvegardées -[restic](./restic/) - Nous utilisons restic pour sauvegarder les logiciels +[restic](@/operations/restic.md) - Nous utilisons restic pour sauvegarder les logiciels qui utilisent le système de fichier (Cryptpad, Dovecot, et Plume) ainsi que Consul. À terme, nous aimerions être en mesure de tout pouvoir stocker directement sur Garage et rendre obsolète ce mode de sauvegarde. -[pg\_basebackup](./pg_basebackup/) - Nous utilisons cet outils pour sauvegarder l'ensemble +[pg\_basebackup](@/operations/pg_basebackup.md) - Nous utilisons cet outils pour sauvegarder l'ensemble des tables gérées par notre base de données SQL sans impacter trop les performances. Le tout est réalisé par un script python qui chiffre avec [age](https://github.com/FiloSottile/age) et envoie le backup via S3. À terme, nous aimerions utiliser [wal-g](https://github.com/wal-g/wal-g) à la place. -[rclone](./rclone/) - Combiné avec btrfs, nous copions sur un système de fichier à plat +[rclone](@/operations/rclone.md) - Combiné avec btrfs, nous copions sur un système de fichier à plat le contenu de notre cluster afin de faire face en cas de corruption. À terme, nous aimerions remplacer cet outil par quelque chose de similaire à [s3s3mirror](https://github.com/cobbzilla/s3s3mirror). # Localisation des sauvegardes -[Suresnes](/infrastructures/machines/support/#suresnes-mercure) - À Suresnes, nous avons une instance Minio +[Suresnes](@/infrastructures/support.md#suresnes-mercure) - À Suresnes, nous avons une instance Minio dédiée aux sauvegardes de données. Elle reçoit les sauvegardes du système de fichier, de consul et de Postgres. -[Rennes 2](/infrastructures/machines/support/#rennes-2-jupiter) - À Rennes, nous avons un simple serveur Debian +[Rennes 2](@/infrastructures/support.md#rennes-jupiter) - À Rennes, nous avons un simple serveur Debian avec une partition en BTRFS. Il se charge de sauvegarder toutes les nuits le contenu de notre instance de production de Garage. À terme il est possible qu'on décide de rationaliser nos sauvegardes et de choisir de sauvegarder S3. -- cgit v1.2.3 From ff6fc649a16691ab634d4a3466178e687b49f880 Mon Sep 17 00:00:00 2001 From: adrien Date: Thu, 16 Mar 2023 13:09:00 +0000 Subject: =?UTF-8?q?Update=20Op=C3=A9rations=20=E2=80=9Cemail=E2=80=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- content/operations/email.md | 40 ++++++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 14 deletions(-) (limited to 'content/operations') diff --git a/content/operations/email.md b/content/operations/email.md index ac5dfe5..2ee981a 100644 --- a/content/operations/email.md +++ b/content/operations/email.md @@ -1,33 +1,45 @@ --- -title: "Emails" -description: "Emails" +title: Emails +description: Emails weight: 10 +draft: false +date: 2023-03-16 extra: - parent: 'operations/courantes.md' + parent: operations/courantes.md --- - # Support d'un nom de domaine personnalisé - 1. xxx - 1. Communiquez lui votre nom de domaine pour qu'il l'ajoute dans `ou=domains,ou=groups,dc=deuxfleurs,dc=fr` - 2. Communiquez lui l'adresse email que vous souhaitez pour qu'il change l'entrée `mail` dans votre profil utilisateur - 3. Si vous souhaitez avoir une boite mais plusieurs alias, demandez un champs `uid` dans votre profil utilisateur +Deuxfleurs peut héberger vos e-mails, même s'ils ne finissent pas en `@deuxfleurs.fr ! Voilà comment faire.` + +1. Communiquez lui votre nom de domaine pour qu'il l'ajoute dans `ou=domains,ou=groups,dc=deuxfleurs,dc=fr` +1. Communiquez lui l'adresse email que vous souhaitez pour qu'il change l'entrée `mail` dans votre profil utilisateur +1. Vous devez ensuite rajouter les entrées pour votre nom de domaine en éditant votre zone : +1. L'entrée MX pour recevoir les emails - 2. Vous devez ensuite rajouter les entrées pour votre nom de domaine en éditant votre zone : - 1. L'entrée MX pour recevoir les emails ```bind @ MX 10 email-in.deuxfleurs.fr ``` - 2. L'entrée SPF pour autoriser notre IP à délivrer des emails en votre nom : + +1. L'entrée SPF pour autoriser notre IP à délivrer des emails en votre nom : + ```bind @ TXT "v=spf1 mx:out.deuxfleurs.fr -all" ``` - 3. L'entrée DKIM pour autoriser notre postfix+opendkim à délivrer des emails en votre nom : + +1. L'entrée DKIM pour autoriser notre postfix+opendkim à délivrer des emails en votre nom : + ``` smtp._domainkey TXT "v=DKIM1; h=sha256; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtdZp4qrgZR+6R7HeAkuLGJ/3L/6Ungvf5zwrMq6T8Tu931j2G4lYuPtsxyn9fZkT4y7DlX0waktLDBOCwf7X78nLEWjAFWiJTeWGRGhRdYRUFpscs9NUN0P+46jKlabibG3XTKd1DeAmywTu6o1oO03yiolrgKD1zgyDRFeUTfSwZIdPrdbcBSA1arda4WFtcBIrSygM9b4jtlqfQwGDrsMLbCBfVHDn4WfmDWyNg0gDAkuLrYClNETk6aqIyj9fC8srKri0Qp3cRagCn+fjBvuxP35qWWJH7Rnnh/tuEDr1ufuNYO2KgJZ7JdMidUotxXE8cfU+OrEWQf4mIYeJ4wIDAQAB" ``` - 4. L'entrée DMARC pour indiquer le comportement à adopter si les contraintes précédentes ne sont pas satisfaites : + +1. L'entrée DMARC pour indiquer le comportement à adopter si les contraintes précédentes ne sont pas satisfaites : + ``` _dmarc TXT "v=DMARC1; p=reject; sp=reject; adkim=s; aspf=s; rua=mailto:contact@deuxfleurs.fr!10m; ruf=mailto:contact@deuxfleurs.fr!10m; rf=afrf; pct=100; ri=86400" ``` - 3. C'est tout ! Vous devrez probablement attendre 24/48h que les changements se propagent. + +1. C'est tout ! Vous devrez probablement attendre 24/48h que les changements se propagent. + + + + -- cgit v1.2.3 From 533aeca395f77c630200e7bb63ee1049c4abe912 Mon Sep 17 00:00:00 2001 From: Adrien Date: Thu, 16 Mar 2023 14:12:13 +0100 Subject: coquille --- content/operations/email.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'content/operations') diff --git a/content/operations/email.md b/content/operations/email.md index 2ee981a..ab49497 100644 --- a/content/operations/email.md +++ b/content/operations/email.md @@ -9,7 +9,7 @@ extra: --- # Support d'un nom de domaine personnalisé -Deuxfleurs peut héberger vos e-mails, même s'ils ne finissent pas en `@deuxfleurs.fr ! Voilà comment faire.` +Deuxfleurs peut héberger vos e-mails, même s'ils ne finissent pas en `@deuxfleurs.fr` ! Voilà comment faire. 1. Communiquez lui votre nom de domaine pour qu'il l'ajoute dans `ou=domains,ou=groups,dc=deuxfleurs,dc=fr` 1. Communiquez lui l'adresse email que vous souhaitez pour qu'il change l'entrée `mail` dans votre profil utilisateur -- cgit v1.2.3 From 68edf0c3d1ec8e4aedafe1a0e2405455b39b877f Mon Sep 17 00:00:00 2001 From: Adrien Date: Thu, 16 Mar 2023 14:14:28 +0100 Subject: coquille --- content/operations/email.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'content/operations') diff --git a/content/operations/email.md b/content/operations/email.md index ab49497..fc774c3 100644 --- a/content/operations/email.md +++ b/content/operations/email.md @@ -17,7 +17,7 @@ Deuxfleurs peut héberger vos e-mails, même s'ils ne finissent pas en `@deuxfle 1. L'entrée MX pour recevoir les emails ```bind -@ MX 10 email-in.deuxfleurs.fr +@ MX 10 email-in.deuxfleurs.fr. ``` 1. L'entrée SPF pour autoriser notre IP à délivrer des emails en votre nom : -- cgit v1.2.3 From 253530da17e4427ed47f6f465893a5298e5c1c63 Mon Sep 17 00:00:00 2001 From: Adrien Date: Thu, 16 Mar 2023 14:41:02 +0100 Subject: =?UTF-8?q?mise=20=C3=A0=20jour=20guide=20Email?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- content/operations/email.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'content/operations') diff --git a/content/operations/email.md b/content/operations/email.md index fc774c3..bb87c57 100644 --- a/content/operations/email.md +++ b/content/operations/email.md @@ -17,7 +17,7 @@ Deuxfleurs peut héberger vos e-mails, même s'ils ne finissent pas en `@deuxfle 1. L'entrée MX pour recevoir les emails ```bind -@ MX 10 email-in.deuxfleurs.fr. +@ MX 10 email-in.deuxfleurs.fr. ``` 1. L'entrée SPF pour autoriser notre IP à délivrer des emails en votre nom : @@ -35,7 +35,7 @@ smtp._domainkey TXT "v=DKIM1; h=sha256; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCA 1. L'entrée DMARC pour indiquer le comportement à adopter si les contraintes précédentes ne sont pas satisfaites : ``` -_dmarc TXT "v=DMARC1; p=reject; sp=reject; adkim=s; aspf=s; rua=mailto:contact@deuxfleurs.fr!10m; ruf=mailto:contact@deuxfleurs.fr!10m; rf=afrf; pct=100; ri=86400" +_dmarc TXT "v=DMARC1; p=reject; sp=reject; adkim=s; fo=1; aspf=s; ruf=mailto:prod-sysadmin@deuxfleurs.fr; rf=afrf; pct=100; ri=86400" ``` 1. C'est tout ! Vous devrez probablement attendre 24/48h que les changements se propagent. -- cgit v1.2.3 From 15b3341237d374b09e4355b284dfe33c58e648f6 Mon Sep 17 00:00:00 2001 From: Alex Auvolat Date: Fri, 17 Mar 2023 12:19:37 +0100 Subject: =?UTF-8?q?d=C3=A9but=20=C3=A9criture=20sur=20les=20enregistrement?= =?UTF-8?q?s=20dns=20du=20mail?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- content/operations/email.md | 56 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) (limited to 'content/operations') diff --git a/content/operations/email.md b/content/operations/email.md index bb87c57..bb8cbb7 100644 --- a/content/operations/email.md +++ b/content/operations/email.md @@ -7,6 +7,7 @@ date: 2023-03-16 extra: parent: operations/courantes.md --- + # Support d'un nom de domaine personnalisé Deuxfleurs peut héberger vos e-mails, même s'ils ne finissent pas en `@deuxfleurs.fr` ! Voilà comment faire. @@ -42,4 +43,59 @@ _dmarc TXT "v=DMARC1; p=reject; sp=reject; adkim=s; fo=1; aspf=s; ruf=mailto:p +# Le fonctionnement des e-mails + +## Serveurs + +- SMTP: Postfix + +- IMAP: Dovecot (fixé sur une machine avec un backup) + +## Enregistrements DNS + +| nom | type | valeur | signification | +| --- | ---- | ------ | ------------- | +| `@` | `MX` | `12 email-in.deuxfleurs.fr` | Serveur que chercheront à joindre les gens qui veulent envoyer un courrier à une addresse `@deuxfleurs.fr` | +| `default.\_domainkey` | `TXT` | `v=DKIM1; h=sha256; k=rsa; p=` | Enregistrement DKIM (voir ci-dessous) | +| `smtp.\_domainkey` | `TXT` | `v=DKIM1; h=sha256; k=rsa; p=` | Enregistrement DKIM (voir ci-dessous) | +| `@` | `TXT` | `"v=spf1 mx:out.deuxfleurs.fr ip4: [...] -all" | Enregistrement SPF (voir ci-dessous) | +| `\_dmarc` | `TXT` | `"v=DMARC1; [...]` | Enregistrement DMARC (voir ci-dessous) | +| `email-in` | `A` | défini par D53 | Addresse IPv4 pour parler au serveur Postfix (pour l'enregistrement MX) | +| `smtp` | `A` | défini par D53 | Addresse IPv4 pour parler au serveur Postfix (pour les utilisateurs Deuxfleurs) | +| `imap` | `A` | défini par D53 | Addresse IPv4 pour parler au serveur Dovecot (pour les utilisateurs Deuxfleurs) | + +### L'enregistrement DKIM + +Exemple de valeurs : + +``` +default._domainkey.deuxfleurs.fr. 10800 IN TXT "v=DKIM1; h=sha256; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtdZp4qrgZR+6R7HeAkuLGJ/3L/6Ungvf5zwrMq6T8Tu931j2G4lYuPtsxyn9fZkT4y7DlX0waktLDB" "OCwf7X78nLEWjAFWiJTeWGRGhRdYRUFpscs9NUN0P+46jKlabibG3XTKd1DeAmywTu6o1oO03yiolrgKD1zgyDRFeUTfSwZIdPrdbcBSA1arda4WFtcBIrSygM9b4jtlqfQwGDrsMLbCBfVHDn4Wfm" "DWyNg0gDAkuLrYClNETk6aqIyj9fC8srKri0Qp3cRagCn+fjBvuxP35qWWJH7Rnnh/tuEDr1ufuNYO2KgJZ7JdMidUotxXE8cfU+OrEWQf4mIYeJ4wIDAQAB" + +smtp._domainkey.deuxfleurs.fr. 1800 IN TXT "v=DKIM1; h=sha256; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtdZp4qrgZR+6R7HeAkuLGJ/3L/6Ungvf5zwrMq6T8Tu931j2G4lYuPtsxyn9fZkT4y7DlX0waktLDB" "OCwf7X78nLEWjAFWiJTeWGRGhRdYRUFpscs9NUN0P+46jKlabibG3XTKd1DeAmywTu6o1oO03yiolrgKD1zgyDRFeUTfSwZIdPrdbcBSA1arda4WFtcBIrSygM9b4jtlqfQwGDrsMLbCBfVHDn4Wfm" "DWyNg0gDAkuLrYClNETk6aqIyj9fC8srKri0Qp3cRagCn+fjBvuxP35qWWJH7Rnnh/tuEDr1ufuNYO2KgJZ7JdMidUotxXE8cfU+OrEWQf4mIYeJ4wIDAQAB" + +default._domainkey.adnab.me. 3600 IN TXT "v=DKIM1; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDHd2zQXgGAoFX2CFaRqvWw1oBGhbUIRB5QXPxE9nvWwe/og5LjZBcnKoInPWsKYEz/f5kmpTDq4RZT3PMmjm+u5IuvyQ2LJcdIKSW6t8KWa7yztk2D87f3Lono6WJwvY8RHdGPqKS5RXfEdQFriXiSCAO5ZSQrNXQ5yiQ9T1ptGwIDAQAB; t=s" +``` +Structure : + +- Le nom de domaine est composé d'un selecteur (souvent `default`, on a ici aussi `smtp`) qui permet de distinguer différentes clefs pour signer les messages. + Il est formé de la manière suivante: `.\_domainkey.` + +### L'enregistrement SPF + +Exemple de valeurs : + +``` +deuxfleurs.fr. 300 IN TXT "v=spf1 mx:out.deuxfleurs.fr ip4:82.66.80.201 -all" +adnab.me. 3600 IN TXT "v=spf1 mx mx:adnab.me include:mx.ovh.com -all" +``` + +### L'enregistrement DMARC + + +Exemple de valeurs : + +``` +_dmarc.deuxfleurs.fr. 300 IN TXT "v=DMARC1; p=reject; sp=reject; adkim=s; fo=1; aspf=s; ruf=mailto:prod-sysadmin@deuxfleurs.fr; rua=mailto:prod-sysadmin@deuxfleurs.fr; rf=afrf; pct=100; ri=86400" +_dmarc.adnab.me. 3600 IN TXT "v=DMARC1; p=reject; sp=reject; adkim=s; aspf=s; rua=mailto:postmaster@adnab.me!10m; ruf=mailto:postmaster@adnab.me!10m; rf=afrf; pct=100; ri=86400" +``` -- cgit v1.2.3 From b577474cfdd4cee3caea93103d0610155ff49aab Mon Sep 17 00:00:00 2001 From: Alex Auvolat Date: Fri, 17 Mar 2023 12:36:10 +0100 Subject: Structure signature DKIM --- content/operations/email.md | 49 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 41 insertions(+), 8 deletions(-) (limited to 'content/operations') diff --git a/content/operations/email.md b/content/operations/email.md index bb8cbb7..89378cf 100644 --- a/content/operations/email.md +++ b/content/operations/email.md @@ -43,7 +43,7 @@ _dmarc TXT "v=DMARC1; p=reject; sp=reject; adkim=s; fo=1; aspf=s; ruf=mailto:p -# Le fonctionnement des e-mails +# Comprendre le fonctionnement des e-mails ## Serveurs @@ -56,17 +56,19 @@ _dmarc TXT "v=DMARC1; p=reject; sp=reject; adkim=s; fo=1; aspf=s; ruf=mailto:p | nom | type | valeur | signification | | --- | ---- | ------ | ------------- | | `@` | `MX` | `12 email-in.deuxfleurs.fr` | Serveur que chercheront à joindre les gens qui veulent envoyer un courrier à une addresse `@deuxfleurs.fr` | -| `default.\_domainkey` | `TXT` | `v=DKIM1; h=sha256; k=rsa; p=` | Enregistrement DKIM (voir ci-dessous) | -| `smtp.\_domainkey` | `TXT` | `v=DKIM1; h=sha256; k=rsa; p=` | Enregistrement DKIM (voir ci-dessous) | +| `default._domainkey` | `TXT` | `v=DKIM1; h=sha256; k=rsa; p=` | Enregistrement DKIM (voir ci-dessous) | +| `smtp._domainkey` | `TXT` | `v=DKIM1; h=sha256; k=rsa; p=` | Enregistrement DKIM (voir ci-dessous) | | `@` | `TXT` | `"v=spf1 mx:out.deuxfleurs.fr ip4: [...] -all" | Enregistrement SPF (voir ci-dessous) | -| `\_dmarc` | `TXT` | `"v=DMARC1; [...]` | Enregistrement DMARC (voir ci-dessous) | +| `_dmarc` | `TXT` | `"v=DMARC1; [...]` | Enregistrement DMARC (voir ci-dessous) | | `email-in` | `A` | défini par D53 | Addresse IPv4 pour parler au serveur Postfix (pour l'enregistrement MX) | | `smtp` | `A` | défini par D53 | Addresse IPv4 pour parler au serveur Postfix (pour les utilisateurs Deuxfleurs) | | `imap` | `A` | défini par D53 | Addresse IPv4 pour parler au serveur Dovecot (pour les utilisateurs Deuxfleurs) | ### L'enregistrement DKIM -Exemple de valeurs : +Référence : + +**Exemple de valeurs :** ``` default._domainkey.deuxfleurs.fr. 10800 IN TXT "v=DKIM1; h=sha256; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtdZp4qrgZR+6R7HeAkuLGJ/3L/6Ungvf5zwrMq6T8Tu931j2G4lYuPtsxyn9fZkT4y7DlX0waktLDB" "OCwf7X78nLEWjAFWiJTeWGRGhRdYRUFpscs9NUN0P+46jKlabibG3XTKd1DeAmywTu6o1oO03yiolrgKD1zgyDRFeUTfSwZIdPrdbcBSA1arda4WFtcBIrSygM9b4jtlqfQwGDrsMLbCBfVHDn4Wfm" "DWyNg0gDAkuLrYClNETk6aqIyj9fC8srKri0Qp3cRagCn+fjBvuxP35qWWJH7Rnnh/tuEDr1ufuNYO2KgJZ7JdMidUotxXE8cfU+OrEWQf4mIYeJ4wIDAQAB" @@ -76,14 +78,45 @@ smtp._domainkey.deuxfleurs.fr. 1800 IN TXT "v=DKIM1; h=sha256; k=rsa; p=MIIBIjAN default._domainkey.adnab.me. 3600 IN TXT "v=DKIM1; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDHd2zQXgGAoFX2CFaRqvWw1oBGhbUIRB5QXPxE9nvWwe/og5LjZBcnKoInPWsKYEz/f5kmpTDq4RZT3PMmjm+u5IuvyQ2LJcdIKSW6t8KWa7yztk2D87f3Lono6WJwvY8RHdGPqKS5RXfEdQFriXiSCAO5ZSQrNXQ5yiQ9T1ptGwIDAQAB; t=s" ``` -Structure : +**Structure :** - Le nom de domaine est composé d'un selecteur (souvent `default`, on a ici aussi `smtp`) qui permet de distinguer différentes clefs pour signer les messages. - Il est formé de la manière suivante: `.\_domainkey.` + Il est formé de la manière suivante: `._domainkey.` +- La valeur est composé de plusieurs champs entre guillemets séparés par des `;`, le champ `v` peut contenir la version de DKIM utilisée (ici `v=DKIM1`) +- Le champ `p` contient la clef publique +- Les autres champs sont optionels + +**Application à la vérification d'une signature (exemple) :** + +Prenons la signature suivante : + +``` +DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=deuxfleurs.fr; s=smtp; + t=1679050854; bh=AkDk3Tm0bnC7b6dvTjRXJbThLE6h/IStsBGIYGa+q7c=; + h=Date:To:From:Subject:From; + b=Qll5ASi9DmD2rw9LK1vJOahE77Pd/HNDbmrkrOCt4S8Nu42WtJXXOtiwo9J3KGPzR + zA2Cw5oCUB0HW5ere8RkINsUj9X/nxOovxFaJw4LSrgEYxQh7unaGBs6Ecw6k2Aqc/ + oMhNE2OVCSlLkJVUQbgzwBUcZuwndlki6yYoJXkSPMuZ4tFbhgjSaxneRgUvPocYw3 + Vqc/yMEAbofrlaEf6nSNQZL+LSE4IEBeudsv3JodMn12OYAijhO0rrHHsinK9UkM3M + PEEISyatG6RzE6veh4VVv3PTyJMYouQI7fKNooLuDmlGsdSTV9HRo4UvQeOQT1SL/7 + KvgJtR0Hqz3mQ== +``` + +Cette signature contient les champs suivants : + +- `v` (obligatoire) indique la version, doit toujours être à `1` +- `a` (obligatoire) indique l'algorithme de signature, généralement `rsa-sha256` +- `d` (obligatoire) indique le domaine pour lequel la signature est produite +- `s` (obligatoire) indique le sélecteur de la clef DKIM utilisée (ici `smtp` pour utiliser la clef `smtp._domainkey.deuxfleurs.fr`) +- `h` (obligatoire) indique la liste des en-têtes signés +- `bh` (obligatoire) donne le hash du contenu du message +- `b` (obligatoire) donne la signature à proprement parler, qui signe les en-têtes `h` et le hash du contenu `bh` +- `t` (recomandé) donne le timestamp de la signature, i.e. sa date et son heure +- `c` est un paramètre additionnel de la méthode de calcul de la signature ### L'enregistrement SPF -Exemple de valeurs : +**Exemple de valeurs :** ``` deuxfleurs.fr. 300 IN TXT "v=spf1 mx:out.deuxfleurs.fr ip4:82.66.80.201 -all" -- cgit v1.2.3 From a6916cf66e7ef6026e68193236a4cb9c1322ee39 Mon Sep 17 00:00:00 2001 From: Alex Auvolat Date: Fri, 17 Mar 2023 12:56:21 +0100 Subject: =?UTF-8?q?=C3=A9criture=20sur=20l'enregistrement=20SPF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- content/operations/email.md | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) (limited to 'content/operations') diff --git a/content/operations/email.md b/content/operations/email.md index 89378cf..6299d97 100644 --- a/content/operations/email.md +++ b/content/operations/email.md @@ -66,6 +66,10 @@ _dmarc TXT "v=DMARC1; p=reject; sp=reject; adkim=s; fo=1; aspf=s; ruf=mailto:p ### L'enregistrement DKIM +Le mécanisme DKIM permet au serveur d'ajouter une signature sur les messages qui sortent de Deuxfleurs, pour que les destinataires puissent en attester la validité. +Il s'agit d'une signature RSA basée sur une paire de clefs privée/publique. La clef publique est donée dans l'enregistrement DNS DKIM, et la clef privée est connue +uniquement du serveur Postfix. La signature de chaque message est ajoutée dans un en-tête spécifique. + Référence : **Exemple de valeurs :** @@ -116,13 +120,43 @@ Cette signature contient les champs suivants : ### L'enregistrement SPF +L'enregistrement SPF sert à aider le serveur de destination à déterminer si le message reçu est légitime ou non, en vérifiant des contraintes sur l'addresse IP par laquelle il a été reçu. +Normalement, c'est l'addresse IP du serveur SMTP de Deuxfleurs, donc on sait qu'on doit rejeter tous les messages venant d'autres addresses. + +Références : + **Exemple de valeurs :** ``` deuxfleurs.fr. 300 IN TXT "v=spf1 mx:out.deuxfleurs.fr ip4:82.66.80.201 -all" adnab.me. 3600 IN TXT "v=spf1 mx mx:adnab.me include:mx.ovh.com -all" +ietf.org. 1794 IN TXT "v=spf1 ip4:50.223.129.192/26 ip6:2001:559:c4c7::/48 a:ietf.org mx:mail.ietf.org ip4:192.95.54.32/27 ip6:2607:5300:60:9ccf::/64 ip4:158.69.166.0/27 ip6:2607:5300:203:1b26::/64 ip4:4.31.198.32/27 ip6:2001:1900:3001:11::/64 include:_spf.google.com ~all" + ``` +**Structure :** + +L'enregistrement commence par `v=spf1`, puis contient un ensemble de directives formées de la manière suivante: + +- Un préfixe pouvant être `+` (résultat favorable), `?` (résultat neutre/aucune règle), `~` (entre le neutre et l'échec, utile pour déboguer), `-` (échec/défavorable). Le préfixe peut être omis, ce qui est interprété comme le préfixe `+`. +- Une paire type/valeur, avec les types suivants: + - `mx` : utiliser un enregistrement DNS de type MX. L'enregistrement `MX` donne un ou plusieurs noms d'hôtes, qui sont eux-même des noms DNS. Ces noms sont ensuite résolus en `A` ou `AAAA` pour trouver les addresses correspondantes. Des `CNAME` peuvent être présents, ce qui donnerait au plus long la chaîne de résolution suivante : `MX -> CNAME -> ... -> CNAME -> A/AAAA`. + - `ip4` : contient directement une plage d'addresses IPv4 + - `ip6` : contient directement une plage d'addresses IPv6 + - `a` : contient un nom d'hôte à résoudre en `A` ou `AAAA` (pouvant utiliser des `CNAME`) + - `include` : contient un nom de domaine ayant une autre règle SPF à inclure + - `ptr` : désuet +- Ou bien le mot `all`, qui correspond à tous les expéditeurs dont l'addresse ne correspond pas aux autres règles + +Par exemple, dans les exemples ci-dessous, voici comment interpréter les différentes règles: + +- `mx:out.deuxfleurs.fr` : accepter le message si l'IP de l'expéditeur est trouvable en suivant les enregistrements `MX` associés à `out.deuxfleurs.fr`. +- `ip4:82.66.80.201` : accepter le message si l'IP de l'expéditeur est `82.66.80.201` +- `include:mx.ovh.com` : accepter le message si il serait accepté par la règle du domaine `mx.ovh.com` (consultable en faisant `dig TXT mx.ovh.com`) +- `a:ietf.org` : accepter le message si il vient de l'addresse IP de `ietf.org` (consultable en faisant `dig A ietf.org`) +- `-all` : rejeter strictement tous les messages venant d'une autre addresse IP + + ### L'enregistrement DMARC -- cgit v1.2.3 From c76d05c09c1959e07b77a13f50e04f8e853cb300 Mon Sep 17 00:00:00 2001 From: Alex Auvolat Date: Fri, 17 Mar 2023 13:16:23 +0100 Subject: =?UTF-8?q?=C3=A9criture=20d'infos=20sur=20les=20e-mails?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- content/operations/email.md | 47 +++++++++++++++++++++++++++++++++++++++------ 1 file changed, 41 insertions(+), 6 deletions(-) (limited to 'content/operations') diff --git a/content/operations/email.md b/content/operations/email.md index 6299d97..32d5105 100644 --- a/content/operations/email.md +++ b/content/operations/email.md @@ -63,8 +63,9 @@ _dmarc TXT "v=DMARC1; p=reject; sp=reject; adkim=s; fo=1; aspf=s; ruf=mailto:p | `email-in` | `A` | défini par D53 | Addresse IPv4 pour parler au serveur Postfix (pour l'enregistrement MX) | | `smtp` | `A` | défini par D53 | Addresse IPv4 pour parler au serveur Postfix (pour les utilisateurs Deuxfleurs) | | `imap` | `A` | défini par D53 | Addresse IPv4 pour parler au serveur Dovecot (pour les utilisateurs Deuxfleurs) | +| `201.80.66.82.in-addr.arpa.` | `PTR` | `orion.site.deuxfleurs.fr.` | Reverse DNS indiquant le nom de domainecorrespondant à l'IP du serveur Postfix | -### L'enregistrement DKIM +## DKIM Le mécanisme DKIM permet au serveur d'ajouter une signature sur les messages qui sortent de Deuxfleurs, pour que les destinataires puissent en attester la validité. Il s'agit d'une signature RSA basée sur une paire de clefs privée/publique. La clef publique est donée dans l'enregistrement DNS DKIM, et la clef privée est connue @@ -72,7 +73,7 @@ uniquement du serveur Postfix. La signature de chaque message est ajoutée dans Référence : -**Exemple de valeurs :** +**Exemple d'enregistrements DNS :** ``` default._domainkey.deuxfleurs.fr. 10800 IN TXT "v=DKIM1; h=sha256; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtdZp4qrgZR+6R7HeAkuLGJ/3L/6Ungvf5zwrMq6T8Tu931j2G4lYuPtsxyn9fZkT4y7DlX0waktLDB" "OCwf7X78nLEWjAFWiJTeWGRGhRdYRUFpscs9NUN0P+46jKlabibG3XTKd1DeAmywTu6o1oO03yiolrgKD1zgyDRFeUTfSwZIdPrdbcBSA1arda4WFtcBIrSygM9b4jtlqfQwGDrsMLbCBfVHDn4Wfm" "DWyNg0gDAkuLrYClNETk6aqIyj9fC8srKri0Qp3cRagCn+fjBvuxP35qWWJH7Rnnh/tuEDr1ufuNYO2KgJZ7JdMidUotxXE8cfU+OrEWQf4mIYeJ4wIDAQAB" @@ -118,14 +119,14 @@ Cette signature contient les champs suivants : - `t` (recomandé) donne le timestamp de la signature, i.e. sa date et son heure - `c` est un paramètre additionnel de la méthode de calcul de la signature -### L'enregistrement SPF +## SPF L'enregistrement SPF sert à aider le serveur de destination à déterminer si le message reçu est légitime ou non, en vérifiant des contraintes sur l'addresse IP par laquelle il a été reçu. Normalement, c'est l'addresse IP du serveur SMTP de Deuxfleurs, donc on sait qu'on doit rejeter tous les messages venant d'autres addresses. Références : -**Exemple de valeurs :** +**Exemple d'enregistrements DNS :** ``` deuxfleurs.fr. 300 IN TXT "v=spf1 mx:out.deuxfleurs.fr ip4:82.66.80.201 -all" @@ -157,12 +158,46 @@ Par exemple, dans les exemples ci-dessous, voici comment interpréter les diffé - `-all` : rejeter strictement tous les messages venant d'une autre addresse IP -### L'enregistrement DMARC +## DMARC +DMARC est un mécanisme qui permet de mieux contrôler la réaction des serveurs de destination en fonction des tests DKIM et SPF. +Par exemple, on peut préciser que tous les messages sont authentifiés par DKIM et SPF, et si un de ces tests échoue, le message doit nécessairement être rejeté. +On peut aussi demander à recevoir des rapports en cas d'échec. -Exemple de valeurs : +Référence : + +**Exemple d'enregistrements DNS :** ``` _dmarc.deuxfleurs.fr. 300 IN TXT "v=DMARC1; p=reject; sp=reject; adkim=s; fo=1; aspf=s; ruf=mailto:prod-sysadmin@deuxfleurs.fr; rua=mailto:prod-sysadmin@deuxfleurs.fr; rf=afrf; pct=100; ri=86400" _dmarc.adnab.me. 3600 IN TXT "v=DMARC1; p=reject; sp=reject; adkim=s; aspf=s; rua=mailto:postmaster@adnab.me!10m; ruf=mailto:postmaster@adnab.me!10m; rf=afrf; pct=100; ri=86400" ``` + +L'enregistrement peut contenir les champs suivants: + +- `v=DMARC1` indique la version de DMARC utilisée +- `p` : procédure en cas d'échec avec le domaine principal (`none/quarantaine/reject`) +- `sp` : comme `p` mais s'applique aux sous-domaines +- `adkim` : indique si on doit appliquer la règle DKIM de manière stricte (`s`, le nom de domaine doit correspondre exactement) ou relaxée (`r`, des variations sur le nom de domaine sont permises) +- `aspf` : indique si on doit appliquer la règle SPF de manière stricte (`s`) ou relaxée (`r`) +- `ruf` : addresse mail à laquelle envoyer un rapport d'échec détaillé à chaque échec de validation +- `fo` : condition pour l'envoi d'un rapport d'échec détaillé (1 = si soit DKIM soit SPF a échoué) +- `rua` : addresse mail à laquelle envoyer un rapport d'échec aggrégé périodiquement +- `ri` : intervalle en secondes entre l'envoi des rapports aggrégés (86400 = 24h) +- `rf` : format des rapports (`afrf` est la seule valeur officiellement supportée) +- `pct` : proportion de messages à rejeter en cas d'échec + +## Reverse DNS + +**Exemple d'enregistrements reverse DNS :** + +``` +201.80.66.82.in-addr.arpa. 86179 IN PTR orion.site.deuxfleurs.fr. +206.118.187.37.in-addr.arpa. 86400 IN PTR shiki.adnab.me. +``` + +L'enregistrement reverse DNS peut être utilisé par le serveur de destination +pour connaître le nom d'hôte correspondant à l'addresse IP du serveur qui a +envoyé le mail. Cet enregistrement doit idéalement correspondre à un nom de +domaine qui lui-même résoud à nouveau vers la même addresse IP. + -- cgit v1.2.3 From 22d1d1ea0d1e2f9a5493e984879a4e3be7944594 Mon Sep 17 00:00:00 2001 From: Alex Auvolat Date: Fri, 17 Mar 2023 13:57:30 +0100 Subject: Nouvelles instructions pour les domaines email --- content/operations/email.md | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'content/operations') diff --git a/content/operations/email.md b/content/operations/email.md index 32d5105..03ed149 100644 --- a/content/operations/email.md +++ b/content/operations/email.md @@ -18,25 +18,25 @@ Deuxfleurs peut héberger vos e-mails, même s'ils ne finissent pas en `@deuxfle 1. L'entrée MX pour recevoir les emails ```bind -@ MX 10 email-in.deuxfleurs.fr. +@ MX 10 smtp.deuxfleurs.fr. ``` 1. L'entrée SPF pour autoriser notre IP à délivrer des emails en votre nom : ```bind -@ TXT "v=spf1 mx:out.deuxfleurs.fr -all" +@ TXT "v=spf1 include:deuxfleurs.fr -all" ``` 1. L'entrée DKIM pour autoriser notre postfix+opendkim à délivrer des emails en votre nom : ``` -smtp._domainkey TXT "v=DKIM1; h=sha256; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtdZp4qrgZR+6R7HeAkuLGJ/3L/6Ungvf5zwrMq6T8Tu931j2G4lYuPtsxyn9fZkT4y7DlX0waktLDBOCwf7X78nLEWjAFWiJTeWGRGhRdYRUFpscs9NUN0P+46jKlabibG3XTKd1DeAmywTu6o1oO03yiolrgKD1zgyDRFeUTfSwZIdPrdbcBSA1arda4WFtcBIrSygM9b4jtlqfQwGDrsMLbCBfVHDn4WfmDWyNg0gDAkuLrYClNETk6aqIyj9fC8srKri0Qp3cRagCn+fjBvuxP35qWWJH7Rnnh/tuEDr1ufuNYO2KgJZ7JdMidUotxXE8cfU+OrEWQf4mIYeJ4wIDAQAB" +smtp._domainkey CNAME smtp._domainkey.deuxfleurs.fr. ``` 1. L'entrée DMARC pour indiquer le comportement à adopter si les contraintes précédentes ne sont pas satisfaites : ``` -_dmarc TXT "v=DMARC1; p=reject; sp=reject; adkim=s; fo=1; aspf=s; ruf=mailto:prod-sysadmin@deuxfleurs.fr; rf=afrf; pct=100; ri=86400" +_dmarc CNAME _dmarc.deuxfleurs.fr. ``` 1. C'est tout ! Vous devrez probablement attendre 24/48h que les changements se propagent. @@ -56,6 +56,7 @@ _dmarc TXT "v=DMARC1; p=reject; sp=reject; adkim=s; fo=1; aspf=s; ruf=mailto:p | nom | type | valeur | signification | | --- | ---- | ------ | ------------- | | `@` | `MX` | `12 email-in.deuxfleurs.fr` | Serveur que chercheront à joindre les gens qui veulent envoyer un courrier à une addresse `@deuxfleurs.fr` | +| `out | `MX` | `12 orion[-v6].deuxfleurs.fr` | Addresses IP pouvant envoyer des messages pour SPF (voir ci-dessous) | | `default._domainkey` | `TXT` | `v=DKIM1; h=sha256; k=rsa; p=` | Enregistrement DKIM (voir ci-dessous) | | `smtp._domainkey` | `TXT` | `v=DKIM1; h=sha256; k=rsa; p=` | Enregistrement DKIM (voir ci-dessous) | | `@` | `TXT` | `"v=spf1 mx:out.deuxfleurs.fr ip4: [...] -all" | Enregistrement SPF (voir ci-dessous) | @@ -119,6 +120,8 @@ Cette signature contient les champs suivants : - `t` (recomandé) donne le timestamp de la signature, i.e. sa date et son heure - `c` est un paramètre additionnel de la méthode de calcul de la signature +**Chez Deuxfleurs:** L'en-tête de signature est rajouté par notre serveur Postfix. La clef privée est stockée dans Consul, et est injéctée dans le conteneur Postfix au lancement. Les enregistrements DNS sont installés manuellement. + ## SPF L'enregistrement SPF sert à aider le serveur de destination à déterminer si le message reçu est légitime ou non, en vérifiant des contraintes sur l'addresse IP par laquelle il a été reçu. @@ -158,6 +161,8 @@ Par exemple, dans les exemples ci-dessous, voici comment interpréter les diffé - `-all` : rejeter strictement tous les messages venant d'une autre addresse IP +**Chez Deuxfleurs:** L'enregistrement SPF, installé manuellement, contient `mx:out.deuxfleurs.fr`, ce qui signifie que les addresses IP sont celles présentes dans l'enregistrement `MX` pour `out.deuxfleurs.fr`. Actuellement, les valeurs sont `orion.site.deuxfleurs.fr` et `orion-v6.site.deuxfleurs.fr`. Le premier contient l'IPv4 (mise manuellement) et une IPv6 (mise automatiquement par D53, c'est celle de la machine contenant Tricot). Le second contient toutes les IPv6 possibles pour Postfix (celui-ci se ballade de machine en machine). + ## DMARC DMARC est un mécanisme qui permet de mieux contrôler la réaction des serveurs de destination en fonction des tests DKIM et SPF. -- cgit v1.2.3 From 7694fd08ab2e5e5041e3592b5cfa85bc4c933423 Mon Sep 17 00:00:00 2001 From: Alex Auvolat Date: Fri, 17 Mar 2023 15:09:14 +0100 Subject: =?UTF-8?q?Mise=20=C3=A0=20jour=20de=20la=20page=20sur=20les=20ema?= =?UTF-8?q?ils?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- content/operations/email.md | 58 ++++++++++++++++++++++++++++++--------------- 1 file changed, 39 insertions(+), 19 deletions(-) (limited to 'content/operations') diff --git a/content/operations/email.md b/content/operations/email.md index 03ed149..43e5cef 100644 --- a/content/operations/email.md +++ b/content/operations/email.md @@ -55,16 +55,15 @@ _dmarc CNAME _dmarc.deuxfleurs.fr. | nom | type | valeur | signification | | --- | ---- | ------ | ------------- | -| `@` | `MX` | `12 email-in.deuxfleurs.fr` | Serveur que chercheront à joindre les gens qui veulent envoyer un courrier à une addresse `@deuxfleurs.fr` | -| `out | `MX` | `12 orion[-v6].deuxfleurs.fr` | Addresses IP pouvant envoyer des messages pour SPF (voir ci-dessous) | -| `default._domainkey` | `TXT` | `v=DKIM1; h=sha256; k=rsa; p=` | Enregistrement DKIM (voir ci-dessous) | -| `smtp._domainkey` | `TXT` | `v=DKIM1; h=sha256; k=rsa; p=` | Enregistrement DKIM (voir ci-dessous) | -| `@` | `TXT` | `"v=spf1 mx:out.deuxfleurs.fr ip4: [...] -all" | Enregistrement SPF (voir ci-dessous) | -| `_dmarc` | `TXT` | `"v=DMARC1; [...]` | Enregistrement DMARC (voir ci-dessous) | -| `email-in` | `A` | défini par D53 | Addresse IPv4 pour parler au serveur Postfix (pour l'enregistrement MX) | -| `smtp` | `A` | défini par D53 | Addresse IPv4 pour parler au serveur Postfix (pour les utilisateurs Deuxfleurs) | -| `imap` | `A` | défini par D53 | Addresse IPv4 pour parler au serveur Dovecot (pour les utilisateurs Deuxfleurs) | -| `201.80.66.82.in-addr.arpa.` | `PTR` | `orion.site.deuxfleurs.fr.` | Reverse DNS indiquant le nom de domainecorrespondant à l'IP du serveur Postfix | +| `@` | `MX` | `12 smtp.deuxfleurs.fr` | Serveur que chercheront à joindre les gens qui veulent envoyer un courrier à une addresse `@deuxfleurs.fr` | +| `smtp._domainkey` | `TXT` | `v=DKIM1; p=` | Enregistrement DKIM (voir ci-dessous) | +| `default._domainkey` | `TXT` | `v=DKIM1; p=` | Ancien enregistrement DKIM (voir ci-dessous) | +| `@` | `TXT` | `v=spf1 [...] -all` | Enregistrement SPF (voir ci-dessous) | +| `_dmarc` | `TXT` | `v=DMARC1; [...]` | Enregistrement DMARC (voir ci-dessous) | +| `smtp` | `A` | défini par D53 | Addresse IPv4 pour parler au serveur Postfix | +| `imap` | `A` | défini par D53 | Addresse IPv4 pour parler au serveur Dovecot | +| `201.80.66.82.in-addr.arpa.` | `PTR` | `orion.site.deuxfleurs.fr.` | Reverse DNS indiquant le nom de domaine correspondant à l'IP du serveur Postfix | +| `orion.site` | `A` | `82.66.80.201` | Reverse DNS indiquant le nom de domaine correspondant à l'IP du serveur Postfix | ## DKIM @@ -120,7 +119,12 @@ Cette signature contient les champs suivants : - `t` (recomandé) donne le timestamp de la signature, i.e. sa date et son heure - `c` est un paramètre additionnel de la méthode de calcul de la signature -**Chez Deuxfleurs:** L'en-tête de signature est rajouté par notre serveur Postfix. La clef privée est stockée dans Consul, et est injéctée dans le conteneur Postfix au lancement. Les enregistrements DNS sont installés manuellement. +**Chez Deuxfleurs:** + +- L'en-tête de signature est rajouté par notre serveur Postfix. +- La clef privée est stockée dans Consul, et est injectée dans le conteneur Postfix au lancement. +- Les enregistrements DNS pour DKIM sont installés manuellement. +- Pour tous les autres domaines dont le courrier est traîté par les serveurs Deuxfleurs, on utilise un enregistrement DKIM en CNAME vers `smtp._domainkey.deuxfleurs.fr` pour que la gestion des règles soit centralisée via l'enregistrement défini sur les DNS Deuxfleurs. ## SPF @@ -132,7 +136,7 @@ Références : **Exemple d'enregistrements DNS :** ``` -deuxfleurs.fr. 300 IN TXT "v=spf1 mx:out.deuxfleurs.fr ip4:82.66.80.201 -all" +deuxfleurs.fr. 300 IN TXT "v=spf1 mx:deuxfleurs.fr a:orion.site.deuxfleurs.fr ip4:82.66.80.201 ip6:2a01:e0a:28f:5e60::/64 -all" adnab.me. 3600 IN TXT "v=spf1 mx mx:adnab.me include:mx.ovh.com -all" ietf.org. 1794 IN TXT "v=spf1 ip4:50.223.129.192/26 ip6:2001:559:c4c7::/48 a:ietf.org mx:mail.ietf.org ip4:192.95.54.32/27 ip6:2607:5300:60:9ccf::/64 ip4:158.69.166.0/27 ip6:2607:5300:203:1b26::/64 ip4:4.31.198.32/27 ip6:2001:1900:3001:11::/64 include:_spf.google.com ~all" @@ -144,7 +148,7 @@ L'enregistrement commence par `v=spf1`, puis contient un ensemble de directives - Un préfixe pouvant être `+` (résultat favorable), `?` (résultat neutre/aucune règle), `~` (entre le neutre et l'échec, utile pour déboguer), `-` (échec/défavorable). Le préfixe peut être omis, ce qui est interprété comme le préfixe `+`. - Une paire type/valeur, avec les types suivants: - - `mx` : utiliser un enregistrement DNS de type MX. L'enregistrement `MX` donne un ou plusieurs noms d'hôtes, qui sont eux-même des noms DNS. Ces noms sont ensuite résolus en `A` ou `AAAA` pour trouver les addresses correspondantes. Des `CNAME` peuvent être présents, ce qui donnerait au plus long la chaîne de résolution suivante : `MX -> CNAME -> ... -> CNAME -> A/AAAA`. + - `mx` : utiliser un enregistrement DNS de type MX. L'enregistrement `MX` donne un ou plusieurs noms d'hôtes, qui sont eux-même des noms DNS. Ces noms sont ensuite résolus en `A` ou `AAAA` pour trouver les addresses correspondantes. Attention, un enregistrement `MX` n'est pas sensé pointer sur un `CNAME`, il doit pointer directement sur des enregistrements `A` et `AAAA` ! - `ip4` : contient directement une plage d'addresses IPv4 - `ip6` : contient directement une plage d'addresses IPv6 - `a` : contient un nom d'hôte à résoudre en `A` ou `AAAA` (pouvant utiliser des `CNAME`) @@ -154,14 +158,21 @@ L'enregistrement commence par `v=spf1`, puis contient un ensemble de directives Par exemple, dans les exemples ci-dessous, voici comment interpréter les différentes règles: -- `mx:out.deuxfleurs.fr` : accepter le message si l'IP de l'expéditeur est trouvable en suivant les enregistrements `MX` associés à `out.deuxfleurs.fr`. +- `mx:deuxfleurs.fr` : accepter le message si l'IP de l'expéditeur est trouvable en suivant les enregistrements `MX` associés à `deuxfleurs.fr`. - `ip4:82.66.80.201` : accepter le message si l'IP de l'expéditeur est `82.66.80.201` - `include:mx.ovh.com` : accepter le message si il serait accepté par la règle du domaine `mx.ovh.com` (consultable en faisant `dig TXT mx.ovh.com`) - `a:ietf.org` : accepter le message si il vient de l'addresse IP de `ietf.org` (consultable en faisant `dig A ietf.org`) - `-all` : rejeter strictement tous les messages venant d'une autre addresse IP -**Chez Deuxfleurs:** L'enregistrement SPF, installé manuellement, contient `mx:out.deuxfleurs.fr`, ce qui signifie que les addresses IP sont celles présentes dans l'enregistrement `MX` pour `out.deuxfleurs.fr`. Actuellement, les valeurs sont `orion.site.deuxfleurs.fr` et `orion-v6.site.deuxfleurs.fr`. Le premier contient l'IPv4 (mise manuellement) et une IPv6 (mise automatiquement par D53, c'est celle de la machine contenant Tricot). Le second contient toutes les IPv6 possibles pour Postfix (celui-ci se ballade de machine en machine). +**Chez Deuxfleurs :** + +- L'enregistrement SPF, installé manuellement, contient `mx:deuxfleurs.fr`, ce qui signifie que les addresses IP sont celles présentes dans l'enregistrement `MX` pour `deuxfleurs.fr`. +- Cet enregistrement pointe sur le serveur `smtp.deuxfleurs.fr`, dont l'addresse est mise à jour automatiquement dans le DNS par D53 pour pointer vers l'IPv4 de la machine sur laquelle tourne Postfix. +- L'enregistrement SPF contient également `a:orion.site.deuxfleurs.fr`, qui contient également l'IPv4 de cette machine ; on garde cette règle en second recours au cas où il y aurait un problème avec la précédente. +- L'enregistrement SPF contient également l'addresse IPv4 et la plage d'addresses IPv6 de la box à Orion (site où le serveur SMTP est actuellement déployé), pour en dernier recours éviter de rejeter des mails en cas de soucis avec les règles précédentes. +- **L'enregistrement SPF doit être mis à jour manuellement en cas de reconfiguration du serveur SMTP, en particulier si celui-ci change de site ou si les addresses IP changent.** +- Pour tous les autres domaines dont le courrier est traîté par les serveurs Deuxfleurs, on utilise un enregistrement SPF `include:deuxfleurs.fr` pour que la gestion des règles soit centralisée via l'enregistrement défini sur les DNS Deuxfleurs. ## DMARC @@ -192,8 +203,21 @@ L'enregistrement peut contenir les champs suivants: - `rf` : format des rapports (`afrf` est la seule valeur officiellement supportée) - `pct` : proportion de messages à rejeter en cas d'échec +**Chez Deuxfleurs :** + +- L'enregistrement DMARC est configuré pour rejeter de manière strict tout message ne passant pas la vérification SPF ou DKIM. +- Les rapports d'erreur doivent être envoyés à l'addresse `prod-sysadmin@deuxfleurs.fr` qui est consultés par les administrateurs systèmes de Deuxfleurs. +- Pour tous les autres domaines dont le courrier est traîté par les serveurs Deuxfleurs, on utilise un enregistrement DMARC en CNAME vers `_dmarc.deuxfleurs.fr` pour que la gestion des règles soit centralisée via l'enregistrement défini sur les DNS Deuxfleurs. + ## Reverse DNS +L'enregistrement reverse DNS peut être utilisé par le serveur de destination +pour connaître le nom d'hôte correspondant à l'addresse IP du serveur qui a +envoyé le mail. Cet enregistrement doit idéalement correspondre à un nom de +domaine qui lui-même résoud à nouveau vers la même addresse IP. +L'application de cette règle de filtrage est à la discrétion des différents hébergeurs +mail, elle ne rentre pas dans le cadre défini par DMARC. + **Exemple d'enregistrements reverse DNS :** ``` @@ -201,8 +225,4 @@ L'enregistrement peut contenir les champs suivants: 206.118.187.37.in-addr.arpa. 86400 IN PTR shiki.adnab.me. ``` -L'enregistrement reverse DNS peut être utilisé par le serveur de destination -pour connaître le nom d'hôte correspondant à l'addresse IP du serveur qui a -envoyé le mail. Cet enregistrement doit idéalement correspondre à un nom de -domaine qui lui-même résoud à nouveau vers la même addresse IP. -- cgit v1.2.3 From 111c54be756f67b02707afa8346beaa92f9ec2f5 Mon Sep 17 00:00:00 2001 From: Alex Auvolat Date: Fri, 17 Mar 2023 15:13:33 +0100 Subject: formattage --- content/operations/email.md | 41 ++++++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 19 deletions(-) (limited to 'content/operations') diff --git a/content/operations/email.md b/content/operations/email.md index 43e5cef..937bfad 100644 --- a/content/operations/email.md +++ b/content/operations/email.md @@ -13,33 +13,36 @@ extra: Deuxfleurs peut héberger vos e-mails, même s'ils ne finissent pas en `@deuxfleurs.fr` ! Voilà comment faire. 1. Communiquez lui votre nom de domaine pour qu'il l'ajoute dans `ou=domains,ou=groups,dc=deuxfleurs,dc=fr` -1. Communiquez lui l'adresse email que vous souhaitez pour qu'il change l'entrée `mail` dans votre profil utilisateur -1. Vous devez ensuite rajouter les entrées pour votre nom de domaine en éditant votre zone : -1. L'entrée MX pour recevoir les emails -```bind -@ MX 10 smtp.deuxfleurs.fr. -``` +2. Communiquez lui l'adresse email que vous souhaitez pour qu'il change l'entrée `mail` dans votre profil utilisateur -1. L'entrée SPF pour autoriser notre IP à délivrer des emails en votre nom : +3. Vous devez ensuite rajouter les entrées pour votre nom de domaine en éditant votre zone : -```bind -@ TXT "v=spf1 include:deuxfleurs.fr -all" -``` + 1. L'entrée MX pour recevoir les emails -1. L'entrée DKIM pour autoriser notre postfix+opendkim à délivrer des emails en votre nom : + ``` + @ MX 10 smtp.deuxfleurs.fr. + ``` -``` -smtp._domainkey CNAME smtp._domainkey.deuxfleurs.fr. -``` + 2. L'entrée SPF pour autoriser notre IP à délivrer des emails en votre nom : -1. L'entrée DMARC pour indiquer le comportement à adopter si les contraintes précédentes ne sont pas satisfaites : + ``` + @ TXT "v=spf1 include:deuxfleurs.fr -all" + ``` -``` -_dmarc CNAME _dmarc.deuxfleurs.fr. -``` + 3. L'entrée DKIM pour autoriser notre postfix+opendkim à délivrer des emails en votre nom : + + ``` + smtp._domainkey CNAME smtp._domainkey.deuxfleurs.fr. + ``` + + 4. L'entrée DMARC pour indiquer le comportement à adopter si les contraintes précédentes ne sont pas satisfaites : + + ``` + _dmarc CNAME _dmarc.deuxfleurs.fr. + ``` -1. C'est tout ! Vous devrez probablement attendre 24/48h que les changements se propagent. +4. C'est tout ! Vous devrez probablement attendre 24/48h que les changements se propagent. -- cgit v1.2.3 From 227eeeaf363c4b0e6317e59ea02d7e216849cd7f Mon Sep 17 00:00:00 2001 From: Alex Auvolat Date: Fri, 17 Mar 2023 15:24:54 +0100 Subject: formattage --- content/operations/email.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'content/operations') diff --git a/content/operations/email.md b/content/operations/email.md index 937bfad..32a44a6 100644 --- a/content/operations/email.md +++ b/content/operations/email.md @@ -79,17 +79,17 @@ Référence : ._domainkey.` + Il est formé de la manière suivante: `._domainkey.` - La valeur est composé de plusieurs champs entre guillemets séparés par des `;`, le champ `v` peut contenir la version de DKIM utilisée (ici `v=DKIM1`) - Le champ `p` contient la clef publique - Les autres champs sont optionels @@ -140,8 +140,8 @@ Références : ``` deuxfleurs.fr. 300 IN TXT "v=spf1 mx:deuxfleurs.fr a:orion.site.deuxfleurs.fr ip4:82.66.80.201 ip6:2a01:e0a:28f:5e60::/64 -all" -adnab.me. 3600 IN TXT "v=spf1 mx mx:adnab.me include:mx.ovh.com -all" -ietf.org. 1794 IN TXT "v=spf1 ip4:50.223.129.192/26 ip6:2001:559:c4c7::/48 a:ietf.org mx:mail.ietf.org ip4:192.95.54.32/27 ip6:2607:5300:60:9ccf::/64 ip4:158.69.166.0/27 ip6:2607:5300:203:1b26::/64 ip4:4.31.198.32/27 ip6:2001:1900:3001:11::/64 include:_spf.google.com ~all" +adnab.me. 3600 IN TXT "v=spf1 mx mx:adnab.me include:mx.ovh.com -all" +ietf.org. 1794 IN TXT "v=spf1 ip4:50.223.129.192/26 ip6:2001:559:c4c7::/48 a:ietf.org mx:mail.ietf.org ip4:192.95.54.32/27 ip6:2607:5300:60:9ccf::/64 ip4:158.69.166.0/27 ip6:2607:5300:203:1b26::/64 ip4:4.31.198.32/27 ip6:2001:1900:3001:11::/64 include:_spf.google.com ~all" ``` @@ -159,7 +159,7 @@ L'enregistrement commence par `v=spf1`, puis contient un ensemble de directives - `ptr` : désuet - Ou bien le mot `all`, qui correspond à tous les expéditeurs dont l'addresse ne correspond pas aux autres règles -Par exemple, dans les exemples ci-dessous, voici comment interpréter les différentes règles: +Par exemple, dans les exemples ci-dessus, voici comment interpréter les différentes règles: - `mx:deuxfleurs.fr` : accepter le message si l'IP de l'expéditeur est trouvable en suivant les enregistrements `MX` associés à `deuxfleurs.fr`. - `ip4:82.66.80.201` : accepter le message si l'IP de l'expéditeur est `82.66.80.201` @@ -188,8 +188,8 @@ Référence : **Exemple d'enregistrements DNS :** ``` -_dmarc.deuxfleurs.fr. 300 IN TXT "v=DMARC1; p=reject; sp=reject; adkim=s; fo=1; aspf=s; ruf=mailto:prod-sysadmin@deuxfleurs.fr; rua=mailto:prod-sysadmin@deuxfleurs.fr; rf=afrf; pct=100; ri=86400" -_dmarc.adnab.me. 3600 IN TXT "v=DMARC1; p=reject; sp=reject; adkim=s; aspf=s; rua=mailto:postmaster@adnab.me!10m; ruf=mailto:postmaster@adnab.me!10m; rf=afrf; pct=100; ri=86400" +_dmarc.deuxfleurs.fr. 300 IN TXT "v=DMARC1; p=reject; sp=reject; adkim=s; fo=1; aspf=s; ruf=mailto:prod-sysadmin@deuxfleurs.fr; rua=mailto:prod-sysadmin@deuxfleurs.fr; rf=afrf; pct=100; ri=86400" +_dmarc.adnab.me. 3600 IN TXT "v=DMARC1; p=reject; sp=reject; adkim=s; aspf=s; rua=mailto:postmaster@adnab.me!10m; ruf=mailto:postmaster@adnab.me!10m; rf=afrf; pct=100; ri=86400" ``` L'enregistrement peut contenir les champs suivants: @@ -224,8 +224,8 @@ mail, elle ne rentre pas dans le cadre défini par DMARC. **Exemple d'enregistrements reverse DNS :** ``` -201.80.66.82.in-addr.arpa. 86179 IN PTR orion.site.deuxfleurs.fr. -206.118.187.37.in-addr.arpa. 86400 IN PTR shiki.adnab.me. +201.80.66.82.in-addr.arpa. 86179 IN PTR orion.site.deuxfleurs.fr. +206.118.187.37.in-addr.arpa. 86400 IN PTR shiki.adnab.me. ``` -- cgit v1.2.3 From 78e7d973ee2dd0d019f1121a5dfb1b70c2db39d7 Mon Sep 17 00:00:00 2001 From: Alex Auvolat Date: Fri, 17 Mar 2023 15:28:59 +0100 Subject: =?UTF-8?q?pr=C3=A9cisions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- content/operations/email.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'content/operations') diff --git a/content/operations/email.md b/content/operations/email.md index 32a44a6..98766e5 100644 --- a/content/operations/email.md +++ b/content/operations/email.md @@ -171,8 +171,9 @@ Par exemple, dans les exemples ci-dessus, voici comment interpréter les différ **Chez Deuxfleurs :** - L'enregistrement SPF, installé manuellement, contient `mx:deuxfleurs.fr`, ce qui signifie que les addresses IP sont celles présentes dans l'enregistrement `MX` pour `deuxfleurs.fr`. -- Cet enregistrement pointe sur le serveur `smtp.deuxfleurs.fr`, dont l'addresse est mise à jour automatiquement dans le DNS par D53 pour pointer vers l'IPv4 de la machine sur laquelle tourne Postfix. -- L'enregistrement SPF contient également `a:orion.site.deuxfleurs.fr`, qui contient également l'IPv4 de cette machine ; on garde cette règle en second recours au cas où il y aurait un problème avec la précédente. +- Cet enregistrement est fixé manuellement pour pointer sur le serveur `smtp.deuxfleurs.fr`. + L'enregistrement `A` pour `smtp.deuxfleurs.fr` est mis à jour automatiquement par D53 pour pointer vers l'IPv4 de la machine sur laquelle tourne Postfix. +- L'enregistrement SPF contient également `a:orion.site.deuxfleurs.fr`, qui contient également l'IPv4 de cette machine ; on garde cette règle en second recours au cas où il y aurait un problème avec la précédente, pour éviter de rejeter du courrier valide. - L'enregistrement SPF contient également l'addresse IPv4 et la plage d'addresses IPv6 de la box à Orion (site où le serveur SMTP est actuellement déployé), pour en dernier recours éviter de rejeter des mails en cas de soucis avec les règles précédentes. - **L'enregistrement SPF doit être mis à jour manuellement en cas de reconfiguration du serveur SMTP, en particulier si celui-ci change de site ou si les addresses IP changent.** - Pour tous les autres domaines dont le courrier est traîté par les serveurs Deuxfleurs, on utilise un enregistrement SPF `include:deuxfleurs.fr` pour que la gestion des règles soit centralisée via l'enregistrement défini sur les DNS Deuxfleurs. -- cgit v1.2.3 From e45969eb72bac89728a5d13a5cfa6f250cf4ed7e Mon Sep 17 00:00:00 2001 From: Alex Auvolat Date: Fri, 17 Mar 2023 15:29:57 +0100 Subject: =?UTF-8?q?pr=C3=A9cision?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- content/operations/email.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'content/operations') diff --git a/content/operations/email.md b/content/operations/email.md index 98766e5..cf36d62 100644 --- a/content/operations/email.md +++ b/content/operations/email.md @@ -54,7 +54,7 @@ Deuxfleurs peut héberger vos e-mails, même s'ils ne finissent pas en `@deuxfle - IMAP: Dovecot (fixé sur une machine avec un backup) -## Enregistrements DNS +## Enregistrements DNS de la zone `deuxfleurs.fr` | nom | type | valeur | signification | | --- | ---- | ------ | ------------- | -- cgit v1.2.3 From 5a0d1977a68f9b9d686e95ed0fe0d5982c9c3fc7 Mon Sep 17 00:00:00 2001 From: Adrien Date: Tue, 21 Mar 2023 15:20:29 +0100 Subject: =?UTF-8?q?ajout=20=C3=A9tape=20conf=20mail?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- content/operations/email.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'content/operations') diff --git a/content/operations/email.md b/content/operations/email.md index bb87c57..fb26fda 100644 --- a/content/operations/email.md +++ b/content/operations/email.md @@ -11,7 +11,7 @@ extra: Deuxfleurs peut héberger vos e-mails, même s'ils ne finissent pas en `@deuxfleurs.fr` ! Voilà comment faire. -1. Communiquez lui votre nom de domaine pour qu'il l'ajoute dans `ou=domains,ou=groups,dc=deuxfleurs,dc=fr` +1. Communiquez lui votre nom de domaine pour qu'il l'ajoute dans `ou=domains,ou=groups,dc=deuxfleurs,dc=fr` et la [table de signature DKIM](https://git.deuxfleurs.fr/Deuxfleurs/nixcfg/src/branch/main/cluster/prod/app/email/config/dkim/signingtable) 1. Communiquez lui l'adresse email que vous souhaitez pour qu'il change l'entrée `mail` dans votre profil utilisateur 1. Vous devez ensuite rajouter les entrées pour votre nom de domaine en éditant votre zone : 1. L'entrée MX pour recevoir les emails -- cgit v1.2.3