diff --git a/roles/dev-nix/TODO.md b/roles/dev-nix/TODO.md new file mode 100644 index 00000000..9fdd5748 --- /dev/null +++ b/roles/dev-nix/TODO.md @@ -0,0 +1,2 @@ +# to-dos +- Implement better hash validation for security \ No newline at end of file diff --git a/roles/dev-nix/defaults/main.yml b/roles/dev-nix/defaults/main.yml index 0e4084ef..b0e42f5d 100644 --- a/roles/dev-nix/defaults/main.yml +++ b/roles/dev-nix/defaults/main.yml @@ -1,14 +1,22 @@ --- -# Path to the installer script inside this role -dev_nix_installer_source: "nix-install.sh" +# Nix version to install via official installer +dev_nix_installer_version: "2.32.4" -# Path where the installer will be copied on the target host +# Base URL for Nix releases +dev_nix_installer_base_url: "https://releases.nixos.org/nix" + +# Full URL to the installer script (can be overridden if needed) +dev_nix_installer_url: >- + {{ dev_nix_installer_base_url }}/nix-{{ dev_nix_installer_version }}/install + +# Full URL to the SHA256 checksum file +dev_nix_installer_sha256_url: "{{ dev_nix_installer_url }}.sha256" + +# Path where the installer will be downloaded on the target host dev_nix_installer_dest: "/usr/local/share/nix-install.sh" -# Expected SHA256 of the installer file. -# You MUST set this to the actual hash of files/nix-install.sh, e.g.: -# sha256sum roles/dev-nix/files/nix-install.sh -dev_nix_installer_sha256: "CHANGE_ME_SHA256_OF_INSTALLER" +# Will be filled at runtime from dev_nix_installer_sha256_url +dev_nix_installer_sha256: "" # Whether to drop a small shell snippet into /etc/profile.d to ensure # Nix environment is available for login shells. @@ -16,3 +24,11 @@ dev_nix_enable_shell_snippet: false # Path of the profile.d snippet dev_nix_shell_snippet_path: "/etc/profile.d/nix.sh" + +# Enable experimental features such as nix-command and flakes +dev_nix_enable_experimental_features: true + +# List of experimental features to enable when dev_nix_enable_experimental_features is true +dev_nix_experimental_features: + - nix-command + - flakes diff --git a/roles/dev-nix/tasks/01_core.yml b/roles/dev-nix/tasks/01_core.yml new file mode 100644 index 00000000..f4dd5be0 --- /dev/null +++ b/roles/dev-nix/tasks/01_core.yml @@ -0,0 +1,49 @@ +--- +# Install Nix differently depending on the target platform: +# - Arch-based systems: install via package manager +# - Non-Arch systems: use the official installer with SHA256 verification + +# 1) Arch-based systems: just install the distro package +- name: Install Nix via package manager on Arch-based systems + community.general.pacman: + name: nix + state: present + become: true + when: ansible_facts.os_family == "Archlinux" + +# 2) Non-Arch systems: delegate installer logic to a separate task file +- name: Include non-Arch installer logic + ansible.builtin.include_tasks: 02_non_arch_installer.yml + when: ansible_facts.os_family != "Archlinux" + +# 3) Configure Nix experimental features (common for all platforms) +- name: Ensure Nix config directory exists + ansible.builtin.file: + path: /etc/nix + state: directory + mode: "0755" + when: dev_nix_enable_experimental_features | bool + become: true + +- name: Deploy Nix configuration (nix.conf) + ansible.builtin.template: + src: "nix.conf.j2" + dest: "/etc/nix/nix.conf" + mode: "0644" + become: true + +# 4) Optionally drop shell snippet for Nix +- name: Optionally drop shell snippet for Nix + ansible.builtin.copy: + dest: "{{ dev_nix_shell_snippet_path }}" + mode: "0644" + content: | + # Added by dev-nix Ansible role + if [ -e /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh ]; then + . /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh + fi + when: dev_nix_enable_shell_snippet | bool + become: true + +# 5) Mark this role as "run once" in your global once-flag system +- include_tasks: utils/once/flag.yml diff --git a/roles/dev-nix/tasks/02_non_arch_installer.yml b/roles/dev-nix/tasks/02_non_arch_installer.yml new file mode 100644 index 00000000..287e1113 --- /dev/null +++ b/roles/dev-nix/tasks/02_non_arch_installer.yml @@ -0,0 +1,37 @@ +--- +# Non-Arch installer logic: +# Download the official Nix installer and its SHA256 from releases.nixos.org +# and run the daemon (multi-user) installer. + +# 1) Fetch the official SHA256 from releases.nixos.org on the control node +- name: Fetch official Nix installer SHA256 + ansible.builtin.uri: + url: "{{ dev_nix_installer_sha256_url }}" + return_content: true + register: dev_nix_official_sha_response + delegate_to: localhost + run_once: true + +- name: Set expected installer checksum from official SHA256 + ansible.builtin.set_fact: + dev_nix_installer_sha256: >- + {{ dev_nix_official_sha_response.content.split()[0] | trim }} + run_once: true + +# 2) Download installer script on the target and verify via checksum +- name: Download Nix installer script from official releases + ansible.builtin.get_url: + url: "{{ dev_nix_installer_url }}" + dest: "{{ dev_nix_installer_dest }}" + mode: "0755" + # get_url will verify the checksum and fail if it does not match + checksum: "sha256:{{ dev_nix_installer_sha256 }}" + become: true + +# 3) Run Nix installer in daemon (multi-user) mode if Nix is not installed +- name: Run Nix installer in daemon (multi-user) mode if Nix is not installed + ansible.builtin.shell: > + "{{ dev_nix_installer_dest }}" --daemon + args: + creates: "/nix/store" + become: true diff --git a/roles/dev-nix/tasks/install.yml b/roles/dev-nix/tasks/install.yml deleted file mode 100644 index 04392f5e..00000000 --- a/roles/dev-nix/tasks/install.yml +++ /dev/null @@ -1,44 +0,0 @@ ---- -# Install Nix using a locally stored installer script with SHA256 verification. - -- name: Ensure Nix installer script is present on target - ansible.builtin.copy: - src: "{{ dev_nix_installer_source }}" - dest: "{{ dev_nix_installer_dest }}" - mode: "0755" - become: true - -- name: Verify Nix installer SHA256 checksum - ansible.builtin.command: > - sh -c "sha256sum '{{ dev_nix_installer_dest }}' | awk '{print $1}'" - register: dev_nix_checksum_result - changed_when: false - become: true - -- name: Fail if Nix installer checksum does not match - ansible.builtin.fail: - msg: >- - Nix installer checksum mismatch. - Expected '{{ dev_nix_installer_sha256 }}', got '{{ dev_nix_checksum_result.stdout }}'. - Refusing to execute the installer. - when: dev_nix_checksum_result.stdout != dev_nix_installer_sha256 - -# Nix multi-user (daemon) mode: creates /nix/store when successful. -- name: Run Nix installer in daemon (multi-user) mode if Nix is not installed - ansible.builtin.shell: > - "{{ dev_nix_installer_dest }}" --daemon - args: - creates: "/nix/store" - become: true - -- name: Optionally drop shell snippet for Nix - ansible.builtin.copy: - dest: "{{ dev_nix_shell_snippet_path }}" - mode: "0644" - content: | - # Added by dev-nix Ansible role - if [ -e /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh ]; then - . /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh - fi - when: dev_nix_enable_shell_snippet | bool - become: true diff --git a/roles/dev-nix/tasks/main.yml b/roles/dev-nix/tasks/main.yml index 6e9975b7..03885f42 100644 --- a/roles/dev-nix/tasks/main.yml +++ b/roles/dev-nix/tasks/main.yml @@ -1,5 +1,3 @@ --- -# Main entrypoint for the dev-nix role - -- name: Include installation tasks for Nix - ansible.builtin.include_tasks: install.yml +- include_tasks: 01_core.yml + when: run_once_dev_nix is not defined diff --git a/roles/dev-nix/templates/nix.conf.j2 b/roles/dev-nix/templates/nix.conf.j2 new file mode 100644 index 00000000..064716cb --- /dev/null +++ b/roles/dev-nix/templates/nix.conf.j2 @@ -0,0 +1,12 @@ +# Nix configuration file +# Managed by the {{ SOFTWARE_NAME }}dev-nix Ansible role + +# Unix group containing the Nix build user accounts +build-users-group = nixbld + +# Enable experimental features if configured +{% if dev_nix_enable_experimental_features %} +experimental-features = {{ dev_nix_experimental_features | join(" ") }} +{% endif %} + +# (Optional) Add more global nix.conf options below diff --git a/roles/pkgmgr/tasks/01_core.yml b/roles/pkgmgr/tasks/01_core.yml index 9b59fec8..5cdb8c77 100644 --- a/roles/pkgmgr/tasks/01_core.yml +++ b/roles/pkgmgr/tasks/01_core.yml @@ -4,7 +4,7 @@ loop: - dev-git - dev-make - - dev-python-yaml + - dev-nix - name: Ensure OpenSSH client is installed community.general.pacman: @@ -66,7 +66,7 @@ become: true - name: "Update all repositories with pkgmgr" - command: "pkgmgr pull --all" + command: "pkgmgr update --all --clone-mode shallow" when: MODE_UPDATE | bool - include_tasks: utils/once/flag.yml