fix: ISO boot, container installs, VPN, nginx, companion input
All checks were successful
Build Archipelago ISO (dev) / build-iso (push) Successful in 30m53s
All checks were successful
Build Archipelago ISO (dev) / build-iso (push) Successful in 30m53s
- LUKS auto-unlock: initramfs hook + systemd service + nofail fstab - Rootfs packages: add passt, aardvark-dns, netavark, nftables for Podman 5.x - nginx: resolver + variable proxy_pass for external domains (DNS at boot) - Boot: loglevel=0 suppresses kernel warnings, serial console for QEMU - Container installs: write configs before chown, sudo chown for LUKS volumes - Container installs: build UI sidecars locally (not from registry) for auth injection - Bitcoin UI: inject RPC auth from secrets file, --no-cache rebuild - Secrets: chown to archipelago user in first-boot (backend needs read access) - Podman: image_copy_tmp_dir for read-only /var/tmp in user namespace - NostrVPN: enable service in auto-install, always include public relays - NostrVPN: read tunnel IP from nvpn status (not just config file) - VPN invite: v2 base64 no-pad format matching phone app - Companion input: relay always active, kiosk skips relay listener (prevents double input) - dev-start.sh: production build includes AIUI deployment Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -274,6 +274,10 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
podman \
|
||||
uidmap \
|
||||
slirp4netns \
|
||||
passt \
|
||||
aardvark-dns \
|
||||
netavark \
|
||||
nftables \
|
||||
fuse-overlayfs \
|
||||
tor \
|
||||
python3 \
|
||||
@@ -922,10 +926,20 @@ else
|
||||
echo " Capturing backend binary from live server..."
|
||||
fi
|
||||
|
||||
# Try to get from live server first (unless BUILD_FROM_SOURCE=1)
|
||||
# Try to get backend binary: local release build → local install → remote → container build
|
||||
BACKEND_CAPTURED=0
|
||||
if [ "$BUILD_FROM_SOURCE" != "1" ]; then
|
||||
# Direct copy from ARCHIPELAGO_BIN env, local install, or remote
|
||||
|
||||
# Check for local release binary first (works for both BUILD_FROM_SOURCE and normal mode)
|
||||
LOCAL_RELEASE="$(cd "$SCRIPT_DIR/.." && pwd)/core/target/release/archipelago"
|
||||
if [ -f "$LOCAL_RELEASE" ]; then
|
||||
cp "$LOCAL_RELEASE" "$ARCH_DIR/bin/archipelago"
|
||||
chmod +x "$ARCH_DIR/bin/archipelago"
|
||||
echo " ✅ Backend from local release build ($(du -h "$ARCH_DIR/bin/archipelago" | cut -f1))"
|
||||
BACKEND_CAPTURED=1
|
||||
fi
|
||||
|
||||
if [ "$BACKEND_CAPTURED" = "0" ] && [ "$BUILD_FROM_SOURCE" != "1" ]; then
|
||||
# Direct copy from ARCHIPELAGO_BIN env or local install
|
||||
BIN="${ARCHIPELAGO_BIN:-/usr/local/bin/archipelago}"
|
||||
if [ -f "$BIN" ]; then
|
||||
cp "$BIN" "$ARCH_DIR/bin/archipelago"
|
||||
@@ -2006,12 +2020,65 @@ DATA_UUID=$(blkid -s UUID -o value "$DATA_PART")
|
||||
echo "# LUKS2 encrypted data — auto-unlock with key file" > /mnt/target/etc/crypttab
|
||||
echo "archipelago-data UUID=$DATA_UUID /root/.luks-archipelago.key luks,discard" >> /mnt/target/etc/crypttab
|
||||
|
||||
# Configure LUKS auto-unlock: three layers to ensure it works
|
||||
# Layer 1: cryptsetup-initramfs config (tells update-initramfs to embed key)
|
||||
mkdir -p /mnt/target/etc/cryptsetup-initramfs
|
||||
cat > /mnt/target/etc/cryptsetup-initramfs/conf <<'CRYPTCONF'
|
||||
KEYFILE_PATTERN="/root/.luks-*.key"
|
||||
UMASK=0077
|
||||
CRYPTCONF
|
||||
|
||||
# Layer 2: initramfs hook to force-copy key file
|
||||
mkdir -p /mnt/target/etc/initramfs-tools/hooks
|
||||
cat > /mnt/target/etc/initramfs-tools/hooks/archipelago-luks <<'LUKSHOOK'
|
||||
#!/bin/sh
|
||||
PREREQ=""
|
||||
prereqs() { echo "$PREREQ"; }
|
||||
case $1 in prereqs) prereqs; exit 0;; esac
|
||||
. /usr/share/initramfs-tools/hook-functions
|
||||
if [ -f /root/.luks-archipelago.key ]; then
|
||||
mkdir -p "${DESTDIR}/root"
|
||||
cp /root/.luks-archipelago.key "${DESTDIR}/root/.luks-archipelago.key"
|
||||
chmod 600 "${DESTDIR}/root/.luks-archipelago.key"
|
||||
fi
|
||||
if [ -f /etc/crypttab ]; then
|
||||
mkdir -p "${DESTDIR}/etc"
|
||||
cp /etc/crypttab "${DESTDIR}/etc/crypttab"
|
||||
fi
|
||||
copy_exec /sbin/cryptsetup
|
||||
LUKSHOOK
|
||||
chmod +x /mnt/target/etc/initramfs-tools/hooks/archipelago-luks
|
||||
|
||||
# Layer 3: systemd service as fallback — unlocks LUKS early if initramfs missed it
|
||||
cat > /mnt/target/etc/systemd/system/archipelago-luks-unlock.service <<'LUKSUNIT'
|
||||
[Unit]
|
||||
Description=Unlock Archipelago LUKS data partition
|
||||
DefaultDependencies=no
|
||||
Before=local-fs-pre.target
|
||||
After=systemd-udevd.service
|
||||
Wants=systemd-udevd.service
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
RemainAfterExit=yes
|
||||
ExecStart=/bin/bash -c '\
|
||||
if [ -e /dev/mapper/archipelago-data ]; then exit 0; fi; \
|
||||
DATA_DEV=$(blkid -t TYPE=crypto_LUKS -o device 2>/dev/null | head -1); \
|
||||
if [ -z "$DATA_DEV" ]; then exit 0; fi; \
|
||||
cryptsetup open --type luks2 --key-file /root/.luks-archipelago.key "$DATA_DEV" archipelago-data'
|
||||
|
||||
[Install]
|
||||
WantedBy=local-fs-pre.target
|
||||
LUKSUNIT
|
||||
chroot /mnt/target systemctl enable archipelago-luks-unlock.service 2>/dev/null || \
|
||||
ln -sf /etc/systemd/system/archipelago-luks-unlock.service /mnt/target/etc/systemd/system/local-fs-pre.target.wants/archipelago-luks-unlock.service
|
||||
|
||||
# Create fstab
|
||||
cat > /mnt/target/etc/fstab <<EOF
|
||||
# Archipelago Bitcoin Node OS
|
||||
UUID=$(blkid -s UUID -o value "$ROOT_PART") / ext4 errors=remount-ro 0 1
|
||||
UUID=$(blkid -s UUID -o value "$EFI_PART") /boot/efi vfat umask=0077 0 1
|
||||
/dev/mapper/archipelago-data /var/lib/archipelago ext4 defaults 0 2
|
||||
/dev/mapper/archipelago-data /var/lib/archipelago ext4 defaults,nofail,x-systemd.device-timeout=60 0 2
|
||||
EOF
|
||||
|
||||
# Configure hostname
|
||||
@@ -2055,7 +2122,13 @@ if [ -f /mnt/target/usr/lib/podman/netavark ]; then
|
||||
cat > /mnt/target/home/archipelago/.config/containers/containers.conf <<'CONTAINERSCONF'
|
||||
[network]
|
||||
network_backend = "netavark"
|
||||
default_rootless_network_cmd = "pasta"
|
||||
|
||||
[engine]
|
||||
image_copy_tmp_dir = "/var/lib/archipelago/containers/tmp"
|
||||
CONTAINERSCONF
|
||||
mkdir -p /mnt/target/var/lib/archipelago/containers/tmp
|
||||
chown -R 1000:1000 /mnt/target/var/lib/archipelago/containers/tmp
|
||||
chown -R 1000:1000 /mnt/target/home/archipelago/.config/containers
|
||||
echo " Configured netavark backend (container DNS enabled)"
|
||||
else
|
||||
@@ -2623,15 +2696,9 @@ if [ -d "$BOOT_MEDIA/archipelago/plymouth-theme" ]; then
|
||||
chroot /mnt/target plymouth-set-default-theme archipelago 2>/dev/null || \
|
||||
ln -sf /usr/share/plymouth/themes/archipelago/archipelago.plymouth \
|
||||
/mnt/target/etc/alternatives/default.plymouth 2>/dev/null || true
|
||||
# Enable splash and ACPI in GRUB
|
||||
if ! grep -q "splash" /mnt/target/etc/default/grub; then
|
||||
sed -i 's/GRUB_CMDLINE_LINUX_DEFAULT="\(.*\)"/GRUB_CMDLINE_LINUX_DEFAULT="\1 splash"/' \
|
||||
/mnt/target/etc/default/grub 2>/dev/null || true
|
||||
fi
|
||||
if ! grep -q "acpi=force" /mnt/target/etc/default/grub; then
|
||||
sed -i 's/GRUB_CMDLINE_LINUX_DEFAULT="\(.*\)"/GRUB_CMDLINE_LINUX_DEFAULT="\1 acpi=force"/' \
|
||||
/mnt/target/etc/default/grub 2>/dev/null || true
|
||||
fi
|
||||
# Configure clean boot: splash, suppress kernel noise, hide cursor
|
||||
sed -i 's/GRUB_CMDLINE_LINUX_DEFAULT=".*"/GRUB_CMDLINE_LINUX_DEFAULT="quiet splash loglevel=0 rd.systemd.show_status=false vt.global_cursor_default=0 acpi=force"/' \
|
||||
/mnt/target/etc/default/grub 2>/dev/null || true
|
||||
echo " Installed Archipelago Plymouth theme on target"
|
||||
fi
|
||||
|
||||
@@ -2816,6 +2883,7 @@ chroot /mnt/target systemctl enable archipelago-load-images.service 2>/dev/null
|
||||
chroot /mnt/target systemctl enable archipelago-setup-tor.service 2>/dev/null || true
|
||||
chroot /mnt/target systemctl enable archipelago-first-boot-containers.service 2>/dev/null || true
|
||||
chroot /mnt/target systemctl enable archipelago-kiosk.service 2>/dev/null || true
|
||||
chroot /mnt/target systemctl enable nostr-vpn.service 2>/dev/null || true
|
||||
# Enable claude-api-proxy (create symlink manually — chroot systemctl can fail)
|
||||
chroot /mnt/target systemctl enable claude-api-proxy.service 2>/dev/null || \
|
||||
ln -sf /etc/systemd/system/claude-api-proxy.service /mnt/target/etc/systemd/system/multi-user.target.wants/claude-api-proxy.service 2>/dev/null || true
|
||||
@@ -3079,15 +3147,21 @@ fi
|
||||
set timeout=5
|
||||
set default=0
|
||||
|
||||
# Serial console for QEMU/headless testing
|
||||
insmod serial
|
||||
serial --unit=0 --speed=115200
|
||||
terminal_input serial console
|
||||
terminal_output serial console
|
||||
|
||||
# Load font for graphical menu — fallback to text mode on hardware without gfxterm
|
||||
if loadfont ($root)/boot/grub/font.pf2; then
|
||||
set gfxmode=auto
|
||||
set gfxpayload=keep
|
||||
insmod gfxterm
|
||||
insmod png
|
||||
terminal_output gfxterm
|
||||
terminal_output gfxterm serial
|
||||
else
|
||||
terminal_output console
|
||||
terminal_output console serial
|
||||
fi
|
||||
|
||||
# Archipelago GRUB theme
|
||||
@@ -3103,7 +3177,7 @@ else
|
||||
fi
|
||||
|
||||
menuentry "Install Archipelago" --hotkey=i {
|
||||
linux ($root)/live/vmlinuz boot=live components quiet splash loglevel=0 rd.systemd.show_status=false vt.global_cursor_default=0 acpi=force
|
||||
linux ($root)/live/vmlinuz boot=live components quiet splash loglevel=0 rd.systemd.show_status=false vt.global_cursor_default=0 acpi=force console=ttyS0,115200 console=tty0
|
||||
initrd ($root)/live/initrd.img
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,10 @@ limit_req_zone $binary_remote_addr zone=rpc:10m rate=20r/s;
|
||||
limit_req_zone $binary_remote_addr zone=auth:10m rate=3r/s;
|
||||
limit_req_zone $binary_remote_addr zone=peer:10m rate=10r/s;
|
||||
|
||||
# Resolve external domains at request time (not startup) to prevent boot failures
|
||||
resolver 1.1.1.1 8.8.8.8 valid=300s ipv6=off;
|
||||
resolver_timeout 5s;
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
server_name _;
|
||||
@@ -46,7 +50,9 @@ server {
|
||||
|
||||
# AIUI OpenRouter API proxy (API key managed by proxy, no session gate needed)
|
||||
location /aiui/api/openrouter/ {
|
||||
proxy_pass https://openrouter.ai/api/;
|
||||
set $upstream_1 "https://openrouter.ai/api/";
|
||||
|
||||
proxy_pass $upstream_1;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host openrouter.ai;
|
||||
proxy_ssl_server_name on;
|
||||
@@ -175,6 +181,20 @@ server {
|
||||
error_page 504 = @backend_timeout;
|
||||
}
|
||||
|
||||
# LND REST proxy — backend handles auth + CORS
|
||||
location /proxy/lnd/ {
|
||||
proxy_pass http://127.0.0.1:5678;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header Cookie $http_cookie;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_connect_timeout 10s;
|
||||
proxy_read_timeout 10s;
|
||||
proxy_send_timeout 5s;
|
||||
error_page 502 503 = @backend_unavailable;
|
||||
error_page 504 = @backend_timeout;
|
||||
}
|
||||
|
||||
# Content sharing — peer access over Tor (no auth)
|
||||
location /content {
|
||||
limit_req zone=peer burst=20 nodelay;
|
||||
@@ -662,7 +682,9 @@ server {
|
||||
# External site proxies — strip X-Frame-Options so iframe embedding works.
|
||||
# add_header here prevents inheritance of server-level X-Frame-Options.
|
||||
location /ext/botfights/ {
|
||||
proxy_pass https://botfights.net/;
|
||||
set $upstream_2 "https://botfights.net/";
|
||||
|
||||
proxy_pass $upstream_2;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host botfights.net;
|
||||
proxy_set_header Accept-Encoding "";
|
||||
@@ -684,7 +706,9 @@ server {
|
||||
sub_filter '</head>' '<script src="/nostr-provider.js"></script></head>';
|
||||
}
|
||||
location /ext/484-kitchen/ {
|
||||
proxy_pass https://484.kitchen/;
|
||||
set $upstream_3 "https://484.kitchen/";
|
||||
|
||||
proxy_pass $upstream_3;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host 484.kitchen;
|
||||
proxy_set_header Accept-Encoding "";
|
||||
@@ -703,7 +727,9 @@ server {
|
||||
sub_filter '</head>' '<script src="/nostr-provider.js"></script></head>';
|
||||
}
|
||||
location /ext/arch-presentation/ {
|
||||
proxy_pass https://present.l484.com/;
|
||||
set $upstream_4 "https://present.l484.com/";
|
||||
|
||||
proxy_pass $upstream_4;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host present.l484.com;
|
||||
proxy_set_header Accept-Encoding "";
|
||||
@@ -722,7 +748,9 @@ server {
|
||||
sub_filter '</head>' '<script src="/nostr-provider.js"></script></head>';
|
||||
}
|
||||
location /ext/nostrudel/ {
|
||||
proxy_pass https://nostrudel.ninja/;
|
||||
set $upstream_5 "https://nostrudel.ninja/";
|
||||
|
||||
proxy_pass $upstream_5;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host nostrudel.ninja;
|
||||
proxy_set_header Accept-Encoding "";
|
||||
@@ -818,7 +846,9 @@ server {
|
||||
proxy_send_timeout 120s;
|
||||
}
|
||||
location /aiui/api/openrouter/ {
|
||||
proxy_pass https://openrouter.ai/api/;
|
||||
set $upstream_6 "https://openrouter.ai/api/";
|
||||
|
||||
proxy_pass $upstream_6;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host openrouter.ai;
|
||||
proxy_ssl_server_name on;
|
||||
@@ -886,6 +916,20 @@ server {
|
||||
error_page 504 = @backend_timeout;
|
||||
}
|
||||
|
||||
# LND REST proxy — backend handles auth + CORS
|
||||
location /proxy/lnd/ {
|
||||
proxy_pass http://127.0.0.1:5678;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header Cookie $http_cookie;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_connect_timeout 10s;
|
||||
proxy_read_timeout 10s;
|
||||
proxy_send_timeout 5s;
|
||||
error_page 502 503 = @backend_unavailable;
|
||||
error_page 504 = @backend_timeout;
|
||||
}
|
||||
|
||||
# Content sharing — peer access over Tor (no auth)
|
||||
location /content {
|
||||
limit_req zone=peer burst=20 nodelay;
|
||||
@@ -1038,7 +1082,9 @@ server {
|
||||
# External site proxies — strip X-Frame-Options so iframe embedding works.
|
||||
# add_header here prevents inheritance of server-level X-Frame-Options.
|
||||
location /ext/botfights/ {
|
||||
proxy_pass https://botfights.net/;
|
||||
set $upstream_7 "https://botfights.net/";
|
||||
|
||||
proxy_pass $upstream_7;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host botfights.net;
|
||||
proxy_set_header Accept-Encoding "";
|
||||
@@ -1060,7 +1106,9 @@ server {
|
||||
sub_filter '</head>' '<script src="/nostr-provider.js"></script></head>';
|
||||
}
|
||||
location /ext/484-kitchen/ {
|
||||
proxy_pass https://484.kitchen/;
|
||||
set $upstream_8 "https://484.kitchen/";
|
||||
|
||||
proxy_pass $upstream_8;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host 484.kitchen;
|
||||
proxy_set_header Accept-Encoding "";
|
||||
@@ -1079,7 +1127,9 @@ server {
|
||||
sub_filter '</head>' '<script src="/nostr-provider.js"></script></head>';
|
||||
}
|
||||
location /ext/arch-presentation/ {
|
||||
proxy_pass https://present.l484.com/;
|
||||
set $upstream_9 "https://present.l484.com/";
|
||||
|
||||
proxy_pass $upstream_9;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host present.l484.com;
|
||||
proxy_set_header Accept-Encoding "";
|
||||
@@ -1098,7 +1148,9 @@ server {
|
||||
sub_filter '</head>' '<script src="/nostr-provider.js"></script></head>';
|
||||
}
|
||||
location /ext/nostrudel/ {
|
||||
proxy_pass https://nostrudel.ninja/;
|
||||
set $upstream_10 "https://nostrudel.ninja/";
|
||||
|
||||
proxy_pass $upstream_10;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host nostrudel.ninja;
|
||||
proxy_set_header Accept-Encoding "";
|
||||
@@ -1139,7 +1191,9 @@ server {
|
||||
listen 8901;
|
||||
server_name _;
|
||||
location / {
|
||||
proxy_pass https://botfights.net;
|
||||
set $upstream_11 "https://botfights.net";
|
||||
|
||||
proxy_pass $upstream_11;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host botfights.net;
|
||||
proxy_set_header Accept-Encoding "";
|
||||
@@ -1164,7 +1218,9 @@ server {
|
||||
listen 8902;
|
||||
server_name _;
|
||||
location / {
|
||||
proxy_pass https://484.kitchen;
|
||||
set $upstream_12 "https://484.kitchen";
|
||||
|
||||
proxy_pass $upstream_12;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host 484.kitchen;
|
||||
proxy_set_header Accept-Encoding "";
|
||||
@@ -1185,7 +1241,9 @@ server {
|
||||
listen 8903;
|
||||
server_name _;
|
||||
location / {
|
||||
proxy_pass https://present.l484.com;
|
||||
set $upstream_13 "https://present.l484.com";
|
||||
|
||||
proxy_pass $upstream_13;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host present.l484.com;
|
||||
proxy_set_header Accept-Encoding "";
|
||||
|
||||
Reference in New Issue
Block a user