Initial commit: Bastillion 6 Dockerfile, Multi-Arch CI/CD Workflow & Compose
Upstream Release Watcher & Multi-Arch Build / Check & Build Docker Image (push) Successful in 1m42s

This commit is contained in:
2026-10-23 19:55:11 +02:00
commit ea502d74a9
7 changed files with 409 additions and 0 deletions
+6
View File
@@ -0,0 +1,6 @@
.git
.gitea
.github
data/
*.log
*.tmp
+139
View File
@@ -0,0 +1,139 @@
# Bastillion Docker CI/CD - Upstream Release Watcher & Multi-Arch Build
# Prüft regelmäßig auf neue Releases von Loophole-LLC/Bastillion und baut
# Multi-Arch Images (linux/amd64 & linux/arm64) für die Container Registry.
name: Upstream Release Watcher & Multi-Arch Build
on:
schedule:
# Alle 6 Stunden prüfen
- cron: '0 */6 * * *'
push:
branches:
- main
paths:
- 'Dockerfile'
- '.gitea/workflows/**'
workflow_dispatch:
inputs:
force_version:
description: 'Spezifische Bastillion-Version erzwingen (z. B. 6.0.3) oder leer für neueste'
required: false
default: ''
env:
IMAGE_NAME: bastillion
UPSTREAM_REPO: Loophole-LLC/Bastillion
jobs:
check-and-build:
name: Check & Build Docker Image
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Determine upstream version
id: version_check
run: |
set -e
if [ -n "${{ inputs.force_version }}" ]; then
TAG="v${{ inputs.force_version }}"
TAG="v${TAG#v}"
VERSION="${TAG#v}"
echo "Manuelle Version vorgegeben: ${VERSION}"
else
echo "Frage neuestes Release von GitHub (${UPSTREAM_REPO}) ab..."
RELEASE_JSON=$(curl -sSL "https://api.github.com/repos/${UPSTREAM_REPO}/releases/latest")
TAG=$(echo "$RELEASE_JSON" | grep -m 1 '"tag_name":' | sed -E 's/.*"tag_name": *"([^"]+)".*/\1/')
if [ -z "$TAG" ] || [ "$TAG" = "null" ]; then
echo "::error::Konnte neuestes Release von ${UPSTREAM_REPO} nicht ermitteln."
exit 1
fi
VERSION="${TAG#v}"
echo "Neuestes Upstream-Release gefunden: ${TAG} (Version: ${VERSION})"
fi
echo "tag=${TAG}" >> "$GITHUB_OUTPUT"
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
# Prüfen, ob dieses Git-Tag im lokalen Repo bereits existiert
if git rev-parse "$TAG" >/dev/null 2>&1; then
echo "Tag ${TAG} existiert bereits im Repository."
if [ "${{ github.event_name }}" = "schedule" ]; then
echo "Kein neues Release vorhanden. Workflow beendet."
echo "should_build=false" >> "$GITHUB_OUTPUT"
exit 0
fi
echo "Build wird trotz existierendem Tag fortgesetzt (Event: ${{ github.event_name }})."
fi
echo "should_build=true" >> "$GITHUB_OUTPUT"
# Registry-URL ermitteln (Fallback auf aktuellen Server / Host)
REGISTRY="${{ vars.REGISTRY_URL || github.server_url }}"
REGISTRY="${REGISTRY#https://}"
REGISTRY="${REGISTRY#http://}"
echo "registry=${REGISTRY}" >> "$GITHUB_OUTPUT"
- name: Set up QEMU
if: steps.version_check.outputs.should_build == 'true'
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
if: steps.version_check.outputs.should_build == 'true'
uses: docker/setup-buildx-action@v3
- name: Login to Container Registry
if: steps.version_check.outputs.should_build == 'true'
uses: docker/login-action@v3
with:
registry: ${{ vars.REGISTRY_URL || github.server_url }}
username: ${{ secrets.REGISTRY_USER || github.actor }}
password: ${{ secrets.REGISTRY_TOKEN || secrets.GITHUB_TOKEN }}
- name: Build & Push Multi-Arch Docker Image
if: steps.version_check.outputs.should_build == 'true'
uses: docker/build-push-action@v6
with:
context: .
platforms: linux/amd64,linux/arm64
push: true
build-args: |
BASTILLION_VERSION=${{ steps.version_check.outputs.version }}
tags: |
${{ steps.version_check.outputs.registry }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:latest
${{ steps.version_check.outputs.registry }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ steps.version_check.outputs.version }}
${{ steps.version_check.outputs.registry }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:${{ steps.version_check.outputs.tag }}
labels: |
org.opencontainers.image.title=Bastillion
org.opencontainers.image.description=Modern web-based SSH console and key management tool
org.opencontainers.image.version=${{ steps.version_check.outputs.version }}
org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }}
- name: Create Git Tag and Release
if: steps.version_check.outputs.should_build == 'true'
run: |
TAG="${{ steps.version_check.outputs.tag }}"
VERSION="${{ steps.version_check.outputs.version }}"
API_URL="${{ github.server_url }}/api/v1/repos/${{ github.repository }}/releases"
echo "Erstelle Release ${TAG}..."
PAYLOAD=$(cat <<EOF
{
"tag_name": "${TAG}",
"target_commitish": "${{ github.sha }}",
"name": "Bastillion ${TAG}",
"body": "Automatisierter Docker Multi-Arch Build für **Bastillion ${TAG}** (Java 21, Ed25519 Support).\n\nUpstream Release: https://github.com/${UPSTREAM_REPO}/releases/tag/${TAG}",
"draft": false,
"prerelease": false
}
EOF
)
curl -s -X POST "$API_URL" \
-H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
-H "Content-Type: application/json" \
-d "$PAYLOAD" || echo "Release-Erstellung abgeschlossen."
+5
View File
@@ -0,0 +1,5 @@
data/
*.log
*.jar
.DS_Store
Thumbs.db
+48
View File
@@ -0,0 +1,48 @@
FROM eclipse-temurin:21-jre-alpine
# Metadaten
LABEL org.opencontainers.image.title="Bastillion"
LABEL org.opencontainers.image.description="Modern web-based SSH console and key management tool"
LABEL org.opencontainers.image.source="https://github.com/Loophole-LLC/Bastillion"
LABEL org.opencontainers.image.vendor="Loophole LLC / Community Docker Image"
# Build-Argument für Upstream-Version (Standard: 6.0.3)
ARG BASTILLION_VERSION=6.0.3
# Standard-Laufzeitumgebung
ENV CONFIG_DIR=/data \
PORT=8080 \
TLS_ENABLED=false \
GEN_DB_PASS=true \
CLIENT_IP_HEADER=X-Forwarded-For
# Minimale Tools für Healthcheck & Netzwerkanfragen
RUN apk add --no-cache curl wget ca-certificates bash
# Unprivilegierten Benutzer anlegen (Sicherheit: Non-Root)
RUN addgroup -g 1000 bastillion && \
adduser -D -u 1000 -G bastillion -s /bin/sh bastillion && \
mkdir -p /opt/bastillion /data && \
chown -R bastillion:bastillion /opt/bastillion /data
WORKDIR /opt/bastillion
# Executable Standalone JAR direkt aus offiziellem GitHub Release beziehen
ADD --chown=bastillion:bastillion \
https://github.com/Loophole-LLC/Bastillion/releases/download/v${BASTILLION_VERSION}/bastillion-${BASTILLION_VERSION}.jar \
/opt/bastillion/bastillion.jar
# Privilegien abgeben
USER bastillion
# Persistenter Datenspeicher (H2-DB, Keystores, SSH-Keypair, Konfiguration)
VOLUME ["/data"]
# HTTP-Port (8080 Standard bei TLS_ENABLED=false)
EXPOSE 8080 8443
# Healthcheck
HEALTHCHECK --interval=30s --timeout=5s --start-period=30s --retries=3 \
CMD wget --no-verbose --tries=1 --spider http://127.0.0.1:${PORT}/ || exit 1
ENTRYPOINT ["java", "-jar", "/opt/bastillion/bastillion.jar"]
+17
View File
@@ -0,0 +1,17 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
Copyright 2026 Bastillion Docker Contributors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
+144
View File
@@ -0,0 +1,144 @@
# Bastillion Docker (Multi-Arch)
[![Docker Multi-Arch](https://img.shields.io/badge/Architecture-amd64%20%7C%20arm64-blue.svg)](#)
[![Java 21](https://img.shields.io/badge/Java-21-orange.svg)](#)
[![Upstream](https://img.shields.io/badge/Upstream-Loophole--LLC%2FBastillion-brightgreen.svg)](https://github.com/Loophole-LLC/Bastillion)
Vollständig containerisiertes **Bastillion 6** (ehemals *KeyBox*) als schlankes Multi-Arch Docker Image (`linux/amd64` und `linux/arm64`) mit **automatischen Upstream-Builds** bei neuen GitHub-Releases.
---
## 🌟 Was ist Bastillion?
[Bastillion](https://github.com/Loophole-LLC/Bastillion) ist eine moderne, browserbasierte SSH-Konsole und ein zentrales SSH-Schlüsselverwaltungssystem:
* **Web-SSH-Terminal:** Volles xterm.js-Terminal im Webbrowser mit synchronisiertem Multi-Terminal-Broadcasting (Befehle parallel an mehrere Server gleichzeitig senden).
* **Zentrales Key-Management:** Bastillion erzeugt ein eigenes sicheres **Ed25519-Schlüsselpaar** und verteilt den Public Key automatisch auf registrierte Hosts. Benutzer müssen keine privaten Schlüssel mehr lokal verwalten.
* **Moderne Krypto:** Ab Version 6 voller Support für moderne SSH-Verfahren, Ed25519, moderne RSA-SHA2-Ciphers und SSH-Zertifikate.
* **Audit-Sicherheit:** Aufzeichnung aller SSH-Sitzungen zur lückenlosen Nachvollziehbarkeit.
* **Zwei-Faktor-Authentifizierung (2FA):** Integrierte 2FA via Google Authenticator, Authy oder Standard-TOTP-Apps.
---
## 🚀 Schnellstart
### Mit Docker Run
```bash
docker run -d \
--name bastillion \
-p 8080:8080 \
-v bastillion_data:/data \
-e CONFIG_DIR=/data \
-e PORT=8080 \
-e TLS_ENABLED=false \
-e GEN_DB_PASS=true \
bastillion:latest
```
### Mit Docker Compose (inkl. Traefik)
Erstelle eine `docker-compose.yaml`:
```yaml
version: "3.8"
services:
bastillion:
image: bastillion:latest
container_name: bastillion
hostname: bastillion
restart: unless-stopped
networks:
bastillion_net:
ipv4_address: 172.28.0.10
volumes:
- ./data:/data
environment:
- CONFIG_DIR=/data
- PORT=8080
- TLS_ENABLED=false
- GEN_DB_PASS=true
- CLIENT_IP_HEADER=X-Forwarded-For
- TZ=Europe/Berlin
labels:
- "traefik.enable=true"
- "traefik.http.routers.bastillion-http.rule=Host(`bastillion.example.com`)"
- "traefik.http.routers.bastillion-http.entrypoints=web"
- "traefik.http.routers.bastillion-http.middlewares=redirect-to-https@file"
- "traefik.http.routers.bastillion.rule=Host(`bastillion.example.com`)"
- "traefik.http.routers.bastillion.entrypoints=websecure"
- "traefik.http.routers.bastillion.tls=true"
- "traefik.http.routers.bastillion.tls.certresolver=letsencrypt"
- "traefik.http.routers.bastillion.service=bastillion-svc"
- "traefik.http.services.bastillion-svc.loadbalancer.server.port=8080"
networks:
bastillion_net:
name: bastillion.dockernetwork.local
driver: bridge
ipam:
driver: default
config:
- subnet: 172.28.0.0/24
gateway: 172.28.0.1
ip_range: 172.28.0.128/25
```
Starte den Dienst:
```bash
docker compose up -d
```
---
## 🔐 Ersteinrichtung & Sicherheit
Beim ersten Start ist der Standard-Zugang aktiv:
* **Benutzer:** `admin`
* **Passwort:** `changeme`
> [!IMPORTANT]
> **Sofortige Maßnahmen nach dem ersten Login:**
> 1. Passwort ändern unter **Settings → Change Password**.
> 2. Zwei-Faktor-Authentifizierung (TOTP) unter **Settings** für den Admin-Account aktivieren.
---
## ⚙️ Wichtige Umgebungsvariablen
| Variable | Standard | Beschreibung |
| :--- | :--- | :--- |
| `CONFIG_DIR` | `/data` | Zentraler Ordner für H2-Datenbank, Keystores und SSH-Schlüssel. |
| `PORT` | `8080` | Interner HTTP/HTTPS Listen-Port. |
| `TLS_ENABLED` | `false` | `false` für Betrieb hinter Reverse Proxy (Traefik/Nginx); `true` für direktes SSL. |
| `GEN_DB_PASS` | `true` | Erzeugt beim Erststart automatisch ein kryptografisch sicheres H2-DB-Passwort. |
| `CLIENT_IP_HEADER` | `X-Forwarded-For` | Liest die echte Client-IP aus dem Proxy-Header für Audit-Logs. |
| `KEY_MANAGEMENT` | `manage` | Modus für `authorized_keys` (`manage`, `append` oder `off`). |
---
## 💾 Backup & Wiederherstellung
Da Bastillion durch `CONFIG_DIR=/data` alle Zustände (H2-Datenbank, SSH-Keypair, Einstellungen) an einem Ort bündelt, reicht eine einfache Dateisicherung:
```bash
# Backup des Datenordners erstellen
tar -cpzf bastillion_backup_$(date +%Y%m%d_%H%M%S).tar.gz ./data
```
---
## 🔄 Automatisierter Release-Watcher
Dieses Repository nutzt CI/CD Actions, um alle 6 Stunden die offizielle [Loophole-LLC Bastillion Release API](https://github.com/Loophole-LLC/Bastillion/releases) abzufragen.
Sobald ein neues Upstream-Tag erscheint, baut die Pipeline vollautomatisch Multi-Arch Images (`linux/amd64` und `linux/arm64`) und pusht sie in die Container Registry.
---
## 📜 Lizenz
* Bastillion steht unter der **Prosperity Public License 3.0.0** von [Loophole, LLC](https://loophole.company/).
* Das Docker-Packaging und die CI/CD-Skripte sind unter der **Apache 2.0 Lizenz** veröffentlicht.
+50
View File
@@ -0,0 +1,50 @@
version: "3.8"
services:
bastillion:
image: bastillion:latest
container_name: bastillion
hostname: bastillion
restart: unless-stopped
networks:
bastillion_net:
ipv4_address: 172.28.0.10
volumes:
- ./data:/data
environment:
# Konsolidiertes Datenverzeichnis (H2 DB, Keystore, SSH Keys)
- CONFIG_DIR=/data
# Interner HTTP-Port (hinter Reverse Proxy)
- PORT=8080
# Intern unverschlüsselt (Reverse Proxy übernimmt HTTPS & Zertifikate)
- TLS_ENABLED=false
# Automatisches Generieren des DB-Passworts beim ersten Start
- GEN_DB_PASS=true
# Client-IP-Header für echte Quell-IPs in den Audit-Logs
- CLIENT_IP_HEADER=X-Forwarded-For
# Zeitzone
- TZ=Europe/Berlin
labels:
- "traefik.enable=true"
# HTTP zu HTTPS Redirect
- "traefik.http.routers.bastillion-http.rule=Host(`bastillion.example.com`)"
- "traefik.http.routers.bastillion-http.entrypoints=web"
- "traefik.http.routers.bastillion-http.middlewares=redirect-to-https@file"
# HTTPS Router
- "traefik.http.routers.bastillion.rule=Host(`bastillion.example.com`)"
- "traefik.http.routers.bastillion.entrypoints=websecure"
- "traefik.http.routers.bastillion.tls=true"
- "traefik.http.routers.bastillion.tls.certresolver=letsencrypt"
- "traefik.http.routers.bastillion.service=bastillion-svc"
- "traefik.http.services.bastillion-svc.loadbalancer.server.port=8080"
networks:
bastillion_net:
name: bastillion.dockernetwork.local
driver: bridge
ipam:
driver: default
config:
- subnet: 172.28.0.0/24
gateway: 172.28.0.1
ip_range: 172.28.0.128/25