Configuration d'un serveur pour déployer une application Rails à l'aide d'Ansible

Il n'y a pas si longtemps, j'avais besoin d'écrire plusieurs playbooks Ansible pour préparer le serveur au déploiement d'une application Rails. Et, étonnamment, je n’ai pas trouvé de manuel simple étape par étape. Je ne voulais pas copier le playbook de quelqu'un d'autre sans comprendre ce qui se passait, et à la fin, j'ai dû lire la documentation et tout rassembler moi-même. Peut-être puis-je aider quelqu'un à accélérer ce processus à l'aide de cet article.

La première chose à comprendre est qu'ansible vous fournit une interface pratique pour effectuer une liste prédéfinie d'actions sur un ou plusieurs serveurs distants via SSH. Il n'y a pas de magie ici, vous ne pouvez pas installer de plugin et obtenir un déploiement sans temps d'arrêt de votre application avec docker, surveillance et autres avantages prêts à l'emploi. Afin d’écrire un playbook, vous devez savoir exactement ce que vous voulez faire et comment le faire. C'est pourquoi je ne me contente pas des playbooks prêts à l'emploi de GitHub, ou d'articles comme : « Copiez et exécutez, cela fonctionnera ».

De quoi avons-nous besoin?

Comme je l'ai déjà dit, pour écrire un playbook, vous devez savoir ce que vous voulez faire et comment le faire. Décidons de ce dont nous avons besoin. Pour une application Rails, nous aurons besoin de plusieurs packages système : nginx, postgresql (redis, etc). De plus, nous avons besoin d’une version spécifique de Ruby. Il est préférable de l'installer via rbenv (rvm, asdf...). Exécuter tout cela en tant qu'utilisateur root est toujours une mauvaise idée, vous devez donc créer un utilisateur distinct et configurer ses droits. Après cela, vous devez télécharger notre code sur le serveur, copier les configurations pour nginx, postgres, etc. et démarrer tous ces services.

En conséquence, la séquence d'actions est la suivante :

  1. Connectez-vous en tant que root
  2. installer les packages système
  3. créer un nouvel utilisateur, configurer les droits, clé ssh
  4. configurer les packages système (nginx, etc.) et les exécuter
  5. Nous créons un utilisateur dans la base de données (vous pouvez immédiatement créer une base de données)
  6. Connectez-vous en tant que nouvel utilisateur
  7. Installer rbenv et Ruby
  8. Installation du bundler
  9. Téléchargement du code de l'application
  10. Lancement du serveur Puma

De plus, les dernières étapes peuvent être effectuées en utilisant Capistrano, au moins dès la sortie de la boîte, il peut copier le code dans les répertoires de version, changer de version avec un lien symbolique en cas de déploiement réussi, copier les configurations à partir d'un répertoire partagé, redémarrer Puma, etc. Tout cela peut être fait avec Ansible, mais pourquoi ?

Structure du fichier

Ansible a strict structure du fichier pour tous vos fichiers, il est donc préférable de tout conserver dans un répertoire séparé. De plus, peu importe que ce soit dans l'application Rails elle-même ou séparément. Vous pouvez stocker des fichiers dans un référentiel git distinct. Personnellement, j'ai trouvé plus pratique de créer un répertoire ansible dans le répertoire /config de l'application rails et de tout stocker dans un seul référentiel.

Manuel de jeu simple

Playbook est un fichier YML qui, à l'aide d'une syntaxe spéciale, décrit ce qu'Ansible doit faire et comment. Créons le premier playbook qui ne fait rien :

---
- name: Simple playbook
  hosts: all

Ici, nous disons simplement que notre playbook s'appelle Simple Playbook et que son contenu doit être exécuté pour tous les hôtes. Nous pouvons l'enregistrer dans le répertoire /ansible avec le nom playbook.yml et essaie de lancer :

ansible-playbook ./playbook.yml

PLAY [Simple Playbook] ************************************************************************************************************************************
skipping: no hosts matched

Ansible dit qu'il ne connaît aucun hôte correspondant à la liste complète. Ils doivent être répertoriés dans un registre spécial dossier d'inventaire.

Créons-le dans le même répertoire ansible :

123.123.123.123

C'est ainsi que nous spécifions simplement l'hôte (idéalement l'hôte de notre VPS pour les tests, ou vous pouvez enregistrer localhost) et l'enregistrons sous le nom inventory.
Vous pouvez essayer d'exécuter ansible avec un fichier d'inventaire :

ansible-playbook ./playbook.yml -i inventory
PLAY [Simple Playbook] ************************************************************************************************************************************

TASK [Gathering Facts] ************************************************************************************************************************************

PLAY RECAP ************************************************************************************************************************************

Si vous disposez d'un accès SSH à l'hôte spécifié, ansible se connectera et collectera des informations sur le système distant. (TASK par défaut [Gathering Facts]) après quoi il donnera un bref rapport sur l'exécution (PLAY RECAP).

Par défaut, la connexion utilise le nom d'utilisateur sous lequel vous êtes connecté au système. Il ne sera probablement pas sur l'hôte. Dans le fichier playbook, vous pouvez spécifier quel utilisateur utiliser pour vous connecter à l'aide de la directive remote_user. De plus, les informations sur un système distant peuvent souvent vous être inutiles et vous ne devriez pas perdre de temps à les collecter. Cette tâche peut également être désactivée :

---
- name: Simple playbook
  hosts: all
  remote_user: root
  become: true
  gather_facts: no

Essayez à nouveau d'exécuter le playbook et assurez-vous que la connexion fonctionne. (Si vous avez spécifié l'utilisateur root, vous devez également spécifier la directive devenir: true afin d'obtenir des droits élevés. Comme écrit dans la documentation : become set to ‘true’/’yes’ to activate privilege escalation. bien que la raison ne soit pas tout à fait claire).

Peut-être recevrez-vous une erreur causée par le fait qu'ansible ne peut pas déterminer l'interpréteur Python, vous pouvez alors le spécifier manuellement :

ansible_python_interpreter: /usr/bin/python3 

Vous pouvez savoir où vous avez python avec la commande whereis python.

Installation des packages système

La distribution standard d'Ansible comprend de nombreux modules permettant de travailler avec divers packages système, nous n'avons donc pas besoin d'écrire de scripts bash pour quelque raison que ce soit. Nous avons maintenant besoin de l'un de ces modules pour mettre à jour le système et installer les packages système. J'ai Ubuntu Linux sur mon VPS, donc pour installer les packages que j'utilise apt-get и module pour cela. Si vous utilisez un système d'exploitation différent, vous aurez peut-être besoin d'un module différent (rappelez-vous, j'ai dit au début que nous devons savoir à l'avance ce que nous allons faire et comment). Cependant, la syntaxe sera probablement similaire.

Complétons notre playbook avec les premières tâches :

---
- name: Simple playbook
  hosts: all
  remote_user: root
  become: true
  gather_facts: no

  tasks:
    - name: Update system
      apt: update_cache=yes
    - name: Install system dependencies
      apt:
        name: git,nginx,redis,postgresql,postgresql-contrib
        state: present

La tâche est exactement la tâche qu'Ansible effectuera sur les serveurs distants. Nous donnons un nom à la tâche afin de pouvoir suivre son exécution dans le journal. Et nous décrivons, en utilisant la syntaxe d'un module spécifique, ce qu'il doit faire. Dans ce cas apt: update_cache=yes - dit de mettre à jour les packages système à l'aide du module apt. La deuxième commande est un peu plus compliquée. Nous transmettons une liste de packages au module apt et disons qu'ils sont state devrait devenir present, c'est-à-dire que nous disons installer ces packages. De la même manière, nous pouvons leur dire de les supprimer, ou de les mettre à jour en modifiant simplement state. Veuillez noter que pour que Rails fonctionne avec postgresql, nous avons besoin du package postgresql-contrib, que nous installons actuellement. Encore une fois, vous devez le savoir et le faire ; ansible seul ne le fera pas.

Essayez à nouveau d'exécuter le playbook et vérifiez que les packages sont installés.

Création de nouveaux utilisateurs.

Pour travailler avec les utilisateurs, Ansible dispose également d'un module - utilisateur. Ajoutons une tâche supplémentaire (j'ai caché les parties déjà connues du playbook derrière les commentaires afin de ne pas le copier entièrement à chaque fois) :

---
- name: Simple playbook
  # ...
  tasks:
    # ...
    - name: Add a new user
      user:
        name: my_user
        shell: /bin/bash
        password: "{{ 123qweasd | password_hash('sha512') }}"

Nous créons un nouvel utilisateur, définissons un schéma et un mot de passe pour celui-ci. Et puis nous rencontrons plusieurs problèmes. Que se passe-t-il si les noms d'utilisateur doivent être différents pour différents hôtes ? Et stocker le mot de passe en texte clair dans le playbook est une très mauvaise idée. Pour commencer, mettons le nom d'utilisateur et le mot de passe dans des variables, et vers la fin de l'article, je montrerai comment crypter le mot de passe.

---
- name: Simple playbook
  # ...
  tasks:
    # ...
    - name: Add a new user
      user:
        name: "{{ user }}"
        shell: /bin/bash
        password: "{{ user_password | password_hash('sha512') }}"

Les variables sont définies dans les playbooks à l’aide de doubles accolades.

Nous indiquerons les valeurs des variables dans le fichier d'inventaire :

123.123.123.123

[all:vars]
user=my_user
user_password=123qweasd

Veuillez noter la directive [all:vars] - il indique que le prochain bloc de texte est constitué de variables (vars) et qu'elles sont applicables à tous les hôtes (tous).

Le design est également intéressant "{{ user_password | password_hash('sha512') }}". Le fait est qu'Ansible n'installe pas l'utilisateur via user_add comme si vous le feriez manuellement. Et elle enregistre toutes les données directement, c'est pourquoi nous devons également convertir le mot de passe en hachage au préalable, ce que fait cette commande.

Ajoutons notre utilisateur au groupe sudo. Cependant, avant cela, nous devons nous assurer qu’un tel groupe existe, car personne ne fera cela à notre place :

---
- name: Simple playbook
  # ...
  tasks:
    # ...
    - name: Ensure a 'sudo' group
      group:
        name: sudo
        state: present
    - name: Add a new user
      user:
        name: "{{ user }}"
        shell: /bin/bash
        password: "{{ user_password | password_hash('sha512') }}"
        groups: "sudo"

Tout est assez simple, nous disposons également d'un module group pour créer des groupes, avec une syntaxe très similaire à apt. Il suffit ensuite d'enregistrer ce groupe auprès de l'utilisateur (groups: "sudo").
Il est également utile d'ajouter une clé ssh à cet utilisateur afin que nous puissions nous connecter en l'utilisant sans mot de passe :

---
- name: Simple playbook
  # ...
  tasks:
    # ...
    - name: Ensure a 'sudo' group
      group:
      name: sudo
        state: present
    - name: Add a new user
      user:
        name: "{{ user }}"
        shell: /bin/bash
        password: "{{ user_password | password_hash('sha512') }}"
        groups: "sudo"
    - name: Deploy SSH Key
      authorized_key:
        user: "{{ user }}"
        key: "{{ lookup('file', '~/.ssh/id_rsa.pub') }}"
        state: present

Dans ce cas, le design est intéressant "{{ lookup('file', '~/.ssh/id_rsa.pub') }}" — il copie le contenu du fichier id_rsa.pub (votre nom peut être différent), c'est-à-dire la partie publique de la clé ssh et la télécharge dans la liste des clés autorisées pour l'utilisateur sur le serveur.

Les rôles

Les trois tâches de création d'utilisation peuvent facilement être classées en un seul groupe de tâches, et ce serait une bonne idée de stocker ce groupe séparément du playbook principal afin qu'il ne devienne pas trop grand. Pour cela, Ansible a les rôles.
Selon la structure de fichiers indiquée au tout début, les rôles doivent être placés dans un répertoire de rôles distinct, pour chaque rôle il existe un répertoire distinct portant le même nom, à l'intérieur du répertoire des tâches, fichiers, modèles, etc.
Créons une structure de fichiers : ./ansible/roles/user/tasks/main.yml (main est le fichier principal qui sera chargé et exécuté lorsqu'un rôle est connecté au playbook ; d'autres fichiers de rôle peuvent y être connectés). Vous pouvez désormais transférer toutes les tâches liées à l'utilisateur vers ce fichier :

# Create user and add him to groups
- name: Ensure a 'sudo' group
  group:
    name: sudo
    state: present

- name: Add a new user
  user:
    name: "{{ user }}"
    shell: /bin/bash
    password: "{{ user_password | password_hash('sha512') }}"
    groups: "sudo"

- name: Deploy SSH Key
  authorized_key:
    user: "{{ user }}"
    key: "{{ lookup('file', '~/.ssh/id_rsa.pub') }}"
    state: present

Dans le playbook principal, vous devez spécifier d'utiliser le rôle d'utilisateur :

---
- name: Simple playbook
  hosts: all
  remote_user: root
  gather_facts: no

  tasks:
    - name: Update system
      apt: update_cache=yes
    - name: Install system dependencies
      apt:
        name: git,nginx,redis,postgresql,postgresql-contrib
        state: present

  roles:
    - user

De plus, il peut être judicieux de mettre à jour le système avant toute autre tâche ; pour ce faire, vous pouvez renommer le bloc tasks dans lequel ils sont définis dans pre_tasks.

Configuration de nginx

Nous devrions déjà avoir installé Nginx ; nous devons le configurer et l’exécuter. Faisons-le tout de suite dans le rôle. Créons une structure de fichiers :

- ansible
  - roles
    - nginx
      - files
      - tasks
        - main.yml
      - templates

Nous avons maintenant besoin de fichiers et de modèles. La différence entre eux est qu'ansible copie les fichiers directement, tels quels. Et les modèles doivent avoir l'extension j2 et ils peuvent utiliser des valeurs variables en utilisant les mêmes doubles accolades.

Activons nginx dans main.yml déposer. Pour cela nous avons un module systemd :

# Copy nginx configs and start it
- name: enable service nginx and start
  systemd:
    name: nginx
    state: started
    enabled: yes

Ici, nous disons non seulement que nginx doit être démarré (c'est-à-dire que nous le lançons), mais nous disons immédiatement qu'il doit être activé.
Copieons maintenant les fichiers de configuration :

# Copy nginx configs and start it
- name: enable service nginx and start
  systemd:
    name: nginx
    state: started
    enabled: yes

- name: Copy the nginx.conf
  copy:
    src: nginx.conf
    dest: /etc/nginx/nginx.conf
    owner: root
    group: root
    mode: '0644'
    backup: yes

- name: Copy template my_app.conf
  template:
    src: my_app_conf.j2
    dest: /etc/nginx/sites-available/my_app.conf
    owner: root
    group: root
    mode: '0644'

Nous créons le fichier de configuration principal de nginx (vous pouvez le récupérer directement depuis le serveur, ou l'écrire vous-même). Et aussi le fichier de configuration de notre application dans le répertoire sites_available (ce n'est pas nécessaire mais utile). Dans le premier cas, on utilise le module copy pour copier des fichiers (le fichier doit être dans /ansible/roles/nginx/files/nginx.conf). Dans la seconde, nous copions le modèle en remplaçant les valeurs des variables. Le modèle doit être dans /ansible/roles/nginx/templates/my_app.j2). Et cela pourrait ressembler à ceci :

upstream {{ app_name }} {
  server unix:{{ app_path }}/shared/tmp/sockets/puma.sock;
}

server {
  listen 80;
  server_name {{ server_name }} {{ inventory_hostname }};
  root {{ app_path }}/current/public;

  try_files $uri/index.html $uri.html $uri @{{ app_name }};
  ....
}

Faites attention aux inserts {{ app_name }}, {{ app_path }}, {{ server_name }}, {{ inventory_hostname }} — ce sont toutes les variables dont Ansible substituera les valeurs dans le modèle avant de copier. Ceci est utile si vous utilisez un playbook pour différents groupes d'hôtes. Par exemple, nous pouvons ajouter notre fichier d'inventaire :

[production]
123.123.123.123

[staging]
231.231.231.231

[all:vars]
user=my_user
user_password=123qweasd

[production:vars]
server_name=production
app_path=/home/www/my_app
app_name=my_app

[staging:vars]
server_name=staging
app_path=/home/www/my_stage
app_name=my_stage_app

Si nous lançons maintenant notre playbook, il effectuera les tâches spécifiées pour les deux hôtes. Mais en même temps, pour un hôte intermédiaire, les variables seront différentes de celles de production, et pas seulement dans les rôles et les playbooks, mais aussi dans les configurations nginx. {{ inventory_hostname }} n'ont pas besoin d'être précisés dans le fichier d'inventaire - ceci variable ansible spéciale et l'hôte pour lequel le playbook est actuellement en cours d'exécution y est stocké.
Si vous souhaitez avoir un fichier d'inventaire pour plusieurs hôtes, mais ne l'exécuter que pour un seul groupe, cela peut être fait avec la commande suivante :

ansible-playbook -i inventory ./playbook.yml -l "staging"

Une autre option consiste à disposer de fichiers d'inventaire distincts pour différents groupes. Ou vous pouvez combiner les deux approches si vous disposez de nombreux hôtes différents.

Revenons à la configuration de nginx. Après avoir copié les fichiers de configuration, nous devons créer un lien symbolique dans sitest_enabled vers my_app.conf depuis sites_available. Et redémarrez nginx.

... # old code in mail.yml

- name: Create symlink to sites-enabled
  file:
    src: /etc/nginx/sites-available/my_app.conf
    dest: /etc/nginx/sites-enabled/my_app.conf
    state: link

- name: restart nginx
  service:
    name: nginx
    state: restarted

Tout est simple ici - encore une fois des modules ansibles avec une syntaxe assez standard. Mais il y a un point. Cela ne sert à rien de redémarrer nginx à chaque fois. Avez-vous remarqué que nous n'écrivons pas de commandes du type : « fais ceci comme ceci », la syntaxe ressemble plutôt à « ceci devrait avoir cet état ». Et le plus souvent, c’est exactement ainsi que fonctionne ansible. Si le groupe existe déjà ou si le package système est déjà installé, ansible le vérifiera et ignorera la tâche. De plus, les fichiers ne seront pas copiés s'ils correspondent parfaitement à ce qui se trouve déjà sur le serveur. Nous pouvons en profiter et redémarrer nginx uniquement si les fichiers de configuration ont été modifiés. Il existe une directive de registre pour cela :

# Copy nginx configs and start it
- name: enable service nginx and start
  systemd:
    name: nginx
    state: started
    enabled: yes

- name: Copy the nginx.conf
  copy:
    src: nginx.conf
    dest: /etc/nginx/nginx.conf
    owner: root
    group: root
    mode: '0644'
    backup: yes
  register: restart_nginx

- name: Copy template my_app.conf
  template:
    src: my_app_conf.j2
    dest: /etc/nginx/sites-available/my_app.conf
    owner: root
    group: root
    mode: '0644'
  register: restart_nginx

- name: Create symlink to sites-enabled
  file:
    src: /etc/nginx/sites-available/my_app.conf
    dest: /etc/nginx/sites-enabled/my_app.conf
    state: link

- name: restart nginx
  service:
    name: nginx
    state: restarted
  when: restart_nginx.changed

Si l'un des fichiers de configuration change, une copie sera faite et la variable sera enregistrée restart_nginx. Et ce n'est que si cette variable a été enregistrée que le service sera redémarré.

Et bien sûr, vous devez ajouter le rôle nginx au playbook principal.

Configuration de postgresql

Nous devons activer postgresql en utilisant systemd de la même manière qu'avec nginx, et également créer un utilisateur que nous utiliserons pour accéder à la base de données et à la base de données elle-même.
Créons un rôle /ansible/roles/postgresql/tasks/main.yml:

# Create user in postgresql
- name: enable postgresql and start
  systemd:
    name: postgresql
    state: started
    enabled: yes

- name: Create database user
  become_user: postgres
  postgresql_user:
    name: "{{ db_user }}"
    password: "{{ db_password }}"
    role_attr_flags: SUPERUSER

- name: Create database
  become_user: postgres
  postgresql_db:
    name: "{{ db_name }}"
    encoding: UTF-8
    owner: "{{ db_user }}"

Je ne décrirai pas comment ajouter des variables à l'inventaire, cela a déjà été fait plusieurs fois, ainsi que la syntaxe des modules postgresql_db et postgresql_user. Plus d’informations peuvent être trouvées dans la documentation. La directive la plus intéressante ici est become_user: postgres. Le fait est que par défaut, seul l'utilisateur postgres a accès à la base de données postgresql et uniquement localement. Cette directive nous permet d'exécuter des commandes au nom de cet utilisateur (si nous y avons accès, bien sûr).
De plus, vous devrez peut-être ajouter une ligne à pg_hba.conf pour autoriser un nouvel utilisateur à accéder à la base de données. Cela peut être fait de la même manière que nous avons modifié la configuration de nginx.

Et bien sûr, vous devez ajouter le rôle postgresql au playbook principal.

Installer Ruby via rbenv

Ansible n'a pas de modules pour travailler avec rbenv, mais il est installé en clonant un référentiel git. Par conséquent, ce problème devient le plus atypique. Créons-lui un rôle /ansible/roles/ruby_rbenv/main.yml et commençons à le remplir :

# Install rbenv and ruby
- name: Install rbenv
  become_user: "{{ user }}"
  git: repo=https://github.com/rbenv/rbenv.git dest=~/.rbenv

Nous utilisons à nouveau la directive devenir_user pour travailler sous l'utilisateur que nous avons créé à ces fins. Puisque rbenv est installé dans son répertoire personnel, et non globalement. Et nous utilisons également le module git pour cloner le référentiel, en spécifiant repo et dest.

Ensuite, nous devons enregistrer rbenv init dans bashrc et y ajouter rbenv à PATH. Pour cela nous avons le module lineinfile :

- name: Add rbenv to PATH
  become_user: "{{ user }}"
  lineinfile:
    path: ~/.bashrc
    state: present
    line: 'export PATH="${HOME}/.rbenv/bin:${PATH}"'

- name: Add rbenv init to bashrc
  become_user: "{{ user }}"
  lineinfile:
    path: ~/.bashrc
    state: present
    line: 'eval "$(rbenv init -)"'

Ensuite, vous devez installer ruby_build :

- name: Install ruby-build
  become_user: "{{ user }}"
  git: repo=https://github.com/rbenv/ruby-build.git dest=~/.rbenv/plugins/ruby-build

Et enfin, installez Ruby. Cela se fait via rbenv, c'est-à-dire simplement avec la commande bash :

- name: Install ruby
  become_user: "{{ user }}"
  shell: |
    export PATH="${HOME}/.rbenv/bin:${PATH}"
    eval "$(rbenv init -)"
    rbenv install {{ ruby_version }}
  args:
    executable: /bin/bash

Nous disons quelle commande exécuter et avec quoi. Cependant, nous constatons ici qu'ansible n'exécute pas le code contenu dans bashrc avant d'exécuter les commandes. Cela signifie que rbenv devra être défini directement dans le même script.

Le problème suivant est dû au fait que la commande shell n'a pas d'état d'un point de vue ansible. Autrement dit, il n'y aura pas de vérification automatique si cette version de Ruby est installée ou non. Nous pouvons le faire nous-mêmes :

- name: Install ruby
  become_user: "{{ user }}"
  shell: |
    export PATH="${HOME}/.rbenv/bin:${PATH}"
    eval "$(rbenv init -)"
    if ! rbenv versions | grep -q {{ ruby_version }}
      then rbenv install {{ ruby_version }} && rbenv global {{ ruby_version }}
    fi
  args:
    executable: /bin/bash

Il ne reste plus qu'à installer le bundler :

- name: Install bundler
  become_user: "{{ user }}"
  shell: |
    export PATH="${HOME}/.rbenv/bin:${PATH}"
    eval "$(rbenv init -)"
    gem install bundler

Et encore une fois, ajoutez notre rôle ruby_rbenv au playbook principal.

Fichiers partagés.

En général, la configuration peut être effectuée ici. Ensuite, il ne reste plus qu'à exécuter Capistrano et il copiera lui-même le code, créera les répertoires nécessaires et lancera l'application (si tout est correctement configuré). Cependant, Capistrano nécessite souvent des fichiers de configuration supplémentaires, tels que database.yml ou .env Ils peuvent être copiés tout comme les fichiers et les modèles pour nginx. Il n'y a qu'une seule subtilité. Avant de copier des fichiers, vous devez créer une structure de répertoires pour eux, quelque chose comme ceci :

# Copy shared files for deploy
- name: Ensure shared dir
  become_user: "{{ user }}"
  file:
    path: "{{ app_path }}/shared/config"
    state: directory

nous spécifions un seul répertoire et ansible créera automatiquement des répertoires parents si nécessaire.

Voûte Ansible

Nous avons déjà constaté que les variables peuvent contenir des données secrètes comme le mot de passe de l’utilisateur. Si vous avez créé .env dossier de demande, et database.yml alors il doit y avoir encore plus de données critiques de ce type. Ce serait bien de les cacher des regards indiscrets. A cet effet, il est utilisé coffre-fort ansible.

Créons un fichier pour les variables /ansible/vars/all.yml (ici vous pouvez créer différents fichiers pour différents groupes d'hôtes, tout comme dans le fichier d'inventaire : production.yml, staging.yml, etc).
Toutes les variables qui doivent être chiffrées doivent être transférées vers ce fichier en utilisant la syntaxe yml standard :

# System vars
user_password: 123qweasd
db_password: 123qweasd

# ENV vars
aws_access_key_id: xxxxx
aws_secret_access_key: xxxxxx
aws_bucket: bucket_name
rails_secret_key_base: very_secret_key_base

Après quoi ce fichier peut être chiffré avec la commande :

ansible-vault encrypt ./vars/all.yml

Naturellement, lors du cryptage, vous devrez définir un mot de passe pour le décryptage. Vous pouvez voir ce qu’il y aura dans le fichier après avoir appelé cette commande.

Au moyen de ansible-vault decrypt le fichier peut être déchiffré, modifié puis crypté à nouveau.

Vous n'avez pas besoin de décrypter le fichier pour fonctionner. Vous le stockez crypté et exécutez le playbook avec l'argument --ask-vault-pass. Ansible demandera le mot de passe, récupérera les variables et exécutera les tâches. Toutes les données resteront cryptées.

La commande complète pour plusieurs groupes d'hôtes et Ansible Vault ressemblera à ceci :

ansible-playbook -i inventory ./playbook.yml -l "staging" --ask-vault-pass

Mais je ne vous donnerai pas le texte intégral des playbooks et des rôles, écrivez-le vous-même. Parce qu'ansible est comme ça : si vous ne comprenez pas ce qui doit être fait, alors il ne le fera pas pour vous.

Source: habr.com

Ajouter un commentaire