feat(ops): add k3s + ArgoCD GitOps pipeline

- Dockerfile: copy web/ and assets/ to runtime stage so ServeDir routes work
- .gitea/workflows/docker-build.yml: build/push image on master push, pin SHA
  tag back into deploy/kustomization.yaml so ArgoCD sees a real manifest change
- deploy/: Kustomize manifests — Namespace, PVC, Deployment (Recreate for
  SQLite), Service, Traefik Ingress at klondike.aleshym.co
- argocd/application.yaml: auto-sync Application watching deploy/ on Gitea

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
funman300
2026-05-13 13:53:09 -07:00
parent 079349dc0f
commit 9983b873f9
9 changed files with 223 additions and 2 deletions
+62
View File
@@ -0,0 +1,62 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: solitaire-server
namespace: solitaire
spec:
replicas: 1
selector:
matchLabels:
app: solitaire-server
# SQLite is single-writer; Recreate avoids two pods owning the PVC at once.
strategy:
type: Recreate
template:
metadata:
labels:
app: solitaire-server
spec:
imagePullSecrets:
- name: gitea-registry
containers:
- name: server
image: solitaire-server
imagePullPolicy: Always
ports:
- containerPort: 8080
env:
- name: DATABASE_URL
value: sqlite:///data/sol.db
- name: JWT_SECRET
valueFrom:
secretKeyRef:
name: solitaire-secrets
key: jwt-secret
- name: SERVER_PORT
value: "8080"
volumeMounts:
- name: db-data
mountPath: /data
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 5
periodSeconds: 30
readinessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 3
periodSeconds: 10
resources:
requests:
cpu: 50m
memory: 64Mi
limits:
cpu: 500m
memory: 256Mi
volumes:
- name: db-data
persistentVolumeClaim:
claimName: solitaire-db
+27
View File
@@ -0,0 +1,27 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: solitaire-server
namespace: solitaire
annotations:
# Remove the next two lines if you are not using cert-manager.
cert-manager.io/cluster-issuer: letsencrypt-prod
traefik.ingress.kubernetes.io/router.entrypoints: websecure
spec:
ingressClassName: traefik
rules:
- host: klondike.aleshym.co
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: solitaire-server
port:
name: http
# Remove the tls block if you are not using cert-manager.
tls:
- hosts:
- klondike.aleshym.co
secretName: solitaire-tls
+16
View File
@@ -0,0 +1,16 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- namespace.yaml
- pvc.yaml
- deployment.yaml
- service.yaml
- ingress.yaml
# CI updates this block automatically via `kustomize edit set image`.
# The image name here matches the `image: solitaire-server` stub in deployment.yaml.
images:
- name: solitaire-server
newName: git.aleshym.co/funman300/solitaire-server
newTag: latest
+4
View File
@@ -0,0 +1,4 @@
apiVersion: v1
kind: Namespace
metadata:
name: solitaire
+11
View File
@@ -0,0 +1,11 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: solitaire-db
namespace: solitaire
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
+12
View File
@@ -0,0 +1,12 @@
apiVersion: v1
kind: Service
metadata:
name: solitaire-server
namespace: solitaire
spec:
selector:
app: solitaire-server
ports:
- name: http
port: 80
targetPort: 8080