Compare commits
8 Commits
6e67dadf27
...
eaec41da1e
Author | SHA1 | Date | |
---|---|---|---|
eaec41da1e | |||
2c53e26bbb | |||
57c778c543 | |||
de3435cf31 | |||
8837606dc1 | |||
e8396b0e0f | |||
73e1ce4973 | |||
3eeb9baa57 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -2,6 +2,7 @@
|
|||||||
*.retry
|
*.retry
|
||||||
ansible/hosts.yml
|
ansible/hosts.yml
|
||||||
ansible/group_vars/all/*
|
ansible/group_vars/all/*
|
||||||
|
ansible/roles/10-include-50-miniconda/defaults/*
|
||||||
ansible/roles/20-common-20-ssh/defaults/*
|
ansible/roles/20-common-20-ssh/defaults/*
|
||||||
ansible/roles/20-common-20-ssh/files/root/.ssh/*
|
ansible/roles/20-common-20-ssh/files/root/.ssh/*
|
||||||
!*.example
|
!*.example
|
||||||
|
31
README.md
31
README.md
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
Set up infrastructure for all things e-mail
|
Set up infrastructure for all things e-mail
|
||||||
|
|
||||||
## Prep
|
# Prep
|
||||||
|
|
||||||
On your Ansible controller make sure the `sshpass` binary exists if Ansible has to connect to target machines via SSH username-password authentication instead of SSH key authentication. The binary usually comes with a package of the same name.
|
On your Ansible controller make sure the `sshpass` binary exists if Ansible has to connect to target machines via SSH username-password authentication instead of SSH key authentication. The binary usually comes with a package of the same name.
|
||||||
|
|
||||||
@@ -11,12 +11,12 @@ We're assuming that you're running Ansible as a Python package inside a virtual
|
|||||||
pip install ansible
|
pip install ansible
|
||||||
```
|
```
|
||||||
|
|
||||||
We're also assuming that secrets are stored in a HashiCorp Vault instance to which you have access. These role access Vault via `hvac`, the HashiCorp Vault API client for Python 3.x, see [github.com/hvac/hvac](https://github.com/hvac/hvac) for reference. Install it like so:
|
We're also assuming that secrets are stored in a HashiCorp Vault instance to which you have access. These roles access Vault via `hvac`, the HashiCorp Vault API client for Python 3.x, see [github.com/hvac/hvac](https://github.com/hvac/hvac) for reference. Install it like so:
|
||||||
```
|
```
|
||||||
pip install hvac
|
pip install hvac
|
||||||
```
|
```
|
||||||
|
|
||||||
## Vars
|
# Vars
|
||||||
|
|
||||||
* For default variables copy [ansible/roles/20-common-20-ssh/defaults/main.yml.example](ansible/roles/20-common-20-ssh/defaults/main.yml.example) to a proper `ansible/roles/20-common-20-ssh/defaults/main.yml`, adjust as needed.
|
* For default variables copy [ansible/roles/20-common-20-ssh/defaults/main.yml.example](ansible/roles/20-common-20-ssh/defaults/main.yml.example) to a proper `ansible/roles/20-common-20-ssh/defaults/main.yml`, adjust as needed.
|
||||||
|
|
||||||
@@ -26,7 +26,7 @@ pip install hvac
|
|||||||
|
|
||||||
* In [ansible/roles/20-common-20-ssh/files/root/.ssh](ansible/roles/20-common-20-ssh/files/root/.ssh) copy both [authorized_keys.example](ansible/roles/20-common-20-ssh/files/root/.ssh/authorized_keys.example) and [known_hosts.example](ansible/roles/20-common-20-ssh/files/root/.ssh/known_hosts.example) to proper files. They contain SSH authorized_keys and public SSH host keys you want installed on target machines.
|
* In [ansible/roles/20-common-20-ssh/files/root/.ssh](ansible/roles/20-common-20-ssh/files/root/.ssh) copy both [authorized_keys.example](ansible/roles/20-common-20-ssh/files/root/.ssh/authorized_keys.example) and [known_hosts.example](ansible/roles/20-common-20-ssh/files/root/.ssh/known_hosts.example) to proper files. They contain SSH authorized_keys and public SSH host keys you want installed on target machines.
|
||||||
|
|
||||||
## Vault structure
|
# Vault structure
|
||||||
|
|
||||||
In Vault we're assuming that every host in your inventory has a secret stored that contains at least the following keys:
|
In Vault we're assuming that every host in your inventory has a secret stored that contains at least the following keys:
|
||||||
|
|
||||||
@@ -36,7 +36,7 @@ In Vault we're assuming that every host in your inventory has a secret stored th
|
|||||||
|
|
||||||
For an example server `fully.qualified.domain.name` and example user `root` Vault secrets are located at `name/domain/qualified/fully/os/root/creds`. Per [ansible/group_vars/all/vars.yml.example](ansible/group_vars/all/vars.yml.example) the default secrets engine mount point is `kv` where this playbook expects a kv secrets engine.
|
For an example server `fully.qualified.domain.name` and example user `root` Vault secrets are located at `name/domain/qualified/fully/os/root/creds`. Per [ansible/group_vars/all/vars.yml.example](ansible/group_vars/all/vars.yml.example) the default secrets engine mount point is `kv` where this playbook expects a kv secrets engine.
|
||||||
|
|
||||||
## Run it
|
# Run it
|
||||||
|
|
||||||
On first run execute it like so:
|
On first run execute it like so:
|
||||||
```
|
```
|
||||||
@@ -49,3 +49,24 @@ On subsequent runs like so:
|
|||||||
```
|
```
|
||||||
ansible-playbook --inventory hosts.yml playbook.yml
|
ansible-playbook --inventory hosts.yml playbook.yml
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## first_run
|
||||||
|
|
||||||
|
To make sure a `first_run` correctly runs all regular tasks plus `first_run`-specific tasks [ansible/roles/20-common-20-ssh/tasks/main.yml](ansible/roles/20-common-20-ssh/tasks/main.yml) has its `import_tasks` tagged as `first_run`.
|
||||||
|
|
||||||
|
```
|
||||||
|
- import_tasks: '20-ssh.yml'
|
||||||
|
tags:
|
||||||
|
- 'first_run'
|
||||||
|
```
|
||||||
|
|
||||||
|
As a result all tasks in that import inherit `first_run`. Two of them, however, must only run during `first_run` and never during normal operation. They get:
|
||||||
|
|
||||||
|
```
|
||||||
|
- name: '...'
|
||||||
|
tags:
|
||||||
|
- 'first_run'
|
||||||
|
- 'never'
|
||||||
|
```
|
||||||
|
|
||||||
|
This overrides the single `first_run` inherited tag. Ansible special tag `never` ensures that these particular tasks are _**never**_ executed unless `first_run` is called. Tasks outside of `20-common-20-ssh` role are not tagged with `first_run` at all so are ignored during a `first_run`.
|
||||||
|
@@ -0,0 +1,7 @@
|
|||||||
|
miniconda_install_dir: '/opt/miniconda3'
|
||||||
|
miniconda_bin_dir: '{{ miniconda_install_dir }}/bin'
|
||||||
|
miniconda_installer_dl_dir: '{{ miniconda_install_dir }}/_downloaded-installer'
|
||||||
|
miniconda_dl_uri_base: 'https://repo.anaconda.com/miniconda/'
|
||||||
|
miniconda_dl_uri_file: 'Miniconda3-latest-Linux-x86_64.sh'
|
||||||
|
miniconda_dl_uri: '{{ miniconda_dl_uri_base }}{{ miniconda_dl_uri_file }}'
|
||||||
|
miniconda_dl_local_abs: '{{ miniconda_installer_dl_dir }}/{{ miniconda_dl_uri_file }}'
|
@@ -0,0 +1 @@
|
|||||||
|
auto_activate_base: false
|
@@ -0,0 +1,87 @@
|
|||||||
|
- name: 'Create Miniconda base dir'
|
||||||
|
loop_control:
|
||||||
|
loop_var: 'conda_dir'
|
||||||
|
loop:
|
||||||
|
- { path: '{{ miniconda_install_dir }}', state: 'directory' }
|
||||||
|
- { path: '{{ miniconda_installer_dl_dir }}', state: 'directory' }
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: '{{ conda_dir.path }}'
|
||||||
|
state: '{{ conda_dir.state }}'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
- name: 'Download latest Miniconda installer'
|
||||||
|
ansible.builtin.get_url:
|
||||||
|
url: '{{ miniconda_dl_uri }}'
|
||||||
|
dest: '{{ miniconda_dl_local_abs }}'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
- name: 'Set execute bit on Miniconda installer'
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: '{{ miniconda_dl_local_abs }}'
|
||||||
|
mode: 'a+x'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
- name: 'Get Miniconda installer help output'
|
||||||
|
register: 'rv_miniconda_installer_help'
|
||||||
|
changed_when: 'rv_miniconda_installer_help.rc != 2'
|
||||||
|
failed_when: 'rv_miniconda_installer_help.rc != 2'
|
||||||
|
ansible.builtin.shell: '{{ miniconda_dl_local_abs }} -h'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
- name: 'Get Miniconda installer version from help output'
|
||||||
|
when: 'rv_miniconda_installer_help.rc == 2'
|
||||||
|
set_fact:
|
||||||
|
miniconda_installer_version: '{{ rv_miniconda_installer_help.stdout | regex_search(''Installs Miniconda3 (py.*?_)(.*?)(\n)'', ''\2'') }}'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
- name: 'Get conda version output'
|
||||||
|
register: 'rv_conda_version_output'
|
||||||
|
changed_when: 'rv_conda_version_output.rc != 0'
|
||||||
|
failed_when: 'false'
|
||||||
|
ansible.builtin.shell: 'conda --version 2> ''/dev/null'''
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
- name: 'Get conda version from version output'
|
||||||
|
register: 'rv_conda_version'
|
||||||
|
changed_when: '(not conda_version) or (rv_conda_version_output.rc != 0)'
|
||||||
|
failed_when: 'false'
|
||||||
|
set_fact:
|
||||||
|
conda_version: '{{ rv_conda_version_output.stdout | regex_search(''conda ([^\r\n\f]+)'', ''\1'') }}'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
- name: 'If Miniconda old or missing: install it'
|
||||||
|
when: '(miniconda_installer_version | first is version(''4.11.9'', ''>'')) or (not conda_version)'
|
||||||
|
register: 'rv_miniconda_install'
|
||||||
|
ansible.builtin.shell: '{{ miniconda_dl_local_abs }} -b -p ''{{ miniconda_install_dir }}'' -u'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
- name: 'If Miniconda was installed: Initialize'
|
||||||
|
when: 'rv_miniconda_install.changed'
|
||||||
|
register: 'rv_conda_init'
|
||||||
|
ansible.builtin.shell: '{{ miniconda_conda_binary }} init'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
- name: 'Set ~/.condarc file'
|
||||||
|
tags:
|
||||||
|
- 'testing'
|
||||||
|
ansible.builtin.copy:
|
||||||
|
src: '_current_user_home_/.condarc'
|
||||||
|
dest: '{{ ansible_env.HOME }}/.condarc'
|
||||||
|
mode: '0644'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
- name: 'Debug vars'
|
||||||
|
tags:
|
||||||
|
- 'testing'
|
||||||
|
debug:
|
||||||
|
msg: '{{ ansible_env.HOME }}'
|
@@ -0,0 +1,30 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# conda deactivate && conda update -y --name base conda && conda update -y --all
|
||||||
|
|
||||||
|
#- name: '...'
|
||||||
|
# tags:
|
||||||
|
# - 'inTesting'
|
||||||
|
# delegate_to: '127.0.0.1'
|
||||||
|
# run_once: true
|
||||||
|
# async: 1
|
||||||
|
# poll: 0
|
||||||
|
# no_log: true
|
||||||
|
# when: '...'
|
||||||
|
# register: '...'
|
||||||
|
# become: 'yes'
|
||||||
|
# changed_when: '...'
|
||||||
|
# failed_when: '...'
|
||||||
|
# until: '(condition)'
|
||||||
|
# retries: 5
|
||||||
|
# delay: 10
|
||||||
|
# loop_control:
|
||||||
|
# loop_var: 'loopVar'
|
||||||
|
# loop:
|
||||||
|
# - { var1: '', var2: '' }
|
||||||
|
# - { ... }
|
||||||
|
# <command>:
|
||||||
|
# argument1: '{{ loopVar.var1 }}'
|
||||||
|
# argument2: '{{ loopVar.var2 }}'
|
||||||
|
#
|
1
ansible/roles/10-include-50-miniconda/tasks/main.yml
Normal file
1
ansible/roles/10-include-50-miniconda/tasks/main.yml
Normal file
@@ -0,0 +1 @@
|
|||||||
|
- import_tasks: '50-setup-miniconda-env.yml'
|
@@ -15,26 +15,46 @@
|
|||||||
- name: 'Install Docker engine basics'
|
- name: 'Install Docker engine basics'
|
||||||
ansible.builtin.dnf:
|
ansible.builtin.dnf:
|
||||||
name:
|
name:
|
||||||
- 'yum-utils'
|
- 'docker-ce' # Docker
|
||||||
- 'docker-ce'
|
- 'docker-ce-cli' #
|
||||||
- 'docker-ce-cli'
|
- 'containerd.io' #
|
||||||
- 'containerd.io'
|
- 'docker-compose-plugin' #
|
||||||
- 'docker-compose-plugin'
|
- 'git' # git clone Mailcow repo
|
||||||
- 'git'
|
|
||||||
state: 'latest'
|
state: 'latest'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
- name: 'Populate service facts'
|
- name: 'Install Miniconda'
|
||||||
tags:
|
tags:
|
||||||
- 'testing'
|
'testing'
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: '10-include-50-miniconda'
|
||||||
|
tasks_from: '40-install-miniconda'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
- name: 'Install Miniconda'
|
||||||
|
loop_control:
|
||||||
|
loop_var: 'conda'
|
||||||
|
loop:
|
||||||
|
- { task: 'setup', data: 'alter' }
|
||||||
|
- { task: 'setup', data: 'wasn' }
|
||||||
|
- { task: 'setup', data: 'digger' }
|
||||||
|
vars:
|
||||||
|
task: '{{ conda.task }}'
|
||||||
|
data: '{{ conda.data }}'
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: '10-include-50-miniconda'
|
||||||
|
tasks_from: '40-install-miniconda'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
- name: 'Populate service facts'
|
||||||
ansible.builtin.service_facts:
|
ansible.builtin.service_facts:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
- name: 'Store Docker daemon.json'
|
- name: 'Store Docker daemon.json'
|
||||||
tags:
|
|
||||||
- 'testing'
|
|
||||||
register: 'rv_upload_daemonjson'
|
register: 'rv_upload_daemonjson'
|
||||||
ansible.builtin.copy:
|
ansible.builtin.copy:
|
||||||
src: 'etc/docker/daemon.json'
|
src: 'etc/docker/daemon.json'
|
||||||
@@ -48,8 +68,6 @@
|
|||||||
|
|
||||||
|
|
||||||
- name: 'Start systemd docker.service'
|
- name: 'Start systemd docker.service'
|
||||||
tags:
|
|
||||||
- 'testing'
|
|
||||||
when: '(ansible_facts.services[''docker.service''].state != ''running'')'
|
when: '(ansible_facts.services[''docker.service''].state != ''running'')'
|
||||||
ansible.builtin.systemd:
|
ansible.builtin.systemd:
|
||||||
name: 'docker.service'
|
name: 'docker.service'
|
||||||
|
Reference in New Issue
Block a user