This release adds major new features for SecuBox management and deployment: ## New Features ### 1. LuCI Admin Control Center (luci-app-secubox-admin) - Unified admin dashboard for managing all SecuBox appstore plugins - **Control Panel**: Real-time stats, system health, alerts, quick actions - **Apps Manager**: Browse catalog, install/remove apps with search & filtering - **App Settings**: Per-app configuration, start/stop controls - **System Health**: Live monitoring (CPU, RAM, disk) with auto-refresh - **System Logs**: Centralized log viewer with download capability - Fully integrated with existing RPCD backend (luci.secubox) - Mobile-responsive design with polished UI components ### 2. Documentation Mirror in SecuBox Bonus - Integrated complete development documentation into luci-app-secubox-bonus - 64+ documentation files now available offline at /luci-static/secubox/docs/ - Beautiful landing page (index-main.html) with 4 sections: - Development guides & references - Live module demos - Tutorials & blog posts - Marketing campaign pages - Accessible locally on router without internet connection ### 3. Automated Docker Plugin Installation - Enhanced secubox-appstore CLI with full Docker automation - One-click installation from web UI now fully automated: - Auto-detects Docker runtime from catalog - Discovers and executes control scripts (*ctl install) - Pulls Docker images automatically - Creates directories and configures UCI - Enables init services - No manual CLI steps required for Docker apps - Works for all Docker apps: AdGuard Home, Mail-in-a-Box, Nextcloud, etc. ### 4. Mail-in-a-Box Plugin - New Docker-based email server plugin (secubox-app-mailinabox) - Complete package with: - UCI configuration (8 port mappings, feature flags) - Control script (mailinaboxctl) with install/check/update/status/logs - Procd init script with auto-restart - Catalog manifest (category: hosting, maturity: beta) - Network mode: host (required for mail server) - Persistent storage: mail, SSL, data, DNS volumes ## Improvements ### Build System - Updated local-build.sh to include luci-app-* packages from package/secubox/ - Now automatically discovers and builds luci-app-secubox-admin and similar packages - Fixed Makefile include paths for feed structure ### Package Releases - Incremented PKG_RELEASE for all 31 SecuBox packages - Ensures clean upgrade path from previous versions ### Catalog Updates - Mail-in-a-Box entry moved from "productivity" to "hosting" category - Status changed to "beta" reflecting community Docker image maturity - Storage requirement increased: 1024MB → 2048MB - Added port 25 accessibility note ## Files Changed ### New Packages (2) - package/secubox/luci-app-secubox-admin/ (12 files) - package/secubox/secubox-app-mailinabox/ (4 files) ### Enhanced Packages (1) - package/secubox/luci-app-secubox-bonus/ (65 new docs files) ### Modified Core (3) - package/secubox/secubox-core/root/usr/sbin/secubox-appstore - package/secubox/secubox-core/root/usr/share/secubox/catalog.json - secubox-tools/local-build.sh ### All Makefiles (31 packages) - Incremented PKG_RELEASE for clean upgrade path ## Technical Details **Admin Control Center Architecture:** - Frontend: 5 views (dashboard, apps, settings, health, logs) - API: Wrapper around luci.secubox RPCD methods - Components: Reusable UI library (cards, badges, alerts, loaders) - Styling: Common + admin-specific CSS with responsive design - Auto-refresh: Polling for live updates (5-30s intervals) **Docker Automation Flow:** ``` Web UI → RPCD → secubox-appstore CLI → opkg install → *ctl install → docker pull → directories → UCI config → init enable → ✓ Ready ``` **Access Points:** - Admin Control: http://router/cgi-bin/luci/admin/secubox/admin/ - Documentation: http://router/luci-static/secubox/index-main.html - Demos: http://router/luci-static/secubox/demo-*.html 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
228 lines
6.6 KiB
Bash
Executable File
228 lines
6.6 KiB
Bash
Executable File
#!/bin/sh
|
|
# SecuBox Mail-in-a-Box manager
|
|
|
|
CONFIG="mailinabox"
|
|
CONTAINER="secbx-mailinabox"
|
|
OPKG_UPDATED=0
|
|
|
|
usage() {
|
|
cat <<'USAGE'
|
|
Usage: mailinaboxctl <command>
|
|
|
|
Commands:
|
|
install Install prerequisites, prepare directories, pull image
|
|
check Run prerequisite checks
|
|
update Pull new image and restart
|
|
status Show container status
|
|
logs Show container logs (use -f to follow)
|
|
admin Open admin interface in browser (shows URL)
|
|
service-run Internal: run container via procd
|
|
service-stop Stop container
|
|
|
|
Post-Installation:
|
|
1. Configure hostname and admin_email in /etc/config/mailinabox
|
|
2. Ensure proper DNS configuration (A, MX, SPF, DKIM, DMARC records)
|
|
3. Start with: /etc/init.d/mailinabox start
|
|
4. Access admin panel at https://your-hostname/admin
|
|
|
|
Important Notes:
|
|
- Requires public IP and proper DNS configuration
|
|
- Port 25 must be open (some ISPs block it)
|
|
- Valid domain name required for SSL certificates
|
|
- Initial setup may take 10-15 minutes
|
|
USAGE
|
|
}
|
|
|
|
require_root() { [ "$(id -u)" -eq 0 ]; }
|
|
|
|
uci_get() { uci -q get ${CONFIG}.main.$1; }
|
|
|
|
defaults() {
|
|
image="$(uci_get image || echo docker-mailserver/docker-mailserver:latest)"
|
|
data_path="$(uci_get data_path || echo /srv/mailinabox)"
|
|
hostname="$(uci_get hostname || echo mail.example.com)"
|
|
admin_email="$(uci_get admin_email || echo admin@example.com)"
|
|
timezone="$(uci_get timezone || echo UTC)"
|
|
|
|
smtp_port="$(uci_get smtp_port || echo 25)"
|
|
dns_port="$(uci_get dns_port || echo 53)"
|
|
http_port="$(uci_get http_port || echo 80)"
|
|
https_port="$(uci_get https_port || echo 443)"
|
|
submission_port="$(uci_get submission_port || echo 587)"
|
|
imaps_port="$(uci_get imaps_port || echo 993)"
|
|
pop3s_port="$(uci_get pop3s_port || echo 995)"
|
|
sieve_port="$(uci_get sieve_port || echo 4190)"
|
|
|
|
enable_dns="$(uci_get enable_dns || echo 1)"
|
|
enable_webmail="$(uci_get enable_webmail || echo 1)"
|
|
letsencrypt="$(uci_get letsencrypt || echo 1)"
|
|
}
|
|
|
|
ensure_dir() { [ -d "$1" ] || mkdir -p "$1"; }
|
|
|
|
ensure_packages() {
|
|
for pkg in "$@"; do
|
|
if ! opkg status "$pkg" >/dev/null 2>&1; then
|
|
if [ "$OPKG_UPDATED" -eq 0 ]; then
|
|
opkg update || return 1
|
|
OPKG_UPDATED=1
|
|
fi
|
|
opkg install "$pkg" || return 1
|
|
fi
|
|
done
|
|
}
|
|
|
|
check_prereqs() {
|
|
defaults
|
|
|
|
# Check hostname configuration
|
|
if [ "$hostname" = "mail.example.com" ]; then
|
|
echo "[WARNING] Please configure hostname in /etc/config/mailinabox" >&2
|
|
echo "[WARNING] Mail-in-a-Box requires a valid domain name" >&2
|
|
fi
|
|
|
|
# Create data directories
|
|
ensure_dir "$data_path"
|
|
ensure_dir "$data_path/mail"
|
|
ensure_dir "$data_path/ssl"
|
|
ensure_dir "$data_path/data"
|
|
ensure_dir "$data_path/dns"
|
|
|
|
# Check system requirements
|
|
[ -d /sys/fs/cgroup ] || { echo "[ERROR] /sys/fs/cgroup missing" >&2; return 1; }
|
|
|
|
# Install Docker
|
|
ensure_packages dockerd docker containerd
|
|
/etc/init.d/dockerd enable >/dev/null 2>&1
|
|
/etc/init.d/dockerd start >/dev/null 2>&1
|
|
|
|
# Port conflict checks
|
|
if [ "$smtp_port" = "25" ]; then
|
|
if netstat -tln 2>/dev/null | grep -q ":25 "; then
|
|
echo "[WARNING] Port 25 already in use - potential conflict" >&2
|
|
fi
|
|
fi
|
|
|
|
if [ "$dns_port" = "53" ] && [ "$enable_dns" = "1" ]; then
|
|
if netstat -uln 2>/dev/null | grep -q ":53 "; then
|
|
echo "[WARNING] Port 53 already in use - DNS may conflict with dnsmasq" >&2
|
|
echo "[WARNING] Consider disabling Mail-in-a-Box DNS or moving dnsmasq" >&2
|
|
fi
|
|
fi
|
|
}
|
|
|
|
pull_image() { defaults; docker pull "$image"; }
|
|
|
|
stop_container() {
|
|
docker stop "$CONTAINER" >/dev/null 2>&1 || true
|
|
docker rm "$CONTAINER" >/dev/null 2>&1 || true
|
|
}
|
|
|
|
cmd_install() {
|
|
require_root || { echo Root required >&2; exit 1; }
|
|
check_prereqs || exit 1
|
|
pull_image || exit 1
|
|
uci set ${CONFIG}.main.enabled='1'
|
|
uci commit ${CONFIG}
|
|
/etc/init.d/mailinabox enable
|
|
echo ""
|
|
echo "Mail-in-a-Box prerequisites installed."
|
|
echo ""
|
|
echo "CRITICAL NEXT STEPS:"
|
|
echo " 1. Edit /etc/config/mailinabox and set:"
|
|
echo " - hostname (must be a valid FQDN)"
|
|
echo " - admin_email"
|
|
echo " 2. Configure DNS records for your domain:"
|
|
echo " - A record: $hostname -> your-public-ip"
|
|
echo " - MX record: @ -> $hostname"
|
|
echo " 3. Ensure port 25 is not blocked by your ISP"
|
|
echo " 4. Start with: /etc/init.d/mailinabox start"
|
|
echo " 5. Access admin at: https://$hostname/admin"
|
|
echo ""
|
|
}
|
|
|
|
cmd_check() {
|
|
check_prereqs
|
|
echo "Prerequisite check completed."
|
|
echo ""
|
|
defaults
|
|
echo "Current configuration:"
|
|
echo " Hostname: $hostname"
|
|
echo " Admin email: $admin_email"
|
|
echo " Data path: $data_path"
|
|
echo " DNS enabled: $enable_dns"
|
|
echo ""
|
|
}
|
|
|
|
cmd_update() {
|
|
require_root || { echo Root required >&2; exit 1; }
|
|
pull_image || exit 1
|
|
/etc/init.d/mailinabox restart
|
|
}
|
|
|
|
cmd_status() { docker ps -a --filter "name=$CONTAINER"; }
|
|
|
|
cmd_logs() { docker logs "$@" "$CONTAINER"; }
|
|
|
|
cmd_admin() {
|
|
defaults
|
|
echo "Admin interface: https://$hostname/admin"
|
|
echo ""
|
|
echo "If accessing locally, you may need to:"
|
|
echo " - Add '$hostname' to your hosts file"
|
|
echo " - Or use: https://$(uci get network.lan.ipaddr 2>/dev/null || echo 'router-ip')/admin"
|
|
}
|
|
|
|
cmd_service_run() {
|
|
require_root || { echo Root required >&2; exit 1; }
|
|
check_prereqs || exit 1
|
|
defaults
|
|
stop_container
|
|
|
|
local docker_args="--name $CONTAINER"
|
|
|
|
# Network mode: host for mail server functionality
|
|
docker_args="$docker_args --network host"
|
|
|
|
# Volume mounts
|
|
docker_args="$docker_args -v $data_path/mail:/var/mail"
|
|
docker_args="$docker_args -v $data_path/ssl:/etc/ssl/mail"
|
|
docker_args="$docker_args -v $data_path/data:/var/mail-state"
|
|
docker_args="$docker_args -v $data_path/dns:/etc/bind"
|
|
|
|
# Environment variables for docker-mailserver
|
|
docker_args="$docker_args -e TZ=$timezone"
|
|
docker_args="$docker_args -e OVERRIDE_HOSTNAME=$hostname"
|
|
docker_args="$docker_args -e ENABLE_SPAMASSASSIN=1"
|
|
docker_args="$docker_args -e ENABLE_CLAMAV=1"
|
|
docker_args="$docker_args -e ENABLE_FAIL2BAN=1"
|
|
docker_args="$docker_args -e SSL_TYPE=letsencrypt"
|
|
|
|
# Capabilities for mail server
|
|
docker_args="$docker_args --cap-add=NET_ADMIN"
|
|
docker_args="$docker_args --cap-add=NET_BIND_SERVICE"
|
|
|
|
# Restart policy
|
|
docker_args="$docker_args --restart=unless-stopped"
|
|
|
|
exec docker run --rm $docker_args "$image"
|
|
}
|
|
|
|
cmd_service_stop() {
|
|
require_root || { echo Root required >&2; exit 1; }
|
|
stop_container
|
|
}
|
|
|
|
case "${1:-}" in
|
|
install) shift; cmd_install "$@" ;;
|
|
check) shift; cmd_check "$@" ;;
|
|
update) shift; cmd_update "$@" ;;
|
|
status) shift; cmd_status "$@" ;;
|
|
logs) shift; cmd_logs "$@" ;;
|
|
admin) shift; cmd_admin "$@" ;;
|
|
service-run) shift; cmd_service_run "$@" ;;
|
|
service-stop) shift; cmd_service_stop "$@" ;;
|
|
help|--help|-h|'') usage ;;
|
|
*) echo "Unknown command: $1" >&2; usage >&2; exit 1 ;;
|
|
esac
|