🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
9.1 KiB
Dangerous Pi - Image Build Guide
Complete guide for building custom Raspberry Pi OS images with pi-gen.
Prerequisites
System Requirements
- Linux or macOS (tested on Apple Silicon)
- Docker (or alternatives like Podman)
- 8GB+ RAM recommended
- 20GB+ free disk space
Install Docker
# macOS
brew install docker
# Ubuntu/Debian
sudo apt-get install docker.io
# Or use Docker Desktop
Setup
1. Clone pi-gen
# Clone the official pi-gen repository
git clone https://github.com/RPi-Distro/pi-gen.git
cd pi-gen
# Checkout arm64 branch (for Pi Zero 2 W)
git checkout arm64
2. Copy Dangerous Pi Stage
# From your dangerous-pi repository
cp -r /path/to/dangerous-pi/pi-gen/stageDTPM3 /path/to/pi-gen/
cp /path/to/dangerous-pi/pi-gen/config /path/to/pi-gen/config
Build Methods
Method 1: Full Build (Recommended for First Time)
Builds a complete Raspberry Pi OS image with all your customizations.
cd /path/to/pi-gen
# Start full build
sudo ./build.sh
Build Time: 1-2 hours
Output: Complete bootable image in deploy/ directory
Method 2: Quick Build (Development)
For rapid iteration when testing changes:
cd /path/to/pi-gen
# Only rebuild your custom stage
CONTINUE=1 STAGE=stageDTPM3 sudo ./build.sh
Build Time: 5-10 minutes Use Case: Testing Dangerous Pi code changes only
Method 3: Using Docker (Recommended)
Clean, isolated build environment:
cd /path/to/pi-gen
# Build in Docker container
./docker-build.sh
Advantages:
- No host system pollution
- Consistent build environment
- Works on macOS
Build Script Helper
Use the provided helper script for easier builds:
# From dangerous-pi directory
./build-image.sh full # Full build
./build-image.sh quick # Incremental build
./build-image.sh test # Validate scripts
Note: Update the PI_GEN_DIR variable in build-image.sh to point to your pi-gen installation.
Configuration
Your build configuration is defined in pi-gen/config:
IMG_NAME="Proxmark3" # Image name
RELEASE="trixie" # Debian Trixie
TARGET_HOSTNAME="Proxmark3" # Hostname
FIRST_USER_NAME="dt" # Default user
FIRST_USER_PASS="proxmark3" # Default password
ENABLE_SSH=1 # SSH enabled
STAGE_LIST="stage0 stage1 stage2 stageDTPM3"
Customizing the Build
Edit config to customize:
Change hostname:
TARGET_HOSTNAME="dangerous-pi"
Change default credentials:
FIRST_USER_NAME="admin"
FIRST_USER_PASS="your-secure-password"
Change WiFi country:
WPA_COUNTRY="GB" # UK
Skip stages (for faster builds):
# Only include your custom stage (requires base stages)
STAGE_LIST="stage0 stage1 stage2 stageDTPM3"
Stage Architecture
Your custom stageDTPM3 includes 4 sub-stages that run in order:
Stage 01: Proxmark3
- Compiles Proxmark3 firmware and client
- Installs to
/usr/local/bin
Stage 02: RaspAP (Wireless AP)
- Configures WiFi access point
- Default SSID:
raspi-webgui - Default password:
ChangeMe
Stage 03: ttyd (Web Terminal)
- Installs web-based terminal
- Accessible at
http://10.3.141.1:8000/
Stage 04: Dangerous Pi
- Installs your custom application
- Location:
/opt/dangerous-pi - Auto-starts on boot via systemd
Build Output
After successful build:
pi-gen/
└── deploy/
├── image_2025-11-26-Proxmark3.img # Bootable image
├── image_2025-11-26-Proxmark3.img.zip # Compressed image
└── build.log # Build logs
Flashing the Image
Using Balena Etcher (Easiest)
- Download Balena Etcher
- Select your
.imgor.zipfile - Select your SD card
- Click "Flash!"
Using dd (Linux/macOS)
# Find your SD card device
lsblk # Linux
diskutil list # macOS
# Flash image (replace /dev/sdX with your device)
sudo dd if=deploy/image_2025-11-26-Proxmark3.img of=/dev/sdX bs=4M status=progress
# Sync and eject
sync
sudo eject /dev/sdX
Warning: Double-check the device path! Using the wrong device will destroy data.
Testing the Image
1. Boot the Pi
- Insert SD card into Raspberry Pi Zero 2 W
- Connect Proxmark3 via USB
- Power on the Pi
- Wait ~1 minute for first boot
2. Connect to Access Point
SSID: raspi-webgui
Password: ChangeMe
Gateway: 10.3.141.1
3. Run Automated Tests
# From your development machine
./test-image.sh 10.3.141.1
This will verify:
- SSH connectivity
- Service status
- Hardware access
- API endpoints
- Python dependencies
4. Manual Verification
SSH into device:
ssh dt@10.3.141.1
# Password: proxmark3
Check service status:
sudo systemctl status dangerous-pi.service
sudo journalctl -u dangerous-pi.service -f
Test API:
curl http://10.3.141.1:8000/api/health
curl http://10.3.141.1:8000/api/system/info
Access web interface:
- Frontend: http://10.3.141.1:3000 (if frontend running)
- Backend: http://10.3.141.1:8000/docs (API docs)
- RaspAP: http://10.3.141.1/ (WiFi management)
- ttyd: http://10.3.141.1:8000/ (web terminal - port conflict!)
Troubleshooting
Build Fails - Permission Denied
# Ensure scripts are executable
chmod +x pi-gen/stageDTPM3/*/00-*.sh
Build Fails - Docker Issues
# Ensure Docker is running
docker ps
# Clean up old containers
docker system prune -a
Build Fails - Disk Space
# Check available space (need 20GB+)
df -h
# Clean up old builds
sudo rm -rf pi-gen/work pi-gen/deploy
Service Not Starting After Boot
Check logs:
ssh dt@10.3.141.1
sudo journalctl -u dangerous-pi.service -n 50
Common issues:
- Port conflict with ttyd (see PORT_CONFLICT.md)
- Missing Python dependencies
- Incorrect file permissions
- Environment variables not set
Quick fix:
# Restart service
sudo systemctl restart dangerous-pi.service
# Check status
sudo systemctl status dangerous-pi.service
Image Too Large
Your current build should be ~600-700MB. If it's larger:
Check what's using space:
ssh dt@10.3.141.1
du -sh /* | sort -h | tail -10
Already implemented optimizations:
- ✅ Package cache cleanup (
apt-get clean) - ✅ Pip cache cleanup (
pip3 cache purge) - ✅ Auto-remove unused packages
Can't Access Hardware (I2C, GPIO, Serial)
Verify groups:
ssh dt@10.3.141.1
groups pi # Should show: i2c bluetooth gpio dialout
If missing:
sudo usermod -a -G i2c,bluetooth,gpio,dialout pi
# Log out and back in
Verify devices exist:
ls -la /dev/i2c* # I2C bus
ls -la /dev/ttyACM* # Proxmark3
Optimization Tips
Faster Builds
- Use incremental builds during development
- Cache compiled binaries from previous builds
- Use Docker for consistent environment
- Skip unnecessary stages in config
Smaller Images
Already implemented in your scripts:
- Package manager cleanup
- No development packages
- No man pages
- Pip cache removal
Build Caching
Pi-gen caches build artifacts in work/ directory:
# Keep work directory for incremental builds
# Clean when you want fresh build
sudo rm -rf work/
Version Management
Set version before building:
echo "1.0.0" > /path/to/dangerous-pi/VERSION
This version will be copied into the image at /opt/dangerous-pi/VERSION.
Advanced: Custom Stage Development
Script Execution Order
For each stage directory (NN-name/), pi-gen runs:
00-run.sh- Host-side preparation (optional)00-run-chroot.sh- Chroot installation (required)01-run-chroot.sh- Additional chroot tasks (optional)02-run-chroot.sh- More chroot tasks (optional)
Adding New Stage
cd pi-gen/stageDTPM3
# Create new stage
mkdir 05-my-feature
cd 05-my-feature
# Create installation script
cat > 00-run-chroot.sh << 'EOF'
#!/bin/bash -e
echo "Installing my feature..."
apt-get install -y my-package
EOF
chmod +x 00-run-chroot.sh
Stage Best Practices
- Use
#!/bin/bash -e- Exit on error - Use
$ROOTFS_DIRin 00-run.sh for paths - Clean up package caches at end
- Set ownership for files (chown pi:pi)
- Document in README.md what stage does
Next Steps
- First build: Run full build to create base image
- Test hardware: Flash to SD card and test on Pi Zero 2 W
- Iterate: Make changes and use quick builds
- Document: Update configuration for your needs
- Deploy: Create final production image
Resources
Support
For issues with:
- pi-gen: Check official pi-gen repository
- Dangerous Pi: Review logs with
journalctl -u dangerous-pi - Proxmark3: See Proxmark3 documentation
- RaspAP: Visit RaspAP website
Happy building! 🚀