Ever wanted to have scalability and deploy TanTan chat on a kubernetes cluter with probably higher uptime than the actual models that the backend interacts with on OpenRouter for some reason??? Deploy on Kubernetes!!11!11!1!11!1!!!
This repository contains Kubernetes manifests for deploying TanTan chat with using GitOps principles and ArgoCD.
There's a vibe coded untested setup.sh script in this repo that'll probably work
Image source: xkcd: Machine Learning
- from the frontend guy: akshually just make vershell do it
The application consists of the following service definitions:
- Frontend: TanTan chat UI
- Backend: TanTan chat API server (built with Hono + BetterAuth + Drizzle ORM)
- Database: PostgreSQL
- Cache, streaming: Redis
- Storage: Persistent volumes for file uploads, PostgreSQL, and Redis
- Ingress: NGINX ingress controller with TLS
- Kubernetes cluster
- ArgoCD installed and configured (we are lazy clickOps admins)
- NGINX Ingress Controller
- cert-manager (for TLS certificate provisioning)
- kubectl configured to access your cluster
This repository contains kubernetes manifests and configurations for deploying the application. You'll need to fork the other repository in order to be able to have CI.
- Fork this repository to your GitHub account
- Clone your forked repository:
git clone https://github.com/YOUR_USERNAME/YOUR_GITOPS_REPO.git
cd YOUR_GITOPS_REPOUpdate the ArgoCD application manifest:
# Edit argocd/application.yaml
# Replace YOUR_USERNAME and YOUR_GITOPS_REPO with your valuesBefore deploying, you need to update the secret values:
Replace the placeholder values with base64-encoded secrets (or create them using kubectl on your cluster):
NOTE: ECHO APPENDS A NEWLINE CHARACTER AT THE END BY DEFAULT, DON'T BE LIKE ME AND SPEND HOURS DEBUGGING π - Pablonara
# Generate base64 encoded values for your secrets
echo -n "your_postgres_password" | base64
echo -n "your_redis_password" | base64
echo -n "your_better_auth_secret" | base64
echo -n "your_discord_client_id" | base64
echo -n "your_discord_client_secret" | base64Update with your GitHub credentials:
- Replace
YOUR_GITHUB_USERNAMEwith your GitHub username - Replace
YOUR_GITHUB_TOKENwith your GitHub Personal Access Token
Alternatively, create the secret using kubectl:
kubectl create secret docker-registry ghcr-io-secret \
--docker-server=ghcr.io \
--docker-username=YOUR_GITHUB_USERNAME \
--docker-password=YOUR_GITHUB_TOKEN \
--namespace=t3-cloneathonYou can adjust the number of replicas for the backend and frontend deployments in their respective manifest files
Consider using Postgres and Redis operators and verify Redis setup for clustered deployments
The example uses local storage for persistient volumes, under the assumption you have some sort of CEPH/glusterFS/DRBD/similar or NFS backed storage infrastructure. If you are deploying on a cloud provider and not bare metal (e.g. AWS), they likely have their own storage classes (e.g.) you can use. You should consult the provider's documentation.
Update the image references in:
manifests/backend/deployment.yamlmanifests/frontend/deployment.yaml
Replace YOUR_USERNAME with your GitHub username. The default images point to ghcr.io/YOUR_USERNAME/t3-cloneathon/backend:latest and ghcr.io/YOUR_USERNAME/t3-cloneathon/frontend:latest.
Review and update the manifests/kustomization.yaml file to ensure all the resources you want to deploy are included. The kustomization file controls which manifests are applied to your cluster.
By default, all necessary resources are included, but you may want to:
- Add or remove specific resources based on your needs
- Modify the namespace if you want to use a different one
- Add any additional configurations or patches
# Review the kustomization file
cat manifests/kustomization.yaml
# Test the kustomization builds correctly
kubectl kustomize manifests/Update your domain name in:
manifests/configmap/configmap.yaml(BETTER_AUTH_URL)manifests/backend/deployment.yaml(FRONTEND_URL)manifests/ingress/ingress.yaml(host and TLS)
- Apply the ArgoCD application (UI or CLI):
kubectl apply -f argocd/application.yaml- Sync the application in ArgoCD UI or CLI:
argocd app sync t3-cloneathonβββ README.md
βββ argocd/
β βββ application.yaml # ArgoCD application definition
βββ manifests/
βββ kustomization.yaml # Kustomize configuration
βββ backend/
β βββ deployment.yaml # Backend deployment, service, and PVC
βββ configmap/
β βββ configmap.yaml # Application configuration
βββ frontend/
β βββ deployment.yaml # Frontend deployment and service
βββ ingress/
β βββ ingress.yaml # Ingress configuration
βββ namespace/
β βββ namespace.yaml # Namespace definition
βββ postgres/
β βββ postgres.yaml # PostgreSQL deployment and service
βββ redis/
β βββ redis.yaml # Redis deployment
β βββ redis-service.yml # Redis service
βββ secret/
β βββ image-pull-secret.yaml # Docker registry secret
β βββ secret.yaml # Application secrets
βββ storage/
βββ persistent-volumes.yaml # Persistent volumes
βββ storageclass.yaml # Storage class definition
The application uses the following environment variables configured via ConfigMap and Secrets:
ConfigMap (app-config):
NODE_ENV: Application environment (production)POSTGRES_DB: Database namePOSTGRES_USER: Database userPOSTGRES_PORT: Database portREDIS_HOST: Redis hostREDIS_PORT: Redis portREDIS_URL: Full Redis connection URLSERVER_PORT: Backend server portLOCAL_FILE_STORE_PATH: File storage pathBETTER_AUTH_URL: Authentication service URL
Secrets (app-secrets):
POSTGRES_PASSWORD: Database passwordREDIS_PASSWORD: Redis password(optional)Kubernetes won't allow empty secrets AFAIKBETTER_AUTH_SECRET: Authentication secret keyDISCORD_CLIENT_ID: Discord OAuth client IDDISCORD_CLIENT_SECRET: Discord OAuth client secret
Storage (EDIT THE STORAGE DEFINITIONS TO AVOID HEADACHES UNLESS YOU HAVE THE EXACT SAME SETUP AS TANTAN PROD FOR SOME REASON)
The application uses persistent storage for:
- Backend uploads: 0.5Gi persistent volume for file storage
- PostgreSQL data: Database persistence
- Redis data: Cache persistence
You'll probably want a loadbalancer for HA. Here are the default internal ports used by the services:
- Ingress: NGINX Ingress Controller with TLS termination bound to the domain specified in the ConfigMap.
- Frontend: Internally bound on port 80
- Backend: Internally bound on port 3001
- Database: Internal service on port 5432
- Redis: Internal service on port 6379
