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
Upstream Release Watcher & Multi-Arch Build / Check & Build Docker Image (push) Successful in 1m42s
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
.git
|
||||
.gitea
|
||||
.github
|
||||
data/
|
||||
*.log
|
||||
*.tmp
|
||||
@@ -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."
|
||||
@@ -0,0 +1,5 @@
|
||||
data/
|
||||
*.log
|
||||
*.jar
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
+48
@@ -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"]
|
||||
@@ -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.
|
||||
@@ -0,0 +1,144 @@
|
||||
# Bastillion Docker (Multi-Arch)
|
||||
|
||||
[](#)
|
||||
[](#)
|
||||
[](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.
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user