lxc: add foundational CLI and docs

This commit is contained in:
CyberMind-FR 2025-12-29 17:25:47 +01:00
parent 3c0003614d
commit da8eeb27ca
6 changed files with 326 additions and 0 deletions

View File

@ -0,0 +1,66 @@
# SecuBox LXC Framework (Preview)
**Version:** 1.0.0
**Last Updated:** 2025-12-28
**Status:** Active
This document captures the baseline LXC tooling added in Step 8. It is a foundation for future “SecuBox Apps” packaged as LXC containers (e.g., Lyrion) and explains the combined CLI/UCI workflow.
---
## Components
1. **UCI config:** `/etc/config/lxcapps` (one section per container).
2. **Storage root:** `/srv/lxc/<name>/` (rootfs, config, logs).
3. **Templates:** `/usr/share/secubox/lxc/templates/` (scripts/tarballs; default `debian`).
4. **CLI helper:** `secubox-tools/lxc/secubox-lxc` (install to `/usr/sbin/secubox-lxc`).
`secubox-lxc` requires standard OpenWrt LXC packages and uses BusyBox-friendly syntax.
---
## CLI Usage
```bash
secubox-lxc list # show defined containers
secubox-lxc create lyrion --bridge br-dmz --ip 192.168.50.10
secubox-lxc start lyrion
secubox-lxc stop lyrion
secubox-lxc status lyrion
secubox-lxc delete lyrion
```
Each `create` call ensures the container directory under `/srv/lxc/<name>` and writes a matching `config container '<name>'` section in `/etc/config/lxcapps`. That makes it discoverable for future LuCI integrations.
---
## UCI Schema
```uci
config container 'lyrion'
option bridge 'br-dmz'
option ip '192.168.50.10'
option gateway '192.168.50.1'
option dns '1.1.1.1'
option memory '1024'
```
Additional options (template, rootfs, custom scripts) can be added later; the CLI already supports `--template`, `--memory`, `--bridge`, `--ip`, `--gateway`, and `--dns` flags.
---
## Storage & Templates
- Default rootfs path: `/srv/lxc/<name>/rootfs`.
- Template lookup: CLI `--template` arg → `/usr/share/secubox/lxc/templates/<name>` → system `lxc-create -t debian`.
- Bridge defaults to `br-lan`; pass `--bridge br-dmz` for DMZ containers.
---
## Future Work
- Expose `/etc/config/lxcapps` via RPC + LuCI so manifests/profiles can declare LXC apps.
- Ship Lyrion and other container templates alongside Docker apps in the App Store.
- Reuse the profile system to install LXC dependencies and provision containers automatically.
For now, this tooling lets power users validate LXC on OpenWrt ARM64 and gives the App Store a consistent foundation.

View File

@ -0,0 +1,78 @@
# SecuBox LXC Framework (Preview)
**Version:** 1.0.0
**Last Updated:** 2025-12-28
**Status:** Active
This document captures the baseline LXC tooling added in Step 8. It is a foundation for future “SecuBox Apps” packaged as LXC containers (e.g., Lyrion) and explains the combined CLI/UCI workflow.
---
## Components
1. **UCI config:** `/etc/config/lxcapps` (one section per container).
2. **Storage root:** `/srv/lxc/<name>/` (rootfs, config, logs).
3. **Templates:** `/usr/share/secubox/lxc/templates/` (scripts/tarballs; default `debian`).
4. **CLI helper:** `secubox-tools/lxc/secubox-lxc` (install to `/usr/sbin/secubox-lxc`).
`secubox-lxc` requires standard OpenWrt LXC packages (`lxc`, `lxc-templates`, `lxc-start`, etc.) and uses BusyBox-friendly syntax.
---
## CLI Usage
```bash
# List defined containers
secubox-lxc list
# Create container using the debian template and attach to br-dmz
secubox-lxc create lyrion --bridge br-dmz --ip 192.168.50.10
# Start / stop lifecycle
secubox-lxc start lyrion
secubox-lxc stop lyrion
# Show detailed config or status
secubox-lxc show lyrion
secubox-lxc status lyrion
# Remove
secubox-lxc delete lyrion
```
`secubox-lxc create <name>` automatically creates a `config` section under `lxcapps.<name>` capturing bridge/IP/memory metadata, so LuCI (future apps) can introspect containers in a consistent way.
---
## UCI Schema (`/etc/config/lxcapps`)
```uci
config container 'lyrion'
option bridge 'br-dmz'
option ip '192.168.50.10'
option gateway '192.168.50.1'
option dns '1.1.1.1'
option memory '1024'
```
This initial version does not yet tie into LuCI, but the schema is ready for future RPC endpoints and wizards (e.g., mapping profile entries to LXC containers).
---
## Storage & Templates
- Default rootfs path: `/srv/lxc/<name>/rootfs`.
- Template lookup order: CLI `--template``/usr/share/secubox/lxc/templates/<name>` → fallback to system `lxc-create -t debian`.
- Bridge defaults to `br-lan`; pass `--bridge br-dmz` to isolate DMZ containers.
---
## Next Steps
This foundation enables the remaining roadmap items:
- Expose `/etc/config/lxcapps` via `luci-app-secubox` RPC for integration with the App Store/wizard.
- Add profiles or manifests referencing specific LXC definitions (e.g., `type": "lxc"`).
- Ship ready-made templates (Lyrion, etc.) and document cgroup requirements alongside Docker apps.
For now, use the CLI + UCI schema to experiment with LXC containers on OpenWrt ARM64 and validate storage/network assumptions.

View File

@ -59,6 +59,7 @@ Baseline profiles:
| `lab` | Monitoring lab | Router mode, ensures Netifyd & Bandwidth Manager |
| `hardened` | Security-focused | Enables CrowdSec + Client Guardian |
| `gateway_dmz` | Router + DMZ segment | Switches to DMZ mode and enables VHost manager |
| `lxc_base` | (Upcoming) baseline LXC container | Reserved for future `secubox-lxc` integrations |
`apply_profile` automatically tars `/etc/config` to `/etc/secubox-profiles/backups/` before modifying settings, so the **Rollback last profile** button (or `rollback_profile` RPC) instantly restores prior UCI files.

10
profiles/README.md Normal file
View File

@ -0,0 +1,10 @@
# SecuBox Profiles
This directory defines baseline profile manifests consumed by `luci-app-secubox`.
- `home.json`: Home router baseline (router mode, Zigbee2MQTT + Netdata).
- `lab.json`: Lab monitoring preset (Netifyd + Bandwidth Manager).
- `hardened.json`: Security preset (CrowdSec + Client Guardian).
- `gateway_dmz.json`: Gateway + DMZ preset (switches to DMZ mode, enables vhost manager).
These JSON files also serve as examples for future LXC or Docker app bundles.

171
secubox-tools/lxc/secubox-lxc Executable file
View File

@ -0,0 +1,171 @@
#!/bin/sh
# SecuBox LXC helper: create/start/stop LXC containers following SecuBox conventions
set -eu
CONFIG="/etc/config/lxcapps"
STORAGE_ROOT="/srv/lxc"
TEMPLATE_DIR="${SECUBOX_LXC_TEMPLATES:-/usr/share/secubox/lxc/templates}"
usage() {
cat <<'USAGE'
SecuBox LXC Manager
Usage: secubox-lxc <command> [options]
Commands:
list Show containers defined in /etc/config/lxcapps
show <name> Display config values for a container
create <name> [options] Create container (downloads template if needed)
start <name> Start container via lxc-start
stop <name> Stop container via lxc-stop
delete <name> Stop and remove container directory
status <name> Show runtime state
Options (create):
--template PATH Rootfs tarball or template script (default debian)
--bridge BRIDGE Bridge to attach (default br-lan)
--ip ADDRESS Static IP address (optional)
--gateway ADDRESS Gateway (optional)
--dns ADDRESS DNS server (optional)
--memory MB Memory limit (optional)
Examples:
secubox-lxc list
secubox-lxc create secubox-lyrion --bridge br-dmz --ip 192.168.50.10
secubox-lxc start secubox-lyrion
USAGE
}
require_tool() {
command -v "$1" >/dev/null 2>&1 || { echo "[ERROR] Missing dependency: $1" >&2; exit 1; }
}
ensure_storage() {
mkdir -p "$STORAGE_ROOT"
}
uci_get_container() {
local name="$1" option="$2"
uci -q get lxcapps."$name"."$2"
}
uci_set_container() {
local name="$1" option="$2" value="$3"
uci set lxcapps."$name"."$option"="$value"
}
list_containers() {
uci -q show lxcapps 2>/dev/null | grep '=container$' | cut -d. -f2 | cut -d= -f1
}
cmd_list() {
require_tool lxc-info
ensure_storage
printf '%-18s %-20s %-10s %-16s\n' "Name" "Bridge" "State" "RootFS"
printf '%-18s %-20s %-10s %-16s\n' "----" "------" "-----" "------"
for name in $(list_containers); do
local bridge rootfs state
bridge=$(uci_get_container "$name" bridge || printf 'br-lan')
rootfs="$STORAGE_ROOT/$name/rootfs"
if lxc-info -n "$name" >/dev/null 2>&1; then
state=$(lxc-info -n "$name" -s 2>/dev/null | awk '{print $2}')
else
state="N/A"
fi
printf '%-18s %-20s %-10s %-16s\n' "$name" "$bridge" "$state" "$rootfs"
done
}
cmd_show() {
local name="$1"
uci -q show lxcapps."$name"
}
cmd_create() {
require_tool lxc-create
local name="$1"; shift
local template="debian"
local bridge="br-lan"
local ip=""
local gateway=""
local dns=""
local memory=""
while [ $# -gt 0 ]; do
case "$1" in
--template) template="$2"; shift 2;;
--bridge) bridge="$2"; shift 2;;
--ip) ip="$2"; shift 2;;
--gateway) gateway="$2"; shift 2;;
--dns) dns="$2"; shift 2;;
--memory) memory="$2"; shift 2;;
*) echo "Unknown option: $1" >&2; exit 1;;
esac
done
[ -n "$name" ] || { echo "Container name required" >&2; exit 1; }
ensure_storage
local container_dir="$STORAGE_ROOT/$name"
if [ -d "$container_dir" ]; then
echo "[WARN] Container directory already exists, skipping rootfs creation."
else
mkdir -p "$container_dir"
local tmpl_path="$template"
if [ -f "$TEMPLATE_DIR/$template" ]; then
tmpl_path="$TEMPLATE_DIR/$template"
fi
lxc-create -n "$name" -P "$STORAGE_ROOT" -t "$tmpl_path"
fi
uci batch <<-EOF
set lxcapps.$name=container
set lxcapps.$name.bridge='$bridge'
EOF
[ -n "$ip" ] && uci_set_container "$name" ip "$ip"
[ -n "$gateway" ] && uci_set_container "$name" gateway "$gateway"
[ -n "$dns" ] && uci_set_container "$name" dns "$dns"
[ -n "$memory" ] && uci_set_container "$name" memory "$memory"
uci commit lxcapps
cat <<MSG
[INFO] Container $name created.
Rootfs: $container_dir
Bridge: $bridge
MSG
}
cmd_start() {
require_tool lxc-start
local name="$1"
lxc-start -n "$name" -d
}
cmd_stop() {
require_tool lxc-stop
local name="$1"
lxc-stop -n "$name"
}
cmd_delete() {
require_tool lxc-destroy
local name="$1"
lxc-stop -n "$name" >/dev/null 2>&1 || true
lxc-destroy -n "$name"
rm -rf "$STORAGE_ROOT/$name"
uci delete lxcapps."$name"
uci commit lxcapps
}
cmd_status() {
require_tool lxc-info
local name="$1"
lxc-info -n "$name"
}
case "${1:-}" in
list) shift; cmd_list "$@" ;;
show) shift; [ $# -ge 1 ] || { usage; exit 1; }; cmd_show "$1" ;;
create) shift; [ $# -ge 1 ] || { usage; exit 1; }; cmd_create "$@" ;;
start) shift; [ $# -ge 1 ] || { usage; exit 1; }; cmd_start "$1" ;;
stop) shift; [ $# -ge 1 ] || { usage; exit 1; }; cmd_stop "$1" ;;
delete) shift; [ $# -ge 1 ] || { usage; exit 1; }; cmd_delete "$1" ;;
status) shift; [ $# -ge 1 ] || { usage; exit 1; }; cmd_status "$1" ;;
help|--help|-h|'') usage ;;
*) usage; exit 1 ;;
esac

View File