[add] librephotos

This commit is contained in:
Andy Bunce 2023-01-14 17:48:03 +00:00
parent ebc53109d4
commit a23428dec3
44 changed files with 2123 additions and 0 deletions

View file

@ -0,0 +1,27 @@
# Kubernetes Installation
1. Clone this repo and change to this directory.
1. Check the values in `kustomization.yaml`, in the `images` section, to make sure they're pointing to the latest
release.
1. Consider changing the sizes of the volumes in `pvcs.yaml`.
1. Edit the hostnames in `ingress.yaml`. Consider installing [cert-manager](https://cert-manager.io/) and uncommenting
the relevant portions of `ingress.yaml`.
1. Edit the values in `config/backend.env` to suit your configuration.
1. Install these manifests to your cluster with `kubectl apply -k .`.
1. Create a secret for PostgreSQL authentication.
```
kubectl create secret generic database -n librephotos DB_PASS=$(openssl rand -hex 16) DB_USER=librephotos
```
1. Create a secret for the backend's key, admin password, and optional MapBox API key.
```
kubectl create secret generic backend -n librephotos SECRET_KEY=$key ADMIN_PASSWORD=$password MAPBOX_API_KEY=$apikey
```
Substitute values for `$key`, `$password`, and `$apikey`. Make sure you remember the `$password` so you can log in.
If you want, you can watch the Pods get ready with `kubectl get pod -n librephotos -w`. Once they're all running,
point your browser at the hostname from `ingress.yaml`, and log in as `admin`.
# Upgrading
Change the values in `kustomization.yaml`, in the `images` section, to point to the latest versions. Then just rerun
the `kubectl apply -k .` command.

View file

@ -0,0 +1,107 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend
spec:
selector:
matchLabels:
app: backend
strategy:
rollingUpdate:
maxSurge: 0
template:
metadata:
labels:
app: backend
spec:
containers:
- name: backend
image: backend-placeholder
envFrom:
- configMapRef:
name: backend
- secretRef:
name: backend
- secretRef:
name: database
securityContext:
readOnlyRootFilesystem: true
ports:
- name: backend
containerPort: 8001
volumeMounts:
- name: photos
mountPath: /data
- name: protected-media
mountPath: /protected_media
- name: logs
mountPath: /logs
- name: cache
mountPath: /root/.cache
- name: backend-tmp
mountPath: /tmp
- name: proxy
image: proxy-placeholder
securityContext:
readOnlyRootFilesystem: true
ports:
- name: proxy
containerPort: 80
volumeMounts:
- name: photos
mountPath: /data
- name: protected-media
mountPath: /protected_media
- name: nginx-cache
mountPath: /var/cache/nginx
- name: proxy-var-run
mountPath: /var/run
securityContext:
runAsUser: 65534
runAsGroup: 65534
fsGroup: 65534
volumes:
- name: photos
persistentVolumeClaim:
claimName: photos
- name: protected-media
persistentVolumeClaim:
claimName: protected
- name: logs
emptyDir: {}
- name: cache
emptyDir: {}
- name: backend-tmp
emptyDir: {}
- name: nginx-cache
emptyDir: {}
- name: proxy-var-run
emptyDir: {}
---
apiVersion: v1
kind: Service
metadata:
name: backend
spec:
selector:
app: backend
ports:
- name: http
port: 8001
targetPort: backend
---
apiVersion: v1
kind: Service
metadata:
name: proxy
spec:
selector:
app: backend
ports:
- name: http
port: 80
targetPort: proxy

View file

@ -0,0 +1,10 @@
BACKEND_HOST=backend
ADMIN_EMAIL=somebody@example.com
ADMIN_USERNAME=admin
DB_BACKEND=postgresql
DB_NAME=librephotos
DB_HOST=postgres
DB_PORT=5432
REDIS_HOST=redis
REDIS_PORT=6379
WEB_CONCURRENCY=2

View file

@ -0,0 +1,69 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: postgres
spec:
strategy:
rollingUpdate:
maxSurge: 0
selector:
matchLabels:
app: postgres
template:
metadata:
labels:
app: postgres
spec:
containers:
- name: postgres
image: postgresql-placeholder
env:
- name: PGDATA
value: /var/lib/postgresql/data/pgdata
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
key: DB_PASS
name: database
- name: POSTGRES_USER
valueFrom:
secretKeyRef:
key: DB_USER
name: database
- name: POSTGRES_DB
value: librephotos
livenessProbe:
exec:
command:
- pg_isready
- -h
- localhost
- -U
- librephotos
ports:
- containerPort: 5432
name: psql
volumeMounts:
- mountPath: /var/lib/postgresql/data
name: data
securityContext:
runAsUser: 999
runAsGroup: 999
fsGroup: 999
volumes:
- name: data
persistentVolumeClaim:
claimName: postgres
---
apiVersion: v1
kind: Service
metadata:
name: postgres
spec:
ports:
- port: 5432
name: psql
selector:
app: postgres

View file

@ -0,0 +1,38 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend
spec:
selector:
matchLabels:
app: frontend
template:
metadata:
labels:
app: frontend
spec:
containers:
- name: frontend
image: frontend-placeholder
ports:
- name: http
containerPort: 3000
securityContext:
readOnlyRootFilesystem: true
securityContext:
runAsUser: 65534
runAsGroup: 65534
fsGroup: 65534
---
apiVersion: v1
kind: Service
metadata:
name: frontend
spec:
ports:
- port: 3000
name: http
selector:
app: frontend

View file

@ -0,0 +1,44 @@
# This ingress will make your photo site available to web browsers. For this to work, you'll need an ingress controller
# already installed in your cluster: https://kubernetes.io/docs/concepts/services-networking/ingress-controllers/
# You should use TLS/SSL to protect the site. Either use cert-manager (https://cert-manager.io/) or something else.
# If TLS/SSL is available, uncomment the annotation below, and the tls section.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: photos.example.com
# annotations:
# ingress.kubernetes.io/ssl-redirect: "true"
spec:
ingressClassName: nginx
rules:
- host: photos.example.com
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: proxy
port:
name: http
# tls:
# - hosts:
# - photos.example.com
# secretName: photos.example.com
---
# If you're using cert-manager, uncomment this to request a certificate that will be used by the ingress above.
# apiVersion: cert-manager.io/v1
# kind: Certificate
# metadata:
# name: photos.example.com
# spec:
# secretName: photos.example.com
# dnsNames:
# - photos.example.com
# issuerRef:
# kind: ClusterIssuer
# name: letsencrypt

View file

@ -0,0 +1,35 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: librephotos
resources:
- backend.yaml
- db.yaml
- frontend.yaml
- ingress.yaml
- ns.yaml
- pvcs.yaml
- redis.yaml
configMapGenerator:
- name: backend
envs:
- config/backend.env
images:
- name: backend-placeholder
newName: reallibrephotos/librephotos
newTag: 2022w12
- name: frontend-placeholder
newName: reallibrephotos/librephotos-frontend
newTag: 2022w12
- name: proxy-placeholder
newName: reallibrephotos/librephotos-proxy
newTag: 2022w10
- name: postgresql-placeholder
newName: postgres
newTag: "13"
- name: redis-placeholder
newName: redis
newTag: "6"

View file

@ -0,0 +1,4 @@
apiVersion: v1
kind: Namespace
metadata:
name: librephotos

View file

@ -0,0 +1,42 @@
# This volume holds your photos.
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: photos
spec:
resources:
requests:
storage: 30Gi
volumeMode: Filesystem
accessModes:
- ReadWriteOnce
---
# This volume contains thumbnails. Setting it to 10-15% the size of "photos" is probably reasonable.
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: protected
spec:
resources:
requests:
storage: 3Gi
volumeMode: Filesystem
accessModes:
- ReadWriteOnce
---
# The postgres volume holds all the metadata. If it's 1% the size of "photos," you're probably fine.
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: postgres
spec:
resources:
requests:
storage: 1Gi
volumeMode: Filesystem
accessModes:
- ReadWriteOnce

View file

@ -0,0 +1,39 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis
spec:
selector:
matchLabels:
app: redis
strategy:
rollingUpdate:
maxSurge: 0
template:
metadata:
labels:
app: redis
spec:
containers:
- name: redis
image: redis-placeholder
ports:
- name: redis
containerPort: 6379
securityContext:
runAsUser: 999
runAsGroup: 999
fsGroup: 999
---
apiVersion: v1
kind: Service
metadata:
name: redis
spec:
ports:
- port: 6379
name: redis
selector:
app: redis