Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [0.0.12] - 2026-07-26

### Fixed

- Linux host updates now apply the verified runtime files, release symlink,
systemd units, restart, health check, and rollback inside one bounded
transient root transaction. This lets a v0.0.11 host escape its obsolete
`ProtectSystem=strict` mount namespace before atomically replacing host
files, while future updater units grant write access only to the required
parent trees.
- Fresh Linux installs create every LXC state/cache root named by the service
unit before systemd builds its private mount namespace, so the first launch
no longer depends on a channel computer having already been provisioned.

## [0.0.11] - 2026-07-26

### Added
Expand Down Expand Up @@ -334,7 +348,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
notarization, stapled tickets, Gatekeeper verification, persistent
Application Support, and isolated Apple container machines.

[Unreleased]: https://github.com/gitcommit90/1Helm/compare/v0.0.11...HEAD
[Unreleased]: https://github.com/gitcommit90/1Helm/compare/v0.0.12...HEAD
[0.0.12]: https://github.com/gitcommit90/1Helm/releases/tag/v0.0.12
[0.0.11]: https://github.com/gitcommit90/1Helm/releases/tag/v0.0.11
[0.0.10]: https://github.com/gitcommit90/1Helm/releases/tag/v0.0.10
[0.0.9]: https://github.com/gitcommit90/1Helm/releases/tag/v0.0.9
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ A fresh data directory opens first-run setup. The source runtime defaults to
| `PORT` | `8123` | HTTP/WebSocket control-plane port. |
| `CTRL_DATA_DIR` | `./data` | Databases, routing state, uploads, and narrow workspace mirrors. |
| `HELM_CHANNEL_COMPUTER_BACKEND` | `apple` on macOS, `lxc` on Linux, `wsl` on Windows | Host isolation backend; `native` and `mock` are explicit development/test overrides. |
| `HELM_CHANNEL_MACHINE_IMAGE` | `local/1helm-channel-machine:0.0.11` | Versioned channel-machine image contract. |
| `HELM_CHANNEL_MACHINE_IMAGE` | `local/1helm-channel-machine:0.0.12` | Versioned channel-machine image contract. |

### Agent-first JSON CLI

Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "1helm",
"productName": "1Helm",
"version": "0.0.11",
"version": "0.0.12",
"private": true,
"type": "module",
"license": "AGPL-3.0-only",
Expand Down
160 changes: 160 additions & 0 deletions site/public/apply-linux-release.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
#!/usr/bin/env bash
set -euo pipefail

# Apply one already downloaded, SHA-verified, built, and retained 1Helm Linux
# release as a single root transaction outside an older updater unit's mount
# namespace. No URL, command, or arbitrary destination is accepted here.

INSTALL_ROOT="/opt/1helm"
RELEASES_ROOT="$INSTALL_ROOT/releases"
APP_ROOT="$INSTALL_ROOT/current"
NODE_LINK="$INSTALL_ROOT/node-current"
STATE_ROOT="/var/lib/1helm"
SERVICE_USER="1helm"
SERVICE_NAME="1helm.service"
PORT="8123"
RELEASE_ROOT="$(readlink -f "${1:-}" 2>/dev/null || true)"
TARGET_VERSION="${2:-}"
STATUS_FILE="$STATE_ROOT/host-update-status.json"
HOST_CONTRACT_PATHS=(
/usr/libexec/1helm-lxc-runtime
/usr/libexec/1helm-lxc-net
/etc/1helm/lxc-unprivileged.conf
/etc/1helm/lxc-idmap
/etc/sudoers.d/1helm-lxc-runtime
/etc/default/lxc-net
/etc/subuid
/etc/subgid
/etc/systemd/system/1helm-lxc-net.service
/etc/systemd/system/1helm.service
/etc/systemd/system/1helm-update.service
/etc/systemd/system/1helm-update.path
/opt/1helm/update-host.sh
/opt/1helm/uninstall-host.sh
)
HOST_UNITS=(1helm-lxc-net.service 1helm.service 1helm-update.path)
TRANSACTION_ACTIVE=0
ROLLING_BACK=0
TEMP_ROOT=""
PREVIOUS_RELEASE=""

[[ "${EUID}" -eq 0 ]] || { echo "The Linux release transaction must run as root." >&2; exit 1; }
[[ "$RELEASE_ROOT" == "$RELEASES_ROOT/"* && -d "$RELEASE_ROOT" ]] \
|| { echo "The Linux release transaction requires a verified retained release." >&2; exit 1; }
[[ "$TARGET_VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] \
|| { echo "The Linux release transaction requires an exact version." >&2; exit 1; }
PACKAGE_VERSION="$("$NODE_LINK/bin/node" -p 'require(process.argv[1]).version' "$RELEASE_ROOT/package.json" 2>/dev/null || true)"
[[ "$PACKAGE_VERSION" == "$TARGET_VERSION" ]] \
|| { echo "The retained release does not match the requested version." >&2; exit 1; }
[[ -x "$RELEASE_ROOT/site/public/install-lxc-runtime.sh" \
&& -x "$RELEASE_ROOT/site/public/install-linux-units.sh" \
&& -x "$RELEASE_ROOT/site/public/update-host.sh" \
&& -x "$RELEASE_ROOT/site/public/uninstall-host.sh" \
&& -x "$RELEASE_ROOT/scripts/1helm-lxc-runtime" \
&& -x "$RELEASE_ROOT/scripts/1helm-lxc-net" ]] \
|| { echo "The verified release is missing its Linux host contract." >&2; exit 1; }

TEMP_ROOT="$(mktemp -d)"
chmod 0700 "$TEMP_ROOT"

json_string() {
"$NODE_LINK/bin/node" -e 'process.stdout.write(JSON.stringify(process.argv[1] || ""))' "$1"
}

write_status() {
local state="$1" message="$2" error="${3:-}" candidate="$TEMP_ROOT/status.json"
printf '{"mode":"linux-systemd","status":%s,"version":%s,"checked_at":%s,"message":%s,"error":%s}\n' \
"$(json_string "$state")" "$(json_string "$TARGET_VERSION")" "$(( $(date +%s) * 1000 ))" \
"$(json_string "$message")" "$([[ -n "$error" ]] && json_string "$error" || printf null)" >"$candidate"
chown "$SERVICE_USER:$SERVICE_USER" "$candidate"
chmod 0600 "$candidate"
mv -f -- "$candidate" "$STATUS_FILE"
}

snapshot_host_contract() {
install -d -m 0700 "$TEMP_ROOT/files" "$TEMP_ROOT/units"
local path encoded unit
for path in "${HOST_CONTRACT_PATHS[@]}"; do
if [[ -e "$path" || -L "$path" ]]; then
encoded="${path#/}"
install -d -m 0700 "$TEMP_ROOT/files/$(dirname "$encoded")"
cp -a -- "$path" "$TEMP_ROOT/files/$encoded"
fi
done
for unit in "${HOST_UNITS[@]}"; do
systemctl is-enabled "$unit" >"$TEMP_ROOT/units/$unit.enabled" 2>/dev/null || true
systemctl is-active "$unit" >"$TEMP_ROOT/units/$unit.active" 2>/dev/null || true
done
}

rollback_host_contract() {
local path encoded unit enabled active restored_healthy=1
ROLLING_BACK=1
systemctl disable --now 1helm-update.path 1helm-lxc-net.service >/dev/null 2>&1 || true
systemctl stop "$SERVICE_NAME" >/dev/null 2>&1 || true
for path in "${HOST_CONTRACT_PATHS[@]}"; do
encoded="${path#/}"
rm -f -- "$path"
if [[ -e "$TEMP_ROOT/files/$encoded" || -L "$TEMP_ROOT/files/$encoded" ]]; then
install -d -m 0755 "$(dirname "$path")"
cp -a -- "$TEMP_ROOT/files/$encoded" "$path"
fi
done
if [[ -n "$PREVIOUS_RELEASE" && -d "$PREVIOUS_RELEASE" ]]; then
ln -s "$PREVIOUS_RELEASE" "$TEMP_ROOT/rollback-current"
mv -Tf "$TEMP_ROOT/rollback-current" "$APP_ROOT"
fi
systemctl daemon-reload
for unit in "${HOST_UNITS[@]}"; do
enabled="$(cat "$TEMP_ROOT/units/$unit.enabled" 2>/dev/null || true)"
active="$(cat "$TEMP_ROOT/units/$unit.active" 2>/dev/null || true)"
[[ "$enabled" == "enabled" ]] && systemctl enable "$unit" >/dev/null 2>&1 || true
[[ "$active" == "active" ]] && systemctl start "$unit" >/dev/null 2>&1 || true
done
if [[ "$(cat "$TEMP_ROOT/units/$SERVICE_NAME.active" 2>/dev/null || true)" == "active" ]]; then
restored_healthy=0
for _ in {1..300}; do
if curl -fsS "http://127.0.0.1:$PORT/api/setup/status" >/dev/null; then restored_healthy=1; break; fi
sleep 0.2
done
fi
TRANSACTION_ACTIVE=0
ROLLING_BACK=0
[[ "$restored_healthy" -eq 1 ]]
}

cleanup_transaction() {
local command_status=$?
trap - EXIT
if [[ "$TRANSACTION_ACTIVE" -eq 1 && "$ROLLING_BACK" -eq 0 ]]; then
if rollback_host_contract; then
write_status "error" "1Helm v$TARGET_VERSION failed its host health transaction; the prior healthy release was restored." "Host update failed and was rolled back." || true
else
write_status "error" "1Helm v$TARGET_VERSION failed and the prior host could not be proven healthy after rollback." "Host update and rollback health check failed." || true
fi
fi
[[ -z "$TEMP_ROOT" ]] || rm -rf -- "$TEMP_ROOT"
exit "$command_status"
}
trap cleanup_transaction EXIT

PREVIOUS_RELEASE="$(readlink -f "$APP_ROOT" 2>/dev/null || true)"
[[ "$PREVIOUS_RELEASE" == "$RELEASES_ROOT/"* && -d "$PREVIOUS_RELEASE" ]] \
|| { echo "The currently installed 1Helm release is not inside the verified release store." >&2; exit 1; }
snapshot_host_contract
TRANSACTION_ACTIVE=1
write_status "installing" "The host verified v$TARGET_VERSION and is applying one atomic runtime and application transaction."
HELM_HOST_APPLY_DELEGATED=1 "$RELEASE_ROOT/site/public/install-lxc-runtime.sh" "$RELEASE_ROOT"
ln -s "$RELEASE_ROOT" "$TEMP_ROOT/current"
mv -Tf "$TEMP_ROOT/current" "$APP_ROOT"
HELM_HOST_APPLY_DELEGATED=1 "$RELEASE_ROOT/site/public/install-linux-units.sh" "$RELEASE_ROOT"
write_status "restarting" "The host installed v$TARGET_VERSION and is restarting 1Helm."
systemctl restart "$SERVICE_NAME"
healthy=0
for _ in {1..300}; do
if curl -fsS "http://127.0.0.1:$PORT/api/setup/status" >/dev/null; then healthy=1; break; fi
sleep 0.2
done
[[ "$healthy" -eq 1 ]] || { echo "1Helm v$TARGET_VERSION failed its host health check." >&2; exit 1; }
TRANSACTION_ACTIVE=0
write_status "current" "This 1Helm host is running v$TARGET_VERSION."
22 changes: 20 additions & 2 deletions site/public/install-linux-units.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,24 @@ NODE_LINK="$INSTALL_ROOT/node-current"
STATE_ROOT="/var/lib/1helm"
SERVICE_USER="1helm"

# Bridge upgrades from v0.0.11's too-narrow ProtectSystem=strict namespace.
# The retained release has already been SHA-verified and built by the root
# updater; only its fixed unit installer can be delegated.
if [[ "${HELM_HOST_APPLY_DELEGATED:-}" != "1" ]] \
&& awk -F: '$1 == "0" && $3 ~ /(^|\/)1helm-update\.service(\/|$)/ { found=1 } END { exit found ? 0 : 1 }' /proc/self/cgroup; then
RESOLVED_RELEASE="$(readlink -f "$RELEASE_ROOT" 2>/dev/null || true)"
[[ "$RESOLVED_RELEASE" == /opt/1helm/releases/* && -d "$RESOLVED_RELEASE" ]] \
|| { echo "The updater can delegate only a verified retained 1Helm release." >&2; exit 1; }
DELEGATE_UNIT="1helm-linux-units-apply-${RANDOM}-$$"
exec systemd-run --quiet --collect --wait --pipe --unit="$DELEGATE_UNIT" \
--property=Type=oneshot --property=NoNewPrivileges=false --property=PrivateTmp=true --property=ProtectHome=true \
--setenv=HELM_HOST_APPLY_DELEGATED=1 \
"$RESOLVED_RELEASE/site/public/install-linux-units.sh" "$RESOLVED_RELEASE"
fi

[[ "${EUID}" -eq 0 ]] || { echo "The Linux service installer must run as root." >&2; exit 1; }
[[ -n "$RELEASE_ROOT" && -d "$RELEASE_ROOT" ]] || { echo "A verified 1Helm release directory is required." >&2; exit 1; }
[[ -x "$RELEASE_ROOT/site/public/update-host.sh" && -x "$RELEASE_ROOT/site/public/migrate-linux-host-contract.sh" && -x "$RELEASE_ROOT/site/public/uninstall-host.sh" ]] \
[[ -x "$RELEASE_ROOT/site/public/update-host.sh" && -x "$RELEASE_ROOT/site/public/apply-linux-release.sh" && -x "$RELEASE_ROOT/site/public/migrate-linux-host-contract.sh" && -x "$RELEASE_ROOT/site/public/uninstall-host.sh" ]] \
|| { echo "The verified 1Helm release is missing its host lifecycle scripts." >&2; exit 1; }
id "$SERVICE_USER" >/dev/null 2>&1 || { echo "The 1Helm service account does not exist." >&2; exit 1; }

Expand Down Expand Up @@ -67,7 +82,10 @@ NoNewPrivileges=false
PrivateTmp=true
ProtectHome=true
ProtectSystem=strict
ReadWritePaths=$INSTALL_ROOT $STATE_ROOT /var/lib/1helm-lxc /var/cache/1helm-lxc /run/lxc /usr/libexec/1helm-lxc-runtime /usr/libexec/1helm-lxc-net /etc/1helm /etc/default/lxc-net /etc/systemd/system/1helm-lxc-net.service /etc/systemd/system/1helm.service /etc/systemd/system/1helm-update.service /etc/systemd/system/1helm-update.path /etc/sudoers.d/1helm-lxc-runtime /etc/subuid /etc/subgid
# Runtime and unit files are installed by atomic rename and removed during a
# failed-update rollback, so their exact parent directories—not merely the old
# files—must be writable inside this root-owned transaction.
ReadWritePaths=$INSTALL_ROOT $STATE_ROOT /var/lib/1helm-lxc /var/cache/1helm-lxc /run/lxc /usr/libexec /etc/1helm /etc/default /etc/systemd/system /etc/sudoers.d /etc/subuid /etc/subgid
EOF

install -m 0644 /dev/stdin /etc/systemd/system/1helm-update.path <<EOF
Expand Down
55 changes: 55 additions & 0 deletions site/public/install-lxc-runtime.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ set -euo pipefail
APP_SOURCE="${1:-}"
INSTALL_ROOT="/opt/1helm"
RUNTIME_ROOT="$INSTALL_ROOT/runtime/lxc"
LXC_ROOT="/var/lib/1helm-lxc"
LXC_PATH="$LXC_ROOT/containers"
CACHE_BASE="/var/cache/1helm-lxc"
HELPER_PATH="/usr/libexec/1helm-lxc-runtime"
NETWORK_HELPER_PATH="/usr/libexec/1helm-lxc-net"
CONFIG_PATH="/etc/1helm/lxc-unprivileged.conf"
Expand All @@ -17,6 +20,52 @@ SUDOERS_PATH="/etc/sudoers.d/1helm-lxc-runtime"
SERVICE_USER="1helm"
IMAGE_BUILD="20260723_07:42"

# v0.0.11's updater unit made the exact destination files writable under
# ProtectSystem=strict. Atomic replacement still requires write access to each
# parent directory, so an upgrade from that unit must hand the complete,
# digest-qualified release transaction to a short-lived root unit outside the
# old mount namespace. Fresh installs and newer updater units run directly.
if [[ "${HELM_HOST_APPLY_DELEGATED:-}" != "1" ]] \
&& awk -F: '$1 == "0" && $3 ~ /(^|\/)1helm-update\.service(\/|$)/ { found=1 } END { exit found ? 0 : 1 }' /proc/self/cgroup; then
RELEASE_ROOT="$(readlink -f "$APP_SOURCE" 2>/dev/null || true)"
[[ "$RELEASE_ROOT" == /opt/1helm/releases/* && -d "$RELEASE_ROOT" ]] \
|| { echo "The updater can delegate only a verified retained 1Helm release." >&2; exit 1; }
[[ -x "$RELEASE_ROOT/site/public/apply-linux-release.sh" ]] \
|| { echo "The retained release is missing its atomic Linux transaction." >&2; exit 1; }
TARGET_VERSION="$(/opt/1helm/node-current/bin/node -p 'require(process.argv[1]).version' "$RELEASE_ROOT/package.json" 2>/dev/null || true)"
[[ "$TARGET_VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] \
|| { echo "The retained release has no valid package version." >&2; exit 1; }
LEGACY_UPDATER_PID="$(systemctl show --property=MainPID --value 1helm-update.service 2>/dev/null || true)"
legacy_updater_pid_is_exact() {
local pid="${1:-}" main_pid command_line
[[ "$pid" =~ ^[0-9]+$ ]] && ((pid > 1)) && [[ -r "/proc/$pid/cgroup" && -r "/proc/$pid/cmdline" ]] || return 1
main_pid="$(systemctl show --property=MainPID --value 1helm-update.service 2>/dev/null || true)"
[[ "$main_pid" == "$pid" ]] || return 1
awk -F: '$1 == "0" && $3 ~ /(^|\/)1helm-update\.service(\/|$)/ { found=1 } END { exit found ? 0 : 1 }' "/proc/$pid/cgroup" || return 1
command_line="$(tr '\0' '\n' <"/proc/$pid/cmdline")"
grep -Fxq '/opt/1helm/update-host.sh' <<<"$command_line"
}
legacy_updater_pid_is_exact "$LEGACY_UPDATER_PID" \
|| { echo "The legacy updater handoff could not validate its exact systemd main process." >&2; exit 1; }
DELEGATE_UNIT="1helm-release-apply-${TARGET_VERSION//./-}-${RANDOM}-$$"
if systemd-run --quiet --collect --wait --pipe --unit="$DELEGATE_UNIT" \
--property=Type=oneshot --property=NoNewPrivileges=false --property=PrivateTmp=true --property=ProtectHome=true \
"$RELEASE_ROOT/site/public/apply-linux-release.sh" "$RELEASE_ROOT" "$TARGET_VERSION"; then
exit 0
fi
# The delegated transaction has already restored the exact prior release,
# reloaded its units, proved its HTTP health, and written the visible error.
# Stop only the still-identical legacy updater main process with SIGKILL so
# its EXIT trap cannot attempt a second rollback from the obsolete namespace
# or overwrite that stronger evidence.
if legacy_updater_pid_is_exact "$LEGACY_UPDATER_PID"; then
kill -KILL "$LEGACY_UPDATER_PID"
else
echo "The failed release was rolled back, but the legacy updater process identity changed before it could be stopped." >&2
fi
exit 1
fi

case "$(uname -m)" in
x86_64|amd64)
IMAGE_ARCH="amd64"
Expand Down Expand Up @@ -50,6 +99,12 @@ for command in curl sha256sum lxc-create lxc-attach lxc-info lxc-start lxc-stop
done
python3 -c 'import ensurepip' >/dev/null 2>&1 || { echo "Python venv support is unavailable after host setup." >&2; exit 1; }

# The service unit names these exact writable roots. They must exist before
# systemd creates the service's mount namespace, even before the first channel
# computer is provisioned.
install -d -o root -g root -m 0711 "$LXC_ROOT" "$LXC_PATH"
install -d -o root -g root -m 0700 "$CACHE_BASE"

TEMP_ROOT="$(mktemp -d)"
trap 'rm -rf -- "$TEMP_ROOT"' EXIT
ASSET_URL="https://images.linuxcontainers.org/images/ubuntu/noble/$IMAGE_ARCH/default/$IMAGE_BUILD"
Expand Down
35 changes: 12 additions & 23 deletions site/public/update-host.sh
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ PACKAGE_VERSION="$("$NODE_LINK/bin/node" -p 'require(process.argv[1]).version' "
|| fail "The verified Linux artifact version does not match its release tag."
[[ -x "$STAGE/site/public/update-host.sh" ]] \
|| fail "The verified Linux artifact is missing its host updater."
[[ -x "$STAGE/site/public/migrate-linux-host-contract.sh" && -x "$STAGE/site/public/install-lxc-runtime.sh" && -x "$STAGE/site/public/install-linux-units.sh" && -x "$STAGE/site/public/uninstall-host.sh" && -x "$STAGE/scripts/1helm-lxc-runtime" && -x "$STAGE/scripts/1helm-lxc-net" ]] \
[[ -x "$STAGE/site/public/apply-linux-release.sh" && -x "$STAGE/site/public/migrate-linux-host-contract.sh" && -x "$STAGE/site/public/install-lxc-runtime.sh" && -x "$STAGE/site/public/install-linux-units.sh" && -x "$STAGE/site/public/uninstall-host.sh" && -x "$STAGE/scripts/1helm-lxc-runtime" && -x "$STAGE/scripts/1helm-lxc-net" ]] \
|| fail "The verified Linux artifact is missing its isolated LXC runtime contract."
chown -R "$SERVICE_USER:$SERVICE_USER" "$STAGE"

Expand All @@ -247,26 +247,15 @@ else
fi
chown -R "$SERVICE_USER:$SERVICE_USER" "$RELEASE_ROOT"

PREVIOUS_RELEASE="$(readlink -f "$APP_ROOT" 2>/dev/null || true)"
[[ "$PREVIOUS_RELEASE" == "$RELEASES_ROOT/"* && -d "$PREVIOUS_RELEASE" ]] || PREVIOUS_RELEASE=""
snapshot_host_contract
TRANSACTION_ACTIVE=1
"$RELEASE_ROOT/site/public/install-lxc-runtime.sh" "$RELEASE_ROOT" \
|| fail "The verified 1Helm release could not install its isolated LXC runtime."
ln -s "$RELEASE_ROOT" "$TEMP_ROOT/current"
mv -Tf "$TEMP_ROOT/current" "$APP_ROOT"
"$RELEASE_ROOT/site/public/install-linux-units.sh" "$RELEASE_ROOT" \
|| fail "The verified 1Helm release could not migrate its Linux service contract."

write_status "restarting" "$TARGET_VERSION" "The host installed v$TARGET_VERSION and is restarting 1Helm."
systemctl restart "$SERVICE_NAME"
healthy=0
for _ in {1..300}; do
if curl -fsS "http://127.0.0.1:$PORT/api/setup/status" >/dev/null; then healthy=1; break; fi
sleep 0.2
done
if [[ "$healthy" -ne 1 ]]; then
fail "1Helm v$TARGET_VERSION failed its host health check; the previous release was restored when available."
# One verified transient root transaction owns the runtime files, current
# symlink, unit migration, restart, health check, and rollback together. This
# also escapes v0.0.11's obsolete ProtectSystem=strict mount namespace before
# the first host file is replaced.
APPLY_UNIT="1helm-release-apply-${TARGET_VERSION//./-}-$$"
if ! systemd-run --quiet --collect --wait --pipe --unit="$APPLY_UNIT" \
--property=Type=oneshot --property=NoNewPrivileges=false --property=PrivateTmp=true --property=ProtectHome=true \
"$RELEASE_ROOT/site/public/apply-linux-release.sh" "$RELEASE_ROOT" "$TARGET_VERSION"; then
echo "1Helm v$TARGET_VERSION failed its atomic host transaction; the transaction's visible status records whether rollback was proven healthy." >&2
exit 1
fi
TRANSACTION_ACTIVE=0
write_status "current" "$TARGET_VERSION" "This 1Helm host is running v$TARGET_VERSION."
exit 0
Loading
Loading