From 2181d490e9b426923a7307c418095407e41214b4 Mon Sep 17 00:00:00 2001 From: Petr Date: Sun, 15 Mar 2026 11:40:11 +0100 Subject: [PATCH] Fix systemd NAMESPACE failures caused by missing ReadWritePaths dirs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit data-refresh.service: use /tmp instead of /tmp/data_analyst_staging in ReadWritePaths — the subdirectory may not exist at service start, causing mount namespace setup to fail before any Exec* directive runs. deploy.sh: fix typo services/corporate-memory -> services/corporate_memory so the mkdir conditional actually matches the repo directory name. deploy.sh: add ReadWritePaths validation loop that auto-creates any missing directories listed in installed .service files before daemon-reload. This acts as a safety net against future NAMESPACE failures from new services. --- server/deploy.sh | 20 ++++++++++++++++++- .../data_refresh/systemd/data-refresh.service | 4 ++-- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/server/deploy.sh b/server/deploy.sh index 55d667c..dd9204e 100755 --- a/server/deploy.sh +++ b/server/deploy.sh @@ -202,7 +202,7 @@ if [[ -f "${REPO_DIR}/auth/password.py" ]]; then fi # Corporate memory directory -if [[ -d "${REPO_DIR}/services/corporate-memory" ]]; then +if [[ -d "${REPO_DIR}/services/corporate_memory" ]]; then log "Setting up corporate memory directory..." sudo /usr/bin/mkdir -p /data/corporate-memory sudo /usr/bin/chown root:data-ops /data/corporate-memory @@ -238,6 +238,24 @@ for unit_file in "${REPO_DIR}"/services/*/systemd/*.service "${REPO_DIR}"/servic fi done if [[ "$SYSTEMD_CHANGED" == "true" ]]; then + # Ensure all ReadWritePaths directories exist before daemon-reload. + # ProtectSystem=strict uses mount namespaces for ReadWritePaths — if any + # listed path is missing, the service fails at NAMESPACE step before any + # Exec* directive runs. This loop prevents that class of failures. + log "Validating ReadWritePaths directories..." + for installed_unit in /etc/systemd/system/*.service; do + [[ -f "$installed_unit" ]] || continue + rw_paths=$(grep -oP '^ReadWritePaths=\K.*' "$installed_unit" 2>/dev/null || true) + for rw_path in $rw_paths; do + if [[ ! -d "$rw_path" ]]; then + log " Creating missing ReadWritePaths: $rw_path (required by $(basename "$installed_unit"))" + sudo /usr/bin/mkdir -p "$rw_path" + sudo /usr/bin/chown root:data-ops "$rw_path" + sudo /usr/bin/chmod 2770 "$rw_path" + fi + done + done + sudo /usr/bin/systemctl daemon-reload log " systemd daemon-reload completed" fi diff --git a/services/data_refresh/systemd/data-refresh.service b/services/data_refresh/systemd/data-refresh.service index 7ed0b9c..14e9a49 100644 --- a/services/data_refresh/systemd/data-refresh.service +++ b/services/data_refresh/systemd/data-refresh.service @@ -15,9 +15,9 @@ EnvironmentFile=/opt/data-analyst/.env Environment=PYTHONPATH=/opt/data-analyst/repo Environment=CONFIG_DIR=/opt/data-analyst/instance/config -# Write access to data directory and logs +# Write access to data directory, logs, and /tmp (for staging + lock file) ProtectSystem=strict -ReadWritePaths=/data /opt/data-analyst/logs /tmp/data_analyst_staging +ReadWritePaths=/data /opt/data-analyst/logs /tmp PrivateTmp=false # Sync can take a while for large tables