diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8012a19 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +vault +.vault_pass diff --git a/Makefile b/Makefile index ec4e04f..c259bb7 100644 --- a/Makefile +++ b/Makefile @@ -1,15 +1,20 @@ -install: - ANSIBLE_HOST_KEY_CHECKING=False ansible-playbook -i "inventory/hosts.yml" "init.yml" --extra-vars "enable_setup=true enable_wireguard=true enable_k3s=true" +init: + ANSIBLE_VAULT_PASSWORD_FILE=./.vault_pass ANSIBLE_HOST_KEY_CHECKING=False ansible-playbook -i "inventory/hosts.yml" "init.yml" -setup: - ANSIBLE_HOST_KEY_CHECKING=False ansible-playbook -i "inventory/hosts.yml" "init.yml" --extra-vars "enable_setup=true enable_wireguard=false enable_k3s=false" +install: + ANSIBLE_VAULT_PASSWORD_FILE=./.vault_pass ANSIBLE_HOST_KEY_CHECKING=False ansible-playbook -i "inventory/hosts.yml" "bootstrap.yml" --extra-vars "enable_setup=true enable_wireguard=true enable_k3s=true" wg: - ANSIBLE_HOST_KEY_CHECKING=False ansible-playbook -i "inventory/hosts.yml" "init.yml" --extra-vars "enable_setup=false enable_wireguard=true enable_k3s=false" + ANSIBLE_VAULT_PASSWORD_FILE=./.vault_pass ANSIBLE_HOST_KEY_CHECKING=False ansible-playbook -i "inventory/hosts.yml" "bootstrap.yml" --extra-vars "enable_wireguard=true enable_k3s=false" k3s: - ANSIBLE_HOST_KEY_CHECKING=False ansible-playbook -i "inventory/hosts.yml" "init.yml" --extra-vars "enable_setup=false enable_wireguard=false enable_k3s=true" + ANSIBLE_VAULT_PASSWORD_FILE=./.vault_pass ANSIBLE_HOST_KEY_CHECKING=False ansible-playbook -i "inventory/hosts.yml" "bootstrap.yml" --extra-vars "enable_wireguard=false enable_k3s=true" uninstall: - ANSIBLE_HOST_KEY_CHECKING=False ansible-playbook -i "inventory/hosts.yml" "k3s-ansible/reset.yml" + ANSIBLE_VAULT_PASSWORD_FILE=./.vault_pass ANSIBLE_HOST_KEY_CHECKING=False ansible-playbook -i "inventory/hosts.yml" "k3s-ansible/reset.yml" +ping: + ANSIBLE_VAULT_PASSWORD_FILE=./.vault_pass ANSIBLE_HOST_KEY_CHECKING=False ansible all -i inventory/hosts.yml --extra-vars "@inventory/vars/main.yaml" -m ping + +ping-unprovisioned: + ANSIBLE_VAULT_PASSWORD_FILE=./.vault_pass ANSIBLE_HOST_KEY_CHECKING=False ansible all -i inventory/unprovisioned.yml -m ping diff --git a/README.md b/README.md index 8d1ee2f..7b28ed2 100644 --- a/README.md +++ b/README.md @@ -1,44 +1,64 @@ # Ansible Catalogue of Ansible playbooks and helper scripts for server management +atmen: slave, servant -## TODO -- Split user provisioning to get rid of `creator` and use `atmen` as fast as possible | This should be done using two differnt playbooks, and switch user between the two -- Add configuration for `creator` to lock the account after initial provisioning, only allowing short connection with returned message - -### Disable creator -Change `~/.profile` to only contain a print message and `exit 0` -Add `.hushlogin` to remove ssh login message +## Configuration options +### SSH Ports +The ssh port can be configured in 2 steps: +1. Change the `ansible_ssh_port` variable in `inventory/group_vars/all.yml` +2. Change the `sshd_port` variable in `inventory/vars/unprovisioned.yaml` ## Node configuration process -### Setup user configuration -- Create provisioning user without password and sudo -- Create tanguy user with password +### Provisioning +- Add atmen user for provisioning +- Configure SSH key for atmen user +- Add maintainer user +- Configure SSH key for maintainer user - Disable root login (passwd --lock root) - -### SSH Setup -- Install fail2ban +- Disable SSH login for creator user - Disable SSH password login - Change SSH port +### SSH Setup +- Install fail2ban + ### Miscellaneous -- Test if unattended-upgrade is installed -- Disable if true +- Disable unattended-upgrade is installed - Disable IPv6 - Setup hostname +- Install open-iscsi, nfs-common, nfs-utils -### Softwares -- Install k3s with token -- Install OMV for NAS node*(s) +### OMV configuration +- Install OMV through OMV-extras +- (lab) Add Vagrant user to SSH group +- Add atmen user to sudoers +- Install openmediavault-zfs, openmediavault-s3, openmediavault-filebrowser -## Update system -- General package manager update - -# Additional configuration -- Add label to output node on k3s to enable load balancer - -# OMV configuration +# OMV manual configuration ## NFS configuration - Create FS - Enable NFS - `subtree_check,insecure,no_root_squash,anonuid=1000,anongid=100` in NFS share extra options + +# Vault +Sensitive data is stored under two files in the `vault` directory: +- `user_provisioning.yml` contains the vault password +- `vault.yml` contains the sensitive data + +## user_provisioning.yml +Configure users for provisioning and manual maintenance +```yaml +vault_atmen_password: +vault_maintainer_user: +vault_maintainer_password: +``` + +## vault.yml +Configure k3s secrets +```yaml +ansible_become_password: +token: +``` + +To avoid pasting your vault password everytime, you can create a `.vault_pass` file in the root directory with the vault password. diff --git a/bootstrap.yml b/bootstrap.yml new file mode 100644 index 0000000..e535380 --- /dev/null +++ b/bootstrap.yml @@ -0,0 +1,29 @@ +--- +- hosts: all + gather_facts: no + tasks: + - name: Include vault vars + include_vars: + file: "{{ playbook_dir ~ '/vault/secrets' }}" + - name: Include vars + include_vars: + file: inventory/vars/main.yaml + - name: Wait for hosts + ansible.builtin.wait_for_connection: + timeout: 60 + - name: Gathering facts + setup: + - name: Start basic node configuration + include_role: + name: node-configuration + when: enable_setup | bool + - name: Configure headscale + include_role: + name: headscale + when: enable_headscale|bool +- name: Configure wireguard + ansible.builtin.import_playbook: wireguard/wireguard.yml + when: enable_wireguard|bool +- name: Configure k3s + ansible.builtin.import_playbook: k3s-ansible/site.yml + when: enable_k3s | bool diff --git a/init.yml b/init.yml index 6a95ec6..bcf3056 100644 --- a/init.yml +++ b/init.yml @@ -1,17 +1,15 @@ --- - hosts: all + gather_facts: no tasks: - - name: Start basic node configuration + - name: Add unprovisioned vars + include_vars: + file: inventory/vars/unprovisioned.yaml + - name: Wait for hosts + ansible.builtin.wait_for_connection: + timeout: 60 + - name: Gathering facts + setup: + - name: Provision users include_role: - name: node-configuration - when: enable_setup | bool - - name: Configure headscale - include_role: - name: headscale - when: enable_wireguard | bool - # - name: Configure wireguard - # ansible.builtin.import_playbook: wireguard/wireguard.yml - # when: enable_wireguard|bool == true -- name: Configure k3s - ansible.builtin.import_playbook: k3s-ansible/site.yml - when: enable_k3s | bool + name: user-provision diff --git a/inventory/group_vars/all.yml b/inventory/group_vars/all.yml index 4d2a288..e7dcb73 100644 --- a/inventory/group_vars/all.yml +++ b/inventory/group_vars/all.yml @@ -1,6 +1,11 @@ --- k3s_version: "v1.29.2+k3s1" systemd_dir: "/etc/systemd/system" -master_ip: "{{ hostvars[groups['master'][0]]['wireguard_ip'] | default(groups['master'][0]) }}" +api_endpoint: "{{ hostvars[groups['server'][0]]['wireguard_ip'] | default(groups['server'][0]) }}" extra_server_args: "--disable traefik --advertise-address {{hostvars[inventory_hostname]['wireguard_ip']}} --flannel-iface wg0 --tls-san {{ ansible_host }} --disable servicelb {{ ['--node-label']|product(hostvars[inventory_hostname]['k3s_label'])|map('join', ' ')|join(' ') }}" extra_agent_args: "--flannel-iface wg0 --node-external-ip {{hostvars[inventory_hostname]['wireguard_ip']}} {{ ['--node-label']|product(hostvars[inventory_hostname]['k3s_label'])|map('join', ' ')|join(' ') }}" +ansible_python_interpreter: /usr/bin/python3 +ansible_ssh_port: 22 +ufw_enabled: false +wireguard_port: 51820 +wireguard_mask_bits: 8 diff --git a/inventory/hosts.template.yml b/inventory/hosts.template.yml new file mode 100644 index 0000000..022953e --- /dev/null +++ b/inventory/hosts.template.yml @@ -0,0 +1,36 @@ +all: + hosts: + cp: + ansible_host: 192.168.56.101 + is_nas: false + hostname: cp + wireguard_ip: 10.20.0.1 + k3s_label: + - type=worker + - size=wide + vps: + ansible_host: 192.168.56.102 + is_nas: false + hostname: vps + wireguard_ip: 10.20.0.2 + k3s_label: + - type=outbound + children: + server: + hosts: + cp: + agent: + hosts: + vps: + k3s_cluster: + children: + server: + agent: + vars: + k3s_version: v1.28.5+k3s1 + api_endpoint: "{{ hostvars[groups['server'][0]]['wireguard_ip'] | default(groups['server'][0]) }}" + extra_server_args: "--disable traefik --advertise-address {{hostvars[inventory_hostname]['wireguard_ip']}} --flannel-iface wg0 --tls-san {{hostvars[inventory_hostname]['wireguard_ip']}} --disable servicelb {{ ['--node-label']|product(hostvars[inventory_hostname]['k3s_label'])|map('join', ' ')|join(' ') }}" + extra_agent_args: "--flannel-iface wg0 --node-external-ip {{hostvars[inventory_hostname]['wireguard_ip']}} {{ ['--node-label']|product(hostvars[inventory_hostname]['k3s_label'])|map('join', ' ')|join(' ') }}" + ufw_enabled: false + wireguard_port: 51820 + wireguard_mask_bits: 8 diff --git a/inventory/hosts.yml b/inventory/hosts.yml index ac76f29..cea3002 100644 --- a/inventory/hosts.yml +++ b/inventory/hosts.yml @@ -1,45 +1,28 @@ all: - hosts: + hosts: + cp: + ansible_host: 192.168.56.101 + is_nas: false + hostname: cp + wireguard_ip: 10.20.0.1 + k3s_label: + - type=worker + - size=wide + vps: + ansible_host: 192.168.56.102 + is_nas: false + hostname: vps + wireguard_ip: 10.20.0.2 + k3s_label: + - type=outbound + children: + server: + hosts: cp: - ansible_host: 10.10.0.64 - is_nas: false - hostname: cp - wireguard_ip: 10.20.0.2 - outsider: - ansible_host: 51.15.60.240 - is_nas: false - hostname: outsider - wireguard_ip: 10.20.0.1 - children: - master: - hosts: - cp: - node: - hosts: - outsider: - etcd_cluster: - hosts: - cp: - outsider: - master: - hosts: - cp: - replica: - hosts: - outsider: - postgres_cluster: - children: - master: - replica: - k3s_cluster: - children: - master: - node: - vars: - ansible_ssh_private_key_file: ~/.ssh/creator - ansible_user: creator - ansible_become_password: aberation - ansible_ssh_port: 22 - ufw_enabled: false - wireguard_port: 51820 - wireguard_mask_bits: 8 + agent: + hosts: + vps: + k3s_cluster: + children: + server: + agent: diff --git a/inventory/vars/main.yml b/inventory/vars/main.yml new file mode 100644 index 0000000..d0f5df6 --- /dev/null +++ b/inventory/vars/main.yml @@ -0,0 +1,2 @@ +ansible_ssh_private_key_file: ~/.ssh/atmen +ansible_user: atmen diff --git a/inventory/vars/unprovisioned.yml b/inventory/vars/unprovisioned.yml new file mode 100644 index 0000000..dd0c5a1 --- /dev/null +++ b/inventory/vars/unprovisioned.yml @@ -0,0 +1,5 @@ +ansible_ssh_private_key_file: ~/.ssh/creator +ansible_user: creator +ansible_become_password: aberation +ansible_ssh_port: 22 +sshd_port: 22 diff --git a/inventory/vars/vagrant.yml b/inventory/vars/vagrant.yml new file mode 100644 index 0000000..c9773cc --- /dev/null +++ b/inventory/vars/vagrant.yml @@ -0,0 +1 @@ +vagrant: true diff --git a/k3s-ansible b/k3s-ansible index fe3df5c..9c8ba5c 160000 --- a/k3s-ansible +++ b/k3s-ansible @@ -1 +1 @@ -Subproject commit fe3df5c836fa93e0a7de3a588a07095112833bbb +Subproject commit 9c8ba5c1555944f02f7ffadc3b0839530b2782f7 diff --git a/misc/defaults/main.yml b/misc/defaults/main.yml deleted file mode 100644 index 6caa488..0000000 --- a/misc/defaults/main.yml +++ /dev/null @@ -1,4 +0,0 @@ ---- -# defaults file for misc -ansible_default_user: autositos -ssh_key_filename: id_autositos_rsa diff --git a/misc/handlers/main.yml b/misc/handlers/main.yml deleted file mode 100644 index a0648b5..0000000 --- a/misc/handlers/main.yml +++ /dev/null @@ -1,2 +0,0 @@ ---- -# handlers file for misc diff --git a/misc/tasks/main.yml b/misc/tasks/main.yml deleted file mode 100644 index f86811d..0000000 --- a/misc/tasks/main.yml +++ /dev/null @@ -1,2 +0,0 @@ ---- -# tasks file for misc diff --git a/misc/tasks/user.yml b/misc/tasks/user.yml deleted file mode 100644 index 8f4f446..0000000 --- a/misc/tasks/user.yml +++ /dev/null @@ -1,32 +0,0 @@ ---- -- name: Create provisioning user - hosts: all - become: true - gather_facts: false - tasks: - - name: Create user - ansible.builtin.user: - name: "{{ ansible_default_user }}" - comment: Automation user for ansible - state: present - append: yes - system: True - create_home: True - - - name: Generate master SSH key - community.crypto.openssh_keypair: - path: "/home/{{ ansible_default_user }}/.ssh/{{ ssh_key_filename }}" - type: rsa - size: 4096 - state: present - force: no - tags: - - init - - - name: Deploy SSH public key - ansible.posix.authorized_key: - user: "{{ ansible_default_user }}" - state: present - key: "{{ lookup('file', '/home/{{ ansible_default_user }}/.ssh/{{ ssh_key_filename }}.pub') }}" - when: "'init' not in ansible_run_tags" - diff --git a/misc/tests/inventory b/misc/tests/inventory deleted file mode 100644 index 878877b..0000000 --- a/misc/tests/inventory +++ /dev/null @@ -1,2 +0,0 @@ -localhost - diff --git a/misc/tests/test.yml b/misc/tests/test.yml deleted file mode 100644 index 98779a7..0000000 --- a/misc/tests/test.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -- hosts: localhost - remote_user: root - roles: - - misc diff --git a/misc/vars/main.yml b/misc/vars/main.yml deleted file mode 100644 index a719f69..0000000 --- a/misc/vars/main.yml +++ /dev/null @@ -1,2 +0,0 @@ ---- -# vars file for misc diff --git a/node-configuration/defaults/main.yml b/node-configuration/defaults/main.yml deleted file mode 100644 index 85e8569..0000000 --- a/node-configuration/defaults/main.yml +++ /dev/null @@ -1,2 +0,0 @@ ---- -# defaults file for node-configuration diff --git a/node-configuration/tasks/main.yml b/node-configuration/tasks/main.yml index ddfee36..486f464 100644 --- a/node-configuration/tasks/main.yml +++ b/node-configuration/tasks/main.yml @@ -1,9 +1,4 @@ --- -# tasks file for node-configuration -- name: Setup user configuration - import_tasks: ./users.yml - become: yes - - name: Configure and harden SSH import_tasks: ./ssh.yml become: yes diff --git a/node-configuration/tasks/omv.yaml b/node-configuration/tasks/omv.yaml index 68b8e3a..c0526c2 100644 --- a/node-configuration/tasks/omv.yaml +++ b/node-configuration/tasks/omv.yaml @@ -16,12 +16,13 @@ - name: Install OMV-extras ansible.builtin.shell: /tmp/omv-extras.install -n -f >> /tmp/omv-extras.log -# TODO: Only enable this within Homelab configuration +# Check for vagrant variable, indicating we are running in a lab environment - name: Add Vagrant user to ssh group ansible.builtin.user: name: vagrant groups: ssh append: yes + when: vagrant | default(false) - name: Add Ansible user to ssh group ansible.builtin.user: diff --git a/node-configuration/tasks/ssh.yml b/node-configuration/tasks/ssh.yml index 7c35b29..3e31f33 100644 --- a/node-configuration/tasks/ssh.yml +++ b/node-configuration/tasks/ssh.yml @@ -19,18 +19,3 @@ ansible.builtin.package: name: fail2ban state: present - -- name: Disable password login - lineinfile: - dest: "/etc/ssh/sshd_config" - regexp: '^(#\s*)?PasswordAuthentication ' - line: "PasswordAuthentication no" - notify: restart sshd - -- name: Change SSH port - lineinfile: - dest: "/etc/ssh/sshd_config" - regexp: "^Port " - line: "Port {{ sshd_port }}" - notify: restart sshd - when: 0 > 1 diff --git a/node-configuration/tests/inventory b/node-configuration/tests/inventory deleted file mode 100644 index 878877b..0000000 --- a/node-configuration/tests/inventory +++ /dev/null @@ -1,2 +0,0 @@ -localhost - diff --git a/node-configuration/tests/test.yml b/node-configuration/tests/test.yml deleted file mode 100644 index f5f13d6..0000000 --- a/node-configuration/tests/test.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -- hosts: localhost - remote_user: root - roles: - - node-configuration diff --git a/node-configuration/vars/main.yml b/node-configuration/vars/main.yml deleted file mode 100644 index 57dc0ec..0000000 --- a/node-configuration/vars/main.yml +++ /dev/null @@ -1,2 +0,0 @@ ---- -# vars file for node-configuration diff --git a/node-configuration/vars/users.yml b/node-configuration/vars/users.yml deleted file mode 100644 index 2733fd5..0000000 --- a/node-configuration/vars/users.yml +++ /dev/null @@ -1,3 +0,0 @@ ---- -maintainer_user: joe -maintainer_password: testing # To be stored in vault diff --git a/misc/README.md b/user-provision/README.md similarity index 100% rename from misc/README.md rename to user-provision/README.md diff --git a/user-provision/handlers/main.yml b/user-provision/handlers/main.yml new file mode 100644 index 0000000..7f10802 --- /dev/null +++ b/user-provision/handlers/main.yml @@ -0,0 +1,8 @@ +--- +- name: Restart sshd service + ansible.builtin.service: + name: sshd + state: restarted + listen: "restart sshd" + ignore_errors: yes + become: yes diff --git a/misc/meta/main.yml b/user-provision/meta/main.yml similarity index 71% rename from misc/meta/main.yml rename to user-provision/meta/main.yml index c572acc..ea68190 100644 --- a/misc/meta/main.yml +++ b/user-provision/meta/main.yml @@ -21,24 +21,6 @@ galaxy_info: # If this a Container Enabled role, provide the minimum Ansible Container version. # min_ansible_container_version: - # - # Provide a list of supported platforms, and for each platform a list of versions. - # If you don't wish to enumerate all versions for a particular platform, use 'all'. - # To view available platforms and versions (or releases), visit: - # https://galaxy.ansible.com/api/v1/platforms/ - # - # platforms: - # - name: Fedora - # versions: - # - all - # - 25 - # - name: SomePlatform - # versions: - # - all - # - 1.0 - # - 7 - # - 99.99 - galaxy_tags: [] # List tags for your role here, one per line. A tag is a keyword that describes # and categorizes the role. Users find roles by searching for tags. Be sure to diff --git a/user-provision/tasks/main.yml b/user-provision/tasks/main.yml new file mode 100644 index 0000000..9d83db2 --- /dev/null +++ b/user-provision/tasks/main.yml @@ -0,0 +1,60 @@ +- block: + - include_vars: "{{ playbook_dir ~ '/vault/user_provisioning' }}" + # Atmen : slave, servant + - name: Add provisioning user "atmen" for ansible + ansible.builtin.user: + name: atmen + comment: Ansible provisioner + groups: sudo + append: yes + shell: /bin/bash + password: "{{ vault_atmen_password | password_hash('sha512') }}" + + - name: Set authorized key for atmen + ansible.posix.authorized_key: + user: atmen + state: present + key: "{{ lookup('file', atmen_ssh_key_host_path) }}" + + - name: Add maintainer user + ansible.builtin.user: + name: "{{ vault_maintainer_user }}" + comment: Maintainer user + groups: sudo + append: yes + shell: /bin/bash + password: "{{ vault_maintainer_password | password_hash('sha512') }}" + + - name: Set authorized key for maintainer user + ansible.posix.authorized_key: + user: "{{ vault_maintainer_user }}" + state: present + key: "{{ lookup('file', maintainer_ssh_key_host_path) }}" + + - name: Disable root login + ansible.builtin.user: + name: root + password: '*' + + - name: Disable SSH login for creator + ansible.builtin.lineinfile: + path: /etc/ssh/sshd_config + line: DenyUsers creator + state: present + + - name: Disable password login + lineinfile: + dest: "/etc/ssh/sshd_config" + regexp: '^(#\s*)?PasswordAuthentication ' + line: "PasswordAuthentication no" + notify: restart sshd + + - name: Change SSH port + lineinfile: + dest: "/etc/ssh/sshd_config" + regexp: "^Port " + line: "Port {{ sshd_port }}" + notify: restart sshd + changed_when: true + + become: yes diff --git a/user-provision/vars/main.yml b/user-provision/vars/main.yml new file mode 100644 index 0000000..417c97f --- /dev/null +++ b/user-provision/vars/main.yml @@ -0,0 +1,3 @@ +--- +atmen_ssh_key_host_path: ~/.ssh/atmen.pub +maintainer_ssh_key_host_path: ~/.ssh/maintainer.pub