From e1a9018ca64396de6206bebd281821dbc9033cde Mon Sep 17 00:00:00 2001 From: "Frank \"PHiAX\" Weggelaar" Date: Fri, 5 Dec 2025 11:02:48 +0100 Subject: [PATCH] It's a start --- .gitignore | 3 + README.md | 2 +- ansible/phiax.nl/testicle/README.rst | 1 + ansible/phiax.nl/testicle/galaxy.yml | 6 + ansible/phiax.nl/testicle/inventory/main.yaml | 5 + .../testicle/playbooks/install_octoprint.yml | 21 +++ .../testicle/playbooks/install_raspberry.yml | 29 ++++ ansible/phiax.nl/testicle/playbooks/omz.yaml | 20 +++ .../testicle/playbooks/requirements.yml | 13 ++ .../switches/mikrotik_backup_config.yml | 14 ++ .../roles/helpers/create_user/meta/main.yml | 3 + .../roles/helpers/create_user/tasks/main.yml | 26 ++++ .../create_user/templates/sudoers_dropin.j2 | 2 + .../roles/helpers/hostname/tasks/main.yml | 11 ++ .../roles/helpers/static_ip/meta/main.yml | 3 + .../roles/helpers/static_ip/tasks/main.yml | 7 + .../static_ip/templates/etc_dhcpcd.conf.j2 | 47 +++++++ .../roles/helpers/user/tasks/main.yml | 117 ++++++++++++++++ .../roles/helpers/user/vars/main/defaults.yml | 2 + .../roles/services/nginx/handlers/main.yml | 10 ++ .../roles/services/nginx/tasks/main.yml | 77 +++++++++++ .../nginx/templates/cloudflare.ini.j2 | 2 + .../templates/register_certbot_domain.sh.j2 | 9 ++ .../services/nginx/vars/main/defaults.yml | 3 + .../roles/services/octoprint/meta/main.yml | 3 + .../services/octoprint/tasks/haproxy.yml | 38 +++++ .../roles/services/octoprint/tasks/main.yml | 130 ++++++++++++++++++ .../roles/services/octoprint/tasks/webcam.yml | 1 + .../octoprint/templates/haproxy.cfg.j2 | 35 +++++ .../octoprint/templates/octoprint.service.j2 | 16 +++ .../roles/system/ohmyzsh/meta/main.yaml | 7 + .../roles/system/ohmyzsh/tasks/main.yaml | 77 +++++++++++ .../roles/system/ohmyzsh/vars/main.yaml | 13 ++ docker/calibre.yaml | 22 +++ 34 files changed, 774 insertions(+), 1 deletion(-) create mode 100644 .gitignore create mode 100644 ansible/phiax.nl/testicle/README.rst create mode 100644 ansible/phiax.nl/testicle/galaxy.yml create mode 100644 ansible/phiax.nl/testicle/inventory/main.yaml create mode 100644 ansible/phiax.nl/testicle/playbooks/install_octoprint.yml create mode 100644 ansible/phiax.nl/testicle/playbooks/install_raspberry.yml create mode 100644 ansible/phiax.nl/testicle/playbooks/omz.yaml create mode 100644 ansible/phiax.nl/testicle/playbooks/requirements.yml create mode 100644 ansible/phiax.nl/testicle/playbooks/switches/mikrotik_backup_config.yml create mode 100644 ansible/phiax.nl/testicle/roles/helpers/create_user/meta/main.yml create mode 100644 ansible/phiax.nl/testicle/roles/helpers/create_user/tasks/main.yml create mode 100644 ansible/phiax.nl/testicle/roles/helpers/create_user/templates/sudoers_dropin.j2 create mode 100644 ansible/phiax.nl/testicle/roles/helpers/hostname/tasks/main.yml create mode 100644 ansible/phiax.nl/testicle/roles/helpers/static_ip/meta/main.yml create mode 100644 ansible/phiax.nl/testicle/roles/helpers/static_ip/tasks/main.yml create mode 100644 ansible/phiax.nl/testicle/roles/helpers/static_ip/templates/etc_dhcpcd.conf.j2 create mode 100644 ansible/phiax.nl/testicle/roles/helpers/user/tasks/main.yml create mode 100644 ansible/phiax.nl/testicle/roles/helpers/user/vars/main/defaults.yml create mode 100644 ansible/phiax.nl/testicle/roles/services/nginx/handlers/main.yml create mode 100644 ansible/phiax.nl/testicle/roles/services/nginx/tasks/main.yml create mode 100644 ansible/phiax.nl/testicle/roles/services/nginx/templates/cloudflare.ini.j2 create mode 100644 ansible/phiax.nl/testicle/roles/services/nginx/templates/register_certbot_domain.sh.j2 create mode 100644 ansible/phiax.nl/testicle/roles/services/nginx/vars/main/defaults.yml create mode 100644 ansible/phiax.nl/testicle/roles/services/octoprint/meta/main.yml create mode 100644 ansible/phiax.nl/testicle/roles/services/octoprint/tasks/haproxy.yml create mode 100644 ansible/phiax.nl/testicle/roles/services/octoprint/tasks/main.yml create mode 100644 ansible/phiax.nl/testicle/roles/services/octoprint/tasks/webcam.yml create mode 100644 ansible/phiax.nl/testicle/roles/services/octoprint/templates/haproxy.cfg.j2 create mode 100644 ansible/phiax.nl/testicle/roles/services/octoprint/templates/octoprint.service.j2 create mode 100644 ansible/phiax.nl/testicle/roles/system/ohmyzsh/meta/main.yaml create mode 100644 ansible/phiax.nl/testicle/roles/system/ohmyzsh/tasks/main.yaml create mode 100644 ansible/phiax.nl/testicle/roles/system/ohmyzsh/vars/main.yaml create mode 100644 docker/calibre.yaml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..05fcacd --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +# Specify filepatterns you want git to ignore. + +.env \ No newline at end of file diff --git a/README.md b/README.md index 8bced7c..7d7542c 100644 --- a/README.md +++ b/README.md @@ -17,4 +17,4 @@ The needed parts as of right now - Ansible - To automate the software layers and container deployments - PXE - - For local cloud-init? with OpenTofu? (still researching this + - For local cloud-init? with OpenTofu? (still researching this) diff --git a/ansible/phiax.nl/testicle/README.rst b/ansible/phiax.nl/testicle/README.rst new file mode 100644 index 0000000..6425b2d --- /dev/null +++ b/ansible/phiax.nl/testicle/README.rst @@ -0,0 +1 @@ +Is this file needed? \ No newline at end of file diff --git a/ansible/phiax.nl/testicle/galaxy.yml b/ansible/phiax.nl/testicle/galaxy.yml new file mode 100644 index 0000000..d913dc4 --- /dev/null +++ b/ansible/phiax.nl/testicle/galaxy.yml @@ -0,0 +1,6 @@ +namespace: phiax.nl +name: testicle +version: 1.0.0 +author: Frank "PHiAX" Weggelaar +description: Ansible collection for doing all the things. +dependencies: [] diff --git a/ansible/phiax.nl/testicle/inventory/main.yaml b/ansible/phiax.nl/testicle/inventory/main.yaml new file mode 100644 index 0000000..6abee02 --- /dev/null +++ b/ansible/phiax.nl/testicle/inventory/main.yaml @@ -0,0 +1,5 @@ +raspberries: + hosts: + app-octoprint.phiax.nl: + sensor-adsb.phiax.nl: + \ No newline at end of file diff --git a/ansible/phiax.nl/testicle/playbooks/install_octoprint.yml b/ansible/phiax.nl/testicle/playbooks/install_octoprint.yml new file mode 100644 index 0000000..1a4c766 --- /dev/null +++ b/ansible/phiax.nl/testicle/playbooks/install_octoprint.yml @@ -0,0 +1,21 @@ +--- +- hosts: all + vars_prompt: + - name: "install_dir" + prompt: "Install directory" + private: false + default: "/opt/OctoPrint" + - name: "new_hostname" + prompt: "Hostname" + private: false + default: "octoprint.local" + - name: "appport" + prompt: "OctoPrint listening Port" + private: false + default: 5000 + - name: "webcam_port" + prompt: "Webcam listening Port" + private: false + default: 8080 + roles: + - octoprint \ No newline at end of file diff --git a/ansible/phiax.nl/testicle/playbooks/install_raspberry.yml b/ansible/phiax.nl/testicle/playbooks/install_raspberry.yml new file mode 100644 index 0000000..744ef5c --- /dev/null +++ b/ansible/phiax.nl/testicle/playbooks/install_raspberry.yml @@ -0,0 +1,29 @@ +--- +# Notice that "# noqa: package-latest" is included in this file. This disabled a specific check for the Ansible linter, +# see: https://ansible.readthedocs.io/projects/lint/usage/#muting-warnings-to-avoid-false-positives. +# For a purely reproducible build this would be a good suggestion but I'm willing to take the risk with the Pi. +- name: Install raspberry pi + hosts: all + # vars_files: + # - vault.yml + # - versions.yml + roles: + # These roles are disabled after they have being applied once for performance reasons, it should be safe to enable them again. + # Notice that this role changes some settings on reruns (on the "Change various sysctl-settings" task), doesn't seem problematic though. + - role: devsec.hardening.ssh_hardening + become: true + - role: packages + become: true + vars: + # devsec.hardening.ssh_hardening vars: + ssh_client_port: 22 # Default, but duplicated here for documentation purpose. Not changed because its only accessible via LAN. + ssh_client_password_login: false # Default, but duplicated here for documentation purpose. + ssh_allow_tcp_forwarding: true + tasks: + # This task can be handy for debugging gathered facts, uncomment it if necessary: + # - name: Store gathered facts in local file + # delegate_to: localhost + # ansible.builtin.copy: + # dest: './.ansible_facts.json' + # content: "{{ ansible_facts }}" + # mode: "0600" \ No newline at end of file diff --git a/ansible/phiax.nl/testicle/playbooks/omz.yaml b/ansible/phiax.nl/testicle/playbooks/omz.yaml new file mode 100644 index 0000000..5bea713 --- /dev/null +++ b/ansible/phiax.nl/testicle/playbooks/omz.yaml @@ -0,0 +1,20 @@ +- hosts: all + become: true + roles: + - role: system/ohmyzsh + vars: + target_user: "phiax" + ohmyzsh_theme: "agnoster" + ohmyzsh_plugins: + - git + - zsh-autosuggestions + http_fetcher: "curl" + +#### +# Notes: +# +# Role creates .oh-my-zsh by running upstream installer as the target user (RUNZSH=no, KEEP_ZSHRC=yes). +# Override variables in playbook/inventory to target different users, themes, or plugin lists. +# For systems where zsh path differs, override zsh_path. +# +#### \ No newline at end of file diff --git a/ansible/phiax.nl/testicle/playbooks/requirements.yml b/ansible/phiax.nl/testicle/playbooks/requirements.yml new file mode 100644 index 0000000..72576b3 --- /dev/null +++ b/ansible/phiax.nl/testicle/playbooks/requirements.yml @@ -0,0 +1,13 @@ +--- +collections: + # See: https://galaxy.ansible.com/ui/repo/published/devsec/hardening/ + - name: devsec.hardening + version: 10.3.0 + # See: https://galaxy.ansible.com/ui/repo/published/prometheus/prometheus/ + # Docs: https://prometheus-community.github.io/ansible/branch/main/prometheus_role.html#ansible-collections-prometheus-prometheus-prometheus-role + - name: prometheus.prometheus + version: 0.26.0 +roles: + # See: https://galaxy.ansible.com/ui/standalone/roles/geerlingguy/docker/ + - name: geerlingguy.docker + version: 7.4.7 diff --git a/ansible/phiax.nl/testicle/playbooks/switches/mikrotik_backup_config.yml b/ansible/phiax.nl/testicle/playbooks/switches/mikrotik_backup_config.yml new file mode 100644 index 0000000..96f38d0 --- /dev/null +++ b/ansible/phiax.nl/testicle/playbooks/switches/mikrotik_backup_config.yml @@ -0,0 +1,14 @@ +--- +- name Backup Mikrotik Device Configs + hosts switches + gather_facts no + tasks + - name Fetch running config + mikrotik.cli_command + commands /export compact + register output + + - name Save config to file + copy + content {{ output.stdout[0] }} + dest backups{{ inventory_hostname }}.cfg \ No newline at end of file diff --git a/ansible/phiax.nl/testicle/roles/helpers/create_user/meta/main.yml b/ansible/phiax.nl/testicle/roles/helpers/create_user/meta/main.yml new file mode 100644 index 0000000..dea3a55 --- /dev/null +++ b/ansible/phiax.nl/testicle/roles/helpers/create_user/meta/main.yml @@ -0,0 +1,3 @@ +--- +dependencies: + - global \ No newline at end of file diff --git a/ansible/phiax.nl/testicle/roles/helpers/create_user/tasks/main.yml b/ansible/phiax.nl/testicle/roles/helpers/create_user/tasks/main.yml new file mode 100644 index 0000000..c19d54b --- /dev/null +++ b/ansible/phiax.nl/testicle/roles/helpers/create_user/tasks/main.yml @@ -0,0 +1,26 @@ +--- +- name: Create new user + user: name={{ new_username }} + password={{ new_password |password_hash('sha512') }} + state=present + update_password=on_create + shell=/bin/bash + become: yes + become_method: sudo + +- name: Copy sudoer dropin file + template: src=sudoers_dropin.j2 + dest=/etc/sudoers.d/{{ new_username }} + owner=root + group=root + mode="0600" + become: yes + become_method: sudo + +- name: Add public ssh key to new users authorized key list + authorized_key: user={{ username }} + key="{{ lookup('file', ssh_pub_key) }}" + state=present + become: yes + become_user: "{{ new_username }}" + when: add_ssh_pub_key |bool \ No newline at end of file diff --git a/ansible/phiax.nl/testicle/roles/helpers/create_user/templates/sudoers_dropin.j2 b/ansible/phiax.nl/testicle/roles/helpers/create_user/templates/sudoers_dropin.j2 new file mode 100644 index 0000000..7f3d134 --- /dev/null +++ b/ansible/phiax.nl/testicle/roles/helpers/create_user/templates/sudoers_dropin.j2 @@ -0,0 +1,2 @@ +Defaults>{{ new_username }} !lecture +{{ new_username }} ALL=(ALL) NOPASSWD:ALL \ No newline at end of file diff --git a/ansible/phiax.nl/testicle/roles/helpers/hostname/tasks/main.yml b/ansible/phiax.nl/testicle/roles/helpers/hostname/tasks/main.yml new file mode 100644 index 0000000..bbf375b --- /dev/null +++ b/ansible/phiax.nl/testicle/roles/helpers/hostname/tasks/main.yml @@ -0,0 +1,11 @@ +--- +- name: Configure hostname + become: true + ansible.builtin.hostname: + name: "{{ hostname }}" +- name: Remove existing /etc/hosts entry for hostname and add FQDN name + become: true + ansible.builtin.lineinfile: + path: /etc/hosts + regexp: "^127.0.1.1.*$" + line: "127.0.0.1 {{ hostname }}.phiax.nl {{ hostname }}" diff --git a/ansible/phiax.nl/testicle/roles/helpers/static_ip/meta/main.yml b/ansible/phiax.nl/testicle/roles/helpers/static_ip/meta/main.yml new file mode 100644 index 0000000..dea3a55 --- /dev/null +++ b/ansible/phiax.nl/testicle/roles/helpers/static_ip/meta/main.yml @@ -0,0 +1,3 @@ +--- +dependencies: + - global \ No newline at end of file diff --git a/ansible/phiax.nl/testicle/roles/helpers/static_ip/tasks/main.yml b/ansible/phiax.nl/testicle/roles/helpers/static_ip/tasks/main.yml new file mode 100644 index 0000000..7d81c61 --- /dev/null +++ b/ansible/phiax.nl/testicle/roles/helpers/static_ip/tasks/main.yml @@ -0,0 +1,7 @@ +--- +- name: Set static ip address (replace /etc/dhcpcd.conf) + template: src=etc_dhcpcd.conf.j2 + dest=/etc/dhcpcd.conf + backup=yes + become: yes + become_method: sudo \ No newline at end of file diff --git a/ansible/phiax.nl/testicle/roles/helpers/static_ip/templates/etc_dhcpcd.conf.j2 b/ansible/phiax.nl/testicle/roles/helpers/static_ip/templates/etc_dhcpcd.conf.j2 new file mode 100644 index 0000000..46a3e33 --- /dev/null +++ b/ansible/phiax.nl/testicle/roles/helpers/static_ip/templates/etc_dhcpcd.conf.j2 @@ -0,0 +1,47 @@ +# A sample configuration for dhcpcd. +# See dhcpcd.conf(5) for details. + +# Allow users of this group to interact with dhcpcd via the control socket. +#controlgroup wheel + +# Inform the DHCP server of our hostname for DDNS. +hostname + +# Use the hardware address of the interface for the Client ID. +clientid +# or +# Use the same DUID + IAID as set in DHCPv6 for DHCPv4 ClientID as per RFC4361. +#duid + +# Persist interface configuration when dhcpcd exits. +persistent + +# Rapid commit support. +# Safe to enable by default because it requires the equivalent option set +# on the server to actually work. +option rapid_commit + +# A list of options to request from the DHCP server. +option domain_name_servers, domain_name, domain_search, host_name +option classless_static_routes +# Most distributions have NTP support. +option ntp_servers +# Respect the network MTU. +# Some interface drivers reset when changing the MTU so disabled by default. +#option interface_mtu + +# A ServerID is required by RFC2131. +require dhcp_server_identifier + +# Generate Stable Private IPv6 Addresses instead of hardware based ones +slaac private + +# A hook script is provided to lookup the hostname if not set by the DHCP +# server, but it should not be run by default. +nohook lookup-hostname + +interface {{iface}} +static ip_address={{new_ip_address}} +static routers={{gateway_address}} +static domain_name_servers={{dns_address}} + diff --git a/ansible/phiax.nl/testicle/roles/helpers/user/tasks/main.yml b/ansible/phiax.nl/testicle/roles/helpers/user/tasks/main.yml new file mode 100644 index 0000000..ffcbb70 --- /dev/null +++ b/ansible/phiax.nl/testicle/roles/helpers/user/tasks/main.yml @@ -0,0 +1,117 @@ +--- +# The ZSH installation instructions are sourced from this blog: +# https://harshithashok.com/tools/oh-my-zsh-with-starship/ +- name: Create the user + when: user_username is not undefined # Skip when no user is provided, we'll asume we're targetting the Ansible user. + block: + - name: Create a new user + become: true + ansible.builtin.user: + append: true + groups: + - users + name: "{{ user_username }}" + # Salt is necessary, see: https://stackoverflow.com/questions/56869949/ansible-user-module-always-shows-changed + password: "{{ user_password | password_hash('sha512', password_salt) }}" + - name: Ensure .ssh directory exists in user home + become: true + become_user: "{{ user_username }}" + ansible.builtin.file: + path: "/home/{{ user_username }}/.ssh" + state: directory + mode: "0700" + # We're assuming that the ansible user has its authorized keys setup before running the playbook and that all created users using this + # rule want the same machines to be able to access them. + - name: Copy over authorized keys from the main ansible user + become: true + ansible.builtin.copy: + remote_src: true + src: "/home/{{ ansible_facts['user_id'] }}/.ssh/authorized_keys" + dest: "/home/{{ user_username }}/.ssh/" + owner: "{{ user_username }}" + group: "{{ user_username }}" + mode: "0600" +- name: Set fact for defining the user which should run the next modules + ansible.builtin.set_fact: + target_user: "{{ ansible_facts['user_id'] if user_username is undefined else user_username }}" +# The "lingering" property seems to be important to Podman, otherwise errors are thrown as mentioned here: +# https://superuser.com/questions/1788594/podman-the-cgroupv2-manager-is-set-to-systemd-but-there-is-no-systemd-user-sess +- name: "Check if lingering is enabled (user: {{ target_user }})" + ansible.builtin.command: + cmd: "loginctl show-user {{ target_user }} --property=Linger" + register: linger_check + changed_when: false + failed_when: false +- name: "Enable systemd \"lingering\" (user: {{ target_user }})" + become: true + ansible.builtin.command: + cmd: "loginctl enable-linger {{ target_user }}" + when: linger_check.rc != 0 + changed_when: true +- name: Ensuring ZSH is installed + become: true + ansible.builtin.apt: + pkg: + - acl # Needed to prevent this error: https://stackoverflow.com/questions/46352173/ansible-failed-to-set-permissions-on-the-temporary + - zsh + state: present +- name: Install Oh My ZSH # noqa: command-instead-of-module ignore error since we're removing the script after install. + become: true + become_user: "{{ target_user }}" + ansible.builtin.shell: | + wget https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh + chmod u+x install.sh + ./install.sh --unattended + rm install.sh + args: + executable: /bin/bash + creates: ~/.oh-my-zsh +- name: Install Starship # noqa: command-instead-of-module ignore error since we're removing the script after install. + become: true + ansible.builtin.shell: | + wget https://starship.rs/install.sh + chmod u+x install.sh + ./install.sh --yes + rm install.sh + args: + executable: /bin/bash + creates: /usr/local/bin/starship +- name: Install zsh-autosuggestions # noqa: command-instead-of-module ignore error since we're removing the script after install. + become: true + become_user: "{{ target_user }}" + ansible.builtin.command: + cmd: git clone https://github.com/zsh-users/zsh-autosuggestions ~/.oh-my-zsh/custom/plugins/zsh-autosuggestions + creates: ~/.oh-my-zsh/custom/plugins/zsh-autosuggestions +- name: Clear "ZSH_THEME" in ~/.zshrc + become: true + become_user: "{{ target_user }}" + ansible.builtin.lineinfile: + path: ~/.zshrc + regexp: '^ZSH_THEME="[^"]+"$' + line: ZSH_THEME="" +- name: Add the zsh-autosuggestions plugin in ~/.zshrc + become: true + become_user: "{{ target_user }}" + ansible.builtin.lineinfile: + path: ~/.zshrc + regexp: '^plugins=\((.*)(?