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/infrastructures/services.md | 2 +- 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 ---- 64 files changed, 1873 insertions(+), 1774 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') diff --git a/content/infrastructures/services.md b/content/infrastructures/services.md index 87ce29a..c868ade 100644 --- a/content/infrastructures/services.md +++ b/content/infrastructures/services.md @@ -33,7 +33,7 @@ rôles identifiés : production, développement, expérimentation, etc. | Drone (runner) | développement | Bespin | Worker pour l'intégration continue | | SSH | sauvegarde | Mercure | Target de backups (Consul) | | [Minio](https://s3.deuxfleurs.shirokumo.net) | sauvegarde | Mercure | Target de backups restic | -| [cron rclone](@/operations/sauvegardes/rclone.md) | sauvegarde | Jupiter | Backup régulier du contenu de Garage | +| [cron rclone](@/operations/rclone.md) | sauvegarde | Jupiter | Backup régulier du contenu de Garage | | [staging.deuxfleurs.org](https://staging.deuxfleurs.org) | expérimentation | Neptune, Jupiter | Site statique de test | | Garage ([S3](https://garage.staging.deuxfleurs.org), [K2V](https://k2v.staging.deuxfleurs.org)) | expérimentation | Neptune, Jupiter | Beta-test serveur de stockage de données | | [Guichet](https://guichet.staging.deuxfleurs.org) | expérimentation | Neptune/Jupiter | Beta-test interface de gestion des utilisateurs | 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