Rewrite first-boot wizard using gum TUI
Replace whiptail with gum (Charm.sh) for beautiful, modern TUI. Features spinners, styled boxes, colored text, and reliable prompts. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -6,7 +6,8 @@
|
|||||||
# This script is triggered by /etc/profile.d/stegasoo-wizard.sh
|
# This script is triggered by /etc/profile.d/stegasoo-wizard.sh
|
||||||
# After completion, it removes itself to prevent re-running
|
# After completion, it removes itself to prevent re-running
|
||||||
#
|
#
|
||||||
# Uses whiptail for reliable TUI dialogs (pre-installed on Pi OS)
|
# Uses gum (Charm.sh) for beautiful TUI - install with:
|
||||||
|
# sudo apt install gum OR go install github.com/charmbracelet/gum@latest
|
||||||
#
|
#
|
||||||
|
|
||||||
# Configuration
|
# Configuration
|
||||||
@@ -14,32 +15,39 @@ INSTALL_DIR="/opt/stegasoo"
|
|||||||
FLAG_FILE="/etc/stegasoo-first-boot"
|
FLAG_FILE="/etc/stegasoo-first-boot"
|
||||||
PROFILE_HOOK="/etc/profile.d/stegasoo-wizard.sh"
|
PROFILE_HOOK="/etc/profile.d/stegasoo-wizard.sh"
|
||||||
|
|
||||||
# Terminal dimensions
|
|
||||||
TERM_HEIGHT=$(tput lines 2>/dev/null || echo 24)
|
|
||||||
TERM_WIDTH=$(tput cols 2>/dev/null || echo 80)
|
|
||||||
BOX_HEIGHT=$((TERM_HEIGHT - 4))
|
|
||||||
BOX_WIDTH=$((TERM_WIDTH - 4))
|
|
||||||
[ $BOX_HEIGHT -gt 20 ] && BOX_HEIGHT=20
|
|
||||||
[ $BOX_WIDTH -gt 70 ] && BOX_WIDTH=70
|
|
||||||
|
|
||||||
# Check if this is first boot
|
# Check if this is first boot
|
||||||
if [ ! -f "$FLAG_FILE" ]; then
|
if [ ! -f "$FLAG_FILE" ]; then
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Check for gum, fall back to basic prompts if not available
|
||||||
|
if ! command -v gum &>/dev/null; then
|
||||||
|
echo "Error: gum not found. Install with: sudo apt install gum"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
clear
|
||||||
|
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
# Welcome
|
# Welcome
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
|
|
||||||
whiptail --title "Stegasoo First Boot Wizard" --msgbox "\
|
gum style \
|
||||||
Welcome to Stegasoo!
|
--border double \
|
||||||
|
--border-foreground 212 \
|
||||||
|
--padding "1 2" \
|
||||||
|
--margin "1" \
|
||||||
|
--align center \
|
||||||
|
"🦕 STEGASOO" \
|
||||||
|
"" \
|
||||||
|
"First Boot Wizard"
|
||||||
|
|
||||||
This wizard will help you configure your Stegasoo server.
|
echo ""
|
||||||
|
gum style --foreground 245 "This wizard will help you configure your Stegasoo server."
|
||||||
|
gum style --foreground 245 "You can reconfigure later by editing /etc/systemd/system/stegasoo.service"
|
||||||
|
echo ""
|
||||||
|
|
||||||
You can reconfigure later by editing:
|
gum confirm "Ready to begin setup?" || exit 0
|
||||||
/etc/systemd/system/stegasoo.service
|
|
||||||
|
|
||||||
Press OK to begin setup..." $BOX_HEIGHT $BOX_WIDTH
|
|
||||||
|
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
# Configuration Variables
|
# Configuration Variables
|
||||||
@@ -53,88 +61,126 @@ CHANNEL_KEY=""
|
|||||||
# Step 1: HTTPS Configuration
|
# Step 1: HTTPS Configuration
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
|
|
||||||
if whiptail --title "Step 1 of 3: HTTPS Configuration" --yesno "\
|
clear
|
||||||
HTTPS encrypts all traffic between your browser and this server using a self-signed certificate.
|
gum style \
|
||||||
|
--foreground 212 --bold \
|
||||||
|
"Step 1 of 3: HTTPS Configuration"
|
||||||
|
echo ""
|
||||||
|
|
||||||
NOTE: Your browser will show a security warning because the certificate is self-signed. This is normal for home networks.
|
gum style --foreground 245 "\
|
||||||
|
HTTPS encrypts all traffic between your browser and this server
|
||||||
|
using a self-signed certificate.
|
||||||
|
|
||||||
Enable HTTPS? (Recommended)" $BOX_HEIGHT $BOX_WIDTH; then
|
NOTE: Your browser will show a security warning because the
|
||||||
|
certificate is self-signed. This is normal for home networks."
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
if gum confirm "Enable HTTPS?" --default=true; then
|
||||||
ENABLE_HTTPS="true"
|
ENABLE_HTTPS="true"
|
||||||
|
gum style --foreground 82 "✓ HTTPS will be enabled"
|
||||||
|
else
|
||||||
|
gum style --foreground 214 "→ Using HTTP (unencrypted)"
|
||||||
fi
|
fi
|
||||||
|
sleep 0.5
|
||||||
|
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
# Step 2: Port Configuration (only if HTTPS)
|
# Step 2: Port Configuration (only if HTTPS)
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
|
|
||||||
if [ "$ENABLE_HTTPS" = "true" ]; then
|
if [ "$ENABLE_HTTPS" = "true" ]; then
|
||||||
if whiptail --title "Step 2 of 3: Port Configuration" --yesno "\
|
clear
|
||||||
The standard HTTPS port is 443, which means you can access Stegasoo without specifying a port in the URL.
|
gum style \
|
||||||
|
--foreground 212 --bold \
|
||||||
|
"Step 2 of 3: Port Configuration"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
gum style --foreground 245 "\
|
||||||
|
The standard HTTPS port is 443, which means you can access
|
||||||
|
Stegasoo without specifying a port in the URL.
|
||||||
|
|
||||||
Port 443: https://stegasoo.local
|
Port 443: https://stegasoo.local
|
||||||
Port 5000: https://stegasoo.local:5000
|
Port 5000: https://stegasoo.local:5000
|
||||||
|
|
||||||
NOTE: Port 443 requires an iptables redirect rule.
|
NOTE: Port 443 requires an iptables redirect rule."
|
||||||
|
echo ""
|
||||||
|
|
||||||
Use standard port 443? (Cleaner URLs)" $BOX_HEIGHT $BOX_WIDTH; then
|
if gum confirm "Use standard port 443?" --default=true; then
|
||||||
USE_PORT_443="true"
|
USE_PORT_443="true"
|
||||||
|
gum style --foreground 82 "✓ Port 443 will be configured"
|
||||||
|
else
|
||||||
|
gum style --foreground 214 "→ Using port 5000"
|
||||||
fi
|
fi
|
||||||
|
sleep 0.5
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
# Step 3: Channel Key Configuration
|
# Step 3: Channel Key Configuration
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
|
|
||||||
if whiptail --title "Step 3 of 3: Channel Key" --yesno "\
|
clear
|
||||||
|
gum style \
|
||||||
|
--foreground 212 --bold \
|
||||||
|
"Step 3 of 3: Channel Key Configuration"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
gum style --foreground 245 "\
|
||||||
A channel key creates a private encoding channel.
|
A channel key creates a private encoding channel.
|
||||||
|
|
||||||
WITHOUT a key: Anyone with Stegasoo can decode your images
|
WITHOUT a key: Anyone with Stegasoo can decode your images
|
||||||
WITH a key: Only people with YOUR key can decode
|
WITH a key: Only people with YOUR key can decode
|
||||||
|
|
||||||
This is useful if you want to share encoded images only with specific people (family, team, etc).
|
This is useful if you want to share encoded images only with
|
||||||
|
specific people (family, team, etc)."
|
||||||
|
echo ""
|
||||||
|
|
||||||
Generate a private channel key?" $BOX_HEIGHT $BOX_WIDTH --defaultno; then
|
if gum confirm "Generate a private channel key?" --default=false; then
|
||||||
|
echo ""
|
||||||
# Generate key (use temp file to preserve across subshell)
|
CHANNEL_KEY=$(gum spin --spinner dot --title "Generating channel key..." -- \
|
||||||
KEY_FILE=$(mktemp)
|
bash -c "source '$INSTALL_DIR/venv/bin/activate' 2>/dev/null && python -c \"from stegasoo.channel import generate_channel_key; print(generate_channel_key())\"")
|
||||||
{
|
|
||||||
echo 50
|
|
||||||
source "$INSTALL_DIR/venv/bin/activate" 2>/dev/null
|
|
||||||
python -c "from stegasoo.channel import generate_channel_key; print(generate_channel_key())" > "$KEY_FILE" 2>/dev/null
|
|
||||||
echo 100
|
|
||||||
} | whiptail --title "Generating Key" --gauge "Generating channel key..." 6 50 0
|
|
||||||
|
|
||||||
CHANNEL_KEY=$(cat "$KEY_FILE" 2>/dev/null)
|
|
||||||
rm -f "$KEY_FILE"
|
|
||||||
|
|
||||||
if [ -n "$CHANNEL_KEY" ]; then
|
if [ -n "$CHANNEL_KEY" ]; then
|
||||||
whiptail --title "Channel Key Generated" --msgbox "\
|
echo ""
|
||||||
Your private channel key:
|
gum style --foreground 82 "✓ Channel key generated!"
|
||||||
|
echo ""
|
||||||
$CHANNEL_KEY
|
gum style \
|
||||||
|
--border rounded \
|
||||||
*** IMPORTANT: Write down or copy this key NOW! ***
|
--border-foreground 226 \
|
||||||
|
--padding "1 2" \
|
||||||
You'll need to share it with anyone who should decode your images. This key won't be shown again after you press OK." $BOX_HEIGHT $BOX_WIDTH
|
--foreground 226 --bold \
|
||||||
|
"$CHANNEL_KEY"
|
||||||
|
echo ""
|
||||||
|
gum style --foreground 196 --bold \
|
||||||
|
"*** IMPORTANT: Write down or copy this key NOW! ***"
|
||||||
|
gum style --foreground 196 \
|
||||||
|
"You'll need to share it with anyone who should decode" \
|
||||||
|
"your images. This key won't be shown again."
|
||||||
|
echo ""
|
||||||
|
gum confirm "I've saved the key" --default=true --affirmative="Continue" --negative=""
|
||||||
else
|
else
|
||||||
whiptail --title "Error" --msgbox "Failed to generate channel key. Using public mode." 8 50
|
gum style --foreground 196 "✗ Failed to generate key. Using public mode."
|
||||||
CHANNEL_KEY=""
|
CHANNEL_KEY=""
|
||||||
|
sleep 1
|
||||||
fi
|
fi
|
||||||
|
else
|
||||||
|
gum style --foreground 214 "→ Using public mode"
|
||||||
|
sleep 0.5
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
# Apply Configuration
|
# Apply Configuration
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
|
|
||||||
{
|
clear
|
||||||
echo 10
|
gum style \
|
||||||
echo "XXX"
|
--foreground 212 --bold \
|
||||||
echo "Updating systemd service..."
|
"Applying Configuration..."
|
||||||
echo "XXX"
|
echo ""
|
||||||
|
|
||||||
# Find the stegasoo user (whoever owns the install dir)
|
# Find the stegasoo user (whoever owns the install dir)
|
||||||
STEGASOO_USER=$(stat -c '%U' "$INSTALL_DIR" 2>/dev/null || echo "pi")
|
STEGASOO_USER=$(stat -c '%U' "$INSTALL_DIR" 2>/dev/null || echo "pi")
|
||||||
|
|
||||||
sudo tee /etc/systemd/system/stegasoo.service >/dev/null <<EOF
|
gum spin --spinner dot --title "Updating systemd service..." -- bash -c "
|
||||||
|
sudo tee /etc/systemd/system/stegasoo.service >/dev/null <<EOF
|
||||||
[Unit]
|
[Unit]
|
||||||
Description=Stegasoo Web UI
|
Description=Stegasoo Web UI
|
||||||
After=network.target
|
After=network.target
|
||||||
@@ -143,11 +189,11 @@ After=network.target
|
|||||||
Type=simple
|
Type=simple
|
||||||
User=$STEGASOO_USER
|
User=$STEGASOO_USER
|
||||||
WorkingDirectory=$INSTALL_DIR/frontends/web
|
WorkingDirectory=$INSTALL_DIR/frontends/web
|
||||||
Environment="PATH=$INSTALL_DIR/venv/bin:/usr/bin"
|
Environment=\"PATH=$INSTALL_DIR/venv/bin:/usr/bin\"
|
||||||
Environment="STEGASOO_AUTH_ENABLED=true"
|
Environment=\"STEGASOO_AUTH_ENABLED=true\"
|
||||||
Environment="STEGASOO_HTTPS_ENABLED=$ENABLE_HTTPS"
|
Environment=\"STEGASOO_HTTPS_ENABLED=$ENABLE_HTTPS\"
|
||||||
Environment="STEGASOO_PORT=5000"
|
Environment=\"STEGASOO_PORT=5000\"
|
||||||
Environment="STEGASOO_CHANNEL_KEY=$CHANNEL_KEY"
|
Environment=\"STEGASOO_CHANNEL_KEY=$CHANNEL_KEY\"
|
||||||
ExecStart=$INSTALL_DIR/venv/bin/python app.py
|
ExecStart=$INSTALL_DIR/venv/bin/python app.py
|
||||||
Restart=on-failure
|
Restart=on-failure
|
||||||
RestartSec=5
|
RestartSec=5
|
||||||
@@ -155,24 +201,19 @@ RestartSec=5
|
|||||||
[Install]
|
[Install]
|
||||||
WantedBy=multi-user.target
|
WantedBy=multi-user.target
|
||||||
EOF
|
EOF
|
||||||
|
"
|
||||||
|
gum style --foreground 82 "✓ Service configured"
|
||||||
|
|
||||||
echo 30
|
# Setup port 443 if requested
|
||||||
|
if [ "$USE_PORT_443" = "true" ]; then
|
||||||
# Setup port 443 if requested
|
gum spin --spinner dot --title "Setting up port 443 redirect..." -- bash -c "
|
||||||
if [ "$USE_PORT_443" = "true" ]; then
|
|
||||||
echo "XXX"
|
|
||||||
echo "Setting up port 443 redirect..."
|
|
||||||
echo "XXX"
|
|
||||||
|
|
||||||
if ! command -v iptables &>/dev/null; then
|
if ! command -v iptables &>/dev/null; then
|
||||||
sudo apt-get install -y iptables >/dev/null 2>&1
|
sudo apt-get install -y iptables >/dev/null 2>&1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ! sudo iptables -t nat -C PREROUTING -p tcp --dport 443 -j REDIRECT --to-port 5000 2>/dev/null; then
|
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
|
sudo iptables -t nat -A PREROUTING -p tcp --dport 443 -j REDIRECT --to-port 5000
|
||||||
fi
|
fi
|
||||||
sudo sh -c 'iptables-save > /etc/iptables.rules'
|
sudo sh -c 'iptables-save > /etc/iptables.rules'
|
||||||
|
|
||||||
sudo tee /etc/systemd/system/iptables-restore.service >/dev/null <<EOF
|
sudo tee /etc/systemd/system/iptables-restore.service >/dev/null <<EOF
|
||||||
[Unit]
|
[Unit]
|
||||||
Description=Restore iptables rules
|
Description=Restore iptables rules
|
||||||
@@ -186,35 +227,35 @@ ExecStart=/sbin/iptables-restore /etc/iptables.rules
|
|||||||
WantedBy=multi-user.target
|
WantedBy=multi-user.target
|
||||||
EOF
|
EOF
|
||||||
sudo systemctl enable iptables-restore.service >/dev/null 2>&1
|
sudo systemctl enable iptables-restore.service >/dev/null 2>&1
|
||||||
fi
|
"
|
||||||
|
gum style --foreground 82 "✓ Port 443 redirect configured"
|
||||||
|
fi
|
||||||
|
|
||||||
echo 50
|
gum spin --spinner dot --title "Reloading systemd..." -- sudo systemctl daemon-reload
|
||||||
echo "XXX"
|
gum style --foreground 82 "✓ Systemd reloaded"
|
||||||
echo "Reloading systemd..."
|
|
||||||
echo "XXX"
|
|
||||||
sudo systemctl daemon-reload
|
|
||||||
|
|
||||||
echo 70
|
gum spin --spinner dot --title "Starting Stegasoo..." -- bash -c "sudo systemctl restart stegasoo && sleep 2"
|
||||||
echo "XXX"
|
|
||||||
echo "Starting Stegasoo..."
|
|
||||||
echo "XXX"
|
|
||||||
sudo systemctl restart stegasoo
|
|
||||||
sleep 2
|
|
||||||
|
|
||||||
echo 90
|
if systemctl is-active --quiet stegasoo; then
|
||||||
echo "XXX"
|
gum style --foreground 82 "✓ Stegasoo started successfully"
|
||||||
echo "Cleaning up wizard..."
|
else
|
||||||
echo "XXX"
|
gum style --foreground 196 "✗ Failed to start (check: journalctl -u stegasoo)"
|
||||||
sudo rm -f "$FLAG_FILE"
|
fi
|
||||||
sudo rm -f "$PROFILE_HOOK"
|
|
||||||
|
|
||||||
echo 100
|
gum spin --spinner dot --title "Cleaning up wizard..." -- bash -c "
|
||||||
} | whiptail --title "Applying Configuration" --gauge "Starting..." 6 50 0
|
sudo rm -f '$FLAG_FILE'
|
||||||
|
sudo rm -f '$PROFILE_HOOK'
|
||||||
|
"
|
||||||
|
gum style --foreground 82 "✓ Wizard complete"
|
||||||
|
|
||||||
|
sleep 1
|
||||||
|
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
# Final Summary
|
# Final Summary
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
|
|
||||||
|
clear
|
||||||
|
|
||||||
PI_IP=$(hostname -I | awk '{print $1}')
|
PI_IP=$(hostname -I | awk '{print $1}')
|
||||||
HOSTNAME=$(hostname)
|
HOSTNAME=$(hostname)
|
||||||
|
|
||||||
@@ -232,49 +273,42 @@ else
|
|||||||
ACCESS_URL_LOCAL="http://$HOSTNAME.local:5000"
|
ACCESS_URL_LOCAL="http://$HOSTNAME.local:5000"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Build channel key message
|
gum style \
|
||||||
CHANNEL_MSG=""
|
--border double \
|
||||||
|
--border-foreground 82 \
|
||||||
|
--padding "1 2" \
|
||||||
|
--margin "1" \
|
||||||
|
--align center \
|
||||||
|
"🦕 STEGASOO" \
|
||||||
|
"" \
|
||||||
|
"Setup Complete!"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
gum style --foreground 82 --bold "Access URL:"
|
||||||
|
gum style --foreground 226 " $ACCESS_URL"
|
||||||
|
gum style --foreground 245 " $ACCESS_URL_LOCAL (if mDNS works)"
|
||||||
|
echo ""
|
||||||
|
|
||||||
if [ -n "$CHANNEL_KEY" ]; then
|
if [ -n "$CHANNEL_KEY" ]; then
|
||||||
CHANNEL_MSG="
|
gum style --foreground 82 --bold "Channel Key:"
|
||||||
Channel Key: $CHANNEL_KEY"
|
gum style --foreground 226 " $CHANNEL_KEY"
|
||||||
|
echo ""
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Check if service started
|
gum style --foreground 82 --bold "First Steps:"
|
||||||
if systemctl is-active --quiet stegasoo; then
|
gum style --foreground 255 \
|
||||||
SERVICE_STATUS="Running"
|
" 1. Open the URL above in your browser" \
|
||||||
else
|
" 2. Accept the security warning (self-signed cert)" \
|
||||||
SERVICE_STATUS="Failed to start (check: journalctl -u stegasoo)"
|
" 3. Create your admin account" \
|
||||||
fi
|
" 4. Start encoding secret messages!"
|
||||||
|
|
||||||
whiptail --title "Setup Complete!" --msgbox "\
|
|
||||||
Your Stegasoo server is ready!
|
|
||||||
|
|
||||||
Access URL:
|
|
||||||
$ACCESS_URL
|
|
||||||
$ACCESS_URL_LOCAL (if mDNS works)
|
|
||||||
|
|
||||||
Service Status: $SERVICE_STATUS
|
|
||||||
$CHANNEL_MSG
|
|
||||||
|
|
||||||
First Steps:
|
|
||||||
1. Open the URL above in your browser
|
|
||||||
2. Accept the security warning (self-signed cert)
|
|
||||||
3. Create your admin account
|
|
||||||
4. Start encoding secret messages!
|
|
||||||
|
|
||||||
Useful Commands:
|
|
||||||
sudo systemctl status stegasoo # Check status
|
|
||||||
sudo systemctl restart stegasoo # Restart
|
|
||||||
journalctl -u stegasoo -f # View logs
|
|
||||||
|
|
||||||
Enjoy Stegasoo!" $((BOX_HEIGHT + 4)) $BOX_WIDTH
|
|
||||||
|
|
||||||
clear
|
|
||||||
echo ""
|
echo ""
|
||||||
echo "Stegasoo setup complete!"
|
|
||||||
|
gum style --foreground 82 --bold "Useful Commands:"
|
||||||
|
gum style --foreground 245 \
|
||||||
|
" sudo systemctl status stegasoo # Check status" \
|
||||||
|
" sudo systemctl restart stegasoo # Restart" \
|
||||||
|
" journalctl -u stegasoo -f # View logs"
|
||||||
echo ""
|
echo ""
|
||||||
echo "Access your server at: $ACCESS_URL"
|
|
||||||
if [ -n "$CHANNEL_KEY" ]; then
|
gum style --foreground 212 --bold "Enjoy Stegasoo! 🦕"
|
||||||
echo "Channel Key: $CHANNEL_KEY"
|
|
||||||
fi
|
|
||||||
echo ""
|
echo ""
|
||||||
|
|||||||
Reference in New Issue
Block a user