opt-jimlab/scripts/podman/create-service-users.sh

111 lines
3.3 KiB
Bash
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/bin/bash
set -euo pipefail
shopt -s lastpipe
UID_MAP="/etc/jimlab/uid.map"
SUBID_MAP="/etc/jimlab/subid.map"
DEFAULT_SUBID_SIZE=4096
if [[ ! -f "$UID_MAP" ]]; then
echo "❌ Error: $UID_MAP not found."
exit 1
fi
touch "$SUBID_MAP"
# Return true if two ranges [start1, end1) and [start2, end2) overlap
ranges_overlap() {
local start1=$1
local size1=$2
local start2=$3
local size2=$4
[[ -z "$start1" || -z "$size1" || -z "$start2" || -z "$size2" ]] && return 1
[[ ! "$start1" =~ ^[0-9]+$ || ! "$size1" =~ ^[0-9]+$ || ! "$start2" =~ ^[0-9]+$ || ! "$size2" =~ ^[0-9]+$ ]] && return 1
local end1=$((start1 + size1))
local end2=$((start2 + size2))
[[ $start1 -lt $end2 && $start2 -lt $end1 ]]
}
# Get next available subid base
get_next_subid_base() {
local max=100000
grep -v '^\s*$' "$SUBID_MAP" | while IFS=: read -r _ base size; do
base=$(echo "$base" | xargs)
size=$(echo "$size" | xargs)
[[ "$base" =~ ^[0-9]+$ && "$size" =~ ^[0-9]+$ ]] || continue
local end=$((base + size))
(( end > max )) && max=$end
done
echo "$max"
}
# Warn if overlapping any prior block
check_overlap() {
local new_start=$1
local new_size=$2
grep -v '^\s*$' "$SUBID_MAP" | while IFS=: read -r user base size; do
if ranges_overlap "$new_start" "$new_size" "$base" "$size"; then
echo "⚠️ Warning: new block $new_start:$new_size overlaps with $user:$base:$size" >&2
fi
done
}
grep -v '^\s*$' "$UID_MAP" | while IFS=: read -r service uid; do
service=$(echo "$service" | xargs)
uid=$(echo "$uid" | xargs)
home="/var/lib/$service"
[[ -z "$service" || -z "$uid" || "$service" == \#* ]] && continue
echo "▶️ Processing $service (UID=$uid, HOME=$home)"
# Create group if missing
if ! getent group "$service" > /dev/null; then
echo " Creating group $service with GID $uid"
groupadd --system --gid "$uid" "$service"
fi
# Create or fix user
if ! id "$service" &>/dev/null; then
echo " Creating user $service with UID $uid and home $home"
useradd --system --uid "$uid" --gid "$uid" --home-dir "$home" --create-home --shell /sbin/nologin "$service"
else
current_home=$(getent passwd "$service" | cut -d: -f6)
if [[ "$current_home" != "$home" ]]; then
echo " 🛠 Updating home dir for $service$home"
usermod -d "$home" "$service"
mkdir -p "$home"
chown "$service:$service" "$home"
fi
fi
# Enable lingering
if ! loginctl show-user "$uid" &>/dev/null || ! loginctl show-user "$uid" | grep -q "Linger=yes"; then
echo " 🔄 Enabling lingering for $service"
loginctl enable-linger "$service"
fi
# Subuid/subgid mapping
if ! grep -q "^$service:" "$SUBID_MAP"; then
next_base=$(get_next_subid_base)
check_overlap "$next_base" "$DEFAULT_SUBID_SIZE"
echo " 📦 Assigning subid range: $service:$next_base:$DEFAULT_SUBID_SIZE"
echo "$service:$next_base:$DEFAULT_SUBID_SIZE" >> "$SUBID_MAP"
fi
# Sync to /etc/subuid and /etc/subgid
map_line=$(grep "^$service:" "$SUBID_MAP" | head -n1)
for file in /etc/subuid /etc/subgid; do
if ! grep -q "^$service:" "$file"; then
echo "$map_line" | sudo tee -a "$file" >/dev/null
elif ! grep -q "^$map_line\$" "$file"; then
echo "⚠️ Mismatch in $file for $service. Check manually!" >&2
fi
done
done