@@ -527,16 +527,14 @@ patch_dappmanager_compose_for_macos() {
527527}
528528
529529bootstrap_filesystem () {
530- # Clean if update
530+ # Clean if update — only the logfile and profile are removed here.
531+ # Removing the profile early forces ensure_profile_loaded to re-download
532+ # the latest one (so resolved package versions match the new release).
533+ # Composes/manifests/archives are removed later by clean_for_update,
534+ # AFTER preflight passes — see comment in main().
531535 if [[ " ${UPDATE} " == " true" ]]; then
532- log " Cleaning for update..."
533536 rm -f " ${LOGFILE} " || true
534- rm -f " ${DAPPNODE_CORE_DIR} " /docker-compose-* .yml || true
535- rm -f " ${DAPPNODE_CORE_DIR} " /dappnode_package-* .json || true
536- rm -f " ${DAPPNODE_CORE_DIR} " /* .tar.xz || true
537- rm -f " ${DAPPNODE_CORE_DIR} " /* .txz || true
538537 rm -f " ${DAPPNODE_CORE_DIR} /.dappnode_profile" || true
539- rm -f " ${CONTENT_HASH_FILE} " || true
540538 fi
541539
542540 # Create necessary directories
@@ -551,6 +549,22 @@ bootstrap_filesystem() {
551549 touch " ${LOGFILE} " || true
552550}
553551
552+ # Destructive: remove on-disk artifacts from the previous install so fresh
553+ # downloads take their place. Must only run AFTER preflight checks have passed —
554+ # otherwise a failing preflight (e.g. port conflict) leaves the host with no
555+ # compose files on disk while running containers continue to hold the ports.
556+ clean_for_update () {
557+ if [[ " ${UPDATE} " != " true" ]]; then
558+ return 0
559+ fi
560+ log " Cleaning for update..."
561+ rm -f " ${DAPPNODE_CORE_DIR} " /docker-compose-* .yml || true
562+ rm -f " ${DAPPNODE_CORE_DIR} " /dappnode_package-* .json || true
563+ rm -f " ${DAPPNODE_CORE_DIR} " /* .tar.xz || true
564+ rm -f " ${DAPPNODE_CORE_DIR} " /* .txz || true
565+ rm -f " ${CONTENT_HASH_FILE} " || true
566+ }
567+
554568# Generic helper: returns 0 if a process is bound to the given port, 1 if not.
555569# Usage: is_port_listening <port> [tcp|udp]
556570# tcp (default): matches TCP sockets in LISTEN state
@@ -591,6 +605,8 @@ check_https_ports_conflict() {
591605
592606# Check that ports required by VPN/Wireguard are not already in use by another process.
593607# Must be called after PKGS is populated. Exits with a helpful error on conflict.
608+ # Ports held by our own dappnode core VPN/Wireguard containers are not conflicts —
609+ # the upcoming compose-up will replace them.
594610check_vpn_ports_conflict () {
595611 if ! command -v lsof > /dev/null 2>&1 ; then
596612 return # cannot check; proceed and let the container report a bind error
@@ -601,23 +617,33 @@ check_vpn_ports_conflict() {
601617 case " $pkg " in
602618 WIREGUARD)
603619 if is_port_listening 51820 udp; then
604- error " Port 51820/UDP is already in use on this host."
605- error " This port is required by the Wireguard package and must be free before installing."
606- error " Free up port 51820 and re-run the installer, or — if you do not need VPN"
607- error " connectivity — consider using --minimal instead (advanced users only)."
608- exit 1
620+ # Port 51820 is in use; check if it's our own Wireguard container
621+ if docker ps --format ' {{.Names}}' 2> /dev/null | grep -qE " ^DAppNodeCore-.*wireguard.*\.dnp\.dappnode\.eth$" ; then
622+ log " Port 51820/UDP is held by the existing DAppNode Wireguard container; it will be replaced."
623+ else
624+ error " Port 51820/UDP is already in use on this host."
625+ error " This port is required by the Wireguard package and must be free before installing."
626+ error " Free up port 51820 and re-run the installer, or — if you do not need VPN"
627+ error " connectivity — consider using --minimal instead (advanced users only)."
628+ exit 1
629+ fi
609630 fi
610631 ;;
611632 VPN)
612633 local vpn_blocked=()
613634 is_port_listening 1194 udp && vpn_blocked+=(1194/UDP)
614635 is_port_listening 8092 tcp && vpn_blocked+=(8092/TCP)
615636 if [[ ${# vpn_blocked[@]} -gt 0 ]]; then
616- error " Port(s) ${vpn_blocked[*]} are already in use on this host."
617- error " These ports are required by the OpenVPN package and must be free before installing."
618- error " Free up the port(s) and re-run the installer, or — if you do not need VPN"
619- error " connectivity — consider using --minimal instead (advanced users only)."
620- exit 1
637+ # Port(s) in use; check if held by our own OpenVPN container
638+ if docker ps --format ' {{.Names}}' 2> /dev/null | grep -q " ^DAppNodeCore-vpn.dnp.dappnode.eth$" ; then
639+ log " Port(s) ${vpn_blocked[*]} are held by the existing DAppNode VPN container; it will be replaced."
640+ else
641+ error " Port(s) ${vpn_blocked[*]} are already in use on this host."
642+ error " These ports are required by the OpenVPN package and must be free before installing."
643+ error " Free up the port(s) and re-run the installer, or — if you do not need VPN"
644+ error " connectivity — consider using --minimal instead (advanced users only)."
645+ exit 1
646+ fi
621647 fi
622648 ;;
623649 esac
@@ -1107,6 +1133,10 @@ main() {
11071133 configure_static_ip
11081134 ensure_profile_loaded
11091135 resolve_packages
1136+ # Destructive cleanup runs only after preflight (resolve_packages -> check_vpn_ports_conflict)
1137+ # has passed; otherwise a failing port check would wipe the on-disk composes while the
1138+ # running containers still hold the ports, leaving the node un-restartable.
1139+ clean_for_update
11101140
11111141 echo " " 2>&1 | tee -a " $LOGFILE "
11121142 log " ##############################################"
0 commit comments