Add first-boot wizard for pre-built RPi images

- Create first-boot-wizard.sh with interactive step-by-step setup
  - Step 1: HTTPS configuration
  - Step 2: Port 443 configuration (if HTTPS enabled)
  - Step 3: Channel key generation
  - ASCII art banner and clear summaries
- Create stegasoo-wizard.sh profile.d hook to trigger wizard on SSH login
- Update sanitize-for-image.sh to:
  - Install wizard hook in /etc/profile.d/
  - Create first-boot flag file
  - Reset service to defaults for fresh config

Users who flash a pre-built image will see the wizard on first SSH login.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Aaron D. Lee
2026-01-02 23:24:20 -05:00
parent 82ac1dcda4
commit 8bb70e5667
3 changed files with 382 additions and 8 deletions

320
rpi/first-boot-wizard.sh Executable file
View File

@@ -0,0 +1,320 @@
#!/bin/bash
#
# Stegasoo First Boot Wizard
# Runs on first SSH login to configure the pre-installed Stegasoo image
#
# This script is triggered by /etc/profile.d/stegasoo-wizard.sh
# After completion, it removes itself to prevent re-running
#
# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
BOLD='\033[1m'
NC='\033[0m'
# Configuration
INSTALL_DIR="$HOME/stegasoo"
FLAG_FILE="/etc/stegasoo-first-boot"
PROFILE_HOOK="/etc/profile.d/stegasoo-wizard.sh"
# Check if this is first boot
if [ ! -f "$FLAG_FILE" ]; then
exit 0
fi
clear
echo -e "${CYAN}"
cat << 'BANNER'
_____ _
/ ____| |
| (___ | |_ ___ __ _ __ _ ___ ___ ___
\___ \| __/ _ \/ _` |/ _` / __|/ _ \ / _ \
____) | || __/ (_| | (_| \__ \ (_) | (_) |
|_____/ \__\___|\__, |\__,_|___/\___/ \___/
__/ |
|___/ First Boot Wizard
BANNER
echo -e "${NC}"
echo -e "${BOLD}Welcome to Stegasoo!${NC}"
echo ""
echo "This wizard will help you configure your Stegasoo server."
echo "You can reconfigure later by editing /etc/systemd/system/stegasoo.service"
echo ""
echo -e "${YELLOW}Press Enter to begin setup...${NC}"
read
# =============================================================================
# Configuration Variables
# =============================================================================
ENABLE_HTTPS="false"
USE_PORT_443="false"
CHANNEL_KEY=""
# =============================================================================
# Step 1: HTTPS Configuration
# =============================================================================
clear
echo -e "${BLUE}╔═══════════════════════════════════════════════════════════════╗${NC}"
echo -e "${BLUE}${NC} ${BOLD}Step 1 of 3: HTTPS Configuration${NC} ${BLUE}${NC}"
echo -e "${BLUE}╚═══════════════════════════════════════════════════════════════╝${NC}"
echo ""
echo "HTTPS encrypts all traffic between your browser and this server"
echo "using a self-signed certificate."
echo ""
echo -e "${YELLOW}Note:${NC} Your browser will show a security warning because the"
echo "certificate is self-signed. This is normal for home networks."
echo ""
echo " [Y] Enable HTTPS (recommended for home network security)"
echo " [n] Use HTTP only (unencrypted, not recommended)"
echo ""
read -p "Enable HTTPS? [Y/n] " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Nn]$ ]]; then
ENABLE_HTTPS="true"
echo ""
echo -e " ${GREEN}${NC} HTTPS will be enabled"
sleep 1
fi
# =============================================================================
# Step 2: Port Configuration (only if HTTPS)
# =============================================================================
if [ "$ENABLE_HTTPS" = "true" ]; then
clear
echo -e "${BLUE}╔═══════════════════════════════════════════════════════════════╗${NC}"
echo -e "${BLUE}${NC} ${BOLD}Step 2 of 3: Port Configuration${NC} ${BLUE}${NC}"
echo -e "${BLUE}╚═══════════════════════════════════════════════════════════════╝${NC}"
echo ""
echo "The standard HTTPS port is 443, which means you can access"
echo "Stegasoo without specifying a port in the URL."
echo ""
echo " Port 443: https://stegasoo.local"
echo " Port 5000: https://stegasoo.local:5000"
echo ""
echo -e "${YELLOW}Note:${NC} Port 443 requires an iptables redirect rule."
echo ""
echo " [Y] Use port 443 (cleaner URLs)"
echo " [n] Use port 5000 (default, no extra config)"
echo ""
read -p "Use standard port 443? [Y/n] " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Nn]$ ]]; then
USE_PORT_443="true"
echo ""
echo -e " ${GREEN}${NC} Port 443 will be configured"
sleep 1
fi
fi
# =============================================================================
# Step 3: Channel Key Configuration
# =============================================================================
clear
echo -e "${BLUE}╔═══════════════════════════════════════════════════════════════╗${NC}"
echo -e "${BLUE}${NC} ${BOLD}Step 3 of 3: Channel Key Configuration${NC} ${BLUE}${NC}"
echo -e "${BLUE}╚═══════════════════════════════════════════════════════════════╝${NC}"
echo ""
echo "A channel key creates a private encoding channel."
echo ""
echo " ${BOLD}Without a key:${NC} Anyone with Stegasoo can decode your images"
echo " ${BOLD}With a key:${NC} Only people with YOUR key can decode your images"
echo ""
echo "This is useful if you want to share encoded images only with"
echo "specific people (family, team, etc)."
echo ""
echo " [y] Generate a private channel key"
echo " [N] Use public mode (anyone can decode)"
echo ""
read -p "Generate a private channel key? [y/N] " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
echo ""
echo "Generating channel key..."
# Source the venv and generate key
source "$INSTALL_DIR/venv/bin/activate" 2>/dev/null
CHANNEL_KEY=$(python -c "from stegasoo.channel import generate_channel_key; print(generate_channel_key())" 2>/dev/null)
if [ -n "$CHANNEL_KEY" ]; then
echo ""
echo -e " ${GREEN}${NC} Channel key generated!"
echo ""
echo -e " ${BOLD}${YELLOW}$CHANNEL_KEY${NC}"
echo ""
echo -e " ${RED}╔═══════════════════════════════════════════════════════════╗${NC}"
echo -e " ${RED}║ IMPORTANT: Write down or copy this key NOW! ║${NC}"
echo -e " ${RED}║ You'll need to share it with anyone who should decode ║${NC}"
echo -e " ${RED}║ your images. This key won't be shown again. ║${NC}"
echo -e " ${RED}╚═══════════════════════════════════════════════════════════╝${NC}"
echo ""
read -p "Press Enter when you've saved the key..."
else
echo -e " ${RED}${NC} Failed to generate key. Using public mode."
CHANNEL_KEY=""
fi
else
echo ""
echo -e " ${YELLOW}${NC} Using public mode"
sleep 1
fi
# =============================================================================
# Apply Configuration
# =============================================================================
clear
echo -e "${BLUE}╔═══════════════════════════════════════════════════════════════╗${NC}"
echo -e "${BLUE}${NC} ${BOLD}Applying Configuration...${NC} ${BLUE}${NC}"
echo -e "${BLUE}╚═══════════════════════════════════════════════════════════════╝${NC}"
echo ""
# Find the stegasoo user (whoever owns the install dir)
STEGASOO_USER=$(stat -c '%U' "$INSTALL_DIR" 2>/dev/null || echo "pi")
echo " Updating systemd service..."
sudo tee /etc/systemd/system/stegasoo.service > /dev/null <<EOF
[Unit]
Description=Stegasoo Web UI
After=network.target
[Service]
Type=simple
User=$STEGASOO_USER
WorkingDirectory=$INSTALL_DIR/frontends/web
Environment="PATH=$INSTALL_DIR/venv/bin:/usr/bin"
Environment="STEGASOO_AUTH_ENABLED=true"
Environment="STEGASOO_HTTPS_ENABLED=$ENABLE_HTTPS"
Environment="STEGASOO_PORT=5000"
Environment="STEGASOO_CHANNEL_KEY=$CHANNEL_KEY"
ExecStart=$INSTALL_DIR/venv/bin/python app.py
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
echo -e " ${GREEN}${NC} Service configured"
# Setup port 443 if requested
if [ "$USE_PORT_443" = "true" ]; then
echo " Setting up port 443 redirect..."
# Install iptables if needed
if ! command -v iptables &> /dev/null; then
sudo apt-get install -y iptables > /dev/null 2>&1
fi
# Add redirect rule (check if it already exists)
if ! sudo iptables -t nat -C PREROUTING -p tcp --dport 443 -j REDIRECT --to-port 5000 2>/dev/null; then
sudo iptables -t nat -A PREROUTING -p tcp --dport 443 -j REDIRECT --to-port 5000
fi
sudo sh -c 'iptables-save > /etc/iptables.rules'
# Create/update persistence service
sudo tee /etc/systemd/system/iptables-restore.service > /dev/null <<EOF
[Unit]
Description=Restore iptables rules
Before=network-pre.target
[Service]
Type=oneshot
ExecStart=/sbin/iptables-restore /etc/iptables.rules
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl enable iptables-restore.service > /dev/null 2>&1
echo -e " ${GREEN}${NC} Port 443 redirect configured"
fi
echo " Reloading systemd..."
sudo systemctl daemon-reload
echo -e " ${GREEN}${NC} Systemd reloaded"
echo " Starting Stegasoo..."
sudo systemctl restart stegasoo
sleep 2
if systemctl is-active --quiet stegasoo; then
echo -e " ${GREEN}${NC} Stegasoo started successfully"
else
echo -e " ${RED}${NC} Failed to start (check: journalctl -u stegasoo)"
fi
# Remove first-boot flag and profile hook
echo " Cleaning up first-boot wizard..."
sudo rm -f "$FLAG_FILE"
sudo rm -f "$PROFILE_HOOK"
echo -e " ${GREEN}${NC} Wizard complete"
# =============================================================================
# Final Summary
# =============================================================================
clear
PI_IP=$(hostname -I | awk '{print $1}')
HOSTNAME=$(hostname)
echo -e "${GREEN}"
cat << 'BANNER'
_____ _
/ ____| |
| (___ | |_ ___ __ _ __ _ ___ ___ ___
\___ \| __/ _ \/ _` |/ _` / __|/ _ \ / _ \
____) | || __/ (_| | (_| \__ \ (_) | (_) |
|_____/ \__\___|\__, |\__,_|___/\___/ \___/
__/ |
|___/ Setup Complete!
BANNER
echo -e "${NC}"
echo -e "${BOLD}Your Stegasoo server is ready!${NC}"
echo ""
echo -e "${GREEN}Access URL:${NC}"
if [ "$ENABLE_HTTPS" = "true" ]; then
if [ "$USE_PORT_443" = "true" ]; then
echo -e " ${BOLD}${YELLOW}https://$PI_IP${NC}"
echo -e " ${BOLD}${YELLOW}https://$HOSTNAME.local${NC} (if mDNS works)"
else
echo -e " ${BOLD}${YELLOW}https://$PI_IP:5000${NC}"
echo -e " ${BOLD}${YELLOW}https://$HOSTNAME.local:5000${NC} (if mDNS works)"
fi
else
echo -e " ${BOLD}${YELLOW}http://$PI_IP:5000${NC}"
fi
echo ""
if [ -n "$CHANNEL_KEY" ]; then
echo -e "${GREEN}Channel Key:${NC}"
echo -e " ${YELLOW}$CHANNEL_KEY${NC}"
echo ""
fi
echo -e "${GREEN}First Steps:${NC}"
echo " 1. Open the URL above in your browser"
echo " 2. Accept the security warning (self-signed cert)"
echo " 3. Create your admin account"
echo " 4. Start encoding secret messages!"
echo ""
echo -e "${GREEN}Useful Commands:${NC}"
echo " sudo systemctl status stegasoo # Check status"
echo " sudo systemctl restart stegasoo # Restart"
echo " journalctl -u stegasoo -f # View logs"
echo ""
echo -e "${CYAN}Enjoy Stegasoo!${NC}"
echo ""

View File

@@ -42,7 +42,7 @@ if [[ ! $REPLY =~ ^[Yy]$ ]]; then
exit 1 exit 1
fi fi
echo -e "${GREEN}[1/8]${NC} Removing WiFi credentials..." echo -e "${GREEN}[1/9]${NC} Removing WiFi credentials..."
if [ -f /etc/wpa_supplicant/wpa_supplicant.conf ]; then if [ -f /etc/wpa_supplicant/wpa_supplicant.conf ]; then
cat > /etc/wpa_supplicant/wpa_supplicant.conf << 'EOF' cat > /etc/wpa_supplicant/wpa_supplicant.conf << 'EOF'
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
@@ -60,7 +60,7 @@ else
echo " No wpa_supplicant.conf found" echo " No wpa_supplicant.conf found"
fi fi
echo -e "${GREEN}[2/8]${NC} Removing SSH authorized keys..." echo -e "${GREEN}[2/9]${NC} Removing SSH authorized keys..."
for user_home in /home/*; do for user_home in /home/*; do
if [ -d "$user_home/.ssh" ]; then if [ -d "$user_home/.ssh" ]; then
rm -f "$user_home/.ssh/authorized_keys" rm -f "$user_home/.ssh/authorized_keys"
@@ -70,7 +70,7 @@ for user_home in /home/*; do
done done
rm -f /root/.ssh/authorized_keys /root/.ssh/known_hosts 2>/dev/null || true rm -f /root/.ssh/authorized_keys /root/.ssh/known_hosts 2>/dev/null || true
echo -e "${GREEN}[3/8]${NC} Clearing bash history..." echo -e "${GREEN}[3/9]${NC} Clearing bash history..."
for user_home in /home/*; do for user_home in /home/*; do
rm -f "$user_home/.bash_history" rm -f "$user_home/.bash_history"
rm -f "$user_home/.python_history" rm -f "$user_home/.python_history"
@@ -78,7 +78,7 @@ done
rm -f /root/.bash_history /root/.python_history 2>/dev/null || true rm -f /root/.bash_history /root/.python_history 2>/dev/null || true
history -c history -c
echo -e "${GREEN}[4/8]${NC} Removing Stegasoo user data..." echo -e "${GREEN}[4/9]${NC} Removing Stegasoo user data..."
# Remove auth database (users create their own admin on first run) # Remove auth database (users create their own admin on first run)
rm -rf /home/*/stegasoo/frontends/web/instance/ rm -rf /home/*/stegasoo/frontends/web/instance/
# Remove SSL certs (will be regenerated) # Remove SSL certs (will be regenerated)
@@ -87,7 +87,50 @@ rm -rf /home/*/stegasoo/frontends/web/certs/
rm -f /home/*/stegasoo/frontends/web/.env rm -f /home/*/stegasoo/frontends/web/.env
echo " Stegasoo instance data cleared" echo " Stegasoo instance data cleared"
echo -e "${GREEN}[5/8]${NC} Clearing logs..." echo -e "${GREEN}[5/9]${NC} Setting up first-boot wizard..."
# Find stegasoo install directory
STEGASOO_DIR=$(ls -d /home/*/stegasoo 2>/dev/null | head -1)
STEGASOO_USER=$(stat -c '%U' "$STEGASOO_DIR" 2>/dev/null || echo "pi")
if [ -n "$STEGASOO_DIR" ] && [ -f "$STEGASOO_DIR/rpi/stegasoo-wizard.sh" ]; then
# Install the profile.d hook
cp "$STEGASOO_DIR/rpi/stegasoo-wizard.sh" /etc/profile.d/stegasoo-wizard.sh
chmod 755 /etc/profile.d/stegasoo-wizard.sh
echo " Installed first-boot wizard hook"
# Create the first-boot flag
touch /etc/stegasoo-first-boot
echo " Created first-boot flag"
# Reset systemd service to defaults (wizard will reconfigure)
cat > /etc/systemd/system/stegasoo.service <<EOF
[Unit]
Description=Stegasoo Web UI
After=network.target
[Service]
Type=simple
User=$STEGASOO_USER
WorkingDirectory=$STEGASOO_DIR/frontends/web
Environment="PATH=$STEGASOO_DIR/venv/bin:/usr/bin"
Environment="STEGASOO_AUTH_ENABLED=true"
Environment="STEGASOO_HTTPS_ENABLED=false"
Environment="STEGASOO_PORT=5000"
Environment="STEGASOO_CHANNEL_KEY="
ExecStart=$STEGASOO_DIR/venv/bin/python app.py
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
echo " Reset service to defaults"
else
echo " ${YELLOW}Warning: Stegasoo not found, skipping wizard setup${NC}"
fi
echo -e "${GREEN}[6/9]${NC} Clearing logs..."
journalctl --rotate journalctl --rotate
journalctl --vacuum-time=1s journalctl --vacuum-time=1s
rm -rf /var/log/*.log /var/log/*.gz /var/log/*.[0-9] rm -rf /var/log/*.log /var/log/*.gz /var/log/*.[0-9]
@@ -96,17 +139,17 @@ rm -rf /var/log/journal/*
find /var/log -type f -name "*.log" -delete 2>/dev/null || true find /var/log -type f -name "*.log" -delete 2>/dev/null || true
echo " Logs cleared" echo " Logs cleared"
echo -e "${GREEN}[6/8]${NC} Clearing temporary files..." echo -e "${GREEN}[7/9]${NC} Clearing temporary files..."
rm -rf /tmp/* rm -rf /tmp/*
rm -rf /var/tmp/* rm -rf /var/tmp/*
echo " Temp files cleared" echo " Temp files cleared"
echo -e "${GREEN}[7/8]${NC} Clearing package cache..." echo -e "${GREEN}[8/9]${NC} Clearing package cache..."
apt-get clean apt-get clean
rm -rf /var/cache/apt/archives/* rm -rf /var/cache/apt/archives/*
echo " Package cache cleared" echo " Package cache cleared"
echo -e "${GREEN}[8/8]${NC} Final cleanup..." echo -e "${GREEN}[9/9]${NC} Final cleanup..."
# Remove this script's evidence # Remove this script's evidence
rm -f /root/.bash_history rm -f /root/.bash_history
sync sync

11
rpi/stegasoo-wizard.sh Executable file
View File

@@ -0,0 +1,11 @@
#!/bin/bash
# Stegasoo First Boot Wizard Trigger
# This file goes in /etc/profile.d/ and runs the wizard on first login
if [ -f /etc/stegasoo-first-boot ] && [ -f /home/*/stegasoo/rpi/first-boot-wizard.sh ]; then
# Find the wizard script
WIZARD=$(ls /home/*/stegasoo/rpi/first-boot-wizard.sh 2>/dev/null | head -1)
if [ -n "$WIZARD" ]; then
bash "$WIZARD"
fi
fi