IncusForge is an Incus custom Image Management Utility for local servers and simplestream servers.
434
Build • Publish • Distribute Incus Custom Images
ScottiBYTE Incus Forge is a lightweight Home Lab focused web application for publishing, managing, and distributing custom Incus images through SimpleStreams repositories.
Incus Forge allows Home Labbers and administrators to:
The platform is intentionally designed to remain:
Recommended deployment model:
| System | Purpose |
|---|---|
| IncusForge | Web UI and image management |
| IncusSimplestreams | SimpleStreams repository |
| Existing Incus Hosts | Source containers and VMs |
Benefits:
incus launch images:ubuntu/26.04 IncusForge
Enter shell:
incus shell IncusForge
From the IncusForge container:
incus remote add vmsstorm https://vmsstorm:8443
Accept the certificate.
Enter trust password or token.
Verify:
incus remote list
Example:
+-------------------+------------------------------------+
| NAME | URL |
+-------------------+------------------------------------+
| vmsstorm | https://vmsstorm:8443 |
| scottibyte-images | https://images.scottibyte.com |
+-------------------+------------------------------------+
Incus Forge synchronizes images to the SimpleStreams repository using SSH and rsync.
Generate SSH key if needed:
ssh-keygen -t ed25519
Copy key to repository server:
ssh-copy-id [email protected]
Verify access:
ssh [email protected] "hostname && whoami"
Expected:
IncusSimplestreams
scott
mkdir -p ~/incusforge
cd ~/incusforge
nano config.json
Paste:
{
"port": 3030,
"simplestreams": {
"name": "scottibyte",
"publicUrl": "https://images.mydomain.com",
"sshHost": "172.16.2.111",
"sshUser": "scott",
"webRoot": "/var/www/html",
"imageDir": "/var/www/html/images",
"streamsDir": "/var/www/html/streams"
}
}
Save file.
nano docker-compose.yml
Paste:
services:
incusforge:
image: scottibyte/incusforge:latest
container_name: incusforge
restart: unless-stopped
ports:
- "3030:3030"
environment:
PORT: "3030"
HOME: /home/scott
INCUS_CONF: /incus-client
CONFIG_PATH: /app/config.json
volumes:
- ./config.json:/app/config.json:ro
- ${HOME}/.config/incus:/incus-client:ro
- ${HOME}/.ssh:/home/scott/.ssh:ro
Save file.
docker compose up -d
Verify logs:
docker logs -f incusforge
Expected:
ScottiBYTE Incus Forge running on port 3030
Open browser:
http://YOUR-IP:3030
Create repository container:
incus launch images:ubuntu/26.04 IncusSimplestreams
Enter shell:
incus shell IncusSimplestreams
nano bootstrap-simplestreams.sh
Paste:
#!/usr/bin/env bash
set -euo pipefail
WEB_ROOT="${WEB_ROOT:-/var/www/html}"
IMAGE_DIR="${IMAGE_DIR:-$WEB_ROOT/images}"
STREAMS_DIR="${STREAMS_DIR:-$WEB_ROOT/streams}"
REPO_USER="${REPO_USER:-$USER}"
echo "=== ScottiBYTE Incus Forge SimpleStreams Bootstrap ==="
echo "[1/8] Installing required packages..."
sudo apt update
sudo apt install -y nginx xz-utils python3 python3-yaml incus-extra openssh-server curl ca-certificates rsync jq
echo "[2/8] Enabling SSH..."
sudo systemctl enable --now ssh || sudo systemctl enable --now sshd
echo "[3/8] Enabling nginx..."
sudo systemctl enable --now nginx
echo "[4/8] Creating repository directories..."
sudo mkdir -p "$IMAGE_DIR"
sudo mkdir -p "$STREAMS_DIR/v1"
echo "[5/8] Setting ownership and permissions..."
sudo chown -R "$REPO_USER:$REPO_USER" "$WEB_ROOT"
sudo chmod -R 775 "$WEB_ROOT"
echo "[6/8] Creating metadata files..."
if [ ! -f "$STREAMS_DIR/v1/index.json" ]; then
cat > "$STREAMS_DIR/v1/index.json" <<'JSON'
{"index":{"images":{"datatype":"image-downloads","path":"streams/v1/images.json","products":[],"format":"products:1.0"}},"format":"index:1.0"}
JSON
fi
if [ ! -f "$STREAMS_DIR/v1/images.json" ]; then
cat > "$STREAMS_DIR/v1/images.json" <<'JSON'
{"content_id":"images","datatype":"image-downloads","format":"products:1.0","products":{}}
JSON
fi
echo "[7/8] Validating repository..."
command -v incus-simplestreams >/dev/null
command -v xz >/dev/null
command -v nginx >/dev/null
echo "[8/8] Bootstrap complete."
echo
echo "Repository ready."
echo
echo "Next step:"
echo "ssh-copy-id $REPO_USER@<repository-ip>"
Save file.
chmod +x bootstrap-simplestreams.sh
REPO_USER=scott WEB_ROOT=/var/www/html ./bootstrap-simplestreams.sh
Open browser:
http://YOUR-REPOSITORY-IP/images
Verify metadata:
curl http://YOUR-REPOSITORY-IP/streams/v1/index.json
incus remote add scottibyte-images \
https://images.scottibyte.com \
--protocol=simplestreams
Verify:
incus remote list
incus image list scottibyte-images:
Error:
xz: executable file not found
Fix:
sudo apt install xz-utils
docker exec -it incusforge bash
incus remote list
docker logs -f incusforge
incus image list scottibyte-images:
If you find Incus Forge useful:
Need help with Incus Forge, Docker deployment, Incus profile management, container creation, or ScottiBYTE utilities?
Join the ScottiBYTE Rocket.Chat community:
New users can start in #general. From there, you can find other ScottiBYTE project channels and community discussions.
For bugs and feature requests, please continue to use GitHub Issues. For quick questions and community discussion, use Rocket.Chat.
Content type
Image
Digest
sha256:9428e8166…
Size
377.5 MB
Last updated
4 months ago
docker pull scottibyte/incusforge