From 22a76436ca9acced00c517b57ae2f2b73a197de0 Mon Sep 17 00:00:00 2001 From: Jan Tuomi Date: Thu, 13 Aug 2026 22:18:47 +0300 Subject: Update immich jail --- roles/jail/templates/jail_conf.j2 | 3 +- roles/jails/20_immich/defaults/main.yml | 1 + roles/jails/20_immich/tasks/main.yml | 45 ++++++++++----------- roles/jails/20_immich/templates/jail.conf.j2 | 19 +++++---- .../templates/usr_local_bin_extract_image.sh | 47 ---------------------- 5 files changed, 36 insertions(+), 79 deletions(-) delete mode 100644 roles/jails/20_immich/templates/usr_local_bin_extract_image.sh (limited to 'roles') diff --git a/roles/jail/templates/jail_conf.j2 b/roles/jail/templates/jail_conf.j2 index d8e0667..25d12bb 100644 --- a/roles/jail/templates/jail_conf.j2 +++ b/roles/jail/templates/jail_conf.j2 @@ -3,10 +3,11 @@ exec.clean; allow.raw_sockets; - mount.devfs; # Mount /dev according to devfs_ruleset + mount.devfs; # Mount /dev according to devfs_ruleset devfs_ruleset = {{ jail.devfs_ruleset }}; enforce_statfs = 1; # Let jail see own mounts + {% for opt in jail.options %} {{ opt }}; {% endfor %} diff --git a/roles/jails/20_immich/defaults/main.yml b/roles/jails/20_immich/defaults/main.yml index 6cb9390..97f4a13 100644 --- a/roles/jails/20_immich/defaults/main.yml +++ b/roles/jails/20_immich/defaults/main.yml @@ -26,5 +26,6 @@ nullfs: pkg: - skopeo + # umoci is a statically linked Linux binary, fetched by setup task services: [] diff --git a/roles/jails/20_immich/tasks/main.yml b/roles/jails/20_immich/tasks/main.yml index cac290e..bcd8258 100644 --- a/roles/jails/20_immich/tasks/main.yml +++ b/roles/jails/20_immich/tasks/main.yml @@ -26,16 +26,20 @@ nullfs: "{{ nullfs | default([]) | normalize_nullfs }}" delegate_to: "{{ jail_delegate_host }}" -# Deploy extraction script -- name: Deploy extract-image script - template: - src: "{{ jail_role_dir }}/templates/usr_local_bin_extract_image.sh" - dest: /usr/local/bin/extract-image.sh - owner: root - group: wheel - mode: "0755" +# Fetch umoci Linux binary (statically linked, runs via Linux compat) +- name: Check if umoci is installed + stat: + path: /usr/local/bin/umoci + register: _umoci_stat + +- name: Fetch umoci Linux binary + shell: | + fetch -o /tmp/umoci https://github.com/opencontainers/umoci/releases/latest/download/umoci.linux.amd64 + install -m 755 /tmp/umoci /usr/local/bin/umoci + rm /tmp/umoci + when: not _umoci_stat.stat.exists -# Create image directory +# Create /image directory - name: Create /image directory file: path: /image @@ -54,7 +58,15 @@ register: _images_extracted - name: Extract OCI images - shell: "/usr/local/bin/extract-image.sh {{ item.item.image }} {{ item.item.name }}" + shell: | + TMPDIR="/tmp/oci_extract_{{ item.item.name }}" + rm -rf "$TMPDIR" + mkdir -p "$TMPDIR" + skopeo copy --override-os linux "docker://{{ item.item.image }}" "oci:$TMPDIR/image" + umoci unpack --image "$TMPDIR/image" "$TMPDIR/unpacked" + rm -rf "/image/{{ item.item.name }}" + mv "$TMPDIR/unpacked/rootfs" "/image/{{ item.item.name }}" + rm -rf "$TMPDIR" loop: "{{ _images_extracted.results }}" loop_control: label: "{{ item.item.name }}" @@ -72,19 +84,6 @@ label: "{{ item[0].name }}:{{ item[1].dst }}" when: "item[1].dst.startswith('/image/' + item[0].name)" -# Create mount points in each rootfs -- name: Create base mount points in image rootfs - file: - path: "/image/{{ item[0].name }}/{{ item[1] }}" - state: directory - owner: root - group: wheel - mode: "0755" - loop: "{{ oci_images | product(['proc', 'sys', 'dev', 'tmp', 'run']) | list }}" - loop_control: - label: "{{ item[0].name }}/{{ item[1] }}" - -# Deploy resolv.conf into each rootfs - name: Deploy resolv.conf into image rootfs copy: content: "nameserver {{ lan_ipv4_gateway }}\n" diff --git a/roles/jails/20_immich/templates/jail.conf.j2 b/roles/jails/20_immich/templates/jail.conf.j2 index 47a0454..6486677 100644 --- a/roles/jails/20_immich/templates/jail.conf.j2 +++ b/roles/jails/20_immich/templates/jail.conf.j2 @@ -1,11 +1,14 @@ +{% set devfs_ruleset = 4 -%} {{ jail.name }} { vnet; exec.clean; allow.raw_sockets; - mount.devfs; - enforce_statfs = 1; - devfs_ruleset = 4; + mount.devfs; # Mount /dev according to devfs_ruleset + devfs_ruleset = {{ devfs_ruleset }}; + + enforce_statfs = 1; # Let jail see own mounts + host.hostname = "${name}"; path = "/usr/local/jails/containers/${name}"; @@ -25,10 +28,10 @@ {% for img in oci_images %} # Mounts for {{ img.name }} rootfs - mount += "linprocfs $path/image/{{ img.name }}/proc linprocfs rw 0 0"; - mount += "linsysfs $path/image/{{ img.name }}/sys linsysfs rw 0 0"; - mount += "devfs $path/image/{{ img.name }}/dev devfs rw 0 0"; - mount += "tmpfs $path/image/{{ img.name }}/tmp tmpfs rw 0 0"; - mount += "tmpfs $path/image/{{ img.name }}/run tmpfs rw 0 0"; + mount += "devfs $path/image/{{ img.name }}/dev devfs rw,ruleset={{ devfs_ruleset }} 0 0"; + mount += "linprocfs $path/image/{{ img.name }}/proc linprocfs rw 0 0"; + mount += "linsysfs $path/image/{{ img.name }}/sys linsysfs rw 0 0"; + mount += "tmpfs $path/image/{{ img.name }}/tmp tmpfs rw 0 0"; + mount += "tmpfs $path/image/{{ img.name }}/run tmpfs rw 0 0"; {% endfor %} } diff --git a/roles/jails/20_immich/templates/usr_local_bin_extract_image.sh b/roles/jails/20_immich/templates/usr_local_bin_extract_image.sh deleted file mode 100644 index e8226dd..0000000 --- a/roles/jails/20_immich/templates/usr_local_bin_extract_image.sh +++ /dev/null @@ -1,47 +0,0 @@ -#!/bin/sh -# Extract a Docker image to a directory under /image/ -# Usage: extract-image.sh -# Example: extract-image.sh ghcr.io/immich-app/immich-server:v2.4.1 immich-server - -set -eu - -IMAGE="$1" -NAME="$2" -IMAGE_DIR="/image" -TARGET="${IMAGE_DIR}/${NAME}" -TMP_DIR="/tmp/oci-${NAME}" - -echo "Extracting ${IMAGE} to ${TARGET}..." - -# Clean up any previous extraction attempt -rm -rf "${TMP_DIR}" -mkdir -p "${TMP_DIR}" - -# Pull image layers -skopeo copy --override-os linux "docker://${IMAGE}" "dir:${TMP_DIR}" - -# Extract all layers in order into new rootfs -rm -rf "${TARGET}.new" -mkdir -p "${TARGET}.new" - -# Parse layer digests from manifest and extract each layer -grep -o '"sha256:[a-f0-9]*"' "${TMP_DIR}/manifest.json" | \ - sed 's/"//g; s/sha256://' | \ - while read hash; do - if [ -f "${TMP_DIR}/${hash}" ]; then - echo " Extracting layer ${hash}..." - tar -xzf "${TMP_DIR}/${hash}" -C "${TARGET}.new" 2>/dev/null || \ - tar -xf "${TMP_DIR}/${hash}" -C "${TARGET}.new" 2>/dev/null || true - fi - done - -# Swap in the new rootfs -if [ -d "${TARGET}" ]; then - mv "${TARGET}" "${TARGET}.old" -fi -mv "${TARGET}.new" "${TARGET}" - -# Cleanup -rm -rf "${TMP_DIR}" "${TARGET}.old" - -echo "Done: ${TARGET}" -- cgit v1.3