« JDB - Migration hébergement 2021 » et « WSL - Installation » : différence entre les pages

De PedroWiki
(Différence entre les pages)
Aller à la navigationAller à la recherche
imported>Jules
 
imported>Jules
 
Ligne 1 : Ligne 1 :
= Introduction =
= Introduction =


Objectif de la migration:
Cet article traite des différentes méthodes disponibles pour l'installation de Windows Subsystem for Linux (WSL) sur un poste Windows (10).
* on reste sur le même provider Cloud.
* on monte 2 nouveaux serveurs en Debian 10.
* on contrôle les déploiements par Terraform.
* on contrôle la gestion fine des serveurs par Ansible.


Ce wiki décrit les installations et configurations faites sur une instance de test (jetable), permettant de valider aussi bien le code Terraform que le code Ansible.
Les guides d'installation Microsoft servent de référence, l'objectif est de mieux identifier les méthodes alternatives.


'''NB:''' cette migration a été faite depuis un poste Windows, mais toutes les commandes dans WSL (git, terraform, ansible) sont également valables si on travaille depuis un poste ou un serveur Linux.
= Tips PowerShell utile =


= Versions =
== Informations du système ==


* OS: Debian 10.9
Pour déterminer les informations de son système (architecture processeur, version de build Windows, etc), vous pouvez procéder de 2 façons:
* Git: 2.20.1
* via les '''paramètres => Système => A propos de'''.
* Terraform: v1.0.5
* via la commande PowerShell suivante: <pre>systeminfo</pre>
* Ansible: 2.7.7
* Python (poste de contrôle): 3.7.3
* Python (node distant): 3.7.3
 
= Liens utiles =
 
* [https://www.scaleway.com/en/docs/storage/object/concepts/ Description des objets Scaleway].
* [https://www.scaleway.com/fr/tarifs/ Pricing des objets Scaleway].
* [https://wiki.debian.org/PHP Les versions de PHP par version d'OS Debian].
* [https://docs.ansible.com/ansible/latest/installation_guide/intro_configuration.html Configuration Ansible].
* Best practices Terraform:
** [https://openupthecloud.com/terraform-best-practices/ 10 bonnes pratiques pour Terraform].
* Best practices Ansible:
** [https://www.ansible.com/hubfs/2018_Content/AA%20BOS%202018%20Slides/Ansible%20Best%20Practices.pdf Best practices officielles].
** [https://serverfault.com/questions/823956/ansible-security-best-practices Autre article sur le sujet].
 
= Journal de bord de la migration =
 
== Préparation du poste ==
 
=== Installation WSL ===
 
La migration s'opère depuis un poste Windows 10.
 
On maximise l'utilisation de WSL pour plus de confort.
 
Cf [https://docs.microsoft.com/fr-fr/windows/wsl/install-win10 la documentation officielle de Microsoft.]
 
Les packages ou applications à installer:
* Windows Terminal.
* WSL Debian.
 
En complément, mais non essentiel pour le projet, activation de WSL2.
 
=== Installation VSCode ===
 
Pour plus de confort, on installe et on utilisera [https://code.visualstudio.com/docs/setup/setup-overview Visual Studio Code].
 
=== Installation Git ===
 
==== Installation ====
 
Dans la distribution WSL Debian:
 
<pre>
sudo apt-get install git
</pre>
 
==== Configuration ====
 
Initialisation de Git en suivant [https://services.renater.fr/sourcesup/git/comment_travailler_avec_git_en_local_sur_son_poste_de_travail ce super tuto Renater]:
 
<pre>
cd /mnt/d/Jules/Tech/Git/
git config --global color.diff auto
git config --global color.status auto
git config --global color.branch auto
git config --global user.email "jules@pedrono.fr"
git config --global user.name "jules"
cd scaleway
git init
</pre>
 
'''NB:''' je n'utilise pour l'instant que le repository local, on ne push pas vers un serveur Gitlab distant ou sur Github.
 
Exclusions de fichier par [https://perhonen.fr/blog/2015/03/exclure-fichiers-depot-git-gitignore-1476 gitignore]:
 
<pre>
git config --global core.excludesfile ./.gitignore
</pre>
 
'''=> à priori sans effet car valeur par défaut contrairement au wiki ci dessus.'''
 
<pre>
vi .gitignore (ignorer /tmp)
git status
</pre>
 
Contenu du gitignore (''.git/info/exclude''):
 
<pre>
# git ls-files --others --exclude-from=.git/info/exclude
# Lines that start with '#' are comments.
# For a project mostly in C, the following would be a good set of
# exclude patterns (uncomment them if you want to use them):
# *.[oa]
# *~
/tmp
/old
</pre>
 
<pre>
vi .git/info/exclude
rm .gitignore
git status
</pre>
 
==== Fichiers ignorés ====
 
* ''/tmp'': des fichiers temporaires.
* ''/old'': des vieux exemples de code, utiles pour ce projet.
* ''*.retry'': fichiers Ansible de retry limité en cas d'échec précédent.
* ''*.plan'': les fichiers de planification Terraform
* ''scwcreds.sh'': script de stockage des creds Scaleway.
 
'''NB''': certains articles indique qu'il est bon de stocker sous git son fichier d'état Terraform (tfstate), d'[https://openupthecloud.com/terraform-best-practices/ autres] indiquent que non... En fait tout dépend vers où on commit (son propre poste, ou un repo distant sur internet, éventuellement public comme Github), et du risque potentiel d'exposer des données critiques (creds, chaîne d'accès à une base de donnée, etc...).
 
=== Installation Terraform ===
 
==== Installation ====
 
Cf [https://www.terraform.io/docs/cli/install/apt.html la documentation Terraform]
 
Dans la distribution WSL Debian:
 
<pre>
sudo apt-get update
sudo apt-get install curl
sudo apt-get install gnupg1
curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo apt-key add -
sudo apt-get install lsb-release
</pre>
 
Cf [https://itsfoss.com/add-apt-repository-command-not-found/ cette doc pour le troubleshooting lors de l'ajout du repository].
 
<pre>
sudo apt-get install software-properties-common
sudo apt-add-repository "deb [arch=$(dpkg --print-architecture)] https://apt.releases.hashicorp.com $(lsb_release -cs) main"
sudo apt install terraform
</pre>
 
Cf [https://registry.terraform.io/providers/scaleway/scaleway/latest/docs ce tuto] pour l'ajout du provider Scaleway.
 
Bloc à placer avant la déclaration du provider:
 
<pre>
terraform {
  required_providers {
    scaleway = {
      source = "scaleway/scaleway"
    }
  }
  required_version = ">= 0.13"
}
</pre>
 
==== Configuration ====
 
<pre>
jules@DESKTOP-QQG9015:/mnt/d/Jules/Tech/Git/scaleway/terraform$ terraform init
 
Initializing the backend...
 
Initializing provider plugins...
- Finding latest version of scaleway/scaleway...
- Installing scaleway/scaleway v2.1.0...
- Installed scaleway/scaleway v2.1.0 (signed by a HashiCorp partner, key ID F5BF26CADF6F9614)
 
Partner and community providers are signed by their developers.
If you'd like to know more about provider signing, you can read about it here:
https://www.terraform.io/docs/cli/plugins/signing.html
 
Terraform has created a lock file .terraform.lock.hcl to record the provider
selections it made above. Include this file in your version control repository
so that Terraform can guarantee to make the same selections by default when
you run "terraform init" in the future.
 
Terraform has been successfully initialized!
 
You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.
 
If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
</pre>
 
=== Installation Ansible ===
 
Cf [https://docs.ansible.com/ansible/latest/index.html la documentation officielle Ansible].
 
<pre>
sudo apt-get update
sudo apt-cache search ansible
sudo apt-get install ansible
</pre>
 
== Configuration Scaleway ==
 
* Suppression des clés RSA dans les "Identifiants" du compte Scaleway, et re création avec le contenu de ma clé publique utilisée par défaut.
 
'''NB:''' cette clé sera automatiquement placée par Scaleway dans le authorized_keys du user root au moment du déploiement de l'instance.
 
[https://www.phcomp.co.uk/Tutorials/Unix-And-Linux/ssh-check-server-fingerprint.html Vérification de la fingerprint] de ma clé publique:
 
<pre>
jules@DESKTOP-QQG9015:~$ ssh-keygen -l -E md5 -f ./id_rsa_jules.pub
2048 MD5:bc:c2:f5:6f:a9:03:97:fb:fc:65:3f:f0:de:d1:31:24 jules@DESKTOP-QQG9015 (RSA)
</pre>
 
* Suppression des anciennes clés d'API et re création d'une paire clé/clé secrète.
 
== Code Terraform ==
 
=== Documentations utiles ===
 
Choix de départ: on colle tout le code Terraform dans un seul ''main.tf''.
 
* Cf [https://www.scaleway.com/fr/terraform/ cette documentation officielle Scaleway].
* Cf [https://registry.terraform.io/providers/scaleway/scaleway/latest/docs/resources/instance_server cette documentation officielle Terraform pour la création d'instances Server].
* Cf [https://registry.terraform.io/providers/scaleway/scaleway/latest/docs/resources/instance_ip cette documentation officielle Terraform pour la création d'instances IP Publique].
* Cf [https://registry.terraform.io/providers/scaleway/scaleway/latest/docs/resources/instance_volume cette documentation officielle Terraform pour la création d'instances Volume].
* Cf [https://registry.terraform.io/providers/scaleway/scaleway/latest/docs/resources/instance_security_group cette documentation officielle Terraform pour la création d'instances Security Group].
* Cf [https://registry.terraform.io/providers/scaleway/scaleway/latest/docs/guides/migration_guide_v2 cette documentation officielle Terraform pour la migration de version du provider Scaleway].
** Cette documentation ne nous concerne pas vraiment puisque les serveurs concernés n'étaient pas gérés par terraform auparavant.
** En revanche elle donne quelques informations utiles, notamment pour permettre de corriger des références de la documentation Scaleway (1er lien ci-dessus).
 
=== Code du projet ===
 
Etapes:
 
* Câblage du provider Scaleway:
 
<pre>
terraform {
  required_providers {
    scaleway = {
      source = "scaleway/scaleway"
    }
  }
  required_version = ">= 0.13"
}
</pre>
 
* Déclaration du provider:
 
<pre>
provider "scaleway" {
  access_key      = "<clé API Scaleway>"
  secret_key      = "<clé secrète de la clé d'API>"
  project_id      = "<utiliser l'ID de l'organisation Scaleway>"
  zone            = "fr-par-1"
  region          = "fr-par"
}
</pre>
 
* Réservation d'une IP publique:
 
<pre>
resource "scaleway_instance_ip" "public_ip" {}
</pre>
 
* Configuration du Security Group:
 
<pre>
resource "scaleway_instance_security_group" "test-sg" {
  inbound_default_policy  = "drop"
  outbound_default_policy = "accept"
  name = "tf-test-sg"
 
  inbound_rule {
    action = "accept"
    port  = "22"
    ip    = "<IP publique du poste ou serveur d'administration>"
  }
 
  inbound_rule {
    action = "accept"
    port  = "80"
  }
 
  inbound_rule {
    action = "accept"
    port  = "443"
  }
}
</pre>
 
* Déclaration de l'instance serveur:
 
<pre>
resource "scaleway_instance_server" "test-srv" {
  type  = "DEV1-S"
  image = "debian_buster"
  name = "tf-test-srv"
  state = "started"
 
  tags = [ "test", "web" ]
 
  ip_id = scaleway_instance_ip.public_ip.id
 
  security_group_id = scaleway_instance_security_group.test-sg.id
}
</pre>
 
'''NB:'''
* A confirmer, mais les types d'instance DEV n'ont pas l'air de supporter un disque additionnel, donc on retire ce bout de code de l'exemple fourni par Scaleway et on se contente du disque local de base (20Go pour DEV1-S).
* la proposition de la doc Scaleway d'utiliser une clé organization_id n'est plus valable dans cette version de Terraform, cf [https://registry.terraform.io/providers/scaleway/scaleway/latest/docs/guides/migration_guide_v2 ce tuto Terraform]. A partir de là, on remplace organization_id par project_id, et on fixe par défaut la valeur à l'ID de notre organisation Scaleway.
 
== Code Ansible ==
 
=== Documentations utiles ===
 
Premiers pas:
* [https://docs.ansible.com/ansible/latest/user_guide/index.html Index du guide utilisateur Ansible]
* [https://docs.ansible.com/ansible/latest/user_guide/intro_getting_started.html Introduction et premiers pas avec Ansible]
 
=== Debug des appels distants à Python ===
 
==== Solution "sale" ====
 
'''NB:''' Dans notre cas, les appels ansible échouaient avec une erreur du type:
 
<pre>
"/bin/sh: 1: /usr/bin/python: not found\r\n",
</pre>
 
Sur le node contrôlé par Ansible, on constate en effet que ce fichier n'existe pas, on contourne brutalement la situation via la commande suivante:
 
<pre>
ln -s /usr/bin/python3.7 /usr/bin/python
</pre>
 
==== Solution "propre" ====
 
La [https://docs.ansible.com/ansible/latest/user_guide/intro_inventory.html#intro-inventory documentation Ansible sur la gestion de l'inventaire] précise que via l'inventaire, on peut préciser explicitement le binaire python à utiliser:
 
<pre>
<alias>  ansible_host=<ip_serveur> ansible_python_interpreter=/usr/bin/python3.7
</pre>
 
'''NB:''' ceci évite d'avoir à passer des commandes en local sur le serveur distant.
 
=== Debug des problèmes liés à la mise à jour du cache Aptitude ===
 
Lors des installations de packages, on peut demander à Ansible de mettre à jour le cache Aptitude avant d'installer (update_cache):
 
<u>Exemple de task:</u>
 
<pre>
    - name: Install Lets Encrypt
      apt:
        name: letsencrypt
        update_cache: yes
        state: latest   
</pre>
 
Lors des premiers runs de playbook sur le serveur de tests, on tombe sur des erreurs indiquant un besoin de validation de modification de configuration de repository pour Aptitude sur le remote node. Ce message correspond aux erreurs suivantes lorsqu'on lance une mise à jour manuelle du cache sur le remote node:
 
<pre>
root@tf-test-srv:~# apt-get update
Get:1 http://security.debian.org/debian-security buster/updates InRelease [65.4 kB]
Get:2 http://deb.debian.org/debian buster InRelease [122 kB]
Get:3 http://deb.debian.org/debian buster-updates InRelease [51.9 kB]
Get:4 http://deb.debian.org/debian buster-backports InRelease [46.7 kB]
Hit:5 http://ppa.launchpad.net/scaleway/stable/ubuntu focal InRelease
Reading package lists... Done
E: Repository 'http://security.debian.org/debian-security buster/updates InRelease' changed its 'Suite' value from 'stable' to 'oldstable'
N: This must be accepted explicitly before updates for this repository can be applied. See apt-secure(8) manpage for details.
N: Repository 'http://deb.debian.org/debian buster InRelease' changed its 'Version' value from '10.9' to '10.10'
E: Repository 'http://deb.debian.org/debian buster InRelease' changed its 'Suite' value from 'stable' to 'oldstable'
N: This must be accepted explicitly before updates for this repository can be applied. See apt-secure(8) manpage for details.
E: Repository 'http://deb.debian.org/debian buster-updates InRelease' changed its 'Suite' value from 'stable-updates' to 'oldstable-updates'
N: This must be accepted explicitly before updates for this repository can be applied. See apt-secure(8) manpage for details.
</pre>
 
==== Solution "sale" ====
 
Après quelques recherches Google, on identifie [https://superuser.com/questions/1456989/how-to-configure-apt-in-debian-buster-after-release une méthode] permettant de supprimer ces erreurs (méthode confirmée sur d'autres sources, à éclairer par lecture du man apt-get).
 
<pre>
root@tf-test-srv:~# apt-get update --allow-releaseinfo-change
Get:1 http://security.debian.org/debian-security buster/updates InRelease [65.4 kB]
Get:2 http://deb.debian.org/debian buster InRelease [122 kB]
Get:3 http://deb.debian.org/debian buster-updates InRelease [51.9 kB]
Hit:4 http://deb.debian.org/debian buster-backports InRelease
Hit:5 http://ppa.launchpad.net/scaleway/stable/ubuntu focal InRelease
Get:6 http://security.debian.org/debian-security buster/updates/main Sources [199 kB]
Get:7 http://security.debian.org/debian-security buster/updates/main amd64 Packages [302 kB]
Get:8 http://security.debian.org/debian-security buster/updates/main Translation-en [158 kB]
Get:9 http://deb.debian.org/debian buster/main Sources [7836 kB]
Get:10 http://deb.debian.org/debian buster/main amd64 Packages [7907 kB]
Get:11 http://deb.debian.org/debian buster/main Translation-en [5968 kB]
Get:12 http://deb.debian.org/debian buster-updates/main Sources.diff/Index [7624 B]
Get:13 http://deb.debian.org/debian buster-updates/main amd64 Packages.diff/Index [7624 B]
Get:14 http://deb.debian.org/debian buster-updates/main Translation-en.diff/Index [5164 B]
Get:15 http://deb.debian.org/debian buster-updates/main Sources 2021-06-21-1401.46.pdiff [923 B]
Get:16 http://deb.debian.org/debian buster-updates/main Sources 2021-06-23-1401.37.pdiff [15.6 kB]
Get:17 http://deb.debian.org/debian buster-updates/main amd64 Packages 2021-06-21-1401.46.pdiff [656 B]
Get:18 http://deb.debian.org/debian buster-updates/main amd64 Packages 2021-06-23-1401.37.pdiff [4999 B]
Get:16 http://deb.debian.org/debian buster-updates/main Sources 2021-06-23-1401.37.pdiff [15.6 kB]
Get:19 http://deb.debian.org/debian buster-updates/main Translation-en 2021-06-21-1401.46.pdiff [719 B]
Get:18 http://deb.debian.org/debian buster-updates/main amd64 Packages 2021-06-23-1401.37.pdiff [4999 B]
Get:20 http://deb.debian.org/debian buster-updates/main Translation-en 2021-06-23-1401.37.pdiff [6585 B]
Get:20 http://deb.debian.org/debian buster-updates/main Translation-en 2021-06-23-1401.37.pdiff [6585 B]
Fetched 22.4 MB in 7s (3169 kB/s)
Reading package lists... Done
N: Repository 'http://security.debian.org/debian-security buster/updates InRelease' changed its 'Suite' value from 'stable' to 'oldstable'
N: Repository 'http://deb.debian.org/debian buster InRelease' changed its 'Version' value from '10.9' to '10.10'
N: Repository 'http://deb.debian.org/debian buster InRelease' changed its 'Suite' value from 'stable' to 'oldstable'
N: Repository 'http://deb.debian.org/debian buster-updates InRelease' changed its 'Suite' value from 'stable-updates' to 'oldstable-updates'
</pre>
 
'''=> les erreurs lors de l'update manuel disparaissent.'''
'''=> à partir de là, les erreurs lors d'une tâche d'installation de package avec mise à jour préalable du cache aptitude disparaissent également.'''
 
==== Solution "propre" ====
 
Toujours dans l'idée d'éviter de se connecter au serveur distant pour y passer des commandes en local, on peut (comme précisé sur [https://askcodez.com/ansible-playbook-pour-executer-les-commandes-shell.html ce forum]) passer la commande à distance:
 
<pre>
ansible <alias> -m command -a '<commande shell>'
</pre>
 
<u>Ex:</u>
 
<pre>
ansible jules -m command -a 'sudo apt-get update --allow-releaseinfo-change'
</pre>
 
'''NB:''' le passage de cette commande ansible produit des warning sur l'utilisation de sudo au lieu de become, on les laisse de côté étant donné qu'on est sur de la commande one shot.
 
 
=== Control node à proximité du remote node ===
 
Cette bonne pratique Ansible n'est pas respectée dans le cadre du projet dans un premier temps.
 
Pour la mettre en oeuvre il faudrait:
* envisager l'utilisation d'une instance bastion (à accès très limités) chez Scaleway, cette instance porterait l'application Ansible et les playbooks.
* envisager de pousser les playbooks sur un repository type Gitlab ou Github afin de pouvoir cloner les projets une fois les modifications poussées sur le repository.
 
=== Constitution de la liste d'hôtes / l'inventaire ===
 
Cf [https://docs.ansible.com/ansible/latest/user_guide/intro_inventory.html#intro-inventory la documentation officielle Ansible sur la gestion de l'inventaire de parc].
 
Il y a de nombreuses façons de désigner les machines de l'inventaire:
* via une option de la ligne de commande ansible-playbook.
* via un fichier d'inventaire local au projet.
* via un fichier d'inventaire global dans ''/etc/ansible/hosts''.
 
==== Solution initiale ====
 
Dans un premier temps on applique une configuration simpliste dans le fichier global, on fera mieux ensuite:
 
<pre>
sudo vi /etc/ansible/hosts
...
[testservers]
<ip_publique_serveur>
</pre>
 
==== Solution définitive: l'inventaire dans le dossier du projet ====
 
On s'appuie sur [https://www.ansible.com/hubfs/2018_Content/AA%20BOS%202018%20Slides/Ansible%20Best%20Practices.pdf Le PDF décrivant les bonnes pratiques Ansible].
 
Constitution (dossiers/fichiers) de l'inventaire:
 
inventory/
├── group_vars
│   └── prodservers.yml
├── hosts
└── host_vars
    ├── denz.yml
    └── jules.yml
 
Les contraintes:
* dans ''group_vars'', les noms des fichiers yml doivent correspondre aux noms des groupes dans l'inventaire.
* dans ''host_vars'', les noms des fichiers yml doivent correspondre aux noms des hôtes dans l'inventaire.
 
Prise en compte de cet inventaire:
* création d'un fichier ''ansible.cfg'' spécifique au projet.
* son contenu est le suivant:
 
<pre>
[defaults]
inventory      = ./inventory/hosts
</pre>
 
Enfin, une contrainte '''spécifique à mon environnement perso (WSL sur Windows)''':
* pour permettre d'accéder aux fichiers via VSCode, stockage de l'arborescence dans un dossier d'un des disques du Windows.
* dans ce cas, la gestion des droits n'est pas standard, et les droits sont très/trop larges en fonction des exigences côté Linux.
* 1 solution possible est présentée [https://devblogs.microsoft.com/commandline/chmod-chown-wsl-improvements/ ici]: solution non adaptée (cf caveats) car l'édition des fichiers via un éditeur Windows (ex: VSCode) va systématiquement recoller des droits windows...
* 1 solution plus laxe identifiée [https://docs.ansible.com/ansible/devel/reference_appendices/config.html#cfg-in-world-writable-dir dans la documentation officielle Ansible]: désigner le fichier ''ansible.cfg'' local au projet par une variable d'environnement:
 
<pre>
export ANSIBLE_CONFIG="/mnt/d/Jules/Tech/Git/scaleway/ansible/ansible.cfg"
</pre>
 
=== Gestion des utilisateurs ===
 
Cf [https://docs.ansible.com/ansible/latest/collections/ansible/builtin/user_module.html La documentation Ansible du module User] ainsi que [https://docs.ansible.com/ansible/latest/collections/ansible/posix/authorized_key_module.html#ansible-collections-ansible-posix-authorized-key-module cette documentation Ansible sur la gestion du module Authorized_keys].
 
Bonne pratique:
* Il est recommandé d'utiliser un autre utilisateur que root pour effectuer l'établissement de la session SSH par Ansible.
* Il faut privilégier l'usage d'un compte de déploiement ayant les droits suffisants pour passer toutes les commandes nécessaires en sudo.
* Il faut ensuite utiliser la directive [https://docs.ansible.com/ansible/latest/user_guide/become.html become] permettant de gérer les élévations de privilèges pour les tâches qui le nécessitent.
 
Le choix fait dans le cadre de cette migration est de:
* créer un playbook à exécuter à la création d'un serveur, ou à chaque ajout/suppression d'utilisateur de déploiement.
* ce playbook sera à exécuter en tant que root (puisque Scaleway livre ses serveurs avec un accès root autorisé et la ou les clés RSA d'administration autorisées à se connecter).
* tous les autres playbook seront joués avec l'utilisateur local de ma session WSL (l'utilisateur de déploiement aura le même login que mon compte WSL).
 
Playbook:
 
<pre>
---
  - name: Playbook de creation des users sudoers
    hosts: all
    vars:
      sudoers:
        - jules
 
    tasks:
      - name: Make sure we have a 'wheel' group
        group:
          name: wheel
          state: present
 
      - name: Allow 'wheel' group to have passwordless sudo
        lineinfile:
          dest: /etc/sudoers
          state: present
          regexp: '^%wheel'
          line: '%wheel ALL=(ALL) NOPASSWD: ALL'
          validate: visudo -cf %s
 
      - name: Add sudoers users to wheel group
        user:
          name: "{{ item }}"
          shell: /bin/bash
          groups: wheel
          append: yes
        with_items: "{{ sudoers }}"
 
      - name: Add jules public key
        authorized_key:
          user: "{{ item }}"
          state: present
          key: "{{ lookup('file', '<chemin_local_de_la_cle_publique_rsa>') }}"
        with_items: "{{ sudoers }}"
 
...
 
</pre>
 
Dans les fils de discussions, on trouve des remarques pertinentes sur l'utilisation de sudoers.d à la place du fichier global sudoers, à tester dans un second temps si possible.
 
'''NB:''' ceci n'est évidemment pas une vraie gestion d'utilisateurs en bonne et dûe forme, et correspond plutôt aux besoins très simples du projet (1 seul ops utilisant toujours la même clé RSA pour l'authentification par exemple).
 
=== Déploiement des packages ===
 
Cf [https://www.scaleway.com/en/docs/tutorials/install-apache-ansible/ cette vieille doc Scaleway sur l'installation d'Apache par Ansible].
 
On peut installer un package, explicitement via Aptitude, grâce à une tâche du type:
  tasks:
    - name: Install Apache2 '''=> nom de la tâche, le nommage des tâches est une bonne pratique.'''
      apt:                  '''=> désignation explicite du gestionnaire de package, puisqu'on ne gère pas un parc hétérogène.'''
        name: apache2      '''=> nom du package tel que fournit par une recherche Aptitude.'''
        update_cache: yes  '''=> mise à jour du cache Aptitude avant l'installation.'''
        state: latest      '''=> version souhaitée du package.'''
 
Playbook:
 
<pre>
---
- name: Playbook d'installation des packages debian
  hosts: all
  become: yes
 
  tasks:
    - name: Install Apache2
      apt:
        name: apache2
        update_cache: yes
        state: latest
 
    - name: Install php
      apt:
        name: php
        update_cache: yes
        state: latest
 
    - name: Install lib curl
      apt:
        name: php-curl
        update_cache: yes
        state: latest
 
    - name: Install lib mbstring
      apt:
        name: php-mbstring
        update_cache: yes
        state: latest
 
    - name: Install lib zip
      apt:
        name: php-zip
        update_cache: yes
        state: latest
 
    - name: Install lib imagick
      apt:
        name: php-imagick
        update_cache: yes
        state: latest
 
    - name: Install Lets Encrypt
      apt:
        name: letsencrypt
        update_cache: yes
        state: latest                         
...
 
</pre>
 
'''NB:'''
* le code peut être largement factorisé en bouclant sur la liste de packages requis.
* la mise à jour systématique du cache Aptitude est discutable car elle pénalise la durée d'exécution de chaque tâche.
 
<pre>
---
  - name: Playbook packages factorise
    hosts: all
    become: yes
    vars:
      pkgs:
        - apache2
        - php
        - php-curl
        ...
        - letsencrypt
 
    tasks:
      - name: Install packages
        apt:
          name: "{{ item }}"
          update_cache: yes
          state: latest
        with_items: "{{ pkgs }}"
</pre>
 
En fin de compte, le with_items dans le module apt est déprécié et la tâche devient encore plus simple:
 
<pre>
  tasks:
    - name: Install all web packages
      apt:
        name: "{{ pkgs }}"
        update_cache: yes
        state: latest
</pre>
 
=== Installation des modules Apache2 ===
 
Cf [https://docs.ansible.com/ansible/latest/collections/community/general/apache2_module_module.html La documentation officielle du module Apache2].
 
Liste des modules:
* ssl
* expires
* rewrite
* headers
 
Tâche type d'installation:


Ex:
<pre>
<pre>
    - name: Install apache SSL module
PS C:\Users\j.pedrono> systeminfo
      apache2_module:
        state: present
        name: ssl
        identifier: ssl_module
</pre>
 
'''NB:'''
* On devrait pouvoir installer les modules via l'option '''name''', en utilisant le nom du module tel que fourni par <pre>apache2ctl -M</pre> et en supprimant le pattern '''_module''', mais lors des appels de playbook, les noms des modules ne sont pas reconnus et Ansible conseille d'utiliser l'option '''identifier'''.
* En utilisant '''identifier''' et en y mettant les noms de modules tels que fournis par la commande précédente, cela fonctionne.
* '''CONTRAINTE:''' soit il faudrait pouvoir parser un tableau à 2 colonnes (name et identifier, par module) pour factoriser la tâche, soit on crée une tâche par module. Je fais le 2eme choix étant donné le faible nombre de modules à activer.
* ces modules sont installés dans le même playbook que celui servant à installer les packages aptitude, et on choisit volontairement d'installer les mêmes modules sur les 2 machines en deb10.
 
=== Gestion des vhosts Apache ===


On choisit pour l'instant de se passer de templates Jinja et de variables à instancier du fait du faible nombre de vhosts à gérer (1 à 3 par machine) et de l'absence d'ajout régulier de confs.
Nom de l’hôte:                              901180281M
 
Nom du système d’exploitation:              Microsoft Windows 10 Professionnel
On reprend donc chaque fichier de configuration Apache2 sur les prods de départ. On stocke ces confs dans des fichiers locaux au projet, et on utilise une tâche de copie de fichier:
Version du système:                        10.0.19042 N/A version 19042
 
Fabricant du système d’exploitation:        Microsoft Corporation
<pre>
Configuration du système d’exploitation:    Station de travail membre
    - name: Copy vhost www Jules
Type de version du système d’exploitation:  Multiprocessor Free
      copy:
Propriétaire enregistré:                    XXXXXXX
        src: ./files/jules_www.pedrono.fr.conf
Organisation enregistrée:                  XXXXXXX
         dest: /etc/apache2/sites-available/www.pedrono.fr.conf
Identificateur de produit:                  XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX
Date d’installation originale:              01/09/2021, 09:55:49
Heure de démarrage du système:              08/09/2021, 14:04:42
Fabricant du système:                      HP
Modèle du système:                          HP EliteBook 840r G4
Type du système:                            x64-based PC
Processeur(s):                              1 processeur(s) installé(s).
                                            [01] : Intel64 Family 6 Model 142 Stepping 9 GenuineIntel ~2511 MHz
Version du BIOS:                            HP Q80 Ver. 01.14.01, 16/10/2020
Répertoire système:                        C:\WINDOWS\system32
Périphérique d’amorçage:                    \Device\HarddiskVolume5
Option régionale du système:                fr;Français (France)
Paramètres régionaux d’entrée:              fr;Français (France)
Fuseau horaire:                            (UTC+01:00) Bruxelles, Copenhague, Madrid, Paris
Mémoire physique totale:                   12 131 Mo
Mémoire physique disponible:                6 127 Mo
Mémoire virtuelle : taille maximale:        14 563 Mo
Mémoire virtuelle : disponible:            7 349 Mo
Mémoire virtuelle : en cours d’utilisation: 7 214 Mo
Emplacements des fichiers d’échange:        C:\pagefile.sys
Domaine:                                   directory.XXXXXXX.com
Serveur d’ouverture de session:            \\XXXXXXX
Correctif(s):                              9 Corrections installées.
                                            [01]: KB5004331
                                            [02]: KB4562830
                                            [03]: KB4570334
                                            [04]: KB4577266
                                            [05]: KB4577586
                                            [06]: KB4589212
                                            [07]: KB4598481
                                            [08]: KB5005033
                                            [09]: KB5005260
Carte(s) réseau:                            3 carte(s) réseau installée(s).
                                            [01]: Intel(R) Ethernet Connection (4) I219-V
                                                  Nom de la connexion : Ethernet
                                                  État :                Support déconnecté
                                            [02]: Intel(R) Dual Band Wireless-AC 8265
                                                  Nom de la connexion : Wi-Fi
                                                  DHCP activé :         Oui
                                                  Serveur DHCP :       XXXXXXX
                                                  Adresse(s) IP
                                                  [01]: XXXXXXX
                                                  [02]: XXXXXXX
                                            [03]: Bluetooth Device (Personal Area Network)
                                                  Nom de la connexion : Connexion réseau Bluetooth
                                                  État :                Support déconnecté
Configuration requise pour Hyper-V:        Un hyperviseur a été détecté. Les fonctionnalités nécessaires à Hyper-V ne seront pas affichées.
</pre>
</pre>


Faute d'identifier un module permettant la gestion fine des vhosts pour Apache2, on procède "manuellement":
== Information de version WSL par distribution Linux ==
* utilisation du module '''command''' pour appeler '''a2ensite'''.
* utilisation du module '''command''' pour appeller '''apache2ctl graceful'''.


<pre>
<pre>
    - name: Enable vhost www Jules
wsl --list --verbose
      command: a2ensite www.pedrono.fr.conf
 
    - name: Apache Graceful
      command: apache2ctl graceful
</pre>
</pre>


On peut aussi utiliser un handler pour gérer le redémarrage (inspiré de [https://www.digitalocean.com/community/tutorials/how-to-configure-apache-using-ansible-on-ubuntu-14-04 cet article]):
ou


<pre>
<pre>
  - tasks:
wsl -l -v
    ...
    - name: Enable vhost peaudeau
      command: a2ensite www.peaudeau.fr.conf
      notify:
        - restart apache2
 
  handlers:
    - name: restart apache2
      service:
        name: apache2
        state: restarted
</pre>
</pre>


=== Gestion des bases de données ===
Ex:
 
==== Pré requis ====
 
Pour fonctionner correctement, les modules mysql_db et mysql_user ont besoin d'un module python sur les nodes distants: '''python3-pymysql'''.
 
On installe ce package via le playbook de gestion des packages.
 
==== Globalement ====
 
MariaDB s'installe par défaut avec un accès root sans mot de passe, ce qui n'est pas très propre.
 
Identification d'[https://dba.stackexchange.com/questions/274547/cant-set-root-password-after-fresh-installation-of-mariadb-using-ansible une méthode] pour effectuer le changement de mot de passe.


<pre>
<pre>
  tasks:
PS C:\Users\j.pedrono> wsl -l -v
    - name: fix empty root password
  NAME      STATE          VERSION
      mysql_user:
* Debian    Running         1
        login_unix_socket: /var/run/mysqld/mysqld.sock
         name: 'root'
        password: "{{ mysql_pass }}"
        state: present
</pre>
</pre>


'''NB:''' le mot de passe est passé via des variables d'hôte de l'inventaire.
== Changer de version WSL par distribution Linux ==
 
On stocke également en local sur les serveurs le .my.cnf contenant le nouveau mot de passe:


<pre>
<pre>
    - name: set .my.cnf file for root
wsl --set-version <distribution name> <versionNumber>
      copy:
        src: ./files/my.cnf
        dest: /root/.my.cnf
</pre>
</pre>


Enfin, application d'une tâche de suppression des comptes "anonymes":
= Installation de WSL =


<pre>
== Installation standard ==
    - name: Removes all anonymous user accounts
      mysql_user:
        login_unix_socket: /var/run/mysqld/mysqld.sock
        name: ''
        host_all: yes
        state: absent
</pre>


'''NB:''' il existe sans doute d'autres tâches à appliquer pour sécuriser le service MariaDB, mais on en reste là pour l'instant.
Cf [https://docs.microsoft.com/en-us/windows/wsl/install-win10 cette documentation Microsoft sur le sujet].


==== Spécifique: bases applicatives ====
* Si vous avez accès au Windows Store sur votre poste Windows, suivez cette méthode, considérée comme la plus simple.
* Une technique équivalente en ligne de commande PowerShell: <pre>wsl --install</pre>
* '''NB:''' cette méthode requiert de faire partie du programme '''Windows Insider'''.


On utilise des tâches de création des bases:
== Sans accès au Windows Store (App) ==


<pre>
Sans accès à Windows Store, l'installation manuelle est possible (cf le lien du paragraphe [https://docs.microsoft.com/en-us/windows/wsl/install-win10 "installation standard"]):
  tasks:
    - name: Create database test
      mysql_db:
        name: test
        login_unix_socket: /var/run/mysqld/mysqld.sock
        state: present
</pre>


'''NB:'''
Les étapes en résumé sont:
* on désigne le socket unix plutôt que l'hôte pour accéder au service et s'authentifier, car MariaDB est configuré par défaut pour fonctionner de cette manière comme l'indique [https://docs.ansible.com/ansible/latest/collections/community/mysql/mysql_variables_module.html#notes la documentation officielle Ansible].
* activation de WSL dans une console PowerShell en tant qu'administrateur (du poste): <pre>dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart</pre>
* l'autre option serait de revoir la configuration du service MariaDB pour utiliser le [https://stackoverflow.com/questions/63433445/ansible-access-denied-for-rootlocalhost-error socket TCP] pour l'authentification.
* '''OPTIONNEL WSL2''': vérification des pré requis pour l'utilisation de WSL 2 (au lieu de WSL 1) => cette feature nécessite un certain niveau de build Windows en fonction de l'architecture.
* '''OPTIONNEL WSL2''': activation de la fonctionnalité Virtual Machine dans une console PowerShell en tant qu'administrateur (du poste): <pre>dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart</pre> (cette action '''nécessite ensuite un reboot''').
* '''OPTIONNEL WSL2''': téléchargement et installation du [https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi Linux kernel update package]. L'installation nécessite '''une élévation de privilège'''.
* '''OPTIONNEL WSL2''': déclarer WSL 2 comme version par défaut. Dans une fenêtre PowerShell: <pre>wsl --set-default-version 2</pre>. '''NB''': ce n'est que la version par défaut, il est ensuite possible de sélectionner une version de WSL par distribution Linux installée sur le système.
* Télécharger depuis le site Microsoft la distribution Linux qui vous intéresse (dans mon cas, [https://www.microsoft.com/store/apps/9MSVKQC78PK6 Debian]).


On utilise également des tâches de création des users applicatifs:
== Sans accès au Windows Store (y compris sites de téléchargement Microsoft) ==


<pre>
Si comme moi, pour une raison non encore identifiée liée à la sécurisation du poste Windows ou du réseau d'entreprise, vous ne pouvez pas télécharger les distributions Linux en cliquant sur '''Obtenir''' (ou '''Get''') sur par exemple [https://www.microsoft.com/fr-fr/p/debian/9msvkqc78pk6?rtc=1&activetab=pivot:overviewtab ce lien], il existe encore des méthodes d'installation alternatives: cf [https://docs.microsoft.com/en-us/windows/wsl/install-manual cette documentation d'installation manuelle].
    - name: Create database user for testuser
      mysql_user:
        login_unix_socket: /var/run/mysqld/mysqld.sock
        state: present
        name: testuser
        password: "{{ mysql_pass_testuser }}"
        priv: 'test.*:ALL,GRANT'
</pre>


'''NB:''' le mot de passe MySQL du user est passé via des variables de host (puisque les mots de passe sont tous différents d'un user à un autre).
Les étapes:
* Déterminer le nom de sa distribution via les URLs de téléchargement.
* Téléchargement d'une distribution, via une commande PowerShell: <pre>Invoke-WebRequest -Uri https://aka.ms/wsl-ubuntu-1604 -OutFile Ubuntu.appx -UseBasicParsing</pre>
* Exemple pour Debian: <pre>Invoke-WebRequest -Uri https://aka.ms/wsl-debian-gnulinux -OutFile Debian.appx -UseBasicParsing</pre>
* Installer le package, via une commande PowerShell: <pre>Add-AppxPackage .\Ubuntu.appx</pre>
* Info utile: le package est téléchargé en principe dans <pre>C:\Windows\System32\</pre>


==== Problème rencontré: utilisation de listes de DB ====
= Quel que soit le mode d'installation =


Lors des tests initiaux, utilisation de la syntaxe [https://docs.ansible.com/ansible/latest/collections/community/mysql/mysql_db_module.html préconisée par la documentation officielle du module]:
* [https://docs.microsoft.com/en-us/windows/wsl/user-support Créer le compte utilisateur] au premier lancement de votre nouvelle distribution.


<pre>
= Ajout de Windows Terminal =
- name: Create new databases with names 'foo' and 'bar'
  community.mysql.mysql_db:
    name:
      - foo
      - bar
    state: present
</pre>


Après les 1ers tests, on constate:
Il y a de nombreux intérêts à l'installation de Windows Terminal en complément de WSL:
* que sur une liste d'un item (ex: foo) la base est créée avec le nom incorrect '''['foo']'''.
* Cet outil permet notamment de faire cohabiter de nombreuses sessions en onglets au sein d'une seule fenêtre.
* que sur une liste de plusieurs items (ex: foo et bar) une seule base est créée avec un nom pourri: '''['foo','bar']'''
* Il permet de lancer de nombreux terminaux: terminal PowerShell, l'intégralité des distributions Linux installées sur WSL, une console Azure PowerShell...


'''Je ne fais pas de mises à jour manuelle du module (via Galaxy) ni d'ouverture d'issue, en revanche vu le faible nombre de bases à gérer je choisis d'utiliser 1 tâche par base pour contourner le problème.'''
Cf [https://www.microsoft.com/fr-fr/p/debian/9msvkqc78pk6?rtc=1&activetab=pivot:overviewtab cette partie de la documentation officielle Microsoft].


== Application des configurations Terraform ==
Cf [https://www.microsoft.com/fr-fr/p/windows-terminal-preview/9n8g5rfz9xk3?rtc=1#activetab=pivot:overviewtab cette documentation spécifique pour installer la version Preview].


Planifier les modifications:
== Avec le Windows Store ==


<pre>
Installation directe avec le Windows Store, ou en lançant le téléchargement depuis la [https://docs.microsoft.com/en-us/windows/terminal/get-started documentation d'installation Microsoft].
terraform plan
</pre>


Planifier les modifications ET produire un fichier de planification:
== Sans le Windows Store ==


<pre>
Sans accès au Windows Store, il existe un [https://github.com/microsoft/terminal/releases dépôt Github] pour la publication des versions successives de Windows Terminal.
terraform plan -out <fichier_de_planif>
</pre>


Appliquer les modifications:
'''NB''': la contrainte dans ce cas est qu'il faut gérer soi même les mises à jour du Windows Terminal.


<pre>
Vous téléchargez un fichier dont l'extension est msibundle: cf [https://github.com/Microsoft/Terminal#via-github cette documentation spécifique pour l'installation].
terraform apply
</pre>


Application des modifications telles que planifiées:
En résumé: <pre>Add-AppxPackage Microsoft.WindowsTerminal_<versionNumber>.msixbundle</pre>


<pre>
Exemple: <pre>Add-AppxPackage .\Microsoft.WindowsTerminalPreview_1.11.2421.0_8wekyb3d8bbwe.msixbundle</pre>
terraform apply "<fichier_de_planif>"
</pre>


Cf [https://www.terraform.io/docs/cli/state/ cette documentation Terraform sur le CLI et les états]: Si un objet a été modifié "dans la vraie vie" et que son état n'est plus cohérent avec les états connus de terraform, il est possible d'importer l'état "de la vraie vie" pour rendre cohérents les états terraform. Cela permet de rattraper les écarts, par exemple, quand on n'a pas été rigoureux et qu'on a géré les objets par d'autres biais que terraform (ex: console Scaleway):
= Diagnostiquer les problèmes d'installation ou de fonctionnement de WSL sur votre système =


<pre>
Microsoft met à disposition [https://docs.microsoft.com/en-us/windows/wsl/troubleshooting ce guide de troubleshooting] assez complet.
terraform import <nom_ressource_terraform> <region>/<id_de_l_objet_instancié>
</pre>


Vous pouvez lister les objets connus de terraform:
== Problème pour utiliser la commande ping ==


<pre>
A l'installation, et fonction de la version de votre build Windows et de WSL, vous pouvez rencontrer l'erreur suivante lors d'un ping:
terraform state list
</pre>
 
<u>Ex:</u>
 
<pre>
jules@DESKTOP-QQG9015:/mnt/d/Jules/Tech/Git/scaleway/terraform$ terraform state list
scaleway_instance_ip.public_ip
scaleway_instance_security_group.test-sg
scaleway_instance_server.test-srv
</pre>
 
Vous pouvez également lister l'état connu d'un objet par terraform:


<pre>
<pre>
terraform state show <nom_ressource_terraform>
jpedrono@901180281M:/mnt/c/Users/j.pedrono$ ping 8.8.8.8
ping: socket: Operation not permitted
</pre>
</pre>


<u>Ex:</u>
D'après les liens suivants, plus ou moins fiable, il s'agit d'un problème de droit de l'utilisateur de votre distribution sur le binaire ping:
* [https://github.com/microsoft/WSL/issues/5109 Un échange sur le dépôt Github de Microsoft].
* [https://www.incredigeek.com/home/how-to-fix-ping-socket-operation-not-permitted/ Une autre méthode de résolution basée sur un simple chmod].
* [https://forum.artixlinux.org/index.php/topic,1809.0.html Une autre méthode de résolution basée sur l'élargissement des GID autorisés à utiliser ping].


<pre>
Dans mon cas, application de la 1ere méthode puisqu'à priori émise par des personnes au sein de l'équipe MS WSL:
jules@DESKTOP-QQG9015:/mnt/d/Jules/Tech/Git/scaleway/terraform$ terraform state show scaleway_instance_server.test-srv
# scaleway_instance_server.test-srv:
resource "scaleway_instance_server" "test-srv" {
    additional_volume_ids = []
    boot_type            = "local"
    bootscript_id        = "<id_bootscript>"
    enable_dynamic_ip    = false
    enable_ipv6          = false
    id                    = "fr-par-1/<id_instance>"
    image                = "debian_buster"
    ip_id                = "fr-par-1/<id_ip>"
    ipv6_prefix_length    = 0
    name                  = "tf-test-srv"
    organization_id      = "<id_organization>"
    private_ip            = "<ip_privee>"
    project_id            = "<id_projet>"
    public_ip            = "<ip_publique>"
    security_group_id    = "fr-par-1/<id_sg>"
    state                = "started"
    tags                  = [
        "test",
        "web",
    ]
    type                  = "DEV1-S"
    zone                  = "fr-par-1"
 
    root_volume {
        delete_on_termination = true
        size_in_gb            = 20
        volume_id            = "fr-par-1/<id_volume>"
    }
}
</pre>
 
== Application des configurations Ansible ==
 
Jouer un playbook:


<pre>
<pre>
ansible-playbook <nom_du_playbook>.yml
jpedrono@901180281M:/mnt/c/Users/j.pedrono$ getcap /bin/ping
jpedrono@901180281M:/mnt/c/Users/j.pedrono$ sudo setcap cap_net_raw+p /bin/ping
[sudo] password for jpedrono:
jpedrono@901180281M:/mnt/c/Users/j.pedrono$ getcap /bin/ping
/bin/ping = cap_net_raw+p
jpedrono@901180281M:/mnt/c/Users/j.pedrono$ ping 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=112 time=10.7 ms
^C
--- 8.8.8.8 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 10.728/10.728/10.728/0.000 ms
</pre>
</pre>


Possibilités de surcharges:
= Une fois votre setup terminé... =
* '''-vvv''': augmenter le niveau de verbosité (débug).
* '''-u''': forcer l'usage d'un utilisateur spécifique (autre que celui de la session linux en cours).
* '''--private-key <path_to_priv_key>''': forcer l'usage d'une paire de clé RSA spécifique.
 
= Etapes de migration pour la prod =
 
== Steps de migration ==
 
* Rédaction (duplication) du code Terraform pour les 2 serveurs de prod.
* Planification dans un fichier de plan, et application Terraform.
* Récupération via <pre>terraform state show <id_objet_terraform_serveur></pre> des IPs publiques des 2 nouveaux serveurs.
* Mise à jour de l'inventaire Ansible global.
* Ajout des groupes, des alias, et des options d'inventaire concernant la version du binaire Python.
* Test de ping d'un des 2 serveurs.
<pre>
jules@DESKTOP-QQG9015:/mnt/d/Jules/Tech/Git/scaleway/ansible/init$ ansible jules -m ping -u root
jules | SUCCESS => {
    "changed": false,
    "ping": "pong"
}
</pre>
* Tests pour l'application d'un playbook par host ou groupe => '''ECHEC''', à reprendre plus tard.
* Application '''en root''' du playbook de création du user de déploiement.
* Correction de la désignation du chemin de la clé publique suite à la création des répertoires.
* Arrêt par Terraform du serveur de test.
* Mise en commentaire du serveur de test dans l'inventaire Ansible (pour éviter les échecs lors d'un hôte injoignable).
* Factorisation de la tâche d'installation des packages, à exécuter sur une liste de packages.
<pre>
  vars:
    pkgs:
      - apache2
      - php
      - php-curl
      - php-mbstring
      - php-zip
      - php-imagick
      - letsencrypt
      - mariadb-server
 
  tasks:
    - name: Install all web packages
      apt:
        name: "{{ pkgs }}"
        update_cache: yes
        state: latest
</pre>
* Ajout de mariadb à la liste des packages et début de recherche de documentation sur la gestion du service, des users et des bases.
** [https://docs.ansible.com/ansible/latest/collections/community/mysql/mysql_db_module.html Module mysql_db].
** [https://mariadb.com/kb/en/existing-ansible-modules-and-roles-for-mariadb/ Existing Ansible modules and roles for MariaDB].
** [https://docs.ansible.com/ansible/latest/collections/community/mysql/mysql_user_module.html Module mysql_user].
* 1 commit git du projet.
* [https://registry.terraform.io/providers/scaleway/scaleway/latest/docs#authentication Stockage des crédentiels Scaleway en variable d'environnement], exclusion de ce script de git et suppression des creds en dur dans le ''main.tf''.
* Test des accès Terraform avec cette nouvelle gestion de creds: '''OK'''.
* 1 commit git du projet.
* Ajout IP Denz dans les ACL SSH Terraform.
* Ajout clé RSA Denz dans les authorized_keys des users à privilèges.
 
* Création des databases:
** via ''depapt.yml'' installation complémentaire: '''python3-pymysql'''.
** identification du problème d'accès aux DB: par défaut, authentification MariaDB via le socket unix (fichier) => désignation de localhost à remplacer dans les tâches Ansible mysql.
** 1 playbook ''common.yml'' pour la sécurisation (accès root avec mdp entre autre).
** 1 playbook pour les bases de Jules.
** 1 playbook pour les bases de Denz.
 
* Rapatriement de l'inventaire Ansible dans le projet:
** 1 dossier inventory
 
jules@DESKTOP-QQG9015:/mnt/d/Jules/Tech/Git/scaleway/ansible$ tree inventory/
inventory/                '''Dossier d'inventaire'''
├── group_vars            '''Dossier pour les variables de groupes'''
│   └── prodservers.yml
├── hosts                  '''Fichier d'inventaire'''
└── host_vars              '''Dossier pour les variables d'hôtes'''
    ├── denz.yml
    └── jules.yml
 
** création d'un fichier de configuration Ansible (''ansible.cfg'') dans le dossier ansible et export d'une variable d'environnement pour contourner le pb de droits trop larges sur le fichier (liés à l'utilisation d'une arbo Windows dans WSL).
 
* Confs apache:
** récupération via scp des confs Apache2 actives en prod dans ''apache/files/''.
** copie de ces fichiers sur les serveurs via tâche ansible.
** pour distinguer les vhosts par machine:
*** 1 playbook Jules.
*** 1 playbook Denz.
** Test de 2 méthodes pour la prise en compte des confs Apache:
*** utilisation d'un handler.
*** OU utilisation du module '''command''' pour appeler <pre>apache2ctl restart/graceful</pre>.
** dans le playbook de déploiement des packages (''depapt.yml'') ajout de tâches apache2_module pour l'activation des modules Apache2 (reprise des modules installés sur les prods d'origine).
 
* Début des tests:
** dump des bases sur les prods d'origine, et dépôts sur les nouvelles prods en deb10.
** récupération des DocRoot sur les prods d'origine, et dépôts sur les nouvelles prod en deb10.
** patch fichier host local et 1er accès: '''HS''' beaucoup d'erreurs PHP.
** comparaison des phpinfo() des anciens et nouveaux serveurs, il manque pas mal de modules PHP:
 
<pre>
php-xml
php-gd
php-json
php-mysql
</pre>
 
== Ordre d'enchainement des codes Terraform et Ansible ==
 
# terraform sur le main.tf pour déployer les objets (et donc les serveurs).
# mettre à jour l'inventaire Ansible.
# application de ''init/sudoers.yml'' pour ne plus travailler en root.
# application de ''deploy/depapt.yml'' pour installer les packages apt et modules apache.
# application de ''db/common.yml'' pour sécuriser l'accès à MariaDB.
# application de ''db/dbdenz.yml'' et ''db/dbjules.yml'' pour créer les bases MySQL et les users dédiés à leur utilisation.
# application de ''apache/apachedenz.yml'' et ''apache/apachejules.yml'' pour configurer les vhosts Apache2.
 
= Reste à faire =
 
== Ansible ==
 
* '''OK''' Améliorer la lisibilité des hosts dans l'inventaire Ansible.
* '''OK''' Stocker l'inventaire localement au projet.
* Ajouter des tags aux items de l'inventaire pour cibler les déploiements dans les playbooks si besoin.
* Trouver le moyen d'appliquer un playbook par host plutôt qu'en hosts: all, plutôt que de faire des playbooks par machine ou par groupe.
* '''OK BOUCLE NATIVE DANS LE MODULE APT''' Playbook packages => faire 1 boucle sur les briques de PHP pour installer tout PHP en 1 seule tâche.
* Tester l'ajout d'un fichier d'inclus dans /etc/sudoers.d/ plutôt qu'un ajout de ligne dans /etc/sudoers pour les users privilégiés
* '''INUTILE, FAIT VIA INVENTAIRE''' Voir si la mise en place du lien symbolique pour python peut se faire via Cloud Init (cf documentation terraform).
 
== Terraform ==
 
* Stockage des états terraform pour permettre le partage avec un autre admin (ex: bucket S3).
* '''OK VARIABLE D'ENV''' Crédentiels Terraform à passer en [https://registry.terraform.io/providers/scaleway/scaleway/latest/docs variable d'environnement] pour ne plus les écrire explicitement dans le code Terraform.
* Evaluer l'utilité des [https://registry.terraform.io/providers/scaleway/scaleway/latest/docs/data-sources/account_ssh_key datas sources ssh key].
* Variabiliser les environnements (Jules, Denz, Test) pour ne pas dupliquer le code Terraform à chaque nouvelle machine?
* Ajouter des règles Terraform Security Group en sortie pour permettre l'envoi de mails via Gmail.
 
== Applis web ==
 
* migration finale des données + bascule DNS.
* sur bascule DNS OK, générer les certifs LE.
* configuration SSL des vhosts.
* automatiser le renew des certifs LE.
* upgrade mediawiki.
 
== Admin ==


* configurer postfix sur au moins denz selon [[POSTFIX - Configurer postfix pour relayer en SASL]].
Une fois WSL installé, vous pouvez ensuite [[WSL - Packages utiles|procéder à l'installation des packages essentiels]].
* désactiver root login.
* créer un storage object (S3?) via TF.
* créer 1 playbook pour:
** dump des bases.
** copie des dumps vers le storage object.


[[Category:Journal]]
[[Category:Howto]]
[[Category:Linux]]
[[Category:Systeme]]
[[Category:Windows]]
[[Category:WSL]]

Version du 2 novembre 2021 à 13:55

Introduction

Cet article traite des différentes méthodes disponibles pour l'installation de Windows Subsystem for Linux (WSL) sur un poste Windows (10).

Les guides d'installation Microsoft servent de référence, l'objectif est de mieux identifier les méthodes alternatives.

Tips PowerShell utile

Informations du système

Pour déterminer les informations de son système (architecture processeur, version de build Windows, etc), vous pouvez procéder de 2 façons:

  • via les paramètres => Système => A propos de.
  • via la commande PowerShell suivante:
    systeminfo

Ex:

PS C:\Users\j.pedrono> systeminfo

Nom de l’hôte:                              901180281M
Nom du système d’exploitation:              Microsoft Windows 10 Professionnel
Version du système:                         10.0.19042 N/A version 19042
Fabricant du système d’exploitation:        Microsoft Corporation
Configuration du système d’exploitation:    Station de travail membre
Type de version du système d’exploitation:  Multiprocessor Free
Propriétaire enregistré:                    XXXXXXX
Organisation enregistrée:                   XXXXXXX
Identificateur de produit:                  XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX
Date d’installation originale:              01/09/2021, 09:55:49
Heure de démarrage du système:              08/09/2021, 14:04:42
Fabricant du système:                       HP
Modèle du système:                          HP EliteBook 840r G4
Type du système:                            x64-based PC
Processeur(s):                              1 processeur(s) installé(s).
                                            [01] : Intel64 Family 6 Model 142 Stepping 9 GenuineIntel ~2511 MHz
Version du BIOS:                            HP Q80 Ver. 01.14.01, 16/10/2020
Répertoire système:                         C:\WINDOWS\system32
Périphérique d’amorçage:                    \Device\HarddiskVolume5
Option régionale du système:                fr;Français (France)
Paramètres régionaux d’entrée:              fr;Français (France)
Fuseau horaire:                             (UTC+01:00) Bruxelles, Copenhague, Madrid, Paris
Mémoire physique totale:                    12 131 Mo
Mémoire physique disponible:                6 127 Mo
Mémoire virtuelle : taille maximale:        14 563 Mo
Mémoire virtuelle : disponible:             7 349 Mo
Mémoire virtuelle : en cours d’utilisation: 7 214 Mo
Emplacements des fichiers d’échange:        C:\pagefile.sys
Domaine:                                    directory.XXXXXXX.com
Serveur d’ouverture de session:             \\XXXXXXX
Correctif(s):                               9 Corrections installées.
                                            [01]: KB5004331
                                            [02]: KB4562830
                                            [03]: KB4570334
                                            [04]: KB4577266
                                            [05]: KB4577586
                                            [06]: KB4589212
                                            [07]: KB4598481
                                            [08]: KB5005033
                                            [09]: KB5005260
Carte(s) réseau:                            3 carte(s) réseau installée(s).
                                            [01]: Intel(R) Ethernet Connection (4) I219-V
                                                  Nom de la connexion : Ethernet
                                                  État :                Support déconnecté
                                            [02]: Intel(R) Dual Band Wireless-AC 8265
                                                  Nom de la connexion : Wi-Fi
                                                  DHCP activé :         Oui
                                                  Serveur DHCP :        XXXXXXX
                                                  Adresse(s) IP
                                                  [01]: XXXXXXX
                                                  [02]: XXXXXXX
                                            [03]: Bluetooth Device (Personal Area Network)
                                                  Nom de la connexion : Connexion réseau Bluetooth
                                                  État :                Support déconnecté
Configuration requise pour Hyper-V:         Un hyperviseur a été détecté. Les fonctionnalités nécessaires à Hyper-V ne seront pas affichées.

Information de version WSL par distribution Linux

wsl --list --verbose

ou

wsl -l -v

Ex:

PS C:\Users\j.pedrono> wsl -l -v
  NAME      STATE           VERSION
* Debian    Running         1

Changer de version WSL par distribution Linux

wsl --set-version <distribution name> <versionNumber>

Installation de WSL

Installation standard

Cf cette documentation Microsoft sur le sujet.

  • Si vous avez accès au Windows Store sur votre poste Windows, suivez cette méthode, considérée comme la plus simple.
  • Une technique équivalente en ligne de commande PowerShell:
    wsl --install
  • NB: cette méthode requiert de faire partie du programme Windows Insider.

Sans accès au Windows Store (App)

Sans accès à Windows Store, l'installation manuelle est possible (cf le lien du paragraphe "installation standard"):

Les étapes en résumé sont:

  • activation de WSL dans une console PowerShell en tant qu'administrateur (du poste):
    dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
  • OPTIONNEL WSL2: vérification des pré requis pour l'utilisation de WSL 2 (au lieu de WSL 1) => cette feature nécessite un certain niveau de build Windows en fonction de l'architecture.
  • OPTIONNEL WSL2: activation de la fonctionnalité Virtual Machine dans une console PowerShell en tant qu'administrateur (du poste):
    dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
    (cette action nécessite ensuite un reboot).
  • OPTIONNEL WSL2: téléchargement et installation du Linux kernel update package. L'installation nécessite une élévation de privilège.
  • OPTIONNEL WSL2: déclarer WSL 2 comme version par défaut. Dans une fenêtre PowerShell:
    wsl --set-default-version 2
    . NB: ce n'est que la version par défaut, il est ensuite possible de sélectionner une version de WSL par distribution Linux installée sur le système.
  • Télécharger depuis le site Microsoft la distribution Linux qui vous intéresse (dans mon cas, Debian).

Sans accès au Windows Store (y compris sites de téléchargement Microsoft)

Si comme moi, pour une raison non encore identifiée liée à la sécurisation du poste Windows ou du réseau d'entreprise, vous ne pouvez pas télécharger les distributions Linux en cliquant sur Obtenir (ou Get) sur par exemple ce lien, il existe encore des méthodes d'installation alternatives: cf cette documentation d'installation manuelle.

Les étapes:

  • Déterminer le nom de sa distribution via les URLs de téléchargement.
  • Téléchargement d'une distribution, via une commande PowerShell:
    Invoke-WebRequest -Uri https://aka.ms/wsl-ubuntu-1604 -OutFile Ubuntu.appx -UseBasicParsing
  • Exemple pour Debian:
    Invoke-WebRequest -Uri https://aka.ms/wsl-debian-gnulinux -OutFile Debian.appx -UseBasicParsing
  • Installer le package, via une commande PowerShell:
    Add-AppxPackage .\Ubuntu.appx
  • Info utile: le package est téléchargé en principe dans
    C:\Windows\System32\

Quel que soit le mode d'installation

Ajout de Windows Terminal

Il y a de nombreux intérêts à l'installation de Windows Terminal en complément de WSL:

  • Cet outil permet notamment de faire cohabiter de nombreuses sessions en onglets au sein d'une seule fenêtre.
  • Il permet de lancer de nombreux terminaux: terminal PowerShell, l'intégralité des distributions Linux installées sur WSL, une console Azure PowerShell...

Cf cette partie de la documentation officielle Microsoft.

Cf cette documentation spécifique pour installer la version Preview.

Avec le Windows Store

Installation directe avec le Windows Store, ou en lançant le téléchargement depuis la documentation d'installation Microsoft.

Sans le Windows Store

Sans accès au Windows Store, il existe un dépôt Github pour la publication des versions successives de Windows Terminal.

NB: la contrainte dans ce cas est qu'il faut gérer soi même les mises à jour du Windows Terminal.

Vous téléchargez un fichier dont l'extension est msibundle: cf cette documentation spécifique pour l'installation.

En résumé:

Add-AppxPackage Microsoft.WindowsTerminal_<versionNumber>.msixbundle

Exemple:

Add-AppxPackage .\Microsoft.WindowsTerminalPreview_1.11.2421.0_8wekyb3d8bbwe.msixbundle

Diagnostiquer les problèmes d'installation ou de fonctionnement de WSL sur votre système

Microsoft met à disposition ce guide de troubleshooting assez complet.

Problème pour utiliser la commande ping

A l'installation, et fonction de la version de votre build Windows et de WSL, vous pouvez rencontrer l'erreur suivante lors d'un ping:

jpedrono@901180281M:/mnt/c/Users/j.pedrono$ ping 8.8.8.8
ping: socket: Operation not permitted

D'après les liens suivants, plus ou moins fiable, il s'agit d'un problème de droit de l'utilisateur de votre distribution sur le binaire ping:

Dans mon cas, application de la 1ere méthode puisqu'à priori émise par des personnes au sein de l'équipe MS WSL:

jpedrono@901180281M:/mnt/c/Users/j.pedrono$ getcap /bin/ping
jpedrono@901180281M:/mnt/c/Users/j.pedrono$ sudo setcap cap_net_raw+p /bin/ping
[sudo] password for jpedrono:
jpedrono@901180281M:/mnt/c/Users/j.pedrono$ getcap /bin/ping
/bin/ping = cap_net_raw+p
jpedrono@901180281M:/mnt/c/Users/j.pedrono$ ping 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=112 time=10.7 ms
^C
--- 8.8.8.8 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 10.728/10.728/10.728/0.000 ms

Une fois votre setup terminé...

Une fois WSL installé, vous pouvez ensuite procéder à l'installation des packages essentiels.