- name: configure system hosts: localhost connection: local become: false tasks: - name: read machine-specific variables include_vars: file: _machines/{{ ansible_hostname }}.yml name: machine tags: - always - name: read variables include_vars: file: variables.yml tags: - always - set_fact: distro: "{{ ansible_distribution|lower }}" tags: - always - name: check for valid distro assert: that: distro in ('archlinux') - block: - name: install ansible requirements package: name: "{{ packages[distro] }}" state: present become: true vars: packages: archlinux: - python-jmespath - block: - name: enable multilib repository blockinfile: path: /etc/pacman.conf block: | [multilib] Include = /etc/pacman.d/mirrorlist marker: "# {mark} ANSIBLE MANAGED multilib" become: true - name: enable parallel download blockinfile: path: /etc/pacman.conf insertafter: '\[options\]' block: | ParallelDownloads = 5 marker: "# {mark} ANSIBLE MANAGED parallel_download" become: true - block: - name: upgrade system pacman: upgrade: true update_cache: true become: true changed_when: false tags: [system-update] - name: install pacman-contrib for paccache package: name: pacman-contrib state: present become: true - block: - name: install pacman cache clean service copy: dest: /etc/systemd/system/pacman-cache-cleanup.service owner: root group: root mode: '0644' content: | [Service] Type=oneshot ExecStart=/bin/sh -c '/usr/bin/paccache -rk1 && /usr/bin/paccache -ruk0' RemainAfterExit=true become: true - name: install pacman cache clean timer copy: dest: /etc/systemd/system/pacman-cache-cleanup.timer owner: root group: root mode: '0644' content: | [Timer] OnCalendar=daily become: true - name: enable pacman cache clean timer systemd: name: pacman-cache-cleanup.timer enabled: true state: started daemon_reload: true become: true tags: [pacman_cache_cleanup] when: distro == 'archlinux' - block: - name: create dotfiles group group: name: dotfiles state: present become: true become_user: root - name: create dotfiles user user: name: dotfiles group: dotfiles home: /var/lib/dotfiles create_home: false shell: /bin/bash system: true become: true become_user: root - name: create dotfiles directory file: state: directory path: /var/lib/dotfiles owner: dotfiles group: dotfiles mode: '0775' # group needs write access! become: true become_user: root - name: fix permissions for dotfiles directory shell: | cd /var/lib/dotfiles if [[ -e .git ]] ; then # There is no sane way to specify the global .gitconfig to use, so we # actually have to override HOME so git looks into ~/.gitconfig export HOME="$(mktemp -d)" set -o pipefail set -o errexit git config --global --add safe.directory /var/lib/dotfiles git ls-tree -z --name-only HEAD | xargs --null chown --changes --recursive dotfiles:dotfiles git ls-tree -z --name-only HEAD | xargs --null chmod --changes --recursive g+wX else chown --changes --recursive dotfiles:dotfiles . chmod --changes --recursive g+wX . fi args: executable: /bin/bash register: dotfiles_permission_change become: true become_user: root changed_when: dotfiles_permission_change.stdout_lines|length > 0 tags: [dotfiles-directory] - block: - name: create build user on arch user: name: makepkg home: /var/lib/makepkg create_home: true shell: /bin/bash system: true become: true - set_fact: aur_packages: # dependency of portfolio - name: archlinux-java-run dependencies: - 'bash' - 'java-runtime-common' version: 10-1 arch: any - name: portfolio dependencies: - 'maven' - 'java-environment=17' - 'gendesk' - 'webkit2gtk' version: 0.68.3-1 arch: x86_64 - name: spotify dependencies: - 'alsa-lib>=1.0.14' - 'gtk3' - 'libxss' - 'desktop-file-utils' - 'openssl' - 'nss' - 'at-spi2-atk' - 'libcurl-gnutls' - 'libsm' - 'libayatana-appindicator' version: 1:1.2.31.1205-2 arch: x86_64 preexec: | #!/usr/bin/env bash curl -sS https://download.spotify.com/debian/pubkey_6224F9941A8AA6D1.gpg | gpg --import - - name: install dependencies package: name: "{{ aur_packages | map(attribute='dependencies') | flatten }}" state: present become: true - name: check preexec script stat: path: /var/lib/makepkg/{{ item.name }}/preexec become_user: makepkg become: true when: item.preexec is defined loop: "{{ aur_packages }}" register: preexec_before loop_control: label: "{{ item.name }}" - name: create build root directory file: path: "/var/lib/makepkg/{{ item.name }}/" state: directory mode: '0700' owner: makepkg group: makepkg become_user: makepkg become: true loop: "{{ aur_packages }}" loop_control: label: "{{ item.name }}" - name: install preexec script copy: dest: /var/lib/makepkg/{{ item.name }}/preexec owner: makepkg group: makepkg mode: "0700" content: "{{ item.preexec }}" become_user: makepkg become: true when: item.preexec is defined loop: "{{ aur_packages }}" loop_control: label: "{{ item.name }}" - name: check preexec script stat: path: /var/lib/makepkg/{{ item.name }}/preexec become_user: makepkg become: true when: item.preexec is defined loop: "{{ aur_packages }}" register: preexec_after loop_control: label: "{{ item.name }}" - name: run preexec script command: "{{ item.1.stat.path }}" become_user: makepkg become: true when: - not item[0].stat.exists - item[0].stat.checksum|default('') != item[1].stat.checksum loop: "{{ preexec_before.results| reject('skipped')|zip(preexec_after.results| reject('skipped')) }}" loop_control: label: "{{ item.1.stat.path }}" - name: build AUR packages command: cmd: > env PKGEXT='.pkg.tar.zst' BUILDDIR=/var/lib/makepkg/{{ item.name }}/build/ SRCDEST=/var/lib/makepkg/{{ item.name }}/src/ PKGDEST=/var/lib/makepkg/{{ item.name }}/ makepkg --clean --nosign creates: /var/lib/makepkg/{{ item.name }}/{{ item.name }}-{{ item.version}}-{{ item.arch }}.pkg.tar.zst chdir: "pkgbuilds/{{ item.name }}" become_user: makepkg become: true loop: "{{ aur_packages }}" loop_control: label: "{{ item.name }}" - name: clean up build leftovers file: path: /var/lib/makepkg/{{ item[0].name }}/{{ item[1] }}/ state: absent become_user: makepkg become: true with_nested: - "{{ aur_packages }}" - - build - src loop_control: label: "{{ item[0].name }}/{{ item[1] }}" - name: install AUR packages pacman: state: installed name: /var/lib/makepkg/{{ item.name }}/{{ item.name }}-{{ item.version }}-{{ item.arch }}.pkg.tar.zst become: true loop: "{{ aur_packages }}" loop_control: label: "{{ item.name }}" tags: ["aur"] when: distro == 'archlinux' - block: - name: load package list include_vars: file: packages.yml - name: force-update iptables to iptables-nft on arch shell: pacman -Q iptables && yes | pacman -S iptables-nft changed_when: false become: true when: distro == 'archlinux' - set_fact: defined_packages: "{{ packages|json_query('keys(list)') }}" - set_fact: distro_packages: "{{ packages|json_query('list.*.%s'|format(distro)) }}" - name: check list assert: that: "defined_packages|length == distro_packages|length" - set_fact: defined_packages_remove: "{{ packages|json_query('keys(remove)') }}" - set_fact: distro_packages_remove: "{{ packages|json_query('remove.*.%s'|format(distro)) }}" - name: check list assert: that: "defined_packages_remove|length == distro_packages_remove|length" - name: remove packages package: name: "{{ packages|json_query(query) }}" state: absent become: true vars: query: "{{ 'remove.*.%s[]'|format(distro) }}" - name: install packages package: name: "{{ packages|json_query(query) }}" state: present become: true vars: query: "{{ 'list.*.%s[]'|format(distro) }}" - name: install machine-specific packages package: name: "{{ machine.packages }}" state: present when: machine.packages is defined become: true tags: [packages] - block: - name: configure timesyncd on arch copy: owner: root group: root mode: "0644" dest: /etc/systemd/timesyncd.conf content: | [Time] NTP=0.arch.pool.ntp.org 1.arch.pool.ntp.org 2.arch.pool.ntp.org 3.arch.pool.ntp.org FallbackNTP=0.pool.ntp.org 1.pool.ntp.org 2.pool.ntp.org 3.pool.ntp.org become: true - name: install lz4 package: name: lz4 state: present become: true - name: use lz4 for mkinitcpio compression lineinfile: path: /etc/mkinitcpio.conf regexp: '^#?COMPRESSION=.*$' line: 'COMPRESSION="lz4"' become: true notify: - rebuild initrd when: distro == 'archlinux' - set_fact: disable_services: - sshd when: distro == 'archlinux' - name: disable services service: state: stopped enabled: false name: "{{ item }}" with_items: "{{ disable_services }}" become: true when: manage_services|default(true)|bool - set_fact: enable_services: - NetworkManager - docker - libvirtd - systemd-timesyncd - pcscd - name: enable services service: state: started enabled: true name: "{{ item }}" with_items: "{{ enable_services }}" become: true when: manage_services|default(true)|bool - name: get systemd boot target command: systemctl get-default register: systemd_target changed_when: false check_mode: false - set_fact: default_target: multi-user.target - name: set systemd boot target command: systemctl set-default {{ default_target }} when: systemd_target.stdout != default_target become: true - name: handle lid switch lineinfile: path: /etc/systemd/logind.conf regexp: '^HandleLidSwitch=' line: 'HandleLidSwitch=ignore' become: true - name: handle power key lineinfile: path: /etc/systemd/logind.conf regexp: '^HandlePowerKey=' line: 'HandlePowerKey=suspend' become: true - name: create sudonopw group group: name: sudonopw system: true - name: configure passwordless sudo copy: owner: root group: root mode: "0600" dest: /etc/sudoers.d/sudonopw content: | %sudonopw ALL=(ALL) NOPASSWD: ALL become: true - block: - name: install AMDGPU packages package: name: - mesa - lib32-mesa - xf86-video-amdgpu - vulkan-radeon - lib32-vulkan-radeon - libva-mesa-driver - lib32-libva-mesa-driver - mesa-vdpau - lib32-mesa-vdpau state: present become: true - name: set AMDGPU options copy: owner: root group: root mode: "0600" dest: /etc/X11/xorg.conf.d/20-amdgpu.conf content: | Section "Device" Identifier "AMD" Driver "amdgpu" Option "VariableRefresh" "true" Option "TearFree" "true" EndSection become: true when: - distro == 'archlinux' - machine.gpu is defined and machine.gpu == 'amd' - set_fact: users: "{{ machine.users }}" tags: - always - include_tasks: user.yml args: apply: become: true become_user: "{{ user.name }}" with_items: "{{ users }}" no_log: True # less spam loop_control: loop_var: user tags: - always handlers: - name: rebuild initrd command: mkinitcpio -P become: true register: mkinitcpio_cmd failed_when: > mkinitcpio_cmd.rc != 0 and not (mkinitcpio_cmd.rc == 1 and "file not found: `fsck.overlay'" in mkinitcpio_cmd.stderr)