Import from elsewhere
This commit is contained in:
parent
4017e9ac0c
commit
0f2bc19d5f
77 changed files with 1479 additions and 0 deletions
ansible.cfg
playbooks
after_provisioning.ymldeploy_common.ymldeploy_firewall.ymldeploy_nginx.ymldeploy_users.ymlremove_user.ymlunattended_upgrades.yml
roles
ansible_base_deps
common
etckeeper
etckeeper_commit
fail2ban
nftables
nginx
sysadmin_users
unattended_upgrades
wireguard
21
ansible.cfg
Normal file
21
ansible.cfg
Normal file
|
@ -0,0 +1,21 @@
|
|||
[defaults]
|
||||
inventory = ./inventory/production
|
||||
roles_path = ./roles
|
||||
collections_path = ./.ansible/collections:/usr/share/ansible/collections
|
||||
|
||||
ansible_managed = "This file is managed by Ansible.
|
||||
DO NOT MODIFY IT HERE, your changes will most likely be overwritten later.
|
||||
You can find the Ansible repository here:
|
||||
https://git.tobast.fr/tobast/dn42-ansible"
|
||||
retry_files_enabled = false
|
||||
interpreter_python = auto_silent
|
||||
stdout_callback = yaml
|
||||
|
||||
[privilege_escalation]
|
||||
become = True
|
||||
become_method = sudo
|
||||
become_user = root
|
||||
become_ask_pass = False
|
||||
|
||||
[ssh_connection]
|
||||
ssh_args = -C -o ControlMaster=auto -o ControlPersist=60s -o ControlPath=/tmp/ansible-socket-%u-to-%r@%h:%p
|
7
playbooks/after_provisioning.yml
Normal file
7
playbooks/after_provisioning.yml
Normal file
|
@ -0,0 +1,7 @@
|
|||
---
|
||||
- hosts: "{{ current_host }}"
|
||||
vars:
|
||||
ansible_user: root
|
||||
roles:
|
||||
- ansible_base_deps
|
||||
- sysadmin_users
|
9
playbooks/deploy_common.yml
Normal file
9
playbooks/deploy_common.yml
Normal file
|
@ -0,0 +1,9 @@
|
|||
---
|
||||
- hosts: fully_managed
|
||||
roles:
|
||||
- etckeeper_commit
|
||||
- common
|
||||
|
||||
- hosts: fully_managed:!no_nullmailer
|
||||
roles:
|
||||
- nullmailer
|
5
playbooks/deploy_firewall.yml
Normal file
5
playbooks/deploy_firewall.yml
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
- hosts:
|
||||
- fully_managed
|
||||
roles:
|
||||
- nftables
|
4
playbooks/deploy_nginx.yml
Normal file
4
playbooks/deploy_nginx.yml
Normal file
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
- hosts: nginx
|
||||
roles:
|
||||
- nginx
|
7
playbooks/deploy_users.yml
Normal file
7
playbooks/deploy_users.yml
Normal file
|
@ -0,0 +1,7 @@
|
|||
---
|
||||
- hosts:
|
||||
- dsi_users
|
||||
roles:
|
||||
- etckeeper_commit
|
||||
- ansible_base_deps
|
||||
- sysadmin_users
|
18
playbooks/remove_user.yml
Normal file
18
playbooks/remove_user.yml
Normal file
|
@ -0,0 +1,18 @@
|
|||
# Removes the user passed as `username` from extra_vars, if it exists
|
||||
|
||||
- hosts: all
|
||||
tasks:
|
||||
- name: Etckeeper - commit
|
||||
import_role:
|
||||
name: etckeeper_commit
|
||||
- name: "Remove user {{ username }}"
|
||||
user:
|
||||
name: "{{ username }}"
|
||||
state: absent
|
||||
remove: true
|
||||
become: yes
|
||||
- name: Etckeeper - commit
|
||||
import_role:
|
||||
name: etckeeper_commit
|
||||
vars:
|
||||
etckeeper_reason: "Remove user {{ username }}"
|
5
playbooks/unattended_upgrades.yml
Normal file
5
playbooks/unattended_upgrades.yml
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
- hosts: debian
|
||||
tasks:
|
||||
- command: unattended-upgrade
|
||||
become: yes
|
20
roles/ansible_base_deps/README.md
Normal file
20
roles/ansible_base_deps/README.md
Normal file
|
@ -0,0 +1,20 @@
|
|||
# Ansible base dependency role
|
||||
|
||||
This role is supposed to be deployed on every machine we have.
|
||||
|
||||
It ensures that all the distribution packages required by the Ansible modules
|
||||
we are using are installed.
|
||||
|
||||
To ensures that other roles will not fail, it should be the first role to be
|
||||
executed on a newly provisionned machine.
|
||||
|
||||
## Variables
|
||||
|
||||
* `required_packages`: this is a role variable. It cannot be overridden by
|
||||
group- or host-variables. Defines the packages that should be installed.
|
||||
|
||||
## Note on required package names
|
||||
|
||||
These are **Debian** package names: if we happen, at some point, to have some
|
||||
other distributions among our machines, we should change this role to reflect
|
||||
this.
|
12
roles/ansible_base_deps/tasks/main.yml
Normal file
12
roles/ansible_base_deps/tasks/main.yml
Normal file
|
@ -0,0 +1,12 @@
|
|||
---
|
||||
- name: install ansible package dependencies
|
||||
apt:
|
||||
name: "{{ required_packages }}"
|
||||
update_cache: yes
|
||||
become: yes
|
||||
|
||||
- name: Etckeeper - commit
|
||||
import_role:
|
||||
name: etckeeper_commit
|
||||
vars:
|
||||
etckeeper_reason: install base Ansible dependencies
|
6
roles/ansible_base_deps/vars/main.yml
Normal file
6
roles/ansible_base_deps/vars/main.yml
Normal file
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
required_packages:
|
||||
- acl # Used for `copy` and `template` modules, see https://docs.ansible.com/ansible/latest/user_guide/become.html#becoming-an-unprivileged-user
|
||||
- aptitude # Used for the `apt` module
|
||||
- sudo # Used for the `become` module
|
||||
- python3
|
10
roles/common/README.md
Normal file
10
roles/common/README.md
Normal file
|
@ -0,0 +1,10 @@
|
|||
# Common
|
||||
|
||||
Ce rôle est le rôle de base, installé sur toutes les machines.
|
||||
|
||||
## Variables de configuration
|
||||
|
||||
* `common_locales`: locales à déployer
|
||||
* `common_packages`: packages Debian à installer
|
||||
* `common_firewall`: whether to deploy the `nftables` role as part of common.
|
||||
Defaults to True.
|
19
roles/common/defaults/main.yml
Normal file
19
roles/common/defaults/main.yml
Normal file
|
@ -0,0 +1,19 @@
|
|||
---
|
||||
common_locales:
|
||||
- 'fr_FR.UTF-8 UTF-8'
|
||||
- 'en_US.UTF-8 UTF-8'
|
||||
|
||||
common_packages:
|
||||
- git
|
||||
- htop
|
||||
- lsb-release
|
||||
- tcpdump
|
||||
- nmap
|
||||
- mtr-tiny
|
||||
- dnsutils
|
||||
- vim
|
||||
- tmux
|
||||
- less
|
||||
- aptitude
|
||||
|
||||
common_firewall: True
|
4
roles/common/handlers/main.yml
Normal file
4
roles/common/handlers/main.yml
Normal file
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
- name: Generate locales
|
||||
command: '/usr/sbin/locale-gen --keep-existing'
|
||||
become: yes
|
7
roles/common/meta/main.yml
Normal file
7
roles/common/meta/main.yml
Normal file
|
@ -0,0 +1,7 @@
|
|||
---
|
||||
dependencies:
|
||||
- ansible_base_deps
|
||||
- etckeeper
|
||||
- sysadmin_users
|
||||
- mollyguard
|
||||
- fail2ban
|
19
roles/common/tasks/configure_locale.yml
Normal file
19
roles/common/tasks/configure_locale.yml
Normal file
|
@ -0,0 +1,19 @@
|
|||
---
|
||||
- name: Configure locale.gen
|
||||
template:
|
||||
src: locale/locale.gen.j2
|
||||
dest: /etc/locale.gen
|
||||
become: yes
|
||||
notify: Generate locales
|
||||
|
||||
- name: Configure locales
|
||||
template:
|
||||
src: locale/locale.conf.j2
|
||||
dest: /etc/locale.conf
|
||||
become: yes
|
||||
|
||||
- name: Etckeeper - commit
|
||||
import_role:
|
||||
name: etckeeper_commit
|
||||
vars:
|
||||
etckeeper_reason: Configure locales
|
12
roles/common/tasks/install_base_packages.yml
Normal file
12
roles/common/tasks/install_base_packages.yml
Normal file
|
@ -0,0 +1,12 @@
|
|||
---
|
||||
- name: Install base packages
|
||||
apt:
|
||||
name: '{{ common_packages }}'
|
||||
state: present
|
||||
become: yes
|
||||
|
||||
- name: Etckeeper - commit
|
||||
import_role:
|
||||
name: etckeeper_commit
|
||||
vars:
|
||||
etckeeper_reason: install base packages
|
16
roles/common/tasks/main.yml
Normal file
16
roles/common/tasks/main.yml
Normal file
|
@ -0,0 +1,16 @@
|
|||
---
|
||||
- name: Install base packages
|
||||
import_tasks: install_base_packages.yml
|
||||
|
||||
- name: Configure locale
|
||||
import_tasks: configure_locale.yml
|
||||
|
||||
- name: Install nftables
|
||||
import_role:
|
||||
name: nftables
|
||||
when: common_firewall
|
||||
|
||||
- name: Install unattended_upgrades
|
||||
import_role:
|
||||
name: unattended_upgrades
|
||||
when: "ansible_distribution == 'Debian'"
|
2
roles/common/templates/locale/locale.conf.j2
Normal file
2
roles/common/templates/locale/locale.conf.j2
Normal file
|
@ -0,0 +1,2 @@
|
|||
LANG=en_US.UTF-8
|
||||
LC_TIME=fr_FR.UTF-8
|
5
roles/common/templates/locale/locale.gen.j2
Normal file
5
roles/common/templates/locale/locale.gen.j2
Normal file
|
@ -0,0 +1,5 @@
|
|||
{{ ansible_managed | comment }}
|
||||
|
||||
{% for locale in common_locales %}
|
||||
{{ locale }}
|
||||
{% endfor %}
|
3
roles/etckeeper/README.md
Normal file
3
roles/etckeeper/README.md
Normal file
|
@ -0,0 +1,3 @@
|
|||
# Etckeeper
|
||||
|
||||
Make git commit for changes to `/etc`.
|
18
roles/etckeeper/defaults/main.yml
Normal file
18
roles/etckeeper/defaults/main.yml
Normal file
|
@ -0,0 +1,18 @@
|
|||
---
|
||||
etckeeper_scripts:
|
||||
- name: 30initial-package-list
|
||||
dir: /etc/etckeeper/init.d
|
||||
- name: 10refresh-package-list
|
||||
dir: /etc/etckeeper/post-install.d
|
||||
- name: etckeeper_prompt.sh
|
||||
dir: /etc/profile.d
|
||||
|
||||
etckeeper_ignore_paths:
|
||||
- comment: ZFS zpool cache
|
||||
path: zfs/zpool.cache
|
||||
- comment: pve (Used by Proxmox)
|
||||
path: pve/
|
||||
- comment: lock for certbot
|
||||
path: letsencrypt/.certbot.lock
|
||||
|
||||
etckeeper_group: 'adm'
|
20
roles/etckeeper/tasks/etckeeper_ignore_paths.yml
Normal file
20
roles/etckeeper/tasks/etckeeper_ignore_paths.yml
Normal file
|
@ -0,0 +1,20 @@
|
|||
---
|
||||
- name: "etckeeper -- Ignore {{ item.comment }}"
|
||||
lineinfile:
|
||||
dest: /etc/.gitignore
|
||||
regexp: "^{{ item.path }}$"
|
||||
line: "{{ item.path }}"
|
||||
become: yes
|
||||
|
||||
# git returns 0 if path was tracked, and 128 if path was already
|
||||
# removed from the index. Don't fail in these two cases.
|
||||
- name: "Remove {{ item.comment }} from git index (but don't actually remove it)"
|
||||
command: git rm --cached -r {{ item.path }}
|
||||
args:
|
||||
chdir: /etc/
|
||||
tags:
|
||||
- skip_ansible_lint
|
||||
register: git_result
|
||||
failed_when: git_result.rc != 0 and git_result.rc != 128
|
||||
changed_when: git_result.rc == 0
|
||||
become: yes
|
50
roles/etckeeper/tasks/main.yml
Normal file
50
roles/etckeeper/tasks/main.yml
Normal file
|
@ -0,0 +1,50 @@
|
|||
---
|
||||
# Installation
|
||||
- name: Etckeeper - install packages
|
||||
apt:
|
||||
name:
|
||||
- etckeeper
|
||||
state: present
|
||||
become: yes
|
||||
|
||||
- name: Etckeeper - ignore some paths
|
||||
include_tasks: etckeeper_ignore_paths.yml
|
||||
loop: "{{ etckeeper_ignore_paths }}"
|
||||
loop_control:
|
||||
label: "{{ item.comment }}"
|
||||
|
||||
- name: "etckeeper: install scripts"
|
||||
template:
|
||||
src: "scripts/{{ item.name }}"
|
||||
dest: "{{ item.dir }}/{{ item.name }}"
|
||||
owner: root
|
||||
group: root
|
||||
mode: 0755
|
||||
loop: "{{ etckeeper_scripts }}"
|
||||
become: yes
|
||||
|
||||
# Configuration
|
||||
|
||||
- name: Etckeeper - configure
|
||||
template:
|
||||
src: etckeeper/etckeeper.conf.j2
|
||||
dest: /etc/etckeeper/etckeeper.conf
|
||||
owner: root
|
||||
group: root
|
||||
mode: 0644
|
||||
become: yes
|
||||
|
||||
- name: Etckeeper - configure sudoers
|
||||
template:
|
||||
src: sudoers/etckeeper.j2
|
||||
dest: /etc/sudoers.d/etckeeper
|
||||
owner: root
|
||||
group: root
|
||||
mode: 0644
|
||||
become: yes
|
||||
|
||||
- name: Etckeeper - commit
|
||||
import_role:
|
||||
name: etckeeper_commit
|
||||
vars:
|
||||
etckeeper_reason: etckeeper configuration
|
42
roles/etckeeper/templates/etckeeper/etckeeper.conf.j2
Normal file
42
roles/etckeeper/templates/etckeeper/etckeeper.conf.j2
Normal file
|
@ -0,0 +1,42 @@
|
|||
{{ ansible_managed | comment }}
|
||||
|
||||
# The VCS to use.
|
||||
VCS="git"
|
||||
|
||||
# Options passed to git commit when run by etckeeper.
|
||||
GIT_COMMIT_OPTIONS=""
|
||||
|
||||
# Options passed to hg commit when run by etckeeper.
|
||||
HG_COMMIT_OPTIONS=""
|
||||
|
||||
# Options passed to bzr commit when run by etckeeper.
|
||||
BZR_COMMIT_OPTIONS=""
|
||||
|
||||
# Options passed to darcs record when run by etckeeper.
|
||||
DARCS_COMMIT_OPTIONS="-a"
|
||||
|
||||
# Uncomment to avoid etckeeper committing existing changes
|
||||
# to /etc automatically once per day.
|
||||
AVOID_DAILY_AUTOCOMMITS=1
|
||||
|
||||
# Uncomment the following to avoid special file warning
|
||||
# (the option is enabled automatically by cronjob regardless).
|
||||
#AVOID_SPECIAL_FILE_WARNING=1
|
||||
|
||||
# Uncomment to avoid etckeeper committing existing changes to
|
||||
# /etc before installation. It will cancel the installation,
|
||||
# so you can commit the changes by hand.
|
||||
AVOID_COMMIT_BEFORE_INSTALL=1
|
||||
|
||||
# The high-level package manager that's being used.
|
||||
# (apt, pacman-g2, yum, zypper etc)
|
||||
HIGHLEVEL_PACKAGE_MANAGER=apt
|
||||
|
||||
# The low-level package manager that's being used.
|
||||
# (dpkg, rpm, pacman, pacman-g2, etc)
|
||||
LOWLEVEL_PACKAGE_MANAGER=dpkg
|
||||
|
||||
# To push each commit to a remote, put the name of the remote here.
|
||||
# (eg, "origin" for git). Space-separated lists of multiple remotes
|
||||
# also work (eg, "origin gitlab github" for git).
|
||||
PUSH_REMOTE=""
|
7
roles/etckeeper/templates/scripts/10refresh-package-list
Normal file
7
roles/etckeeper/templates/scripts/10refresh-package-list
Normal file
|
@ -0,0 +1,7 @@
|
|||
{{ ansible_managed | comment }}
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
echo "# Generated by etckeeper. Do not edit." > .package-list
|
||||
echo "" >> .package-list
|
||||
etckeeper list-installed >> .package-list
|
11
roles/etckeeper/templates/scripts/30initial-package-list
Normal file
11
roles/etckeeper/templates/scripts/30initial-package-list
Normal file
|
@ -0,0 +1,11 @@
|
|||
{{ ansible_managed | comment }}
|
||||
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
if ! [ -e .package-list ]; then
|
||||
echo "# Generated by etckeeper. Do not edit." > .package-list
|
||||
echo "" >> .package-list
|
||||
chmod 600 .package-list
|
||||
etckeeper list-installed >> .package-list
|
||||
fi
|
98
roles/etckeeper/templates/scripts/etckeeper_prompt.sh
Executable file
98
roles/etckeeper/templates/scripts/etckeeper_prompt.sh
Executable file
|
@ -0,0 +1,98 @@
|
|||
{{ ansible_managed | comment }}
|
||||
|
||||
# /etc/profile.d/etckeeper_prompt.sh
|
||||
#
|
||||
# Ce fragment de shell a vocation a être « sourcé » lors de l'initialisation de
|
||||
# bash. Sous Debian, il suffit de l'ajouter dans /etc/profile.d
|
||||
#
|
||||
# Une fois en place quand une modification n'est pas publiée dans etckeeper, un
|
||||
# '(!)' s'affiche dans le prompt.
|
||||
|
||||
|
||||
IS_ETCKEEPER="no"
|
||||
SUDO="sudo -n"
|
||||
|
||||
if [ "$(id -u)" = 0 ]; then
|
||||
IS_ETCKEEPER="yes"
|
||||
SUDO=""
|
||||
elif id -nG | grep -qw "{{ etckeeper_group }}"; then
|
||||
IS_ETCKEEPER="yes"
|
||||
fi
|
||||
|
||||
if [ "$IS_ETCKEEPER" = "yes" ] ; then
|
||||
case $- in
|
||||
*i*) # interactive shell
|
||||
etckeeper_unclean() {
|
||||
if $SUDO etckeeper unclean 2> /dev/null; then
|
||||
echo -n '(!) '
|
||||
fi
|
||||
}
|
||||
etckeeper_prompt() {
|
||||
if [ -z "$ETCKEEPER_PS1" ]; then
|
||||
ETCKEEPER_PS1="$PS1"
|
||||
fi
|
||||
PS1="\$(etckeeper_unclean)$ETCKEEPER_PS1"
|
||||
}
|
||||
|
||||
etckeeper_prompt_color() {
|
||||
if [ -z "$ETCKEEPER_PS1" ]; then
|
||||
ETCKEEPER_PS1="$PS1"
|
||||
fi
|
||||
PS1="\[\e[1;31m\]\$(etckeeper_unclean)\[\033[00m\]$ETCKEEPER_PS1"
|
||||
}
|
||||
|
||||
git_export_env() {
|
||||
local ttyuser ttyuserhome conf
|
||||
|
||||
ttyuser="$(stat -c "%U" $(tty))"
|
||||
ttyuserhome="$(getent passwd "$ttyuser" | cut -d: -f6)"
|
||||
conf="$ttyuserhome/.gitconfig"
|
||||
|
||||
if [ -z "$GIT_AUTHOR_NAME" ] && [ -z "$GIT_AUTHOR_EMAIL" ]; then
|
||||
if [ ! -z "$GIT_CONFIG_LOCAL" ] || [ ! -z "$GIT_CONFIG" ]; then
|
||||
export GIT_AUTHOR_NAME="$(git config --get user.name)"
|
||||
export GIT_AUTHOR_EMAIL="$(git config --get user.email)"
|
||||
elif [ -r "$conf" ]; then
|
||||
export GIT_AUTHOR_NAME="$(git config --file "$conf" --get user.name)"
|
||||
export GIT_AUTHOR_EMAIL="$(git config --file "$conf" --get user.email)"
|
||||
else
|
||||
export GIT_AUTHOR_NAME="$USER"
|
||||
export GIT_AUTHOR_EMAIL="$USER@$(hostname -f)"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
check_uncommitted() {
|
||||
if $SUDO etckeeper unclean 2> /dev/null; then
|
||||
echo "Uncommitted changes to /etc found, please commit them"
|
||||
CHECK_UNCOMMITED="done" bash -l$-
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
if [ -x /usr/bin/tput ] && tput setaf 1 >&/dev/null; then
|
||||
# We have color support; assume it's compliant with Ecma-48
|
||||
# (ISO/IEC-6429). (Lack of such support is extremely rare, and such
|
||||
# a case would tend to support setf rather than setaf.)
|
||||
color_prompt=yes
|
||||
else
|
||||
color_prompt=
|
||||
fi
|
||||
|
||||
|
||||
if [ "$color_prompt" = "yes" ]; then
|
||||
PROMPT_COMMAND=etckeeper_prompt_color
|
||||
else
|
||||
PROMPT_COMMAND=etckeeper_prompt
|
||||
fi
|
||||
|
||||
|
||||
if [ "$CHECK_UNCOMMITED" != "done" ]; then
|
||||
trap check_uncommitted EXIT
|
||||
fi
|
||||
git_export_env
|
||||
;;
|
||||
|
||||
esac
|
||||
fi
|
||||
unset IS_ETCKEEPER
|
4
roles/etckeeper/templates/sudoers/etckeeper.j2
Normal file
4
roles/etckeeper/templates/sudoers/etckeeper.j2
Normal file
|
@ -0,0 +1,4 @@
|
|||
{{ ansible_managed | comment }}
|
||||
|
||||
%{{ etckeeper_group }} ALL=(ALL) NOPASSWD: /usr/sbin/etckeeper unclean
|
||||
%{{ etckeeper_group }} ALL=(ALL) NOPASSWD: /usr/bin/etckeeper unclean
|
2
roles/etckeeper_commit/defaults/main.yml
Normal file
2
roles/etckeeper_commit/defaults/main.yml
Normal file
|
@ -0,0 +1,2 @@
|
|||
---
|
||||
etckeeper_reason: 'autocommit'
|
12
roles/etckeeper_commit/tasks/main.yml
Normal file
12
roles/etckeeper_commit/tasks/main.yml
Normal file
|
@ -0,0 +1,12 @@
|
|||
---
|
||||
- name: Etckeeper - check if commit is needed
|
||||
command: etckeeper unclean
|
||||
register: etckeeper_result
|
||||
failed_when: etckeeper_result.rc not in [0, 1, 2]
|
||||
changed_when: etckeeper_result.rc == 0
|
||||
become: yes
|
||||
|
||||
- name: Etckeeper - commit
|
||||
command: '/usr/bin/etckeeper commit -m "Ansible: {{ etckeeper_reason }}"'
|
||||
when: etckeeper_result.changed
|
||||
become: yes
|
9
roles/fail2ban/README.md
Normal file
9
roles/fail2ban/README.md
Normal file
|
@ -0,0 +1,9 @@
|
|||
# fail2ban
|
||||
|
||||
Fail2ban monitors the system to ban, through the firewall, hosts that are
|
||||
offending certain rules (eg. trying to `ssh` too many times in a row with
|
||||
incorrect credentials).
|
||||
|
||||
## Variables
|
||||
|
||||
* `fail2ban_ssh_dsi_ip`: IPs that must not be blocked.
|
2
roles/fail2ban/defaults/main.yml
Normal file
2
roles/fail2ban/defaults/main.yml
Normal file
|
@ -0,0 +1,2 @@
|
|||
---
|
||||
fail2ban_ssh_dsi_ip: 10.35.36.0/24
|
6
roles/fail2ban/handlers/main.yml
Normal file
6
roles/fail2ban/handlers/main.yml
Normal file
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
- name: reload fail2ban
|
||||
service:
|
||||
name: fail2ban
|
||||
state: reloaded
|
||||
become: yes
|
24
roles/fail2ban/tasks/main.yml
Normal file
24
roles/fail2ban/tasks/main.yml
Normal file
|
@ -0,0 +1,24 @@
|
|||
---
|
||||
- name: install fail2ban
|
||||
block:
|
||||
- apt:
|
||||
name: fail2ban
|
||||
- service:
|
||||
name: fail2ban
|
||||
state: started
|
||||
enabled: yes
|
||||
become: yes
|
||||
|
||||
- name: configure fail2ban
|
||||
template:
|
||||
src: jail.d/defaults-echirolles.conf.j2
|
||||
dest: /etc/fail2ban/jail.d/defaults-echirolles.conf
|
||||
become: yes
|
||||
notify:
|
||||
- reload fail2ban
|
||||
|
||||
- name: Etckeeper - commit
|
||||
import_role:
|
||||
name: etckeeper_commit
|
||||
vars:
|
||||
etckeeper_reason: Install and configure Fail2ban
|
10
roles/fail2ban/templates/jail.d/defaults-echirolles.conf.j2
Normal file
10
roles/fail2ban/templates/jail.d/defaults-echirolles.conf.j2
Normal file
|
@ -0,0 +1,10 @@
|
|||
{{ ansible_managed | comment }}
|
||||
|
||||
[DEFAULT]
|
||||
banaction = nftables
|
||||
banaction_allports = nftables[type=allports]
|
||||
|
||||
[sshd]
|
||||
enabled = true
|
||||
backend = systemd
|
||||
ignoreip = {{ fail2ban_ssh_dsi_ip }}
|
36
roles/nftables/README.md
Normal file
36
roles/nftables/README.md
Normal file
|
@ -0,0 +1,36 @@
|
|||
# iptables
|
||||
|
||||
Defines an `nftables` firewall.
|
||||
|
||||
## Allowing services
|
||||
|
||||
To allow a certain service that should not be allowed on all of our machines,
|
||||
we use a `firewall_allow_[service]` construct.
|
||||
|
||||
In the filters template file, we guard the specific rule with a
|
||||
`{% if firewall_allow_[service] %}`. This variable should be set to `false` in
|
||||
the `default_vars` of the present role.
|
||||
|
||||
To allow this service, this variable must be overriden to `true` in the
|
||||
`group_vars` of the relevant group.
|
||||
|
||||
The files under `/etc/nftables/local/` are included in the relevant chins.
|
||||
|
||||
## Firewalls **MUST** be tested!
|
||||
|
||||
When this role is deployed to a host, the firewall configuration is
|
||||
**immediately** applied, and will be applied upon reboot. If you mess up with
|
||||
this, we might end up locked out of our machine.
|
||||
|
||||
**Please**, test this role **extensively** whenever you modify it. Someone else
|
||||
might end up deploying it if you do not specify clearly and explicitly that
|
||||
your modifications are not ready for production.
|
||||
|
||||
## Variables
|
||||
|
||||
### `firewall_allow_*` vars
|
||||
|
||||
All these defaults to false and should be overriden as stated above.
|
||||
|
||||
* `firewall_allow_http`: allow tcp ports 80/443 from everywhere
|
||||
* `firewall_allow_dns`: allow tcp and udp port 53
|
5
roles/nftables/defaults/main.yml
Normal file
5
roles/nftables/defaults/main.yml
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
# Service accesses are disallowed by default. They are set to true in
|
||||
# group_vars for groups that need them to be available.
|
||||
firewall_allow_http: false
|
||||
firewall_allow_dns: false
|
6
roles/nftables/handlers/main.yml
Normal file
6
roles/nftables/handlers/main.yml
Normal file
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
- name: reload nftables
|
||||
service:
|
||||
name: nftables
|
||||
state: reloaded
|
||||
become: yes
|
41
roles/nftables/tasks/main.yml
Normal file
41
roles/nftables/tasks/main.yml
Normal file
|
@ -0,0 +1,41 @@
|
|||
---
|
||||
- name: install nftables firewall
|
||||
apt:
|
||||
name: nftables
|
||||
- name: make nftables configuration directories
|
||||
file:
|
||||
path: "/etc/nftables/{{ item }}"
|
||||
state: directory
|
||||
owner: root
|
||||
group: adm
|
||||
mode: 0750
|
||||
items:
|
||||
- ''
|
||||
- 'toplevel.d'
|
||||
- 'filter-toplevel.d'
|
||||
- 'filter-input.d'
|
||||
- 'filter-forward.d'
|
||||
- 'filter-output.d'
|
||||
- name: deploy nftables root configuration
|
||||
template:
|
||||
src: "nftables/nftables.conf.j2"
|
||||
dest: "/etc/nftables.conf"
|
||||
owner: root
|
||||
group: adm
|
||||
mode: 0640
|
||||
notify: reload nftables
|
||||
|
||||
- name: enable nftables service
|
||||
systemd:
|
||||
# If we do not call daemon-reload, systemd can somehow fail to find the
|
||||
# nftables service.
|
||||
name: nftables
|
||||
state: started
|
||||
enabled: true
|
||||
daemon-reload: true
|
||||
|
||||
- name: Etckeeper - commit
|
||||
import_role:
|
||||
name: etckeeper_commit
|
||||
vars:
|
||||
etckeeper_reason: install and configure nftables firewall
|
50
roles/nftables/templates/nftables/nftables.conf.j2
Normal file
50
roles/nftables/templates/nftables/nftables.conf.j2
Normal file
|
@ -0,0 +1,50 @@
|
|||
#!/usr/sbin/nft -f
|
||||
{{ ansible_managed | comment }}
|
||||
|
||||
flush ruleset
|
||||
|
||||
include "/etc/nftables/toplevel.d/*.conf"
|
||||
|
||||
table inet filter {
|
||||
include "/etc/nftables/filter-toplevel.d/*.conf"
|
||||
|
||||
chain input {
|
||||
type filter hook input priority 0; policy drop;
|
||||
|
||||
iifname "lo" accept comment "Accept localhost traffict"
|
||||
iifname != "lo" ip daddr 127.0.0.0/8 reject comment "Spoofed lo"
|
||||
ct state related,established accept
|
||||
|
||||
meta l4proto icmp accept
|
||||
meta l4proto igmp accept
|
||||
meta l4proto ipv6-icmp accept
|
||||
|
||||
include "/etc/nftables/filter-input.d/*.conf"
|
||||
|
||||
meta l4proto tcp tcp dport 22 accept
|
||||
|
||||
{% if firewall_allow_http %}
|
||||
# Web server (TCP/80,443)
|
||||
tcp dport 80 accept
|
||||
tcp dport 443 accept
|
||||
|
||||
{% endif %}
|
||||
{% if firewall_allow_dns %}
|
||||
# DNS
|
||||
tcp dport 53 accept
|
||||
udp dport 53 accept
|
||||
|
||||
{% endif %}
|
||||
}
|
||||
|
||||
chain forward {
|
||||
type filter hook forward priority 0; policy drop;
|
||||
|
||||
include "/etc/nftables/filter-forward.d/*.conf"
|
||||
}
|
||||
chain output {
|
||||
type filter hook output priority 0; policy accept;
|
||||
|
||||
include "/etc/nftables/filter-output.d/*.conf"
|
||||
}
|
||||
}
|
16
roles/nginx/README.md
Normal file
16
roles/nginx/README.md
Normal file
|
@ -0,0 +1,16 @@
|
|||
# Nginx
|
||||
|
||||
Nginx is a web server and reverse-proxy.
|
||||
|
||||
This role configures the base server, other roles should be used to configure
|
||||
its various servers (ie. configuration files to serve content in a certain way
|
||||
over a certain domain name).
|
||||
|
||||
## Important note
|
||||
|
||||
If you wish a certain host to embed this role, you should add it to the `nginx`
|
||||
group. Otherwise, you might end up with the ports firewalled out.
|
||||
|
||||
## Variables
|
||||
|
||||
None.
|
6
roles/nginx/handlers/main.yml
Normal file
6
roles/nginx/handlers/main.yml
Normal file
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
- name: reload nginx
|
||||
service:
|
||||
name: nginx
|
||||
state: reloaded
|
||||
become: yes
|
3
roles/nginx/meta/main.yml
Normal file
3
roles/nginx/meta/main.yml
Normal file
|
@ -0,0 +1,3 @@
|
|||
---
|
||||
dependencies:
|
||||
- role: fail2ban
|
73
roles/nginx/tasks/main.yml
Normal file
73
roles/nginx/tasks/main.yml
Normal file
|
@ -0,0 +1,73 @@
|
|||
---
|
||||
- name: install nginx
|
||||
apt:
|
||||
name: nginx
|
||||
- name: add gitignore
|
||||
template:
|
||||
src: nginx/gitignore.j2
|
||||
dest: /etc/nginx/.gitignore
|
||||
- name: create snippets directory
|
||||
file:
|
||||
path: /etc/nginx/include
|
||||
state: directory
|
||||
- name: add configuration snippets
|
||||
template:
|
||||
src: "nginx/include/{{ item }}.j2"
|
||||
dest: "/etc/nginx/include/{{ item }}"
|
||||
loop:
|
||||
- php
|
||||
- php_with_upstream
|
||||
- proxy_params
|
||||
- redirect_ssl
|
||||
- ssl_conf
|
||||
- static
|
||||
- name: "add ssl_keys_* files"
|
||||
template:
|
||||
src: "nginx/include/ssl_keys.j2"
|
||||
dest: "/etc/nginx/include/ssl_keys_{{ item }}"
|
||||
loop: "{{ ssl_domains | mandatory | map('first') | flatten }}"
|
||||
when: ssl_domains is defined
|
||||
vars:
|
||||
- cert_name: "{{ item }}"
|
||||
- name: create keys directory
|
||||
file:
|
||||
path: /etc/nginx/keys
|
||||
state: directory
|
||||
owner: root
|
||||
group: root
|
||||
mode: 0750
|
||||
- name: generate dhparam
|
||||
openssl_dhparam:
|
||||
path: /etc/nginx/keys/dhparam.pem
|
||||
force: no
|
||||
owner: root
|
||||
group: root
|
||||
mode: 0640
|
||||
size: 2048
|
||||
- name: add default server
|
||||
template:
|
||||
src: nginx/sites-available/default_server.j2
|
||||
dest: /etc/nginx/sites-available/default_server
|
||||
notify: reload nginx
|
||||
- name: enable default server
|
||||
file:
|
||||
path: /etc/nginx/sites-enabled/default_server
|
||||
state: link
|
||||
src: '../sites-available/default_server'
|
||||
notify: reload nginx
|
||||
- name: disable nginx stock default server
|
||||
file:
|
||||
path: /etc/nginx/sites-enabled/default
|
||||
state: absent
|
||||
notify: reload nginx
|
||||
- name: configure fail2ban
|
||||
template:
|
||||
src: fail2ban/nginx.conf.j2
|
||||
dest: /etc/fail2ban/jail.d/nginx.conf
|
||||
notify: reload fail2ban
|
||||
|
||||
- name: Etckeeper - commit
|
||||
import_role:
|
||||
name: etckeeper_commit
|
||||
vars:
|
||||
etckeeper_reason: install and base configuration of nginx
|
7
roles/nginx/templates/fail2ban/nginx.conf.j2
Normal file
7
roles/nginx/templates/fail2ban/nginx.conf.j2
Normal file
|
@ -0,0 +1,7 @@
|
|||
{{ ansible_managed | comment }}
|
||||
|
||||
[nginx-limit-req]
|
||||
enabled = true
|
||||
|
||||
[nginx-botsearch]
|
||||
enabled = true
|
3
roles/nginx/templates/nginx/gitignore.j2
Normal file
3
roles/nginx/templates/nginx/gitignore.j2
Normal file
|
@ -0,0 +1,3 @@
|
|||
{{ ansible_managed | comment }}
|
||||
# This file is provided in case the system has an etckeeper
|
||||
keys
|
|
@ -0,0 +1,6 @@
|
|||
{{ ansible_managed | comment }}
|
||||
|
||||
location /.well-known/acme-challenge {
|
||||
alias /var/lib/dehydrated/acme-challenges/;
|
||||
default_type 'text/plain';
|
||||
}
|
4
roles/nginx/templates/nginx/include/limit_req.j2
Normal file
4
roles/nginx/templates/nginx/include/limit_req.j2
Normal file
|
@ -0,0 +1,4 @@
|
|||
{{ ansible_managed | comment }}
|
||||
# Implements requests rate limit -- see conf.d/limit_req_zone.conf
|
||||
|
||||
limit_req zone=all_sites burst=5;
|
10
roles/nginx/templates/nginx/include/php.j2
Normal file
10
roles/nginx/templates/nginx/include/php.j2
Normal file
|
@ -0,0 +1,10 @@
|
|||
{{ ansible_managed | comment }}
|
||||
|
||||
# HOW TO (typically) USE THIS FILE:
|
||||
#
|
||||
# location ~ [^/]\.php(/|$) {
|
||||
# include include/php;
|
||||
# }
|
||||
|
||||
set $php_upstream php;
|
||||
include include/php_with_upstream;
|
14
roles/nginx/templates/nginx/include/php_with_upstream.j2
Normal file
14
roles/nginx/templates/nginx/include/php_with_upstream.j2
Normal file
|
@ -0,0 +1,14 @@
|
|||
{{ ansible_managed | comment }}
|
||||
|
||||
# HOW TO (typically) USE THIS FILE:
|
||||
#
|
||||
# location ~ [^/]\.php(/|$) {
|
||||
# set $php_upstream my_blah_upstream;
|
||||
# include include/php_with_upstream;
|
||||
# }
|
||||
|
||||
include fastcgi.conf;
|
||||
fastcgi_intercept_errors on;
|
||||
fastcgi_pass $php_upstream;
|
||||
fastcgi_buffers 16 16k;
|
||||
fastcgi_buffer_size 32k;
|
10
roles/nginx/templates/nginx/include/proxy_params.j2
Normal file
10
roles/nginx/templates/nginx/include/proxy_params.j2
Normal file
|
@ -0,0 +1,10 @@
|
|||
{{ ansible_managed | comment }}
|
||||
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header X-SSL-Client-Serial $ssl_client_serial;
|
||||
proxy_set_header X-SSL-Client-Verify $ssl_client_verify;
|
||||
proxy_set_header X-SSL-Client-S-DN $ssl_client_s_dn;
|
||||
proxy_pass_header Authorization;
|
6
roles/nginx/templates/nginx/include/redirect_ssl.j2
Normal file
6
roles/nginx/templates/nginx/include/redirect_ssl.j2
Normal file
|
@ -0,0 +1,6 @@
|
|||
{{ ansible_managed | comment }}
|
||||
|
||||
include include/letsencrypt-challenge;
|
||||
location / {
|
||||
return 301 https://$server_name$request_uri;
|
||||
}
|
24
roles/nginx/templates/nginx/include/ssl_conf.j2
Normal file
24
roles/nginx/templates/nginx/include/ssl_conf.j2
Normal file
|
@ -0,0 +1,24 @@
|
|||
{{ ansible_managed | comment }}
|
||||
|
||||
include include/letsencrypt-challenge;
|
||||
|
||||
# Taken from https://mozilla.github.io/server-side-tls/ssl-config-generator/
|
||||
|
||||
ssl_session_timeout 1d;
|
||||
ssl_session_cache shared:SSL:10m; # about 40000 sessions
|
||||
ssl_session_tickets off;
|
||||
|
||||
# Diffie-Hellman parameter for DHE ciphersuites, recommended 2048 bits
|
||||
ssl_dhparam /etc/nginx/keys/dhparam.pem;
|
||||
|
||||
# intermediate configuration
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
|
||||
ssl_prefer_server_ciphers off;
|
||||
|
||||
# HSTS (ngx_http_headers_module is required) (63072000 seconds)
|
||||
add_header Strict-Transport-Security "max-age=63072000" always;
|
||||
|
||||
# OCSP stapling
|
||||
ssl_stapling on;
|
||||
ssl_stapling_verify on;
|
10
roles/nginx/templates/nginx/include/ssl_keys.j2
Normal file
10
roles/nginx/templates/nginx/include/ssl_keys.j2
Normal file
|
@ -0,0 +1,10 @@
|
|||
{{ ansible_managed | comment }}
|
||||
|
||||
# Defines the SSL certificates and every SSL security parameter (through the
|
||||
# inclusion of `include/ssl_conf`)
|
||||
|
||||
include include/ssl_conf;
|
||||
|
||||
## Dehydrated
|
||||
ssl_certificate /etc/dehydrated/certs/{{ cert_name }}/fullchain.pem;
|
||||
ssl_certificate_key /etc/dehydrated/certs/{{ cert_name }}/privkey.pem;
|
5
roles/nginx/templates/nginx/include/static.j2
Normal file
5
roles/nginx/templates/nginx/include/static.j2
Normal file
|
@ -0,0 +1,5 @@
|
|||
{{ ansible_managed | comment }}
|
||||
|
||||
access_log off;
|
||||
add_header Cache-Control "public";
|
||||
expires 7d;
|
|
@ -0,0 +1,15 @@
|
|||
{{ ansible_managed | comment }}
|
||||
|
||||
server {
|
||||
server_name _;
|
||||
listen 80 default_server;
|
||||
listen [::]:80 default_server;
|
||||
|
||||
include include/letsencrypt-challenge;
|
||||
|
||||
access_log /var/log/nginx/access.default_server.log;
|
||||
|
||||
location / {
|
||||
return 404;
|
||||
}
|
||||
}
|
36
roles/sysadmin_users/README.md
Normal file
36
roles/sysadmin_users/README.md
Normal file
|
@ -0,0 +1,36 @@
|
|||
# Sysadmin users
|
||||
|
||||
Creates UNIX users and home directories for each sysadmin. Also takes care of
|
||||
disabling former sysadmin users.
|
||||
|
||||
|
||||
## Variables
|
||||
|
||||
* `sysadmins`: list of usernames of the current sysadmins, ie. people that have
|
||||
an account on the various machines and are sudoers. This value can be
|
||||
overridden to have different sysadmins on a specific machine.
|
||||
Please refer to `defaults/main.yml` for the current default value.
|
||||
* `former_sysadmins`: list of usernames of the former sysadmins, ie. people
|
||||
that used to have a sudoer account on the machines and must now be disabled
|
||||
(ie., cannot log in anymore).
|
||||
Please refer to `defaults/main.yml` for the current default value.
|
||||
* `sysadmins_groups`: additional groups in which the sysadmins belong. Defaults
|
||||
to `adm sudonopass`.
|
||||
|
||||
### Role variables (cannot be overridden)
|
||||
|
||||
* `sysadmins_details`: dictionary mapping sysadmin or former sysadmin logins
|
||||
to the given user's configuration.
|
||||
This variable is set as a role variable: we might want different sysadmins on
|
||||
various machines, but we want a consistent configuration of the defined
|
||||
users.
|
||||
Each entry contains:
|
||||
* `full_name`: full name of the sysadmin.
|
||||
* `email`: email address of the sysadmin
|
||||
* `ssh_keys`: list of ssh public keys. **PLEASE KEEP IN MIND** that it is
|
||||
your responsability to keep your private key safe. In particular, once you
|
||||
add a computer's public key here, always lock your computer and have a
|
||||
strong passphrase.
|
||||
* `shell`: shell this user wants to use.
|
||||
* `deploy_files`: list of `src`/`dest` entries that will be deployed from
|
||||
this role's `files` to the user's home directory.
|
8
roles/sysadmin_users/defaults/main.yml
Normal file
8
roles/sysadmin_users/defaults/main.yml
Normal file
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
sysadmins:
|
||||
- tobast
|
||||
former_sysadmins: []
|
||||
sysadmins_sudo_group: 'sudonopass'
|
||||
sysadmins_groups:
|
||||
- adm
|
||||
- '{{ sysadmins_sudo_group }}'
|
63
roles/sysadmin_users/files/tobast/tmux.conf
Normal file
63
roles/sysadmin_users/files/tobast/tmux.conf
Normal file
|
@ -0,0 +1,63 @@
|
|||
# Set $TERM env
|
||||
set -g default-terminal "screen-256color"
|
||||
|
||||
# No escape delay, so that one can still use vim
|
||||
set -sg escape-time 0
|
||||
|
||||
# Set prefix to ^A
|
||||
unbind C-b
|
||||
set -g prefix C-a
|
||||
bind C-a send-prefix
|
||||
|
||||
# Navigation
|
||||
## Navigation in panes with C+hjkl integrated with vim
|
||||
bind -n C-h run "(tmux display-message -p '#{pane_current_command}' | grep -iq vim && tmux send-keys C-h) || tmux select-pane -L"
|
||||
bind -n C-j run "(tmux display-message -p '#{pane_current_command}' | grep -iq vim && tmux send-keys C-j) || tmux select-pane -D"
|
||||
bind -n C-k run "(tmux display-message -p '#{pane_current_command}' | grep -iq vim && tmux send-keys C-k) || tmux select-pane -U"
|
||||
bind -n C-l run "(tmux display-message -p '#{pane_current_command}' | grep -iq vim && tmux send-keys C-l) || tmux select-pane -R"
|
||||
## Navigation in windows with alt+shift+jk
|
||||
bind -n M-j select-window -p
|
||||
bind -n M-k select-window -n
|
||||
|
||||
# Resizing
|
||||
## Resize panes through C-M-{hjkl}
|
||||
bind -n C-M-h resize-pane -L
|
||||
bind -n C-M-j resize-pane -D
|
||||
bind -n C-M-k resize-pane -U
|
||||
bind -n C-M-l resize-pane -R
|
||||
|
||||
# Splitting
|
||||
unbind %
|
||||
unbind '"'
|
||||
bind | split-window -h -c "#{pane_current_path}"
|
||||
bind - split-window -v -c "#{pane_current_path}"
|
||||
|
||||
# New windows use the same working directory
|
||||
bind c new-window -c "#{pane_current_path}"
|
||||
|
||||
# Set window notifications
|
||||
setw -g monitor-activity on
|
||||
set -g visual-activity on
|
||||
|
||||
# Reload tmux conf
|
||||
unbind r
|
||||
bind r source-file ~/.tmux.conf \; display-message " Config reloaded".
|
||||
|
||||
# Reassign overloaded bindings
|
||||
bind l send-keys 'C-l'
|
||||
|
||||
|
||||
# Status bar
|
||||
set -g status-style bg=colour237
|
||||
set -ag status-style fg=colour216
|
||||
set -ag status-style dim
|
||||
set-option -g status-left '#[fg=colour196][#[fg=default]#S#[fg=colour196]]#[fg=default] '
|
||||
set-option -g status-right \
|
||||
'#[fg=colour196][#[fg=default]#(echo $USER)#[fg=colour196]@\
|
||||
#[fg=default]#h#[fg=colour196]]#[fg=default] \
|
||||
#[fg=colour196][#[fg=default]#(date "+%H:%M %F")#[fg=colour196]]#[fg=defaultb'
|
||||
|
||||
# Current window
|
||||
set-window-option -g window-status-current-style bg=colour215
|
||||
set-window-option -ag window-status-current-style fg=colour88
|
||||
set-window-option -g window-status-current-format ' #I:#W#F '
|
77
roles/sysadmin_users/files/tobast/vimrc
Normal file
77
roles/sysadmin_users/files/tobast/vimrc
Normal file
|
@ -0,0 +1,77 @@
|
|||
" Tiny vimrc without plugins, to be deployed on servers
|
||||
|
||||
filetype plugin on
|
||||
syntax on
|
||||
set colorcolumn=80
|
||||
set background=dark
|
||||
set number
|
||||
set relativenumber
|
||||
set tabstop=4
|
||||
"set softtabstop=4
|
||||
set shiftwidth=4
|
||||
set expandtab
|
||||
set smartindent
|
||||
set incsearch
|
||||
set ttimeoutlen=100
|
||||
set scrolloff=5
|
||||
set tw=79
|
||||
|
||||
" Leader
|
||||
let mapleader = "\<Space>"
|
||||
let maplocalleader = "\<Space>"
|
||||
|
||||
" Tab completion
|
||||
set wildmode=longest,list,full
|
||||
set wildmenu
|
||||
|
||||
" Splitting
|
||||
set splitbelow
|
||||
set splitright
|
||||
|
||||
" Split delimiter
|
||||
set fillchars+=vert:\│
|
||||
hi! VertSplit ctermbg=243 ctermfg=16
|
||||
hi! SignColumn ctermbg=16
|
||||
|
||||
set exrc
|
||||
set secure
|
||||
|
||||
if has("autocmd")
|
||||
au BufReadPost * if line("'\"") > 0 && line("'\"") <= line("$")
|
||||
\| exe "normal! g'\"" | endif
|
||||
endif
|
||||
|
||||
filetype plugin indent on " required
|
||||
|
||||
|
||||
""""""""""""""""" Trailing whitespaces
|
||||
fun! TrimWhitespace()
|
||||
let l:save_cursor = getpos('.')
|
||||
%s/\s\+$//e
|
||||
call setpos('.', l:save_cursor)
|
||||
endfun
|
||||
" Show trailing whitepace and spaces before a tab:
|
||||
highlight ExtraWhitespace ctermbg=darkgreen guibg=lightgreen
|
||||
match ExtraWhitespace /\s\+$\| \+\ze\t/
|
||||
autocmd Syntax * syn match ExtraWhitespace /\s\+$\| \+\ze\t/
|
||||
|
||||
""""""""""""""""" Key bindings
|
||||
nnoremap <F1> :w<CR>:!make<CR>
|
||||
inoremap <F1> <esc>:echo 'F1 help disabled'<CR>
|
||||
nnoremap <F2> :!git status<CR>
|
||||
nnoremap __ :lprev<CR>
|
||||
nnoremap ++ :lnext<CR>
|
||||
nnoremap _+ :ll<CR>
|
||||
nnoremap <Leader>w :call TrimWhitespace()<CR>
|
||||
|
||||
xnoremap <Leader>x <esc>:'<,'>:w !xclip -selection clipboard<CR><esc>
|
||||
|
||||
nnoremap <Leader>p <esc>:set invpaste<CR>
|
||||
|
||||
cmap w!! w !sudo tee % > /dev/null
|
||||
|
||||
" Disable arrow keys - use hjkl, ffs.
|
||||
noremap <Up> <NOP>
|
||||
noremap <Down> <NOP>
|
||||
noremap <Left> <NOP>
|
||||
noremap <Right> <NOP>
|
37
roles/sysadmin_users/tasks/create_sysadmin.yml
Normal file
37
roles/sysadmin_users/tasks/create_sysadmin.yml
Normal file
|
@ -0,0 +1,37 @@
|
|||
# Create a sysadmin user. Arguments:
|
||||
# * `username`: username of the sysadmin
|
||||
# * `details`: details of the sysadmin
|
||||
---
|
||||
|
||||
- name: "create sysadmin user {{ username }}"
|
||||
user:
|
||||
name: "{{ username }}"
|
||||
create_home: yes
|
||||
append: true
|
||||
groups: "{{ sysadmins_groups }}"
|
||||
home: "/home/{{ username }}"
|
||||
shell: "{{ details.shell }}"
|
||||
expires: -1 # Remove expiracy, in case we re-enabled a former sysadmin
|
||||
password_lock: no # idem
|
||||
state: present
|
||||
become: yes
|
||||
- name: "set {{ username }}'s public SSH keys"
|
||||
authorized_key:
|
||||
key: "{{ details.ssh_keys|join('\n') }}"
|
||||
user: "{{ username }}"
|
||||
exclusive: yes
|
||||
become: yes
|
||||
become_user: "{{ username }}"
|
||||
tags:
|
||||
- update_files
|
||||
- name: "deploy {{ username }}'s files"
|
||||
copy:
|
||||
src: "{{ cur_file.src }}"
|
||||
dest: "/home/{{ username }}/{{ cur_file.dest }}"
|
||||
loop: "{{ details.deploy_files }}"
|
||||
loop_control:
|
||||
loop_var: cur_file
|
||||
become: yes
|
||||
become_user: "{{ username }}"
|
||||
tags:
|
||||
- update_files
|
19
roles/sysadmin_users/tasks/disable_sysadmin.yml
Normal file
19
roles/sysadmin_users/tasks/disable_sysadmin.yml
Normal file
|
@ -0,0 +1,19 @@
|
|||
# Disable an existing sysadmin user, which is now a former sysadmin. Arguments:
|
||||
# * `username`: username of the sysadmin
|
||||
# * `details`: details of the sysadmin
|
||||
---
|
||||
|
||||
- name: "unset {{ username }}'s public SSH keys"
|
||||
authorized_key:
|
||||
key: ""
|
||||
user: "{{ username }}"
|
||||
exclusive: yes
|
||||
become: yes
|
||||
become_user: "{{ username }}"
|
||||
- name: "expire user account {{ username }}"
|
||||
user:
|
||||
name: "{{ item }}"
|
||||
password_lock: yes
|
||||
groups: ""
|
||||
expires: 1
|
||||
become: yes
|
38
roles/sysadmin_users/tasks/main.yml
Normal file
38
roles/sysadmin_users/tasks/main.yml
Normal file
|
@ -0,0 +1,38 @@
|
|||
---
|
||||
- name: create sysadmin sudoer group
|
||||
group:
|
||||
name: '{{ sysadmins_sudo_group }}'
|
||||
state: present
|
||||
become: yes
|
||||
|
||||
- name: add sysadmin group to sudoers
|
||||
template:
|
||||
src: sudoers.d/sysadmins.j2
|
||||
dest: /etc/sudoers.d/sysadmins
|
||||
become: yes
|
||||
|
||||
- name: create sysadmin users
|
||||
include_role:
|
||||
name: sysadmin_users
|
||||
tasks_from: create_sysadmin
|
||||
vars:
|
||||
- username: "{{ item }}"
|
||||
- details: "{{ sysadmin_details[item] }}"
|
||||
loop: "{{ sysadmins }}"
|
||||
tags:
|
||||
- update_files
|
||||
|
||||
- name: disable former sysadmins
|
||||
include_role:
|
||||
name: sysadmin_users
|
||||
tasks_from: disable_sysadmin
|
||||
vars:
|
||||
- username: "{{ item }}"
|
||||
- details: "{{ sysadmin_details[item] }}"
|
||||
loop: "{{ former_sysadmins }}"
|
||||
|
||||
- name: Etckeeper - commit
|
||||
import_role:
|
||||
name: etckeeper_commit
|
||||
vars:
|
||||
etckeeper_reason: update sysadmin users
|
14
roles/sysadmin_users/templates/root_authorized_keys.j2
Normal file
14
roles/sysadmin_users/templates/root_authorized_keys.j2
Normal file
|
@ -0,0 +1,14 @@
|
|||
{{ ansible_managed | comment }}
|
||||
|
||||
{% if sysadmins_root_ssh_keys_others %}
|
||||
# Additional specific keys for this machine
|
||||
{% for key in sysadmins_root_ssh_keys_others %}{{ key }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
{% for sysadmin in sysadmins %}
|
||||
|
||||
# {{ sysadmin_details[sysadmin].full_name }} "{{ sysadmin }}" <{{ sysadmin_details[sysadmin].email }}>
|
||||
{% for key in sysadmin_details[sysadmin].ssh_keys %}{{ key }}
|
||||
{% endfor %}
|
||||
{% endfor %}
|
3
roles/sysadmin_users/templates/sudoers.d/sysadmins.j2
Normal file
3
roles/sysadmin_users/templates/sudoers.d/sysadmins.j2
Normal file
|
@ -0,0 +1,3 @@
|
|||
{{ ansible_managed | comment }}
|
||||
|
||||
%{{ sysadmins_sudo_group }} ALL=(ALL:ALL) NOPASSWD: ALL
|
14
roles/sysadmin_users/vars/main.yml
Normal file
14
roles/sysadmin_users/vars/main.yml
Normal file
|
@ -0,0 +1,14 @@
|
|||
---
|
||||
sysadmin_details:
|
||||
tobast:
|
||||
full_name: "tobast"
|
||||
email: "contact+dn42@tobast.fr"
|
||||
ssh_keys:
|
||||
- "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMcfT+BBD1b9ZbJHPwfzdFVNlliZZEg0JaID+u0z2VJS tobast@idefix"
|
||||
- "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMI7S6w08j5AVfw7hGHGyjnycoCPukCJaiAByVVGVQym tobast@popcorn"
|
||||
shell: "/bin/bash"
|
||||
deploy_files:
|
||||
- src: tobast/tmux.conf
|
||||
dest: '.tmux.conf'
|
||||
- src: tobast/vimrc
|
||||
dest: '.vimrc'
|
7
roles/unattended_upgrades/README.md
Normal file
7
roles/unattended_upgrades/README.md
Normal file
|
@ -0,0 +1,7 @@
|
|||
# Unattended-upgrades
|
||||
|
||||
This service ensures that the security updates are installed daily.
|
||||
|
||||
## Variables
|
||||
|
||||
None.
|
29
roles/unattended_upgrades/tasks/main.yml
Normal file
29
roles/unattended_upgrades/tasks/main.yml
Normal file
|
@ -0,0 +1,29 @@
|
|||
---
|
||||
- name: check whether Debian is running
|
||||
assert:
|
||||
that:
|
||||
- "ansible_distribution == 'Debian'"
|
||||
fail_msg: "Unattended-upgrades is only intended for Debian.
|
||||
We expected only Debian servers managed by this Ansible"
|
||||
- name: install unattended-upgrades
|
||||
apt:
|
||||
name:
|
||||
- unattended-upgrades
|
||||
- apt-listchanges
|
||||
become: yes
|
||||
- name: configure unattended-upgrades
|
||||
template:
|
||||
src: 50unattended-upgrades.j2
|
||||
dest: /etc/apt/apt.conf.d/50unattended-upgrades
|
||||
become: yes
|
||||
- name: enable unattended-upgrades
|
||||
template:
|
||||
src: 20auto-upgrades.j2
|
||||
dest: /etc/apt/apt.conf.d/20auto-upgrades
|
||||
become: yes
|
||||
|
||||
- name: Etckeeper - commit
|
||||
import_role:
|
||||
name: etckeeper_commit
|
||||
vars:
|
||||
etckeeper_reason: install and configure unattended-upgrades
|
4
roles/unattended_upgrades/templates/20auto-upgrades.j2
Normal file
4
roles/unattended_upgrades/templates/20auto-upgrades.j2
Normal file
|
@ -0,0 +1,4 @@
|
|||
{{ ansible_managed | comment('c') }}
|
||||
|
||||
APT::Periodic::Update-Package-Lists "1";
|
||||
APT::Periodic::Unattended-Upgrade "1";
|
105
roles/unattended_upgrades/templates/50unattended-upgrades.j2
Normal file
105
roles/unattended_upgrades/templates/50unattended-upgrades.j2
Normal file
|
@ -0,0 +1,105 @@
|
|||
{{ ansible_managed | comment('c') }}
|
||||
|
||||
// Unattended-Upgrade::Origins-Pattern controls which packages are
|
||||
// upgraded.
|
||||
//
|
||||
// Lines below have the format format is "keyword=value,...". A
|
||||
// package will be upgraded only if the values in its metadata match
|
||||
// all the supplied keywords in a line. (In other words, omitted
|
||||
// keywords are wild cards.) The keywords originate from the Release
|
||||
// file, but several aliases are accepted. The accepted keywords are:
|
||||
// a,archive,suite (eg, "stable")
|
||||
// c,component (eg, "main", "contrib", "non-free")
|
||||
// l,label (eg, "Debian", "Debian-Security")
|
||||
// o,origin (eg, "Debian", "Unofficial Multimedia Packages")
|
||||
// n,codename (eg, "jessie", "jessie-updates")
|
||||
// site (eg, "http.debian.net")
|
||||
// The available values on the system are printed by the command
|
||||
// "apt-cache policy", and can be debugged by running
|
||||
// "unattended-upgrades -d" and looking at the log file.
|
||||
//
|
||||
// Within lines unattended-upgrades allows 2 macros whose values are
|
||||
// derived from /etc/debian_version:
|
||||
// ${distro_id} Installed origin.
|
||||
// ${distro_codename} Installed codename (eg, "jessie")
|
||||
Unattended-Upgrade::Origins-Pattern {
|
||||
// Codename based matching:
|
||||
// This will follow the migration of a release through different
|
||||
// archives (e.g. from testing to stable and later oldstable).
|
||||
// "o=Debian,n=jessie";
|
||||
// "o=Debian,n=jessie-updates";
|
||||
// "o=Debian,n=jessie-proposed-updates";
|
||||
// "o=Debian,n=jessie,l=Debian-Security";
|
||||
|
||||
// Archive or Suite based matching:
|
||||
// Note that this will silently match a different release after
|
||||
// migration to the specified archive (e.g. testing becomes the
|
||||
// new stable).
|
||||
// "o=Debian,a=stable";
|
||||
// "o=Debian,a=stable-updates";
|
||||
// "o=Debian,a=proposed-updates";
|
||||
"origin=Debian,codename=${distro_codename},label=Debian-Security";
|
||||
"origin=Debian,codename=${distro_codename}-security,label=Debian-Security";
|
||||
};
|
||||
|
||||
// List of packages to not update (regexp are supported)
|
||||
Unattended-Upgrade::Package-Blacklist {
|
||||
// "vim";
|
||||
// "libc6";
|
||||
// "libc6-dev";
|
||||
// "libc6-i686";
|
||||
};
|
||||
|
||||
// This option allows you to control if on a unclean dpkg exit
|
||||
// unattended-upgrades will automatically run
|
||||
// dpkg --force-confold --configure -a
|
||||
// The default is true, to ensure updates keep getting installed
|
||||
//Unattended-Upgrade::AutoFixInterruptedDpkg "false";
|
||||
|
||||
// Split the upgrade into the smallest possible chunks so that
|
||||
// they can be interrupted with SIGUSR1. This makes the upgrade
|
||||
// a bit slower but it has the benefit that shutdown while a upgrade
|
||||
// is running is possible (with a small delay)
|
||||
//Unattended-Upgrade::MinimalSteps "true";
|
||||
|
||||
// Install all unattended-upgrades when the machine is shuting down
|
||||
// instead of doing it in the background while the machine is running
|
||||
// This will (obviously) make shutdown slower
|
||||
//Unattended-Upgrade::InstallOnShutdown "true";
|
||||
|
||||
// Send email to this address for problems or packages upgrades
|
||||
// If empty or unset then no email is sent, make sure that you
|
||||
// have a working mail setup on your system. A package that provides
|
||||
// 'mailx' must be installed. E.g. "user@example.com"
|
||||
Unattended-Upgrade::Mail "root";
|
||||
|
||||
// Set this value to "true" to get emails only on errors. Default
|
||||
// is to always send a mail if Unattended-Upgrade::Mail is set
|
||||
Unattended-Upgrade::MailOnlyOnError "true";
|
||||
|
||||
// Do automatic removal of new unused dependencies after the upgrade
|
||||
// (equivalent to apt-get autoremove)
|
||||
//Unattended-Upgrade::Remove-Unused-Dependencies "false";
|
||||
|
||||
// Automatically reboot *WITHOUT CONFIRMATION* if
|
||||
// the file /var/run/reboot-required is found after the upgrade
|
||||
//Unattended-Upgrade::Automatic-Reboot "false";
|
||||
|
||||
// Automatically reboot even if there are users currently logged in.
|
||||
//Unattended-Upgrade::Automatic-Reboot-WithUsers "true";
|
||||
|
||||
// If automatic reboot is enabled and needed, reboot at the specific
|
||||
// time instead of immediately
|
||||
// Default: "now"
|
||||
//Unattended-Upgrade::Automatic-Reboot-Time "02:00";
|
||||
|
||||
// Use apt bandwidth limit feature, this example limits the download
|
||||
// speed to 70kb/sec
|
||||
//Acquire::http::Dl-Limit "70";
|
||||
|
||||
// Enable logging to syslog. Default is False
|
||||
// Unattended-Upgrade::SyslogEnable "false";
|
||||
|
||||
// Specify syslog facility. Default is daemon
|
||||
// Unattended-Upgrade::SyslogFacility "daemon";
|
||||
|
22
roles/wireguard/README.md
Normal file
22
roles/wireguard/README.md
Normal file
|
@ -0,0 +1,22 @@
|
|||
# Wireguard
|
||||
|
||||
Définit un réseau Wireguard avec les pairs définis.
|
||||
|
||||
## Variables
|
||||
|
||||
* `wg_if_name`: nom de l'interface Wireguard à créer.
|
||||
* `wg_port`: port à utiliser pour la communication Wireguard. Par défaut,
|
||||
`51810`.
|
||||
* `wg_addr`: adresse IP à utiliser sur cette interface, avec son préfixe CIDR.
|
||||
* `wg_keepalive`: `true` pour envoyer des keepalive réguliers. Par défaut,
|
||||
`false`.
|
||||
* `wg_peers`: liste des pairs wireguard à configurer (également configurés par
|
||||
ce rôle). Chaque entrée de cette liste est le nom du pair dans l'inventaire ;
|
||||
* `wg_extra_hosts`: liste des pairs wireguard à configurer qui ne sont pas
|
||||
gérés par ce rôle ansible. Chaque entrée de cette liste est un dictionnaire
|
||||
contenant :
|
||||
* `host`: nom de la machine ;
|
||||
* `hostaddr`: adresse de la machine dans le réseau wireguard, sans préfixe
|
||||
* `pk`: clé publique de la machine ;
|
||||
* `endpoint`: optionnel. Adresse à laquelle cette machine peut être jointe
|
||||
pour initier la connexion wireguard.
|
4
roles/wireguard/defaults/main.yml
Normal file
4
roles/wireguard/defaults/main.yml
Normal file
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
wg_port: 51810
|
||||
wg_keepalive: false
|
||||
wg_extra_hosts: []
|
10
roles/wireguard/handlers/main.yml
Normal file
10
roles/wireguard/handlers/main.yml
Normal file
|
@ -0,0 +1,10 @@
|
|||
---
|
||||
- name: restart wireguard
|
||||
systemd:
|
||||
name: "wg-quick@{{ wg_if_name }}"
|
||||
state: restarted
|
||||
become: yes
|
||||
- name: wireguard daemon-reload
|
||||
systemd:
|
||||
daemon-reload: yes
|
||||
become: yes
|
77
roles/wireguard/tasks/main.yml
Normal file
77
roles/wireguard/tasks/main.yml
Normal file
|
@ -0,0 +1,77 @@
|
|||
---
|
||||
### Install Wireguard
|
||||
|
||||
- name: "Install wireguard"
|
||||
apt:
|
||||
name:
|
||||
- wireguard
|
||||
- wireguard-tools
|
||||
become: yes
|
||||
|
||||
### Generate keys
|
||||
|
||||
- name: Create keys directory
|
||||
file:
|
||||
path: '/etc/wireguard/keys'
|
||||
state: directory
|
||||
owner: root
|
||||
mode: 0700
|
||||
become: yes
|
||||
- name: Generate keypair
|
||||
shell:
|
||||
chdir: '/etc/wireguard/keys'
|
||||
cmd: "wg genkey | tee /etc/wireguard/keys/{{ wg_if_name }}-private.key
|
||||
| wg pubkey > /etc/wireguard/keys/{{ wg_if_name }}-public.key"
|
||||
creates: "/etc/wireguard/keys/{{ wg_if_name }}-private.key"
|
||||
# ^^^ n'est pas exécuté si ce fichier existe déjà.
|
||||
become: yes
|
||||
- name: Set private key file permissions
|
||||
file:
|
||||
path: "/etc/wireguard/keys/{{ wg_if_name }}-private.key"
|
||||
owner: root
|
||||
mode: 0600
|
||||
state: file
|
||||
become: yes
|
||||
- name: Read public key file
|
||||
slurp:
|
||||
src: /etc/wireguard/keys/{{ wg_if_name }}-public.key
|
||||
become: yes
|
||||
register: wireguard_public_key_file
|
||||
- name: Set public key as a host fact
|
||||
set_fact:
|
||||
wg_public_key: "{{ wireguard_public_key_file['content']
|
||||
| b64decode | regex_replace('\n$', '') }}"
|
||||
|
||||
### Deploy Wireguard configuration
|
||||
|
||||
- name: Create wg-quick service override directory
|
||||
file:
|
||||
path: "/etc/systemd/system/wg-quick@.service.d/"
|
||||
state: directory
|
||||
owner: root
|
||||
mode: 0755
|
||||
become: yes
|
||||
- name: Install wg-quick service override
|
||||
template:
|
||||
src: systemd/wg-quick-override.conf.j2
|
||||
dest: "/etc/systemd/system/wg-quick@.service.d/load-privkey.conf"
|
||||
become: yes
|
||||
notify: wireguard daemon-reload
|
||||
- name: Install wireguard configuration
|
||||
template:
|
||||
src: wireguard/wg.conf.j2
|
||||
dest: "/etc/wireguard/{{ wg_if_name }}.conf"
|
||||
become: yes
|
||||
register: wg_wireguard_config_file
|
||||
notify: restart wireguard
|
||||
- name: Enable wireguard
|
||||
systemd:
|
||||
name: "wg-quick@{{ wg_if_name }}"
|
||||
enabled: yes
|
||||
become: yes
|
||||
|
||||
- name: Etckeeper - commit
|
||||
import_role:
|
||||
name: etckeeper_commit
|
||||
vars:
|
||||
etckeeper_reason: "Configure wireguard for {{ wg_if_name }}"
|
|
@ -0,0 +1,5 @@
|
|||
{{ ansible_managed | comment }}
|
||||
|
||||
[Service]
|
||||
# Load private key from file, if it exists
|
||||
ExecStartPost=-/usr/bin/wg set %i private-key /etc/wireguard/keys/{{ wg_if_name }}-private.key
|
31
roles/wireguard/templates/wireguard/wg.conf.j2
Normal file
31
roles/wireguard/templates/wireguard/wg.conf.j2
Normal file
|
@ -0,0 +1,31 @@
|
|||
{{ ansible_managed | comment }}
|
||||
|
||||
[Interface]
|
||||
ListenPort = {{ wg_port }}
|
||||
Address = {{ wg_addr }}
|
||||
|
||||
{% for peer in wg_peers %}
|
||||
# {{ peer }}
|
||||
[Peer]
|
||||
PublicKey = {{ hostvars[peer].wg_public_key }}
|
||||
Endpoint = {{ hostvars[peer].inventory_hostname}}:{{ wg_port }}
|
||||
AllowedIPs = {{ hostvars[peer].wg_addr | ipaddr('address') }}/128
|
||||
{% if wg_keepalive -%}
|
||||
PersistentKeepalive = 25
|
||||
{%- endif %}
|
||||
|
||||
{% endfor %}
|
||||
|
||||
{% for peer in wg_extra_hosts %}
|
||||
# {{ peer['host'] }}
|
||||
[Peer]
|
||||
PublicKey = {{ peer['pk'] }}
|
||||
AllowedIPs = {{ peer['hostaddr'] }}/128
|
||||
{% if 'endpoint' in peer %}
|
||||
Endpoint = {{ peer['endpoint'] }}:{{ wg_port }}
|
||||
{% endif %}
|
||||
{% if wg_keepalive -%}
|
||||
PersistentKeepalive = 25
|
||||
{%- endif %}
|
||||
|
||||
{% endfor %}
|
Loading…
Add table
Reference in a new issue