Add karakeep, migrated off CasaOS on the Orange Pi
Three containers move across as three deployments: the app, meilisearch, and
the headless-chrome renderer. Data (4.2M of SQLite + assets, 3.3M meilisearch
index) copied from /DATA/AppData/karakeep on the Orange Pi to gvolume0 at
/mnt/gvolume0/karakeep/{data,meilisearch}.
MEILI_MASTER_KEY and NEXTAUTH_SECRET are carried over unchanged, not
regenerated -- the first unlocks the existing index and the second signs
existing sessions. OPENAI_API_KEY was already empty on CasaOS, so AI tagging
was unused; the key is kept but blank.
NEXTAUTH_URL changes from http://localhost:14592 to https://keep.wittyoneoff.com
so NextAuth builds correct callback URLs behind the proxy.
chrome.yaml passes EXACTLY the args the CasaOS container used. Adding
--remote-debugging-address/--remote-debugging-port breaks it: the image's
entrypoint runs Chrome on 127.0.0.1:9223 and socat-proxies 9222 -> 9223, so
overriding those flags leaves socat retrying a dead port forever. Learned the
hard way.
App and meilisearch use strategy: Recreate -- single-writer SQLite on a
ReadWriteOnce volume, same rule as apps/tududi.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
c01d5852d4
commit
00a1742b85
@@ -0,0 +1,41 @@
|
|||||||
|
# Headless Chrome used by karakeep to render and screenshot pages.
|
||||||
|
# Stateless -- no volume, safe to restart freely.
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: karakeep-chrome
|
||||||
|
namespace: karakeep
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: karakeep-chrome
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: karakeep-chrome
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: chrome
|
||||||
|
image: ghcr.io/karakeep-app/karakeep-chrome:release
|
||||||
|
# EXACTLY the args the CasaOS container used. Do NOT add
|
||||||
|
# --remote-debugging-address/--remote-debugging-port: the image's
|
||||||
|
# entrypoint (/headless-shell/run.sh) already runs Chrome on
|
||||||
|
# 127.0.0.1:9223 and socat-proxies 9222 -> 9223. Overriding those
|
||||||
|
# flags moves Chrome off 9223 and socat then logs
|
||||||
|
# "connect 127.0.0.1:9223: Connection refused" forever.
|
||||||
|
args:
|
||||||
|
- --disable-gpu
|
||||||
|
- --disable-dev-shm-usage
|
||||||
|
- --hide-scrollbars
|
||||||
|
- --disable-blink-features=AutomationControlled
|
||||||
|
- --window-size=1440,900
|
||||||
|
ports:
|
||||||
|
- containerPort: 9222
|
||||||
|
name: cdp
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 256Mi
|
||||||
|
limits:
|
||||||
|
memory: 1Gi
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: karakeep
|
||||||
|
namespace: karakeep
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
strategy:
|
||||||
|
# single-writer SQLite (db.db, queue.db) on a ReadWriteOnce volume
|
||||||
|
type: Recreate
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: karakeep
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: karakeep
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: karakeep
|
||||||
|
image: ghcr.io/karakeep-app/karakeep:0.33.2
|
||||||
|
env:
|
||||||
|
- name: DATA_DIR
|
||||||
|
value: /data
|
||||||
|
- name: PORT
|
||||||
|
value: "3000"
|
||||||
|
- name: NODE_ENV
|
||||||
|
value: production
|
||||||
|
- name: NEXT_TELEMETRY_DISABLED
|
||||||
|
value: "1"
|
||||||
|
- name: MEILI_ADDR
|
||||||
|
value: http://karakeep-meilisearch:7700
|
||||||
|
- name: BROWSER_WEB_URL
|
||||||
|
value: http://karakeep-chrome:9222
|
||||||
|
# Was http://localhost:14592 on CasaOS; must be the public URL so
|
||||||
|
# NextAuth builds correct callback links behind the proxy.
|
||||||
|
- name: NEXTAUTH_URL
|
||||||
|
value: https://keep.wittyoneoff.com
|
||||||
|
- name: NEXTAUTH_URL_INTERNAL
|
||||||
|
value: http://localhost:3000
|
||||||
|
- name: MEILI_MASTER_KEY
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: karakeep
|
||||||
|
key: meili-master-key
|
||||||
|
- name: NEXTAUTH_SECRET
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: karakeep
|
||||||
|
key: nextauth-secret
|
||||||
|
- name: OPENAI_API_KEY
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: karakeep
|
||||||
|
key: openai-api-key
|
||||||
|
ports:
|
||||||
|
- containerPort: 3000
|
||||||
|
name: http
|
||||||
|
readinessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /
|
||||||
|
port: 3000
|
||||||
|
initialDelaySeconds: 20
|
||||||
|
periodSeconds: 10
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 256Mi
|
||||||
|
limits:
|
||||||
|
memory: 1Gi
|
||||||
|
volumeMounts:
|
||||||
|
- name: data
|
||||||
|
mountPath: /data
|
||||||
|
volumes:
|
||||||
|
- name: data
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: karakeep
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
# TLS is terminated at the AWS proxy (Cox blocks 80/443 at home), so this
|
||||||
|
# ingress is plain HTTP, same as every other app here.
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: karakeep
|
||||||
|
namespace: karakeep
|
||||||
|
spec:
|
||||||
|
ingressClassName: traefik
|
||||||
|
rules:
|
||||||
|
- host: keep.wittyoneoff.com
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- path: /
|
||||||
|
pathType: Prefix
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: karakeep
|
||||||
|
port:
|
||||||
|
number: 3000
|
||||||
|
- host: origin-keep.wittyoneoff.com
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- path: /
|
||||||
|
pathType: Prefix
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: karakeep
|
||||||
|
port:
|
||||||
|
number: 3000
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
# secret.example.yaml is intentionally NOT listed -- copy it to secret.yaml
|
||||||
|
# (gitignored), set real values, and apply it once per cluster.
|
||||||
|
resources:
|
||||||
|
- namespace.yaml
|
||||||
|
- storage.yaml
|
||||||
|
- deployment.yaml
|
||||||
|
- meilisearch.yaml
|
||||||
|
- chrome.yaml
|
||||||
|
- service.yaml
|
||||||
|
- ingress.yaml
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: karakeep-meilisearch
|
||||||
|
namespace: karakeep
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
strategy:
|
||||||
|
type: Recreate
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: karakeep-meilisearch
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: karakeep-meilisearch
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: meilisearch
|
||||||
|
image: getmeili/meilisearch:v1.41.0
|
||||||
|
env:
|
||||||
|
- name: MEILI_HTTP_ADDR
|
||||||
|
value: 0.0.0.0:7700
|
||||||
|
- name: MEILI_NO_ANALYTICS
|
||||||
|
value: "true"
|
||||||
|
- name: MEILI_MASTER_KEY
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: karakeep
|
||||||
|
key: meili-master-key
|
||||||
|
ports:
|
||||||
|
- containerPort: 7700
|
||||||
|
name: http
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 256Mi
|
||||||
|
limits:
|
||||||
|
memory: 1Gi
|
||||||
|
volumeMounts:
|
||||||
|
- name: data
|
||||||
|
mountPath: /meili_data
|
||||||
|
volumes:
|
||||||
|
- name: data
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: karakeep-meilisearch
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: karakeep
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
# Copy to secret.yaml (gitignored), set real values, apply once per cluster.
|
||||||
|
# Carried over from the CasaOS deployment -- NEXTAUTH_SECRET signs existing
|
||||||
|
# sessions and MEILI_MASTER_KEY unlocks the existing index, so these must be
|
||||||
|
# the SAME values, not fresh ones.
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: karakeep
|
||||||
|
namespace: karakeep
|
||||||
|
type: Opaque
|
||||||
|
stringData:
|
||||||
|
meili-master-key: CHANGEME
|
||||||
|
nextauth-secret: CHANGEME
|
||||||
|
openai-api-key: CHANGEME
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: karakeep
|
||||||
|
namespace: karakeep
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
selector:
|
||||||
|
app: karakeep
|
||||||
|
ports:
|
||||||
|
- port: 3000
|
||||||
|
targetPort: 3000
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: karakeep-meilisearch
|
||||||
|
namespace: karakeep
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
selector:
|
||||||
|
app: karakeep-meilisearch
|
||||||
|
ports:
|
||||||
|
- port: 7700
|
||||||
|
targetPort: 7700
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: karakeep-chrome
|
||||||
|
namespace: karakeep
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
selector:
|
||||||
|
app: karakeep-chrome
|
||||||
|
ports:
|
||||||
|
- port: 9222
|
||||||
|
targetPort: 9222
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
# Migrated off CasaOS on the Orange Pi (/DATA/AppData/karakeep) 2026-09-21.
|
||||||
|
# Two volumes because the app and meilisearch are separate pods.
|
||||||
|
# karakeep keeps SQLite (db.db, queue.db) in DATA_DIR, so both deployments use
|
||||||
|
# strategy: Recreate -- exactly the single-writer rule apps/tududi follows.
|
||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolume
|
||||||
|
metadata:
|
||||||
|
name: karakeep-pv
|
||||||
|
spec:
|
||||||
|
capacity:
|
||||||
|
storage: 10Gi
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
persistentVolumeReclaimPolicy: Retain
|
||||||
|
volumeMode: Filesystem
|
||||||
|
hostPath:
|
||||||
|
path: /mnt/gvolume0/karakeep/data
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: karakeep
|
||||||
|
namespace: karakeep
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 10Gi
|
||||||
|
storageClassName: ""
|
||||||
|
volumeName: karakeep-pv
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolume
|
||||||
|
metadata:
|
||||||
|
name: karakeep-meilisearch-pv
|
||||||
|
spec:
|
||||||
|
capacity:
|
||||||
|
storage: 5Gi
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
persistentVolumeReclaimPolicy: Retain
|
||||||
|
volumeMode: Filesystem
|
||||||
|
hostPath:
|
||||||
|
path: /mnt/gvolume0/karakeep/meilisearch
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: karakeep-meilisearch
|
||||||
|
namespace: karakeep
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 5Gi
|
||||||
|
storageClassName: ""
|
||||||
|
volumeName: karakeep-meilisearch-pv
|
||||||
@@ -11,3 +11,4 @@ resources:
|
|||||||
- apps/dashwise
|
- apps/dashwise
|
||||||
- apps/tududi
|
- apps/tududi
|
||||||
- apps/limesurvey
|
- apps/limesurvey
|
||||||
|
- apps/karakeep
|
||||||
|
|||||||
Reference in New Issue
Block a user