feat: first release
All checks were successful
Create Release PR / Create Release PR (push) Successful in 20s

This commit is contained in:
2026-07-13 13:31:51 +02:00
parent d98e219de5
commit 8d0db9beba
9 changed files with 85 additions and 73 deletions

View File

@@ -8,6 +8,10 @@ __pycache__/
.env
.env.example
docker/
docker-compose.yml
.gitea/
.release-please-manifest.json
CHANGELOG.md
README.md
# Local dev runtime dirs
data/

View File

@@ -22,9 +22,15 @@ DOCKHAND_VERIFY_TLS=true
# --- Timezone (display, filenames, cron) ---
TZ=Europe/Berlin
# --- Paths (usually only set inside Docker) ---
# --- Prod deployment (docker-compose.yml reads these for HOST paths) ---
# Where the .tar files land / where config.json is persisted on the host:
BACKUP_DIR=/mnt/user/backups/stacks
CONFIG_DIR=/mnt/user/appdata/dockhand-backup
# Host root that gets mounted read-only (source of the bind paths to back up):
BIND_ROOT=/mnt/user
# --- Container-internal paths (rarely changed) ---
# BACKUP_ROOT=/backup
# DATA_DIR=/data
# --- Authentik OIDC for THIS tool's web UI (optional) ---
# Leave empty to keep the UI open (e.g. behind a reverse proxy).

View File

@@ -6,46 +6,51 @@ on:
permissions:
contents: write
env:
REGISTRY: git.tdpi.dev
IMAGE: git.tdpi.dev/tdpi/Dockhand_Backup
REPO_SLUG: TDPI/Dockhand_Backup
jobs:
deploy:
name: Build + Push to Packages + Deploy to Prod
runs-on: ubuntu-latest
steps:
- name: Checkout Repo
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set image tag
id: vars
run: |
# Extrahiert den Tag-Namen direkt aus dem Release-Event (z.B. v1.17.8)
# Tag-Name direkt aus dem Release-Event (z.B. v1.2.3)
TAG="${{ gitea.event.release.tag_name }}"
# Der Tag-Name enthält bereits das 'v'
echo "TAG=$TAG" >> "$GITHUB_ENV"
- name: Login to Gitea Packages
run: |
echo "${{ secrets.GT_TOKEN }}" | docker login git.tdpi.dev -u ${{ gitea.actor }} --password-stdin
echo "${{ secrets.GT_TOKEN }}" | docker login ${REGISTRY} -u ${{ gitea.actor }} --password-stdin
- name: Build Image
run: |
docker build -t git.tdpi.dev/tdpi/shopify-helper:${TAG} .
docker tag git.tdpi.dev/tdpi/shopify-helper:${TAG} git.tdpi.dev/tdpi/shopify-helper:latest
# Dockerfile liegt in docker/, Build-Context ist das Repo-Root.
docker build -f docker/Dockerfile -t ${IMAGE}:${TAG} .
docker tag ${IMAGE}:${TAG} ${IMAGE}:latest
- name: Update docker-compose.yml tag
env:
GIT_TOKEN: ${{ secrets.GT_TOKEN }}
run: |
sed -i "s|image: git.tdpi.dev/tdpi/shopify-helper:.*|image: git.tdpi.dev/tdpi/shopify-helper:${TAG}|" docker-compose.yml
sed -i "s|image: ${IMAGE}:.*|image: ${IMAGE}:${TAG}|" docker-compose.yml
git config user.name "Gitea Actions"
git config user.email "actions@git.tdpi.dev"
git add docker-compose.yml
git commit -m "chore: update docker-compose tag to ${TAG}"
git push https://x-access-token:${GIT_TOKEN}@git.tdpi.dev/TDPI/Shopify-Helper.git HEAD:main
git commit -m "chore: update docker-compose tag to ${TAG}" || echo "no changes to commit"
git push https://x-access-token:${GIT_TOKEN}@${REGISTRY}/${REPO_SLUG}.git HEAD:main
- name: Push Image
run: |
docker push git.tdpi.dev/tdpi/shopify-helper:${TAG}
docker push git.tdpi.dev/tdpi/shopify-helper:latest
docker push ${IMAGE}:${TAG}
docker push ${IMAGE}:latest

View File

@@ -32,7 +32,7 @@ jobs:
- name: Create Release PR
env:
GIT_TOKEN: ${{ secrets.GT_TOKEN }}
REPO: "TDPI/Shopify-Helper"
REPO: "TDPI/Dockhand_Backup"
run: |
python3 << 'EOF'
import re

View File

@@ -33,7 +33,7 @@ jobs:
git config user.name "Gitea Actions"
git config user.email "actions@git.tdpi.dev"
git tag -a "v${{ steps.version.outputs.version }}" -m "Release v${{ steps.version.outputs.version }}"
git push https://x-access-token:${GIT_TOKEN}@git.tdpi.dev/TDPI/Shopify-Helper.git "v${{ steps.version.outputs.version }}"
git push https://x-access-token:${GIT_TOKEN}@git.tdpi.dev/TDPI/Dockhand_Backup.git "v${{ steps.version.outputs.version }}"
- name: Create Release
env:
@@ -51,7 +51,7 @@ jobs:
'{tag_name: $tag, name: $name, body: $body, draft: false, prerelease: false}')
# Führt den Curl-Befehl mit der sicheren Payload aus
curl -X POST "https://git.tdpi.dev/api/v1/repos/TDPI/Shopify-Helper/releases" \
curl -X POST "https://git.tdpi.dev/api/v1/repos/TDPI/Dockhand_Backup/releases" \
-H "Authorization: token $GIT_TOKEN" \
-H "Content-Type: application/json" \
-d "$PAYLOAD"

View File

@@ -0,0 +1,3 @@
{
".": "0.0.0"
}

View File

@@ -63,17 +63,18 @@ sichern), setze `DOCKHAND_URL`/`DOCKHAND_USER`/`DOCKHAND_PASS`.
## Deployment (Docker / Unraid)
Die Prod-Compose (`docker-compose.yml`) zieht das fertige Image aus der Gitea-Registry und
liest **alle** Werte aus einer `.env` daneben (nichts Sensibles im Repo). Kein Port-Mapping —
der Container hängt im externen Netzwerk `nginx` hinter dem Reverse-Proxy.
```bash
cp docker/docker-compose.example.yml docker-compose.yml
# Pfade, Secrets und OIDC anpassen
docker compose up -d --build
cp .env.example .env # Secrets/Pfade eintragen (DOCKHAND_*, FLASK_SECRET_KEY, BACKUP_DIR, ...)
docker compose up -d
```
Die UI läuft auf Port `8080`. Wichtige Env-Vars: `DOCKHAND_URL`, `DOCKHAND_USER`,
`DOCKHAND_PASS`, `DOCKHAND_ENV_ID`, `FLASK_SECRET_KEY`, optional `OIDC_*`.
Der Build kompiliert Tailwind mit der Standalone-CLI in `app/static/app.css` — zur Laufzeit
wird **kein CDN** benötigt.
Voraussetzung: das externe Docker-Netzwerk `nginx` existiert und das Image wurde per CI
gebaut/gepusht (siehe `.gitea/workflows/`). Das Image kompiliert Tailwind mit der
Standalone-CLI in `app/static/app.css` — zur Laufzeit wird **kein CDN** benötigt.
## Projektstruktur
@@ -88,8 +89,10 @@ app/ # Python-Package
routes.py # Flask-Routes
templates/ # Jinja + Tailwind
static/ # src.css, app.css (build), vendor/sortable.min.js
docker/ # Dockerfile + compose-Beispiel (NICHT im Image)
wsgi.py # Entrypoint
docker/Dockerfile # Multi-stage build (NICHT im Image)
docker-compose.yml # Prod-Compose (Registry-Image, .env-gesteuert)
.gitea/workflows/ # CI: build+push Image, Release-Automation
wsgi.py # Entrypoint
```
## Hinweis

35
docker-compose.yml Normal file
View File

@@ -0,0 +1,35 @@
# Production compose — pulls the pre-built image from the Gitea registry.
# The "Deploy on Release" workflow bumps the image tag on this file.
# ALL config comes from a .env next to this file (NOT committed). No secrets here.
services:
dockhand-backup:
image: git.tdpi.dev/tdpi/Dockhand_Backup:latest
container_name: dockhand-backup
restart: unless-stopped
environment:
DOCKHAND_URL: "${DOCKHAND_URL}"
DOCKHAND_USER: "${DOCKHAND_USER}"
DOCKHAND_PASS: "${DOCKHAND_PASS}"
DOCKHAND_PROVIDER: "${DOCKHAND_PROVIDER:-local}"
DOCKHAND_ENV_ID: "${DOCKHAND_ENV_ID}"
DOCKHAND_VERIFY_TLS: "${DOCKHAND_VERIFY_TLS:-true}"
FLASK_SECRET_KEY: "${FLASK_SECRET_KEY}"
OIDC_ISSUER: "${OIDC_ISSUER:-}"
OIDC_CLIENT_ID: "${OIDC_CLIENT_ID:-}"
OIDC_CLIENT_SECRET: "${OIDC_CLIENT_SECRET:-}"
OIDC_REDIRECT_URI: "${OIDC_REDIRECT_URI:-}"
TZ: "${TZ:-Europe/Berlin}"
volumes:
- /mnt/user/backup/docker:/backup
- /mnt/cache/appdata/backupdocker:/data
# Mount ONLY the host paths you want backed up, identically mapped.
# Anything not mounted (or switched off per bind in the UI) is skipped.
- /mnt/cache/appdata:/mnt/cache/appdata
- /mnt/docker/appdata:/mnt/docker/appdata
- /mnt/user/appdata:/mnt/user/appdata
networks:
- nginx
networks:
nginx:
external: true

View File

@@ -1,44 +0,0 @@
# Example deployment for Unraid / Docker.
# Copy to docker-compose.yml, adjust paths & secrets, then: docker compose up -d --build
services:
dockhand-backup:
build:
context: ..
dockerfile: docker/Dockerfile
image: dockhand-backup:latest
container_name: dockhand-backup
restart: unless-stopped
ports:
- "8080:8080"
environment:
# --- Dockhand connection (daemon logs in with these) ---
DOCKHAND_URL: "http://192.168.1.10:3000"
DOCKHAND_USER: "backup-service"
DOCKHAND_PASS: "change-me"
DOCKHAND_PROVIDER: "local" # local user/password login in Dockhand
DOCKHAND_ENV_ID: "1"
DOCKHAND_VERIFY_TLS: "true"
# --- Flask ---
FLASK_SECRET_KEY: "generate-a-long-random-string"
# --- Authentik OIDC for THIS tool's web UI (optional) ---
# Leave unset to run the UI open (e.g. behind a reverse proxy).
OIDC_ISSUER: "" # e.g. https://auth.example.com/application/o/dockhand-backup/
OIDC_CLIENT_ID: ""
OIDC_CLIENT_SECRET: ""
OIDC_REDIRECT_URI: "" # e.g. https://backup.example.com/callback
TZ: "Europe/Berlin"
# DEV_MODE auto-off inside Docker; force with DEV_MODE: "false" if needed.
volumes:
# Backup output — pick where the .tar files land on the host:
- /mnt/user/backups/stacks:/backup
# JSON "DB" / config persistence:
- /mnt/user/appdata/dockhand-backup:/data
# IMPORTANT: bind-mount host paths must exist INSIDE the container at the
# SAME absolute path Dockhand reports. Mount ONLY what you want backed up —
# anything not mounted (or switched off per bind in the UI) is skipped.
- /mnt/user:/mnt/user:ro