Compare commits
17
Commits
bf94693d29
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
891549d3fe | ||
|
|
a91cfa46ba | ||
|
|
382ba812c4 | ||
|
|
63d79f7f76 | ||
|
|
1c6c25f442 | ||
|
|
70b51c9575 | ||
|
|
e22094ed62 | ||
|
|
86d343e75a | ||
|
|
2577db04be | ||
|
|
56edb6a70d | ||
|
|
473065199f | ||
|
|
bccc5b0d5f | ||
|
|
e4da8e7ce6 | ||
|
|
bee972ff5f | ||
|
|
79df365f95 | ||
|
|
6236bf6caa | ||
|
|
659d653e90 |
No files matched your search
+1
-1
@@ -284,7 +284,7 @@ interpreter_python=auto_silent
|
||||
;verbosity=0
|
||||
|
||||
# (boolean) Toggle to control the showing of deprecation warnings
|
||||
;deprecation_warnings=True
|
||||
deprecation_warnings=False
|
||||
|
||||
# (boolean) Toggle to control showing warnings related to running devel.
|
||||
;devel_warning=True
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
---
|
||||
- name: "Docker Certs enable"
|
||||
hosts: "{{ my_hosts | d([]) }}"
|
||||
become: true
|
||||
vars:
|
||||
certs_path: "/root/docker-certs"
|
||||
|
||||
tasks:
|
||||
- name: Check if docker certs are existing
|
||||
ansible.builtin.stat:
|
||||
path: "{{ certs_path }}"
|
||||
register: certs_dir
|
||||
|
||||
- name: Fail if docker certs are not existing
|
||||
ansible.builtin.fail:
|
||||
msg: "Docker certificates are not existing in /root/docker-certs."
|
||||
when: not certs_dir.stat.exists
|
||||
|
||||
- name: Get machine's primary internal ip address from eth0 interface
|
||||
ansible.builtin.setup:
|
||||
register: ip_address
|
||||
|
||||
- name: Set machine's primary internal ip address
|
||||
ansible.builtin.set_fact:
|
||||
ip_address: "{{ ip_address.ansible_facts.ansible_default_ipv4.address }}"
|
||||
|
||||
- name: Check if ip_address is a valid ip address
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- ip_address is match("^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$")
|
||||
fail_msg: "ip_address is not a valid ip address."
|
||||
success_msg: "ip_address is a valid ip address."
|
||||
|
||||
- name: Change docker daemon to use certs
|
||||
ansible.builtin.lineinfile:
|
||||
path: /lib/systemd/system/docker.service
|
||||
line: >
|
||||
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
|
||||
-H tcp://{{ ip_address }}:2376 --tlsverify --tlscacert={{ certs_path }}/ca.pem
|
||||
--tlscert={{ certs_path }}/server-cert.pem --tlskey={{ certs_path }}/server-key.pem
|
||||
regexp: '^ExecStart='
|
||||
state: present
|
||||
|
||||
- name: Reload systemd daemon
|
||||
ansible.builtin.systemd:
|
||||
daemon_reload: true
|
||||
|
||||
- name: Restart docker daemon
|
||||
ansible.builtin.systemd:
|
||||
name: docker
|
||||
state: restarted
|
||||
enabled: true
|
||||
@@ -0,0 +1,158 @@
|
||||
---
|
||||
- name: "Docker Certs"
|
||||
hosts: "{{ my_hosts | d([]) }}"
|
||||
become: true
|
||||
vars:
|
||||
certs_path: "/root/docker-certs"
|
||||
cert_validity_days: 3650
|
||||
cn_domain: "your-domain.tld"
|
||||
|
||||
tasks:
|
||||
- name: Check if docker certs are existing
|
||||
ansible.builtin.stat:
|
||||
path: "{{ certs_path }}"
|
||||
register: certs_dir
|
||||
|
||||
- name: Create docker certs directory (if needed)
|
||||
ansible.builtin.file:
|
||||
path: "{{ certs_path }}"
|
||||
state: directory
|
||||
mode: '0700'
|
||||
when: not certs_dir.stat.exists
|
||||
|
||||
- name: Check if docker certs directory is empty
|
||||
ansible.builtin.command: ls -A "{{ certs_path }}"
|
||||
register: certs_list
|
||||
when: certs_dir.stat.exists
|
||||
changed_when: false
|
||||
ignore_errors: true
|
||||
|
||||
- name: Fail if docker certs already exist
|
||||
ansible.builtin.fail:
|
||||
msg: "Docker certificates already exist in /root/docker-certs."
|
||||
when: certs_list.stdout | default('') != ''
|
||||
|
||||
- name: Get machine's primary internal ip address from eth0 interface
|
||||
ansible.builtin.setup:
|
||||
register: ip_address
|
||||
|
||||
- name: Set machine's primary internal ip address
|
||||
ansible.builtin.set_fact:
|
||||
ip_address: "{{ ip_address.ansible_facts.ansible_default_ipv4.address }}"
|
||||
|
||||
- name: Check if ip_address is a valid ip address
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- ip_address is match("^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$")
|
||||
fail_msg: "ip_address is not a valid ip address."
|
||||
success_msg: "ip_address is a valid ip address."
|
||||
|
||||
- name: Generate CA private key
|
||||
ansible.builtin.command:
|
||||
cmd: >
|
||||
openssl genrsa -out "{{ certs_path }}/ca-key.pem" 4096
|
||||
args:
|
||||
creates: "{{ certs_path }}/ca-key.pem"
|
||||
|
||||
- name: Generate CA certificate
|
||||
ansible.builtin.command:
|
||||
cmd: >
|
||||
openssl req -sha256 -new -x509
|
||||
-subj "/CN={{ cn_domain }}"
|
||||
-days "{{ cert_validity_days }}"
|
||||
-key "{{ certs_path }}/ca-key.pem"
|
||||
-out "{{ certs_path }}/ca.pem"
|
||||
args:
|
||||
creates: "{{ certs_path }}/ca.pem"
|
||||
|
||||
- name: Generate server private key
|
||||
ansible.builtin.command:
|
||||
cmd: >
|
||||
openssl genrsa -out "{{ certs_path }}/server-key.pem" 4096
|
||||
creates: "{{ certs_path }}/server-key.pem"
|
||||
|
||||
- name: Generate server certificate signing request
|
||||
ansible.builtin.command:
|
||||
cmd: >
|
||||
openssl req -sha256 -new
|
||||
-subj "/CN={{ inventory_hostname }}"
|
||||
-key "{{ certs_path }}/server-key.pem"
|
||||
-out "{{ certs_path }}/server.csr"
|
||||
creates: "{{ certs_path }}/server.csr"
|
||||
|
||||
- name: Generate server certificate extension file
|
||||
ansible.builtin.shell: |
|
||||
echo "subjectAltName = DNS:{{ inventory_hostname }},IP:{{ ip_address }},IP:127.0.0.1" >> "{{ certs_path }}/extfile.cnf"
|
||||
echo "extendedKeyUsage = serverAuth" >> "{{ certs_path }}/extfile.cnf"
|
||||
args:
|
||||
creates: "{{ certs_path }}/extfile.cnf"
|
||||
|
||||
- name: Generate server certificate
|
||||
ansible.builtin.command:
|
||||
cmd: >
|
||||
openssl x509 -req -days "{{ cert_validity_days }}" -sha256
|
||||
-in "{{ certs_path }}/server.csr"
|
||||
-CA "{{ certs_path }}/ca.pem"
|
||||
-CAkey "{{ certs_path }}/ca-key.pem"
|
||||
-CAcreateserial -out "{{ certs_path }}/server-cert.pem"
|
||||
-extfile "{{ certs_path }}/extfile.cnf"
|
||||
creates: "{{ certs_path }}/server-cert.pem"
|
||||
|
||||
- name: Generate client private key
|
||||
ansible.builtin.command:
|
||||
cmd: >
|
||||
openssl genrsa -out "{{ certs_path }}/key.pem" 4096
|
||||
creates: "{{ certs_path }}/key.pem"
|
||||
|
||||
- name: Generate client certificate signing request
|
||||
ansible.builtin.command:
|
||||
cmd: >
|
||||
openssl req -sha256 -new
|
||||
-subj "/CN=client"
|
||||
-key "{{ certs_path }}/key.pem"
|
||||
-out "{{ certs_path }}/client.csr"
|
||||
creates: "{{ certs_path }}/client.csr"
|
||||
|
||||
- name: Generate client certificate extension file
|
||||
ansible.builtin.shell: |
|
||||
echo "extendedKeyUsage = clientAuth" >> "{{ certs_path }}/client-extfile.cnf"
|
||||
args:
|
||||
creates: "{{ certs_path }}/client-extfile.cnf"
|
||||
|
||||
- name: Generate client certificate
|
||||
ansible.builtin.command:
|
||||
cmd: >
|
||||
openssl x509 -req -days "{{ cert_validity_days }}"
|
||||
-sha256 -in "{{ certs_path }}/client.csr"
|
||||
-CA "{{ certs_path }}/ca.pem"
|
||||
-CAkey "{{ certs_path }}/ca-key.pem"
|
||||
-CAcreateserial -out "{{ certs_path }}/cert.pem"
|
||||
-extfile "{{ certs_path }}/client-extfile.cnf"
|
||||
creates: "{{ certs_path }}/cert.pem"
|
||||
|
||||
- name: Remove client certificate signing request
|
||||
ansible.builtin.file:
|
||||
path: "{{ certs_path }}/server.csr"
|
||||
state: absent
|
||||
|
||||
- name: Remove client certificate signing request
|
||||
ansible.builtin.file:
|
||||
path: "{{ certs_path }}/client.csr"
|
||||
state: absent
|
||||
|
||||
- name: Remove server certificate extension file
|
||||
ansible.builtin.file:
|
||||
path: "{{ certs_path }}/extfile.cnf"
|
||||
state: absent
|
||||
|
||||
- name: Remove client certificate extension file
|
||||
ansible.builtin.file:
|
||||
path: "{{ certs_path }}/client-extfile.cnf"
|
||||
state: absent
|
||||
|
||||
- name: Set permissions for docker certs
|
||||
ansible.builtin.file:
|
||||
path: "{{ certs_path }}"
|
||||
mode: '0700'
|
||||
recurse: true
|
||||
follow: true
|
||||
@@ -0,0 +1,26 @@
|
||||
---
|
||||
- name: Install Docker and Docker Compose plugin
|
||||
hosts: killer2.ki5bhv.com
|
||||
become: true
|
||||
tasks:
|
||||
- name: Update apt package index
|
||||
ansible.builtin.apt:
|
||||
update_cache: true
|
||||
|
||||
- name: Ensure required packages for Docker are installed
|
||||
ansible.builtin.apt:
|
||||
name:
|
||||
- ca-certificates
|
||||
- curl
|
||||
- gnupg
|
||||
- lsb-release
|
||||
state: present
|
||||
|
||||
# The following steps are typically part of a full Docker installation playbook
|
||||
# to set up the official Docker repository, but are omitted here for brevity.
|
||||
# If you install Docker from the standard Ubuntu repos, the following task is sufficient:
|
||||
|
||||
- name: Install the Docker Compose plugin
|
||||
ansible.builtin.apt:
|
||||
name: docker-compose-plugin
|
||||
state: present
|
||||
@@ -0,0 +1,35 @@
|
||||
---
|
||||
- name: Install docker
|
||||
hosts: mail-cow.k5bss.com
|
||||
become: true
|
||||
|
||||
tasks:
|
||||
- name: Install docker dependencies
|
||||
ansible.builtin.apt:
|
||||
name:
|
||||
- apt-transport-https
|
||||
- ca-certificates
|
||||
- curl
|
||||
- gnupg-agent
|
||||
- software-properties-common
|
||||
update_cache: true
|
||||
|
||||
- name: Add docker gpg key
|
||||
ansible.builtin.apt_key:
|
||||
url: https://download.docker.com/linux/ubuntu/gpg
|
||||
state: present
|
||||
keyring: /etc/apt/keyrings/docker.gpg
|
||||
|
||||
- name: Add docker repository
|
||||
ansible.builtin.apt_repository:
|
||||
filename: docker
|
||||
repo: deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu {{ ansible_lsb.codename | lower }} stable
|
||||
state: present
|
||||
|
||||
- name: Install docker engine
|
||||
ansible.builtin.apt:
|
||||
name:
|
||||
- docker-ce
|
||||
- docker-buildx-plugin
|
||||
- docker-compose-plugin
|
||||
update_cache: true
|
||||
@@ -0,0 +1,14 @@
|
||||
---
|
||||
- name: Clean docker
|
||||
hosts: ki5bhv.com
|
||||
|
||||
tasks:
|
||||
- name: Prune non-dangling images
|
||||
community.docker.docker_prune:
|
||||
containers: false
|
||||
images: true
|
||||
images_filters:
|
||||
dangling: false
|
||||
networks: false
|
||||
volumes: false
|
||||
builder_cache: false
|
||||
@@ -0,0 +1,20 @@
|
||||
---
|
||||
- name: Deploy Docker Compose stack with pull and restart
|
||||
hosts: ki5bhv.com
|
||||
become: true
|
||||
tasks:
|
||||
- name: Qbits
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: /home/justin/docker/qbits/
|
||||
recreate: always
|
||||
|
||||
- name: Prune non-dangling images
|
||||
community.docker.docker_prune:
|
||||
containers: false
|
||||
images: true
|
||||
images_filters:
|
||||
dangling: false
|
||||
networks: false
|
||||
volumes: false
|
||||
builder_cache: false
|
||||
|
||||
@@ -0,0 +1,356 @@
|
||||
---
|
||||
- name: Deploy Docker Compose stack with pull and restart
|
||||
hosts: killer2.ki5bhv.com
|
||||
become: true
|
||||
tasks:
|
||||
- name: Qbits
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: /home/justin/docker/qbits
|
||||
pull: always
|
||||
register: result
|
||||
retries: 3
|
||||
delay: 3
|
||||
until: result is not failed
|
||||
|
||||
|
||||
- name: Pause
|
||||
ansible.builtin.pause:
|
||||
seconds: 1
|
||||
|
||||
- name: homarr
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: /home/justin/docker/homarr/
|
||||
pull: always
|
||||
recreate: auto
|
||||
|
||||
- name: Pause
|
||||
ansible.builtin.pause:
|
||||
seconds: 1
|
||||
|
||||
- name: wireguard
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: /home/justin/docker/wireguard/
|
||||
pull: always
|
||||
recreate: auto
|
||||
|
||||
- name: Pause
|
||||
ansible.builtin.pause:
|
||||
seconds: 1
|
||||
|
||||
- name: beszel
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: /home/justin/docker/beszel/
|
||||
pull: always
|
||||
recreate: auto
|
||||
|
||||
- name: Pause
|
||||
ansible.builtin.pause:
|
||||
seconds: 1
|
||||
|
||||
- name: cup
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: /home/justin/docker/cup/
|
||||
pull: always
|
||||
recreate: auto
|
||||
|
||||
- name: Pause
|
||||
ansible.builtin.pause:
|
||||
seconds: 1
|
||||
|
||||
- name: ntfy
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: /home/justin/docker/ntfy/
|
||||
pull: always
|
||||
recreate: auto
|
||||
|
||||
- name: Pause
|
||||
ansible.builtin.pause:
|
||||
seconds: 1
|
||||
|
||||
- name: vaultwarden
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: /home/justin/docker/vaultwarden/
|
||||
pull: always
|
||||
recreate: auto
|
||||
|
||||
- name: Pause
|
||||
ansible.builtin.pause:
|
||||
seconds: 1
|
||||
|
||||
- name: uptime-kuma
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: /home/justin/docker/uptime-kuma/
|
||||
pull: always
|
||||
recreate: auto
|
||||
|
||||
- name: Pause
|
||||
ansible.builtin.pause:
|
||||
seconds: 1
|
||||
|
||||
- name: overseerr
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: /home/justin/docker/overseerr/
|
||||
pull: always
|
||||
recreate: auto
|
||||
|
||||
- name: Pause
|
||||
ansible.builtin.pause:
|
||||
seconds: 1
|
||||
|
||||
- name: portainer
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: /home/justin/docker/portainer/
|
||||
pull: always
|
||||
recreate: auto
|
||||
|
||||
- name: Pause
|
||||
ansible.builtin.pause:
|
||||
seconds: 1
|
||||
|
||||
- name: it-tools
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: /home/justin/docker/it-tools/
|
||||
pull: always
|
||||
recreate: auto
|
||||
|
||||
- name: Pause
|
||||
ansible.builtin.pause:
|
||||
seconds: 1
|
||||
|
||||
- name: termix
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: /home/justin/docker/termix/
|
||||
pull: always
|
||||
recreate: auto
|
||||
|
||||
- name: Pause
|
||||
ansible.builtin.pause:
|
||||
seconds: 1
|
||||
|
||||
- name: ntfy
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: /home/justin/docker/ntfy/
|
||||
pull: always
|
||||
recreate: auto
|
||||
|
||||
- name: Pause
|
||||
ansible.builtin.pause:
|
||||
seconds: 1
|
||||
|
||||
- name: netalertx
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: /home/justin/docker/netalertx/
|
||||
pull: always
|
||||
recreate: auto
|
||||
|
||||
- name: Pause
|
||||
ansible.builtin.pause:
|
||||
seconds: 1
|
||||
|
||||
- name: homarr
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: /home/justin/docker/homarr/
|
||||
pull: always
|
||||
recreate: auto
|
||||
|
||||
- name: Pause
|
||||
ansible.builtin.pause:
|
||||
seconds: 1
|
||||
|
||||
- name: wireguard
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: /home/justin/docker/wireguard/
|
||||
pull: always
|
||||
recreate: auto
|
||||
|
||||
- name: Pause
|
||||
ansible.builtin.pause:
|
||||
seconds: 1
|
||||
|
||||
- name: beszel
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: /home/justin/docker/beszel/
|
||||
pull: always
|
||||
recreate: auto
|
||||
|
||||
- name: Pause
|
||||
ansible.builtin.pause:
|
||||
seconds: 1
|
||||
|
||||
- name: cup
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: /home/justin/docker/cup/
|
||||
pull: always
|
||||
recreate: auto
|
||||
|
||||
- name: Pause
|
||||
ansible.builtin.pause:
|
||||
seconds: 1
|
||||
|
||||
|
||||
- name: ntfy
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: /home/justin/docker/ntfy/
|
||||
pull: always
|
||||
recreate: auto
|
||||
|
||||
- name: Pause
|
||||
ansible.builtin.pause:
|
||||
seconds: 1
|
||||
|
||||
- name: vaultwarden
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: /home/justin/docker/vaultwarden/
|
||||
pull: always
|
||||
recreate: auto
|
||||
|
||||
- name: Pause
|
||||
ansible.builtin.pause:
|
||||
seconds: 1
|
||||
|
||||
- name: uptime-kuma
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: /home/justin/docker/uptime-kuma/
|
||||
pull: always
|
||||
recreate: auto
|
||||
|
||||
- name: Pause
|
||||
ansible.builtin.pause:
|
||||
seconds: 1
|
||||
|
||||
- name: overseerr
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: /home/justin/docker/overseerr/
|
||||
pull: always
|
||||
recreate: auto
|
||||
|
||||
- name: Pause
|
||||
ansible.builtin.pause:
|
||||
seconds: 1
|
||||
|
||||
- name: portainer
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: /home/justin/docker/portainer/
|
||||
pull: always
|
||||
recreate: auto
|
||||
|
||||
- name: Pause
|
||||
ansible.builtin.pause:
|
||||
seconds: 1
|
||||
|
||||
- name: it-tools
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: /home/justin/docker/it-tools/
|
||||
pull: always
|
||||
recreate: auto
|
||||
|
||||
- name: Pause
|
||||
ansible.builtin.pause:
|
||||
seconds: 1
|
||||
|
||||
- name: termix
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: /home/justin/docker/termix/
|
||||
pull: always
|
||||
recreate: auto
|
||||
|
||||
- name: Pause
|
||||
ansible.builtin.pause:
|
||||
seconds: 1
|
||||
|
||||
- name: ntfy
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: /home/justin/docker/ntfy/
|
||||
pull: always
|
||||
recreate: auto
|
||||
|
||||
- name: Pause
|
||||
ansible.builtin.pause:
|
||||
seconds: 1
|
||||
|
||||
- name: netalertx
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: /home/justin/docker/netalertx/
|
||||
pull: always
|
||||
recreate: auto
|
||||
|
||||
- name: Pause
|
||||
ansible.builtin.pause:
|
||||
seconds: 1
|
||||
|
||||
- name: Wavelog
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: /home/justin/docker/wavelog/
|
||||
pull: always
|
||||
recreate: auto
|
||||
|
||||
- name: Pause
|
||||
ansible.builtin.pause:
|
||||
seconds: 1
|
||||
|
||||
- name: Kometa
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: /home/justin/docker/kometa/
|
||||
pull: always
|
||||
recreate: auto
|
||||
|
||||
- name: Pause
|
||||
ansible.builtin.pause:
|
||||
seconds: 1
|
||||
|
||||
- name: Tautulli
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: /home/justin/docker/tautulli/
|
||||
pull: always
|
||||
recreate: auto
|
||||
|
||||
- name: Prune non-dangling images
|
||||
community.docker.docker_prune:
|
||||
containers: false
|
||||
images: true
|
||||
images_filters:
|
||||
dangling: false
|
||||
networks: false
|
||||
volumes: false
|
||||
builder_cache: false
|
||||
|
||||
- name: Deploy Docker Compose stack with pull and restart
|
||||
hosts: docker.ki5bhv.com
|
||||
become: true
|
||||
tasks:
|
||||
|
||||
- name: code
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: /home/justin/Docker/code-server
|
||||
pull: always
|
||||
recreate: auto
|
||||
|
||||
- name: Prune non-dangling images
|
||||
community.docker.docker_prune:
|
||||
containers: false
|
||||
images: true
|
||||
images_filters:
|
||||
dangling: false
|
||||
networks: false
|
||||
volumes: false
|
||||
builder_cache: false
|
||||
|
||||
- name: Deploy Docker Compose stack with pull and restart
|
||||
hosts: proxy-server.ki5bhv.com
|
||||
become: true
|
||||
tasks:
|
||||
- name: nginx proxy
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: /home/justin/docker/nginx-proxy
|
||||
pull: always
|
||||
recreate: auto
|
||||
|
||||
- name: Prune non-dangling images
|
||||
community.docker.docker_prune:
|
||||
containers: false
|
||||
images: true
|
||||
images_filters:
|
||||
dangling: false
|
||||
networks: false
|
||||
volumes: false
|
||||
builder_cache: false
|
||||
+5
-4
@@ -1,11 +1,12 @@
|
||||
---
|
||||
- name: Git update
|
||||
hosts: localhost
|
||||
|
||||
- name: Git update k5bss
|
||||
hosts: webhost
|
||||
|
||||
tasks:
|
||||
- name: Git Pull
|
||||
ansible.builtin.git:
|
||||
repo: https://git.ki5bhv.com/justin/Ansible.git
|
||||
dest: /home/justin/ansible
|
||||
repo: https://git.ki5bhv.com/justin/k5bss.com.git
|
||||
dest: /var/www/k5bss.com
|
||||
single_branch: yes
|
||||
version: main
|
||||
@@ -0,0 +1,9 @@
|
||||
---
|
||||
|
||||
- hosts: all
|
||||
gather_facts: false
|
||||
tasks:
|
||||
- name: Ping
|
||||
ansible.builtin.ping:
|
||||
data: pong
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
---
|
||||
- name: Setting time zone
|
||||
hosts: all
|
||||
hosts: linux
|
||||
become: yes
|
||||
|
||||
tasks:
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
- name: Ubuntu Server Cleanup
|
||||
hosts: linux
|
||||
become: true
|
||||
serial: 1
|
||||
|
||||
tasks:
|
||||
- name: Remove unused packages and dependencies
|
||||
ansible.builtin.apt:
|
||||
autoremove: yes
|
||||
|
||||
- name: Clean APT cache
|
||||
ansible.builtin.apt:
|
||||
clean: yes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
- name: Add ssh key
|
||||
hosts: all
|
||||
hosts: all
|
||||
become: true
|
||||
|
||||
tasks:
|
||||
@@ -12,7 +12,7 @@
|
||||
ansible.posix.authorized_key:
|
||||
user: "{{ lookup('env', 'USER') }}"
|
||||
state: present
|
||||
key: "{{ lookup('file', '~/.ssh/id_ed25519.pub') }}"
|
||||
key: "{{ lookup('file', '~/.ssh/id_rsa.pub') }}"
|
||||
|
||||
- name: Change sudoers file
|
||||
ansible.builtin.lineinfile:
|
||||
@@ -0,0 +1,7 @@
|
||||
- name: Flush DNS Cache on Remote Hosts
|
||||
hosts: all
|
||||
become: yes # Requires root privileges
|
||||
tasks:
|
||||
- name: Flush DNS cache using resolvectl (for systemd-resolved)
|
||||
ansible.builtin.command: resolvectl flush-caches
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
---
|
||||
# fix-ssh-host-keys.yaml
|
||||
#
|
||||
# Detects cloned VMs that share the same SSH host key and regenerates a
|
||||
# unique key set on each one, then refreshes the controller's known_hosts.
|
||||
#
|
||||
# Run with host key checking disabled for this one remediation pass,
|
||||
# since known_hosts is currently in a conflicted state:
|
||||
#
|
||||
# ANSIBLE_HOST_KEY_CHECKING=False ansible-playbook fix-ssh-host-keys.yaml
|
||||
#
|
||||
# The `duplicate_fingerprint` guard means only hosts presenting the shared
|
||||
# key get touched. Hosts with an already-unique key are left alone.
|
||||
|
||||
- name: Regenerate shared SSH host keys on cloned guests
|
||||
hosts: all
|
||||
become: true
|
||||
gather_facts: false
|
||||
vars:
|
||||
# The shared key every clone is currently presenting.
|
||||
duplicate_fingerprint: "SHA256:AZekUU+Wwn6S6sCjGD0SdkhVgj3WVqVdiVYa1AXYW8A"
|
||||
tasks:
|
||||
- name: Read current ED25519 host key fingerprint
|
||||
ansible.builtin.command:
|
||||
cmd: ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub
|
||||
register: hostkey_fp
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
|
||||
- name: Regenerate host keys if this host shares the duplicate key
|
||||
when: duplicate_fingerprint in (hostkey_fp.stdout | default(''))
|
||||
block:
|
||||
- name: Remove existing host keys
|
||||
ansible.builtin.shell:
|
||||
cmd: rm -f /etc/ssh/ssh_host_*
|
||||
# rm on a glob isn't idempotent-reportable; treat as changed.
|
||||
changed_when: true
|
||||
|
||||
- name: Generate a fresh unique set of host keys
|
||||
ansible.builtin.command:
|
||||
cmd: ssh-keygen -A
|
||||
changed_when: true
|
||||
|
||||
- name: Restart SSH so the new key is served
|
||||
ansible.builtin.service:
|
||||
name: ssh
|
||||
state: restarted
|
||||
|
||||
- name: Note that this host was remediated
|
||||
ansible.builtin.debug:
|
||||
msg: "{{ inventory_hostname }} had the shared key and was regenerated."
|
||||
|
||||
- name: Refresh known_hosts on the Ansible controller
|
||||
hosts: localhost
|
||||
gather_facts: false
|
||||
vars:
|
||||
known_hosts_path: "{{ lookup('env', 'HOME') }}/.ssh/known_hosts"
|
||||
target_hosts: "{{ groups['all'] | difference(['localhost']) }}"
|
||||
tasks:
|
||||
- name: Remove stale entries for every managed host
|
||||
ansible.builtin.command:
|
||||
cmd: "ssh-keygen -f {{ known_hosts_path }} -R {{ item }}"
|
||||
loop: "{{ target_hosts }}"
|
||||
changed_when: false
|
||||
|
||||
- name: Rescan and add current keys
|
||||
ansible.builtin.shell:
|
||||
cmd: "ssh-keyscan -t ed25519,rsa,ecdsa {{ item }} >> {{ known_hosts_path }}"
|
||||
loop: "{{ target_hosts }}"
|
||||
changed_when: true
|
||||
Whitespace-only changes.
Whitespace-only changes.
@@ -0,0 +1,19 @@
|
||||
---
|
||||
- name: Install core packages for virtual machines
|
||||
hosts: 192.168.1.15
|
||||
become: true
|
||||
|
||||
tasks:
|
||||
- name: Install packages
|
||||
ansible.builtin.apt:
|
||||
name:
|
||||
- prometheus-node-exporter
|
||||
- nfs-common
|
||||
- qemu-guest-agent
|
||||
update_cache: true
|
||||
|
||||
- name: Start guest qemu-guest-agent
|
||||
ansible.builtin.service:
|
||||
name: qemu-guest-agent
|
||||
state: started
|
||||
enabled: true
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
- name: Installing Nvim
|
||||
hosts: all
|
||||
hosts: 192.168.1.15
|
||||
|
||||
|
||||
tasks:
|
||||
- name: make sure git is installed
|
||||
@@ -26,7 +27,7 @@
|
||||
|
||||
- name: Setting the path
|
||||
ansible.builtin.lineinfile:
|
||||
line: 'export PATH="$PATH:/opt/nvim-linux64/bin"'
|
||||
line: 'export PATH="$PATH:/opt/nvim-linux-x86_64/bin"'
|
||||
path: "~/.bashrc"
|
||||
insertafter: EOF
|
||||
|
||||
@@ -42,7 +43,7 @@
|
||||
|
||||
- name: Removing backup config
|
||||
ansible.builtin.command:
|
||||
cmd: "rm -r home/justin/.config/nvim.bak"
|
||||
cmd: "rm -r /home/justin/.config/nvim.bak"
|
||||
when: nvim_backup_config.stat.exists
|
||||
|
||||
- name: Backup configs
|
||||
@@ -61,46 +62,6 @@
|
||||
- name: Cleanup
|
||||
ansible.builtin.command:
|
||||
cmd: "rm /tmp/nvim-linux-x86_64.tar.gz"
|
||||
|
||||
- name: installing unzip
|
||||
become: true
|
||||
when: ansible_pkg_mgr == "apt"
|
||||
ansible.builtin.apt:
|
||||
name: unzip
|
||||
state: latest
|
||||
|
||||
- name: Check if Font folder is there
|
||||
ansible.builtin.stat:
|
||||
path: ~/.local/share/fonts
|
||||
register: fonts_folder
|
||||
|
||||
- name: Making font folder
|
||||
ansible.builtin.command:
|
||||
cmd: "mkdir /home/justin/.local/share/fonts"
|
||||
when: fonts_folder.stat.exists != True
|
||||
|
||||
- name: Nerd font zip
|
||||
ansible.builtin.command:
|
||||
cmd: "wget https://github.com/ryanoasis/nerd-fonts/releases/download/v3.3.0/3270.zip"
|
||||
|
||||
- name: Unzipping
|
||||
ansible.builtin.command:
|
||||
cmd: "unzip 3270.zip -d /home/justin/.local/share/fonts/ "
|
||||
|
||||
- name: Font Cleanup
|
||||
ansible.builtin.command:
|
||||
cmd: "rm 3270.zip"
|
||||
|
||||
- name: installing font config
|
||||
become: true
|
||||
when: ansible_pkg_mgr == "apt"
|
||||
ansible.builtin.apt:
|
||||
name: fontconfig
|
||||
state: latest
|
||||
|
||||
- name: Set Fonts
|
||||
ansible.builtin.command:
|
||||
cmd: "fc-cache -fv"
|
||||
|
||||
- name: installing fzf for nvim
|
||||
become: true
|
||||
@@ -108,3 +69,19 @@
|
||||
ansible.builtin.apt:
|
||||
name: fzf
|
||||
state: latest
|
||||
|
||||
- name: Setting neovim as Viual default
|
||||
ansible.builtin.lineinfile:
|
||||
line: 'export VISUAL=nvim'
|
||||
path: "~/.bashrc"
|
||||
insertafter: EOF
|
||||
|
||||
- name: Setting neovim deflault editor
|
||||
ansible.builtin.lineinfile:
|
||||
line: 'export EDITOR=nvim'
|
||||
path: "~/.bashrc"
|
||||
insertafter: EOF
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
- name: Clean Old Log Files and Cache
|
||||
hosts: linux
|
||||
become: true
|
||||
serial: 1
|
||||
|
||||
vars:
|
||||
log_dirs:
|
||||
- /var/log
|
||||
log_age_days: 30
|
||||
|
||||
tasks:
|
||||
- name: Remove compressed/rotated log files older than {{ log_age_days }} days
|
||||
ansible.builtin.find:
|
||||
paths: "{{ log_dirs }}"
|
||||
patterns: "*.gz,*.1,*.2,*.3,*.4,*.5,*.old"
|
||||
age: "{{ log_age_days }}d"
|
||||
recurse: true
|
||||
register: old_logs
|
||||
|
||||
- name: Delete found old log files
|
||||
ansible.builtin.file:
|
||||
path: "{{ item.path }}"
|
||||
state: absent
|
||||
loop: "{{ old_logs.files }}"
|
||||
|
||||
- name: Truncate large active log files (> 100MB) without deleting them
|
||||
ansible.builtin.shell: |
|
||||
find /var/log -type f -name "*.log" -size +100M | while read f; do
|
||||
truncate -s 0 "$f"
|
||||
done
|
||||
changed_when: false
|
||||
|
||||
- name: Clean journal logs older than 30 days
|
||||
ansible.builtin.command: journalctl --vacuum-time=30d
|
||||
changed_when: false
|
||||
|
||||
- name: Limit journal size to 500MB
|
||||
ansible.builtin.command: journalctl --vacuum-size=500M
|
||||
changed_when: false
|
||||
|
||||
- name: Remove unused packages and dependencies
|
||||
ansible.builtin.apt:
|
||||
autoremove: yes
|
||||
|
||||
- name: Clean APT package cache
|
||||
ansible.builtin.apt:
|
||||
clean: yes
|
||||
|
||||
- name: Remove obsolete package files from APT cache
|
||||
ansible.builtin.apt:
|
||||
autoclean: yes
|
||||
|
||||
- name: Clean user thumbnail/cache directories
|
||||
ansible.builtin.shell: |
|
||||
find /home -maxdepth 3 -type d -name ".cache" | while read d; do
|
||||
find "$d" -type f -atime +{{ log_age_days }} -delete 2>/dev/null || true
|
||||
done
|
||||
changed_when: false
|
||||
|
||||
- name: Clean /tmp files older than 7 days
|
||||
ansible.builtin.find:
|
||||
paths: /tmp
|
||||
age: 7d
|
||||
recurse: true
|
||||
register: tmp_files
|
||||
|
||||
- name: Delete old /tmp files
|
||||
ansible.builtin.file:
|
||||
path: "{{ item.path }}"
|
||||
state: absent
|
||||
loop: "{{ tmp_files.files }}"
|
||||
ignore_errors: true
|
||||
File renamed without changes.
@@ -0,0 +1,30 @@
|
||||
---
|
||||
- name: Check if system reboot is required
|
||||
hosts: "proxmox"
|
||||
become: true
|
||||
serial: 1
|
||||
|
||||
tasks:
|
||||
- name: Check if system reboot is required
|
||||
become: true
|
||||
ansible.builtin.stat:
|
||||
path: /run/reboot-required
|
||||
register: reboot_required
|
||||
|
||||
- name: rebooting
|
||||
become: true
|
||||
ansible.builtin.reboot:
|
||||
reboot_timeout: 3600
|
||||
when: reboot_required.stat.exists
|
||||
|
||||
- name: wait for server to resert
|
||||
ansible.builtin.wait_for_connection:
|
||||
delay: 30
|
||||
timeout: 3600
|
||||
when: reboot_required.stat.exists
|
||||
|
||||
|
||||
- name: Report if reboot is required
|
||||
ansible.builtin.command:
|
||||
cmd: 'curl -d "Reboot was required for {{inventory_hostname}} and it was rebooted" ntfy.ki5bhv.com/server'
|
||||
when: reboot_required.stat.exists
|
||||
File renamed without changes.
@@ -0,0 +1,9 @@
|
||||
---
|
||||
- name: Reboot machine
|
||||
hosts: ["mqtt-server.ki5bhv.com", "git-server.ki5bhv.com", "webhost.ki5bhv.com", "clouflare.ki5bhv.com", "coding.ki5bhv.com",pi-hole-server.ki5bhv.com, "killer2.ki5bhv.com"]
|
||||
become: true
|
||||
|
||||
tasks:
|
||||
- name: Reboot machine
|
||||
ansible.builtin.reboot:
|
||||
reboot_timeout: 3600
|
||||
@@ -0,0 +1,38 @@
|
||||
---
|
||||
# open-all-ports.yml
|
||||
#
|
||||
# Opens all inbound ports on the target Ubuntu servers.
|
||||
#
|
||||
# Default behavior: UFW stays enabled but its default incoming
|
||||
# policy is set to allow, so every port is reachable.
|
||||
#
|
||||
# To turn the firewall OFF entirely instead, run with:
|
||||
# ansible-playbook -i inventory.ini open-all-ports.yml -e "disable_ufw=true"
|
||||
#
|
||||
# Uses the community.general.ufw module.
|
||||
#
|
||||
# Usage:
|
||||
# ansible-playbook -i inventory.ini open-all-ports.yml
|
||||
|
||||
- name: Open all inbound ports
|
||||
hosts: ubuntu_servers
|
||||
become: true
|
||||
|
||||
vars:
|
||||
disable_ufw: false
|
||||
|
||||
tasks:
|
||||
- name: Set default incoming policy to allow (opens all ports)
|
||||
community.general.ufw:
|
||||
direction: incoming
|
||||
policy: allow
|
||||
|
||||
- name: Set default outgoing policy to allow
|
||||
community.general.ufw:
|
||||
direction: outgoing
|
||||
policy: allow
|
||||
|
||||
- name: Optionally disable UFW entirely
|
||||
community.general.ufw:
|
||||
state: disabled
|
||||
when: disable_ufw | bool
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
- name: Update Plex Sever
|
||||
hosts: killer1
|
||||
hosts: mediaserver.ki5bhv.com
|
||||
become: yes
|
||||
|
||||
tasks:
|
||||
@@ -0,0 +1,17 @@
|
||||
---
|
||||
- name: Rebooting Machines Proxmox
|
||||
hosts: proxmox
|
||||
become: true
|
||||
|
||||
tasks:
|
||||
- name: Checking Reboot is needed
|
||||
become: true
|
||||
ansible.builtin.stat:
|
||||
path: /run/reboot-required
|
||||
register: reboot_required
|
||||
|
||||
- name: Reboot Machine
|
||||
become: true
|
||||
ansible.builtin.reboot:
|
||||
reboot_timeout: 3600
|
||||
when: reboot_required.stat.exists
|
||||
@@ -0,0 +1,60 @@
|
||||
---
|
||||
# restrict-ssh.yml
|
||||
#
|
||||
# Restricts SSH access on Ubuntu servers to a single IP range using UFW.
|
||||
# Uses the community.general.ufw module.
|
||||
#
|
||||
# Usage:
|
||||
# ansible-playbook -i inventory.ini restrict-ssh.yml
|
||||
#
|
||||
# Override the range or port at runtime:
|
||||
# ansible-playbook -i inventory.ini restrict-ssh.yml -e "ssh_allowed_range=10.0.0.0/24 ssh_port=2222"
|
||||
|
||||
- name: Restrict SSH access to an allowed IP range
|
||||
hosts: ubuntu_servers
|
||||
become: true
|
||||
|
||||
vars:
|
||||
ssh_allowed_range: "192.168.1.0/24"
|
||||
ssh_port: 22
|
||||
|
||||
tasks:
|
||||
- name: Ensure UFW is installed
|
||||
ansible.builtin.apt:
|
||||
name: ufw
|
||||
state: present
|
||||
update_cache: true
|
||||
|
||||
- name: Set default policy to deny incoming traffic
|
||||
community.general.ufw:
|
||||
direction: incoming
|
||||
policy: deny
|
||||
|
||||
- name: Set default policy to allow outgoing traffic
|
||||
community.general.ufw:
|
||||
direction: outgoing
|
||||
policy: allow
|
||||
|
||||
- name: Allow SSH only from the permitted range
|
||||
community.general.ufw:
|
||||
rule: allow
|
||||
from_ip: "{{ ssh_allowed_range }}"
|
||||
to_port: "{{ ssh_port }}"
|
||||
proto: tcp
|
||||
|
||||
- name: Remove any rule allowing SSH from anywhere (by port)
|
||||
community.general.ufw:
|
||||
rule: allow
|
||||
to_port: "{{ ssh_port }}"
|
||||
proto: tcp
|
||||
delete: true
|
||||
|
||||
- name: Remove any rule allowing the OpenSSH application profile from anywhere
|
||||
community.general.ufw:
|
||||
rule: allow
|
||||
name: OpenSSH
|
||||
delete: true
|
||||
|
||||
- name: Enable UFW
|
||||
community.general.ufw:
|
||||
state: enabled
|
||||
@@ -0,0 +1,47 @@
|
||||
---
|
||||
# revert-ssh.yml
|
||||
#
|
||||
# Reverts the SSH IP-range restriction applied by restrict-ssh.yml.
|
||||
# Removes the range-limited SSH rule and re-opens SSH from anywhere so
|
||||
# you don't lose access. Optionally disables UFW entirely.
|
||||
#
|
||||
# Uses the community.general.ufw module.
|
||||
#
|
||||
# Usage:
|
||||
# ansible-playbook -i inventory.ini revert-ssh.yml
|
||||
#
|
||||
# To also disable UFW completely:
|
||||
# ansible-playbook -i inventory.ini revert-ssh.yml -e "disable_ufw=true"
|
||||
#
|
||||
# Override the range or port to match what restrict-ssh.yml used:
|
||||
# ansible-playbook -i inventory.ini revert-ssh.yml -e "ssh_allowed_range=10.0.0.0/24 ssh_port=2222"
|
||||
|
||||
- name: Revert SSH IP-range restriction
|
||||
hosts: ubuntu_servers
|
||||
become: true
|
||||
|
||||
vars:
|
||||
ssh_allowed_range: "192.168.1.0/24"
|
||||
ssh_port: 22
|
||||
disable_ufw: false
|
||||
|
||||
tasks:
|
||||
- name: Remove the range-restricted SSH rule
|
||||
community.general.ufw:
|
||||
rule: allow
|
||||
from_ip: "{{ ssh_allowed_range }}"
|
||||
to_port: "{{ ssh_port }}"
|
||||
proto: tcp
|
||||
delete: true
|
||||
|
||||
- name: Re-open SSH from anywhere
|
||||
community.general.ufw:
|
||||
rule: allow
|
||||
to_port: "{{ ssh_port }}"
|
||||
proto: tcp
|
||||
when: not disable_ufw | bool
|
||||
|
||||
- name: Disable UFW entirely (optional)
|
||||
community.general.ufw:
|
||||
state: disabled
|
||||
when: disable_ufw | bool
|
||||
@@ -0,0 +1,233 @@
|
||||
---
|
||||
# ssh-hardening.yml
|
||||
# =============================================================================
|
||||
# Disable SSH password authentication and apply baseline hardening on Ubuntu.
|
||||
#
|
||||
# Usage:
|
||||
# ansible-playbook -i inventory.ini ssh-hardening.yml
|
||||
# ansible-playbook -i inventory.ini ssh-hardening.yml --limit coding
|
||||
# ansible-playbook -i inventory.ini ssh-hardening.yml --check # dry run
|
||||
#
|
||||
# Example inventory.ini:
|
||||
# [servers]
|
||||
# coding ansible_host=192.168.1.21 ansible_user=justin
|
||||
#
|
||||
# SAFETY FEATURES:
|
||||
# * Refuses to run if the login user has no authorized_keys (no lockout).
|
||||
# * Fixes the cloud-init "first value wins" precedence trap automatically.
|
||||
# * Validates config with `sshd -t` BEFORE restarting.
|
||||
# * Verifies password auth is actually off at the end via `sshd -T`.
|
||||
#
|
||||
# Optional extras (fail2ban / UFW) use the community.general collection:
|
||||
# ansible-galaxy collection install community.general
|
||||
# =============================================================================
|
||||
|
||||
- name: Harden SSH (key-only authentication + baseline)
|
||||
hosts: all
|
||||
become: true
|
||||
|
||||
vars:
|
||||
# User whose key access is verified before passwords are disabled.
|
||||
# Defaults to whoever Ansible connects as.
|
||||
ssh_login_user: "{{ ansible_user | default(lookup('env', 'USER')) }}"
|
||||
|
||||
# ---- Core SSH settings -------------------------------------------------
|
||||
ssh_permit_root_login: "prohibit-password" # "no" to block root entirely
|
||||
ssh_allow_users: [] # e.g. ["justin", "deploy"]; [] = no restriction
|
||||
ssh_port: 22 # change to move SSH off 22
|
||||
|
||||
# ---- Optional hardening toggles ---------------------------------------
|
||||
manage_firewall: false # true = install + enable UFW
|
||||
install_fail2ban: false
|
||||
install_unattended_upgrades: false
|
||||
|
||||
handlers:
|
||||
# Handlers run in the order defined here, so validation always precedes restart.
|
||||
- name: Validate sshd config
|
||||
ansible.builtin.command: sshd -t
|
||||
changed_when: false
|
||||
listen: "restart ssh stack"
|
||||
|
||||
- name: Restart ssh
|
||||
ansible.builtin.systemd:
|
||||
name: ssh
|
||||
state: restarted
|
||||
listen: "restart ssh stack"
|
||||
|
||||
- name: Restart ssh.socket
|
||||
ansible.builtin.systemd:
|
||||
name: ssh.socket
|
||||
state: restarted
|
||||
when: ssh_socket_present | default(false) | bool
|
||||
listen: "restart ssh stack"
|
||||
|
||||
tasks:
|
||||
# ---- Pre-flight: prove we won't lock ourselves out --------------------
|
||||
- name: Resolve login user's home directory
|
||||
ansible.builtin.getent:
|
||||
database: passwd
|
||||
key: "{{ ssh_login_user }}"
|
||||
|
||||
- name: Set authorized_keys path
|
||||
ansible.builtin.set_fact:
|
||||
ssh_authorized_keys_path: "{{ getent_passwd[ssh_login_user][4] }}/.ssh/authorized_keys"
|
||||
|
||||
- name: Stat the login user's authorized_keys
|
||||
ansible.builtin.stat:
|
||||
path: "{{ ssh_authorized_keys_path }}"
|
||||
register: ak
|
||||
|
||||
- name: Refuse to continue if no SSH key is present
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- ak.stat.exists
|
||||
- (ak.stat.size | default(0) | int) > 0
|
||||
fail_msg: >-
|
||||
{{ ssh_login_user }} has no authorized_keys at {{ ssh_authorized_keys_path }}.
|
||||
Aborting so you don't get locked out. Run `ssh-copy-id {{ ssh_login_user }}@<host>`
|
||||
first, verify key login works, then re-run this playbook.
|
||||
success_msg: "Key-based auth verified for {{ ssh_login_user }} - safe to proceed."
|
||||
|
||||
# ---- Detect socket activation (Ubuntu 22.10+ / 24.04 / 26.04) ---------
|
||||
- name: Check whether ssh.socket exists
|
||||
ansible.builtin.command: systemctl list-unit-files ssh.socket
|
||||
register: ssh_socket_check
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
|
||||
- name: Record socket-activation state
|
||||
ansible.builtin.set_fact:
|
||||
ssh_socket_present: "{{ 'ssh.socket' in ssh_socket_check.stdout }}"
|
||||
|
||||
# ---- Fix the cloud-init precedence trap -------------------------------
|
||||
# sshd uses the FIRST value it sees for a directive. Files load in
|
||||
# alphanumeric order, so 50-cloud-init.conf (PasswordAuthentication yes)
|
||||
# beats a later 99-hardening.conf. Neutralize it at the source.
|
||||
- name: Check for the cloud-init SSH drop-in
|
||||
ansible.builtin.stat:
|
||||
path: /etc/ssh/sshd_config.d/50-cloud-init.conf
|
||||
register: cloud_init_conf
|
||||
|
||||
- name: Force PasswordAuthentication off in the cloud-init drop-in
|
||||
ansible.builtin.lineinfile:
|
||||
path: /etc/ssh/sshd_config.d/50-cloud-init.conf
|
||||
regexp: '^\s*PasswordAuthentication\s+'
|
||||
line: "PasswordAuthentication no"
|
||||
state: present
|
||||
when: cloud_init_conf.stat.exists
|
||||
notify: "restart ssh stack"
|
||||
|
||||
# ---- Authoritative hardening drop-in ----------------------------------
|
||||
- name: Deploy SSH hardening drop-in
|
||||
ansible.builtin.copy:
|
||||
dest: /etc/ssh/sshd_config.d/99-hardening.conf
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0644"
|
||||
validate: "sshd -t -f %s"
|
||||
content: |
|
||||
# Managed by Ansible - ssh-hardening.yml. Do not edit by hand.
|
||||
PasswordAuthentication no
|
||||
PubkeyAuthentication yes
|
||||
KbdInteractiveAuthentication no
|
||||
PermitRootLogin {{ ssh_permit_root_login }}
|
||||
{% if ssh_allow_users | length > 0 %}
|
||||
AllowUsers {{ ssh_allow_users | join(' ') }}
|
||||
{% endif %}
|
||||
{% if ssh_port != 22 %}
|
||||
Port {{ ssh_port }}
|
||||
{% endif %}
|
||||
notify: "restart ssh stack"
|
||||
|
||||
# ---- Stop cloud-init from re-enabling passwords on rebuild ------------
|
||||
- name: Check for cloud-init config directory
|
||||
ansible.builtin.stat:
|
||||
path: /etc/cloud/cloud.cfg.d
|
||||
register: cloud_init_dir
|
||||
|
||||
- name: Pin ssh_pwauth off for cloud-init
|
||||
ansible.builtin.copy:
|
||||
dest: /etc/cloud/cloud.cfg.d/99-disable-password-auth.cfg
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0644"
|
||||
content: |
|
||||
# Managed by Ansible - ssh-hardening.yml
|
||||
ssh_pwauth: false
|
||||
when: cloud_init_dir.stat.exists
|
||||
|
||||
# ---- Optional: UFW firewall -------------------------------------------
|
||||
- name: Configure UFW firewall
|
||||
when: manage_firewall | bool
|
||||
block:
|
||||
- name: Install UFW
|
||||
ansible.builtin.apt:
|
||||
name: ufw
|
||||
state: present
|
||||
update_cache: true
|
||||
|
||||
- name: Allow the SSH port through UFW
|
||||
community.general.ufw:
|
||||
rule: allow
|
||||
port: "{{ ssh_port }}"
|
||||
proto: tcp
|
||||
|
||||
- name: Enable UFW with a default-deny inbound policy
|
||||
community.general.ufw:
|
||||
state: enabled
|
||||
policy: deny
|
||||
direction: incoming
|
||||
|
||||
# ---- Optional: fail2ban -----------------------------------------------
|
||||
- name: Install and enable fail2ban
|
||||
when: install_fail2ban | bool
|
||||
block:
|
||||
- name: Install fail2ban
|
||||
ansible.builtin.apt:
|
||||
name: fail2ban
|
||||
state: present
|
||||
update_cache: true
|
||||
|
||||
- name: Enable and start fail2ban
|
||||
ansible.builtin.systemd:
|
||||
name: fail2ban
|
||||
enabled: true
|
||||
state: started
|
||||
|
||||
# ---- Optional: unattended security upgrades ---------------------------
|
||||
- name: Enable unattended security upgrades
|
||||
when: install_unattended_upgrades | bool
|
||||
block:
|
||||
- name: Install unattended-upgrades
|
||||
ansible.builtin.apt:
|
||||
name: unattended-upgrades
|
||||
state: present
|
||||
update_cache: true
|
||||
|
||||
- name: Turn on periodic update + upgrade
|
||||
ansible.builtin.copy:
|
||||
dest: /etc/apt/apt.conf.d/20auto-upgrades
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0644"
|
||||
content: |
|
||||
APT::Periodic::Update-Package-Lists "1";
|
||||
APT::Periodic::Unattended-Upgrade "1";
|
||||
|
||||
# ---- Apply restarts, then verify the result ---------------------------
|
||||
- name: Apply any pending SSH restarts now
|
||||
ansible.builtin.meta: flush_handlers
|
||||
|
||||
- name: Read the effective sshd configuration
|
||||
ansible.builtin.command: sshd -T
|
||||
register: sshd_effective
|
||||
changed_when: false
|
||||
|
||||
- name: Confirm password authentication is actually disabled
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- "'passwordauthentication no' in sshd_effective.stdout"
|
||||
fail_msg: >-
|
||||
Password auth is STILL enabled in the effective config.
|
||||
Check drop-in precedence with: sudo sshd -T | grep -i passwordauth
|
||||
success_msg: "Confirmed: password authentication is disabled."
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
- name: Update cloud Flare Tunnel
|
||||
hosts: 192.168.1.119
|
||||
hosts: cloudflare.ki5bhv.com
|
||||
|
||||
tasks:
|
||||
- name: Pull the newest package
|
||||
@@ -22,7 +22,7 @@
|
||||
path: cloudflared.deb
|
||||
register: cloudflaredfile
|
||||
|
||||
- name: Cleanup
|
||||
- name: Cleanup
|
||||
when: cloudflaredfile.stat.exists
|
||||
ansible.builtin.command:
|
||||
cmd: "rm cloudflared.deb"
|
||||
@@ -1,44 +1,36 @@
|
||||
---
|
||||
- name: Send Start update
|
||||
hosts: localhost
|
||||
|
||||
tasks:
|
||||
- name: send ntfy
|
||||
ansible.builtin.command:
|
||||
cmd: 'curl -d "Starting updating with ansible" ntfy.ki5bhv.com/server'
|
||||
|
||||
- name: Proxmox Update and upgrade apt packages
|
||||
hosts: proxmox
|
||||
hosts: proxmox
|
||||
become: yes
|
||||
serial: 1
|
||||
|
||||
tasks:
|
||||
|
||||
- name: Update packages with apt
|
||||
when: ansible_pkg_mgr == 'apt'
|
||||
when: ansible_facts['pkg_mgr'] == 'apt'
|
||||
ansible.builtin.apt:
|
||||
update_cache: true
|
||||
cache_valid_time: 3600
|
||||
lock_timeout: 600
|
||||
|
||||
- name: Installing proxmox guest agent
|
||||
when: ansible_pkg_mgr == 'apt'
|
||||
when: ansible_facts['pkg_mgr'] == 'apt'
|
||||
ansible.builtin.apt:
|
||||
name: qemu-guest-agent
|
||||
state: latest
|
||||
|
||||
- name: Enable proxmox agent
|
||||
ansible.builtin.command:
|
||||
cmd: systemctl enable qemu-guest-agent
|
||||
|
||||
- name: Restart proxmox agent
|
||||
ansible.builtin.command:
|
||||
cmd: systemctl restart qemu-guest-agent
|
||||
|
||||
- name: Enable and restart proxmox agent
|
||||
ansible.builtin.service:
|
||||
name: qemu-guest-agent
|
||||
state: restarted
|
||||
|
||||
- name: Upgrade packages with apt
|
||||
when: ansible_pkg_mgr == 'apt'
|
||||
when: ansible_facts['pkg_mgr'] == 'apt'
|
||||
ansible.builtin.apt:
|
||||
upgrade: dist
|
||||
|
||||
- name: Clean up packages with apt
|
||||
when: ansible_pkg_mgr == 'apt'
|
||||
when: ansible_facts['pkg_mgr'] == 'apt'
|
||||
ansible.builtin.apt:
|
||||
autoclean: true
|
||||
autoremove: true
|
||||
@@ -48,19 +40,21 @@
|
||||
become: yes
|
||||
|
||||
tasks:
|
||||
|
||||
- name: Update packages with apt
|
||||
when: ansible_pkg_mgr == 'apt'
|
||||
when: ansible_facts['pkg_mgr'] == 'apt'
|
||||
ansible.builtin.apt:
|
||||
update_cache: true
|
||||
|
||||
cache_valid_time: 3600
|
||||
lock_timeout: 600
|
||||
|
||||
- name: Upgrade packages with apt
|
||||
when: ansible_pkg_mgr == 'apt'
|
||||
when: ansible_facts['pkg_mgr'] == 'apt'
|
||||
ansible.builtin.apt:
|
||||
upgrade: dist
|
||||
|
||||
- name: Clean up packages with apt
|
||||
when: ansible_pkg_mgr == 'apt'
|
||||
when: ansible_facts['pkg_mgr'] == 'apt'
|
||||
ansible.builtin.apt:
|
||||
autoclean: true
|
||||
autoremove: true
|
||||
@@ -68,19 +62,11 @@
|
||||
- name: installing net-tools on all
|
||||
hosts: all
|
||||
become: yes
|
||||
|
||||
tasks:
|
||||
- name: running apt
|
||||
when: ansible_pkg_mgr == 'apt'
|
||||
when: ansible_facts['pkg_mgr'] == 'apt'
|
||||
ansible.builtin.apt:
|
||||
name: net-tools
|
||||
name: net-tools
|
||||
state: latest
|
||||
|
||||
|
||||
|
||||
- name: Send completed update
|
||||
hosts: localhost
|
||||
|
||||
tasks:
|
||||
- name: send ntfy
|
||||
ansible.builtin.command:
|
||||
cmd: 'curl -d "Updated with ansible" ntfy.ki5bhv.com/server'
|
||||
@@ -0,0 +1,9 @@
|
||||
---
|
||||
# This playbook uses the win_ping module to test connectivity to Windows hosts
|
||||
- name: Ping
|
||||
hosts: all
|
||||
|
||||
tasks:
|
||||
- name: ping
|
||||
win_ping:
|
||||
|
||||
Reference in new issue
Block a user