infra: relocate docker-30 compose stack under vms-home/, add garage and frisbee-drills
Move the docker-30 service definitions (gitea, kanidm, vault, zot, nginx, lab-proxy, maru-hleda-byt, fuj-management) into vms-home/ to match the naming convention used for other hosts, and add the new garage object-storage and frisbee-drills services alongside it. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
9
vms-home/docker-30/frisbee-drills/run-presejpacky.sh
Normal file
9
vms-home/docker-30/frisbee-drills/run-presejpacky.sh
Normal file
@@ -0,0 +1,9 @@
|
||||
#!/bin/bash
|
||||
|
||||
docker rm -f drills-presejpacky
|
||||
|
||||
# gitea registry login with kacerr / token
|
||||
docker run -d --name drills-presejpacky \
|
||||
--restart=always \
|
||||
-p 3101:3000 \
|
||||
gitea.home.hrajfrisbee.cz/kacerr/flat-stack-presejpacky:presejpacky-v1
|
||||
10
vms-home/docker-30/fuj-management/run.sh
Normal file
10
vms-home/docker-30/fuj-management/run.sh
Normal file
@@ -0,0 +1,10 @@
|
||||
#!/bin/bash
|
||||
|
||||
docker rm -f fuj-management
|
||||
|
||||
# gitea registry login with kacerr / token
|
||||
docker run -d --name fuj-management \
|
||||
--restart=always \
|
||||
-p 8081:5001 \
|
||||
-v /srv/fuj-management/data:/app/data \
|
||||
gitea.home.hrajfrisbee.cz/kacerr/fuj-management:latest
|
||||
42
vms-home/docker-30/garage/docker-compose.yml
Normal file
42
vms-home/docker-30/garage/docker-compose.yml
Normal file
@@ -0,0 +1,42 @@
|
||||
services:
|
||||
garage:
|
||||
image: dxflrs/garage:v2.3.0
|
||||
container_name: garage
|
||||
restart: unless-stopped
|
||||
networks: [garage]
|
||||
ports:
|
||||
- "3900:3900" # S3 API (LAN-reachable for your other services)
|
||||
- "3902:3902" # S3 web
|
||||
# - "3901:3901" # RPC — only publish once you go multi-node
|
||||
volumes:
|
||||
- /srv/docker/garage/garage.toml:/etc/garage.toml:ro
|
||||
- /srv/docker/garage/meta:/var/lib/garage/meta
|
||||
- /srv/docker/garage/data:/var/lib/garage/data
|
||||
- /srv/docker/garage/snapshots:/var/lib/garage/snapshots
|
||||
healthcheck:
|
||||
test: ["CMD", "/garage", "status"] # image is distroless; use the binary, not curl
|
||||
interval: 30s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
start_period: 20s
|
||||
|
||||
garage-webui:
|
||||
image: khairul169/garage-webui:1.1.0
|
||||
container_name: garage-webui
|
||||
restart: unless-stopped
|
||||
networks: [garage]
|
||||
depends_on:
|
||||
garage:
|
||||
condition: service_healthy
|
||||
ports:
|
||||
# - "127.0.0.1:3909:3909" # bind localhost only — reverse-proxy in front for TLS/auth
|
||||
- "3909:3909"
|
||||
volumes:
|
||||
- /srv/docker/garage/garage.toml:/etc/garage.toml:ro
|
||||
environment:
|
||||
API_BASE_URL: "http://garage:3903" # override self-pointing default
|
||||
S3_ENDPOINT_URL: "http://garage:3900"
|
||||
|
||||
networks:
|
||||
garage:
|
||||
driver: bridge
|
||||
28
vms-home/docker-30/garage/garage.toml
Normal file
28
vms-home/docker-30/garage/garage.toml
Normal file
@@ -0,0 +1,28 @@
|
||||
metadata_dir = "/var/lib/garage/meta"
|
||||
data_dir = "/var/lib/garage/data"
|
||||
metadata_snapshots_dir = "/var/lib/garage/snapshots"
|
||||
db_engine = "lmdb"
|
||||
|
||||
metadata_fsync = true
|
||||
metadata_auto_snapshot_interval = "6h" # LMDB corruption insurance
|
||||
compression_level = 2
|
||||
replication_factor = 1 # single node; bump when you add nodes
|
||||
|
||||
rpc_bind_addr = "[::]:3901"
|
||||
rpc_public_addr = "127.0.0.1:3901" # self-RPC only on single node
|
||||
rpc_secret = "REPLACE_rpc_secret" # openssl rand -hex 32
|
||||
|
||||
[s3_api]
|
||||
s3_region = "garage"
|
||||
api_bind_addr = "[::]:3900"
|
||||
root_domain = ".s3.garage"
|
||||
|
||||
[s3_web]
|
||||
bind_addr = "[::]:3902"
|
||||
root_domain = ".web.garage"
|
||||
index = "index.html"
|
||||
|
||||
[admin]
|
||||
api_bind_addr = "[::]:3903"
|
||||
admin_token = "REPLACE_admin_token" # webui reads this for auth; openssl rand -hex 32
|
||||
metrics_token = "REPLACE_metrics_token" # openssl rand -hex 32
|
||||
0
vms-home/docker-30/garage/readme.md
Normal file
0
vms-home/docker-30/garage/readme.md
Normal file
128
vms-home/docker-30/gitea/docker-compose.yaml
Normal file
128
vms-home/docker-30/gitea/docker-compose.yaml
Normal file
@@ -0,0 +1,128 @@
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:16
|
||||
container_name: gitea-postgres
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
POSTGRES_DB: gitea
|
||||
POSTGRES_USER: gitea
|
||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
|
||||
volumes:
|
||||
- ./postgres:/var/lib/postgresql/data
|
||||
networks:
|
||||
- gitea-network
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U gitea"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
# minio:
|
||||
# image: minio/minio:RELEASE.2025-09-07T16-13-09Z-cpuv1
|
||||
# container_name: gitea-minio
|
||||
# restart: unless-stopped
|
||||
# command: server /data --console-address ":9001"
|
||||
# environment:
|
||||
# MINIO_ROOT_USER: gitea
|
||||
# MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD}
|
||||
# volumes:
|
||||
# - ./minio:/data
|
||||
# networks:
|
||||
# - gitea-network
|
||||
# healthcheck:
|
||||
# test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
|
||||
# interval: 30s
|
||||
# timeout: 20s
|
||||
# retries: 3
|
||||
|
||||
gitea:
|
||||
image: gitea/gitea:1.25
|
||||
container_name: gitea-server
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
#minio:
|
||||
# condition: service_healthy
|
||||
environment:
|
||||
- GITEA__database__DB_TYPE=postgres
|
||||
- GITEA__database__HOST=postgres:5432
|
||||
- GITEA__database__NAME=gitea
|
||||
- GITEA__database__USER=gitea
|
||||
- GITEA__database__PASSWD=${POSTGRES_PASSWORD}
|
||||
- GITEA__server__DOMAIN=gitea.home.hrajfrisbee.cz
|
||||
- GITEA__server__SSH_DOMAIN=gitea.home.hrajfrisbee.cz
|
||||
- GITEA__server__ROOT_URL=https://gitea.home.hrajfrisbee.cz
|
||||
- GITEA__security__SECRET_KEY=${GITEA_SECRET_KEY}
|
||||
- GITEA__security__INTERNAL_TOKEN=${INTERNAL_TOKEN}
|
||||
- GITEA__mailer__ENABLED=true
|
||||
- GITEA__mailer__PROTOCOL=smtps
|
||||
- GITEA__mailer__SMTP_ADDR=smtp.gmail.com
|
||||
- GITEA__mailer__SMTP_PORT=465
|
||||
- GITEA__mailer__USER=kacerr.cz@gmail.com
|
||||
- GITEA__mailer__PASSWD=${GMAIL_GITEA_APP_PASSWORD}
|
||||
- GITEA__mailer__FROM=kacerr.cz+gitea@gmail.com
|
||||
- GITEA__packages__ENABLED=true
|
||||
|
||||
#- GITEA__storage__STORAGE_TYPE=minio
|
||||
#- GITEA__storage__MINIO_ENDPOINT=minio:9000
|
||||
#- GITEA__storage__MINIO_ACCESS_KEY_ID=gitea
|
||||
#- GITEA__storage__MINIO_SECRET_ACCESS_KEY=${MINIO_ROOT_PASSWORD}
|
||||
#- GITEA__storage__MINIO_BUCKET=gitea
|
||||
#- GITEA__storage__MINIO_USE_SSL=false
|
||||
#- GITEA__lfs__STORAGE_TYPE=minio
|
||||
#- GITEA__packages__STORAGE_TYPE=minio
|
||||
- GITEA__actions__ENABLED=true
|
||||
volumes:
|
||||
- ./data:/data
|
||||
- /etc/timezone:/etc/timezone:ro
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
ports:
|
||||
- "3000:3000"
|
||||
- "2222:22"
|
||||
networks:
|
||||
- gitea-network
|
||||
|
||||
gitea-runner:
|
||||
image: gitea/act_runner:nightly
|
||||
container_name: gitea-runner
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- gitea
|
||||
environment:
|
||||
GITEA_INSTANCE_URL: https://gitea.home.hrajfrisbee.cz/
|
||||
GITEA_RUNNER_REGISTRATION_TOKEN: ${RUNNER_TOKEN}
|
||||
CONFIG_FILE: /config/config.yaml
|
||||
volumes:
|
||||
- ./runner-data:/data
|
||||
- ./runner-config.yaml:/config/config.yaml:ro
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
networks:
|
||||
- gitea-network
|
||||
|
||||
# caddy:
|
||||
# image: caddy:2.7-alpine
|
||||
# container_name: gitea-caddy
|
||||
# restart: unless-stopped
|
||||
# ports:
|
||||
# - "80:80"
|
||||
# - "443:443"
|
||||
# volumes:
|
||||
# - ./Caddyfile:/etc/caddy/Caddyfile
|
||||
# - ./caddy-data:/data
|
||||
# - ./caddy-config:/config
|
||||
# networks:
|
||||
# - gitea-network
|
||||
|
||||
networks:
|
||||
gitea-network:
|
||||
driver: bridge
|
||||
|
||||
volumes:
|
||||
postgres-data:
|
||||
#minio-data:
|
||||
gitea-data:
|
||||
#caddy-data:
|
||||
#caddy-config:
|
||||
14
vms-home/docker-30/gitea/readme.md
Normal file
14
vms-home/docker-30/gitea/readme.md
Normal file
@@ -0,0 +1,14 @@
|
||||
# Gitea
|
||||
|
||||
```bash
|
||||
# mkdir -p /srv/docker/gitea-production/{data,postgres,minio,config}
|
||||
mkdir -p /srv/docker/gitea-production/{data,postgres,config}
|
||||
cd /srv/docker/gitea-production
|
||||
|
||||
# Generate secure passwords
|
||||
echo "POSTGRES_PASSWORD=$(openssl rand -base64 32)" > .env
|
||||
echo "MINIO_ROOT_PASSWORD=$(openssl rand -base64 24)" >> .env
|
||||
echo "GITEA_SECRET_KEY=$(openssl rand -base64 32)" >> .env
|
||||
echo "INTERNAL_TOKEN=$(openssl rand -base64 32)" >> .env
|
||||
|
||||
```
|
||||
15
vms-home/docker-30/gitea/runner-config.yaml
Normal file
15
vms-home/docker-30/gitea/runner-config.yaml
Normal file
@@ -0,0 +1,15 @@
|
||||
runner:
|
||||
file: /data/.runner
|
||||
fetch_interval: 10s
|
||||
fetch_timeout: 30s
|
||||
capacity: 4 # number of concurrent jobs this runner will accept
|
||||
|
||||
cache:
|
||||
enabled: true
|
||||
dir: /data/cache
|
||||
host: gitea-runner
|
||||
port: 8088
|
||||
|
||||
container:
|
||||
network: gitea-production_gitea-network
|
||||
force_pull: true
|
||||
84
vms-home/docker-30/kanidm/gitea-action-kubernetes-access.md
Normal file
84
vms-home/docker-30/kanidm/gitea-action-kubernetes-access.md
Normal file
@@ -0,0 +1,84 @@
|
||||
## 1. Create Kanidm service account + OAuth2 client
|
||||
|
||||
```bash
|
||||
# Create a service account for CI
|
||||
kanidm service-account create gitea_ci "Gitea CI Deploy" idm_admins --name idm_admin
|
||||
|
||||
# Create a group and add the service account
|
||||
kanidm group create k8s_deployers
|
||||
kanidm group add-members k8s_deployers gitea_ci
|
||||
|
||||
# Create the OAuth2 client (or reuse existing k8s one)
|
||||
# If you already have a k8s OIDC client, just add scope maps:
|
||||
kanidm system oauth2 update-scope-map k8s k8s_deployers openid groups
|
||||
|
||||
# Generate an API token for the service account
|
||||
kanidm service-account api-token generate --name idm_admin gitea_ci "gitea-ci-token"
|
||||
# ⚠️ Save the output token — this is the subject_token for exchange
|
||||
```
|
||||
|
||||
## 2. RBAC in Kubernetes
|
||||
|
||||
```yaml
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: gitea-ci-deploy
|
||||
subjects:
|
||||
- kind: User
|
||||
name: "gitea_ci@idm.home.hrajfrisbee.cz" # matches preferred_username claim
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
roleRef:
|
||||
kind: ClusterRole
|
||||
name: edit # scope down as needed
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
|
||||
```
|
||||
|
||||
## 3. Token exchange + kubeconfig setup (test in bash)
|
||||
|
||||
```bash
|
||||
vault-login # prepared alias
|
||||
|
||||
#!/usr/bin/env bash
|
||||
# set -euo pipefail
|
||||
|
||||
KANIDM_URL="https://idm.home.hrajfrisbee.cz"
|
||||
OAUTH2_CLIENT_ID="k8s" # your k8s OIDC client name in Kanidm
|
||||
API_TOKEN=$(vault kv get -format=json -mount="secret" "k8s_home/gitea/gitea-ci-token" |jq -r .data.data.token)
|
||||
K8S_API="https://192.168.0.31:6443"
|
||||
|
||||
# Exchange the API token for an OIDC token via RFC 8693
|
||||
RESPONSE=$(curl -sf -X POST "${KANIDM_URL}/oauth2/token" \
|
||||
-d "grant_type=urn:ietf:params:oauth:grant-type:token-exchange" \
|
||||
-d "client_id=${OAUTH2_CLIENT_ID}" \
|
||||
-d "subject_token=${API_TOKEN}" \
|
||||
-d "subject_token_type=urn:ietf:params:oauth:token-type:access_token" \
|
||||
-d "audience=${OAUTH2_CLIENT_ID}" \
|
||||
-d "scope=openid groups")
|
||||
|
||||
ID_TOKEN=$(echo "$RESPONSE" | jq -r '.id_token')
|
||||
|
||||
# Inspect claims (sanity check)
|
||||
echo "$ID_TOKEN" | cut -d. -f2 | base64 -d 2>/dev/null | jq .
|
||||
|
||||
# Build kubeconfig
|
||||
export KUBECONFIG=$(mktemp)
|
||||
kubectl config set-cluster mycluster \
|
||||
--server="${K8S_API}" \
|
||||
--certificate-authority=/path/to/ca.crt
|
||||
|
||||
kubectl config set-credentials gitea-ci \
|
||||
--token="${ID_TOKEN}"
|
||||
|
||||
kubectl config set-context gitea-ci \
|
||||
--cluster=mycluster \
|
||||
--user=gitea-ci
|
||||
|
||||
kubectl config use-context gitea-ci
|
||||
|
||||
# Test
|
||||
kubectl auth whoami
|
||||
kubectl get ns
|
||||
|
||||
```
|
||||
169
vms-home/docker-30/kanidm/readme.md
Normal file
169
vms-home/docker-30/kanidm/readme.md
Normal file
@@ -0,0 +1,169 @@
|
||||
## Upgrade
|
||||
|
||||
```bash
|
||||
docker exec -it kanidmd kanidmd domain upgrade-check
|
||||
# make sure backup exists: /srv/docker/kanidm/data/kanidm/backups
|
||||
|
||||
# change container image in: /srv/docker/kanidm/run.sh
|
||||
|
||||
# kanidm data restore
|
||||
docker stop kanidmd
|
||||
docker run --rm -it \
|
||||
-v kanidmd:/data \
|
||||
-v kanidmd_backups:/backup \
|
||||
kanidm/server:latest \
|
||||
/sbin/kanidmd database restore -c /data/server.toml /backup/kanidm.backup.json
|
||||
docker start kanidmd
|
||||
```
|
||||
|
||||
## Recover passwords from kanidm instance
|
||||
|
||||
```bash
|
||||
docker exec -i -t kanidmd kanidmd recover-account idm_admin
|
||||
```
|
||||
|
||||
## add user to k8s group
|
||||
|
||||
based on: https://blog.kammel.dev/post/k8s_home_lab_2025_06/
|
||||
|
||||
```bash
|
||||
export GROUP_NAME=k8s_users
|
||||
kanidm group create ${GROUP_NAME}
|
||||
kanidm group add-members ${GROUP_NAME} novakj
|
||||
|
||||
|
||||
export OAUTH2_NAME=k8s
|
||||
kanidm system oauth2 create-public ${OAUTH2_NAME} ${OAUTH2_NAME} http://localhost:8000
|
||||
kanidm system oauth2 add-redirect-url ${OAUTH2_NAME} http://localhost:8000
|
||||
kanidm system oauth2 update-scope-map ${OAUTH2_NAME} ${GROUP_NAME} email openid profile groups
|
||||
kanidm system oauth2 enable-localhost-redirects ${OAUTH2_NAME}
|
||||
|
||||
|
||||
kubectl oidc-login setup \
|
||||
--oidc-issuer-url=https://idm.home.hrajfrisbee.cz/oauth2/openid/k8s \
|
||||
--oidc-client-id=k8s
|
||||
|
||||
|
||||
|
||||
kubectl config set-credentials oidc \
|
||||
--exec-api-version=client.authentication.k8s.io/v1 \
|
||||
--exec-interactive-mode=Never \
|
||||
--exec-command=kubectl \
|
||||
--exec-arg=oidc-login \
|
||||
--exec-arg=get-token \
|
||||
--exec-arg="--oidc-issuer-url=https://idm.home.hrajfrisbee.cz/oauth2/openid/k8s" \
|
||||
--exec-arg="--oidc-client-id=k8s"
|
||||
|
||||
kubectl create clusterrolebinding oidc-cluster-admin \
|
||||
--clusterrole=cluster-admin \
|
||||
--user='https://idm.home.hrajfrisbee.cz/oauth2/openid/k8s#35842461-a1c4-4ad6-8b29-697c5ddbfe84'
|
||||
|
||||
```
|
||||
## commands
|
||||
|
||||
```bash
|
||||
# recover admin password
|
||||
# on the docker host
|
||||
docker exec -i -t kanidmd kanidmd recover-account admin
|
||||
docker exec -i -t kanidmd kanidmd recover-account idm_admin
|
||||
|
||||
# kanidm mangement commands (could be run on any logged in client)
|
||||
kanidm person credential create-reset-token novakj
|
||||
kanidm person get novakj | grep memberof
|
||||
kanidm group get kanidm group get
|
||||
kanidm group get idm_all_accounts
|
||||
kanidm group get idm_all_persons
|
||||
kanidm group account-policy credential-type-minimum idm_all_accounts any
|
||||
kanidm person get novakj | grep memberof
|
||||
kanidm group get idm_people_self_name_write
|
||||
```
|
||||
|
||||
## configure oauth proxy
|
||||
|
||||
```bash
|
||||
kanidm system oauth2 create oauth2-proxy "OAuth2 Proxy" https://oauth2-proxy.lab.home.hrajfrisbee.cz/oauth2/callback
|
||||
kanidm system oauth2 set-landing-url oauth2-proxy https://oauth2-proxy.lab.home.hrajfrisbee.cz
|
||||
kanidm system oauth2 enable-pkce oauth2-proxy
|
||||
kanidm system oauth2 warning-insecure-client-disable-pkce oauth2-proxy # if proxy doesn't support PKCE
|
||||
kanidm system oauth2 get oauth2-proxy # note the client secret
|
||||
|
||||
# update incorrect urls if needed
|
||||
remove-redirect-url
|
||||
kanidm system oauth2 add-redirect-url oauth2-proxy https://oauth2-proxy.lab.home.hrajfrisbee.cz/oauth2/callback
|
||||
kanidm system oauth2 set-landing-url oauth2-proxy https://oauth2-proxy.lab.home.hrajfrisbee.cz
|
||||
|
||||
# output
|
||||
✔ Multiple authentication tokens exist. Please select one · idm_admin@idm.home.hrajfrisbee.cz
|
||||
---
|
||||
class: account
|
||||
class: key_object
|
||||
class: key_object_internal
|
||||
class: key_object_jwe_a128gcm
|
||||
class: key_object_jwt_es256
|
||||
class: memberof
|
||||
class: oauth2_resource_server
|
||||
class: oauth2_resource_server_basic
|
||||
class: object
|
||||
displayname: OAuth2 Proxy
|
||||
key_internal_data: 69df0a387991455f7c9800f13b881803: valid jwe_a128gcm 0
|
||||
key_internal_data: c5f61c48a9c0eb61ba993a36748826cc: valid jws_es256 0
|
||||
name: oauth2-proxy
|
||||
oauth2_allow_insecure_client_disable_pkce: true
|
||||
oauth2_rs_basic_secret: hidden
|
||||
oauth2_rs_origin_landing: https://oauth2-proxylab.home.hrajfrisbee.cz/
|
||||
oauth2_strict_redirect_uri: true
|
||||
spn: oauth2-proxy@idm.home.hrajfrisbee.cz
|
||||
uuid: d0dcbad5-90e4-4e36-a51b-653624069009
|
||||
|
||||
secret: 7KJbUe5x35NVCT1VbzZfhYBU19cz9Xe9Z1fvw4WazrkHX2c8
|
||||
|
||||
|
||||
|
||||
kanidm system oauth2 update-scope-map oauth2-proxy k8s_users openid profile email
|
||||
```
|
||||
|
||||
|
||||
|
||||
```bash
|
||||
|
||||
docker run -d --name=kanidmd --restart=always \
|
||||
-p '8443:8443' \
|
||||
-p '3636:3636' \
|
||||
--volume /srv/docker/kanidm/data:/data \
|
||||
docker.io/kanidm/server:latest
|
||||
|
||||
docker run --rm -i -t -v --restart=always \
|
||||
-p '8443:8443' \
|
||||
-p '3636:3636' \
|
||||
--volume /srv/docker/kanidm/data:/data \
|
||||
docker.io/kanidm/server:latest \
|
||||
kanidmd cert-generate
|
||||
|
||||
```
|
||||
|
||||
|
||||
## Service account for gitea runner
|
||||
|
||||
```bash
|
||||
# create service account
|
||||
#kanidm service-account create \
|
||||
# gitea_ci \ # account name
|
||||
# "Gitea CI Deploy" \ # display name
|
||||
# idm_admins \ # entry-managed-by (delegation group)
|
||||
# --name idm_admin # authenticate as this user
|
||||
|
||||
kanidm service-account create gitea_ci "Gitea CI Deploy" idm_admins --name idm_admin
|
||||
|
||||
# Create a group and add the service account
|
||||
kanidm group create k8s_deployers
|
||||
kanidm group add-members k8s_deployers gitea_ci
|
||||
|
||||
# Create the OAuth2 client (or reuse existing k8s one)
|
||||
# If you already have a k8s OIDC client, just add scope maps:
|
||||
kanidm system oauth2 update-scope-map k8s k8s_deployers openid groups
|
||||
|
||||
# Generate an API token for the service account
|
||||
kanidm service-account api-token generate --name idm_admin gitea_ci "gitea-ci-token"
|
||||
# ⚠️ Save the output token — this is the subject_token for exchange
|
||||
|
||||
```
|
||||
9
vms-home/docker-30/kanidm/run.sh
Normal file
9
vms-home/docker-30/kanidm/run.sh
Normal file
@@ -0,0 +1,9 @@
|
||||
docker rm -f kanidmd
|
||||
|
||||
docker run -d --name=kanidmd --restart=always \
|
||||
-p '8443:8443' \
|
||||
-p '3636:3636' \
|
||||
--volume /srv/docker/kanidm/data:/data \
|
||||
docker.io/kanidm/server:1.9.1
|
||||
|
||||
# previous version: 1.8.5
|
||||
136
vms-home/docker-30/kanidm/server.toml
Normal file
136
vms-home/docker-30/kanidm/server.toml
Normal file
@@ -0,0 +1,136 @@
|
||||
# The server configuration file version.
|
||||
version = "2"
|
||||
|
||||
# The webserver bind address. Requires TLS certificates.
|
||||
# If the port is set to 443 you may require the
|
||||
# NET_BIND_SERVICE capability. This accepts a single address
|
||||
# or an array of addresses to listen on.
|
||||
# Defaults to "127.0.0.1:8443"
|
||||
bindaddress = "0.0.0.0:8443"
|
||||
#
|
||||
# The read-only ldap server bind address. Requires
|
||||
# TLS certificates. If set to 636 you may require the
|
||||
# NET_BIND_SERVICE capability. This accepts a single address
|
||||
# or an array of addresses to listen on.
|
||||
# Defaults to "" (disabled)
|
||||
# ldapbindaddress = "0.0.0.0:3636"
|
||||
#
|
||||
# The path to the kanidm database.
|
||||
db_path = "/data/kanidm.db"
|
||||
#
|
||||
# If you have a known filesystem, kanidm can tune the
|
||||
# database page size to match. Valid choices are:
|
||||
# [zfs, other]
|
||||
# If you are unsure about this leave it as the default
|
||||
# (other). After changing this
|
||||
# value you must run a vacuum task.
|
||||
# - zfs:
|
||||
# * sets database pagesize to 64k. You must set
|
||||
# recordsize=64k on the zfs filesystem.
|
||||
# - other:
|
||||
# * sets database pagesize to 4k, matching most
|
||||
# filesystems block sizes.
|
||||
# db_fs_type = "zfs"
|
||||
#
|
||||
# The number of entries to store in the in-memory cache.
|
||||
# Minimum value is 256. If unset
|
||||
# an automatic heuristic is used to scale this.
|
||||
# You should only adjust this value if you experience
|
||||
# memory pressure on your system.
|
||||
# db_arc_size = 2048
|
||||
#
|
||||
# TLS chain and key in pem format. Both must be present.
|
||||
# If the server receives a SIGHUP, these files will be
|
||||
# re-read and reloaded if their content is valid.
|
||||
tls_chain = "/data/chain.pem"
|
||||
tls_key = "/data/key.pem"
|
||||
#
|
||||
# The log level of the server. May be one of info, debug, trace
|
||||
#
|
||||
# NOTE: this can be overridden by the environment variable
|
||||
# `KANIDM_LOG_LEVEL` at runtime
|
||||
# Defaults to "info"
|
||||
# log_level = "info"
|
||||
#
|
||||
# The DNS domain name of the server. This is used in a
|
||||
# number of security-critical contexts
|
||||
# such as webauthn, so it *must* match your DNS
|
||||
# hostname. It is used to create
|
||||
# security principal names such as `william@idm.example.com`
|
||||
# so that in a (future) trust configuration it is possible
|
||||
# to have unique Security Principal Names (spns) throughout
|
||||
# the topology.
|
||||
#
|
||||
# ⚠️ WARNING ⚠️
|
||||
#
|
||||
# Changing this value WILL break many types of registered
|
||||
# credentials for accounts including but not limited to
|
||||
# webauthn, oauth tokens, and more.
|
||||
# If you change this value you *must* run
|
||||
# `kanidmd domain rename` immediately after.
|
||||
domain = "idm.home.hrajfrisbee.cz"
|
||||
#
|
||||
# The origin for webauthn. This is the url to the server,
|
||||
# with the port included if it is non-standard (any port
|
||||
# except 443). This must match or be a descendent of the
|
||||
# domain name you configure above. If these two items are
|
||||
# not consistent, the server WILL refuse to start!
|
||||
# origin = "https://idm.example.com"
|
||||
# # OR
|
||||
# origin = "https://idm.example.com:8443"
|
||||
origin = "https://idm.home.hrajfrisbee.cz"
|
||||
|
||||
# HTTPS requests can be reverse proxied by a loadbalancer.
|
||||
# To preserve the original IP of the caller, these systems
|
||||
# will often add a header such as "Forwarded" or
|
||||
# "X-Forwarded-For". Some other proxies can use the PROXY
|
||||
# protocol v2 header. While we support the PROXY protocol
|
||||
# v1 header, we STRONGLY discourage it's use as it has
|
||||
# significantly greater overheads compared to v2 during
|
||||
# processing.
|
||||
# This setting allows configuration of the list of trusted
|
||||
# IPs or IP ranges which can supply this header information,
|
||||
# and which format the information is provided in.
|
||||
# Defaults to "none" (no trusted sources)
|
||||
# Only one option can be used at a time.
|
||||
# [http_client_address_info]
|
||||
# proxy-v2 = ["127.0.0.1", "127.0.0.0/8"]
|
||||
# # OR
|
||||
# [http_client_address_info]
|
||||
# x-forward-for = ["127.0.0.1", "127.0.0.0/8"]
|
||||
# # OR
|
||||
# [http_client_address_info]
|
||||
# # AVOID IF POSSIBLE!!!
|
||||
# proxy-v1 = ["127.0.0.1", "127.0.0.0/8"]
|
||||
|
||||
# LDAPS requests can be reverse proxied by a loadbalancer.
|
||||
# To preserve the original IP of the caller, these systems
|
||||
# can add a header such as the PROXY protocol v2 header.
|
||||
# While we support the PROXY protocol v1 header, we STRONGLY
|
||||
# discourage it's use as it has significantly greater
|
||||
# overheads compared to v2 during processing.
|
||||
# This setting allows configuration of the list of trusted
|
||||
# IPs or IP ranges which can supply this header information,
|
||||
# and which format the information is provided in.
|
||||
# Defaults to "none" (no trusted sources)
|
||||
# [ldap_client_address_info]
|
||||
# proxy-v2 = ["127.0.0.1", "127.0.0.0/8"]
|
||||
# # OR
|
||||
# [ldap_client_address_info]
|
||||
# # AVOID IF POSSIBLE!!!
|
||||
# proxy-v1 = ["127.0.0.1", "127.0.0.0/8"]
|
||||
|
||||
[online_backup]
|
||||
# The path to the output folder for online backups
|
||||
path = "/data/kanidm/backups/"
|
||||
# The schedule to run online backups (see https://crontab.guru/)
|
||||
# every day at 22:00 UTC (default)
|
||||
schedule = "00 22 * * *"
|
||||
# four times a day at 3 minutes past the hour, every 6th hours
|
||||
# schedule = "03 */6 * * *"
|
||||
# We also support non standard cron syntax, with the following format:
|
||||
# sec min hour day of month month day of week year
|
||||
# (it's very similar to the standard cron syntax, it just allows to specify the seconds
|
||||
# at the beginning and the year at the end)
|
||||
# Number of backups to keep (default 7)
|
||||
# versions = 7
|
||||
46
vms-home/docker-30/lab-proxy/nginx.conf
Normal file
46
vms-home/docker-30/lab-proxy/nginx.conf
Normal file
@@ -0,0 +1,46 @@
|
||||
# nginx.conf
|
||||
|
||||
error_log /dev/stderr;
|
||||
|
||||
http {
|
||||
|
||||
server {
|
||||
listen 9080;
|
||||
|
||||
location / {
|
||||
proxy_pass http://192.168.0.35:80;
|
||||
proxy_set_header Host $host;
|
||||
}
|
||||
}
|
||||
|
||||
log_format detailed '$remote_addr - [$time_local] '
|
||||
'"$request_method $host$request_uri" '
|
||||
'$status $body_bytes_sent '
|
||||
'"$http_referer" "$http_user_agent"';
|
||||
|
||||
access_log /dev/stdout detailed;
|
||||
}
|
||||
|
||||
stream {
|
||||
# Stream doesn't log by default, enable explicitly:
|
||||
log_format stream_log '$remote_addr [$time_local] '
|
||||
'$protocol $ssl_preread_server_name '
|
||||
'$status $bytes_sent $bytes_received $session_time';
|
||||
|
||||
access_log /dev/stdout stream_log;
|
||||
|
||||
# Nginx ingress in kubernetes
|
||||
server {
|
||||
listen 9443;
|
||||
proxy_pass 192.168.0.35:443;
|
||||
}
|
||||
|
||||
# Gateway provided by cilium/envoy
|
||||
server {
|
||||
listen 9444;
|
||||
proxy_pass 192.168.0.36:443;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
events {}
|
||||
9
vms-home/docker-30/lab-proxy/run.sh
Normal file
9
vms-home/docker-30/lab-proxy/run.sh
Normal file
@@ -0,0 +1,9 @@
|
||||
docker rm -f lab-proxy || /usr/bin/true
|
||||
|
||||
docker run -d --name lab-proxy \
|
||||
--restart unless-stopped \
|
||||
-v /srv/docker/lab-proxy/nginx.conf:/etc/nginx/nginx.conf:ro \
|
||||
-p 9443:9443 \
|
||||
-p 9444:9444 \
|
||||
-p 9080:9080 \
|
||||
nginx:alpine
|
||||
10
vms-home/docker-30/maru-hleda-byt/run.sh
Normal file
10
vms-home/docker-30/maru-hleda-byt/run.sh
Normal file
@@ -0,0 +1,10 @@
|
||||
#!/bin/bash
|
||||
|
||||
docker rm -f maru-hleda-byt
|
||||
|
||||
# gitea registry login with kacerr / token
|
||||
docker run -d --name maru-hleda-byt \
|
||||
--restart=always \
|
||||
-p 8080:8080 \
|
||||
-v /srv/maru-hleda-byt/data:/app/data \
|
||||
gitea.home.hrajfrisbee.cz/littlemeat/maru-hleda-byt:0.01
|
||||
22
vms-home/docker-30/nginx/001-gitea.conf
Normal file
22
vms-home/docker-30/nginx/001-gitea.conf
Normal file
@@ -0,0 +1,22 @@
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
server_name gitea.home.hrajfrisbee.cz;
|
||||
|
||||
ssl_certificate /etc/letsencrypt/live/gitea.home.hrajfrisbee.cz/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/gitea.home.hrajfrisbee.cz/privkey.pem;
|
||||
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
|
||||
ssl_prefer_server_ciphers off;
|
||||
|
||||
location / {
|
||||
proxy_pass http://192.168.0.30:3000;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
|
||||
# Gitea Git over HTTP
|
||||
client_max_body_size 512m;
|
||||
}
|
||||
35
vms-home/docker-30/nginx/002-jellyfin.conf
Normal file
35
vms-home/docker-30/nginx/002-jellyfin.conf
Normal file
@@ -0,0 +1,35 @@
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
server_name jellyfin.home.hrajfrisbee.cz;
|
||||
|
||||
ssl_certificate /etc/letsencrypt/live/gitea.home.hrajfrisbee.cz/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/gitea.home.hrajfrisbee.cz/privkey.pem;
|
||||
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
|
||||
ssl_prefer_server_ciphers off;
|
||||
|
||||
|
||||
# Security headers for media streaming
|
||||
add_header X-Frame-Options "SAMEORIGIN";
|
||||
add_header X-XSS-Protection "1; mode=block";
|
||||
add_header X-Content-Type-Options "nosniff";
|
||||
|
||||
# Increase body size for high-res movie posters
|
||||
client_max_body_size 20M;
|
||||
|
||||
location / {
|
||||
# Proxy to your Synology or VM IP and Jellyfin port (default 8096)
|
||||
proxy_pass http://192.168.0.2:8096;
|
||||
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header X-Forwarded-Protocol $scheme;
|
||||
proxy_set_header X-Forwarded-Host $http_host;
|
||||
|
||||
# Disable buffering for smoother streaming
|
||||
proxy_buffering off;
|
||||
}
|
||||
}
|
||||
20
vms-home/docker-30/nginx/021-drills.conf
Normal file
20
vms-home/docker-30/nginx/021-drills.conf
Normal file
@@ -0,0 +1,20 @@
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
server_name drills.home.hrajfrisbee.cz;
|
||||
|
||||
ssl_certificate /etc/letsencrypt/live/drills.home.hrajfrisbee.cz/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/drills.home.hrajfrisbee.cz/privkey.pem;
|
||||
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
|
||||
ssl_prefer_server_ciphers off;
|
||||
|
||||
location /presejpacky {
|
||||
proxy_pass http://192.168.0.30:3101;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
|
||||
}
|
||||
43
vms-home/docker-30/readme.md
Normal file
43
vms-home/docker-30/readme.md
Normal file
@@ -0,0 +1,43 @@
|
||||
# docker-30
|
||||
|
||||
## taiscale
|
||||
|
||||
```bash
|
||||
# Add signing key
|
||||
curl -fsSL https://pkgs.tailscale.com/stable/ubuntu/$(lsb_release -cs).noarmor.gpg | sudo tee /usr/share/keyrings/tailscale-archive-keyring.gpg >/dev/null
|
||||
|
||||
# Add repo
|
||||
echo "deb [signed-by=/usr/share/keyrings/tailscale-archive-keyring.gpg] https://pkgs.tailscale.com/stable/ubuntu $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/tailscale.list
|
||||
|
||||
# Install
|
||||
sudo apt update && sudo apt install tailscale
|
||||
|
||||
# Start
|
||||
sudo tailscale up
|
||||
```
|
||||
|
||||
|
||||
## connect nvmeof volume
|
||||
|
||||
```bash
|
||||
nvme discover -t tcp -a 192.168.0.40 -s 4420
|
||||
|
||||
nvme connect -t tcp -a 192.168.0.40 -s 4420 -n nqn.2011-06.com.truenas:uuid:6ac818fb-9f51-4e28-a5d6-41502eba031d:garage-s3
|
||||
|
||||
nvme list
|
||||
|
||||
mkfs.xfs -L garage /dev/nvme0n1
|
||||
mkdir -p /srv/garage
|
||||
mount /dev/disk/by-label/garage /srv/garage
|
||||
mkdir -p /srv/garage/{meta,data,snapshots}
|
||||
|
||||
# add to fstab
|
||||
# LABEL=garage /srv/garage xfs defaults,_netdev,nofail,x-systemd.requires=nvmf-autoconnect.service 0 0
|
||||
|
||||
# /etc/nvme/discovery.conf
|
||||
-t tcp -a <TRUENAS_IP> -s 4420 -n nqn.2011-06.com.truenas:garage-s3
|
||||
systemctl enable nvmf-autoconnect.service
|
||||
|
||||
|
||||
|
||||
```
|
||||
35
vms-home/docker-30/vault/backup.md
Normal file
35
vms-home/docker-30/vault/backup.md
Normal file
@@ -0,0 +1,35 @@
|
||||
## vault-cli install
|
||||
|
||||
```bash
|
||||
VAULT_VERSION="1.21.2"
|
||||
wget https://releases.hashicorp.com/vault/${VAULT_VERSION}/vault_${VAULT_VERSION}_linux_amd64.zip
|
||||
unzip vault_${VAULT_VERSION}_linux_amd64.zip
|
||||
sudo mv vault /usr/local/bin/
|
||||
```
|
||||
|
||||
## minio-cli
|
||||
|
||||
```bash
|
||||
wget https://dl.min.io/client/mc/release/linux-amd64/mc -O /tmp/minio-cli
|
||||
chmod +x /tmp/minio-cli
|
||||
sudo mv /tmp/minio-cli /usr/local/bin/minio-cli
|
||||
|
||||
minio-cli alias set synology http://192.168.0.2:9000 k8s ----proper secret here----
|
||||
|
||||
```
|
||||
|
||||
|
||||
## backup token
|
||||
|
||||
```bash
|
||||
mkdir -p /etc/vault.d/
|
||||
vault policy write backup - <<EOF
|
||||
path "sys/storage/raft/snapshot" {
|
||||
capabilities = ["read"]
|
||||
}
|
||||
EOF
|
||||
|
||||
vault token create -policy=backup -period=8760h -orphan > /etc/vault.d/backup-token
|
||||
chmod 600 /etc/vault.d/backup-token
|
||||
|
||||
```
|
||||
20
vms-home/docker-30/vault/config.json
Normal file
20
vms-home/docker-30/vault/config.json
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"ui": true,
|
||||
"listener": {
|
||||
"tcp": {
|
||||
"address": "0.0.0.0:8200",
|
||||
"tls_disable": "1",
|
||||
"tls_cert_file": "/vault/certs/fullchain.pem",
|
||||
"tls_key_file": "/vault/certs/privkey.pem"
|
||||
}
|
||||
},
|
||||
"backend": {
|
||||
"file": {
|
||||
"path": "/vault/data/file"
|
||||
}
|
||||
},
|
||||
"default_lease_ttl": "168h",
|
||||
"max_lease_ttl": "0h",
|
||||
"api_addr": "https://vault.hrajfrisbee.cz"
|
||||
// "api_addr": "http://0.0.0.0:8200"
|
||||
}
|
||||
20
vms-home/docker-30/vault/docker-compose.yaml
Normal file
20
vms-home/docker-30/vault/docker-compose.yaml
Normal file
@@ -0,0 +1,20 @@
|
||||
services:
|
||||
vault:
|
||||
image: hashicorp/vault:1.21.1
|
||||
container_name: vault
|
||||
restart: unless-stopped
|
||||
cap_add:
|
||||
- IPC_LOCK
|
||||
ports:
|
||||
- 8200:8200
|
||||
environment:
|
||||
- VAULT_ADDR=http://0.0.0.0:8200
|
||||
- VAULT_API_ADDR=http://0.0.0.0:8200
|
||||
- VAULT_ADDRESS=http://0.0.0.0:8200
|
||||
volumes:
|
||||
- ./data:/vault/data
|
||||
- ./config:/vault/config
|
||||
- ./logs:/vault/logs
|
||||
- ./certs:/vault/certs
|
||||
entrypoint: vault
|
||||
command: server -config=/vault/config/vault.json -log-level=debug
|
||||
10
vms-home/docker-30/vault/gitea-access-into-vault.md
Normal file
10
vms-home/docker-30/vault/gitea-access-into-vault.md
Normal file
@@ -0,0 +1,10 @@
|
||||
## 1. Enable & configure JWT auth in Vault
|
||||
|
||||
```bash
|
||||
vault auth enable jwt
|
||||
|
||||
vault write auth/jwt/config \
|
||||
bound_issuer="https://gitea.home.hrajfrisbee.cz" \
|
||||
jwks_url="https://gitea.home.hrajfrisbee.cz/login/oauth/keys"
|
||||
|
||||
```
|
||||
38
vms-home/docker-30/vault/readme.md
Normal file
38
vms-home/docker-30/vault/readme.md
Normal file
@@ -0,0 +1,38 @@
|
||||
## deployment notes
|
||||
|
||||
There was a problem with "production" deployment of Vault through docker container, because default `docker-entrypoint.sh` adds argument saying where dev instance is supposed to listen and then vault crashes because it tries to listen on same port twice.
|
||||
|
||||
Solution: override default entrypoint
|
||||
|
||||
```bash
|
||||
# vault helpers
|
||||
alias set-vault="export VAULT_ADDR=https://docker-30:8200"
|
||||
alias set-vault-ignore-tls="export VAULT_ADDR=https://docker-30:8200; export VAULT_SKIP_VERIFY=true"
|
||||
|
||||
|
||||
export VAULT_ADDR="https://vault.hrajfrisbee.cz"
|
||||
export VAULT_SKIP_VERIFY=true
|
||||
```
|
||||
|
||||
## backup
|
||||
|
||||
Simple file copy initiated by cron, backend storage is minio (s3) running on synology
|
||||
|
||||
```bash
|
||||
echo '30 2 * * * root /root/bin/vault-backup.sh >> /var/log/vault-backup.log 2>&1' > /etc/cron.d/vault-backup
|
||||
```
|
||||
|
||||
```bash
|
||||
# output role info
|
||||
tofu output -raw role_id
|
||||
tofu output -raw secret_id
|
||||
|
||||
```
|
||||
|
||||
## vault initialization
|
||||
|
||||
```bash
|
||||
|
||||
vault operator init -key-shares=1 -key-threshold=1
|
||||
|
||||
```
|
||||
115
vms-home/docker-30/vault/terraform/main.tf
Normal file
115
vms-home/docker-30/vault/terraform/main.tf
Normal file
@@ -0,0 +1,115 @@
|
||||
resource "vault_mount" "kv" {
|
||||
path = "secret"
|
||||
type = "kv-v2"
|
||||
description = "KV v2 secrets engine"
|
||||
}
|
||||
|
||||
resource "vault_jwt_auth_backend" "gitea" {
|
||||
path = "jwt"
|
||||
type = "jwt"
|
||||
bound_issuer = "https://gitea.home.hrajfrisbee.cz"
|
||||
jwks_url = "https://gitea.home.hrajfrisbee.cz/login/oauth/keys"
|
||||
}
|
||||
|
||||
resource "vault_policy" "eso_read" {
|
||||
name = "external-secrets-read"
|
||||
policy = <<-EOT
|
||||
path "${vault_mount.kv.path}/data/*" {
|
||||
capabilities = ["read"]
|
||||
}
|
||||
path "${vault_mount.kv.path}/metadata/*" {
|
||||
capabilities = ["read", "list"]
|
||||
}
|
||||
EOT
|
||||
}
|
||||
|
||||
# for now i allow my gitea to read everything in /v1/secret/data/gitea
|
||||
resource "vault_policy" "gitea_ci_read" {
|
||||
name = "gitea-ci-read"
|
||||
policy = <<-EOT
|
||||
path "${vault_mount.kv.path}/data/gitea/*" {
|
||||
capabilities = ["read"]
|
||||
}
|
||||
path "${vault_mount.kv.path}/metadata/gitea/*" {
|
||||
capabilities = ["read", "list"]
|
||||
}
|
||||
EOT
|
||||
}
|
||||
|
||||
resource "vault_jwt_auth_backend_role" "gitea_ci" {
|
||||
backend = vault_jwt_auth_backend.gitea.path
|
||||
role_name = "gitea-ci"
|
||||
role_type = "jwt"
|
||||
token_policies = [vault_policy.gitea_ci_read.name]
|
||||
|
||||
user_claim = "sub"
|
||||
bound_audiences = ["https://gitea.home.hrajfrisbee.cz"]
|
||||
|
||||
# allow any valid jwt token when commented out
|
||||
# bound_claims = {
|
||||
# repository = "myorg/repo1,myorg/repo3"
|
||||
# }
|
||||
|
||||
token_ttl = 600
|
||||
token_max_ttl = 1200
|
||||
}
|
||||
|
||||
resource "vault_auth_backend" "approle" {
|
||||
type = "approle"
|
||||
}
|
||||
|
||||
resource "vault_approle_auth_backend_role" "eso" {
|
||||
backend = vault_auth_backend.approle.path
|
||||
role_name = "external-secrets"
|
||||
token_policies = [vault_policy.eso_read.name]
|
||||
token_ttl = 3600
|
||||
token_max_ttl = 14400
|
||||
}
|
||||
|
||||
data "vault_approle_auth_backend_role_id" "eso" {
|
||||
backend = vault_auth_backend.approle.path
|
||||
role_name = vault_approle_auth_backend_role.eso.role_name
|
||||
}
|
||||
|
||||
resource "vault_approle_auth_backend_role_secret_id" "eso" {
|
||||
backend = vault_auth_backend.approle.path
|
||||
role_name = vault_approle_auth_backend_role.eso.role_name
|
||||
}
|
||||
|
||||
output "role_id" {
|
||||
value = data.vault_approle_auth_backend_role_id.eso.role_id
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
output "secret_id" {
|
||||
value = vault_approle_auth_backend_role_secret_id.eso.secret_id
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
resource "vault_approle_auth_backend_role" "gitea_ci" {
|
||||
backend = vault_auth_backend.approle.path
|
||||
role_name = "gitea-ci"
|
||||
token_policies = [vault_policy.gitea_ci_read.name]
|
||||
token_ttl = 600
|
||||
token_max_ttl = 1200
|
||||
}
|
||||
|
||||
data "vault_approle_auth_backend_role_id" "gitea_ci" {
|
||||
backend = vault_auth_backend.approle.path
|
||||
role_name = vault_approle_auth_backend_role.gitea_ci.role_name
|
||||
}
|
||||
|
||||
resource "vault_approle_auth_backend_role_secret_id" "gitea_ci" {
|
||||
backend = vault_auth_backend.approle.path
|
||||
role_name = vault_approle_auth_backend_role.gitea_ci.role_name
|
||||
}
|
||||
|
||||
output "gitea_ci_role_id" {
|
||||
value = data.vault_approle_auth_backend_role_id.gitea_ci.role_id
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
output "gitea_ci_secret_id" {
|
||||
value = vault_approle_auth_backend_role_secret_id.gitea_ci.secret_id
|
||||
sensitive = true
|
||||
}
|
||||
1
vms-home/docker-30/vault/terraform/terraform.tfstate
Normal file
1
vms-home/docker-30/vault/terraform/terraform.tfstate
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
12
vms-home/docker-30/vault/terraform/versions.tf
Normal file
12
vms-home/docker-30/vault/terraform/versions.tf
Normal file
@@ -0,0 +1,12 @@
|
||||
terraform {
|
||||
required_providers {
|
||||
vault = {
|
||||
source = "hashicorp/vault"
|
||||
version = "~> 4.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
provider "vault" {
|
||||
# Uses VAULT_ADDR and VAULT_TOKEN from env
|
||||
}
|
||||
38
vms-home/docker-30/vault/vault-backup.sh
Normal file
38
vms-home/docker-30/vault/vault-backup.sh
Normal file
@@ -0,0 +1,38 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
# set -x # Enable debug output
|
||||
|
||||
# --- Configuration ---
|
||||
VAULT_DATA_DIR="${VAULT_DATA_DIR:-/srv/docker/vault/data/}"
|
||||
S3_BUCKET="${S3_BUCKET:-vault-backup}"
|
||||
MC_ALIAS="${MC_ALIAS:-synology}" # Pre-configured mc alias
|
||||
RETENTION_DAYS="${RETENTION_DAYS:-60}"
|
||||
|
||||
TIMESTAMP=$(date +%Y%m%d-%H%M%S)
|
||||
BACKUP_FILE="/tmp/vault-backup-${TIMESTAMP}.tar.gz"
|
||||
|
||||
log() { echo "[$(date -Iseconds)] $*"; }
|
||||
|
||||
cleanup() {
|
||||
rm -f "${BACKUP_FILE}"
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
# --- Create backup ---
|
||||
log "Backing up ${VAULT_DATA_DIR}..."
|
||||
tar -czf "${BACKUP_FILE}" -C "$(dirname "${VAULT_DATA_DIR}")" "$(basename "${VAULT_DATA_DIR}")"
|
||||
|
||||
BACKUP_SIZE=$(stat -c%s "${BACKUP_FILE}")
|
||||
log "Backup size: ${BACKUP_SIZE} bytes"
|
||||
|
||||
# --- Upload to MinIO ---
|
||||
log "Uploading to ${MC_ALIAS}/${S3_BUCKET}..."
|
||||
set -x
|
||||
minio-cli cp --quiet "${BACKUP_FILE}" "${MC_ALIAS}/${S3_BUCKET}/vault-backup-${TIMESTAMP}.tar.gz"
|
||||
|
||||
# --- Prune old backups ---
|
||||
log "Pruning backups older than ${RETENTION_DAYS} days..."
|
||||
minio-cli rm --quiet --recursive --force --older-than "${RETENTION_DAYS}d" "${MC_ALIAS}/${S3_BUCKET}/"
|
||||
|
||||
log "Backup complete: vault-backup-${TIMESTAMP}.tar.gz"
|
||||
52
vms-home/docker-30/zot/config.yaml
Normal file
52
vms-home/docker-30/zot/config.yaml
Normal file
@@ -0,0 +1,52 @@
|
||||
distSpecVersion: "1.1.0"
|
||||
storage:
|
||||
rootDirectory: /var/lib/zot
|
||||
gc: true
|
||||
gcDelay: "24h"
|
||||
dedupe: true
|
||||
http:
|
||||
address: 0.0.0.0
|
||||
port: 5000
|
||||
compat:
|
||||
- docker2s2
|
||||
log:
|
||||
# level: info
|
||||
level: debug
|
||||
extensions:
|
||||
ui:
|
||||
enable: true
|
||||
search:
|
||||
enable: true
|
||||
sync:
|
||||
enable: true
|
||||
credentialsFile: "/etc/zot/sync-credentials.json"
|
||||
registries:
|
||||
- urls: ["https://registry-1.docker.io"]
|
||||
onDemand: true
|
||||
tlsVerify: true
|
||||
content:
|
||||
- prefix: "library/**"
|
||||
destination: "/docker.io/library"
|
||||
- prefix: "democraticcsi/**"
|
||||
destination: "/democraticcsi"
|
||||
- prefix: "**"
|
||||
destination: "/docker.io"
|
||||
|
||||
- urls: ["https://registry.k8s.io"]
|
||||
onDemand: true
|
||||
tlsVerify: true
|
||||
content:
|
||||
- prefix: "**"
|
||||
destination: "/registry.k8s.io"
|
||||
- urls: ["https://ghcr.io"]
|
||||
onDemand: true
|
||||
tlsVerify: true
|
||||
content:
|
||||
- prefix: "**"
|
||||
destination: "/ghcr.io"
|
||||
- urls: ["https://quay.io"]
|
||||
onDemand: true
|
||||
tlsVerify: true
|
||||
content:
|
||||
- prefix: "**"
|
||||
destination: "/quay.io"
|
||||
12
vms-home/docker-30/zot/docker-compose.yaml
Normal file
12
vms-home/docker-30/zot/docker-compose.yaml
Normal file
@@ -0,0 +1,12 @@
|
||||
services:
|
||||
zot:
|
||||
image: ghcr.io/project-zot/zot-linux-amd64:latest
|
||||
container_name: zot
|
||||
restart: unless-stopped
|
||||
command: serve /etc/zot/config.yaml
|
||||
ports:
|
||||
- "5000:5000"
|
||||
volumes:
|
||||
- ./config.yaml:/etc/zot/config.yaml:ro
|
||||
- ./sync-credentials.json:/etc/zot/sync-credentials.json:ro
|
||||
- /srv/container-registry-data:/var/lib/zot
|
||||
Reference in New Issue
Block a user