apiVersion: v1 kind: Namespace metadata: name: img-infinite-canvas --- apiVersion: v1 kind: Secret metadata: name: turnstile-secret namespace: img-infinite-canvas type: Opaque stringData: TURNSTILE_SECRET_KEY: 1x0000000000000000000000000000000AA --- apiVersion: v1 kind: Secret metadata: name: postgres-secret namespace: img-infinite-canvas type: Opaque stringData: POSTGRES_DB: canvas POSTGRES_USER: canvas POSTGRES_PASSWORD: canvas --- apiVersion: v1 kind: ConfigMap metadata: name: api-config namespace: img-infinite-canvas data: config.yaml: | Name: img_infinite_canvas-api Host: 0.0.0.0 Port: 8888 Timeout: 1200000 Storage: Driver: postgres DataSource: postgres://canvas:canvas@postgres:5432/canvas?sslmode=disable Cache: Driver: redis Addr: redis:6379 Password: "" DB: 0 TTLSeconds: 300 JobQueue: Driver: asynq Addr: redis:6379 Password: "" DB: 0 Queue: default Concurrency: 10 MaxRetry: 3 TimeoutSeconds: 900 ShutdownTimeoutSeconds: 30 Agent: Driver: pi Auth: Region: global RegionMode: manual TokenSecret: local-dev-change-me TokenTTLSeconds: 604800 RefreshTTLSeconds: 2592000 CodeTTLSeconds: 600 DevReturnCode: true Email: Driver: none Host: "" Port: 587 Username: "" Password: "" FromName: hello FromEmail: hello@auth.moteva.local BrandName: Moteva UseTLS: false StartTLS: true InsecureSkipVerify: false TimeoutSeconds: 10 Turnstile: Enabled: true SiteKey: 1x00000000000000000000AA SecretKey: "" SecretKeyEnv: TURNSTILE_SECRET_KEY SiteVerifyURL: https://challenges.cloudflare.com/turnstile/v0/siteverify TimeoutSeconds: 5 ObjectStorage: Driver: minio Bucket: canvas-assets Endpoint: minio:9000 Region: us-east-1 AccessKey: canvas SecretKey: canvas-secret PublicBase: http://minio:9000/canvas-assets UseSSL: false ExpiresIn: 900 --- apiVersion: apps/v1 kind: Deployment metadata: name: postgres namespace: img-infinite-canvas spec: replicas: 1 selector: matchLabels: app: postgres template: metadata: labels: app: postgres spec: containers: - name: postgres image: postgres:18-alpine envFrom: - secretRef: name: postgres-secret ports: - containerPort: 5432 --- apiVersion: v1 kind: Service metadata: name: postgres namespace: img-infinite-canvas spec: selector: app: postgres ports: - port: 5432 targetPort: 5432 --- apiVersion: apps/v1 kind: Deployment metadata: name: redis namespace: img-infinite-canvas spec: replicas: 1 selector: matchLabels: app: redis template: metadata: labels: app: redis spec: containers: - name: redis image: redis:8-alpine args: ["redis-server", "--appendonly", "yes"] ports: - containerPort: 6379 --- apiVersion: v1 kind: Service metadata: name: redis namespace: img-infinite-canvas spec: selector: app: redis ports: - port: 6379 targetPort: 6379 --- apiVersion: apps/v1 kind: Deployment metadata: name: minio namespace: img-infinite-canvas spec: replicas: 1 selector: matchLabels: app: minio template: metadata: labels: app: minio spec: containers: - name: minio image: minio/minio:RELEASE.2025-09-07T16-13-09Z args: ["server", "/data", "--console-address", ":9001"] env: - name: MINIO_ROOT_USER value: canvas - name: MINIO_ROOT_PASSWORD value: canvas-secret ports: - containerPort: 9000 - containerPort: 9001 --- apiVersion: v1 kind: Service metadata: name: minio namespace: img-infinite-canvas spec: selector: app: minio ports: - name: api port: 9000 targetPort: 9000 - name: console port: 9001 targetPort: 9001 --- apiVersion: apps/v1 kind: Deployment metadata: name: api namespace: img-infinite-canvas spec: replicas: 1 selector: matchLabels: app: api template: metadata: labels: app: api spec: containers: - name: api image: img-infinite-canvas-api:latest imagePullPolicy: IfNotPresent args: ["-f", "/app/etc/config.yaml", "-mode", "api"] ports: - containerPort: 8888 envFrom: - secretRef: name: turnstile-secret volumeMounts: - name: api-config mountPath: /app/etc/config.yaml subPath: config.yaml volumes: - name: api-config configMap: name: api-config --- apiVersion: v1 kind: Service metadata: name: api namespace: img-infinite-canvas spec: selector: app: api ports: - port: 8888 targetPort: 8888 --- apiVersion: apps/v1 kind: Deployment metadata: name: worker namespace: img-infinite-canvas spec: replicas: 1 selector: matchLabels: app: worker template: metadata: labels: app: worker spec: containers: - name: worker image: img-infinite-canvas-api:latest imagePullPolicy: IfNotPresent args: ["-f", "/app/etc/config.yaml", "-mode", "worker"] envFrom: - secretRef: name: turnstile-secret volumeMounts: - name: api-config mountPath: /app/etc/config.yaml subPath: config.yaml volumes: - name: api-config configMap: name: api-config --- apiVersion: apps/v1 kind: Deployment metadata: name: web namespace: img-infinite-canvas spec: replicas: 1 selector: matchLabels: app: web template: metadata: labels: app: web spec: containers: - name: web image: img-infinite-canvas-web:latest imagePullPolicy: IfNotPresent env: - name: NEXT_PUBLIC_API_PROXY value: http://api:8888 ports: - containerPort: 3000 --- apiVersion: v1 kind: Service metadata: name: web namespace: img-infinite-canvas spec: selector: app: web ports: - port: 80 targetPort: 3000 --- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: web namespace: img-infinite-canvas spec: rules: - host: canvas.local http: paths: - path: / pathType: Prefix backend: service: name: web port: number: 80