Author SHA1 Message Date
pi-farm 25189f800b revert 2b8b8260b1
build-and-push.yaml / release-and-build (push) Canceled after 5s
revert add archive-tools
2026-10-07 10:05:39 +00:00
pi-farm 2b8b8260b1 add archive-tools
build-and-push.yaml / release-and-build (push) Canceled after 1m48s
2026-10-07 10:00:02 +00:00
pi-farm a2f1c987f8 .gitea/workflows/build-and-push.yaml aktualisiert
build-and-push.yaml / release-and-build (push) Successful in 25m5s
2026-10-06 15:59:13 +00:00
pi-farm 2be18e6fd2 README.md aktualisiert
build-and-push.yaml / release-and-build (push) Canceled after 16s
2026-10-06 15:39:04 +00:00
Gitea Action 0970dbefae .gitea/workflows/build-and-push.yaml aktualisiert [skip ci] 2026-10-06 15:30:06 +00:00
pi-farm 246e5e85d9 .gitea/workflows/build-and-push.yaml aktualisiert
build-and-push.yaml / release-and-build (push) Successful in 24m23s
2026-10-06 15:05:55 +00:00
pi-farm 694b13f01c .gitea/workflows/build-and-push.yaml aktualisiert
build-and-push.yaml / release-and-build (push) Canceled after 1m11s
2026-10-06 15:04:53 +00:00
pi-farm 8786971d24 .gitea/workflows/build-and-push.yaml aktualisiert
build-and-push.yaml / release-and-build (push) Failing after 16s
2026-10-06 13:42:43 +00:00
pi-farm c20986cf6c .gitea/workflows/build-and-push.yaml aktualisiert
build-and-push.yaml / release-and-build (push) Failing after 2s
2026-10-06 13:33:55 +00:00
pi-farm d16175d16b .gitea/workflows/build-and-push.yaml aktualisiert
build-and-push.yaml / release-and-build (push) Failing after 2s
2026-10-06 13:27:34 +00:00
pi-farm 516ff1a0fa .gitea/workflows/build-and-push.yaml aktualisiert
build-and-push.yaml / release-and-build (push) Failing after 3s
2026-10-06 13:24:32 +00:00
Gitea Action 901e9c94f4 [skip ci] 2026-08-09 05:29:22 +00:00
Gitea Action 835ca055c2 [skip ci] 2026-07-19 05:26:02 +00:00
Gitea Action b5fbadd560 [skip ci] 2026-06-28 05:27:55 +00:00
Gitea Action b6ed37f3b4 [skip ci] 2026-06-14 05:25:18 +00:00
Gitea Action ab19e63e94 build trixie-de latest [skip ci] 2026-06-04 11:41:44 +00:00
pi-farm 0609225281 build trixie-de latest
/ release-and-build (push) Successful in 24m1s
2026-06-04 11:17:51 +00:00
Gitea Action 9afb1e0794 Trixie build [skip ci] 2026-06-04 10:25:48 +00:00
pi-farm 5f0b994768 Trixie build
/ release-and-build (push) Successful in 24m19s
2026-06-04 10:01:36 +00:00
Gitea Action 0be6135e52 .gitea/workflows/build-and-push.yaml aktualisiert [skip ci] 2026-06-02 16:17:26 +00:00
pi-farm ec21aa2b9e .gitea/workflows/build-and-push.yaml aktualisiert
/ release-and-build (push) Successful in 18m35s
2026-06-02 15:58:56 +00:00
Gitea Action b27c3e257b [skip ci] 2026-06-02 15:04:59 +00:00
Gitea Action 284ee7462e [skip ci] 2026-05-24 05:22:59 +00:00
Gitea Action 4c6c8df7af [skip ci] 2026-05-10 05:21:05 +00:00
Gitea Action 05d51481d7 [skip ci] 2026-04-26 05:23:16 +00:00
Gitea Action d5a99d0f88 build for bookworm [skip ci] 2026-04-09 15:19:55 +00:00
pi-farm b6a8bc1f61 build for bookworm
/ release-and-build (push) Successful in 18m41s
2026-04-09 15:01:17 +00:00
Gitea Action eaf568bb9e build for trixie-de [skip ci] 2026-04-09 14:44:37 +00:00
pi-farm d5d9a5d07c build for trixie-de
/ release-and-build (push) Successful in 26m30s
2026-04-09 14:18:14 +00:00
Gitea Action a8870999a7 Merge pull request dev (#2) from dev into main Reviewed-on: #2 [skip ci] 2026-04-09 14:15:24 +00:00
pi-farm 9c795a58ee Merge pull request 'dev' (#2) from dev into main
/ release-and-build (push) Successful in 19m9s
Reviewed-on: #2
2026-04-09 13:56:20 +00:00
5 changed files with 573 additions and 251 deletions

No files matched your search

+253 -210
View File
@@ -8,6 +8,10 @@ on:
- cron: '0 5 * * 0' - cron: '0 5 * * 0'
workflow_dispatch: workflow_dispatch:
permissions:
contents: write
packages: write
jobs: jobs:
release-and-build: release-and-build:
runs-on: buildx-multiarch runs-on: buildx-multiarch
@@ -16,6 +20,7 @@ jobs:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4
with: with:
token: ${{ secrets.RUNNER_TOKEN }}
fetch-depth: 0 fetch-depth: 0
- name: Prepare Environment and Read Config - name: Prepare Environment and Read Config
@@ -59,8 +64,7 @@ jobs:
- name: Login to Gitea Registry - name: Login to Gitea Registry
run: | run: |
echo "${{ secrets.REGISTRY_PASSWORD }}" | docker login \ echo "${{ secrets.RUNNER_TOKEN }}" | docker login git.pi-farm.de -u "${{ gitea.actor }}" --password-stdin
git.pi-farm.de -u ${{ secrets.REGISTRY_USER }} --password-stdin
- name: Check for Real Changes - name: Check for Real Changes
id: check_changes id: check_changes
@@ -125,6 +129,7 @@ jobs:
ARGS_HASH=${{ steps.prep.outputs.build_args_hash }} ARGS_HASH=${{ steps.prep.outputs.build_args_hash }}
BASE=${{ steps.prep.outputs.base_image }} BASE=${{ steps.prep.outputs.base_image }}
REPO_PURE=${{ steps.prep.outputs.repo_pure }} REPO_PURE=${{ steps.prep.outputs.repo_pure }}
DOCKERHUB_REPO="${{ secrets.DOCKERHUB_USERNAME }}/$REPO_PURE"
set -a set -a
source <(grep -v '^#' buildargs.env | sed 's/\r$//') source <(grep -v '^#' buildargs.env | sed 's/\r$//')
@@ -138,14 +143,26 @@ jobs:
BASE_SHA=$(docker buildx imagetools inspect $BASE --format '{{json .Manifest.Digest}}' 2>/dev/null | tr -d '"' || echo "unknown") BASE_SHA=$(docker buildx imagetools inspect $BASE --format '{{json .Manifest.Digest}}' 2>/dev/null | tr -d '"' || echo "unknown")
docker buildx build "${DOCKER_ARGS[@]}" -t "$IMAGE_GITEA:tmp-amd64" \ # Bereite die Tags für den initialen Build vor (Gitea immer, Docker Hub optional)
AMD_TAGS=("-t" "$IMAGE_GITEA:tmp-amd64")
ARM_TAGS=("-t" "$IMAGE_GITEA:tmp-arm64")
if [[ "$PUSH" == *"dockerhub"* ]]; then
AMD_TAGS+=("-t" "$DOCKERHUB_REPO:tmp-amd64")
ARM_TAGS+=("-t" "$DOCKERHUB_REPO:tmp-arm64")
fi
# Build AMD64 & Push zu allen Zielen
docker buildx build "${DOCKER_ARGS[@]}" "${AMD_TAGS[@]}" \
--pull --platform linux/amd64 -f Dockerfile \ --pull --platform linux/amd64 -f Dockerfile \
--label "pi_farm.base_digest=$BASE_SHA" --label "pi_farm.args_hash=$ARGS_HASH" --push . --label "pi_farm.base_digest=$BASE_SHA" --label "pi_farm.args_hash=$ARGS_HASH" --push .
docker buildx build "${DOCKER_ARGS[@]}" -t "$IMAGE_GITEA:tmp-arm64" \ # Build ARM64 & Push zu allen Zielen
docker buildx build "${DOCKER_ARGS[@]}" "${ARM_TAGS[@]}" \
--pull --platform linux/arm64 -f Dockerfile.aarch64 \ --pull --platform linux/arm64 -f Dockerfile.aarch64 \
--label "pi_farm.base_digest=$BASE_SHA" --label "pi_farm.args_hash=$ARGS_HASH" --push . --label "pi_farm.base_digest=$BASE_SHA" --label "pi_farm.args_hash=$ARGS_HASH" --push .
# 1. Manifest auf Gitea erstellen (aus Gitea Temp-Tags)
GITEA_MANIFEST_TAGS=("-t" "$IMAGE_GITEA:$TAG") GITEA_MANIFEST_TAGS=("-t" "$IMAGE_GITEA:$TAG")
if [[ "$BUILD_TAG_LATEST" == "y" ]]; then if [[ "$BUILD_TAG_LATEST" == "y" ]]; then
GITEA_MANIFEST_TAGS+=("-t" "$IMAGE_GITEA:latest") GITEA_MANIFEST_TAGS+=("-t" "$IMAGE_GITEA:latest")
@@ -155,232 +172,258 @@ jobs:
--annotation "index:pi_farm.base_digest=$BASE_SHA" --annotation "index:pi_farm.args_hash=$ARGS_HASH" \ --annotation "index:pi_farm.base_digest=$BASE_SHA" --annotation "index:pi_farm.args_hash=$ARGS_HASH" \
"${GITEA_MANIFEST_TAGS[@]}" $IMAGE_GITEA:tmp-amd64 $IMAGE_GITEA:tmp-arm64 "${GITEA_MANIFEST_TAGS[@]}" $IMAGE_GITEA:tmp-amd64 $IMAGE_GITEA:tmp-arm64
# 2. Manifest auf Docker Hub erstellen (aus Docker Hub Temp-Tags!)
if [[ "$PUSH" == *"dockerhub"* ]]; then if [[ "$PUSH" == *"dockerhub"* ]]; then
DOCKERHUB_REPO="${{ secrets.DOCKERHUB_USERNAME }}/$REPO_PURE"
DH_MANIFEST_TAGS=("-t" "$DOCKERHUB_REPO:$TAG") DH_MANIFEST_TAGS=("-t" "$DOCKERHUB_REPO:$TAG")
if [[ "$BUILD_TAG_LATEST" == "y" ]]; then if [[ "$BUILD_TAG_LATEST" == "y" ]]; then
DH_MANIFEST_TAGS+=("-t" "$DOCKERHUB_REPO:latest") DH_MANIFEST_TAGS+=("-t" "$DOCKERHUB_REPO:latest")
fi fi
# WICHTIG: Hier werden jetzt als Quelle die Docker Hub Temp-Tags genutzt!
docker buildx imagetools create \ docker buildx imagetools create \
--annotation "index:pi_farm.base_digest=$BASE_SHA" --annotation "index:pi_farm.args_hash=$ARGS_HASH" \ --annotation "index:pi_farm.base_digest=$BASE_SHA" --annotation "index:pi_farm.args_hash=$ARGS_HASH" \
"${DH_MANIFEST_TAGS[@]}" $IMAGE_GITEA:tmp-amd64 $IMAGE_GITEA:tmp-arm64 "${DH_MANIFEST_TAGS[@]}" $DOCKERHUB_REPO:tmp-amd64 $DOCKERHUB_REPO:tmp-arm64
fi fi
- name: Update Documentation and Compose - name: Update Documentation and Compose
id: update_doc id: update_doc
if: steps.check_changes.outputs.should_build == 'true' if: steps.check_changes.outputs.should_build == 'true'
run: | run: |
set -x set -x
export TZ=Europe/Berlin export TZ=Europe/Berlin
CURRENT_TIME=$(date '+%d.%m.%Y %H:%M') CURRENT_TIME=$(date '+%d.%m.%Y %H:%M')
BUILD_TAG="${{ steps.prep.outputs.docker_tag }}" BUILD_TAG="${{ steps.prep.outputs.docker_tag }}"
FULL_URL="${{ steps.prep.outputs.image_name }}" FULL_URL="${{ steps.prep.outputs.image_name }}"
REPO_PURE="${{ steps.prep.outputs.repo_pure }}" REPO_PURE="${{ steps.prep.outputs.repo_pure }}"
BASE_IMAGE="${{ steps.prep.outputs.base_image }}" BASE_IMAGE="${{ steps.prep.outputs.base_image }}"
if [ ! -f "buildargs.env" ]; then echo "❌ buildargs.env missing!"; exit 1; fi if [ ! -f "buildargs.env" ]; then echo "❌ buildargs.env missing!"; exit 1; fi
grep -v '^#' buildargs.env | sed 's/\r$//' > cleaned_env.sh grep -v '^#' buildargs.env | sed 's/\r$//' > cleaned_env.sh
set -a set -a
source ./cleaned_env.sh source ./cleaned_env.sh
set +a set +a
if [ -f "Dockerfile.aarch64" ]; then ARM_STATUS="✅ Active"; else ARM_STATUS="❌ Not supported"; fi if [ -f "Dockerfile.aarch64" ]; then ARM_STATUS="✅ Active"; else ARM_STATUS="❌ Not supported"; fi
cat << 'EOF' > commit_msg.txt cat << 'EOF' > commit_msg.txt
${{ gitea.event.head_commit.message }} ${{ gitea.event.head_commit.message }}
EOF EOF
COMMIT_MSG=$(sed 's/\[skip ci\]//g' commit_msg.txt | xargs) COMMIT_MSG=$(sed 's/\[skip ci\]//g' commit_msg.txt | xargs)
wget -q https://git.pi-farm.de/pi-farm/templates/raw/branch/main/README.template -O README.template || echo "Warnung: README Template fehlt" # 1. Authentifizierter Download der Templates via curl (-f bricht bei HTTP-Fehlern ab)
wget -q https://git.pi-farm.de/pi-farm/templates/raw/branch/main/docker-compose.template -O docker-compose.template || echo "Warnung: Compose Template fehlt" TOKEN="${{ secrets.RUNNER_TOKEN }}"
curl -sSLf -H "Authorization: token $TOKEN" \
NEW_ROW="| **$BUILD_TAG** | $CURRENT_TIME | $COMMIT_MSG ✅ |" "https://git.pi-farm.de/pi-farm/templates/raw/branch/main/README.template" \
if [ -f "VERSION.history" ]; then -o README.template || echo "Warnung: README Template konnte nicht geladen werden"
grep -v "| **$BUILD_TAG** |" VERSION.history > VERSION.history.tmp || true
echo "$NEW_ROW" > VERSION.history curl -sSLf -H "Authorization: token $TOKEN" \
cat VERSION.history.tmp >> VERSION.history "https://git.pi-farm.de/pi-farm/templates/raw/branch/main/docker-compose.template" \
rm VERSION.history.tmp -o docker-compose.template || echo "Warnung: Compose Template konnte nicht geladen werden"
else
echo "$NEW_ROW" > VERSION.history # 2. Sicherheitsprüfung: Falls Gitea trotz -f eine HTML-Login-Seite ausgibt, Datei sofort verwerfen
fi for t_file in README.template docker-compose.template; do
HISTORY_CONTENT=$(cat VERSION.history) if [ -f "$t_file" ] && grep -qi "<!DOCTYPE html>" "$t_file"; then
echo "❌ FEHLER: $t_file ist eine HTML-Loginseite! Download verworfen."
ENV_BLOCK_CONTENT="" rm -f "$t_file"
env_vars=$(grep '^ENV_' buildargs.env | grep -v '^#' | tr -d '\r' || true)
if [ -n "$env_vars" ]; then
ENV_BLOCK_CONTENT=" environment:\n"
while read -r line; do
[ -z "$line" ] && continue
key=$(echo "$line" | cut -d= -f1); val=$(echo "$line" | cut -d= -f2-); clean_key=${key#ENV_}
ENV_BLOCK_CONTENT="${ENV_BLOCK_CONTENT} - ${clean_key}=${val}\n"
done <<< "$env_vars"
fi
PORTS_BLOCK_CONTENT=""
port_vars=$(grep '^PORT_' buildargs.env | grep -v '^#' | tr -d '\r' || true)
if [ -n "$port_vars" ]; then
PORTS_BLOCK_CONTENT=" ports:\n"
while read -r line; do
[ -z "$line" ] && continue
val=$(echo "$line" | cut -d= -f2-); PORTS_BLOCK_CONTENT="${PORTS_BLOCK_CONTENT} - ${val}\n"
done <<< "$port_vars"
fi
VOL_BLOCK_CONTENT=""
vol_vars=$(grep '^VOL_' buildargs.env | grep -v '^#' | tr -d '\r' || true)
if [ -n "$vol_vars" ]; then
VOL_BLOCK_CONTENT=" volumes:\n"
while read -r line; do
[ -z "$line" ] && continue
val=$(echo "$line" | cut -d= -f2-); VOL_BLOCK_CONTENT="${VOL_BLOCK_CONTENT} - ${val}\n"
done <<< "$vol_vars"
fi
{
echo "docker run -d \\"
echo " --name $REPO_PURE \\"
echo " --restart unless-stopped \\"
all_params=$(grep -E '^(PORT_|ENV_|VOL_)' buildargs.env | grep -v '^#' | sed 's/\r$//' || true)
if [ -n "$all_params" ]; then
while read -r line; do
[ -z "$line" ] && continue
if [[ "$line" =~ ^PORT_ ]]; then
val=$(echo "$line" | cut -d= -f2-)
echo " -p ${val} \\"
elif [[ "$line" =~ ^ENV_ ]]; then
key=$(echo "$line" | cut -d= -f1); clean_key=${key#ENV_}; val=$(echo "$line" | cut -d= -f2-)
echo " -e ${clean_key}=${val} \\"
elif [[ "$line" =~ ^VOL_ ]]; then
val=$(echo "$line" | cut -d= -f2-)
echo " -v ${val} \\"
fi fi
done <<< "$all_params" done
fi
echo " $FULL_URL:$BUILD_TAG" NEW_ROW="| **$BUILD_TAG** | $CURRENT_TIME | $COMMIT_MSG ✅ |"
} > docker_run_block.txt if [ -f "VERSION.history" ]; then
grep -v "| **$BUILD_TAG** |" VERSION.history > VERSION.history.tmp || true
DOCKERHUB_LINK_CONTENT="" echo "$NEW_ROW" > VERSION.history
if [[ "${{ steps.prep.outputs.push_targets }}" == *"dockerhub"* ]]; then cat VERSION.history.tmp >> VERSION.history
DH_USER="${{ secrets.DOCKERHUB_USERNAME }}" rm VERSION.history.tmp
DOCKERHUB_LINK_CONTENT="[![Docker Hub](https://img.shields.io/badge/docker-hub-blue?logo=docker&logoColor=white)](https://hub.docker.com/r/${DH_USER}/${REPO_PURE})" else
fi echo "$NEW_ROW" > VERSION.history
fi
process_template() { HISTORY_CONTENT=$(cat VERSION.history)
local template=$1; local output=$2
[ ! -f "$template" ] && return ENV_BLOCK_CONTENT=""
cp "$template" "$output" env_vars=$(grep '^ENV_' buildargs.env | grep -v '^#' | tr -d '\r' || true)
if [ -n "$env_vars" ]; then
ENV_BLOCK_CONTENT=" environment:\n"
while read -r line; do
[ -z "$line" ] && continue
key=$(echo "$line" | cut -d= -f1); val=$(echo "$line" | cut -d= -f2-); clean_key=${key#ENV_}
ENV_BLOCK_CONTENT="${ENV_BLOCK_CONTENT} - ${clean_key}=${val}\n"
done <<< "$env_vars"
fi
PORTS_BLOCK_CONTENT=""
port_vars=$(grep '^PORT_' buildargs.env | grep -v '^#' | tr -d '\r' || true)
if [ -n "$port_vars" ]; then
PORTS_BLOCK_CONTENT=" ports:\n"
while read -r line; do
[ -z "$line" ] && continue
val=$(echo "$line" | cut -d= -f2-); PORTS_BLOCK_CONTENT="${PORTS_BLOCK_CONTENT} - ${val}\n"
done <<< "$port_vars"
fi
VOL_BLOCK_CONTENT=""
vol_vars=$(grep '^VOL_' buildargs.env | grep -v '^#' | tr -d '\r' || true)
if [ -n "$vol_vars" ]; then
VOL_BLOCK_CONTENT=" volumes:\n"
while read -r line; do
[ -z "$line" ] && continue
val=$(echo "$line" | cut -d= -f2-); VOL_BLOCK_CONTENT="${VOL_BLOCK_CONTENT} - ${val}\n"
done <<< "$vol_vars"
fi
{
echo "docker run -d \\"
echo " --name $REPO_PURE \\"
echo " --restart unless-stopped \\"
all_params=$(grep -E '^(PORT_|ENV_|VOL_)' buildargs.env | grep -v '^#' | sed 's/\r$//' || true)
if [ -n "$all_params" ]; then
while read -r line; do
[ -z "$line" ] && continue
if [[ "$line" =~ ^PORT_ ]]; then
val=$(echo "$line" | cut -d= -f2-)
echo " -p ${val} \\"
elif [[ "$line" =~ ^ENV_ ]]; then
key=$(echo "$line" | cut -d= -f1); clean_key=${key#ENV_}; val=$(echo "$line" | cut -d= -f2-)
echo " -e ${clean_key}=${val} \\"
elif [[ "$line" =~ ^VOL_ ]]; then
val=$(echo "$line" | cut -d= -f2-)
echo " -v ${val} \\"
fi
done <<< "$all_params"
fi
echo " $FULL_URL:$BUILD_TAG"
} > docker_run_block.txt
DOCKERHUB_LINK_CONTENT=""
if [[ "${{ steps.prep.outputs.push_targets }}" == *"dockerhub"* ]]; then
DH_USER="${{ secrets.DOCKERHUB_USERNAME }}"
DOCKERHUB_LINK_CONTENT="[![Docker Hub](https://img.shields.io/badge/docker-hub-blue?logo=docker&logoColor=white)](https://hub.docker.com/r/${DH_USER}/${REPO_PURE})"
fi
# Template-Verarbeitung via Python (verhindert awk-Abstürze bei Zeilenumbrüchen)
process_template() {
local template=$1; local output=$2
[ ! -f "$template" ] && return
cp "$template" "$output"
export REPO_PURE FULL_URL BUILD_TAG BASE_IMAGE ARM_STATUS CURRENT_TIME \
HISTORY_CONTENT DOCKERHUB_LINK_CONTENT ENV_BLOCK_CONTENT \
PORTS_BLOCK_CONTENT VOL_BLOCK_CONTENT DESCRIPTION
python3 -c '
import os, sys
output = sys.argv[1]
with open(output, "r", encoding="utf-8") as f:
content = f.read()
content = content.replace("__REPO_NAME__", os.environ.get("REPO_PURE", ""))
content = content.replace("__FULL_URL__", os.environ.get("FULL_URL", ""))
content = content.replace("__BUILD_TAG__", os.environ.get("BUILD_TAG", ""))
content = content.replace("__BASE_IMAGE__", os.environ.get("BASE_IMAGE", ""))
content = content.replace("__ARM_STATUS__", os.environ.get("ARM_STATUS", ""))
content = content.replace("__CURRENT_DATE__", os.environ.get("CURRENT_TIME", ""))
content = content.replace("__HISTORY_CONTENT__", os.environ.get("HISTORY_CONTENT", ""))
content = content.replace("__DOCKERHUB_LINK__", os.environ.get("DOCKERHUB_LINK_CONTENT", ""))
content = content.replace("__ENV_BLOCK__", os.environ.get("ENV_BLOCK_CONTENT", "").replace("\\n", "\n"))
content = content.replace("__PORTS_BLOCK__", os.environ.get("PORTS_BLOCK_CONTENT", "").replace("\\n", "\n"))
content = content.replace("__VOL_BLOCK__", os.environ.get("VOL_BLOCK_CONTENT", "").replace("\\n", "\n"))
content = content.replace("__DESCRIPTION__", os.environ.get("DESCRIPTION", "Keine Beschreibung."))
sed -i "s|__REPO_NAME__|$REPO_PURE|g" "$output" if "__DOCKER_RUN__" in content and os.path.exists("docker_run_block.txt"):
sed -i "s|__FULL_URL__|$FULL_URL|g" "$output" with open("docker_run_block.txt", "r", encoding="utf-8") as f:
sed -i "s|__BUILD_TAG__|$BUILD_TAG|g" "$output" content = content.replace("__DOCKER_RUN__", f.read())
sed -i "s|__BASE_IMAGE__|$BASE_IMAGE|g" "$output"
sed -i "s|__ARM_STATUS__|$ARM_STATUS|g" "$output"
sed -i "s|__CURRENT_DATE__|$CURRENT_TIME|g" "$output"
awk -v r="$HISTORY_CONTENT" '{gsub(/__HISTORY_CONTENT__/, r)}1' "$output" > "$output.tmp" && mv "$output.tmp" "$output" if "__COMPOSE_BLOCK__" in content and os.path.exists("docker-compose.yml"):
awk -v r="$DOCKERHUB_LINK_CONTENT" '{gsub(/__DOCKERHUB_LINK__/, r)}1' "$output" > "$output.tmp" && mv "$output.tmp" "$output" with open("docker-compose.yml", "r", encoding="utf-8") as f:
content = content.replace("__COMPOSE_BLOCK__", f.read())
if grep -q "__DOCKER_RUN__" "$output" && [ -f "docker_run_block.txt" ]; then
sed -e '/__DOCKER_RUN__/{r docker_run_block.txt' -e 'd;}' "$output" > "$output.tmp" && mv "$output.tmp" "$output"
fi
if grep -q "__COMPOSE_BLOCK__" "$output" && [ -f "docker-compose.yml" ]; then with open(output, "w", encoding="utf-8") as f:
sed -e '/__COMPOSE_BLOCK__/{r docker-compose.yml' -e 'd;}' "$output" > "$output.tmp" && mv "$output.tmp" "$output" f.write(content)
fi ' "$output"
}
if grep -q "__ENV_BLOCK__" "$output"; then process_template "docker-compose.template" "docker-compose.yml"
awk -v r="$(echo -e "$ENV_BLOCK_CONTENT")" '{gsub(/__ENV_BLOCK__/, r)}1' "$output" > "$output.tmp" && mv "$output.tmp" "$output" process_template "README.template" "README.md"
fi
awk -v r="$(echo -e "$PORTS_BLOCK_CONTENT")" '{gsub(/__PORTS_BLOCK__/, r)}1' "$output" > "$output.tmp" && mv "$output.tmp" "$output" echo "FINAL_MSG=$COMMIT_MSG" >> $GITHUB_ENV
awk -v r="$(echo -e "$VOL_BLOCK_CONTENT")" '{gsub(/__VOL_BLOCK__/, r)}1' "$output" > "$output.tmp" && mv "$output.tmp" "$output" echo "DESCRIPTION<<EOF" >> $GITHUB_ENV
echo -e "$DESCRIPTION" >> $GITHUB_ENV
echo "EOF" >> $GITHUB_ENV
if grep -q "__DESCRIPTION__" "$output"; then - name: Push README to Docker Hub
awk -v r="$(echo -e "${DESCRIPTION:-Keine Beschreibung.}")" '{gsub(/__DESCRIPTION__/, r)}1' "$output" > "$output.tmp" && mv "$output.tmp" "$output" if: steps.check_changes.outputs.should_build == 'true' && contains(steps.prep.outputs.push_targets, 'dockerhub')
fi run: |
} if ! command -v jq &> /dev/null; then
apt-get update && apt-get install -y jq || apk add --no-cache jq || true
process_template "docker-compose.template" "docker-compose.yml" fi
process_template "README.template" "README.md"
echo "🚀 Starting update README on Docker Hub..."
echo "FINAL_MSG=$COMMIT_MSG" >> $GITHUB_ENV
echo "DESCRIPTION<<EOF" >> $GITHUB_ENV TOKEN=$(curl -s -X POST "https://hub.docker.com/v2/users/login/" \
echo -e "$DESCRIPTION" >> $GITHUB_ENV -H "Content-Type: application/json" \
echo "EOF" >> $GITHUB_ENV -d "{\"username\": \"${{ secrets.DOCKERHUB_USERNAME }}\", \"password\": \"${{ secrets.DOCKERHUB_TOKEN }}\"}" | jq -r .token)
- name: Push README to Docker Hub if [ "$TOKEN" == "null" ] || [ -z "$TOKEN" ]; then
if: steps.check_changes.outputs.should_build == 'true' && contains(steps.prep.outputs.push_targets, 'dockerhub') echo "❌ Error: No login-token available. Check your credentials!"
run: | exit 1
if ! command -v jq &> /dev/null; then fi
apt-get update && apt-get install -y jq || apk add --no-cache jq || true
fi REPO_PURE="${{ steps.prep.outputs.repo_pure }}"
DH_USER="${{ secrets.DOCKERHUB_USERNAME }}"
echo "🚀 Starting update README on Docker Hub..."
SHORT_DESC=$(echo -e "${{ env.DESCRIPTION }}" | head -n 1 | cut -c 1-100)
TOKEN=$(curl -s -X POST "https://hub.docker.com/v2/users/login/" \ [ -z "$SHORT_DESC" ] && SHORT_DESC="Docker Image for $REPO_PURE"
-H "Content-Type: application/json" \
-d "{\"username\": \"${{ secrets.DOCKERHUB_USERNAME }}\", \"password\": \"${{ secrets.DOCKERHUB_TOKEN }}\"}" | jq -r .token) echo "📦 Processing README.md (${REPO_PURE})..."
if [ "$TOKEN" == "null" ] || [ -z "$TOKEN" ]; then jq -n \
echo "❌ Error: No login-token available. Check your credentials!" --arg desc "$SHORT_DESC" \
exit 1 --rawfile full_desc README.md \
fi '{description: $desc, full_description: $full_desc}' > payload.json
REPO_PURE="${{ steps.prep.outputs.repo_pure }}" echo "📤 Sending data to Docker Hub API..."
DH_USER="${{ secrets.DOCKERHUB_USERNAME }}" RESPONSE=$(curl -s -w "\n%{http_code}" -X PATCH \
"https://hub.docker.com/v2/repositories/${DH_USER}/${REPO_PURE}/" \
SHORT_DESC=$(echo -e "${{ env.DESCRIPTION }}" | head -n 1 | cut -c 1-100) -H "Authorization: JWT ${TOKEN}" \
[ -z "$SHORT_DESC" ] && SHORT_DESC="Docker Image for $REPO_PURE" -H "Content-Type: application/json" \
-d @payload.json)
echo "📦 Processing README.md (${REPO_PURE})..."
HTTP_STATUS=$(echo "$RESPONSE" | tail -n 1)
jq -n \ BODY=$(echo "$RESPONSE" | head -n -1)
--arg desc "$SHORT_DESC" \
--rawfile full_desc README.md \ if [ "$HTTP_STATUS" -eq 200 ]; then
'{description: $desc, full_description: $full_desc}' > payload.json echo "✅ README update successfull (HTTP 200)."
else
echo "📤 Sending data to Docker Hub API..." echo "❌ Error on update! HTTP Status: $HTTP_STATUS"
RESPONSE=$(curl -s -w "\n%{http_code}" -X PATCH \ echo "Answer from Docker Hub: $BODY"
"https://hub.docker.com/v2/repositories/${DH_USER}/${REPO_PURE}/" \ exit 1
-H "Authorization: JWT ${TOKEN}" \ fi
-H "Content-Type: application/json" \
-d @payload.json) - name: Commit, Tag and Push Changes
if: steps.check_changes.outputs.should_build == 'true'
HTTP_STATUS=$(echo "$RESPONSE" | tail -n 1) run: |
BODY=$(echo "$RESPONSE" | head -n -1) git config --local user.email "action@pi-farm.de"
git config --local user.name "Gitea Action"
if [ "$HTTP_STATUS" -eq 200 ]; then
echo "✅ README update successfull (HTTP 200)." git add VERSION.history README.md docker-compose.yml
else
echo "❌ Error on update! HTTP Status: $HTTP_STATUS" git diff --quiet && git diff --staged --quiet || git commit -m "${{ env.FINAL_MSG }} [skip ci]"
echo "Answer from Docker Hub: $BODY"
exit 1 TARGET_TAG="${{ steps.prep.outputs.docker_tag }}"
fi git tag -f "$TARGET_TAG"
- name: Commit, Tag and Push Changes if [[ "${{ gitea.ref }}" == refs/tags/* ]]; then
if: steps.check_changes.outputs.should_build == 'true' echo "🏷️ Build aus Tag getriggert: $TARGET_TAG"
run: | git push -f origin "$TARGET_TAG"
git config --local user.email "action@pi-farm.de" else
git config --local user.name "Gitea Action" echo "🌿 Build aus Branch/Schedule getriggert: ${{ gitea.ref_name }}"
git push origin HEAD:${{ gitea.ref_name }}
git add VERSION.history README.md docker-compose.yml git push -f origin "$TARGET_TAG"
fi
git diff --quiet && git diff --staged --quiet || git commit -m "${{ env.FINAL_MSG }} [skip ci]"
TARGET_TAG="${{ steps.prep.outputs.docker_tag }}"
git tag -f "$TARGET_TAG"
if [[ "${{ gitea.ref }}" == refs/tags/* ]]; then
echo "🏷️ Build aus Tag getriggert: $TARGET_TAG"
git push -f origin "$TARGET_TAG"
else
echo "🌿 Build aus Branch/Schedule getriggert: ${{ gitea.ref_name }}"
git push origin HEAD:${{ gitea.ref_name }}
git push -f origin "$TARGET_TAG"
fi
- name: Cleanup Temporary Tags on Docker Hub - name: Cleanup Temporary Tags on Docker Hub
if: steps.check_changes.outputs.should_build == 'true' && contains(steps.prep.outputs.push_targets, 'dockerhub') if: steps.check_changes.outputs.should_build == 'true' && contains(steps.prep.outputs.push_targets, 'dockerhub')
+21 -22
View File
@@ -1,5 +1,5 @@
# base-image-debian-rdp-ldap # base-image-debian-rdp-ldap
Debian Desktop with LDAP-Authentication. To use behind Guacamole with LDAP-Authentication and pass-through to Debian-Desktop. Debian Desktop with LDAP-Authentication and Pulse-Audio. To use behind Guacamole with LDAP-Authentication and pass-through to Debian-Desktop.
[![Build Status](https://git.pi-farm.de/pi-farm/base-image-debian-rdp-ldap/actions/workflows/build-and-push.yaml/badge.svg)](https://git.pi-farm.de/pi-farm/base-image-debian-rdp-ldap/actions) [![Build Status](https://git.pi-farm.de/pi-farm/base-image-debian-rdp-ldap/actions/workflows/build-and-push.yaml/badge.svg)](https://git.pi-farm.de/pi-farm/base-image-debian-rdp-ldap/actions)
[![Gitea Repo](https://img.shields.io/badge/gitea-repository-blue?logo=gitea&logoColor=white)](__REPO_URL__) [![Gitea Repo](https://img.shields.io/badge/gitea-repository-blue?logo=gitea&logoColor=white)](__REPO_URL__)
@@ -11,18 +11,18 @@ This repository is built and pushed automatically.
### 🏗️ Platform Support ### 🏗️ Platform Support
| Architecture | Status | Base Image | Build Date | | Architecture | Status | Base Image | Build Date |
| :--- | :--- | :--- | :--- | | :--- | :--- | :--- | :--- |
| x86_64 (amd64) | ✅ Active | debian:bookworm | 09.04.2026 15:23 | | x86_64 (amd64) | ✅ Active | debian:trixie | 09.08.2026 07:29 |
| aarch64 (arm64) | ✅ Active | debian:bookworm | 09.04.2026 15:23 | | aarch64 (arm64) | ✅ Active | debian:trixie | 09.08.2026 07:29 |
### 🚀 Docker Pull ### 🚀 Docker Pull
```bash ```bash
docker pull git.pi-farm.de/pi-farm/base-image-debian-rdp-ldap:bookworm-de docker pull git.pi-farm.de/pi-farm/base-image-debian-rdp-ldap:trixie-de
``` ```
### 🚀 Docker Compose ### 🚀 Docker Compose
```yaml ```yaml
services: services:
base-image-debian-rdp-ldap: base-image-debian-rdp-ldap:
image: git.pi-farm.de/pi-farm/base-image-debian-rdp-ldap:bookworm-de image: git.pi-farm.de/pi-farm/base-image-debian-rdp-ldap:trixie-de
container_name: base-image-debian-rdp-ldap container_name: base-image-debian-rdp-ldap
restart: unless-stopped restart: unless-stopped
ports: ports:
@@ -50,26 +50,25 @@ docker run -d \
-e LDAP_SUDO_GROUP=YOUR-SUDO-USERS-GROUP \ -e LDAP_SUDO_GROUP=YOUR-SUDO-USERS-GROUP \
-v ./YOUR-PERSISTENT-FOLDER:/home \ -v ./YOUR-PERSISTENT-FOLDER:/home \
-p 3889 \ -p 3889 \
git.pi-farm.de/pi-farm/base-image-debian-rdp-ldap:bookworm-de git.pi-farm.de/pi-farm/base-image-debian-rdp-ldap:trixie-de
``` ```
*Last updated on: 09.04.2026 15:23* *Last updated on: 09.08.2026 07:29*
### 📜 Version History ### 📜 Version History
| Version | Date | Status | | Version | Date | Status |
| :--- | :--- | :--- | | :--- | :--- | :--- |
| **bookworm-de** | 09.04.2026 15:23 | ✅ | | **trixie-de** | 09.08.2026 07:29 | ✅ |
| **trixie-de** | 09.04.2026 14:58 | ✅ | | **trixie-de** | 19.07.2026 07:26 | ✅ |
| **bookworm-de** | 09.04.2026 14:13 | ✅ | | **trixie-de** | 28.06.2026 07:27 | ✅ |
| **bookworm-de** | 09.04.2026 13:10 | ✅ | | **trixie-de** | 14.06.2026 07:25 | ✅ |
| **bookworm-de** | 09.04.2026 11:58 | ✅ | | **trixie-de** | 04.06.2026 13:41 | build trixie-de latest ✅ |
| **bookworm-de** | 09.04.2026 10:11 | ✅ | | **trixie-de** | 04.06.2026 12:25 | Trixie build ✅ |
| **bookworm-de** | 07.04.2026 19:27 | ✅ | | **bookworm-de** | 02.06.2026 18:17 | .gitea/workflows/build-and-push.yaml aktualisiert ✅ |
| **bookworm-de** | 07.04.2026 17:38 | ✅ | | **bookworm-de** | 02.06.2026 17:04 | ✅ |
| **bookworm-de** | 05.04.2026 11:47 | ✅ | | **bookworm-de** | 24.05.2026 07:22 | ✅ |
| **bookworm-de** | 05.04.2026 11:20 | ✅ | | **bookworm-de** | 10.05.2026 07:21 | ✅ |
| **bookworm-de** | 04.04.2026 00:31 | ✅ | | **bookworm-de** | 26.04.2026 07:23 | ✅ |
| **bookworm-de** | 02.04.2026 17:26 | ✅ | | **bookworm-de** | 09.04.2026 17:19 | build for bookworm ✅ |
| **bookworm-de** | 02.04.2026 16:44 | ✅ | | **trixie-de** | 09.04.2026 16:44 | build for trixie-de ✅ |
| **bookworm-de** | 02.04.2026 15:37 | ✅ | | **bookworm-de** | 09.04.2026 16:15 | Merge pull request dev (#2) from dev into main Reviewed-on: https://git.pi-farm.de/pi-farm/base-image-debian-rdp-ldap/pulls/2 ✅ |
| **bookworm** | 02.04.2026 14:15 | ✅ |
+15
View File
@@ -0,0 +1,15 @@
| **trixie-de** | 06.10.2026 17:30 | .gitea/workflows/build-and-push.yaml aktualisiert ✅ |
| **trixie-de** | 09.08.2026 07:29 | ✅ |
| **trixie-de** | 19.07.2026 07:26 | ✅ |
| **trixie-de** | 28.06.2026 07:27 | ✅ |
| **trixie-de** | 14.06.2026 07:25 | ✅ |
| **trixie-de** | 04.06.2026 13:41 | build trixie-de latest ✅ |
| **trixie-de** | 04.06.2026 12:25 | Trixie build ✅ |
| **bookworm-de** | 02.06.2026 18:17 | .gitea/workflows/build-and-push.yaml aktualisiert ✅ |
| **bookworm-de** | 02.06.2026 17:04 | ✅ |
| **bookworm-de** | 24.05.2026 07:22 | ✅ |
| **bookworm-de** | 10.05.2026 07:21 | ✅ |
| **bookworm-de** | 26.04.2026 07:23 | ✅ |
| **bookworm-de** | 09.04.2026 17:19 | build for bookworm ✅ |
| **trixie-de** | 09.04.2026 16:44 | build for trixie-de ✅ |
| **bookworm-de** | 09.04.2026 16:15 | Merge pull request dev (#2) from dev into main Reviewed-on: https://git.pi-farm.de/pi-farm/base-image-debian-rdp-ldap/pulls/2 ✅ |
+3 -3
View File
@@ -1,8 +1,8 @@
## BUILD STAGE ## BUILD STAGE
BUILD_BASE_IMAGE=debian:bookworm BUILD_BASE_IMAGE=debian:trixie
BUILD_COUNTRY=de BUILD_COUNTRY=de
BUILD_TAG=bookworm-de BUILD_TAG=trixie-de
BUILD_TAG_LATEST=n BUILD_TAG_LATEST=y
BUILD_LANG=de_DE.UTF-8 BUILD_LANG=de_DE.UTF-8
BUILD_LANGUAGE=de_DE:de BUILD_LANGUAGE=de_DE:de
BUILD_LC_ALL=de_DE.UTF-8 BUILD_LC_ALL=de_DE.UTF-8
+281 -16
View File
@@ -1,16 +1,281 @@
services: <!DOCTYPE html>
base-image-debian-rdp-ldap: <html lang="en-US" data-theme="gitea-auto">
image: git.pi-farm.de/pi-farm/base-image-debian-rdp-ldap:bookworm-de <head>
container_name: base-image-debian-rdp-ldap <meta http-equiv="Content-Security-Policy" content="default-src * data: blob:;script-src * &#39;nonce-2f1114650edc4dcd89ad1b32c2c5a1c0&#39;;style-src * &#39;unsafe-inline&#39;;">
restart: unless-stopped <meta name="viewport" content="width=device-width, initial-scale=1">
ports: <title>Sign In - Gitea: Git with a cup of tea</title>
- 3889 <link rel="manifest" href="/assets/site-manifest.json">
environment: <meta name="author" content="Gitea - Git with a cup of tea">
- SSSD_DEBUG_LEVEL=5 <meta name="description" content="Gitea (Git with a cup of tea) is a painless self-hosted Git service written in Go">
- LDAP_URI=ldap://YOUR-LDAP-SERVER:389 <meta name="keywords" content="go,git,self-hosted,gitea">
- LDAP_BASE_DN=dc=YOUR-DOMAIN,dc=LOC <meta name="referrer" content="same-origin">
- LDAP_BIND_DN=cn=YOUR-BIND-USER,dc=YOUR-DOMAIN,dc=LOC
- LDAP_BIND_PASSWORD=YOUR-SUPER-SECRET-BIND-PASSWORD
- LDAP_SUDO_GROUP=YOUR-SUDO-USERS-GROUP <link rel="icon" href="/assets/img/favicon.svg" type="image/svg+xml">
volumes: <link rel="alternate icon" href="/assets/img/favicon.png" type="image/png">
- ./YOUR-PERSISTENT-FOLDER:/home
<meta property="og:title" content="Gitea: Git with a cup of tea">
<meta property="og:type" content="website">
<meta property="og:image" content="/assets/img/logo.png">
<meta property="og:url" content="https://git.pi-farm.de">
<meta property="og:description" content="Gitea (Git with a cup of tea) is a painless self-hosted Git service written in Go">
<meta property="og:site_name" content="Gitea: Git with a cup of tea">
<link rel="stylesheet" href="/assets/css/index.BHUwT9fG.css">
<link rel="stylesheet" href="/assets/css/theme-gitea-auto.v3RW7v-i.css">
<script nonce="2f1114650edc4dcd89ad1b32c2c5a1c0">
window.addEventListener('error', function(e) {window._globalHandlerErrors=window._globalHandlerErrors||[]; window._globalHandlerErrors.push(e);});
window.addEventListener('unhandledrejection', function(e) {window._globalHandlerErrors=window._globalHandlerErrors||[]; window._globalHandlerErrors.push(e);});
window.config = {
appUrl: 'https:\/\/git.pi-farm.de\/',
appSubUrl: '',
assetUrlPrefix: '\/assets',
runModeIsProd: true ,
customEmojis: {"codeberg":":codeberg:","git":":git:","gitea":":gitea:","github":":github:","gitlab":":gitlab:","gogs":":gogs:"},
pageData: {},
notificationSettings: {"EventSourceUpdateTime":10000,"MaxTimeout":60000,"MinTimeout":10000,"TimeoutStep":10000},
enableTimeTracking: true ,
mermaidMaxSourceCharacters: 50000 ,
sharedWorkerUri: '\/assets\/js\/eventsource.sharedworker.DV1Z2uJv.js',
i18n: {
error_occurred: "An error occurred",
remove_label_str: "Remove item \"%s\"",
modal_confirm: "Confirm",
modal_cancel: "Cancel",
more_items: "More items",
copy_success: "Copied!",
copy_error: "Copy failed",
},
};
window.config.pageData = window.config.pageData || {};
</script>
<script nonce="2f1114650edc4dcd89ad1b32c2c5a1c0" src="/assets/js/iife.D2XhYhS2.js"></script>
</head>
<body>
<div class="full height">
<noscript>This website requires JavaScript.</noscript>
<nav id="navbar" aria-label="Navigation Bar">
<div class="navbar-left">
<a class="item" id="navbar-logo" href="/" aria-label="Home">
<img width="30" height="30" src="/assets/img/logo.svg" alt="Logo" aria-hidden="true">
</a>
<div class="ui secondary menu navbar-mobile-right only-mobile">
<button class="item ui icon mini button tw-m-0" id="navbar-expand-toggle" aria-label="Navigation Menu"><svg viewBox="0 0 16 16" class="svg octicon-three-bars" aria-hidden="true" width="16" height="16"><path d="M1 2.75A.75.75 0 0 1 1.75 2h12.5a.75.75 0 0 1 0 1.5H1.75A.75.75 0 0 1 1 2.75m0 5A.75.75 0 0 1 1.75 7h12.5a.75.75 0 0 1 0 1.5H1.75A.75.75 0 0 1 1 7.75M1.75 12h12.5a.75.75 0 0 1 0 1.5H1.75a.75.75 0 0 1 0-1.5"/></svg></button>
</div>
<a class="item" href="/explore/repos">Explore</a>
<a class="item" target="_blank" href="https://docs.gitea.com">Help</a>
</div>
<div class="navbar-right">
<a class="item active" rel="nofollow" href="/user/login">
<svg viewBox="0 0 16 16" class="svg octicon-sign-in" aria-hidden="true" width="16" height="16"><path d="M2 2.75C2 1.784 2.784 1 3.75 1h2.5a.75.75 0 0 1 0 1.5h-2.5a.25.25 0 0 0-.25.25v10.5c0 .138.112.25.25.25h2.5a.75.75 0 0 1 0 1.5h-2.5A1.75 1.75 0 0 1 2 13.25Zm6.56 4.5h5.69a.75.75 0 0 1 0 1.5H8.56l1.97 1.97a.749.749 0 0 1-.326 1.275.75.75 0 0 1-.734-.215L6.22 8.53a.75.75 0 0 1 0-1.06l3.25-3.25a.749.749 0 0 1 1.275.326.75.75 0 0 1-.215.734Z"/></svg>
<span class="tw-ml-1">Sign In</span>
</a>
</div>
</nav>
<div role="main" aria-label="Sign In" class="page-content user signin">
<div class="ui middle very relaxed page grid">
<div class="column tw-flex tw-flex-col tw-gap-4 tw-max-w-2xl tw-m-auto">
<div class="ui container fluid">
<h4 class="ui top attached header center">
Sign In
</h4>
<div class="ui attached segment">
<form class="ui form" action="/user/login" method="post">
<div class="required field ">
<label for="user_name">Username or Email Address</label>
<input id="user_name" type="text" name="user_name" value="" autofocus required tabindex="1">
</div>
<div class="required field ">
<div class="tw-flex tw-mb-1">
<label for="password" class="tw-flex-1">Password</label>
<a href="/user/forgot_password" tabindex="4">Forgot password?</a>
</div>
<input id="password" name="password" type="password" value="" autocomplete="current-password" required tabindex="2">
</div>
<div class="inline field">
<div class="ui checkbox">
<label>Remember This Device</label>
<input name="remember" type="checkbox" tabindex="5">
</div>
</div>
<div class="field">
<button class="ui primary button tw-w-full" tabindex="3">
Sign In
</button>
</div>
</form>
</div>
</div>
<div class="ui container fluid">
<div class="ui attached segment header top tw-max-w-2xl tw-m-auto tw-flex tw-flex-col tw-items-center">
<div id="webauthn-error" class="ui negative message tw-hidden">
<div class="header">Could not read your security key.</div>
<div id="webauthn-error-msg" class="tw-pt-2"></div>
<div class="tw-hidden">
<div data-webauthn-error-msg="browser">Your browser does not currently support WebAuthn.</div>
<div data-webauthn-error-msg="unknown">An unknown error occurred. Please retry.</div>
<div data-webauthn-error-msg="insecure">WebAuthn only supports secure connections. For testing over HTTP, you can use the origin "localhost" or "127.0.0.1".</div>
<div data-webauthn-error-msg="unable-to-process">The server could not process your request.</div>
<div data-webauthn-error-msg="duplicated">The security key is not permitted for this request. Please make sure that the key is not already registered.</div>
<div data-webauthn-error-msg="empty">You must set a name for this key.</div>
<div data-webauthn-error-msg="timeout">Timeout reached before your key could be read. Please reload this page and retry.</div>
</div>
</div>
<a class="signin-passkey">Sign in with a passkey</a>
</div>
</div>
</div>
</div>
</div>
</div>
<footer class="page-footer" role="group" aria-label="Footer">
<div class="left-links" role="contentinfo" aria-label="About Software">
<a target="_blank" href="https://about.gitea.com">Powered by Gitea</a>
<span>
Version:
1.27.2
</span>
<span>
Page: <strong>2ms</strong>
Template: <strong>0ms</strong>
</span>
</div>
<div class="right-links" role="group" aria-label="Links">
<div class="ui dropdown custom" id="footer-theme-selector">
<span class="default-text"><div class="theme-menu-item" data-tooltip-content=""><svg viewBox="490 490 820 820" class="svg gitea-eclipse" aria-hidden="true" width="16" height="16"><path d="M866.7 582.1A321.3 321.3 0 0 0 738.6 623a317.3 317.3 0 0 0-109.1 108.5A418 418 0 0 0 609 772a335.3 335.3 0 0 0-19.6 71.5 205.2 205.2 0 0 0-2.8 45c0 25.8.2 29.3 2.8 45 4.1 25.4 9.9 46.4 19.6 71.5a314.2 314.2 0 0 0 111.6 137.3A306.8 306.8 0 0 0 893 1196a308.6 308.6 0 0 0 303.6-262.5c2.6-15.7 2.8-19.2 2.8-45s-.2-29.3-2.8-45A335.3 335.3 0 0 0 1177 772a314.2 314.2 0 0 0-111.6-137.3A308.3 308.3 0 0 0 918 582c-13-1.1-38.2-1.1-51.3.1M747 663.5l-2.4 16.7c-4 26.4-4.9 41.1-4.3 65.3a323.7 323.7 0 0 0 37.2 145c18.2 36 41.3 66.6 72 95.5a346.4 346.4 0 0 0 208.5 93.1l18 1.6 4.5.5-8.5 8a259.3 259.3 0 0 1-141.5 65.8 281 281 0 0 1-123.9-11.4 267.2 267.2 0 0 1-181.7-269.9c2-27.6 5.7-47.6 13.3-70.7a281.2 281.2 0 0 1 46.4-85c8-10.1 28-30.2 37.9-38.1 13.8-11.1 24.5-18.3 24.5-16.4"/></svg> Auto </div></span>
<div class="menu theme-menu"></div>
</div>
<div class="ui dropdown upward">
<span class="flex-text-inline"><svg viewBox="0 0 16 16" class="svg octicon-globe" aria-hidden="true" width="14" height="14"><path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0M5.78 8.75a9.64 9.64 0 0 0 1.363 4.177q.383.64.857 1.215c.245-.296.551-.705.857-1.215A9.64 9.64 0 0 0 10.22 8.75Zm4.44-1.5a9.64 9.64 0 0 0-1.363-4.177c-.307-.51-.612-.919-.857-1.215a10 10 0 0 0-.857 1.215A9.64 9.64 0 0 0 5.78 7.25Zm-5.944 1.5H1.543a6.51 6.51 0 0 0 4.666 5.5q-.184-.271-.352-.552c-.715-1.192-1.437-2.874-1.581-4.948m-2.733-1.5h2.733c.144-2.074.866-3.756 1.58-4.948q.18-.295.353-.552a6.51 6.51 0 0 0-4.666 5.5m10.181 1.5c-.144 2.074-.866 3.756-1.58 4.948q-.18.296-.353.552a6.51 6.51 0 0 0 4.666-5.5Zm2.733-1.5a6.51 6.51 0 0 0-4.666-5.5q.184.272.353.552c.714 1.192 1.436 2.874 1.58 4.948Z"/></svg> English</span>
<div class="menu language-menu">
<a lang="id-ID" data-url="/?lang=id-ID" class="item ">Bahasa Indonesia</a>
<a lang="de-DE" data-url="/?lang=de-DE" class="item ">Deutsch</a>
<a lang="en-US" data-url="/?lang=en-US" class="item selected">English</a>
<a lang="es-ES" data-url="/?lang=es-ES" class="item ">Español</a>
<a lang="fr-FR" data-url="/?lang=fr-FR" class="item ">Français</a>
<a lang="ga-IE" data-url="/?lang=ga-IE" class="item ">Gaeilge</a>
<a lang="it-IT" data-url="/?lang=it-IT" class="item ">Italiano</a>
<a lang="lv-LV" data-url="/?lang=lv-LV" class="item ">Latviešu</a>
<a lang="hu-HU" data-url="/?lang=hu-HU" class="item ">Magyar nyelv</a>
<a lang="nl-NL" data-url="/?lang=nl-NL" class="item ">Nederlands</a>
<a lang="pl-PL" data-url="/?lang=pl-PL" class="item ">Polski</a>
<a lang="pt-PT" data-url="/?lang=pt-PT" class="item ">Português de Portugal</a>
<a lang="pt-BR" data-url="/?lang=pt-BR" class="item ">Português do Brasil</a>
<a lang="fi-FI" data-url="/?lang=fi-FI" class="item ">Suomi</a>
<a lang="sv-SE" data-url="/?lang=sv-SE" class="item ">Svenska</a>
<a lang="tr-TR" data-url="/?lang=tr-TR" class="item ">Türkçe</a>
<a lang="cs-CZ" data-url="/?lang=cs-CZ" class="item ">Čeština</a>
<a lang="el-GR" data-url="/?lang=el-GR" class="item ">Ελληνικά</a>
<a lang="bg-BG" data-url="/?lang=bg-BG" class="item ">Български</a>
<a lang="ru-RU" data-url="/?lang=ru-RU" class="item ">Русский</a>
<a lang="uk-UA" data-url="/?lang=uk-UA" class="item ">Українська</a>
<a lang="fa-IR" data-url="/?lang=fa-IR" class="item ">فارسی</a>
<a lang="ml-IN" data-url="/?lang=ml-IN" class="item ">മലയാളം</a>
<a lang="ja-JP" data-url="/?lang=ja-JP" class="item ">日本語</a>
<a lang="zh-CN" data-url="/?lang=zh-CN" class="item ">简体中文</a>
<a lang="zh-TW" data-url="/?lang=zh-TW" class="item ">繁體中文(台灣)</a>
<a lang="zh-HK" data-url="/?lang=zh-HK" class="item ">繁體中文(香港)</a>
<a lang="ko-KR" data-url="/?lang=ko-KR" class="item ">한국어</a>
</div>
</div>
<a href="/assets/licenses.txt">Licenses</a>
<a href="/api/swagger">API</a>
</div>
</footer>
<script nonce="2f1114650edc4dcd89ad1b32c2c5a1c0" type="module" src="/assets/js/index.8BwIzI4A.js"></script>
<script nonce="2f1114650edc4dcd89ad1b32c2c5a1c0" type="module">
if (!window.config?.frontendInited && window.config?.runModeIsProd) alert("Frontend is not initialized, check console errors or asset files.");
</script>
</body>
</html>