Unraid-Template-Sync

Unraid-Template-Sync

Docker app from Florian Dambrine's Repository

Overview

Receives authenticated GitHub push webhooks and automatically refreshes this Unraid server's private Community Applications XML templates.

Unraid Template Sync

Unraid Template Sync logo

A small, standard-library-only Go service that receives authenticated GitHub push webhooks and refreshes private Unraid Community Applications templates. On its first start it clones the configured repository into an empty mounted directory; later starts and webhooks fetch and reset that managed checkout.

GitHub webhook
  -> Nginx Proxy Manager (TLS and GitHub hooks IP allowlist)
  -> Unraid Template Sync (HMAC, repository and branch validation)
  -> git fetch/reset
  -> private/Lowess/*.xml

Security model

Nginx Proxy Manager is responsible for allowing only the current networks in the hooks field returned by https://api.github.com/meta. GitHub changes these ranges periodically, so the NPM Access List must be kept current.

The service independently requires GitHub's X-Hub-Signature-256 HMAC, accepts only the configured repository and branch, suppresses duplicate delivery IDs, limits request bodies and HTTP timeouts, and never mounts the Docker socket. IP allowlisting is intentionally not implemented in the app.

Container

Images are published by GitHub Actions to:

ghcr.io/lowess/unraid-template-sync:latest

Every pull request is tested and built. Pushes to main publish latest and commit-SHA tags. Tags such as v1.2.3 also publish semantic-version tags.

The GHCR package must be public for an unauthenticated Unraid installation to pull it. After its first publication, set the package visibility to public in GitHub's package settings.

Configuration

Variable Default Purpose
WEBHOOK_SECRET required High-entropy secret shared with GitHub
GITHUB_REPOSITORY Lowess/docker-templates-unraid Accepted webhook repository
GITHUB_BRANCH main Accepted push branch
GIT_REMOTE_URL public HTTPS repository URL Source used by git fetch
REPO_DIR /repo Managed checkout, cloned when empty
SOURCE_SUBDIR Lowess XML source beneath the checkout
DEST_DIR /templates Private CA template destination
PORT 9000 HTTP listener port
SYNC_ON_START true Reconcile after container startup
GIT_CLEAN true Remove untracked checkout files

The service deliberately clones and fetches the public repository over HTTPS instead of mounting host SSH credentials. No PAT is needed. If /repo has no .git metadata, it must be empty; the service refuses to overwrite unrelated files. GIT_CLEAN=true matches the previous script and means local untracked files in the managed checkout are deleted after it has been cloned.

Endpoints

  • POST /webhook validates and queues eligible GitHub webhook deliveries.
  • GET /healthz reports the latest synchronization result.

Nginx Proxy Manager and GitHub

  1. Create an NPM Access List containing every current GitHub hooks CIDR and deny all other sources. Do not add browser authentication.
  2. Proxy an HTTPS hostname to container port 9000, or the Unraid mapped port.
  3. Generate a secret with openssl rand -hex 32.
  4. Put that secret in the Unraid template and the GitHub repository webhook.
  5. Set the GitHub payload URL to https://YOUR-HOST/webhook, content type to application/json, and subscribe only to push events.

The current hook CIDRs can be inspected with:

curl -fsSL https://api.github.com/meta | jq -r '.hooks[]'

Development

go test -race ./...
go vet ./...
docker build -t unraid-template-sync:dev .

Install Unraid-Template-Sync on Unraid in a few clicks.

Find Unraid-Template-Sync in Community Apps on your Unraid server, review the template, and click Install. Unraid handles the Docker app or plugin setup from the published template.

Open the Apps tab on your Unraid server Search Community Apps for Unraid-Template-Sync Review the template variables and paths Click Install

Related apps

Explore more like this

Explore all

Details

Repository
ghcr.io/lowess/unraid-template-sync:latest
Last Updated2026-09-23
First Seen2026-09-23

Runtime arguments

Web UI
http://[IP]:[PORT:9000]/healthz
Network
bridge
Privileged
false
Extra Params
--security-opt=no-new-privileges:true

Template configuration

Managed template repositoryPathrw

Managed docker-templates-unraid checkout. The service clones it automatically when this directory is empty; tracked changes and, when enabled, untracked files are discarded during sync.

Target
/repo
Default
/boot/config/plugins/community.applications/docker-templates-unraid
Value
/boot/config/plugins/community.applications/docker-templates-unraid
Private template destinationPathrw

Destination for the mirrored Lowess XML templates. Stale XML files are deleted; non-XML files are left untouched.

Target
/templates
Default
/boot/config/plugins/community.applications/private/Lowess
Value
/boot/config/plugins/community.applications/private/Lowess
Webhook HTTP portPorttcp

HTTP port consumed by Nginx Proxy Manager. Do not expose it directly to the internet.

Target
9000
Default
9141
Value
9141
GitHub Webhook SecretVariable

Required high-entropy secret shared with the GitHub repository webhook. Generate one with: openssl rand -hex 32

Target
WEBHOOK_SECRET
GitHub RepositoryVariable

Only webhook payloads for this exact owner/repository are accepted.

Target
GITHUB_REPOSITORY
Default
Lowess/docker-templates-unraid
Value
Lowess/docker-templates-unraid
GitHub BranchVariable

Only pushes to this branch start a sync.

Target
GITHUB_BRANCH
Default
main
Value
main
Git HTTPS URLVariable

Public HTTPS Git URL used for fetches; no host SSH keys are mounted.

Target
GIT_REMOTE_URL
Default
https://github.com/Lowess/docker-templates-unraid.git
Value
https://github.com/Lowess/docker-templates-unraid.git
Clean untracked repository filesVariable

Run git clean -fd after reset, matching the previous script. Disable only if this checkout intentionally contains untracked files.

Target
GIT_CLEAN
Default
true
Value
true
Sync on container startVariable

Reconcile templates at startup to recover from missed webhook deliveries.

Target
SYNC_ON_START
Default
true
Value
true