aboutsummaryrefslogtreecommitdiff
path: root/os_config
diff options
context:
space:
mode:
Diffstat (limited to 'os_config')
-rw-r--r--os_config/README.md15
-rw-r--r--os_config/README.more.md52
-rw-r--r--os_config/cluster_nodes.yml19
-rw-r--r--os_config/group_vars/all/.gitignore1
-rw-r--r--os_config/group_vars/all/vars_file.yml.sample1
-rw-r--r--os_config/production4
-rw-r--r--os_config/roles/common/tasks/main.yml51
-rw-r--r--os_config/roles/consul/files/consul.service10
-rw-r--r--os_config/roles/consul/tasks/main.yml26
-rw-r--r--os_config/roles/consul/templates/consul.json.j230
-rw-r--r--os_config/roles/consul/templates/resolv.conf.j22
-rw-r--r--os_config/roles/consul/vars/.gitignore1
-rw-r--r--os_config/roles/consul/vars/main.yml.sample2
-rw-r--r--os_config/roles/network/files/rules.v612
-rw-r--r--os_config/roles/network/tasks/main.yml11
-rw-r--r--os_config/roles/network/templates/rules.v4.j236
-rw-r--r--os_config/roles/nomad/files/nomad.service15
-rw-r--r--os_config/roles/nomad/tasks/main.yml23
-rw-r--r--os_config/roles/nomad/templates/nomad.hcl.j234
-rw-r--r--os_config/roles/storage/handlers/main.yml3
-rw-r--r--os_config/roles/storage/tasks/main.yml72
-rw-r--r--os_config/roles/users/files/alex-key1.pub1
-rw-r--r--os_config/roles/users/files/alex-key2.pub1
-rw-r--r--os_config/roles/users/files/florian-key1.pub1
-rw-r--r--os_config/roles/users/files/florian-key2.pub1
-rw-r--r--os_config/roles/users/files/maximilien-key1.pub1
-rw-r--r--os_config/roles/users/files/quentin-key1.pub1
-rw-r--r--os_config/roles/users/files/quentin-key2.pub1
-rw-r--r--os_config/roles/users/tasks/main.yml39
-rw-r--r--os_config/roles/users/vars/main.yml30
-rw-r--r--os_config/site.yml2
31 files changed, 498 insertions, 0 deletions
diff --git a/os_config/README.md b/os_config/README.md
new file mode 100644
index 0000000..db8d960
--- /dev/null
+++ b/os_config/README.md
@@ -0,0 +1,15 @@
+# ANSIBLE
+
+## How to proceed
+
+For each machine, **one by one** do:
+ - Check that cluster is healthy
+ - `sudo gluster peer status`
+ - `sudo gluster volume status all` (check Online Col, only `Y` must appear)
+ - Check that Nomad is healthy
+ - Check that Consul is healthy
+ - Check that Postgres is healthy
+ - Run `ansible-playbook -i production --limit <machine> site.yml`
+ - Reboot
+ - Check that cluster is healthy
+
diff --git a/os_config/README.more.md b/os_config/README.more.md
new file mode 100644
index 0000000..0d0c607
--- /dev/null
+++ b/os_config/README.more.md
@@ -0,0 +1,52 @@
+
+## Provisionning
+
+ 1. Need a public IP address
+ 2. Deploy Debian sid/buster
+ 3. Add a DNS entry like xxxx.machine.deuxfleurs.fr A 0.0.0.0 in Cloudflare + Havelock
+ 4. Setup the fqdn in /etc/hosts (127.0.1.1 xxxx.machine.deuxfleurs.fr)
+ 5. Switch the SSH port to the port 110
+ 6. Add the server to the ./production file
+ 7. Reboot machine
+ 8. Deploy Ansible
+ 9. Check that everything works as intended
+ 10. Update NS 1.cluster.deuxfleurs.fr
+
+## Useful commands
+
+Show every variables collected by Ansible for a given host:
+
+```
+ansible -i production villequin.machine.deuxfleurs.fr -m setup
+```
+
+Run playbook for only one host:
+
+```
+ansible-playbook -i production --limit villequin.machine.deuxfleurs.fr site.yml
+```
+
+Dump hostvars:
+
+```
+ansible -m debug villequin.machine.deuxfleurs.fr -i ./production -a "var=hostvars"
+```
+
+Deploy only one tag:
+
+```
+ansible-playbook -i production site.yml --tags "container"
+```
+
+Redeploy everything:
+
+```
+ansible-playbook -i production site.yml
+```
+
+Upgrade packages and force overwirte to fix bad packing done by GlusterFS:
+
+```
+apt-get -o Dpkg::Options::="--force-overwrite" dist-upgrade -y
+```
+
diff --git a/os_config/cluster_nodes.yml b/os_config/cluster_nodes.yml
new file mode 100644
index 0000000..ea58630
--- /dev/null
+++ b/os_config/cluster_nodes.yml
@@ -0,0 +1,19 @@
+---
+
+- hosts: cluster_nodes
+ serial: 1
+ roles:
+ - role: common
+ tags: base
+ - role: users
+ tags: account
+ - role: consul
+ tags: kv
+ - role: nomad
+ tags: orchestrator
+ - role: network
+ tags: net
+
+# UNSAFE!! This section configures glusterfs. Once done, don't run it ever again as it may break stuff.
+# - role: storage
+# tags: sto
diff --git a/os_config/group_vars/all/.gitignore b/os_config/group_vars/all/.gitignore
new file mode 100644
index 0000000..9271182
--- /dev/null
+++ b/os_config/group_vars/all/.gitignore
@@ -0,0 +1 @@
+vars_file.yml
diff --git a/os_config/group_vars/all/vars_file.yml.sample b/os_config/group_vars/all/vars_file.yml.sample
new file mode 100644
index 0000000..191f35c
--- /dev/null
+++ b/os_config/group_vars/all/vars_file.yml.sample
@@ -0,0 +1 @@
+consul_gossip_encrypt: 'xxx'
diff --git a/os_config/production b/os_config/production
new file mode 100644
index 0000000..c8f08f2
--- /dev/null
+++ b/os_config/production
@@ -0,0 +1,4 @@
+[cluster_nodes]
+veterini ansible_host=fbx-rennes2.machine.deuxfleurs.fr ansible_port=110 ansible_user=root public_ip=192.168.1.2 private_ip=192.168.1.2 interface=eno1 dns_server=80.67.169.40
+silicareux ansible_host=fbx-rennes2.machine.deuxfleurs.fr ansible_port=111 ansible_user=root public_ip=192.168.1.3 private_ip=192.168.1.3 interface=eno1 dns_server=80.67.169.40
+wonse ansible_host=fbx-rennes2.machine.deuxfleurs.fr ansible_port=112 ansible_user=root public_ip=192.168.1.4 private_ip=192.168.1.4 interface=eno1 dns_server=80.67.169.40
diff --git a/os_config/roles/common/tasks/main.yml b/os_config/roles/common/tasks/main.yml
new file mode 100644
index 0000000..b4d00bb
--- /dev/null
+++ b/os_config/roles/common/tasks/main.yml
@@ -0,0 +1,51 @@
+- name: "Check that host runs Debian buster/sid on armv7l or x86_64"
+ assert:
+ that:
+ - "ansible_architecture == 'aarch64' or ansible_architecture == 'armv7l' or ansible_architecture == 'x86_64'"
+ - "ansible_os_family == 'Debian'"
+
+- name: "Upgrade system"
+ apt:
+ upgrade: dist # Should we do a full uprade instead of a dist one?
+ update_cache: yes
+ cache_valid_time: 3600
+ autoclean: yes
+ autoremove: yes
+
+- name: "Install base tools"
+ apt:
+ name:
+ - vim
+ - htop
+ - screen
+ - iptables
+ - iptables-persistent
+ - nftables
+ - iproute2
+ - curl
+ - iputils-ping
+ - dnsutils
+ - bmon
+ - iftop
+ - iotop
+ - docker.io
+ - unzip
+ - tar
+ - tcpdump
+ - less
+ - parted
+ - btrfs-tools
+ - libnss-resolve
+ - net-tools
+ - strace
+ - sudo
+ state: present
+
+- name: "Passwordless sudo"
+ lineinfile:
+ path: /etc/sudoers
+ state: present
+ regexp: '^%sudo'
+ line: '%sudo ALL=(ALL) NOPASSWD: ALL'
+ validate: 'visudo -cf %s'
+
diff --git a/os_config/roles/consul/files/consul.service b/os_config/roles/consul/files/consul.service
new file mode 100644
index 0000000..ffaa2a3
--- /dev/null
+++ b/os_config/roles/consul/files/consul.service
@@ -0,0 +1,10 @@
+[Unit]
+Description=Consul
+After=network-online.target
+Wants=network-online.target
+
+[Service]
+ExecStart=/usr/local/bin/consul agent -config-dir=/etc/consul
+
+[Install]
+WantedBy=multi-user.target
diff --git a/os_config/roles/consul/tasks/main.yml b/os_config/roles/consul/tasks/main.yml
new file mode 100644
index 0000000..2b77080
--- /dev/null
+++ b/os_config/roles/consul/tasks/main.yml
@@ -0,0 +1,26 @@
+- name: "Set consul version"
+ set_fact:
+ consul_version: 1.8.0
+
+- name: "Download and install Consul for x86_64"
+ unarchive:
+ src: "https://releases.hashicorp.com/consul/{{ consul_version }}/consul_{{ consul_version }}_linux_amd64.zip"
+ dest: /usr/local/bin
+ remote_src: yes
+ when:
+ - "ansible_architecture == 'x86_64'"
+
+- name: "Create consul configuration directory"
+ file: path=/etc/consul/ state=directory
+
+- name: "Deploy consul configuration"
+ template: src=consul.json.j2 dest=/etc/consul/consul.json
+
+- name: "Deploy consul systemd service"
+ copy: src=consul.service dest=/etc/systemd/system/consul.service
+
+- name: "Enable consul systemd service at boot"
+ service: name=consul state=started enabled=yes daemon_reload=yes
+
+- name: "Deploy resolv.conf to use Consul"
+ template: src=resolv.conf.j2 dest=/etc/resolv.conf
diff --git a/os_config/roles/consul/templates/consul.json.j2 b/os_config/roles/consul/templates/consul.json.j2
new file mode 100644
index 0000000..b6c86aa
--- /dev/null
+++ b/os_config/roles/consul/templates/consul.json.j2
@@ -0,0 +1,30 @@
+{
+ "data_dir": "/var/lib/consul",
+ "bind_addr": "0.0.0.0",
+ "advertise_addr": "{{ public_ip }}",
+ "addresses": {
+ "dns": "0.0.0.0",
+ "http": "0.0.0.0"
+ },
+ "retry_join": [
+ {% for selected_host in groups['cluster_nodes']|reject("sameas", ansible_fqdn) %}{# @FIXME: Reject doesn't work #}
+ "{{ hostvars[selected_host]['private_ip'] }}" {{ "," if not loop.last else "" }}
+ {% endfor %}
+ ],
+ "bootstrap_expect": 3,
+ "server": true,
+ "ui": true,
+ "ports": {
+ "dns": 53
+ },
+ "recursors": [
+ "{{ dns_server }}"
+ ],
+ "encrypt": "{{ consul_gossip_encrypt }}",
+ "domain": "2.cluster.deuxfleurs.fr",
+ "performance": {
+ "raft_multiplier": 10,
+ "rpc_hold_timeout": "30s",
+ "leave_drain_time": "30s"
+ }
+}
diff --git a/os_config/roles/consul/templates/resolv.conf.j2 b/os_config/roles/consul/templates/resolv.conf.j2
new file mode 100644
index 0000000..2404034
--- /dev/null
+++ b/os_config/roles/consul/templates/resolv.conf.j2
@@ -0,0 +1,2 @@
+nameserver {{ private_ip }}
+nameserver {{ dns_server }}
diff --git a/os_config/roles/consul/vars/.gitignore b/os_config/roles/consul/vars/.gitignore
new file mode 100644
index 0000000..ff5c0bd
--- /dev/null
+++ b/os_config/roles/consul/vars/.gitignore
@@ -0,0 +1 @@
+main.yml
diff --git a/os_config/roles/consul/vars/main.yml.sample b/os_config/roles/consul/vars/main.yml.sample
new file mode 100644
index 0000000..9c44126
--- /dev/null
+++ b/os_config/roles/consul/vars/main.yml.sample
@@ -0,0 +1,2 @@
+---
+consul_gossip_encrypt: "<secret>"
diff --git a/os_config/roles/network/files/rules.v6 b/os_config/roles/network/files/rules.v6
new file mode 100644
index 0000000..17ff71c
--- /dev/null
+++ b/os_config/roles/network/files/rules.v6
@@ -0,0 +1,12 @@
+# WARNING!! When rules.{v4,v6} are changed, the whole iptables configuration is reloaded.
+# This creates issues with Docker, which injects its own configuration in iptables when it starts.
+# In practice, most (all?) containers will break if rules.{v4,v6} are changed,
+# and docker will have to be restared.
+
+
+*filter
+:INPUT DROP [0:0]
+:FORWARD DROP [0:0]
+:OUTPUT ACCEPT [0:0]
+COMMIT
+
diff --git a/os_config/roles/network/tasks/main.yml b/os_config/roles/network/tasks/main.yml
new file mode 100644
index 0000000..1443e0c
--- /dev/null
+++ b/os_config/roles/network/tasks/main.yml
@@ -0,0 +1,11 @@
+- name: "Deploy iptablesv4 configuration"
+ template: src=rules.v4.j2 dest=/etc/iptables/rules.v4
+
+- name: "Deploy iptablesv6 configuration"
+ copy: src=rules.v6 dest=/etc/iptables/rules.v6
+
+- name: "Activate IP forwarding"
+ sysctl:
+ name: net.ipv4.ip_forward
+ value: "1"
+ sysctl_set: yes
diff --git a/os_config/roles/network/templates/rules.v4.j2 b/os_config/roles/network/templates/rules.v4.j2
new file mode 100644
index 0000000..a446139
--- /dev/null
+++ b/os_config/roles/network/templates/rules.v4.j2
@@ -0,0 +1,36 @@
+*filter
+:INPUT DROP [0:0]
+:FORWARD DROP [0:0]
+:OUTPUT ACCEPT [0:0]
+
+# Administration
+-A INPUT -p tcp --dport 22 -j ACCEPT
+
+# Cluster
+-A INPUT -s 192.168.1.254 -j ACCEPT
+-A INPUT -s 82.253.205.190 -j ACCEPT
+{% for selected_host in groups['cluster_nodes'] %}
+-A INPUT -s {{ hostvars[selected_host]['public_ip'] }} -j ACCEPT
+-A INPUT -s {{ hostvars[selected_host]['private_ip'] }} -j ACCEPT
+{% endfor %}
+
+# Local
+-A INPUT -i docker0 -j ACCEPT
+-A INPUT -s 127.0.0.1/8 -j ACCEPT
+-A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
+COMMIT
+
+*nat
+:PREROUTING ACCEPT [0:0]
+:INPUT ACCEPT [0:0]
+:OUTPUT ACCEPT [0:0]
+:POSTROUTING ACCEPT [0:0]
+COMMIT
+
+*mangle
+:PREROUTING ACCEPT [0:0]
+:INPUT ACCEPT [0:0]
+:FORWARD ACCEPT [0:0]
+:OUTPUT ACCEPT [0:0]
+:POSTROUTING ACCEPT [0:0]
+COMMIT
diff --git a/os_config/roles/nomad/files/nomad.service b/os_config/roles/nomad/files/nomad.service
new file mode 100644
index 0000000..50116be
--- /dev/null
+++ b/os_config/roles/nomad/files/nomad.service
@@ -0,0 +1,15 @@
+[Unit]
+Description=Nomad
+After=network-online.target
+After=glusterd.service
+After=consul.service
+Wants=network-online.target
+Wants=glusterd.service
+Wants=consul.service
+
+[Service]
+ExecStart=/usr/local/bin/nomad agent -config /etc/nomad
+
+[Install]
+WantedBy=multi-user.target
+
diff --git a/os_config/roles/nomad/tasks/main.yml b/os_config/roles/nomad/tasks/main.yml
new file mode 100644
index 0000000..7c73362
--- /dev/null
+++ b/os_config/roles/nomad/tasks/main.yml
@@ -0,0 +1,23 @@
+- name: "Set nomad version"
+ set_fact:
+ nomad_version: 0.12.0-beta2
+
+- name: "Download and install Nomad for x86_64"
+ unarchive:
+ src: "https://releases.hashicorp.com/nomad/{{ nomad_version }}/nomad_{{ nomad_version }}_linux_amd64.zip"
+ dest: /usr/local/bin
+ remote_src: yes
+ when:
+ - "ansible_architecture == 'x86_64'"
+
+- name: "Create Nomad configuration directory"
+ file: path=/etc/nomad/ state=directory
+
+- name: "Deploy Nomad configuration"
+ template: src=nomad.hcl.j2 dest=/etc/nomad/nomad.hcl
+
+- name: "Deploy Nomad systemd service"
+ copy: src=nomad.service dest=/etc/systemd/system/nomad.service
+
+- name: "Enable Nomad systemd service at boot"
+ service: name=nomad state=started enabled=yes daemon_reload=yes
diff --git a/os_config/roles/nomad/templates/nomad.hcl.j2 b/os_config/roles/nomad/templates/nomad.hcl.j2
new file mode 100644
index 0000000..b0be6a8
--- /dev/null
+++ b/os_config/roles/nomad/templates/nomad.hcl.j2
@@ -0,0 +1,34 @@
+addresses {
+ http = "0.0.0.0"
+ rpc = "0.0.0.0"
+ serf = "0.0.0.0"
+}
+
+advertise {
+ http = "{{ public_ip }}"
+ rpc = "{{ public_ip }}"
+ serf = "{{ public_ip }}"
+}
+
+data_dir = "/var/lib/nomad"
+
+server {
+ enabled = true
+ bootstrap_expect = 3
+}
+
+consul {
+ address="127.0.0.1:8500"
+}
+
+client {
+ enabled = true
+ #cpu_total_compute = 4000
+ servers = ["127.0.0.1:4648"]
+ network_interface = "{{ interface }}"
+ options {
+ docker.privileged.enabled = "true"
+ docker.volumes.enabled = "true"
+ }
+}
+
diff --git a/os_config/roles/storage/handlers/main.yml b/os_config/roles/storage/handlers/main.yml
new file mode 100644
index 0000000..a395c93
--- /dev/null
+++ b/os_config/roles/storage/handlers/main.yml
@@ -0,0 +1,3 @@
+---
+- name: umount gluster
+ shell: umount --force --lazy /mnt/glusterfs ; true
diff --git a/os_config/roles/storage/tasks/main.yml b/os_config/roles/storage/tasks/main.yml
new file mode 100644
index 0000000..a1f2d8f
--- /dev/null
+++ b/os_config/roles/storage/tasks/main.yml
@@ -0,0 +1,72 @@
+- name: "Add GlusterFS Repo Key"
+ apt_key:
+ url: https://download.gluster.org/pub/gluster/glusterfs/5/rsa.pub
+ state: present
+
+- name: "Add GlusterFS official repository"
+ apt_repository:
+ repo: "deb [arch=amd64] https://download.gluster.org/pub/gluster/glusterfs/5/LATEST/Debian/buster/amd64/apt buster main"
+ state: present
+ filename: gluster
+
+- name: "Install GlusterFS"
+ apt:
+ name:
+ - glusterfs-server
+ - glusterfs-client
+ state: present
+
+- name: "Ensure Gluster Daemon started and enabled"
+ service:
+ name: glusterd
+ enabled: yes
+ state: started
+
+- name: "Create directory for GlusterFS bricks"
+ file: path=/mnt/storage/glusterfs/brick1 recurse=yes state=directory
+
+- name: "Create GlusterFS volumes"
+ gluster_volume:
+ state: present
+ name: donnees
+ bricks: /mnt/storage/glusterfs/brick1/g1
+ #rebalance: yes
+ redundancies: 1
+ disperses: 3
+ #replicas: 3
+ force: yes
+ options:
+ client.event-threads: "8"
+ server.event-threads: "8"
+ performance.stat-prefetch: "on"
+ nfs.disable: "on"
+ features.cache-invalidation: "on"
+ performance.client-io-threads: "on"
+ config.transport: tcp
+ performance.quick-read: "on"
+ performance.io-cache: "on"
+ nfs.export-volumes: "off"
+ cluster.lookup-optimize: "on"
+
+ cluster: "{% for selected_host in groups['cluster_nodes'] %}{{ hostvars[selected_host]['private_ip'] }}{{ ',' if not loop.last else '' }}{% endfor %}"
+ run_once: true
+
+- name: "Create mountpoint"
+ file: path=/mnt/glusterfs recurse=yes state=directory
+
+- name: "Flush handlers (umount glusterfs and restart ganesha)"
+ meta: flush_handlers
+
+- name: "Add fstab entry"
+ tags: gluster-fstab
+ mount:
+ path: /mnt/glusterfs
+ src: "{{ private_ip }}:/donnees"
+ fstype: glusterfs
+ opts: "defaults,_netdev,noauto,x-systemd.automount"
+ state: present
+
+- name: Mount everything
+ command: mount -a
+ args:
+ warn: no
diff --git a/os_config/roles/users/files/alex-key1.pub b/os_config/roles/users/files/alex-key1.pub
new file mode 100644
index 0000000..93514ab
--- /dev/null
+++ b/os_config/roles/users/files/alex-key1.pub
@@ -0,0 +1 @@
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDIDdVbA9fEdqSr5UJ77NnoIqDTVp8ca5kHExhZYI4ecBExFJfonJllXMBN9KdC4ukxtY8Ug47PcMOfMaTBZQc+e+KpvDWpkBt15Xpem3RCxmMBES79sLL7LgtAdBXc5mNaCX8EOEVixWKdarjvxRyf6py6the51G5muaiMpoj5fae4ZpRGjhGTPefzc7y7zRWBUUZ8pYHW774BIaK6XT9gn3hyHV+Occjl/UODXvodktk55YtnuPi8adXTYEsHrVVz8AkFhx+cr0U/U8vtQnsTrZG+JmgQLqpXVs0RDw5bE1RefEbMuYNKxutYKUe3L+ZJtDe0M0MqOFI8a4F5TxP5 katchup@konata
diff --git a/os_config/roles/users/files/alex-key2.pub b/os_config/roles/users/files/alex-key2.pub
new file mode 100644
index 0000000..1eddcc8
--- /dev/null
+++ b/os_config/roles/users/files/alex-key2.pub
@@ -0,0 +1 @@
+ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJk4tAEhDkLeik9eEHIHMliyckM/gWr/k6fX/CSmayCM katchup@charlotte
diff --git a/os_config/roles/users/files/florian-key1.pub b/os_config/roles/users/files/florian-key1.pub
new file mode 100644
index 0000000..47b5593
--- /dev/null
+++ b/os_config/roles/users/files/florian-key1.pub
@@ -0,0 +1 @@
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC/qOM2BYy3UFycDylioACWrnDwg69AoTNE6Ym9W4WI2R+FXd6A1DDG+NLW2orUfkARcJGYEXkzsd3wjDg0s+FS23QWTP+JTkZbdGzuMAcoNeJBtgsCq6m5Q2kvrQc5RscYBr/OZtx2PUfrGyRE3yiVCj38zOgRLRWY0Iqs97tlH74YP4BG3jQ/MI5zXEptWcXBO86FtISB3QyHPRg5OH0192094X/QcG18GKd2ORxC/ZcwK9GdEbJJHgkxJ0TbsQO3KfNTEFBCiynYpYViBsQZsrdBkw4sHHy5OKEahIexdpUg8EJhpyzLn6pvGSqua/mVxirJazgNgtvLlrUsAuNd4/HoWRSqzh51/4hQJ3BV4Yed/tX0rwlT/ZzIIzpGw+qJF3IVuxdvXIineNAEyjVfLVT6hADyQu52ziHSE0cVmUkWT0R7ZgPku0PRBuSeewJIm8uLM69GU/GeRt+mSNl6xOvtBrY/j6sRHcMROlgSHhJ6YnvmkiYXl0MyrH9YGc8=
diff --git a/os_config/roles/users/files/florian-key2.pub b/os_config/roles/users/files/florian-key2.pub
new file mode 100644
index 0000000..f9935b3
--- /dev/null
+++ b/os_config/roles/users/files/florian-key2.pub
@@ -0,0 +1 @@
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC0OcDsEZdiizsz8UIgOIqOQilnHWq0sOxuu6idOqqLVYLPZEv8owdeC5oIgQj94BcKnRzpe8UHxN13GQdEWsqCim6Zn8G5x1HdZDBC83466x3i6KBkMP0dk+h47tENxKFXBPUbh/2sR8r/lZXEhzCCo7tpVuRZpCc/r8WPbAQpLgDO2D0dR7etwf3ndgObxQU0w7WbN+7NzmaHE+VQLu/pqH0op8jZyebfb26XhZ1JnNrDhp86KYbusagn6wUwp3vaJmK9UyEMi21E5HI0ri51+FP8kaTCUpgIRmgIkKFFWiup5I56K8cpgZHcJ4NY7G3jHJeI3KBlazVMyhDVJ5glI1mV0zgdr7BRGqhn70hjf5vbkzcHbRVaMaGzGENLpTFWnaONB/EbqRghWsiVpV75BYzvxSSM8Yrx8pwKUBtLWU+FjljwuumXNLigLIc/FTxdcLvZudn51+XdJXtCBrBI1H22Q7kYXz7Pi800CDLQ8rUWkW8upQ+zu5fSRH+Ptwc=
diff --git a/os_config/roles/users/files/maximilien-key1.pub b/os_config/roles/users/files/maximilien-key1.pub
new file mode 100644
index 0000000..963b1f9
--- /dev/null
+++ b/os_config/roles/users/files/maximilien-key1.pub
@@ -0,0 +1 @@
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDHMMR6zNzz8NQU80wFquhUCeiXJuGphjP+zNouKbn228GyESu8sfNBwnuZq86vblR11Lz8l2rtCM73GfAKg29qmUWUHRKWvRIYWv2vaUJcCdy0bAxIzcvCvjZX0SpnIKxe9y3Rp0LGO5WLYfw0ZFaavwFZP0Z8w1Kj9/zBmL2X2avbhkaYHi/C1yXhbvESYQysmqLa48EX/TS616MBrgR9zbI9AoTQ9NOHnR14Tve/AP/khcZoBJdm4hTttMbNkEc0wonzdylTDew263SPRs/uoqnQIpUtErdPHqU10Yup8HjXjEyFJsSwcZcM5sZOw5JKckKJwmcd0yjO/x/4/Mk5
diff --git a/os_config/roles/users/files/quentin-key1.pub b/os_config/roles/users/files/quentin-key1.pub
new file mode 100644
index 0000000..f3667e0
--- /dev/null
+++ b/os_config/roles/users/files/quentin-key1.pub
@@ -0,0 +1 @@
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDT1+H08FdUSvdPpPKdcafq4+JRHvFVjfvG5Id97LAoROmFRUb/ZOMTLdNuD7FqvW0Da5CPxIMr8ZxfrFLtpGyuG7qdI030iIRZPlKpBh37epZHaV+l9F4ZwJQMIBO9cuyLPXgsyvM/s7tDtrdK1k7JTf2EVvoirrjSzBaMhAnhi7//to8zvujDtgDZzy6aby75bAaDetlYPBq2brWehtrf9yDDG9WAMYJqp//scje/WmhbRR6eSdim1HaUcWk5+4ZPt8sQJcy8iWxQ4jtgjqTvMOe5v8ZPkxJNBine/ZKoJsv7FzKem00xEH7opzktaGukyEqH0VwOwKhmBiqsX2yN quentin@dufour.io
diff --git a/os_config/roles/users/files/quentin-key2.pub b/os_config/roles/users/files/quentin-key2.pub
new file mode 100644
index 0000000..c1b19fd
--- /dev/null
+++ b/os_config/roles/users/files/quentin-key2.pub
@@ -0,0 +1 @@
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDBu+KUebaWwlugMC5fGbNhHc6IaQDAC6+1vMc4Ww7nVU1rs2nwI7L5qcWxOwNdhFaorZQZy/fJuCWdFbF61RCKGayBWPLZHGPsfqDuggYNEi1Qil1kpeCECfDQNjyMTK058ZBBhOWNMHBjlLWXUlRJDkRBBECY0vo4jRv22SvSaPUCAnkdJ9rbAp/kqb497PTIb2r1l1/ew8YdhINAlpYQFQezZVfkZdTKxt22n0QCjhupqjfh3gfNnbBX0z/iO+RvAOWRIZsjPFLC+jXl+n7cnu2cq1nvST5eHiYfXXeIgIwmeENLKqp+2Twr7PIdv22PnJkh6iR5kx7eTRxkNZdN quentin@deuxfleurs.fr
diff --git a/os_config/roles/users/tasks/main.yml b/os_config/roles/users/tasks/main.yml
new file mode 100644
index 0000000..990a041
--- /dev/null
+++ b/os_config/roles/users/tasks/main.yml
@@ -0,0 +1,39 @@
+- name: Add users in the system
+ user:
+ name: "{{ item.username }}"
+ #groups: docker
+ shell: "{{ item.shell | default('/bin/bash') }}"
+ append: no
+ loop: "{{ active_users
+ | selectattr('is_admin', 'defined')
+ | rejectattr('is_admin')
+ | list
+ | union( active_users
+ | selectattr('is_admin', 'undefined')
+ | list )}}"
+
+- name: Set admin rights
+ user:
+ name: "{{ item.username }}"
+ groups: docker, sudo
+ shell: "{{ item.shell | default('/bin/bash') }}"
+ append: no
+ loop: "{{ active_users
+ | selectattr('is_admin', 'defined')
+ | selectattr('is_admin')
+ | list }}"
+
+# [V How SSH Key works] magic is done by subelements, understand the trick at:
+# https://docs.ansible.com/ansible/latest/user_guide/playbooks_filters.html#subelements-filter
+- name: Add SSH keys
+ authorized_key:
+ user: "{{ item.0.username }}"
+ state: present
+ key: "{{ lookup('file', item.1) }}"
+ loop: "{{ active_users | subelements('ssh_keys', skip_missing=True) }}"
+
+- name: Disable old users
+ user:
+ name: "{{ item }}"
+ state: absent
+ loop: "{{ disabled_users }}"
diff --git a/os_config/roles/users/vars/main.yml b/os_config/roles/users/vars/main.yml
new file mode 100644
index 0000000..5f4df4d
--- /dev/null
+++ b/os_config/roles/users/vars/main.yml
@@ -0,0 +1,30 @@
+---
+active_users:
+ - username: 'quentin'
+ is_admin: true
+ ssh_keys:
+ - 'quentin-key1.pub'
+ - 'quentin-key2.pub'
+
+ - username: 'alex'
+ is_admin: true
+ ssh_keys:
+ - 'alex-key1.pub'
+ - 'alex-key2.pub'
+
+ - username: 'maximilien'
+ is_admin: true
+ ssh_keys:
+ - 'maximilien-key1.pub'
+
+ - username: 'florian'
+ is_admin: false
+ ssh_keys:
+ - 'quentin-key1.pub'
+ #- 'florian-key1.pub'
+ #- 'florian-key2.pub'
+
+disabled_users:
+ - 'john.doe'
+ - 'erwan'
+ - 'valentin'
diff --git a/os_config/site.yml b/os_config/site.yml
new file mode 100644
index 0000000..f66e019
--- /dev/null
+++ b/os_config/site.yml
@@ -0,0 +1,2 @@
+---
+- import_playbook: cluster_nodes.yml