commit 85bcc8f88d26cf2d139a3d9f840cbc2c60623c80 Author: Elmar Kresse Date: Tue Jun 17 15:56:56 2025 +0200 Initial commit diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..edb25b0 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,66 @@ +services: + overleaf: + restart: always + image: overleafcep/sharelatex:5.5.1-ext-v3 + container_name: overleaf + depends_on: + mongo: + condition: service_healthy + redis: + condition: service_started + ports: + - 80:80 + links: + - mongo + - redis + stop_grace_period: 60s + volumes: + - ./overleaf/overleaf_data:/var/lib/overleaf + environment: + OVERLEAF_APP_NAME: Overleaf FSR-IM + OVERLEAF_SITE_LANGUAGE: de + OVERLEAF_MONGO_URL: mongodb://mongo/overleaf + OVERLEAF_REDIS_HOST: redis + REDIS_HOST: redis + ENABLED_LINKED_FILE_TYPES: 'project_file,project_output_file' + ENABLE_CONVERSIONS: 'true' + EMAIL_CONFIRMATION_DISABLED: 'true' + TEXMFVAR: /var/lib/overleaf/tmp/texmf-var + OVERLEAF_SITE_URL: https://overleaf.fsr.imn.htwk-leipzig.de + OVERLEAF_NAV_TITLE: Overleaf FSR-IM + OVERLEAF_ADMIN_EMAIL: fsrim@htwk-leipzig.de + OVERLEAF_LEFT_FOOTER: '[{"text": "© Overleaf 2025 Powered by FSR-IM"} ]' + OVERLEAF_RIGHT_FOOTER: '[{"text": "Gitlab"} ]' + redis: + restart: always + image: redis:6.2 + container_name: redis + expose: + - 6379 + volumes: + - ./overleaf/redis_data:/data + + mongo: + image: mongo:7.0 + container_name: mongo + hostname: mongo + command: '--replSet overleaf' + environment: + MONGO_INITDB_DATABASE: overleaf + volumes: + - ./mongodb-init.js:/docker-entrypoint-initdb.d/mongo-init.js:ro + - mongodb-data:/data/db/ + ports: + - "27017:27017" + extra_hosts: + - mongo:127.0.0.1 + healthcheck: + test: echo 'db.stats().ok' | mongosh localhost:27017/test --quiet + interval: 10s + timeout: 10s + retries: 5 + +volumes: + mongodb-data: + driver: local + name: mongo-data diff --git a/mongodb-init.js b/mongodb-init.js new file mode 100644 index 0000000..bfa521d --- /dev/null +++ b/mongodb-init.js @@ -0,0 +1,3 @@ +/* eslint-disable no-undef */ + +rs.initiate({ _id: 'overleaf', members: [{ _id: 0, host: 'mongo:27017' }] }) \ No newline at end of file diff --git a/overleaf-helm-chart/Chart.yaml b/overleaf-helm-chart/Chart.yaml new file mode 100644 index 0000000..9763e30 --- /dev/null +++ b/overleaf-helm-chart/Chart.yaml @@ -0,0 +1,17 @@ +apiVersion: v2 +name: overleaf +version: 0.1.0 +description: A Helm chart for deploying Overleaf on Kubernetes +maintainers: + - name: Elmar Kresse + email: elmar.kresse@stud.htwk-leipzig.de +keywords: + - overleaf + - latex + - collaboration + - helm + - kubernetes +home: https://www.overleaf.com +sources: + - https://github.com/overleaf/overleaf +icon: https://www.overleaf.com/assets/images/logo.png \ No newline at end of file diff --git a/overleaf-helm-chart/README.md b/overleaf-helm-chart/README.md new file mode 100644 index 0000000..ab1f6a6 --- /dev/null +++ b/overleaf-helm-chart/README.md @@ -0,0 +1,73 @@ +# Overleaf Helm Chart + +This Helm chart deploys Overleaf on a Kubernetes cluster using Traefik for ingress and cert-manager for SSL certificate management. It also utilizes CSI CephFS for persistent storage. + +## Prerequisites + +- Kubernetes cluster +- Helm 3.x +- Traefik installed in the cluster +- Cert-manager installed in the cluster +- CSI CephFS storage class configured + +## Installation + +To install the Overleaf Helm chart, follow these steps: + +1. **Clone the repository:** + + ```bash + git clone + cd overleaf-helm-chart + ``` + +2. **Update the dependencies (if any):** + + ```bash + helm dependency update + ``` + +3. **Install the chart:** + + ```bash + helm install overleaf ./overleaf-helm-chart + ``` + + You can customize the installation by providing your own `values.yaml` file: + + ```bash + helm install overleaf ./overleaf-helm-chart -f custom-values.yaml + ``` + +## Configuration + +The following configuration options are available in `values.yaml`: + +- `image.repository`: The Docker image repository for Overleaf. +- `image.tag`: The Docker image tag for Overleaf. +- `mongo.storage.size`: The size of the persistent volume for MongoDB. +- `redis.storage.size`: The size of the persistent volume for Redis. +- `overleaf.storage.size`: The size of the persistent volume for Overleaf data. +- `ingress.enabled`: Enable or disable ingress. +- `ingress.hosts`: The hostnames for the ingress resource. +- `certManager.enabled`: Enable or disable cert-manager integration. + +## Usage + +After installation, you can access Overleaf through the configured ingress hostname. Make sure that your DNS is set up to point to the Traefik ingress controller. + +## Uninstallation + +To uninstall the Overleaf Helm chart, run: + +```bash +helm uninstall overleaf +``` + +## Contributing + +Contributions are welcome! Please submit a pull request or open an issue for any enhancements or bug fixes. + +## License + +This project is licensed under the MIT License. See the LICENSE file for details. \ No newline at end of file diff --git a/overleaf-helm-chart/charts b/overleaf-helm-chart/charts new file mode 100644 index 0000000..154d76e --- /dev/null +++ b/overleaf-helm-chart/charts @@ -0,0 +1 @@ +# This directory is for any dependent charts that your Helm chart may require. It can be empty if there are no dependencies. \ No newline at end of file diff --git a/overleaf-helm-chart/templates/deployment-mongo.yaml b/overleaf-helm-chart/templates/deployment-mongo.yaml new file mode 100644 index 0000000..2e0ad94 --- /dev/null +++ b/overleaf-helm-chart/templates/deployment-mongo.yaml @@ -0,0 +1,49 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: mongo +spec: + replicas: 1 + selector: + matchLabels: + app: mongo + template: + metadata: + labels: + app: mongo + spec: + securityContext: + runAsUser: 1001 + fsGroup: 0 + containers: + - name: mongo + image: {{ .Values.mongo.image }} + ports: + - containerPort: {{ .Values.mongo.port }} + env: + - name: MONGODB_REPLICA_SET_MODE + value: primary + - name: MONGODB_REPLICA_SET_NAME + value: {{ .Values.mongo.replSet }} + - name: MONGODB_ROOT_USER + value: {{ .Values.mongo.rootUser | quote }} + - name: MONGODB_ROOT_PASSWORD + value: {{ .Values.mongo.rootPassword | quote }} + - name: MONGODB_DATABASE + value: {{ .Values.mongo.initDb | quote }} + - name: MONGODB_REPLICA_SET_KEY + value: {{ .Values.mongo.replSetKey | quote }} + volumeMounts: + - name: mongo-data + mountPath: {{ .Values.mongo.volumeMounts.db }} + resources: + requests: + cpu: {{ .Values.resources.mongo.requests.cpu }} + memory: {{ .Values.resources.mongo.requests.memory }} + limits: + cpu: {{ .Values.resources.mongo.limits.cpu }} + memory: {{ .Values.resources.mongo.limits.memory }} + volumes: + - name: mongo-data + persistentVolumeClaim: + claimName: {{ .Values.persistence.mongoData }} \ No newline at end of file diff --git a/overleaf-helm-chart/templates/deployment-redis.yaml b/overleaf-helm-chart/templates/deployment-redis.yaml new file mode 100644 index 0000000..86a1ef2 --- /dev/null +++ b/overleaf-helm-chart/templates/deployment-redis.yaml @@ -0,0 +1,33 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: redis +spec: + replicas: 1 + selector: + matchLabels: + app: redis + template: + metadata: + labels: + app: redis + spec: + containers: + - name: redis + image: {{ .Values.redis.image }} + ports: + - containerPort: {{ .Values.redis.port }} + volumeMounts: + - name: redis-data + mountPath: {{ .Values.redis.volumeMount }} + resources: + requests: + cpu: {{ .Values.resources.redis.requests.cpu }} + memory: {{ .Values.resources.redis.requests.memory }} + limits: + cpu: {{ .Values.resources.redis.limits.cpu }} + memory: {{ .Values.resources.redis.limits.memory }} + volumes: + - name: redis-data + persistentVolumeClaim: + claimName: {{ .Values.persistence.redisData }} diff --git a/overleaf-helm-chart/templates/deployment-sharelatex.yaml b/overleaf-helm-chart/templates/deployment-sharelatex.yaml new file mode 100644 index 0000000..ed1115b --- /dev/null +++ b/overleaf-helm-chart/templates/deployment-sharelatex.yaml @@ -0,0 +1,62 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: overleaf +spec: + replicas: 1 + selector: + matchLabels: + app: overleaf + template: + metadata: + labels: + app: overleaf + spec: + containers: + - name: overleaf + image: {{ .Values.overleaf.image }} + ports: + - containerPort: {{ .Values.overleaf.port }} + env: + - name: OVERLEAF_APP_NAME + value: {{ .Values.overleaf.appName | quote }} + - name: OVERLEAF_SITE_LANGUAGE + value: {{ .Values.overleaf.siteLanguage | quote }} + - name: OVERLEAF_MONGO_URL + value: 'mongodb://{{ .Values.mongo.rootUser }}:{{ .Values.mongo.rootPassword }}@mongo:27017/{{ .Values.mongo.initDb }}?replicaSet={{ .Values.mongo.replSet }}' + - name: OVERLEAF_REDIS_HOST + value: redis + - name: REDIS_HOST + value: redis + - name: ENABLED_LINKED_FILE_TYPES + value: project_file,project_output_file + - name: ENABLE_CONVERSIONS + value: {{ .Values.overleaf.enableConversions | quote }} + - name: EMAIL_CONFIRMATION_DISABLED + value: {{ .Values.overleaf.emailConfirmationDisabled | quote }} + - name: TEXMFVAR + value: {{ .Values.overleaf.texmfvar | quote }} + - name: OVERLEAF_SITE_URL + value: {{ .Values.overleaf.siteUrl | quote }} + - name: OVERLEAF_NAV_TITLE + value: {{ .Values.overleaf.navTitle | quote }} + - name: OVERLEAF_ADMIN_EMAIL + value: {{ .Values.overleaf.adminEmail | quote }} + - name: OVERLEAF_LEFT_FOOTER + value: {{ .Values.overleaf.leftFooter | quote }} + - name: OVERLEAF_RIGHT_FOOTER + value: {{ .Values.overleaf.rightFooter | quote }} + volumeMounts: + - name: overleaf-data + mountPath: {{ .Values.overleaf.volumeMount }} + resources: + requests: + cpu: {{ .Values.resources.overleaf.requests.cpu }} + memory: {{ .Values.resources.overleaf.requests.memory }} + limits: + cpu: {{ .Values.resources.overleaf.limits.cpu }} + memory: {{ .Values.resources.overleaf.limits.memory }} + volumes: + - name: overleaf-data + persistentVolumeClaim: + claimName: {{ .Values.persistence.overleafData }} diff --git a/overleaf-helm-chart/templates/ingress.yaml b/overleaf-helm-chart/templates/ingress.yaml new file mode 100644 index 0000000..ef95100 --- /dev/null +++ b/overleaf-helm-chart/templates/ingress.yaml @@ -0,0 +1,27 @@ +{{- if .Values.ingress.enabled }} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: overleaf-ingress + annotations: + kubernetes.io/ingress.class: "traefik" + cert-manager.io/cluster-issuer: "{{ .Values.ingress.certManagerIssuer }}" + # Traefik spezifisch: Enable HTTPS redirect (optional) + traefik.ingress.kubernetes.io/redirect-entry-point: websecure +spec: + tls: + - hosts: + - {{ .Values.ingress.host | quote }} + secretName: {{ .Values.ingress.tlsSecretName }} + rules: + - host: {{ .Values.ingress.host | quote }} + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: overleaf + port: + number: 80 +{{- end }} diff --git a/overleaf-helm-chart/templates/pvc.yaml b/overleaf-helm-chart/templates/pvc.yaml new file mode 100644 index 0000000..ded60e0 --- /dev/null +++ b/overleaf-helm-chart/templates/pvc.yaml @@ -0,0 +1,39 @@ +{{- if .Values.persistence.enabled }} + +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ .Values.persistence.overleafData }} +spec: + accessModes: + - ReadWriteMany + storageClassName: {{ .Values.persistence.storageClassName }} + resources: + requests: + storage: 5Gi +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ .Values.persistence.redisData }} +spec: + accessModes: + - ReadWriteMany + storageClassName: {{ .Values.persistence.storageClassName }} + resources: + requests: + storage: 2Gi +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ .Values.persistence.mongoData }} +spec: + accessModes: + - ReadWriteMany + storageClassName: {{ .Values.persistence.storageClassName }} + resources: + requests: + storage: 5Gi +--- +{{- end }} diff --git a/overleaf-helm-chart/templates/service-mongo.yaml b/overleaf-helm-chart/templates/service-mongo.yaml new file mode 100644 index 0000000..f7d32b3 --- /dev/null +++ b/overleaf-helm-chart/templates/service-mongo.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: Service +metadata: + name: mongo +spec: + ports: + - port: {{ .Values.mongo.port }} + targetPort: {{ .Values.mongo.port }} + selector: + app: mongo diff --git a/overleaf-helm-chart/templates/service-redis.yaml b/overleaf-helm-chart/templates/service-redis.yaml new file mode 100644 index 0000000..07027cb --- /dev/null +++ b/overleaf-helm-chart/templates/service-redis.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: Service +metadata: + name: redis +spec: + ports: + - port: {{ .Values.redis.port }} + targetPort: {{ .Values.redis.port }} + selector: + app: redis diff --git a/overleaf-helm-chart/templates/service-sharelatex.yaml b/overleaf-helm-chart/templates/service-sharelatex.yaml new file mode 100644 index 0000000..7ce9bb2 --- /dev/null +++ b/overleaf-helm-chart/templates/service-sharelatex.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: Service +metadata: + name: overleaf +spec: + type: ClusterIP + ports: + - port: 80 + targetPort: {{ .Values.overleaf.port }} + selector: + app: overleaf diff --git a/overleaf-helm-chart/values.yaml b/overleaf-helm-chart/values.yaml new file mode 100644 index 0000000..0bb9338 --- /dev/null +++ b/overleaf-helm-chart/values.yaml @@ -0,0 +1,68 @@ +overleaf: + image: overleafcep/sharelatex:5.5.1-ext-v3 + appName: "Overleaf FSR-IM" + siteLanguage: "de" + siteUrl: "https://overleaf.fsr.imn.htwk-leipzig.de" + navTitle: "Overleaf FSR-IM" + adminEmail: "fsrim@htwk-leipzig.de" + leftFooter: '[{"text": "© Overleaf 2025 Powered by FSR-IM"} ]' + rightFooter: '[{"text": "Gitlab"} ]' + port: 80 + volumeMount: /var/lib/overleaf + enableConversions: "true" + emailConfirmationDisabled: "true" + texmfvar: /var/lib/overleaf/tmp/texmf-var + +redis: + image: redis:6.2 + port: 6379 + volumeMount: /data + +mongo: + image: mongo:7.0 + port: 27017 + replSet: overleaf + initDb: overleaf + volumeMounts: + db: /data/db + rootUser: root + rootPassword: 45fg2465g3645tgg563456 + replSetKey: "543gv0h3v8z7t6i39v87ztv35v" + +persistence: + enabled: true + overleafData: overleaf-data + redisData: redis-data + mongoData: mongo-data + storageClassName: csi-cephfs-sc + +resources: + overleaf: + limits: + cpu: "1000m" + memory: "8Gi" + requests: + cpu: "800m" + memory: "2Gi" + + redis: + limits: + cpu: "1000m" + memory: "4Gi" + requests: + cpu: "800m" + memory: "2Gi" + + mongo: + limits: + cpu: "1000m" + memory: "4Gi" + requests: + cpu: "800m" + memory: "2Gi" + +ingress: + enabled: true + host: "overleaf.fsr.imn.htwk-leipzig.de" + certManagerIssuer: "letsencrypt-prod" # ClusterIssuer Name, anpassen falls anders + tlsSecretName: "overleaf-tls"