Skip to content

Commit 28f2069

Browse files
committed
feat: add dedicated AMI build script
Replaces fragile 'head -n -12' line-stripping of the prerequisites script with a self-contained build script that: - Installs Docker, wireguard, lsof, iptables - Sets up /etc/rc.local for first-boot DAppNode installation - Skips network connectivity checks (not needed during AMI build) - Handles Ubuntu 24 LTS properly
1 parent 14f6ec4 commit 28f2069

1 file changed

Lines changed: 139 additions & 0 deletions

File tree

scripts/dappnode_ami_build.sh

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
#!/bin/bash
2+
# DAppNode AMI Build Script
3+
# Purpose: Install prerequisites, pre-download core Docker images, and set up
4+
# first-boot installer for EC2 Image Builder.
5+
#
6+
# The installer still runs at first boot (via rc.local), but finds the heavy
7+
# Docker images already cached in /usr/src/dappnode/DNCORE/, making boot fast
8+
# and not dependent on network for bulk downloads.
9+
10+
set -euo pipefail
11+
12+
DAPPNODE_DIR="/usr/src/dappnode"
13+
DNCORE_DIR="$DAPPNODE_DIR/DNCORE"
14+
LOGS_DIR="$DAPPNODE_DIR/logs"
15+
LOG_FILE="$LOGS_DIR/ami_build.log"
16+
17+
mkdir -p "$DAPPNODE_DIR/scripts" "$DNCORE_DIR" "$LOGS_DIR"
18+
touch "$LOG_FILE"
19+
20+
log() { echo "[AMI-BUILD] $*" | tee -a "$LOG_FILE"; }
21+
22+
lsb_dist="$(. /etc/os-release && echo "$ID")"
23+
log "Detected OS: $lsb_dist"
24+
25+
# ─── Docker ───────────────────────────────────────────────────────────────────
26+
install_docker() {
27+
log "Installing Docker..."
28+
apt-get update -y
29+
apt-get remove -y docker docker-engine docker.io containerd runc || true
30+
31+
apt-get install -y ca-certificates curl lsb-release
32+
install -m 0755 -d /etc/apt/keyrings
33+
curl -fsSL "https://download.docker.com/linux/${lsb_dist}/gpg" -o /etc/apt/keyrings/docker.asc
34+
chmod a+r /etc/apt/keyrings/docker.asc
35+
36+
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/$lsb_dist $(lsb_release -cs) stable" \
37+
| tee /etc/apt/sources.list.d/docker.list >/dev/null
38+
39+
apt-get update -y
40+
apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
41+
[ -f "/usr/bin/xz" ] || apt-get install -y xz-utils
42+
log "Docker installed successfully"
43+
}
44+
45+
# ─── Docker Compose alias (legacy compatibility) ──────────────────────────────
46+
install_compose_alias() {
47+
cat >/usr/local/bin/docker-compose <<'EOL'
48+
#!/bin/bash
49+
docker compose "$@"
50+
EOL
51+
chmod +x /usr/local/bin/docker-compose
52+
}
53+
54+
# ─── Prerequisites ────────────────────────────────────────────────────────────
55+
log "=== Phase 1: Prerequisites ==="
56+
57+
apt-get update -y | tee -a "$LOG_FILE"
58+
59+
if ! docker -v >/dev/null 2>&1; then
60+
install_docker 2>&1 | tee -a "$LOG_FILE"
61+
else
62+
log "Docker already installed"
63+
fi
64+
65+
install_compose_alias
66+
67+
modprobe wireguard 2>/dev/null || apt-get install -y wireguard-dkms || apt-get install -y wireguard-tools || true
68+
apt-get install -y lsof iptables xz-utils || true
69+
70+
# ─── Pre-download core Docker images ─────────────────────────────────────────
71+
log "=== Phase 2: Pre-downloading core images ==="
72+
73+
# Download latest released profile (contains version pins)
74+
wget -O "$DNCORE_DIR/.dappnode_profile" \
75+
"https://github.com/dappnode/DAppNode/releases/latest/download/dappnode_profile.sh"
76+
77+
# Source only the version variables (up to ISOBUILD marker)
78+
sed '/^\#\!ISOBUILD/q' "$DNCORE_DIR/.dappnode_profile" > /tmp/vars.sh
79+
source /tmp/vars.sh
80+
81+
COMPONENTS=(BIND IPFS WIREGUARD DAPPMANAGER WIFI HTTPS)
82+
83+
for comp in "${COMPONENTS[@]}"; do
84+
ver="${comp}_VERSION"
85+
comp_lower="$(echo "$comp" | tr '[:upper:]' '[:lower:]')"
86+
VERSION="${!ver}"
87+
88+
if [[ "$VERSION" == /ipfs/* ]]; then
89+
log "Skipping $comp (IPFS-based version)"
90+
continue
91+
fi
92+
93+
BASE_URL="https://github.com/dappnode/DNP_${comp}/releases/download/v${VERSION}"
94+
95+
log "Downloading $comp v${VERSION}..."
96+
wget -q -O "$DNCORE_DIR/${comp_lower}.dnp.dappnode.eth_${VERSION}_linux-amd64.txz" \
97+
"${BASE_URL}/${comp_lower}.dnp.dappnode.eth_${VERSION}_linux-amd64.txz" || \
98+
log "WARNING: Failed to download $comp image"
99+
100+
wget -q -O "$DNCORE_DIR/docker-compose-${comp_lower}.yml" \
101+
"${BASE_URL}/docker-compose.yml" || \
102+
log "WARNING: Failed to download $comp compose"
103+
104+
wget -q -O "$DNCORE_DIR/dappnode_package-${comp_lower}.json" \
105+
"${BASE_URL}/dappnode_package.json" || \
106+
log "WARNING: Failed to download $comp manifest"
107+
done
108+
109+
# Grab content hashes for execution/consensus clients
110+
CONTENT_HASH_PKGS=(besu geth nethermind erigon prysm teku lighthouse lodestar nimbus)
111+
HASH_FILE="$DNCORE_DIR/packages-content-hash.csv"
112+
rm -f "$HASH_FILE"
113+
for pkg in "${CONTENT_HASH_PKGS[@]}"; do
114+
HASH=$(wget -q -O- "https://github.com/dappnode/DAppNodePackage-${pkg}/releases/latest/download/content-hash" || true)
115+
if [ -n "$HASH" ]; then
116+
echo "${pkg}.dnp.dappnode.eth,${HASH}" >> "$HASH_FILE"
117+
log "Got content hash for $pkg"
118+
fi
119+
done
120+
121+
log "Pre-download complete:"
122+
ls -lh "$DNCORE_DIR/"
123+
du -sh "$DNCORE_DIR/"
124+
125+
# ─── Set up first-boot installer ─────────────────────────────────────────────
126+
log "=== Phase 3: First-boot installer ==="
127+
128+
wget -O "$DAPPNODE_DIR/scripts/dappnode_install.sh" https://installer.dappnode.io
129+
chmod +x "$DAPPNODE_DIR/scripts/dappnode_install.sh"
130+
131+
cat > /etc/rc.local << 'RC'
132+
#!/bin/sh -e
133+
/usr/src/dappnode/scripts/dappnode_install.sh
134+
exit 0
135+
RC
136+
chmod +x /etc/rc.local
137+
touch "$DAPPNODE_DIR/.firstboot"
138+
139+
log "=== AMI build complete. First boot will find pre-cached images in DNCORE/ ==="

0 commit comments

Comments
 (0)