diff --git a/init.sh b/init.sh index bb32576..794b9a5 100755 --- a/init.sh +++ b/init.sh @@ -830,6 +830,45 @@ initFolders() isSuccessful "All folders have been created." } +# Establish the rootless container layer — the docker-install user and ownership +# of /docker/containers — during the ROOT phase, BEFORE the manager-run install +# boots. That boot scans app configs under /docker/containers AS the container +# user (runFileOp), so if the dir is still manager-owned (as initFolders leaves +# it) the scan errors with "Permission denied". Handing the dir to the container +# user here means the scan reads a dir it owns. Rootless-only — rooted keeps +# containers manager/root-owned, which the manager reads fine. Idempotent: the +# later rootless setup finds the user existing and just (re)asserts its password +# + daemon config. Runs after initGIT (config present) + initFolders (dir present). +initContainerLayer() +{ + local cfg="$configs_dir/general/general_docker_install" + local dtype duser + dtype=$(grep -h '^CFG_DOCKER_INSTALL_TYPE=' "$cfg" 2>/dev/null | head -1 | cut -d= -f2 | awk '{print $1}') + [[ "$dtype" != "rootless" ]] && return 0 + duser=$(grep -h '^CFG_DOCKER_INSTALL_USER=' "$cfg" 2>/dev/null | head -1 | cut -d= -f2 | awk '{print $1}') + duser="${duser:-dockerinstall}" + + isHeader "Container Layer Setup" + if id "$duser" &>/dev/null; then + isSuccessful "Container user '$duser' already exists." + else + # -m + the system login.defs SUB_UID/GID defaults assign its subordinate + # uid/gid ranges (needed for rootless). The later rootless setup sees it + # existing and configures the daemon/linger/password. + sudo useradd -m -s /bin/bash -d "/home/$duser" "$duser" 2>/dev/null + isSuccessful "Created container user '$duser'." + fi + + # Hand containers/ to the container user (it owns per-app data in rootless) so + # the manager-run startup config scans can read it. 751: owner full; the + # manager (other) can traverse in to known paths (it lists/writes via runFileOp). + if [[ -d "$containers_dir" ]]; then + sudo chown "$duser:$duser" "$containers_dir" + sudo chmod 751 "$containers_dir" + isSuccessful "containers/ handed to '$duser'." + fi +} + setupConfigsFromRepo() { isNotice "Setting up configuration files from repository..." @@ -1468,6 +1507,7 @@ else initRootHelpers initLibrePortalCommand initUpdateConfigs + initContainerLayer completeInitMessage elif [[ "$param1" == "uninstall" ]]; then runFullUninstall diff --git a/scripts/config/application/application_missing_variables.sh b/scripts/config/application/application_missing_variables.sh index e3d3ba1..e5598ac 100755 --- a/scripts/config/application/application_missing_variables.sh +++ b/scripts/config/application/application_missing_variables.sh @@ -9,10 +9,7 @@ checkApplicationsConfigFilesMissingVariables() app=$(basename "$live" .config) remote="$install_containers_dir$app/$app.config" reconcileConfigFile "$live" "$remote" - # 2>/dev/null: before the docker-type config loads (early install) runFileOp - # falls back to the manager, which can't list the container-owned containers/ - # dir — harmless "Permission denied" on a best-effort reconcile (no apps yet). - done < <(runFileOp find "$containers_dir" -maxdepth 2 -type f -name '*.config' ! -name '*.bak' 2>/dev/null) + done < <(runFileOp find "$containers_dir" -maxdepth 2 -type f -name '*.config' ! -name '*.bak') isSuccessful "Application config reconciliation completed." } diff --git a/scripts/docker/install/rootless/rootless_user.sh b/scripts/docker/install/rootless/rootless_user.sh index 7f46a32..61f0f1d 100755 --- a/scripts/docker/install/rootless/rootless_user.sh +++ b/scripts/docker/install/rootless/rootless_user.sh @@ -14,7 +14,10 @@ installDockerRootlessUser() # rootless). Run unmasked so checkSuccess sees real failures. runSystem useradd -m -s /bin/bash -d "/home/$CFG_DOCKER_INSTALL_USER" "$CFG_DOCKER_INSTALL_USER" checkSuccess "Creating $CFG_DOCKER_INSTALL_USER User." - updateDockerInstallPassword; fi + # (Re)assert the password regardless — the user may have been pre-created + # in init.sh's root phase (so /docker/containers ownership is ready before + # the manager-run boot scans), where the password isn't set. + updateDockerInstallPassword; fi } diff --git a/scripts/source/loading/scan_files.sh b/scripts/source/loading/scan_files.sh index cc77c9a..9643c24 100755 --- a/scripts/source/loading/scan_files.sh +++ b/scripts/source/loading/scan_files.sh @@ -61,12 +61,7 @@ sourceScanFiles() source "$file" # echo "$load_type FILE $file" fi - # 2>/dev/null: early in an install the docker-type config isn't loaded - # yet, so runFileOp falls back to the manager, which can't list the - # container-owned containers/ dir — a harmless "Permission denied" on a - # best-effort scan (no app configs exist yet). Suppress that noise; the - # -print0 output still flows. - done < <($scan_op find "$folder_dir" -maxdepth 3 -type d \( -name 'resources' \) -prune -o -type f -name "$file_pattern" -print0 2>/dev/null) + done < <($scan_op find "$folder_dir" -maxdepth 3 -type d \( -name 'resources' \) -prune -o -type f -name "$file_pattern" -print0) fi # Load the categories from the file into an array