feat: deploy onto the pi and add scripts for boot
This commit is contained in:
parent
f4d95c595e
commit
16ad3c6181
13 changed files with 399 additions and 175 deletions
|
|
@ -7,7 +7,6 @@ HOSTNAME=noisebridge-pi
|
|||
WIFI_SSID=Noisebridge
|
||||
WIFI_PASSWORD=noisebridge
|
||||
PI_USERNAME=pi
|
||||
PI_PASSWORD=noisebridge
|
||||
SSH_KEY='ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIE40ISu3ydCqfdpb26JYD5cIN0Fu0id/FDS+xjB5zpqu'
|
||||
|
||||
if [[ $EUID -ne 0 ]]; then
|
||||
|
|
@ -15,14 +14,26 @@ if [[ $EUID -ne 0 ]]; then
|
|||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ! -d "$BOOTFS" || ! -d "$ROOTFS" ]]; then
|
||||
echo "Expected mounted boot and root partitions." >&2
|
||||
if [[ ! -d "$BOOTFS" ]]; then
|
||||
echo "Expected mounted boot partition." >&2
|
||||
echo "Boot: $BOOTFS" >&2
|
||||
echo "Root: $ROOTFS" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
PASSWORD_HASH=$(mkpasswd -m sha-512 "$PI_PASSWORD")
|
||||
CONFIG_TXT="$BOOTFS/config.txt"
|
||||
if [[ ! -f "$CONFIG_TXT" && -f "$BOOTFS/firmware/config.txt" ]]; then
|
||||
CONFIG_TXT="$BOOTFS/firmware/config.txt"
|
||||
fi
|
||||
|
||||
if [[ ! -f "$CONFIG_TXT" ]]; then
|
||||
echo "Could not find config.txt in $BOOTFS" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ROOTFS_READY=0
|
||||
if [[ -d "$ROOTFS" && -f "$ROOTFS/etc/shadow" ]]; then
|
||||
ROOTFS_READY=1
|
||||
fi
|
||||
|
||||
cat > "$BOOTFS/network-config" <<EOF
|
||||
network:
|
||||
|
|
@ -59,17 +70,15 @@ dsmode: local
|
|||
instance_id: ${HOSTNAME}-bootstrap-1
|
||||
EOF
|
||||
|
||||
grep -q '^enable_uart=1$' "$BOOTFS/config.txt" || printf '\nenable_uart=1\n' >> "$BOOTFS/config.txt"
|
||||
grep -q '^enable_uart=1$' "$CONFIG_TXT" || printf '\nenable_uart=1\n' >> "$CONFIG_TXT"
|
||||
: > "$BOOTFS/ssh"
|
||||
cat > "$BOOTFS/userconf.txt" <<EOF
|
||||
${PI_USERNAME}:${PASSWORD_HASH}
|
||||
EOF
|
||||
|
||||
cat > "$ROOTFS/etc/hostname" <<EOF
|
||||
if [[ "$ROOTFS_READY" -eq 1 ]]; then
|
||||
cat > "$ROOTFS/etc/hostname" <<EOF
|
||||
${HOSTNAME}
|
||||
EOF
|
||||
|
||||
cat > "$ROOTFS/etc/hosts" <<EOF
|
||||
cat > "$ROOTFS/etc/hosts" <<EOF
|
||||
127.0.0.1 localhost
|
||||
::1 localhost ip6-localhost ip6-loopback
|
||||
ff02::1 ip6-allnodes
|
||||
|
|
@ -78,13 +87,14 @@ ff02::2 ip6-allrouters
|
|||
127.0.1.1 ${HOSTNAME}
|
||||
EOF
|
||||
|
||||
mkdir -p "$ROOTFS/home/pi/.ssh"
|
||||
cat > "$ROOTFS/home/pi/.ssh/authorized_keys" <<EOF
|
||||
mkdir -p "$ROOTFS/home/pi/.ssh"
|
||||
cat > "$ROOTFS/home/pi/.ssh/authorized_keys" <<EOF
|
||||
${SSH_KEY}
|
||||
EOF
|
||||
chown -R 1000:1000 "$ROOTFS/home/pi/.ssh"
|
||||
chmod 700 "$ROOTFS/home/pi/.ssh"
|
||||
chmod 600 "$ROOTFS/home/pi/.ssh/authorized_keys"
|
||||
chown -R 1000:1000 "$ROOTFS/home/pi/.ssh"
|
||||
chmod 700 "$ROOTFS/home/pi/.ssh"
|
||||
chmod 600 "$ROOTFS/home/pi/.ssh/authorized_keys"
|
||||
fi
|
||||
|
||||
sync
|
||||
|
||||
|
|
@ -94,5 +104,7 @@ echo "- Wi-Fi: ${WIFI_SSID}"
|
|||
echo "- SSH enabled on first boot"
|
||||
echo "- Serial UART enabled"
|
||||
echo "- Username: ${PI_USERNAME}"
|
||||
echo "- Password: ${PI_PASSWORD}"
|
||||
echo "- Pi user authorized key installed"
|
||||
if [[ "$ROOTFS_READY" -ne 1 ]]; then
|
||||
echo "- Note: rootfs was not mounted; only boot partition config was updated"
|
||||
fi
|
||||
|
|
|
|||
6
scripts/deploy-full-pi.sh
Executable file
6
scripts/deploy-full-pi.sh
Executable file
|
|
@ -0,0 +1,6 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
TARGET_HOST=${1:-root@noisebridge-pi.local}
|
||||
|
||||
exec nixos-rebuild switch --flake ".#pi" --target-host "$TARGET_HOST"
|
||||
117
scripts/deploy-pios-pi.sh
Executable file
117
scripts/deploy-pios-pi.sh
Executable file
|
|
@ -0,0 +1,117 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
TARGET_HOST=${1:-pi@noisebridge-pi.local}
|
||||
SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)
|
||||
REPO_ROOT=$(cd -- "$SCRIPT_DIR/.." && pwd)
|
||||
RELEASE_ID=${RELEASE_ID:-$(date +%Y%m%d-%H%M%S)}
|
||||
REMOTE_RELEASE_DIR=${REMOTE_RELEASE_DIR:-/opt/noisebell/releases/$RELEASE_ID}
|
||||
REMOTE_CURRENT_LINK=${REMOTE_CURRENT_LINK:-/opt/noisebell/current}
|
||||
REMOTE_TMP_DIR=${REMOTE_TMP_DIR:-/home/pi/noisebell-deploy-tmp}
|
||||
TMP_DIR=$(mktemp -d)
|
||||
|
||||
cleanup() {
|
||||
rm -rf "$TMP_DIR"
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
SSH_OPTS=(
|
||||
-o StrictHostKeyChecking=accept-new
|
||||
)
|
||||
|
||||
echo "Building static aarch64 Noisebell binary locally..."
|
||||
PACKAGE_PATH=$(nix build .#packages.aarch64-linux.noisebell-static --print-out-paths --no-link)
|
||||
BIN_PATH="$PACKAGE_PATH/bin/noisebell"
|
||||
|
||||
if [[ ! -x "$BIN_PATH" ]]; then
|
||||
echo "built binary not found: $BIN_PATH" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! command -v agenix >/dev/null 2>&1; then
|
||||
echo "agenix is required in your shell to decrypt secrets locally" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Decrypting Pi secrets locally..."
|
||||
(
|
||||
cd "$REPO_ROOT/secrets"
|
||||
RULES="$REPO_ROOT/secrets/secrets.nix" agenix -d pi-to-cache-key.age > "$TMP_DIR/pi-to-cache-key"
|
||||
RULES="$REPO_ROOT/secrets/secrets.nix" agenix -d cache-to-pi-key.age > "$TMP_DIR/cache-to-pi-key"
|
||||
RULES="$REPO_ROOT/secrets/secrets.nix" agenix -d tailscale-auth-key.age > "$TMP_DIR/tailscale-auth-key"
|
||||
)
|
||||
chmod 600 "$TMP_DIR"/*
|
||||
|
||||
echo "Preparing remote directories on $TARGET_HOST..."
|
||||
ssh "${SSH_OPTS[@]}" "$TARGET_HOST" "mkdir -p '$REMOTE_TMP_DIR' && rm -f '$REMOTE_TMP_DIR/noisebell' '$REMOTE_TMP_DIR/pi-to-cache-key' '$REMOTE_TMP_DIR/cache-to-pi-key' '$REMOTE_TMP_DIR/tailscale-auth-key' && sudo mkdir -p '$REMOTE_RELEASE_DIR' /etc/noisebell /opt/noisebell/releases /var/lib/noisebell"
|
||||
|
||||
echo "Uploading binary and secret files..."
|
||||
scp "${SSH_OPTS[@]}" "$BIN_PATH" "$TARGET_HOST:$REMOTE_TMP_DIR/noisebell"
|
||||
scp "${SSH_OPTS[@]}" "$TMP_DIR/pi-to-cache-key" "$TARGET_HOST:$REMOTE_TMP_DIR/pi-to-cache-key"
|
||||
scp "${SSH_OPTS[@]}" "$TMP_DIR/cache-to-pi-key" "$TARGET_HOST:$REMOTE_TMP_DIR/cache-to-pi-key"
|
||||
scp "${SSH_OPTS[@]}" "$TMP_DIR/tailscale-auth-key" "$TARGET_HOST:$REMOTE_TMP_DIR/tailscale-auth-key"
|
||||
|
||||
echo "Installing service and Tailscale on $TARGET_HOST..."
|
||||
ssh "${SSH_OPTS[@]}" "$TARGET_HOST" "REMOTE_RELEASE_DIR='$REMOTE_RELEASE_DIR' REMOTE_CURRENT_LINK='$REMOTE_CURRENT_LINK' REMOTE_TMP_DIR='$REMOTE_TMP_DIR' bash -s" <<'EOF'
|
||||
set -euo pipefail
|
||||
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y curl rsync avahi-daemon
|
||||
|
||||
if ! command -v tailscale >/dev/null 2>&1; then
|
||||
curl -fsSL https://tailscale.com/install.sh | sh
|
||||
fi
|
||||
sudo systemctl enable --now ssh avahi-daemon tailscaled
|
||||
|
||||
sudo install -m 755 "$REMOTE_TMP_DIR/noisebell" "$REMOTE_RELEASE_DIR/noisebell"
|
||||
sudo mv "$REMOTE_TMP_DIR/pi-to-cache-key" /etc/noisebell/pi-to-cache-key
|
||||
sudo mv "$REMOTE_TMP_DIR/cache-to-pi-key" /etc/noisebell/cache-to-pi-key
|
||||
sudo mv "$REMOTE_TMP_DIR/tailscale-auth-key" /etc/noisebell/tailscale-auth-key
|
||||
sudo chown root:root /etc/noisebell/pi-to-cache-key /etc/noisebell/cache-to-pi-key /etc/noisebell/tailscale-auth-key
|
||||
sudo chmod 600 /etc/noisebell/pi-to-cache-key /etc/noisebell/cache-to-pi-key /etc/noisebell/tailscale-auth-key
|
||||
|
||||
sudo tee /etc/noisebell/noisebell.env >/dev/null <<'ENVEOF'
|
||||
NOISEBELL_GPIO_PIN=17
|
||||
NOISEBELL_DEBOUNCE_SECS=5
|
||||
NOISEBELL_PORT=80
|
||||
NOISEBELL_RETRY_ATTEMPTS=3
|
||||
NOISEBELL_RETRY_BASE_DELAY_SECS=1
|
||||
NOISEBELL_HTTP_TIMEOUT_SECS=10
|
||||
NOISEBELL_ENDPOINT_URL=https://noisebell.extremist.software/webhook
|
||||
NOISEBELL_BIND_ADDRESS=0.0.0.0
|
||||
NOISEBELL_ACTIVE_LOW=true
|
||||
RUST_LOG=info
|
||||
ENVEOF
|
||||
sudo chmod 600 /etc/noisebell/noisebell.env
|
||||
|
||||
sudo tee /etc/systemd/system/noisebell.service >/dev/null <<UNITEOF
|
||||
[Unit]
|
||||
Description=Noisebell GPIO door monitor
|
||||
After=network-online.target tailscaled.service
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=notify
|
||||
NotifyAccess=all
|
||||
EnvironmentFile=/etc/noisebell/noisebell.env
|
||||
ExecStart=/bin/bash -lc 'export NOISEBELL_API_KEY="$$(cat /etc/noisebell/pi-to-cache-key)"; export NOISEBELL_INBOUND_API_KEY="$$(cat /etc/noisebell/cache-to-pi-key)"; exec ${REMOTE_CURRENT_LINK}/noisebell'
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
WatchdogSec=30
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
UNITEOF
|
||||
|
||||
sudo ln -sfn "$REMOTE_RELEASE_DIR" "$REMOTE_CURRENT_LINK"
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl enable --now noisebell.service
|
||||
|
||||
sudo tailscale up --auth-key="$(sudo cat /etc/noisebell/tailscale-auth-key)" --hostname=noisebridge-pi || true
|
||||
|
||||
rmdir "$REMOTE_TMP_DIR" 2>/dev/null || true
|
||||
|
||||
echo "Noisebell deployed on Raspberry Pi OS."
|
||||
EOF
|
||||
|
||||
echo "Done."
|
||||
Loading…
Add table
Add a link
Reference in a new issue