diff --git a/ansible/roles/compiled/tasks/common/apptainer.yaml b/ansible/roles/compiled/tasks/common/apptainer.yaml index cc218f0..64bf209 100644 --- a/ansible/roles/compiled/tasks/common/apptainer.yaml +++ b/ansible/roles/compiled/tasks/common/apptainer.yaml @@ -42,8 +42,13 @@ path: "{{ apptainer_dir }}" state: directory mode: u=rwx,g=rx,o=rx + # localstatedir lives under install_dir on purpose: it holds only empty + # mount-point stubs (<1 MiB), written only at `make install` and never at + # runtime (the runtime mounts over the stubs). This keeps the install + # sudo-free and lets install_dir be mounted/chmod'd read-only. + # Do NOT move it back to /usr/local/var. - name: Configure apptainer - command: "./mconfig --prefix={{ install_dir }} --localstatedir=/usr/local/var --sysconfdir={{ install_dir }}/etc --with-suid" + command: "./mconfig --prefix={{ install_dir }} --localstatedir={{ install_dir }}/var --sysconfdir={{ install_dir }}/etc --without-suid" args: chdir: "{{ unzip_dir }}" creates: "{{ unzip_dir }}/builddir/Makefile" @@ -59,7 +64,6 @@ make: chdir: "{{ unzip_dir }}/builddir" target: install - become: true - name: Install apptainer {{ version_number }} module block: @@ -73,22 +77,11 @@ src: common/apptainer.lua dest: "{{ apptainer_module_dir }}/{{ version_number }}.lua" - - name: Configure apptainer {{ version_number }} - block: - - name: Ensure apptainer config directory exists - file: - path: "{{ install_dir }}/etc/apptainer" - state: directory - mode: u=rwx,g=rx,o=rx - owner: root - group: root - become: true - - name: Deploy apptainer configuration file - template: - src: common/apptainer.conf - dest: "{{ install_dir }}/etc/apptainer/apptainer.conf" - mode: u=rw,g=r,o=r - owner: root - group: root - backup: yes - become: true + - name: Reminder to disable setuid in apptainer.conf + ansible.builtin.debug: + msg: >- + Apptainer {{ version_number }} built --without-suid into {{ install_dir }}. + The config file {{ install_dir }}/etc/apptainer/apptainer.conf is managed + elsewhere, NOT by this repo. Ensure 'allow setuid = no' (and 'allow + setuid-mount squashfs = no') is set there so the runtime uses unprivileged + user namespaces and never the setuid flow. diff --git a/ansible/roles/compiled/tasks/common/main.yml b/ansible/roles/compiled/tasks/common/main.yml index 803574c..7125720 100644 --- a/ansible/roles/compiled/tasks/common/main.yml +++ b/ansible/roles/compiled/tasks/common/main.yml @@ -804,6 +804,11 @@ checksum: "sha256:0335f314b6e7bfe08c3d0cfaa7c19db961b7b99fb20be62b0a826c992ad14e0f", url: "https://golang.org/dl/go1.25.3.linux-amd64.tar.gz", } + - { + version_number: "1.25.10", + checksum: "sha256:42d4f7a32316aa66591eca7e89867256057a4264451aca10570a715b3637ba70", + url: "https://golang.org/dl/go1.25.10.linux-amd64.tar.gz", + } include_tasks: file: golang.yaml loop: "{{ go_versions }}" @@ -815,69 +820,77 @@ vars: singularity_versions: - { - version_number: "3.8.0", - checksum: "sha256:5fa2c0e7ef2b814d8aa170826b833f91e5031a85d85cd1292a234e6c55da1be1", - url: "https://github.com/sylabs/singularity/releases/download/v3.8.0/singularity-ce-3.8.0.tar.gz", - go_location: "{{ common_dir }}/golang/1.16.3/bin" - } - - { - version_number: "3.8.3", - checksum: "sha256:9ecb6f01f1a3f2cd8d0f73d9806201ec1b25b23c9722d374a6430eeba0785981", - url: "https://github.com/sylabs/singularity/releases/download/v3.8.3/singularity-ce-3.8.3.tar.gz", - go_location: "{{ common_dir }}/golang/1.16.3/bin" - } - - { - version_number: "2.6.1", - checksum: "sha256:f38d46a225e8368eb4693137806d2dc96e925a50bdf7f6983662848831041df2" - } - - { - version_number: "3.9.0", - checksum: "sha256:3569928cbd907fe90c52f6a809f5f8e99f597237c5a25a9dce07e3efb3b1447a", - url: "https://github.com/sylabs/singularity/releases/download/v3.9.0/singularity-ce-3.9.0.tar.gz", - go_location: "{{ common_dir }}/golang/1.16.3/bin" - } - - { - version_number: "3.9.1", - checksum: "sha256:1ba3bb1719a420f48e9b0a6afdb5011f6c786d0f107ef272528c632fff9fd153", - url: "https://github.com/sylabs/singularity/releases/download/v3.9.1/singularity-ce-3.9.1.tar.gz", - go_location: "{{ common_dir }}/golang/1.17.3/bin" - } - - { - version_number: "3.10.1", - checksum: "sha256:e3af12edc0260bc3a3a481459a3a4457de9235025e6b37288da80e3cdc011a7a", - url: "https://github.com/sylabs/singularity/releases/download/v3.10.1/singularity-ce-3.10.1.tar.gz", - go_location: "{{ common_dir }}/golang/1.18.4/bin" - } - - { - version_number: "3.11.3", - checksum: "sha256:a77ede063fd115f85f98f82d2e30459b5565db7d098665497bcd684bf8edaec9", - url: "https://github.com/sylabs/singularity/releases/download/v3.11.3/singularity-ce-3.11.3.tar.gz", - go_location: "{{ common_dir }}/golang/1.20.4/bin" - } - - { - version_number: "4.1.0", - checksum: "sha256:119667f18e76a750b7d4f8612d7878c18a824ee171852795019aa68875244813", - url: "https://github.com/sylabs/singularity/releases/download/v4.1.0/singularity-ce-4.1.0.tar.gz", - go_location: "{{ common_dir }}/golang/1.21.6/bin" - } - - { - version_number: "4.1.3", - checksum: "sha256:0a575292ddb2e7b74ab534b287c4dc8a1bd34d961accc0ba56ffa3714cca9c15", - url: "https://github.com/sylabs/singularity/releases/download/v4.1.3/singularity-ce-4.1.3.tar.gz", - go_location: "{{ common_dir }}/golang/1.22.4/bin" - } - - { - version_number: "4.2.2", - checksum: "sha256:f22c7eee64546abafada639225eb70c993da873abc05a48081402f18f49e47b1", - url: "https://github.com/sylabs/singularity/releases/download/v4.2.2/singularity-ce-4.2.2.tar.gz", - go_location: "{{ common_dir }}/golang/1.22.4/bin" - } - - { - version_number: "4.3.3", - checksum: "sha256:3b1517179f697293d1f09f75eadc43d25c92be132c279369c1096142ce9194be", - url: "https://github.com/sylabs/singularity/releases/download/v4.3.3/singularity-ce-4.3.3.tar.gz", - go_location: "{{ common_dir }}/golang/1.25.3/bin" - } + version_number: "4.4.1", + checksum: "sha256:5e0611d5e85d471e0a1dcfeef2c4e3bf01a6019bb7bfca10d955cd6c08853417", + url: "https://github.com/sylabs/singularity/releases/download/v4.4.1/singularity-ce-4.4.1.tar.gz", + go_location: "{{ common_dir }}/golang/1.25.10/bin" + } + # Older versions retained for reference only. We now install only the + # latest singularity, built --without-suid (see singularity.yaml). + # - { + # version_number: "3.8.0", + # checksum: "sha256:5fa2c0e7ef2b814d8aa170826b833f91e5031a85d85cd1292a234e6c55da1be1", + # url: "https://github.com/sylabs/singularity/releases/download/v3.8.0/singularity-ce-3.8.0.tar.gz", + # go_location: "{{ common_dir }}/golang/1.16.3/bin" + # } + # - { + # version_number: "3.8.3", + # checksum: "sha256:9ecb6f01f1a3f2cd8d0f73d9806201ec1b25b23c9722d374a6430eeba0785981", + # url: "https://github.com/sylabs/singularity/releases/download/v3.8.3/singularity-ce-3.8.3.tar.gz", + # go_location: "{{ common_dir }}/golang/1.16.3/bin" + # } + # - { + # version_number: "2.6.1", + # checksum: "sha256:f38d46a225e8368eb4693137806d2dc96e925a50bdf7f6983662848831041df2" + # } + # - { + # version_number: "3.9.0", + # checksum: "sha256:3569928cbd907fe90c52f6a809f5f8e99f597237c5a25a9dce07e3efb3b1447a", + # url: "https://github.com/sylabs/singularity/releases/download/v3.9.0/singularity-ce-3.9.0.tar.gz", + # go_location: "{{ common_dir }}/golang/1.16.3/bin" + # } + # - { + # version_number: "3.9.1", + # checksum: "sha256:1ba3bb1719a420f48e9b0a6afdb5011f6c786d0f107ef272528c632fff9fd153", + # url: "https://github.com/sylabs/singularity/releases/download/v3.9.1/singularity-ce-3.9.1.tar.gz", + # go_location: "{{ common_dir }}/golang/1.17.3/bin" + # } + # - { + # version_number: "3.10.1", + # checksum: "sha256:e3af12edc0260bc3a3a481459a3a4457de9235025e6b37288da80e3cdc011a7a", + # url: "https://github.com/sylabs/singularity/releases/download/v3.10.1/singularity-ce-3.10.1.tar.gz", + # go_location: "{{ common_dir }}/golang/1.18.4/bin" + # } + # - { + # version_number: "3.11.3", + # checksum: "sha256:a77ede063fd115f85f98f82d2e30459b5565db7d098665497bcd684bf8edaec9", + # url: "https://github.com/sylabs/singularity/releases/download/v3.11.3/singularity-ce-3.11.3.tar.gz", + # go_location: "{{ common_dir }}/golang/1.20.4/bin" + # } + # - { + # version_number: "4.1.0", + # checksum: "sha256:119667f18e76a750b7d4f8612d7878c18a824ee171852795019aa68875244813", + # url: "https://github.com/sylabs/singularity/releases/download/v4.1.0/singularity-ce-4.1.0.tar.gz", + # go_location: "{{ common_dir }}/golang/1.21.6/bin" + # } + # - { + # version_number: "4.1.3", + # checksum: "sha256:0a575292ddb2e7b74ab534b287c4dc8a1bd34d961accc0ba56ffa3714cca9c15", + # url: "https://github.com/sylabs/singularity/releases/download/v4.1.3/singularity-ce-4.1.3.tar.gz", + # go_location: "{{ common_dir }}/golang/1.22.4/bin" + # } + # - { + # version_number: "4.2.2", + # checksum: "sha256:f22c7eee64546abafada639225eb70c993da873abc05a48081402f18f49e47b1", + # url: "https://github.com/sylabs/singularity/releases/download/v4.2.2/singularity-ce-4.2.2.tar.gz", + # go_location: "{{ common_dir }}/golang/1.22.4/bin" + # } + # - { + # version_number: "4.3.3", + # checksum: "sha256:3b1517179f697293d1f09f75eadc43d25c92be132c279369c1096142ce9194be", + # url: "https://github.com/sylabs/singularity/releases/download/v4.3.3/singularity-ce-4.3.3.tar.gz", + # go_location: "{{ common_dir }}/golang/1.25.3/bin" + # } include_tasks: file: singularity.yaml loop: "{{ singularity_versions }}" @@ -919,16 +932,27 @@ vars: apptainer_versions: - { - version_number: "1.4.2", - checksum: "sha256:6dda1dd2ca8e42ed7f498d2bc8574f01d7ad3db68494e453639d76aef4424d1d", - url: "https://github.com/apptainer/apptainer/releases/download/v1.4.2/apptainer-1.4.2.tar.gz", - go_location: "{{ common_dir }}/golang/1.22.4/bin", + version_number: "1.5.0", + checksum: "sha256:36d67d57ef959397fa4f59169cf7deb92220537160e761e0c1cff84624ad81e3", + url: "https://github.com/apptainer/apptainer/releases/download/v1.5.0/apptainer-1.5.0.tar.gz", + go_location: "{{ common_dir }}/golang/1.25.10/bin", squashfuse_location: "{{ common_dir }}/squashfuse/0.6.1", gocryptfs_location: "{{ common_dir }}/gocryptfs/2.6.1", squashfuse_module: "squashfuse/0.6.1", gocryptfs_module: "gocryptfs/2.6.1" - } + # Older version retained for reference only. We now install only the + # latest apptainer, built --without-suid (see apptainer.yaml). + # - { + # version_number: "1.4.2", + # checksum: "sha256:6dda1dd2ca8e42ed7f498d2bc8574f01d7ad3db68494e453639d76aef4424d1d", + # url: "https://github.com/apptainer/apptainer/releases/download/v1.4.2/apptainer-1.4.2.tar.gz", + # go_location: "{{ common_dir }}/golang/1.22.4/bin", + # squashfuse_location: "{{ common_dir }}/squashfuse/0.6.1", + # gocryptfs_location: "{{ common_dir }}/gocryptfs/2.6.1", + # squashfuse_module: "squashfuse/0.6.1", + # gocryptfs_module: "gocryptfs/2.6.1" + # } include_tasks: file: apptainer.yaml loop: "{{ apptainer_versions }}" diff --git a/ansible/roles/compiled/tasks/common/singularity.yaml b/ansible/roles/compiled/tasks/common/singularity.yaml index f177878..0cc915d 100644 --- a/ansible/roles/compiled/tasks/common/singularity.yaml +++ b/ansible/roles/compiled/tasks/common/singularity.yaml @@ -35,9 +35,14 @@ file: path: "{{ singularity_dir }}" state: directory - mode: o=rwx,g=rx,o=rx + mode: u=rwx,g=rx,o=rx + # localstatedir lives under install_dir on purpose: it holds only empty + # mount-point stubs (<1 MiB), written only at `make install` and never at + # runtime (the runtime mounts over the stubs). This keeps the install + # sudo-free and lets install_dir be mounted/chmod'd read-only. + # Do NOT move it back to /usr/local/var. - name: Configure singularity - command: "./mconfig --prefix={{ install_dir }} --localstatedir=/usr/local/var --sysconfdir=/usr/local/etc{% if version_number is version('3.10', '>=') %} --without-seccomp --without-conmon{% endif %}" + command: "./mconfig --prefix={{ install_dir }} --localstatedir={{ install_dir }}/var --sysconfdir={{ install_dir }}/etc --without-suid{% if version_number is version('3.10', '>=') %} --without-seccomp{% endif %}{% if version_number is version('3.10', '>=') and version_number is version('4.3', '<') %} --without-conmon{% endif %}{% if version_number is version('4.3', '>=') %} --without-libsubid{% endif %}" args: chdir: "{{ unzip_dir }}" creates: "{{ unzip_dir }}/builddir/Makefile" @@ -48,7 +53,14 @@ make: chdir: "{{ unzip_dir }}/builddir" target: install - become: true + - name: Reminder to disable setuid in singularity.conf + ansible.builtin.debug: + msg: >- + Singularity {{ version_number }} built --without-suid into {{ install_dir }}. + The config file {{ install_dir }}/etc/singularity/singularity.conf is + managed elsewhere, NOT by this repo. Ensure 'allow setuid = no' is set + there so the runtime uses unprivileged user namespaces and never the + setuid flow. - name: Install singularity {{ version_number }} when: "version_number.startswith('2')" vars: @@ -70,7 +82,7 @@ file: path: "{{ singularity_dir }}" state: directory - mode: o=rwx,g=rx,o=rx + mode: u=rwx,g=rx,o=rx - name: Configure singularity (non-go) command: "./configure --prefix={{ install_dir }} --localstatedir=/usr/local/var --sysconfdir=/usr/local/etc" args: diff --git a/ansible/roles/compiled/templates/common/apptainer.conf b/ansible/roles/compiled/templates/common/apptainer.conf index 05d4ee2..8cea482 100644 --- a/ansible/roles/compiled/templates/common/apptainer.conf +++ b/ansible/roles/compiled/templates/common/apptainer.conf @@ -1,3 +1,8 @@ +# NOTE: RETAINED FOR REFERENCE ONLY. +# This template is no longer deployed by this repo. Apptainer's runtime config +# is managed elsewhere; this file is kept only as a reference for the required +# settings (notably 'allow setuid = no') and the ilifu bind paths. +# # APPTAINER.CONF # This is the global configuration file for Apptainer. This file controls # what the container is allowed to do on a particular host, and as a result @@ -13,7 +18,7 @@ # note2: If this option is disabled, it will rely on unprivileged user # namespaces which have not been integrated equally between different Linux # distributions. -allow setuid = yes +allow setuid = no # MAX LOOP DEVICES: [INT] # DEFAULT: 256 @@ -259,4 +264,4 @@ memory fs type = tmpfs # usage and optimize kernel cache (useful for MPI) shared loop devices = no limit container owners = -allow setuid-mount squashfs = yes +allow setuid-mount squashfs = no