From b3b280fbe4aaa4b000cb39b1862bae66a797afb4 Mon Sep 17 00:00:00 2001 From: Marty Oehme <contact@martyoeh.me> Date: Fri, 28 Feb 2025 20:57:34 +0100 Subject: [PATCH] ref(playbook): Change to role-based structure --- books/void_base.yaml | 257 ------------------ books/void_network.yaml | 23 -- books/void_packages.yaml | 90 ------ books/void_user.yaml | 28 -- books/void_wayland.yaml | 174 ------------ play.yaml | 49 +++- .../backup}/files/snapper-snap-script | 0 roles/backup/tasks/main.yaml | 5 + roles/backup/tasks/snapper.yaml | 67 +++++ .../templates/snapper-configurations/home.j2 | 0 .../templates/snapper-configurations/root.j2 | 0 roles/backup/vars/main.yaml | 0 roles/base/handlers/main.yaml | 31 +++ roles/base/tasks/main.yaml | 122 +++++++++ {books => roles/base}/templates/hostname.j2 | 0 roles/base/vars/main.yaml | 6 + roles/bluetooth/tasks/main.yaml | 16 ++ roles/display_manager/tasks/main.yaml | 29 ++ .../templates/greetd-config.toml.j2 | 0 roles/display_manager/vars/main.yaml | 2 + roles/fonts/handlers/main.yaml | 9 + roles/fonts/tasks/main.yaml | 8 + roles/gnupg/tasks/main.yaml | 18 ++ roles/host/defaults/main.yml | 3 + books/host.yaml => roles/host/tasks/main.yaml | 23 +- roles/keyd/files/default.conf | 41 +++ roles/keyd/tasks/main.yaml | 22 ++ roles/network/tasks/main.yaml | 21 ++ roles/network/tasks/wireless.yaml | 13 + roles/network/vars/main.yaml | 3 + roles/packages/tasks/main.yaml | 4 + roles/pipewire/tasks/main.yaml | 49 ++++ roles/pipewire/vars/main.yaml | 4 + roles/power/tasks/main.yaml | 20 ++ roles/power/vars/main.yaml | 0 roles/user/tasks/main.yaml | 27 ++ roles/user/vars/main.yaml | 18 ++ {books => roles/wayland}/files/runit.conf | 0 roles/wayland/tasks/main.yaml | 54 ++++ 39 files changed, 635 insertions(+), 601 deletions(-) delete mode 100644 books/void_base.yaml delete mode 100644 books/void_network.yaml delete mode 100644 books/void_packages.yaml delete mode 100644 books/void_user.yaml delete mode 100644 books/void_wayland.yaml rename {books => roles/backup}/files/snapper-snap-script (100%) create mode 100644 roles/backup/tasks/main.yaml create mode 100644 roles/backup/tasks/snapper.yaml rename {books => roles/backup}/templates/snapper-configurations/home.j2 (100%) rename {books => roles/backup}/templates/snapper-configurations/root.j2 (100%) create mode 100644 roles/backup/vars/main.yaml create mode 100644 roles/base/handlers/main.yaml create mode 100644 roles/base/tasks/main.yaml rename {books => roles/base}/templates/hostname.j2 (100%) create mode 100644 roles/base/vars/main.yaml create mode 100644 roles/bluetooth/tasks/main.yaml create mode 100644 roles/display_manager/tasks/main.yaml rename {books => roles/display_manager}/templates/greetd-config.toml.j2 (100%) create mode 100644 roles/display_manager/vars/main.yaml create mode 100644 roles/fonts/handlers/main.yaml create mode 100644 roles/fonts/tasks/main.yaml create mode 100644 roles/gnupg/tasks/main.yaml create mode 100644 roles/host/defaults/main.yml rename books/host.yaml => roles/host/tasks/main.yaml (67%) create mode 100644 roles/keyd/files/default.conf create mode 100644 roles/keyd/tasks/main.yaml create mode 100644 roles/network/tasks/main.yaml create mode 100644 roles/network/tasks/wireless.yaml create mode 100644 roles/network/vars/main.yaml create mode 100644 roles/packages/tasks/main.yaml create mode 100644 roles/pipewire/tasks/main.yaml create mode 100644 roles/pipewire/vars/main.yaml create mode 100644 roles/power/tasks/main.yaml create mode 100644 roles/power/vars/main.yaml create mode 100644 roles/user/tasks/main.yaml create mode 100644 roles/user/vars/main.yaml rename {books => roles/wayland}/files/runit.conf (100%) create mode 100644 roles/wayland/tasks/main.yaml diff --git a/books/void_base.yaml b/books/void_base.yaml deleted file mode 100644 index 88efe1b..0000000 --- a/books/void_base.yaml +++ /dev/null @@ -1,257 +0,0 @@ -- name: Install void base system - hosts: target_system - become: true - tasks: - # Prefer booster to dracut so make sure to never install it - - name: Ignore dracut - ansible.builtin.lineinfile: - path: /etc/xbps.d/ignore-dracut.conf - line: ignorepkg=dracut - state: present - create: true # create file if absent - - - name: Update xbps and system - community.general.xbps: - name: - - xbps - state: latest - update_cache: true - upgrade: true - - - name: Install Base system - community.general.xbps: - name: - - base-system - state: present - - - name: Get rid of temporary container metapackage - community.general.xbps: - name: - - base-container-full - state: absent - - - name: Install booster - community.general.xbps: - name: booster - state: present - notify: installed-booster - - handlers: - - name: List kernel module dirs - ansible.builtin.find: - paths: "/usr/lib/modules" - file_type: directory - register: found_kernels - listen: installed-booster - - - name: Find kernels - ansible.builtin.set_fact: - kernel_list: "{{ found_kernels['files'] | map(attribute='path') | map('regex_replace', '^.*/(.*)$', '\\1') | list }}" - listen: installed-booster - - - name: Create booster initramfs - vars: - fname: /boot/booster-void - ansible.builtin.command: - argv: - - booster - - --verbose - - build - - --kernel-version={{ item }} - - "{{ fname }}-{{ item }}.img" - creates: "{{ fname }}-{{ item }}.img" - loop: "{{ kernel_list }}" - listen: installed-booster - -- name: Configure void base system - hosts: target_system - become: true - vars: - host_name: voider - timezone: Europe/Berlin - locales_enabled: - - en_US.UTF-8 UTF-8 - - tasks: - - name: Set hostname - ansible.builtin.template: - src: hostname.j2 - dest: /etc/hostname - - - name: Set timezone - ansible.builtin.file: - path: /etc/localtime - src: /usr/share/zoneinfo/{{ timezone }} - state: link - - - name: Check if glibc locales exist - ansible.builtin.stat: - path: /etc/default/libc-locales - register: libc_locales_file - - - name: Set correct glibc locales - ansible.builtin.lineinfile: - path: /etc/default/libc-locales - regexp: "^{{ item }}" - line: "{{ item }}" - state: present - create: true - loop: "{{ locales_enabled }}" - when: libc_locales_file.stat.exists - notify: glibc-locales-changed - - - name: Set up chrony for NTP management - community.general.xbps: - name: - - chrony - state: present - notify: installed-chrony - - - name: Activate acpid service - ansible.builtin.file: - force: "yes" - src: "/etc/sv/acpid" - dest: "/etc/runit/runsvdir/default/acpid" - state: link - - handlers: - - name: Regenerate locales - ansible.builtin.command: - argv: - - xbps-reconfigure - - --force - - libc-locales - listen: glibc-locales-changed - - - name: Activate chronyd service - ansible.builtin.file: - force: "yes" - src: "/etc/sv/{{ item }}" - dest: "/etc/runit/runsvdir/default/{{ item }}" - state: link - with_items: [chronyd] - listen: installed-chrony - -- name: Set up wireless networking - hosts: target_system - become: true - tags: - - wireless - - iwd - tasks: - - name: Install iwd - community.general.xbps: - name: - - iwd - state: present - - - name: Activate wireless networking service - ansible.builtin.file: - src: "/etc/sv/iwd" - dest: "/etc/runit/runsvdir/default/iwd" - state: link - -- name: Set up snapper backups - hosts: target_system - become: true - tags: - - btrfs - - snapshots - tasks: - - name: Install snapper - community.general.xbps: - name: - - snapper - state: present - notify: installed-snapper - - # https://wiki.archlinux.org/title/Snapper#updatedb - - name: Disable updatedb indexing for snapshot directories - ansible.builtin.copy: - content: 'PRUNENAMES = ".snapshots"' - dest: "/etc/updatedb.conf" - owner: root - group: root - mode: 0644 - force: true - - - name: Ensure snapper configs directory exists - ansible.builtin.file: - dest: "/etc/snapper/configs" - state: directory - recurse: true - - - name: Ensure root /.snapshots directory exists - ansible.builtin.file: - dest: "/.snapshots" - state: directory - mode: 0755 - - - name: Create root backup configuration - ansible.builtin.template: - src: snapper-configurations/root.j2 - dest: "/etc/snapper/configs/root" - mode: 0640 - force: true # ensure contents are always exact - - - name: Ensure home /.snapshots directory exists - ansible.builtin.file: - dest: "/home/.snapshots" - state: directory - mode: 0755 - - - name: Create homedir backup configuration - ansible.builtin.template: - src: snapper-configurations/home.j2 - dest: "/etc/snapper/configs/home" - mode: 0640 - force: true - - - name: Add snap manual safety command - ansible.builtin.copy: - src: snapper-snap-script - dest: "/usr/bin/snap" - owner: root - group: root - mode: 0755 - - handlers: - # # Do NOT activate the snapperd service - - # # on systems without elogind I guess? Unsure - # - name: Activate snapper service - # ansible.builtin.file: - # force: "yes" - # src: "/etc/sv/snapperd" - # dest: "/etc/runit/runsvdir/default/snapperd" - # state: link - # listen: installed-snapper - - name: Snapper handler stub - ansible.builtin.debug: - msg: "" - listen: installed-snapper - -- name: Set up snooze as cron daemon - hosts: target_system - become: true - tags: - - cron - - snooze - tasks: - - name: Install snooze - community.general.xbps: - name: - - snooze - state: present - - - name: Activate snooze cron services - ansible.builtin.file: - force: "yes" - src: "/etc/sv/{{ item }}" - dest: "/etc/runit/runsvdir/default/{{ item }}" - state: link - loop: - - snooze-hourly - - snooze-daily - - snooze-weekly - - snooze-monthly - diff --git a/books/void_network.yaml b/books/void_network.yaml deleted file mode 100644 index a99e5ed..0000000 --- a/books/void_network.yaml +++ /dev/null @@ -1,23 +0,0 @@ -- name: Set up voidlinux networking - hosts: target_system - become: true - vars: - nameserver1: 9.9.9.9 - nameserver2: 9.9.9.10 - tasks: - - name: Configure resolv DNS - ansible.builtin.copy: - mode: 0644 - dest: "/etc/resolv.conf" - content: | - nameserver {{ nameserver1 }} - nameserver {{ nameserver2 }} - failed_when: false # can't ever fail - - - name: Activate dhcp service - ansible.builtin.file: - force: 'yes' - src: "/etc/sv/{{ item }}" - dest: "/etc/runit/runsvdir/default/{{ item }}" - state: link - with_items: [ dhcpcd ] diff --git a/books/void_packages.yaml b/books/void_packages.yaml deleted file mode 100644 index c826dac..0000000 --- a/books/void_packages.yaml +++ /dev/null @@ -1,90 +0,0 @@ -- name: Install basic custom void packages - hosts: interface - become: true - tags: - - interface - - packages - tasks: - - name: Set up keyd for custom key events - community.general.xbps: - name: - - keyd - state: "{{ desired_package_state }}" - notify: installed-keyd - - - name: Install many fonts - community.general.xbps: - name: "{{ fonts }}" - state: "{{ desired_package_state }}" - notify: installed-fonts - when: fonts - - handlers: - - name: Activate keyd service - ansible.builtin.file: - force: "yes" - src: "/etc/sv/{{ item }}" - dest: "/etc/runit/runsvdir/default/{{ item }}" - state: link - with_items: [keyd] - listen: installed-keyd - - - name: Regenerate fontconfig - ansible.builtin.command: - argv: - - xbps-reconfigure - - --force - - fontconfig - listen: installed-fonts - -- name: Install bluetooth - hosts: target_system - become: true - tags: - - bluetooth - tasks: - - name: Install bluetooth packages - community.general.xbps: - name: - - bluez - state: "{{ desired_package_state }}" - notify: installed-bluetooth - - handlers: - - name: Activate bluetooth service - ansible.builtin.file: - force: "yes" - src: "/etc/sv/{{ item }}" - dest: "/etc/runit/runsvdir/default/{{ item }}" - state: link - with_items: [bluetoothd, dbus] - listen: installed-bluetooth - -- name: Install gnupg - hosts: target_system - become: true - tags: - - packages - - gpg - tasks: - - name: Install a bunch of base custom stuff - community.general.xbps: - name: [gnupg, gnupg2-scdaemon] - state: "{{ desired_package_state }}" - handlers: - - name: Put user in plugdev group - ansible.builtin.user: - name: "{{ user_name }}" - groups: [plugdev] - append: true - -- name: Install basic custom void packages - hosts: target_system - become: true - tags: - - packages - tasks: - - name: Install a bunch of base custom stuff - community.general.xbps: - name: "{{ lookup('community.general.merge_variables', '^packages_.*') }}" - state: "{{ desired_package_state }}" diff --git a/books/void_user.yaml b/books/void_user.yaml deleted file mode 100644 index 64474bf..0000000 --- a/books/void_user.yaml +++ /dev/null @@ -1,28 +0,0 @@ -- name: Set up primary user - hosts: target_system - become: true - tasks: - - name: Ensure user groups all exist - ansible.builtin.group: - name: "{{ item }}" - state: present - loop: "{{ user_groups }}" - - - name: Enable sudo for "wheel" group - ansible.builtin.copy: - content: "%wheel ALL=(ALL) ALL" - dest: "/etc/sudoers.d/10-wheel" - owner: root - group: root - mode: 0644 - force: true - - - name: Add user - ansible.builtin.user: - name: "{{ user_name }}" - password: "{{ user_pass | password_hash('sha512', 'supersecretsalt') }}" - create_home: true - shell: "/bin/{{ user_shell }}" - group: "{{ user_name }}" - groups: "{{ user_groups }}" - generate_ssh_key: true diff --git a/books/void_wayland.yaml b/books/void_wayland.yaml deleted file mode 100644 index 9e6cfcf..0000000 --- a/books/void_wayland.yaml +++ /dev/null @@ -1,174 +0,0 @@ -- name: Install void wayland environment - hosts: target_system - become: true - tags: wayland - tasks: - - name: Install intel wayland drivers - community.general.xbps: - name: - - mesa-dri - state: present - - - name: Install wayland packages - community.general.xbps: - name: - - dbus - - seatd - - turnstile - state: present - # notify: installed-wayland -> TODO: Use handler? Currently using task below - - - name: Activate wayland services - ansible.builtin.file: - force: "yes" - src: "/etc/sv/{{ item }}" - dest: "/etc/runit/runsvdir/default/{{ item }}" - state: link - with_items: [dbus, turnstiled, seatd] - - - name: Set user service directory to $HOME/.local/state/service - ansible.builtin.copy: - src: runit.conf - dest: /etc/turnstile/backend/runit.conf - mode: 0644 - - - name: Install wlr desktop portals - community.general.xbps: - name: - - xdg-desktop-portal - - xdg-desktop-portal-wlr - state: present - tags: desktop-portal - - - name: Install qt5 and qt6 wayland libraries - community.general.xbps: - name: - - qt5-wayland - - qt6-wayland - state: present - tags: qt-wayland - -- name: Set up display manager - hosts: target_system - become: true - vars: - greeter_user: _greeter - tags: - - wayland - - greetd - - tuigreet - tasks: - - name: Ensure user group for greeter exists - ansible.builtin.group: - name: "{{ greeter_user }}" - state: present - - - name: Install greetd and tuigreet - community.general.xbps: - name: - - greetd - - tuigreet - state: present - - - name: Set up tuigreet config for greetd - ansible.builtin.template: - src: greetd-config.toml.j2 - dest: "/etc/greetd/config.toml" - owner: root - group: root - mode: 0644 - force: true - - - name: Activate greetd service - ansible.builtin.file: - src: "/etc/sv/greetd" - dest: "/etc/runit/runsvdir/default/greetd" - state: link - -- name: Install audio and video for wayland - hosts: target_system - become: true - tags: audio - vars: - audio_groups: [audio, video] - tasks: - - name: Ensure user group for audio/video exists - ansible.builtin.group: - name: "{{ item }}" - state: present - loop: "{{ audio_groups }}" - - - name: Put user in audio group - ansible.builtin.user: - name: "{{ user_name }}" - groups: "{{ audio_groups }}" - append: true - - - name: Install pipewire - community.general.xbps: - name: - - pipewire - state: present - notify: installed-pipewire - - - name: Install pipewire bluetooth - community.general.xbps: - name: - - libspa-bluetooth - state: present - tags: bluetooth - - handlers: - - name: Set up wireplumber to auto start - ansible.builtin.file: - dest: "/etc/pipewire/pipewire.conf.d" - state: directory - listen: installed-pipewire - - # FIXME: Does not work automatically for some reason? - - name: Set up wireplumber to auto start - ansible.builtin.file: - force: "yes" - src: "/usr/share/examples/wireplumber/10-wireplumber.conf" - dest: "/etc/pipewire/pipewire.conf.d/10-wireplumber.conf" - state: link - listen: installed-pipewire - - - name: Enable pipewire-pulse interface - ansible.builtin.file: - force: "yes" - src: "/usr/share/examples/pipewire/20-pipewire-pulse.conf" - dest: "/etc/pipewire/pipewire.conf.d/20-pipewire-pulse.conf" - state: link - listen: installed-pipewire - - ## TODO: Enable its start in river init script - # - # TODO: Find way to install and enable pipewire-roc-sink module (and enable ~/.config/pipewire/pipewire.conf.d/roc-sink.conf) - - -- name: Allow user to manage system power - hosts: target_system - become: true - tags: - - power - tasks: - - name: Ensure user group "power" exists - ansible.builtin.group: - name: power - state: present - - - name: Put user in power group - ansible.builtin.user: - name: "{{ user_name }}" - groups: [power] - append: true - - - name: Enable power management for power group - ansible.builtin.copy: - content: "%power ALL=(ALL) NOPASSWD: /usr/bin/halt, /usr/bin/poweroff, /usr/bin/reboot, /usr/bin/shutdown, /usr/bin/zzz, /usr/bin/ZZZ" - dest: "/etc/sudoers.d/20-power" - owner: root - group: root - mode: 0644 - force: true diff --git a/play.yaml b/play.yaml index f4ae7cd..c2dcdba 100644 --- a/play.yaml +++ b/play.yaml @@ -1,6 +1,9 @@ --- -- name: Import host tasks - ansible.builtin.import_playbook: books/host.yaml +- name: Prepare host system + hosts: hostsystem + become: true + roles: + - host # Get python onto void - otherwise we can not interact through ansible - name: Bootstrap void python @@ -12,17 +15,35 @@ register: python_install changed_when: "'installed successfully' in python_install.stdout" -- name: Import chroot void base tasks - ansible.builtin.import_playbook: books/void_base.yaml +- name: Set up target system + hosts: target_system + become: true + roles: + - role: base + tags: base + - role: user + tags: user + - role: network + tags: network + - role: backup + tags: backup + - role: keyd + tags: keyd -- name: Import chroot void network tasks - ansible.builtin.import_playbook: books/void_network.yaml + - role: wayland + tags: wayland + - role: display_manager + tags: display_manager + - role: pipewire + tags: pipewire + - role: bluetooth + tags: bluetooth + - role: power + tags: power + - role: gnupg + tags: gnupg -- name: Import chroot void wayland tasks - ansible.builtin.import_playbook: books/void_wayland.yaml - -- name: Import chroot user management tasks - ansible.builtin.import_playbook: books/void_user.yaml - -- name: Import chroot void customizations - ansible.builtin.import_playbook: books/void_packages.yaml + - role: fonts + tags: fonts + - role: packages + tags: packages diff --git a/books/files/snapper-snap-script b/roles/backup/files/snapper-snap-script similarity index 100% rename from books/files/snapper-snap-script rename to roles/backup/files/snapper-snap-script diff --git a/roles/backup/tasks/main.yaml b/roles/backup/tasks/main.yaml new file mode 100644 index 0000000..a7039cf --- /dev/null +++ b/roles/backup/tasks/main.yaml @@ -0,0 +1,5 @@ +- name: Set up snapper snapshots + import_tasks: snapper.yaml + tags: + - btrfs + - snapshots diff --git a/roles/backup/tasks/snapper.yaml b/roles/backup/tasks/snapper.yaml new file mode 100644 index 0000000..d551e3f --- /dev/null +++ b/roles/backup/tasks/snapper.yaml @@ -0,0 +1,67 @@ +- name: Install snapper + community.general.xbps: + name: + - snapper + state: present + +# https://wiki.archlinux.org/title/Snapper#updatedb +- name: Disable updatedb indexing for snapshot directories + ansible.builtin.copy: + content: 'PRUNENAMES = ".snapshots"' + dest: "/etc/updatedb.conf" + owner: root + group: root + mode: 0644 + force: true + +- name: Ensure snapper configs directory exists + ansible.builtin.file: + dest: "/etc/snapper/configs" + state: directory + recurse: true + +- name: Ensure root /.snapshots directory exists + ansible.builtin.file: + dest: "/.snapshots" + state: directory + mode: 0755 + +- name: Create root backup configuration + ansible.builtin.template: + src: snapper-configurations/root.j2 + dest: "/etc/snapper/configs/root" + mode: 0640 + force: true # ensure contents are always exact + +- name: Ensure home /.snapshots directory exists + ansible.builtin.file: + dest: "/home/.snapshots" + state: directory + mode: 0755 + +- name: Create homedir backup configuration + ansible.builtin.template: + src: snapper-configurations/home.j2 + dest: "/etc/snapper/configs/home" + mode: 0640 + force: true + +- name: Add snap manual safety command + ansible.builtin.copy: + src: snapper-snap-script + dest: "/usr/bin/snap" + owner: root + group: root + mode: 0755 + +# For now we never activate the snapper daemon +# Does not work without elogind? +# Using snooze (i.e. cron) enabled recurring +# backup tasks instead. +# - name: Activate snapper service +# ansible.builtin.file: +# force: "yes" +# src: "/etc/sv/snapperd" +# dest: "/etc/runit/runsvdir/default/snapperd" +# state: link +# tags: never diff --git a/books/templates/snapper-configurations/home.j2 b/roles/backup/templates/snapper-configurations/home.j2 similarity index 100% rename from books/templates/snapper-configurations/home.j2 rename to roles/backup/templates/snapper-configurations/home.j2 diff --git a/books/templates/snapper-configurations/root.j2 b/roles/backup/templates/snapper-configurations/root.j2 similarity index 100% rename from books/templates/snapper-configurations/root.j2 rename to roles/backup/templates/snapper-configurations/root.j2 diff --git a/roles/backup/vars/main.yaml b/roles/backup/vars/main.yaml new file mode 100644 index 0000000..e69de29 diff --git a/roles/base/handlers/main.yaml b/roles/base/handlers/main.yaml new file mode 100644 index 0000000..514fd62 --- /dev/null +++ b/roles/base/handlers/main.yaml @@ -0,0 +1,31 @@ +- name: List kernel module dirs + ansible.builtin.find: + paths: "/usr/lib/modules" + file_type: directory + register: found_kernels + listen: installed-booster + +- name: Find kernels + ansible.builtin.set_fact: + kernel_list: "{{ found_kernels['files'] | map(attribute='path') | map('regex_replace', '^.*/(.*)$', '\\1') | list }}" + listen: installed-booster + +- name: Create booster initramfs + ansible.builtin.command: + argv: + - booster + - --verbose + - build + - --kernel-version={{ item }} + - "{{ fname }}-{{ item }}.img" + creates: "{{ fname }}-{{ item }}.img" + loop: "{{ kernel_list }}" + listen: installed-booster + +- name: Regenerate locales + ansible.builtin.command: + argv: + - xbps-reconfigure + - --force + - libc-locales + listen: glibc-locales-changed diff --git a/roles/base/tasks/main.yaml b/roles/base/tasks/main.yaml new file mode 100644 index 0000000..b175181 --- /dev/null +++ b/roles/base/tasks/main.yaml @@ -0,0 +1,122 @@ +# Prefer booster to dracut so make sure to never install it +- name: Ignore dracut + ansible.builtin.lineinfile: + path: /etc/xbps.d/ignore-dracut.conf + line: ignorepkg=dracut + state: present + create: true # create file if absent + tags: + - packages + - dracut + +- name: Update xbps and system + community.general.xbps: + name: + - xbps + state: latest + update_cache: true + upgrade: true + tags: + - packages + - update + +- name: Install Base system + community.general.xbps: + name: + - base-system + state: present + tags: + - packages + +- name: Get rid of temporary container metapackage + community.general.xbps: + name: + - base-container-full + state: absent + tags: + - packages + +- name: Install booster + community.general.xbps: + name: booster + state: present + notify: installed-booster + tags: + - packages + - booster + +- name: Set hostname + ansible.builtin.template: + src: hostname.j2 + dest: /etc/hostname + tags: hostname + +- name: Set timezone + ansible.builtin.file: + path: /etc/localtime + src: /usr/share/zoneinfo/{{ timezone }} + state: link + tags: timezone + +- name: Install glibc + tags: glibc + block: + - name: Check if glibc locales exist + ansible.builtin.stat: + path: /etc/default/libc-locales + register: libc_locales_file + + - name: Set correct glibc locales + ansible.builtin.lineinfile: + path: /etc/default/libc-locales + regexp: "^{{ item }}" + line: "{{ item }}" + state: present + create: true + loop: "{{ locales_enabled }}" + when: libc_locales_file.stat.exists + notify: glibc-locales-changed + +- name: Set up chrony for NTP management + community.general.xbps: + name: + - chrony + state: present + tags: chrony + +- name: Activate chronyd service + ansible.builtin.file: + src: "/etc/sv/chronyd" + dest: "/etc/runit/runsvdir/default/chronyd" + state: link + tags: chrony + +- name: Activate acpid service + ansible.builtin.file: + src: "/etc/sv/acpid" + dest: "/etc/runit/runsvdir/default/acpid" + state: link + tags: acpid + +- name: Set up snooze as cron daemon + tags: + - cron + - snooze + block: + - name: Install snooze + community.general.xbps: + name: + - snooze + state: present + + - name: Activate snooze cron services + ansible.builtin.file: + force: "yes" + src: "/etc/sv/{{ item }}" + dest: "/etc/runit/runsvdir/default/{{ item }}" + state: link + loop: + - snooze-hourly + - snooze-daily + - snooze-weekly + - snooze-monthly diff --git a/books/templates/hostname.j2 b/roles/base/templates/hostname.j2 similarity index 100% rename from books/templates/hostname.j2 rename to roles/base/templates/hostname.j2 diff --git a/roles/base/vars/main.yaml b/roles/base/vars/main.yaml new file mode 100644 index 0000000..01f3915 --- /dev/null +++ b/roles/base/vars/main.yaml @@ -0,0 +1,6 @@ +--- +booster_initramfs_name: /boot/booster-void +host_name: voider +timezone: Europe/Berlin +locales_enabled: + - en_US.UTF-8 UTF-8 diff --git a/roles/bluetooth/tasks/main.yaml b/roles/bluetooth/tasks/main.yaml new file mode 100644 index 0000000..eb3e94e --- /dev/null +++ b/roles/bluetooth/tasks/main.yaml @@ -0,0 +1,16 @@ +- name: Install bluetooth packages + community.general.xbps: + name: + - bluez + state: "{{ desired_package_state }}" + tags: packages + +- name: Activate bluetooth service + ansible.builtin.file: + force: "yes" + src: "/etc/sv/{{ item }}" + dest: "/etc/runit/runsvdir/default/{{ item }}" + state: link + with_items: + - bluetoothd + - dbus diff --git a/roles/display_manager/tasks/main.yaml b/roles/display_manager/tasks/main.yaml new file mode 100644 index 0000000..5ca7090 --- /dev/null +++ b/roles/display_manager/tasks/main.yaml @@ -0,0 +1,29 @@ +--- +- name: Ensure user group for greeter exists + ansible.builtin.group: + name: "{{ greeter_user }}" + state: present + +- name: Install greetd and tuigreet + community.general.xbps: + name: + - greetd + - tuigreet + state: present + tags: + - packages + +- name: Set up tuigreet config for greetd + ansible.builtin.template: + src: greetd-config.toml.j2 + dest: "/etc/greetd/config.toml" + owner: root + group: root + mode: 0644 + force: true + +- name: Activate greetd service + ansible.builtin.file: + src: "/etc/sv/greetd" + dest: "/etc/runit/runsvdir/default/greetd" + state: link diff --git a/books/templates/greetd-config.toml.j2 b/roles/display_manager/templates/greetd-config.toml.j2 similarity index 100% rename from books/templates/greetd-config.toml.j2 rename to roles/display_manager/templates/greetd-config.toml.j2 diff --git a/roles/display_manager/vars/main.yaml b/roles/display_manager/vars/main.yaml new file mode 100644 index 0000000..90abdad --- /dev/null +++ b/roles/display_manager/vars/main.yaml @@ -0,0 +1,2 @@ +--- +greeter_user: _greeter diff --git a/roles/fonts/handlers/main.yaml b/roles/fonts/handlers/main.yaml new file mode 100644 index 0000000..93a1b49 --- /dev/null +++ b/roles/fonts/handlers/main.yaml @@ -0,0 +1,9 @@ +--- +- name: Regenerate fontconfig + ansible.builtin.command: + argv: + - xbps-reconfigure + - --force + - fontconfig + listen: installed-fonts + diff --git a/roles/fonts/tasks/main.yaml b/roles/fonts/tasks/main.yaml new file mode 100644 index 0000000..c436b5c --- /dev/null +++ b/roles/fonts/tasks/main.yaml @@ -0,0 +1,8 @@ +--- +- name: Install many fonts + community.general.xbps: + name: "{{ fonts }}" + state: "{{ desired_package_state }}" + notify: installed-fonts + when: fonts + diff --git a/roles/gnupg/tasks/main.yaml b/roles/gnupg/tasks/main.yaml new file mode 100644 index 0000000..84c172e --- /dev/null +++ b/roles/gnupg/tasks/main.yaml @@ -0,0 +1,18 @@ +- name: Install gnupg and smartcard addon + community.general.xbps: + name: + - gnupg + - gnupg2-scdaemon + state: "{{ desired_package_state }}" + tags: packages + +- name: Ensure user group plugdev exist + ansible.builtin.group: + name: plugdev + state: present + +- name: Put user in plugdev group + ansible.builtin.user: + name: "{{ user_name }}" + groups: [plugdev] + append: true diff --git a/roles/host/defaults/main.yml b/roles/host/defaults/main.yml new file mode 100644 index 0000000..272d121 --- /dev/null +++ b/roles/host/defaults/main.yml @@ -0,0 +1,3 @@ +--- +mount_dir: /mnt/void +tarball_url: "https://repo-default.voidlinux.org/live/current/void-x86_64-ROOTFS-20250202.tar.xz" diff --git a/books/host.yaml b/roles/host/tasks/main.yaml similarity index 67% rename from books/host.yaml rename to roles/host/tasks/main.yaml index 6b4b92f..ac6391c 100644 --- a/books/host.yaml +++ b/roles/host/tasks/main.yaml @@ -26,18 +26,11 @@ # - { fstype: 'ext4', src: '/dev/mapper/{{ vgname }}-root', path: '{{ mount_dir }}/' } # # TODO: should take opts from fstab. Definitely needs 'boot' type option # - { fstype: 'vfat', src: '/dev/disk/by-uuid/{{ boot_dev_uuid }}', path: '{{ mount_dir }}/boot' } - -- name: Create voidlinux guest - hosts: hostsystem - become: true - vars: - mount_dir: /mnt/void - tarball_url: "https://repo-default.voidlinux.org/live/current/void-x86_64-ROOTFS-20250202.tar.xz" - tasks: - - name: Unpack rootfs - ansible.builtin.unarchive: - remote_src: yes # we already downloaded it to the 'remote' system - src: "{{ tarball_url }}" - dest: "{{ mount_dir }}" - # ONLY run if this file does not exist (could use any rootfs file to check) - creates: "{{ mount_dir }}/etc/os-release" + +- name: Unpack rootfs + ansible.builtin.unarchive: + remote_src: yes # we already downloaded it to the 'remote' system + src: "{{ tarball_url }}" + dest: "{{ mount_dir }}" + # ONLY run if this file does not exist (could use any rootfs file to check) + creates: "{{ mount_dir }}/etc/os-release" diff --git a/roles/keyd/files/default.conf b/roles/keyd/files/default.conf new file mode 100644 index 0000000..9b88a03 --- /dev/null +++ b/roles/keyd/files/default.conf @@ -0,0 +1,41 @@ +# Makes capslock to control/escape +# insert to paste +# right alt to enable German Umlaute (äÄöÖüÜ), +# sharp s (ß), and the Euro sign (€). +# Needs compose key to be set in xkb to work correctly: +# $ setxkbmap -option "compose:menu" + +[ids] + +* + +[main] + +capslock = overload(control, esc) +insert = S-insert +rightalt = layer(dia) +shift = layer(shift) +rightshift = layer(shift) + +[shift:S] + +rightalt = layer(shiftedDia) + +[dia] + +shift = layer(shiftedDia) +rightshift = layer(shiftedDia) + +a = macro(compose a ") +o = macro(compose o ") +u = macro(compose u ") +s = macro(compose s s) +e = macro(compose = e) + +[shiftedDia] + +a = macro(compose A ") +o = macro(compose O ") +u = macro(compose U ") +s = macro(compose S S) +e = macro(compose l -) diff --git a/roles/keyd/tasks/main.yaml b/roles/keyd/tasks/main.yaml new file mode 100644 index 0000000..5d5624a --- /dev/null +++ b/roles/keyd/tasks/main.yaml @@ -0,0 +1,22 @@ +--- +- name: Install keyd + community.general.xbps: + name: + - keyd + state: "{{ desired_package_state }}" + tags: + - packages + +- name: Set up keyd umlaut configuration + ansible.builtin.copy: + src: default.conf + dest: "/etc/keyd/default.conf" + force: yes + +- name: Activate keyd service + ansible.builtin.file: + src: "/etc/sv/keyd" + dest: "/etc/runit/runsvdir/default/keyd" + state: link + force: true + diff --git a/roles/network/tasks/main.yaml b/roles/network/tasks/main.yaml new file mode 100644 index 0000000..eaa0901 --- /dev/null +++ b/roles/network/tasks/main.yaml @@ -0,0 +1,21 @@ +--- +- name: Configure resolv DNS + ansible.builtin.copy: + mode: 0644 + dest: "/etc/resolv.conf" + content: | + nameserver {{ nameserver1 }} + nameserver {{ nameserver2 }} + failed_when: false # can't ever fail + +- name: Activate dhcp service + ansible.builtin.file: + src: "/etc/sv/dhcpcd" + dest: "/etc/runit/runsvdir/default/dhcpcd" + state: link + +- name: Set up wireless networking + import_tasks: wireless.yaml + tags: + - wireless + - iwd diff --git a/roles/network/tasks/wireless.yaml b/roles/network/tasks/wireless.yaml new file mode 100644 index 0000000..f66cd64 --- /dev/null +++ b/roles/network/tasks/wireless.yaml @@ -0,0 +1,13 @@ +--- +- name: Install iwd + community.general.xbps: + name: + - iwd + state: present + +- name: Activate wireless networking service + ansible.builtin.file: + src: "/etc/sv/iwd" + dest: "/etc/runit/runsvdir/default/iwd" + state: link + diff --git a/roles/network/vars/main.yaml b/roles/network/vars/main.yaml new file mode 100644 index 0000000..299df36 --- /dev/null +++ b/roles/network/vars/main.yaml @@ -0,0 +1,3 @@ +--- +nameserver1: 9.9.9.9 +nameserver2: 9.9.9.10 diff --git a/roles/packages/tasks/main.yaml b/roles/packages/tasks/main.yaml new file mode 100644 index 0000000..a4c942b --- /dev/null +++ b/roles/packages/tasks/main.yaml @@ -0,0 +1,4 @@ +- name: Install all my used void packages + community.general.xbps: + name: "{{ lookup('community.general.merge_variables', '^packages_.*') }}" + state: "{{ desired_package_state }}" diff --git a/roles/pipewire/tasks/main.yaml b/roles/pipewire/tasks/main.yaml new file mode 100644 index 0000000..eacdf4b --- /dev/null +++ b/roles/pipewire/tasks/main.yaml @@ -0,0 +1,49 @@ +- name: Ensure user group for audio/video exists + ansible.builtin.group: + name: "{{ item }}" + state: present + loop: "{{ audio_groups }}" + +- name: Put user in audio group + ansible.builtin.user: + name: "{{ user_name }}" + groups: "{{ audio_groups }}" + append: true + +- name: Install pipewire + community.general.xbps: + name: + - pipewire + state: present + tags: packages + +- name: Install pipewire bluetooth + community.general.xbps: + name: + - libspa-bluetooth + state: present + tags: + - packages + - bluetooth + +- name: Set up wireplumber to auto start + ansible.builtin.file: + dest: "/etc/pipewire/pipewire.conf.d" + state: directory + + # FIXME: Does not work automatically for some reason? +- name: Set up wireplumber to auto start + ansible.builtin.file: + force: "yes" + src: "/usr/share/examples/wireplumber/10-wireplumber.conf" + dest: "/etc/pipewire/pipewire.conf.d/10-wireplumber.conf" + state: link + +- name: Enable pipewire-pulse interface + ansible.builtin.file: + force: "yes" + src: "/usr/share/examples/pipewire/20-pipewire-pulse.conf" + dest: "/etc/pipewire/pipewire.conf.d/20-pipewire-pulse.conf" + state: link + +# TODO: Find way to install and enable pipewire-roc-sink module (and enable ~/.config/pipewire/pipewire.conf.d/roc-sink.conf) diff --git a/roles/pipewire/vars/main.yaml b/roles/pipewire/vars/main.yaml new file mode 100644 index 0000000..99f9a86 --- /dev/null +++ b/roles/pipewire/vars/main.yaml @@ -0,0 +1,4 @@ +--- +audio_groups: + - audio + - video diff --git a/roles/power/tasks/main.yaml b/roles/power/tasks/main.yaml new file mode 100644 index 0000000..ae80b33 --- /dev/null +++ b/roles/power/tasks/main.yaml @@ -0,0 +1,20 @@ +--- +- name: Ensure user group "power" exists + ansible.builtin.group: + name: power + state: present + +- name: Put user in power group + ansible.builtin.user: + name: "{{ user_name }}" + groups: [power] + append: true + +- name: Enable power management for power group + ansible.builtin.copy: + content: "%power ALL=(ALL) NOPASSWD: /usr/bin/halt, /usr/bin/poweroff, /usr/bin/reboot, /usr/bin/shutdown, /usr/bin/zzz, /usr/bin/ZZZ" + dest: "/etc/sudoers.d/20-power" + owner: root + group: root + mode: 0644 + force: true diff --git a/roles/power/vars/main.yaml b/roles/power/vars/main.yaml new file mode 100644 index 0000000..e69de29 diff --git a/roles/user/tasks/main.yaml b/roles/user/tasks/main.yaml new file mode 100644 index 0000000..1de769a --- /dev/null +++ b/roles/user/tasks/main.yaml @@ -0,0 +1,27 @@ +- name: Enable sudo access for "wheel" group + ansible.builtin.copy: + content: "%wheel ALL=(ALL) ALL" + dest: "/etc/sudoers.d/10-wheel" + owner: root + group: root + mode: 0644 + force: true + tags: sudo + +- name: Ensure all desired user groups exist + ansible.builtin.group: + name: "{{ item }}" + state: present + loop: "{{ user_groups }}" + +- name: Add primary user + ansible.builtin.user: + name: "{{ user_name }}" + password: "{{ user_pass | password_hash('sha512', '{{ user_pass_salt}}') }}" + create_home: true + shell: "/bin/{{ user_shell }}" + group: "{{ user_name }}" + groups: "{{ user_groups }}" + generate_ssh_key: true + tags: + - passlib diff --git a/roles/user/vars/main.yaml b/roles/user/vars/main.yaml new file mode 100644 index 0000000..eb66afc --- /dev/null +++ b/roles/user/vars/main.yaml @@ -0,0 +1,18 @@ +user_pass_salt: supersecretsalt +user_name: voidboi +user_pass: voidlinux +user_shell: zsh +user_shell: zsh +user_groups: + - wheel + - _seatd # TODO: This will error if it does not exist? (seatd not installed) + - dialout + - disk + - input + - kvm + - lp + - plugdev + - scanner + - storage + - usbmon + diff --git a/books/files/runit.conf b/roles/wayland/files/runit.conf similarity index 100% rename from books/files/runit.conf rename to roles/wayland/files/runit.conf diff --git a/roles/wayland/tasks/main.yaml b/roles/wayland/tasks/main.yaml new file mode 100644 index 0000000..5de7e56 --- /dev/null +++ b/roles/wayland/tasks/main.yaml @@ -0,0 +1,54 @@ +- name: Install intel wayland drivers + community.general.xbps: + name: + - mesa-dri + state: present + tags: + - intel + - drivers + - packages + +- name: Install wayland packages + community.general.xbps: + name: + - dbus + - seatd + - turnstile + state: present + tags: + - packages + +- name: Activate wayland services + ansible.builtin.file: + force: "yes" + src: "/etc/sv/{{ item }}" + dest: "/etc/runit/runsvdir/default/{{ item }}" + state: link + with_items: [dbus, turnstiled, seatd] + +- name: Set user service directory to $HOME/.local/state/service + ansible.builtin.copy: + src: runit.conf + dest: /etc/turnstile/backend/runit.conf + mode: 0644 + +- name: Install wlr desktop portals + community.general.xbps: + name: + - xdg-desktop-portal + - xdg-desktop-portal-wlr + state: present + tags: desktop-portal + tags: + - packages + +# required e.g. for sioyek to work in wayland void +- name: Install qt5 and qt6 wayland libraries + community.general.xbps: + name: + - qt5-wayland + - qt6-wayland + state: present + tags: + - packages + - qt