Reusable Bash + systemd appliance skeleton built around a simple model:
- Primary mode: run your main workload (
APPLIANCE_PRIMARY_CMD) - Secondary mode: run a fallback workload (
APPLIANCE_SECONDARY_CMD) - Healthcheck timer: if primary is not active, start secondary
This repo is intentionally minimal: you provide the commands and any extra packages.
Build the devcontainer image:
docker build -t template-appliance-devcontainer -f .devcontainer/Dockerfile .Run the full CI pipeline inside it:
docker run --rm \
-v "$PWD:/work" \
-w /work \
template-appliance-devcontainer \
bash -lc './scripts/ci.sh'Or, use the Makefile (requires make + Docker on your host):
make ciSee CONTRIBUTING.md for the required pre-PR checks.
At a glance, systemd manages three key units:
template-appliance-primary.servicetemplate-appliance-secondary.servicetemplate-appliance-healthcheck.timer(runstemplate-appliance-healthcheck.service)
flowchart TD
PRIMARY["template-appliance-primary.service<br/>runs APPLIANCE_PRIMARY_CMD"]
SECONDARY["template-appliance-secondary.service<br/>runs APPLIANCE_SECONDARY_CMD"]
TIMER["template-appliance-healthcheck.timer"] --> CHECK["template-appliance-healthcheck.service"]
CHECK -->|"primary inactive"| SECONDARY
The recommended install flow is:
- cloud-init writes
/etc/template-appliance/config.env. - cloud-init installs a one-time installer unit + bootstrap script.
- systemd runs
template-appliance-install.serviceuntil install succeeds.
Examples:
Runtime configuration lives in /etc/template-appliance/config.env.
Required (first-boot bootstrap):
APPLIANCE_REPO_URLAPPLIANCE_REPO_REF(branch/tag/commit; pinning to a tag/commit is recommended)
Required (runtime modes):
APPLIANCE_PRIMARY_CMDAPPLIANCE_SECONDARY_CMD
Optional:
APPLIANCE_CHECKOUT_DIR(default:/opt/template-appliance)APPLIANCE_INSTALLED_MARKER(default:/var/lib/template-appliance/installed)APPLIANCE_APT_PACKAGES(space-separated extra packages for install)APPLIANCE_PRIMARY_SERVICE/APPLIANCE_SECONDARY_SERVICE(override healthcheck targets)APPLIANCE_DRY_RUN=1(do not modify system; record intended actions)
Switch modes:
systemctl start template-appliance-primary.service
systemctl start template-appliance-secondary.serviceInspect install/boot status:
systemctl status template-appliance-install.service --no-pager
ls -l /var/lib/template-appliance/installed || trueIf you cannot use cloud-init, you can install via SSH.
- Install prerequisites:
sudo apt-get update
sudo apt-get install -y --no-install-recommends ca-certificates curl git- Create
/etc/template-appliance/config.env(start from the example):
sudo mkdir -p /etc/template-appliance
sudo cp /path/to/template-appliance/examples/config.env.example /etc/template-appliance/config.env
sudo nano /etc/template-appliance/config.env- Clone the repo and run the installer as root:
git clone https://github.com/your-org/template-appliance.git /opt/template-appliance
cd /opt/template-appliance
sudo ./scripts/install.sh