Skip to content
Open
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
64 changes: 47 additions & 17 deletions scripts/dappnode_install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -527,16 +527,14 @@ patch_dappmanager_compose_for_macos() {
}

bootstrap_filesystem() {
# Clean if update
# Clean if update — only the logfile and profile are removed here.
# Removing the profile early forces ensure_profile_loaded to re-download
# the latest one (so resolved package versions match the new release).
# Composes/manifests/archives are removed later by clean_for_update,
# AFTER preflight passes — see comment in main().
if [[ "${UPDATE}" == "true" ]]; then
log "Cleaning for update..."
rm -f "${LOGFILE}" || true
rm -f "${DAPPNODE_CORE_DIR}"/docker-compose-*.yml || true
rm -f "${DAPPNODE_CORE_DIR}"/dappnode_package-*.json || true
rm -f "${DAPPNODE_CORE_DIR}"/*.tar.xz || true
rm -f "${DAPPNODE_CORE_DIR}"/*.txz || true
rm -f "${DAPPNODE_CORE_DIR}/.dappnode_profile" || true
rm -f "${CONTENT_HASH_FILE}" || true
fi

# Create necessary directories
Expand All @@ -551,6 +549,22 @@ bootstrap_filesystem() {
touch "${LOGFILE}" || true
}

# Destructive: remove on-disk artifacts from the previous install so fresh
# downloads take their place. Must only run AFTER preflight checks have passed —
# otherwise a failing preflight (e.g. port conflict) leaves the host with no
# compose files on disk while running containers continue to hold the ports.
clean_for_update() {
if [[ "${UPDATE}" != "true" ]]; then
return 0
fi
log "Cleaning for update..."
rm -f "${DAPPNODE_CORE_DIR}"/docker-compose-*.yml || true
rm -f "${DAPPNODE_CORE_DIR}"/dappnode_package-*.json || true
rm -f "${DAPPNODE_CORE_DIR}"/*.tar.xz || true
rm -f "${DAPPNODE_CORE_DIR}"/*.txz || true
rm -f "${CONTENT_HASH_FILE}" || true
}

# Generic helper: returns 0 if a process is bound to the given port, 1 if not.
# Usage: is_port_listening <port> [tcp|udp]
# tcp (default): matches TCP sockets in LISTEN state
Expand Down Expand Up @@ -591,6 +605,8 @@ check_https_ports_conflict() {

# Check that ports required by VPN/Wireguard are not already in use by another process.
# Must be called after PKGS is populated. Exits with a helpful error on conflict.
# Ports held by our own dappnode core VPN/Wireguard containers are not conflicts —
# the upcoming compose-up will replace them.
check_vpn_ports_conflict() {
if ! command -v lsof >/dev/null 2>&1; then
return # cannot check; proceed and let the container report a bind error
Expand All @@ -601,23 +617,33 @@ check_vpn_ports_conflict() {
case "$pkg" in
WIREGUARD)
if is_port_listening 51820 udp; then
error "Port 51820/UDP is already in use on this host."
error "This port is required by the Wireguard package and must be free before installing."
error "Free up port 51820 and re-run the installer, or — if you do not need VPN"
error "connectivity — consider using --minimal instead (advanced users only)."
exit 1
# Port 51820 is in use; check if it's our own Wireguard container
if docker ps --format '{{.Names}}' 2>/dev/null | grep -qE "^DAppNodeCore-.*wireguard.*\.dnp\.dappnode\.eth$"; then
log "Port 51820/UDP is held by the existing DAppNode Wireguard container; it will be replaced."
else
error "Port 51820/UDP is already in use on this host."
error "This port is required by the Wireguard package and must be free before installing."
error "Free up port 51820 and re-run the installer, or — if you do not need VPN"
error "connectivity — consider using --minimal instead (advanced users only)."
exit 1
fi
fi
;;
VPN)
local vpn_blocked=()
is_port_listening 1194 udp && vpn_blocked+=(1194/UDP)
is_port_listening 8092 tcp && vpn_blocked+=(8092/TCP)
if [[ ${#vpn_blocked[@]} -gt 0 ]]; then
error "Port(s) ${vpn_blocked[*]} are already in use on this host."
error "These ports are required by the OpenVPN package and must be free before installing."
error "Free up the port(s) and re-run the installer, or — if you do not need VPN"
error "connectivity — consider using --minimal instead (advanced users only)."
exit 1
# Port(s) in use; check if held by our own OpenVPN container
if docker ps --format '{{.Names}}' 2>/dev/null | grep -q "^DAppNodeCore-vpn.dnp.dappnode.eth$"; then
log "Port(s) ${vpn_blocked[*]} are held by the existing DAppNode VPN container; it will be replaced."
else
error "Port(s) ${vpn_blocked[*]} are already in use on this host."
error "These ports are required by the OpenVPN package and must be free before installing."
error "Free up the port(s) and re-run the installer, or — if you do not need VPN"
error "connectivity — consider using --minimal instead (advanced users only)."
exit 1
fi
fi
;;
esac
Expand Down Expand Up @@ -1107,6 +1133,10 @@ main() {
configure_static_ip
ensure_profile_loaded
resolve_packages
# Destructive cleanup runs only after preflight (resolve_packages -> check_vpn_ports_conflict)
# has passed; otherwise a failing port check would wipe the on-disk composes while the
# running containers still hold the ports, leaving the node un-restartable.
clean_for_update

echo "" 2>&1 | tee -a "$LOGFILE"
log "##############################################"
Expand Down
Loading