initial upload
This commit is contained in:
2
infrastructure/apps/traefik-edge/.gitignore
vendored
Normal file
2
infrastructure/apps/traefik-edge/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
.env
|
||||
certs/
|
||||
@@ -0,0 +1 @@
|
||||
#Testcomment
|
||||
@@ -0,0 +1,18 @@
|
||||
http:
|
||||
routers:
|
||||
# Route für Apps auf VM 301
|
||||
to-apps-vm:
|
||||
rule: HostRegexp(`^[a-z0-9-]+\.apps\.stabify\.de$`)
|
||||
service: apps-vm-service
|
||||
entryPoints: [ websecure ]
|
||||
tls:
|
||||
certResolver: le
|
||||
domains:
|
||||
- main: "*.apps.stabify.de"
|
||||
|
||||
services:
|
||||
apps-vm-service:
|
||||
loadBalancer:
|
||||
servers:
|
||||
- url: "http://vm-docker-apps-301.stabify.de:80"
|
||||
passHostHeader: true
|
||||
42
infrastructure/apps/traefik-edge/config/traefik.yml
Normal file
42
infrastructure/apps/traefik-edge/config/traefik.yml
Normal file
@@ -0,0 +1,42 @@
|
||||
api:
|
||||
dashboard: false
|
||||
|
||||
entryPoints:
|
||||
web:
|
||||
address: ":80"
|
||||
http:
|
||||
redirections:
|
||||
entryPoint:
|
||||
to: websecure
|
||||
scheme: https
|
||||
|
||||
websecure:
|
||||
address: ":443"
|
||||
http:
|
||||
tls:
|
||||
certResolver: le
|
||||
domains:
|
||||
- main: "stabify.de"
|
||||
sans:
|
||||
- "*.stabify.de"
|
||||
- "*.k3s.stabify.de"
|
||||
- "*.sys.stabify.de"
|
||||
- "*.apps.stabify.de"
|
||||
|
||||
providers:
|
||||
docker:
|
||||
endpoint: "unix:///var/run/docker.sock"
|
||||
exposedByDefault: false
|
||||
file:
|
||||
directory: "/etc/traefik/dynamic"
|
||||
watch: true
|
||||
|
||||
certificatesResolvers:
|
||||
le:
|
||||
acme:
|
||||
email: acme@infrastructure.stabify.de
|
||||
storage: /certs/acme.json
|
||||
caServer: https://acme-v02.api.letsencrypt.org/directory
|
||||
dnsChallenge:
|
||||
provider: cloudflare
|
||||
delayBeforeCheck: 10
|
||||
30
infrastructure/apps/traefik-edge/docker-compose.yml
Normal file
30
infrastructure/apps/traefik-edge/docker-compose.yml
Normal file
@@ -0,0 +1,30 @@
|
||||
---
|
||||
services:
|
||||
traefik:
|
||||
image: traefik:v3.6
|
||||
container_name: traefik-edge
|
||||
restart: unless-stopped
|
||||
security_opt:
|
||||
- no-new-privileges:true
|
||||
environment:
|
||||
- TZ=Europe/Berlin
|
||||
- CF_ZONE_API_TOKEN=${CF_ZONE_API_TOKEN}
|
||||
- CF_DNS_API_TOKEN=${CF_DNS_API_TOKEN}
|
||||
command:
|
||||
# --- DEBUGGING AKTIVIEREN ---
|
||||
- "--log.level=DEBUG" # Setzt das Log-Level auf DEBUG (Fehlersuche)
|
||||
- "--accesslog=true"
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
volumes:
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
- ./config/traefik.yml:/etc/traefik/traefik.yml:ro
|
||||
- ./config/dynamic:/etc/traefik/dynamic:ro
|
||||
- ./certs:/certs
|
||||
networks:
|
||||
- proxy
|
||||
networks:
|
||||
proxy:
|
||||
name: proxy-edge
|
||||
23
infrastructure/apps/traefik-sub/docker-compose.yml
Normal file
23
infrastructure/apps/traefik-sub/docker-compose.yml
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
services:
|
||||
traefik:
|
||||
image: traefik:v3.6
|
||||
container_name: traefik-sub
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- TZ=Europe/Berlin
|
||||
command:
|
||||
- "--providers.docker=true"
|
||||
- "--providers.docker.exposedbydefault=false"
|
||||
- "--entrypoints.web.address=:80"
|
||||
ports:
|
||||
- "80:80"
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
networks:
|
||||
- proxy
|
||||
|
||||
networks:
|
||||
proxy:
|
||||
name: proxy-sub
|
||||
external: false
|
||||
12
infrastructure/apps/vault/Dockerfile
Normal file
12
infrastructure/apps/vault/Dockerfile
Normal file
@@ -0,0 +1,12 @@
|
||||
FROM hashicorp/vault:1.15
|
||||
|
||||
# Install dependencies for automation script
|
||||
RUN apk add --no-cache openssl jq curl bash ca-certificates
|
||||
|
||||
# Copy entrypoint script
|
||||
COPY entrypoint.sh /usr/local/bin/entrypoint.sh
|
||||
RUN chmod +x /usr/local/bin/entrypoint.sh
|
||||
|
||||
# Use our script as entrypoint
|
||||
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
|
||||
|
||||
81
infrastructure/apps/vault/README_VAULT.md
Normal file
81
infrastructure/apps/vault/README_VAULT.md
Normal file
@@ -0,0 +1,81 @@
|
||||
# Vault Operations Manual (Automated)
|
||||
|
||||
Dieses Dokument beschreibt den Betrieb von HashiCorp Vault innerhalb der Stabify Infrastruktur.
|
||||
Vault läuft als Docker-Container auf der VM `vm-docker-apps-301.stabify.de` (IP: `10.100.30.11`).
|
||||
|
||||
## Automatisiertes Setup
|
||||
|
||||
Dieser Service nutzt ein **Custom Entrypoint Script**, welches folgende Schritte automatisiert:
|
||||
1. **Zertifikate**: Generiert CA & Server-Zertifikate beim Start, falls diese fehlen.
|
||||
2. **Initialisierung**: Initialisiert Vault automatisch beim ersten Start.
|
||||
3. **Auto-Unseal**: Speichert die Keys lokal (`file/init_keys.json`) und nutzt sie zum automatischen Entsperren beim Boot.
|
||||
|
||||
**⚠️ SECURITY WARNING:**
|
||||
Die Unseal-Keys werden im Klartext unter `/opt/vault/file/init_keys.json` gespeichert.
|
||||
Dies dient dem komfortablen "Set-and-Forget" Betrieb im Homelab. In Hochsicherheitsumgebungen sollte diese Datei nach dem initialen Setup gelöscht und die Keys an einem sicheren Ort (Passwort Manager) verwahrt werden.
|
||||
|
||||
## Inbetriebnahme
|
||||
|
||||
### 1. Deployment (via Ansible)
|
||||
Da der Service Teil der `vm-docker-apps-301` Deployment-Definition ist, wird er automatisch gestartet, sobald das Ansible-Playbook läuft.
|
||||
|
||||
### 2. Zugriff erhalten
|
||||
Nach dem Start liegen die generierten Daten auf dem Server.
|
||||
|
||||
1. **CA Zertifikat holen** (damit dein Browser/Client vertraut):
|
||||
```bash
|
||||
scp ansible@10.100.30.11:/opt/vault/certs/ca.crt ./
|
||||
# Importiere ca.crt in deinen Truststore / Schlüsselbund
|
||||
```
|
||||
|
||||
2. **Root Token holen** (für Admin-Zugriff):
|
||||
```bash
|
||||
ssh ansible@10.100.30.11 "cat /opt/vault/file/init_keys.json" | jq -r .root_token
|
||||
```
|
||||
|
||||
3. **Login**:
|
||||
```bash
|
||||
export VAULT_ADDR='https://10.100.30.11:8200'
|
||||
export VAULT_CACERT=./ca.crt
|
||||
vault login <Root-Token>
|
||||
```
|
||||
|
||||
## Secrets anlegen (Einmalig)
|
||||
|
||||
Aktiviere die KV v2 Engine und lege die benötigten Secrets an.
|
||||
|
||||
```bash
|
||||
# Engine aktivieren
|
||||
vault secrets enable -path=secret kv-v2
|
||||
|
||||
# 1. Proxmox Credentials
|
||||
vault kv put secret/infrastructure/proxmox \
|
||||
api_token_id="root@pam!terraform" \
|
||||
api_token_secret="dein-secret-token"
|
||||
|
||||
# 2. OPNsense Credentials
|
||||
vault kv put secret/infrastructure/opnsense \
|
||||
api_key="dein-api-key" \
|
||||
api_secret="dein-api-secret"
|
||||
|
||||
# 3. VM User Credentials
|
||||
vault kv put secret/infrastructure/vm-credentials \
|
||||
ci_user="ansible" \
|
||||
ci_password="super-secure-password" \
|
||||
ssh_public_key="ssh-ed25519 AAAA..."
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
**Logs prüfen:**
|
||||
```bash
|
||||
ssh ansible@10.100.30.11 "docker logs vault-prod"
|
||||
```
|
||||
|
||||
**Zertifikate neu generieren:**
|
||||
Lösche einfach den Ordner `certs` auf dem Server und starte den Container neu.
|
||||
```bash
|
||||
rm -rf /opt/vault/certs/*
|
||||
docker compose restart vault
|
||||
```
|
||||
**Achtung:** Danach musst du das neue `ca.crt` wieder auf deine Clients verteilen.
|
||||
20
infrastructure/apps/vault/config/vault.hcl
Normal file
20
infrastructure/apps/vault/config/vault.hcl
Normal file
@@ -0,0 +1,20 @@
|
||||
storage "raft" {
|
||||
path = "/vault/file"
|
||||
node_id = "node1"
|
||||
}
|
||||
|
||||
listener "tcp" {
|
||||
address = "0.0.0.0:8200"
|
||||
tls_cert_file = "/vault/config/certs/vault.crt"
|
||||
tls_key_file = "/vault/config/certs/vault.key"
|
||||
tls_disable = 0
|
||||
}
|
||||
|
||||
api_addr = "https://10.100.30.11:8200"
|
||||
cluster_addr = "https://10.100.30.11:8201"
|
||||
ui = true
|
||||
|
||||
# Production hardening
|
||||
disable_mlock = true
|
||||
max_lease_ttl = "768h"
|
||||
default_lease_ttl = "168h"
|
||||
25
infrastructure/apps/vault/docker-compose.yml
Normal file
25
infrastructure/apps/vault/docker-compose.yml
Normal file
@@ -0,0 +1,25 @@
|
||||
services:
|
||||
vault:
|
||||
build: .
|
||||
image: stabify/vault-custom:latest
|
||||
container_name: vault-prod
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "8200:8200"
|
||||
environment:
|
||||
VAULT_ADDR: 'https://127.0.0.1:8200'
|
||||
VAULT_API_ADDR: 'https://127.0.0.1:8200'
|
||||
volumes:
|
||||
- ./config:/vault/config
|
||||
- ./file:/vault/file
|
||||
- ./logs:/vault/logs
|
||||
# Mount certs directory.
|
||||
- ./certs:/vault/config/certs
|
||||
cap_add:
|
||||
- IPC_LOCK
|
||||
networks:
|
||||
- internal
|
||||
|
||||
networks:
|
||||
internal:
|
||||
name: vault-net
|
||||
99
infrastructure/apps/vault/entrypoint.sh
Normal file
99
infrastructure/apps/vault/entrypoint.sh
Normal file
@@ -0,0 +1,99 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
# --- 1. Auto-Generate Certificates ---
|
||||
CERTS_DIR="/vault/config/certs"
|
||||
if [ ! -f "$CERTS_DIR/vault.crt" ] || [ ! -f "$CERTS_DIR/vault.key" ]; then
|
||||
echo "[ENTRYPOINT] Certificates missing. Generating self-signed certs..."
|
||||
mkdir -p "$CERTS_DIR"
|
||||
|
||||
# Create CA
|
||||
openssl genrsa -out "$CERTS_DIR/ca.key" 4096
|
||||
openssl req -new -x509 -days 3650 -key "$CERTS_DIR/ca.key" -out "$CERTS_DIR/ca.crt" \
|
||||
-subj "/C=DE/ST=Berlin/L=Berlin/O=Stabify/OU=IT/CN=StabifyRootCA"
|
||||
|
||||
# Create Server Key/CSR
|
||||
openssl genrsa -out "$CERTS_DIR/vault.key" 4096
|
||||
openssl req -new -key "$CERTS_DIR/vault.key" -out "$CERTS_DIR/vault.csr" \
|
||||
-subj "/C=DE/ST=Berlin/L=Berlin/O=Stabify/OU=IT/CN=vault.stabify.de"
|
||||
|
||||
# Config for SANs
|
||||
cat > "$CERTS_DIR/v3.ext" << EOF
|
||||
authorityKeyIdentifier=keyid,issuer
|
||||
basicConstraints=CA:FALSE
|
||||
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
|
||||
subjectAltName = @alt_names
|
||||
|
||||
[alt_names]
|
||||
DNS.1 = vault.stabify.de
|
||||
DNS.2 = vm-docker-apps-301.stabify.de
|
||||
DNS.3 = localhost
|
||||
IP.1 = 127.0.0.1
|
||||
IP.2 = 10.100.30.11
|
||||
EOF
|
||||
|
||||
# Sign Cert
|
||||
openssl x509 -req -in "$CERTS_DIR/vault.csr" \
|
||||
-CA "$CERTS_DIR/ca.crt" -CAkey "$CERTS_DIR/ca.key" -CAcreateserial \
|
||||
-out "$CERTS_DIR/vault.crt" -days 3650 -sha256 -extfile "$CERTS_DIR/v3.ext"
|
||||
|
||||
chmod 644 "$CERTS_DIR/vault.crt" "$CERTS_DIR/ca.crt"
|
||||
chmod 600 "$CERTS_DIR/vault.key" "$CERTS_DIR/ca.key"
|
||||
|
||||
echo "[ENTRYPOINT] Certificates generated successfully."
|
||||
fi
|
||||
|
||||
# Trust our own CA inside the container (for local curl/vault calls)
|
||||
cp "$CERTS_DIR/ca.crt" /usr/local/share/ca-certificates/stabify-ca.crt
|
||||
update-ca-certificates
|
||||
|
||||
# --- 2. Start Vault in Background ---
|
||||
echo "[ENTRYPOINT] Starting Vault server..."
|
||||
vault server -config=/vault/config/vault.hcl &
|
||||
VAULT_PID=$!
|
||||
|
||||
# Wait for Vault to be ready (it will be sealed initially)
|
||||
echo "[ENTRYPOINT] Waiting for Vault API..."
|
||||
until nc -z 127.0.0.1 8200; do
|
||||
sleep 1
|
||||
done
|
||||
sleep 2
|
||||
|
||||
# --- 3. Auto-Init ---
|
||||
export VAULT_ADDR='https://127.0.0.1:8200'
|
||||
export VAULT_SKIP_VERIFY=true # We trust localhost
|
||||
|
||||
KEYS_FILE="/vault/file/init_keys.json"
|
||||
|
||||
if ! vault status | grep -q "Initialized.*true"; then
|
||||
echo "[ENTRYPOINT] Vault is not initialized. Initializing..."
|
||||
vault operator init -format=json > "$KEYS_FILE"
|
||||
chmod 600 "$KEYS_FILE"
|
||||
echo "[ENTRYPOINT] Vault initialized. Keys saved to $KEYS_FILE"
|
||||
echo "!!! WARNING: Unseal keys are stored in $KEYS_FILE. Secure this file or delete it after noting the keys !!!"
|
||||
fi
|
||||
|
||||
# --- 4. Auto-Unseal ---
|
||||
if [ -f "$KEYS_FILE" ]; then
|
||||
echo "[ENTRYPOINT] Found keys file. Attempting auto-unseal..."
|
||||
# Read first 3 keys and unseal
|
||||
KEY1=$(jq -r ".unseal_keys_b64[0]" "$KEYS_FILE")
|
||||
KEY2=$(jq -r ".unseal_keys_b64[1]" "$KEYS_FILE")
|
||||
KEY3=$(jq -r ".unseal_keys_b64[2]" "$KEYS_FILE")
|
||||
|
||||
vault operator unseal "$KEY1" > /dev/null
|
||||
vault operator unseal "$KEY2" > /dev/null
|
||||
vault operator unseal "$KEY3" > /dev/null
|
||||
|
||||
if vault status | grep -q "Sealed.*false"; then
|
||||
echo "[ENTRYPOINT] Vault successfully unsealed!"
|
||||
else
|
||||
echo "[ENTRYPOINT] Failed to unseal Vault."
|
||||
fi
|
||||
else
|
||||
echo "[ENTRYPOINT] No keys file found. Manual unseal required."
|
||||
fi
|
||||
|
||||
# --- 5. Wait for Vault Process ---
|
||||
wait $VAULT_PID
|
||||
|
||||
8
infrastructure/apps/vault/vars.yml
Normal file
8
infrastructure/apps/vault/vars.yml
Normal file
@@ -0,0 +1,8 @@
|
||||
app_name: "vault"
|
||||
|
||||
vault_config:
|
||||
ui: true
|
||||
listener_address: "0.0.0.0:8200"
|
||||
api_addr: "https://10.100.30.11:8200"
|
||||
cluster_addr: "https://10.100.30.11:8201"
|
||||
|
||||
16
infrastructure/apps/whoami/docker-compose.yml
Normal file
16
infrastructure/apps/whoami/docker-compose.yml
Normal file
@@ -0,0 +1,16 @@
|
||||
---
|
||||
services:
|
||||
whoami:
|
||||
image: traefik/whoami
|
||||
container_name: whoami
|
||||
restart: unless-stopped
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.whoami.rule=Host(`whoami.apps.stabify.de`)"
|
||||
- "traefik.http.routers.whoami.entrypoints=web"
|
||||
networks:
|
||||
- proxy-sub
|
||||
|
||||
networks:
|
||||
proxy-sub:
|
||||
external: true
|
||||
Reference in New Issue
Block a user