IMPORTANT UPDATE: For auto-start configuration on boot, see AUTOSTART_SETUP.md which documents the
mount --bindsolution for DD-WRT's read-only filesystem.
The automated deployment script (deploy.sh) provides a complete, unattended installation of EmergencyBox on DD-WRT routers. It handles all critical configuration issues including timezone data, SQLite3 extensions, and PHP configuration.
Run from your computer with SSH access to the router:
cd /path/to/emergencybox
chmod +x deploy.sh
./deploy.sh 192.168.1.1 rootFor routers without SSH but with telnet access:
python3 router_telnet.py "$(cat deploy.sh)"Copy the script to the router and execute directly:
scp deploy.sh root@192.168.1.1:/tmp/
ssh root@192.168.1.1
cd /tmp
./deploy.shThe script performs the following steps automatically:
- Verifies router connectivity
- Checks USB drive availability at
/opt - Validates available storage space
- Detects existing Entware installation
- Detects router architecture (ARMv7 for RT-AC68U)
- Downloads and installs Entware package manager
- Updates package repository lists
- Installs PHP 8 with required extensions:
php8,php8-cgi,php8-cliphp8-mod-sqlite3(CRITICAL)php8-mod-session,php8-mod-jsonphp8-mod-ctype,php8-mod-fileinfo
- Installs Lighttpd web server with modules
- Installs SQLite3 CLI tools
- Installs timezone data packages
- Installs debugging tools (strace, bash)
Problem: PHP expects timezone data at /usr/share/zoneinfo but Entware installs it to /opt/share/zoneinfo
Solution: The script attempts multiple strategies:
- Try to create symlink (preferred)
- If symlink fails (JFFS2 limitation):
- Remount
/usras read-write - Copy timezone files to correct location
- Remount
/usras read-only
- Remount
- Falls back to TZ environment variable if all else fails
Why This Matters: Without correct timezone data, PHP's date functions will fail, breaking the entire application.
Critical Configurations:
-
extension_dir: Auto-detected from PHP installation
- Usually
/opt/lib/php8 - MUST match actual extension location
- Verified by checking for
sqlite3.so
- Usually
-
PHPRC Environment Variable:
- Set to
/opt/etc(where php.ini lives) - Added to
/opt/etc/profilefor persistence - CRITICAL: Without this, PHP won't find php.ini
- Set to
-
Upload Limits:
upload_max_filesize = 5Gpost_max_size = 5Gmax_execution_time = 600(10 minutes)memory_limit = 256M
-
Extensions Loaded:
extension=sqlite3.so extension=session.so extension=json.so extension=ctype.so extension=fileinfo.so
Critical Settings:
-
FastCGI Environment Variables:
"PHPRC" => "/opt/etc"This ensures PHP-CGI finds the configuration file.
-
Large File Support:
server.max-request-size = 5368709120 # 5GB server.max-write-idle = 600 server.max-read-idle = 600 -
Port Configuration:
- Port 8080 (avoids conflicts with router's web interface on port 80)
-
Init Script:
- Creates
/opt/etc/init.d/S80lighttpd - Provides start/stop/restart/status commands
- Exports PHPRC before starting
- Creates
- Creates directory structure under
/opt/share/www - Copies all web application files
- Creates upload directories with proper permissions:
/emergency,/media,/documents,/general
- Sets permissions (755 for web root, 777 for uploads)
Two methods:
-
Using init_db.php (preferred):
- Runs the PHP initialization script
- Creates all tables with proper schema
-
Manual SQLite (fallback):
- Uses
sqlite3CLI directly - Creates tables if PHP method fails
- Uses
Tables Created:
messages- Chat messages with priority flagsfiles- File metadata with categoriesannouncements- System announcements
- Stops any existing services
- Cleans up stale sockets and PID files
- Starts Lighttpd with proper environment
- Verifies service is running
- Checks port 8080 is listening
The script runs 8 comprehensive tests:
- Lighttpd process running
- PHP-CGI process (spawns on first request)
- Port 8080 listening
- Web root accessible (index.html exists)
- Database file exists and is queryable
- PHP configuration correct and SQLite3 loaded
- HTTP request successful (wget/curl test)
- Upload directory writable
Problem: PHP can't find sqlite3.so even when installed
Solution:
extension_dir = "/opt/lib/php8"
extension=sqlite3.soVerification:
/opt/bin/php -c /opt/etc/php.ini -m | grep sqlite3Problem: PHP error: "Timezone database is corrupt"
Root Cause:
- PHP compiled to look in
/usr/share/zoneinfo - Entware installs to
/opt/share/zoneinfo - JFFS2 filesystem doesn't support symlinks
Solution Hierarchy:
- Symlink (if filesystem supports)
- Copy files after remounting read-write
- Use TZ environment variable
Manual Fix if Script Fails:
# Remount as read-write
mount -o remount,rw /usr
# Copy timezone data
mkdir -p /usr/share/zoneinfo
cp -r /opt/share/zoneinfo/* /usr/share/zoneinfo/
# Remount as read-only
mount -o remount,ro /usrProblem: PHP-CGI can't find php.ini
Solution:
- Set
PHPRC=/opt/etcin lighttpd FastCGI configuration - Export PHPRC in init script
- Add to
/opt/etc/profilefor persistence
Why: PHP searches for php.ini in multiple locations, but on embedded systems, it may not check /opt/etc by default.
Three Components Must Align:
-
PHP (php.ini):
upload_max_filesize = 5G post_max_size = 5G max_execution_time = 600
-
Lighttpd (lighttpd.conf):
server.max-request-size = 5368709120 server.max-write-idle = 600 -
Application (config.php):
define('MAX_FILE_SIZE', 5 * 1024 * 1024 * 1024);
All three must match or uploads will fail at the weakest link.
The script automatically backs up:
- Existing web files to
/tmp/emergencybox_backup_TIMESTAMP/www/ - Existing php.ini
- Existing lighttpd.conf
On error, it attempts to restore from backup.
If automatic rollback fails:
# Stop services
/opt/etc/init.d/S80lighttpd stop
# Restore from backup
BACKUP=/tmp/emergencybox_backup_YYYYMMDD_HHMMSS
cp -r $BACKUP/www/* /opt/share/www/
cp $BACKUP/php.ini /opt/etc/php.ini
cp $BACKUP/lighttpd.conf /opt/etc/lighttpd/lighttpd.conf
# Restart services
/opt/etc/init.d/S80lighttpd startIf you want to prevent rollback (e.g., for debugging):
# Edit deploy.sh and change:
ROLLBACK_ENABLED=falseSymptom: Can't download Entware installer
Solutions:
- Check internet connectivity:
ping 8.8.8.8 - Check DNS:
nslookup google.com - Try alternative mirror
- Manual Entware installation first
Diagnosis:
/opt/bin/php -c /opt/etc/php.ini -m | grep sqlite3
# Should show "sqlite3"If missing:
# Check extension file exists
ls -l /opt/lib/php8/sqlite3.so
# Check extension_dir in php.ini
grep extension_dir /opt/etc/php.ini
# Try loading manually
/opt/bin/php -c /opt/etc/php.ini -r "var_dump(extension_loaded('sqlite3'));"Fix:
# Find actual extension directory
/opt/bin/php -i | grep extension_dir
# Update php.ini with correct path
vi /opt/etc/php.ini
# Change: extension_dir = "/correct/path"Symptom: PHP warnings about timezone database
Manual Fix:
# Check if files exist
ls -l /usr/share/zoneinfo/UTC
# If not, force copy
mount -o remount,rw /usr
mkdir -p /usr/share/zoneinfo
cp -r /opt/share/zoneinfo/* /usr/share/zoneinfo/
mount -o remount,ro /usr
# Or use environment variable
export TZ=UTC
echo 'export TZ=UTC' >> /opt/etc/profileCheck error log:
tail -f /opt/var/log/lighttpd/error.logCommon issues:
-
Config syntax error:
/opt/sbin/lighttpd -t -f /opt/etc/lighttpd/lighttpd.conf
-
Port already in use:
netstat -ln | grep 8080 killall lighttpd -
Missing directories:
mkdir -p /opt/var/log/lighttpd mkdir -p /opt/var/run
-
PHP-CGI not found:
which php-cgi # Should show /opt/bin/php-cgi
Manual creation:
/opt/bin/sqlite3 /opt/share/data/emergencybox.db << 'EOF'
CREATE TABLE IF NOT EXISTS messages (
id INTEGER PRIMARY KEY AUTOINCREMENT,
username TEXT DEFAULT NULL,
message TEXT NOT NULL,
priority INTEGER DEFAULT 0,
file_id INTEGER DEFAULT NULL,
timestamp DATETIME DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE IF NOT EXISTS files (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
path TEXT NOT NULL,
category TEXT NOT NULL,
size INTEGER NOT NULL,
uploaded DATETIME DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE IF NOT EXISTS announcements (
id INTEGER PRIMARY KEY AUTOINCREMENT,
message TEXT NOT NULL,
active INTEGER DEFAULT 1,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
EOF
chmod 666 /opt/share/data/emergencybox.dbEnable auto-start:
-
Via DD-WRT Web Interface:
- Administration > Commands
- Add to Startup:
/opt/etc/init.d/S80lighttpd start
-
Via init.d naming:
- The script is named
S80lighttpdto auto-start - Ensure
/opt/etc/init.d/is in startup path
- The script is named
-
Manual startup script:
# Add to /opt/etc/init.d/rc.local #!/bin/sh export PHPRC=/opt/etc /opt/etc/init.d/S80lighttpd start
-
Check services:
/opt/etc/init.d/S80lighttpd status netstat -ln | grep 8080 -
Test web access:
wget -O- http://localhost:8080/
-
Test PHP:
echo "<?php phpinfo(); ?>" > /tmp/test.php /opt/bin/php -c /opt/etc/php.ini /tmp/test.php
-
Test database:
/opt/bin/sqlite3 /opt/share/data/emergencybox.db "SELECT COUNT(*) FROM messages;"
- Access from browser: http://192.168.1.1:8080
- Send a test message in the chat
- Upload a small file (< 10MB)
- Upload a large file (> 500MB)
- Link file to message
- Test from multiple devices simultaneously
Edit /opt/etc/lighttpd/lighttpd.conf:
server.max-connections = 100
server.max-fds = 512
fastcgi.server = (
".php" => (
"localhost" => (
"max-procs" => 4,
"PHP_FCGI_CHILDREN" => "4",
...
)
)
)
Restart: /opt/etc/init.d/S80lighttpd restart
Edit /opt/etc/php.ini:
memory_limit = 128MReduce concurrent processes in lighttpd config:
"max-procs" => 1,
"PHP_FCGI_CHILDREN" => "1",
# Lighttpd error log
tail -f /opt/var/log/lighttpd/error.log
# PHP errors
tail -f /tmp/php_errors.log
# System log
dmesg | tail/opt/etc/init.d/S80lighttpd restart/opt/bin/sqlite3 /opt/share/data/emergencybox.db "DELETE FROM messages;"df -h /opt
du -sh /opt/share/www/uploads/*# Backup database
cp /opt/share/data/emergencybox.db /tmp/backup_$(date +%Y%m%d).db
# Backup entire application
tar czf /tmp/emergencybox_backup.tar.gz /opt/share/www /opt/share/dataEdit /opt/etc/lighttpd/lighttpd.conf:
server.port = 80 # or any other port
Restart: /opt/etc/init.d/S80lighttpd restart
SSL adds complexity and certificate management. For offline emergency scenarios, HTTP is sufficient within a trusted network.
Must change in THREE places:
-
/opt/etc/php.ini:upload_max_filesize = 10G post_max_size = 10G
-
/opt/etc/lighttpd/lighttpd.conf:server.max-request-size = 10737418240 # 10GB -
/opt/share/www/api/config.php:define('MAX_FILE_SIZE', 10 * 1024 * 1024 * 1024);
Restart: /opt/etc/init.d/S80lighttpd restart
This deployment is designed for offline, trusted environments. For production use:
-
Add authentication:
- Implement user login system
- Use lighttpd's mod_auth
-
Enable HTTPS:
- Generate self-signed certificate
- Configure SSL in lighttpd
-
Restrict access:
- Firewall rules
- IP whitelisting
- VPN access only
-
File scanning:
- Integrate ClamAV
- Content type validation
- Lighttpd:
/opt/var/log/lighttpd/error.log - PHP:
/tmp/php_errors.log - Deployment: Script output (save to file)
# Check PHP modules
/opt/bin/php -c /opt/etc/php.ini -m
# PHP configuration info
/opt/bin/php -c /opt/etc/php.ini -i
# Test PHP file
/opt/bin/php -c /opt/etc/php.ini /opt/share/www/api/config.php
# SQLite query
/opt/bin/sqlite3 /opt/share/data/emergencybox.db ".tables"
# Check running processes
ps | grep -E '(lighttpd|php)'
# Check listening ports
netstat -ln | grep LISTEN- Check logs first: Most issues are logged
- Run verification tests: Use test functions in script
- Manual verification: Follow troubleshooting steps
- Community: DD-WRT forums, Entware documentation
To completely remove EmergencyBox:
# Stop services
/opt/etc/init.d/S80lighttpd stop
# Remove files
rm -rf /opt/share/www
rm -rf /opt/share/data
rm /opt/etc/php.ini
rm -rf /opt/etc/lighttpd
rm /opt/etc/init.d/S80lighttpd
# Optional: Remove packages (will affect other apps)
# opkg remove php8 lighttpd sqlite3-cliThe automated deployment script handles all critical configuration issues and provides a robust, production-ready installation of EmergencyBox. The comprehensive error handling, rollback capability, and verification tests ensure reliable deployment even in challenging router environments.
For most users, the script "just works" - but this guide provides the deep knowledge needed for troubleshooting and customization.