added produciton db

This commit is contained in:
Jun-te Kim 2025-12-28 12:58:07 +00:00
parent 63415817bc
commit 5067b604f6
7 changed files with 169 additions and 10 deletions

1
db/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
.env

View file

@ -1,5 +1,5 @@
env "stripe_invoice_dev" {
url = "postgres://${getenv("POSTGRES_USER")}:${getenv("POSTGRES_PASSWORD")}@postgres.default.svc.cluster.local:5432/stripe_invoice?sslmode=disable"
url = "postgres://${getenv("POSTGRES_USER")}:${getenv("POSTGRES_PASSWORD")}@postgres-dev.default.svc.cluster.local:5432/stripe_invoice?sslmode=disable"
migration {
dir = "file://./db/atlas/stripe_invoice/migrations"
@ -7,9 +7,11 @@ env "stripe_invoice_dev" {
}
env "stripe_invoice_prod" {
url = "postgres://${getenv("POSTGRES_USER")}:${getenv("POSTGRES_PASSWORD")}@postgres.default.svc.cluster.local:5432/stripe_invoice_prod?sslmode=disable"
url = "postgres://${getenv("POSTGRES_USER")}:${getenv("POSTGRES_PASSWORD")}@postgres-prod.default.svc.cluster.local:5432/stripe_invoice_prod?sslmode=disable"
migration {
dir = "file://./db/atlas/stripe_invoice/migrations"
}
}

View file

@ -0,0 +1,7 @@
CREATE TABLE login_tokens (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
token TEXT NOT NULL UNIQUE,
expires_at TIMESTAMPTZ NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

View file

@ -1,4 +1,5 @@
h1:R/iRQ2a7u+QeDRyEVRvl8TcvAzRjWXbjBpn4dNpyMAA=
h1:ELwFHTBDb63mdRBhmjXMMSpy05pUSVxH03zuUuHYAto=
0001_init.sql h1:gzb02ZbjrrJkXOC+2qIZsngnj7A+29O2/b4awScPlPs=
0002_auth.sql h1:4NhBu26dIBMy9gxMxM3tf6Z2CS2kfKlGjFBj07T/aBw=
0003_stripe_xero.sql h1:E2bcdUDnondsXwbdIwVlZqR4DQwzcoDiyeRFJwVxXwg=
0004_login_tokens.sql h1:rj1KcWu/0znh2YvtI7JV8Z2nwtL5rZzONbPwX1P+/PI=

View file

@ -1,9 +1,10 @@
apiVersion: batch/v1
kind: CronJob
metadata:
name: postgres-backup
name: postgres-backup-dev
namespace: default
spec:
schedule: "30 18 * * 5" # weekly on friday at 18:30
schedule: "30 18 * * 5" # weekly Friday 18:30
jobTemplate:
spec:
template:
@ -16,11 +17,47 @@ spec:
- /bin/sh
- -c
- |
pg_dump stripe_invoice \
pg_dump \
-h postgres-dev.default.svc.cluster.local \
-U $POSTGRES_USER \
stripe_invoice \
| gzip \
| aws s3 cp - s3://$S3_BUCKET/stripe_invoice/$(date +%F).sql.gz
| aws s3 cp - s3://$S3_BUCKET/dev/stripe_invoice/$(date +%F).sql.gz
envFrom:
- secretRef:
name: postgres-secret
name: postgres-secret # DEV DB creds
- secretRef:
name: aws-backup-secret
name: aws-backup-secret # shared AWS creds
---
apiVersion: batch/v1
kind: CronJob
metadata:
name: postgres-backup-prod
namespace: default
spec:
schedule: "30 01 * * *" # daily at 01:30 (recommended for prod)
jobTemplate:
spec:
template:
spec:
restartPolicy: OnFailure
containers:
- name: backup
image: postgres:16
command:
- /bin/sh
- -c
- |
pg_dump \
-h postgres-prod.default.svc.cluster.local \
-U $POSTGRES_USER \
stripe_invoice_prod \
| gzip \
| aws s3 cp - s3://$S3_BUCKET/prod/stripe_invoice/$(date +%F).sql.gz
envFrom:
- secretRef:
name: postgres-prod-secret # PROD DB creds
- secretRef:
name: aws-backup-secret # shared AWS creds

View file

@ -84,7 +84,7 @@ spec:
apiVersion: v1
kind: Service
metadata:
name: postgres
name: postgres-dev
namespace: default
spec:
type: ClusterIP

View file

@ -0,0 +1,111 @@
# --------------------------------------------------
# PersistentVolume (local disk on mist) — PROD
# --------------------------------------------------
apiVersion: v1
kind: PersistentVolume
metadata:
name: postgres-prod-pv
spec:
capacity:
storage: 20Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: local-storage
hostPath:
path: /home/kimjunte/k8s_storage/postgres/stripe_invoice_prod
---
# --------------------------------------------------
# PersistentVolumeClaim — PROD
# --------------------------------------------------
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: postgres-prod-pvc
namespace: default
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 20Gi
storageClassName: local-storage
---
# --------------------------------------------------
# PostgreSQL Secret — PROD
# (DO NOT COMMIT real values)
# --------------------------------------------------
apiVersion: v1
kind: Secret
metadata:
name: postgres-prod-secret
namespace: default
type: Opaque
stringData:
POSTGRES_USER: stripe_invoice_prod
POSTGRES_PASSWORD: productionPassword1142M@ke!tH@rd2Br3akWith$ymb0ls
POSTGRES_DB: stripe_invoice_prod
---
# --------------------------------------------------
# PostgreSQL Deployment — PROD
# --------------------------------------------------
apiVersion: apps/v1
kind: Deployment
metadata:
name: postgres-prod
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: postgres-prod
template:
metadata:
labels:
app: postgres-prod
spec:
containers:
- name: postgres
image: postgres:16
ports:
- containerPort: 5432
envFrom:
- secretRef:
name: postgres-prod-secret
volumeMounts:
- name: postgres-data
mountPath: /var/lib/postgresql/data
readinessProbe:
tcpSocket:
port: 5432
initialDelaySeconds: 10
periodSeconds: 5
livenessProbe:
tcpSocket:
port: 5432
initialDelaySeconds: 30
periodSeconds: 10
volumes:
- name: postgres-data
persistentVolumeClaim:
claimName: postgres-prod-pvc
---
# --------------------------------------------------
# PostgreSQL Service (cluster-internal only) — PROD
# --------------------------------------------------
apiVersion: v1
kind: Service
metadata:
name: postgres-prod
namespace: default
spec:
type: ClusterIP
selector:
app: postgres-prod
ports:
- port: 5432
targetPort: 5432