Compare commits

..

10 Commits

Author SHA1 Message Date
MickLesk 3a9aa287b1 Update portainer.sh 2026-08-06 07:54:05 +02:00
MickLesk a92cba7525 Docker: report container updates instead of prompting, stop auto-updating Portainer Agent, fix addon detection of legacy Portainer 2026-08-06 07:51:01 +02:00
community-scripts-pr-app[bot] d53486c86e Update CHANGELOG.md (#16294)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-08-05 20:36:09 +00:00
community-scripts-pr-app[bot] 4f80c217fc Update CHANGELOG.md (#16293)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-08-05 20:35:38 +00:00
jomplox f4afdfcd0c fix(monitor-all): reduce polling CPU overhead (#15907) 2026-08-05 22:35:03 +02:00
MickLesk 3865f855f0 qf 2026-08-05 17:35:32 +02:00
MickLesk 94da6eeb83 qf 2026-08-05 15:00:34 +02:00
MickLesk 078a76f263 Extract reclaim_tty into reusable function
Move the inline TTY reclamation logic from build.func into a standalone reclaim_tty() function in core.func. This improves code reusability, as the function now needs to be called before each interactive prompt (not just after install) since pct exec/pull/enter can take the terminal away again. The function also includes better error handling with checks for perl availability and /dev/tty existence, and explicitly sets SIGTTOU to IGNORE in perl.
2026-08-05 14:57:15 +02:00
community-scripts-pr-app[bot] 58d819b2f4 Update CHANGELOG.md (#16290)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-08-05 12:04:43 +00:00
CanbiZ (MickLesk) 1c03d0506c NextcloudPI: Bump to Debian Trixie & Tweak broken SSH (#15957)
* Pin NextCloudPi installer to last known-good stable release

The floating "master" branch of nextcloud/nextcloudpi's install.sh
started rejecting our default Debian 12 base with "distro not
supported" (#15944) after a regression landed upstream; the script
is third-party code we don't audit or control. Pin to v1.57.1, the
latest stable (non-prerelease) release, which explicitly targets
Debian bookworm and predates the regression.

* Actually pin the branch nextcloudpi's install.sh clones internally

install.sh is only a thin bootstrapper: it clones BRANCH (default
"master") of the nextcloudpi repo itself and runs the real installer
from that fresh checkout, including the distro-support check. Fetching
install.sh from a pinned tag alone left BRANCH defaulting to "master",
so the internally-cloned code was unaffected and still failed with
"distro not supported" - confirmed by testing the previous fix. Pass
BRANCH explicitly so the internal clone also targets the pinned tag.

* Bump NextCloudPi to Debian 13, matching upstream's trixie move

Upstream's master ncp.cfg now targets release "trixie" (Debian 13);
bookworm (Debian 12) is no longer in the supported check_distro list
at all. Move our own default to Debian 13 and pin the installer ref
to v1.58.0-rc1, the only tagged ref with release=trixie so far (no
stable trixie release exists yet upstream).

* Revert installer pin, track master again

master now targets trixie itself (matches the Debian 13 bump), and
the only tagged trixie ref was an RC explicitly marked "expect bugs".
Tracking master gets upstream trixie fixes as they land instead of
being stuck on a stale test release.

* Work around nextcloudpi's broken ssh.socket restart on Debian 13

Debian 13's openssh-server ships socket-activated by default. NCP's
own bin/ncp/NETWORKING/SSH.sh detects that (systemctl is-active
ssh.socket) but then runs "systemctl restart ssh" in that branch
instead of reloading, which collides with the port ssh.socket already
holds and fails with "Job for ssh.service failed" (#15944). Switch the
container to classic ssh.service before handing off to their
installer so it takes the safe "systemctl reload ssh" branch instead.
2026-08-05 22:04:16 +10:00
10 changed files with 107 additions and 72 deletions
+14
View File
@@ -518,6 +518,20 @@ Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit
</details>
## 2026-08-05
### 🚀 Updated Scripts
- #### ✨ New Features
- NextcloudPI: Bump to Debian Trixie & Tweak broken SSH [@MickLesk](https://github.com/MickLesk) ([#15957](https://github.com/community-scripts/ProxmoxVE/pull/15957))
### 🧰 Tools
- #### 🐞 Bug Fixes
- fix(monitor-all): reduce polling CPU overhead [@jomplox](https://github.com/jomplox) ([#15907](https://github.com/community-scripts/ProxmoxVE/pull/15907))
## 2026-08-04
### 🆕 New Scripts
-14
View File
@@ -42,20 +42,6 @@ function update_script() {
echo -e "${TAB}${TAB}${GN}bash -c \"\$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/addon/portainer.sh)\"${CL}"
fi
if docker ps -a --format '{{.Names}}' | grep -q '^portainer_agent$'; then
msg_info "Updating Portainer Agent"
$STD docker pull portainer/agent:latest
$STD docker stop portainer_agent
$STD docker rm portainer_agent
$STD docker run -d \
-p 9001:9001 \
--name=portainer_agent \
--restart=always \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /var/lib/docker/volumes:/var/lib/docker/volumes \
portainer/agent
msg_ok "Updated Portainer Agent"
fi
msg_ok "Updated successfully!"
exit
}
+1 -1
View File
@@ -11,7 +11,7 @@ var_cpu="${var_cpu:-2}"
var_ram="${var_ram:-2048}"
var_disk="${var_disk:-8}"
var_os="${var_os:-debian}"
var_version="${var_version:-12}"
var_version="${var_version:-13}"
var_arm64="${var_arm64:-yes}"
var_unprivileged="${var_unprivileged:-1}"
+10
View File
@@ -24,6 +24,16 @@ if [[ ! "$CONFIRM" =~ ^([yY][eE][sS]|[yY])$ ]]; then
exit 10
fi
msg_info "Making ssh.service reloads behave like restarts"
mkdir -p /etc/systemd/system/ssh.service.d
cat <<'EOF' >/etc/systemd/system/ssh.service.d/reload-as-restart.conf
[Service]
ExecReload=
ExecReload=/usr/bin/systemd-run --no-block --quiet /bin/systemctl restart ssh.service
EOF
systemctl daemon-reload
msg_ok "Made ssh.service reloads behave like restarts"
msg_info "Installing NextCloudPi (Patience)"
$STD bash <(curl -fsSL https://raw.githubusercontent.com/nextcloud/nextcloudpi/master/install.sh)
msg_ok "Installed NextCloudPi"
+8 -9
View File
@@ -5200,15 +5200,11 @@ EOF
# TSTP = Ctrl+Z, TTIN = bg read from tty, TTOU = bg write to tty (tostop)
trap '' TSTP TTIN TTOU
# lxc-attach takes the controlling terminal while the install runs and does
# not hand it back, leaving us in a background process group. Reading from
# the terminal then returns EIO instead of blocking, because SIGTTIN is
# ignored above - so every recovery prompt fails before the user can answer.
# Redirecting to /dev/tty does not help: the rule applies to the terminal,
# not the file descriptor. Claim the foreground group back; SIGTTOU is
# ignored too, so tcsetpgrp() succeeds instead of stopping us. No-op when we
# already are in the foreground. perl is a hard dependency of Proxmox VE.
perl -e 'use POSIX; open(my $t, "+<", "/dev/tty") or exit 1; POSIX::tcsetpgrp(fileno($t), getpgrp()) or exit 1;' 2>/dev/null || true
# lxc-attach left us in a background process group - claim the terminal back
# before we print anything. Note this does NOT hold: the log collection
# below uses pct pull/exec, which take it away again, so every interactive
# prompt has to reclaim it again right before its read.
reclaim_tty
msg_error "Installation failed in container ${CTID} (exit code: ${install_exit_code})"
@@ -5338,6 +5334,7 @@ EOF
pct enter "$CTID"
echo ""
echo -en "${YW}Container ${CTID} still running. Remove now? (y/N): ${CL}"
reclaim_tty
if read -r response </dev/tty && [[ "$response" =~ ^[Yy]$ ]]; then
pct stop "$CTID" &>/dev/null || true
pct destroy "$CTID" &>/dev/null || true
@@ -5497,6 +5494,7 @@ EOF
local response=""
local read_rc
reclaim_tty
read -t 60 -r response </dev/tty
read_rc=$?
if [[ $read_rc -eq 0 ]]; then
@@ -5761,6 +5759,7 @@ destroy_lxc() {
trap 'echo; msg_error "Aborted by user (SIGINT/SIGQUIT)"; return 130' INT QUIT
local prompt
reclaim_tty
if ! read -rp "Remove this Container? <y/N> " prompt </dev/tty; then
# read returns non-zero on Ctrl-D/ESC
msg_error "Aborted input (Ctrl-D/ESC)"
+33
View File
@@ -1042,6 +1042,39 @@ ensure_tput() {
fi
}
# ------------------------------------------------------------------------------
# reclaim_tty()
#
# - Reclaims the controlling terminal's foreground process group
# - lxc-attach takes the terminal and does not hand it back, leaving us in a
# background process group. Reading from the terminal then returns EIO
# instead of blocking, because SIGTTIN is ignored during recovery - so the
# prompt fails before the user can answer and their keystroke leaks into the
# parent shell. Redirecting to /dev/tty does not help: the rule applies to
# the terminal, not to the file descriptor.
# - pct exec/pull/enter use lxc-attach internally, so the terminal can be taken
# away again at any point. Call this immediately before each interactive
# read, not once after the install.
# - SIGTTOU is ignored inside perl so tcsetpgrp() succeeds instead of stopping
# us. No-op when we already are in the foreground or there is no terminal.
# perl is a hard dependency of Proxmox VE.
# ------------------------------------------------------------------------------
reclaim_tty() {
command -v perl >/dev/null 2>&1 || return 0
[[ -e /dev/tty ]] || return 0
local pgid
pgid=$(ps -o pgid= -p $$ 2>/dev/null | tr -d ' ') || true
perl -e '
use POSIX;
$SIG{TTOU} = "IGNORE";
my $pgid = $ARGV[0] || POSIX::getpgrp();
open(my $t, "+<", "/dev/tty") or exit 1;
POSIX::tcsetpgrp(fileno($t), $pgid) or exit 1;
' "${pgid:-0}" 2>/dev/null || true
}
# ------------------------------------------------------------------------------
# is_alpine()
#
+1
View File
@@ -499,6 +499,7 @@ error_handler() {
local response=""
local read_rc
declare -f reclaim_tty >/dev/null 2>&1 && reclaim_tty
read -t 60 -r response </dev/tty
read_rc=$?
if [[ $read_rc -eq 0 ]]; then
+5 -32
View File
@@ -4801,8 +4801,8 @@ EOF
# Container Update Check
# - Skipped entirely when running unattended / non-interactive
# - Compose-managed containers: offered via Y/N → docker compose pull + up -d
# - Standalone containers: offered via Y/N → image pull only (no stop/rm)
# - Lists containers with a newer image available and the command to update
# them; does not pull/recreate anything itself
if [ "$docker_installed" = true ] && ! _docker_is_noninteractive; then
msg_info "Checking for container updates"
@@ -4840,41 +4840,14 @@ EOF
if [[ ${#compose_updates[@]} -eq 0 && ${#standalone_updates[@]} -eq 0 ]]; then
msg_ok "All containers are up-to-date"
else
local reply
msg_warn "Updates available (not applied automatically):"
for entry in "${compose_updates[@]}"; do
IFS='|' read -r name image compose_workdir compose_service <<<"$entry"
reply=""
if read -r -t 60 -p "${TAB3}Update ${name} (${image}) via Compose? <y/N> (auto-no in 60s): " reply </dev/tty; then
echo ""
else
echo ""
fi
if [[ "${reply,,}" =~ ^(y|yes)$ ]]; then
msg_info "Updating $name"
if (cd "$compose_workdir" && $STD docker compose pull "$compose_service" && $STD docker compose up -d "$compose_service"); then
msg_ok "Updated $name"
else
msg_warn "Could not update $name — try manually in $compose_workdir"
fi
fi
echo -e "${TAB3}${name} (${image}) — update via: cd ${compose_workdir} && docker compose pull ${compose_service} && docker compose up -d ${compose_service}"
done
for entry in "${standalone_updates[@]}"; do
IFS='|' read -r name image <<<"$entry"
reply=""
if read -r -t 60 -p "${TAB3}Pull new image for ${name} (${image})? <y/N> (auto-no in 60s): " reply </dev/tty; then
echo ""
else
echo ""
fi
if [[ "${reply,,}" =~ ^(y|yes)$ ]]; then
msg_info "Pulling new image for $name"
if $STD docker pull "$image"; then
msg_ok "New image available for $name — recreate the container to apply the update"
else
msg_warn "Failed to pull image for $name"
fi
fi
echo -e "${TAB3}${name} (${image}) — update via: docker pull ${image} && docker restart ${name}"
done
fi
fi
+22 -9
View File
@@ -49,6 +49,22 @@ function uninstall() {
msg_ok "${APP} has been uninstalled"
}
# ==============================================================================
# UPDATE SCRIPT HELPER
# ==============================================================================
function ensure_update_script() {
[[ -f /usr/local/bin/update_portainer ]] && return 0
msg_info "Creating update script"
cat <<'UPDATEEOF' >/usr/local/bin/update_portainer
#!/usr/bin/env bash
# Portainer Update Script
type=update bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/addon/portainer.sh)"
UPDATEEOF
chmod +x /usr/local/bin/update_portainer
msg_ok "Created update script (/usr/local/bin/update_portainer)"
}
# ==============================================================================
# UPDATE
# ==============================================================================
@@ -62,6 +78,8 @@ function update() {
$STD docker compose up -d --remove-orphans
msg_ok "Restarted ${APP}"
ensure_update_script
msg_ok "Updated successfully"
exit
}
@@ -115,15 +133,7 @@ function install() {
$STD docker compose up -d
msg_ok "Started ${APP}"
# Create update script
msg_info "Creating update script"
cat <<'UPDATEEOF' >/usr/local/bin/update_portainer
#!/usr/bin/env bash
# Portainer Update Script
type=update bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/addon/portainer.sh)"
UPDATEEOF
chmod +x /usr/local/bin/update_portainer
msg_ok "Created update script (/usr/local/bin/update_portainer)"
ensure_update_script
echo ""
msg_ok "${APP} is reachable at: ${BL}https://${LOCAL_IP}:${DEFAULT_PORT}${CL}"
@@ -150,6 +160,9 @@ fi
header_info
get_lxc_ip
check_docker
check_existing_container
# Check if already installed
if [[ -f "$COMPOSE_FILE" ]]; then
msg_warn "${APP} is already installed."
+13 -7
View File
@@ -54,18 +54,24 @@ while true; do
continue
fi
# Determine type and set config command
if pct status $instance >/dev/null 2>&1; then
# Determine type and read the current config directly from Proxmox's pmxcfs.
# Ignore snapshot sections, matching the current config shown by pct/qm config.
if [ -r "/etc/pve/lxc/$instance.conf" ]; then
type="ct"
config_cmd="pct config"
config_file="/etc/pve/lxc/$instance.conf"
else
type="vm"
config_cmd="qm config"
config_file="/etc/pve/qemu-server/$instance.conf"
fi
config=$(sed '/^\[/,$d' "$config_file")
# Skip templates and onboot-disabled
onboot=$($config_cmd $instance | grep -q "onboot: 0" || ( ! $config_cmd $instance | grep -q "onboot" ) && echo "true" || echo "false")
template=$($config_cmd $instance | grep -q "^template:" && echo "true" || echo "false")
if grep -q "onboot: 0" <<<"$config" || ! grep -q "onboot" <<<"$config"; then
onboot="true"
else
onboot="false"
fi
template=$(grep -q "^template:" <<<"$config" && echo "true" || echo "false")
if [ "$onboot" == "true" ]; then
echo "Skipping $instance because it is set not to boot"
@@ -76,7 +82,7 @@ while true; do
fi
# Check for mon-restart tag
has_tag=$($config_cmd $instance | grep -q "tags:.*mon-restart" && echo "true" || echo "false")
has_tag=$(grep -q "tags:.*mon-restart" <<<"$config" && echo "true" || echo "false")
if [ "$has_tag" != "true" ]; then
echo "Skipping $instance because it does not have 'mon-restart' tag"
continue