Compare commits
2
Commits
f59fb476b8
...
920693df1b
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
920693df1b | ||
|
|
dfd5f8dd2d |
@@ -0,0 +1,127 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: paperless-ai-data
|
||||||
|
namespace: paperless
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
storageClassName: longhorn
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 2Gi
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: paperless-ai
|
||||||
|
namespace: paperless
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: paperless-ai
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app.kubernetes.io/name: paperless-ai
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: paperless-ai
|
||||||
|
spec:
|
||||||
|
tolerations:
|
||||||
|
- key: node-role.kubernetes.io/control-plane
|
||||||
|
operator: Exists
|
||||||
|
effect: NoSchedule
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
- name: paperless-ai-data
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: paperless-ai-data
|
||||||
|
|
||||||
|
initContainers:
|
||||||
|
- name: fetch-llm-token
|
||||||
|
image: curlimages/curl:8.12.0
|
||||||
|
command:
|
||||||
|
- sh
|
||||||
|
- -c
|
||||||
|
- |
|
||||||
|
set -e
|
||||||
|
echo "[init] Fetching JWT token from Authentik for paperless-ai-agent..."
|
||||||
|
|
||||||
|
# Get JWT token via client_credentials grant
|
||||||
|
TOKEN_RESPONSE=$(curl -s -X POST https://authentik.riotpiao.com/application/o/token/ \
|
||||||
|
-d "grant_type=client_credentials" \
|
||||||
|
-d "client_id=paperless-ai-agent" \
|
||||||
|
-d "client_secret=29skAhE0tBzWn0qrPvmPTQMva0joFjcCr7msDQr_VXQ" \
|
||||||
|
-d "scope=openid llm:inference" 2>/dev/null)
|
||||||
|
|
||||||
|
# Extract token
|
||||||
|
TOKEN=$(echo "$TOKEN_RESPONSE" | grep -o '"access_token":"[^"]*' | cut -d'"' -f4)
|
||||||
|
|
||||||
|
if [ -z "$TOKEN" ]; then
|
||||||
|
echo "[error] Failed to get token. Response: $TOKEN_RESPONSE"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Store token in file for main container to read
|
||||||
|
mkdir -p /data
|
||||||
|
echo "$TOKEN" > /data/llm_token.txt
|
||||||
|
echo "[init] Token fetched and stored successfully"
|
||||||
|
volumeMounts:
|
||||||
|
- name: paperless-ai-data
|
||||||
|
mountPath: /data
|
||||||
|
|
||||||
|
containers:
|
||||||
|
- name: paperless-ai
|
||||||
|
image: clusterzx/paperless-ai:latest
|
||||||
|
imagePullPolicy: Always
|
||||||
|
env:
|
||||||
|
# Paperless-ngx connection
|
||||||
|
- name: PAPERLESS_API_URL
|
||||||
|
value: "http://paperless.paperless.svc.cluster.local:8000"
|
||||||
|
- name: PAPERLESS_API_TOKEN
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: paperless-ai-config
|
||||||
|
key: PAPERLESS_API_TOKEN
|
||||||
|
- name: PAPERLESS_USERNAME
|
||||||
|
value: "admin"
|
||||||
|
|
||||||
|
# LLM API configuration
|
||||||
|
- name: AI_PROVIDER
|
||||||
|
value: "custom"
|
||||||
|
- name: CUSTOM_BASE_URL
|
||||||
|
value: "https://api.riotpiao.com/v1"
|
||||||
|
# Token file created by init container with JWT from Authentik
|
||||||
|
- name: CUSTOM_API_KEY_FILE
|
||||||
|
value: "/app/data/llm_token.txt"
|
||||||
|
- name: CUSTOM_MODEL
|
||||||
|
value: "qwen2.5:3b-instruct"
|
||||||
|
|
||||||
|
# Scanning behavior
|
||||||
|
- name: SCAN_INTERVAL
|
||||||
|
value: "60"
|
||||||
|
- name: PROCESS_PREDEFINED_DOCUMENTS
|
||||||
|
value: "no"
|
||||||
|
|
||||||
|
# Tagging configuration
|
||||||
|
- name: ADD_AI_TAG
|
||||||
|
value: "yes"
|
||||||
|
- name: AI_TAG_NAME
|
||||||
|
value: "ai-processed"
|
||||||
|
- name: ADD_AI_DESCRIPTIONS
|
||||||
|
value: "yes"
|
||||||
|
- name: USE_PROMPT_TAGS
|
||||||
|
value: "yes"
|
||||||
|
|
||||||
|
volumeMounts:
|
||||||
|
- name: paperless-ai-data
|
||||||
|
mountPath: /app/data
|
||||||
|
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 512Mi
|
||||||
|
limits:
|
||||||
|
cpu: "1"
|
||||||
|
memory: 2Gi
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
apiVersion: argoproj.io/v1alpha1
|
||||||
|
kind: Application
|
||||||
|
metadata:
|
||||||
|
name: poimen-toolkit
|
||||||
|
namespace: argocd
|
||||||
|
annotations:
|
||||||
|
argocd.argoproj.io/sync-wave: "7"
|
||||||
|
argocd-image-updater.argoproj.io/image-list: |
|
||||||
|
controller=ghcr.io/riotpiao-poimen/poimen-toolkit-controller
|
||||||
|
argocd-image-updater.argoproj.io/controller.update-strategy: digest
|
||||||
|
argocd-image-updater.argoproj.io/controller.allow-tags: regexp:^latest$
|
||||||
|
argocd-image-updater.argoproj.io/write-back-method: argocd
|
||||||
|
spec:
|
||||||
|
project: homelab
|
||||||
|
source:
|
||||||
|
repoURL: https://forgejo.riotpiao.com/riotpiao-poimen/poimen-toolkit.git
|
||||||
|
targetRevision: main
|
||||||
|
path: k8s
|
||||||
|
destination:
|
||||||
|
server: https://kubernetes.default.svc
|
||||||
|
namespace: poimen
|
||||||
|
syncPolicy:
|
||||||
|
automated:
|
||||||
|
prune: true
|
||||||
|
selfHeal: true
|
||||||
|
syncOptions:
|
||||||
|
- CreateNamespace=true
|
||||||
|
- ServerSideApply=true
|
||||||
|
retry:
|
||||||
|
limit: 5
|
||||||
|
backoff:
|
||||||
|
duration: 5s
|
||||||
|
factor: 2
|
||||||
|
maxDuration: 3m
|
||||||
@@ -24,6 +24,7 @@ spec:
|
|||||||
- https://forgejo.riotpiao.com/riotpiao-poimen/poimen-memory.git
|
- https://forgejo.riotpiao.com/riotpiao-poimen/poimen-memory.git
|
||||||
- https://forgejo.riotpiao.com/riotpiao-poimen/poimen-workflows.git
|
- https://forgejo.riotpiao.com/riotpiao-poimen/poimen-workflows.git
|
||||||
- https://forgejo.riotpiao.com/riotpiao-poimen/poimen-frontend.git
|
- https://forgejo.riotpiao.com/riotpiao-poimen/poimen-frontend.git
|
||||||
|
- https://forgejo.riotpiao.com/riotpiao-poimen/poimen-toolkit.git
|
||||||
- https://forgejo.riotpiao.com/rock/riotpiao.com.git
|
- https://forgejo.riotpiao.com/rock/riotpiao.com.git
|
||||||
# Public Helm chart repos referenced by k8s/argocd/apps/* and bootstrap/*
|
# Public Helm chart repos referenced by k8s/argocd/apps/* and bootstrap/*
|
||||||
- https://cloudnative-pg.github.io/charts
|
- https://cloudnative-pg.github.io/charts
|
||||||
|
|||||||
@@ -145,6 +145,7 @@ SERVICE_ACCOUNTS: Dict[str, Dict[str, Any]] = {
|
|||||||
SCOPE_MAPPINGS: Dict[str, Dict[str, str]] = {
|
SCOPE_MAPPINGS: Dict[str, Dict[str, str]] = {
|
||||||
"roles": {"expression": 'return user.attributes.get("roles", [])'},
|
"roles": {"expression": 'return user.attributes.get("roles", [])'},
|
||||||
"permissions": {"expression": 'return ["*"] if any(user.groups.filter(is_superuser=True)) else list(user.groups.values_list("name", flat=True))'},
|
"permissions": {"expression": 'return ["*"] if any(user.groups.filter(is_superuser=True)) else list(user.groups.values_list("name", flat=True))'},
|
||||||
|
"groups": {"expression": 'return {"groups": list(user.groups.values_list("name", flat=True))}'},
|
||||||
"minio_buckets": {"expression": 'return user.attributes.get("minio_buckets", [])'},
|
"minio_buckets": {"expression": 'return user.attributes.get("minio_buckets", [])'},
|
||||||
"paperless_doctypes": {"expression": 'return user.attributes.get("paperless_doctypes", [])'},
|
"paperless_doctypes": {"expression": 'return user.attributes.get("paperless_doctypes", [])'},
|
||||||
"memory_projects": {"expression": 'return user.attributes.get("memory_projects", [])'},
|
"memory_projects": {"expression": 'return user.attributes.get("memory_projects", [])'},
|
||||||
@@ -246,6 +247,25 @@ for scope_name, scope_spec in SCOPE_MAPPINGS.items():
|
|||||||
else:
|
else:
|
||||||
print(f" {scope_name}: FAILED {status} {res}")
|
print(f" {scope_name}: FAILED {status} {res}")
|
||||||
|
|
||||||
|
# Fix built-in 'openid' scope to include preferred_username (needed by Grafana, Forgejo, etc.)
|
||||||
|
# Note: sub MUST be a string, not int, for JSON compatibility with Go struct unmarshaling
|
||||||
|
if "openid" in existing_scopes:
|
||||||
|
openid_scope = existing_scopes["openid"]
|
||||||
|
openid_pk = openid_scope["pk"]
|
||||||
|
openid_expression = 'return {"sub": str(user.pk), "preferred_username": user.username}'
|
||||||
|
if openid_expression not in openid_scope.get("expression", ""):
|
||||||
|
status, res = api("PUT", f"/api/v3/propertymappings/provider/scope/{openid_pk}/", {
|
||||||
|
"name": openid_scope["name"],
|
||||||
|
"scope_name": "openid",
|
||||||
|
"expression": openid_expression,
|
||||||
|
})
|
||||||
|
if status in (200, 201):
|
||||||
|
print(f" openid: updated (sub as string + preferred_username)")
|
||||||
|
else:
|
||||||
|
print(f" openid: UPDATE FAILED {status} {res}")
|
||||||
|
else:
|
||||||
|
print(f" openid: already correct (sub as string)")
|
||||||
|
|
||||||
# ===========================================================================
|
# ===========================================================================
|
||||||
# Phase 4: Get flow UUIDs (needed for providers)
|
# Phase 4: Get flow UUIDs (needed for providers)
|
||||||
# ===========================================================================
|
# ===========================================================================
|
||||||
|
|||||||
Reference in New Issue
Block a user