feat(wiki): git-storage sync to Gitea (ADR-0015)
Wiki.js cannot reach git.lab from the cluster, so its content syncs to Gitea
(sorb/ThreadNetWiki) over HTTPS with a dedicated deploy PAT; a CI job canonizes
Gitea->git.lab (TURN-rotation pattern). The config job's ensure_git_storage
configures the git storage target (mode sync, config values {v:...}-encoded like
the auth strategy). Repo/user/branch/author are plain env; only the PAT lives in
the SOPS secret wikijs-git-secret, wired optional so the job still runs without it.
This commit is contained in:
@@ -57,6 +57,7 @@ resources:
|
|||||||
- wikijs-postgres-secret.yaml # SOPS, von sorb angelegt
|
- wikijs-postgres-secret.yaml # SOPS, von sorb angelegt
|
||||||
- wikijs-admin-secret.yaml # SOPS, randomisiert — Bootstrap durch den Konfig-Job
|
- wikijs-admin-secret.yaml # SOPS, randomisiert — Bootstrap durch den Konfig-Job
|
||||||
- wikijs-oidc-secret.yaml # SOPS, client_id/secret für die OIDC-Strategy
|
- wikijs-oidc-secret.yaml # SOPS, client_id/secret für die OIDC-Strategy
|
||||||
|
- wikijs-git-secret.yaml # SOPS, Git-Storage-PAT nach Gitea (ADR-0015)
|
||||||
- wikijs-postgres.yaml
|
- wikijs-postgres.yaml
|
||||||
- wikijs.yaml
|
- wikijs.yaml
|
||||||
- wiki-ingress.yaml
|
- wiki-ingress.yaml
|
||||||
|
|||||||
@@ -202,6 +202,38 @@ def ensure_theming(jwt: str):
|
|||||||
log("Theming gesetzt (Dark-Default, Logo + Login-Hintergrund aus gemounteten Assets)")
|
log("Theming gesetzt (Dark-Default, Logo + Login-Hintergrund aus gemounteten Assets)")
|
||||||
|
|
||||||
|
|
||||||
|
def ensure_git_storage(jwt: str):
|
||||||
|
# Git-Storage: Wiki.js-Inhalt nach Gitea syncen (ADR-0015). Der Cluster erreicht
|
||||||
|
# git.lab nicht -> Gitea ist das Ziel, ein CI-Job kanonisiert Gitea->git.lab.
|
||||||
|
# Nur der PAT (GIT_STORAGE_TOKEN) ist ein Secret; Repo/User/Branch sind Klartext.
|
||||||
|
# Fehlt der Token, wird der Schritt übersprungen -> der Job bleibt lauffähig, bevor
|
||||||
|
# der Storage eingerichtet ist. Config-Werte brauchen die {"v":…}-Kodierung.
|
||||||
|
token = os.environ.get("GIT_STORAGE_TOKEN", "").strip()
|
||||||
|
repo = os.environ.get("GIT_STORAGE_REPO", "").strip()
|
||||||
|
user = os.environ.get("GIT_STORAGE_USER", "").strip()
|
||||||
|
if not (token and repo and user):
|
||||||
|
log("Git-Storage übersprungen (GIT_STORAGE_TOKEN/REPO/USER nicht gesetzt)")
|
||||||
|
return
|
||||||
|
cfg = {
|
||||||
|
"authType": "basic", "repoUrl": repo,
|
||||||
|
"branch": os.environ.get("GIT_STORAGE_BRANCH", "main"),
|
||||||
|
"basicUsername": user, "basicPassword": token, "verifySSL": True,
|
||||||
|
"defaultEmail": os.environ.get("GIT_STORAGE_EMAIL", "wiki@localhost"),
|
||||||
|
"defaultName": os.environ.get("GIT_STORAGE_NAME", "Wiki"),
|
||||||
|
"sshPrivateKeyMode": "path", "localRepoPath": "./data/repo",
|
||||||
|
"alwaysNamespace": False, "gitBinaryPath": "",
|
||||||
|
}
|
||||||
|
config = [{"key": k, "value": json.dumps({"v": v})} for k, v in cfg.items()]
|
||||||
|
target = {"isEnabled": True, "key": "git", "mode": "sync",
|
||||||
|
"syncInterval": "PT5M", "config": config}
|
||||||
|
r = gql('mutation($t:[StorageTargetInput]!){storage{updateTargets(targets:$t)'
|
||||||
|
'{responseResult{succeeded message}}}}',
|
||||||
|
jwt, {"t": [target]})["storage"]["updateTargets"]["responseResult"]
|
||||||
|
if not r["succeeded"]:
|
||||||
|
sys.exit(f"Git-Storage fehlgeschlagen: {r['message']}")
|
||||||
|
log(f"Git-Storage aktiviert (Gitea, sync): {repo}")
|
||||||
|
|
||||||
|
|
||||||
def group_id(jwt: str, name: str):
|
def group_id(jwt: str, name: str):
|
||||||
for g in gql("{groups{list{id name}}}", jwt)["groups"]["list"]:
|
for g in gql("{groups{list{id name}}}", jwt)["groups"]["list"]:
|
||||||
if g["name"] == name:
|
if g["name"] == name:
|
||||||
@@ -248,6 +280,7 @@ def main():
|
|||||||
ensure_oidc(jwt)
|
ensure_oidc(jwt)
|
||||||
set_hide_local(jwt)
|
set_hide_local(jwt)
|
||||||
ensure_theming(jwt)
|
ensure_theming(jwt)
|
||||||
|
ensure_git_storage(jwt)
|
||||||
log("fertig — Wiki.js konfiguriert")
|
log("fertig — Wiki.js konfiguriert")
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -45,6 +45,25 @@ spec:
|
|||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: wikijs-oidc-secret
|
name: wikijs-oidc-secret
|
||||||
key: client_secret
|
key: client_secret
|
||||||
|
# Git-Storage (ADR-0015): Inhalt nach Gitea syncen. Klartext-Koordinaten;
|
||||||
|
# nur der PAT liegt im SOPS-Secret wikijs-git-secret. optional=true, damit
|
||||||
|
# der Job auch läuft, bevor das Secret existiert (Skript überspringt dann).
|
||||||
|
- name: GIT_STORAGE_REPO
|
||||||
|
value: https://rohana.axion1337.de/sorb/ThreadNetWiki.git
|
||||||
|
- name: GIT_STORAGE_USER
|
||||||
|
value: sorb
|
||||||
|
- name: GIT_STORAGE_BRANCH
|
||||||
|
value: main
|
||||||
|
- name: GIT_STORAGE_EMAIL
|
||||||
|
value: wiki@axion1337.chat
|
||||||
|
- name: GIT_STORAGE_NAME
|
||||||
|
value: ThreadNet Wiki
|
||||||
|
- name: GIT_STORAGE_TOKEN
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: wikijs-git-secret
|
||||||
|
key: token
|
||||||
|
optional: true
|
||||||
volumeMounts:
|
volumeMounts:
|
||||||
- name: script
|
- name: script
|
||||||
mountPath: /script
|
mountPath: /script
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
data:
|
||||||
|
token: ENC[AES256_GCM,data:Z+oD7NDgHTTuMyNLFY+2PhZmTJzN4eIAGgmCx2TnI73BQ2v40Um/ppioLY4kyow56lfj23jpI6w=,iv:/Y7Oti9e7+Se4DjxI1nT4J0f+l73PKNbgbeSiyIpdU8=,tag:ilW/M/uSTn8qOUcUfOhtwA==,type:str]
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: wikijs-git-secret
|
||||||
|
namespace: matrix
|
||||||
|
sops:
|
||||||
|
age:
|
||||||
|
- enc: |
|
||||||
|
-----BEGIN AGE ENCRYPTED FILE-----
|
||||||
|
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB4c3pFV3gxeEgrVjkzVnZ3
|
||||||
|
TkZHbThJV0dqY3BXanhtMExzUTV3aTdXTlVVCjQxZjN2cjRiMjQzTG1XM3JyVzZt
|
||||||
|
Si9GL1ZEVFArd2FxR3ltaDJhS21GeFkKLS0tIHhKVUtKaUlFOGRkOGJNUkR0Ymwy
|
||||||
|
dzREc0lNMlowMXdNa1I3ODhsN2k4WUkKFRTpU/cQq0+EcIldJn3/77P6HYaxH0uK
|
||||||
|
Xd6CT+WdX83vcmwX4d1Brh6y3GEX+cKeNAaxUL4raZdkjCOz0n8bnQ==
|
||||||
|
-----END AGE ENCRYPTED FILE-----
|
||||||
|
recipient: age14l0hwfqylwpemz5y2ghh2yxk0phszlnj3qlejhue0fw0kz3tmfgqdsjzdh
|
||||||
|
encrypted_regex: ^(data|stringData)$
|
||||||
|
lastmodified: "2026-08-13T09:46:49Z"
|
||||||
|
mac: ENC[AES256_GCM,data:STpYfsCDwZA1OIZLfTrO3Ww6Nuo8h/lIufrnQj8yeeuYcT1vEev0Tr/c2+8fNRW4yLEfRkqNMhP4p6akh9G2BChQN4FnwuUqb9yA7s+una83IXmn4UOCvwchxhY2c95lLKMNr45f3fUx6bw4tlENRor3ZrF3+jvvbX7b6c1XlC8=,iv:LVZdHBWSbwUgc4/JQSbw6twIVsa6QdSzAW7LnQn81I0=,tag:tTfFxm1URN1U1bbOroKHUA==,type:str]
|
||||||
|
version: 3.13.3
|
||||||
Reference in New Issue
Block a user