Merge branch 'main' into main

This commit is contained in:
Tim Gibbon
2026-06-26 22:08:06 +01:00
committed by GitHub
30 changed files with 876 additions and 149 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
version: "2.2"
services:
sharelatex:
overleaf:
ports:
- 30000:30000
- 30150:30150
+9 -9
View File
@@ -1,10 +1,10 @@
services:
sharelatex:
overleaf:
restart: always
# Server Pro users:
# image: quay.io/sharelatex/sharelatex-pro
image: sharelatex/sharelatex
container_name: sharelatex
# image: quay.io/overleaf/overleaf-pro
image: overleaf/overleaf
container_name: overleaf
depends_on:
mongo:
condition: service_healthy
@@ -14,7 +14,7 @@ services:
- 80:80
stop_grace_period: 60s
volumes:
- ~/sharelatex_data:/var/lib/overleaf
- ~/overleaf_data:/var/lib/overleaf
########################################################################
#### Server Pro: Uncomment the following line to mount the docker ####
#### socket, required for Sibling Containers to work ####
@@ -23,7 +23,7 @@ services:
environment:
OVERLEAF_APP_NAME: Overleaf Community Edition
OVERLEAF_MONGO_URL: mongodb://mongo/sharelatex
OVERLEAF_MONGO_URL: mongodb://mongo/overleaf
# Same property, unfortunately with different names in
# different locations
@@ -81,9 +81,9 @@ services:
## Sandboxed Compiles: https://docs.overleaf.com/on-premises/configuration/overleaf-toolkit/server-pro-only-configuration/sandboxed-compiles
SANDBOXED_COMPILES: "true"
### Bind-mount source for /var/lib/overleaf/data/compiles inside the container.
SANDBOXED_COMPILES_HOST_DIR_COMPILES: "/home/user/sharelatex_data/data/compiles"
SANDBOXED_COMPILES_HOST_DIR_COMPILES: "/home/user/overleaf_data/data/compiles"
### Bind-mount source for /var/lib/overleaf/data/output inside the container.
SANDBOXED_COMPILES_HOST_DIR_OUTPUT: "/home/user/sharelatex_data/data/output"
SANDBOXED_COMPILES_HOST_DIR_OUTPUT: "/home/user/overleaf_data/data/output"
### Backwards compatibility (before Server Pro 5.5)
DOCKER_RUNNER: "true"
SANDBOXED_COMPILES_SIBLING_CONTAINERS: "true"
@@ -113,7 +113,7 @@ services:
- ~/mongo_data:/data/db
- ./bin/shared/mongodb-init-replica-set.js:/docker-entrypoint-initdb.d/mongodb-init-replica-set.js
environment:
MONGO_INITDB_DATABASE: sharelatex
MONGO_INITDB_DATABASE: overleaf
extra_hosts:
# Required when using the automatic database setup for initializing the replica set.
# This override is not needed when running the setup after starting up mongo.
+181
View File
@@ -0,0 +1,181 @@
# Overleaf — Local Kubernetes Bootstrap
Runs Overleaf Community Edition on a local [kind](https://kind.sigs.k8s.io/) cluster
[Argo CD](https://argo-cd.readthedocs.io/) for GitOps deployment.
All runtime images are pulled exclusively from localhost:5001 once bootstrapped.
## Architecture
```
macOS (podman)
│
├── kind cluster (podman provider)
│ ├── local-repo :5001 — local OCI registry
│ ├── Argo CD :30080 — GitOps controller
│ └── overleaf namespace
│ ├── overleaf :30000
│ ├── mongo
│ └── redis
│
└── podman build → push → localhost:5001
```
## Prerequisites
- macOS with [Homebrew](https://brew.sh/)
- `brew install kind kubectl helm podman argocd`
Run the prereqs check:
```bash
./k8s/bootstrap/01-prereqs.sh
```
This also initialises and starts the podman machine if one isn't running.
## Step 1 — Create the kind cluster
```bash
./k8s/bootstrap/02-cluster.sh
```
What it does:
- Creates a single-node kind cluster named `overleaf` using `k8s/kind/cluster.yaml`
- Adds `localhost:5001` as an insecure registry in `~/.config/containers/registries.conf`
> **Podman note**: kind uses `KIND_EXPERIMENTAL_PROVIDER=podman` automatically.
> Port bindings go through the podman machine — `localhost:5001` on macOS reaches the local registry in podman
## Step 2 — Install Local Registry
```bash
./k8s/bootstrap/03-local-registry.sh
```
Access at **http://localhost:5001/v2**
## Step 3 — Install Argo CD
```bash
./k8s/bootstrap/04-argocd.sh
```
Installs Argo CD via Helm and registers the Overleaf `Application` from
`k8s/argocd/application.yaml`. Argo CD watches `k8s/charts/overleaf/` in the
configured git repo and syncs on every commit.
Access at **http://localhost:30080** — credentials printed by the script.
> By default `application.yaml` points at `https://github.com/overleaf/overleaf.git`.
> For a fully sandboxed setup, deploy [Gitea](https://gitea.io/) inside the cluster
> and update `repoURL` to point there.
## Step 4 — Build overleaf and push all images to Local Registry
```bash
./k8s/bootstrap/05-build-push.sh
```
Builds the overleaf image locally from `server-ce/` using podman, then pushes
all three images to Local Registry:
| Image | Local Registry tag |
|-------|-----------|
| built from `server-ce/Dockerfile-base` | `localhost:5001/overleaf/overleaf-base:local` |
| built from `server-ce/Dockerfile` | `localhost:5001/overleaf/overleaf:local` |
| `mongo:8.0` (mirrored from Docker Hub) | `localhost:5001/overleaf/mongo:8.0` |
| `redis:6.2` (mirrored from Docker Hub) | `localhost:5001/overleaf/redis:6.2` |
After this step the cluster is fully sandboxed for runtime — no external pulls happen.
> **Podman version**: `COPY --parents` in `server-ce/Dockerfile` requires
> **podman 4.8+ / Buildah 1.32+**. Check with `podman --version`.
>
> Override the image tag with `TAG=myfeature ./k8s/bootstrap/05-build-push.sh`,
> then set `overleaf.image.tag: myfeature` in `k8s/charts/overleaf/values.yaml`.
## Step 5 — Sync and access Overleaf
```bash
argocd app sync overleaf
argocd app wait overleaf --health
```
Overleaf will be available at **http://localhost:30000**.
Create an admin account:
```bash
kubectl exec -n overleaf deploy/overleaf -- \
/bin/bash -c "cd /overleaf/services/web && node modules/server-ce-scripts/scripts/create-user --admin --email admin@example.com"
```
## Day-to-day workflow
### Rebuild and redeploy
```bash
# Build with a custom tag
TAG=myfeature ./k8s/bootstrap/05-build-push.sh
# Update the tag and sync
# Edit k8s/charts/overleaf/values.yaml: overleaf.image.tag: myfeature
argocd app sync overleaf
```
Or build manually:
```bash
cp server-ce/.dockerignore .
podman build -f server-ce/Dockerfile-base -t localhost:5001/overleaf/overleaf-base:dev .
podman build -f server-ce/Dockerfile \
--build-arg OVERLEAF_BASE_TAG=localhost:5001/overleaf/overleaf-base:dev \
-t localhost:5001/overleaf/overleaf:dev .
podman push localhost:5001/overleaf/overleaf:dev --tls-verify=false
```
### Iterate on Helm chart changes
Edit files under `k8s/charts/overleaf/`, commit, push to the tracked branch,
then `argocd app sync overleaf`. Argo CD can also auto-sync on every push if
the webhook is configured.
### Tear down
```bash
kind delete cluster --name overleaf
```
## File layout
```
k8s/
├── README.md
├── kind/
│ └── cluster.yaml kind cluster config (podman, port mappings, containerd registry mirror)
├── argocd/
│ ├── values.yaml Argo CD Helm values (NodePort, insecure mode)
│ └── application.yaml Argo CD Application pointing to k8s/charts/overleaf
├── charts/
│ └── overleaf/
│ ├── Chart.yaml
│ ├── values.yaml Image refs, resource limits, env vars
│ └── templates/
│ ├── mongo-* Deployment, Service, PVC, ConfigMap (replica-set init)
│ ├── redis-* Deployment, Service, PVC
│ └── overleaf-* Deployment, Service (NodePort 30000), PVC, Ingress (disabled by default)
└── bootstrap/
├── 01-prereqs.sh
├── 02-cluster.sh
├── 03-local-registry.sh
├── 04-argocd.sh
└── 05-build-push.sh
```
## Known limitations
- **Sandboxed compiles** (`SANDBOXED_COMPILES`) are disabled. That feature requires
Docker sibling containers, which needs a privileged DinD sidecar in Kubernetes.
- Local Repo is HTTP-only.
- The Argo CD `Application` uses the public GitHub remote. For offline use, add
Gitea to the cluster and mirror the repo there.
+24
View File
@@ -0,0 +1,24 @@
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: overleaf
namespace: argocd
spec:
project: default
source:
# Update repoURL to your fork or a local Gitea instance for true air-gap operation
repoURL: https://github.com/tommybobbins/overleaf.git
targetRevision: HEAD
path: k8s/charts/overleaf
helm:
valueFiles:
- values.yaml
destination:
server: https://kubernetes.default.svc
namespace: overleaf
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
+9
View File
@@ -0,0 +1,9 @@
server:
service:
type: NodePort
nodePortHttp: 30080
configs:
params:
# Disable TLS on the ArgoCD API server so NodePort HTTP access works without cert errors
server.insecure: "true"
+37
View File
@@ -0,0 +1,37 @@
#!/usr/bin/env bash
set -euo pipefail
REQUIRED_TOOLS=(kind kubectl helm podman argocd)
MISSING=()
for tool in "${REQUIRED_TOOLS[@]}"; do
if ! command -v "$tool" &>/dev/null; then
MISSING+=("$tool")
else
echo " [ok] $tool $(${tool} version --short 2>/dev/null || ${tool} --version 2>/dev/null | head -1)"
fi
done
if [[ ${#MISSING[@]} -gt 0 ]]; then
echo ""
echo "Missing tools: ${MISSING[*]}"
echo ""
echo "Install via Homebrew:"
echo " brew install kind kubectl helm podman"
echo " brew install argocd"
exit 1
fi
echo ""
echo "Checking podman machine..."
if ! podman machine list 2>/dev/null | grep -q running; then
echo " No running podman machine found. Starting default machine..."
podman machine init --memory 8192 --cpus 4 --disk-size 20 2>/dev/null || true
#podman machine init 2>/dev/null || true
podman machine start
else
echo " [ok] podman machine running"
fi
echo ""
echo "All prerequisites satisfied."
+26
View File
@@ -0,0 +1,26 @@
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
CLUSTER_NAME="${CLUSTER_NAME:-overleaf}"
export KIND_EXPERIMENTAL_PROVIDER=podman
echo "==> Creating kind cluster '${CLUSTER_NAME}'..."
if kind get clusters 2>/dev/null | grep -q "^${CLUSTER_NAME}$"; then
echo " Cluster '${CLUSTER_NAME}' already exists, skipping."
else
KIND_EXPERIMENTAL_PROVIDER=podman kind create cluster \
--name "${CLUSTER_NAME}" \
--config "${SCRIPT_DIR}/../kind/cluster.yaml" \
--wait 120s
echo " [ok] Cluster created."
fi
echo ""
echo "==> Setting kubectl context..."
kubectl cluster-info --context "kind-${CLUSTER_NAME}"
echo ""
echo "Cluster ready. Next: run 03-local-registry.sh"
+58
View File
@@ -0,0 +1,58 @@
#!/bin/sh
set -o errexit
# 1. Create registry container unless it already exists
reg_name='kind-registry'
reg_port='5001'
if [ "$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" != 'true' ]; then
docker run \
-d --restart=always -p "127.0.0.1:${reg_port}:5000" --network bridge --name "${reg_name}" \
registry:3
fi
# 2. Create kind cluster with containerd registry config dir enabled
#
# NOTE: the containerd config patch is not necessary with images from kind v0.27.0+
# It may enable some older images to work similarly.
# If you're only supporting newer relases, you can just use `kind create cluster` here.
#
# See:
# https://github.com/kubernetes-sigs/kind/issues/2875
# https://github.com/containerd/containerd/blob/main/docs/cri/config.md#registry-configuration
# See: https://github.com/containerd/containerd/blob/main/docs/hosts.md
# 3. Add the registry config to the nodes
#
# This is necessary because localhost resolves to loopback addresses that are
# network-namespace local.
# In other words: localhost in the container is not localhost on the host.
#
# We want a consistent name that works from both ends, so we tell containerd to
# alias localhost:${reg_port} to the registry container when pulling images
REGISTRY_DIR="/etc/containerd/certs.d/localhost:${reg_port}"
for node in $(kubectl get nodes -o jsonpath='{.items[*].metadata.name}'); do
docker exec "${node}" mkdir -p "${REGISTRY_DIR}"
cat <<EOF | docker exec -i "${node}" cp /dev/stdin "${REGISTRY_DIR}/hosts.toml"
[host."http://${reg_name}:5000"]
EOF
done
# 4. Connect the registry to the cluster network if not already connected
# This allows kind to bootstrap the network but ensures they're on the same network
if [ "$(docker inspect -f='{{json .NetworkSettings.Networks.kind}}' "${reg_name}")" = 'null' ]; then
docker network connect "kind" "${reg_name}"
fi
# 5. Document the local registry
# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ConfigMap
metadata:
name: local-registry-hosting
namespace: kube-public
data:
localRegistryHosting.v1: |
host: "localhost:${reg_port}"
help: "https://kind.sigs.k8s.io/docs/user/local-registry/"
EOF
+47
View File
@@ -0,0 +1,47 @@
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ARGOCD_NAMESPACE="argocd"
echo "==> Adding ArgoCD Helm repo..."
helm repo add argo https://argoproj.github.io/argo-helm
helm repo update argo
echo ""
echo "==> Installing ArgoCD into namespace '${ARGOCD_NAMESPACE}'..."
helm upgrade --install argocd argo/argo-cd \
--namespace "${ARGOCD_NAMESPACE}" \
--create-namespace \
--values "${SCRIPT_DIR}/../argocd/values.yaml" \
--timeout 10m \
--wait
echo ""
echo "==> Waiting for ArgoCD server..."
kubectl rollout status deployment/argocd-server -n "${ARGOCD_NAMESPACE}" --timeout=300s
echo ""
echo "==> Logging into ArgoCD CLI..."
ARGOCD_PASSWORD=$(kubectl get secret argocd-initial-admin-secret \
-n "${ARGOCD_NAMESPACE}" \
-o jsonpath="{.data.password}" | base64 -d)
argocd login localhost:30080 \
--username admin \
--password "${ARGOCD_PASSWORD}" \
--insecure
echo ""
echo "==> Applying Overleaf Application..."
kubectl apply -f "${SCRIPT_DIR}/../argocd/application.yaml"
echo ""
echo "ArgoCD is up at http://localhost:30080"
echo " User: admin / Password: ${ARGOCD_PASSWORD}"
echo ""
echo "To watch sync status:"
echo " argocd app get overleaf"
echo " argocd app sync overleaf"
echo ""
echo "Next: run 05-build-push.sh, then sync the app."
+70
View File
@@ -0,0 +1,70 @@
#!/usr/bin/env bash
# Builds overleaf from server-ce/ using podman and pushes all images to Registry
# Requires podman 4.8+ (Buildah 1.32+) for COPY --parents support.
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)"
SERVER_CE="${REPO_ROOT}/server-ce"
REGISTRY="localhost:5001"
PROJECT="overleaf"
PASSWORD="passwordr12345"
TAG="${TAG:-local}"
BASE_IMAGE="${REGISTRY}/${PROJECT}/overleaf-base:${TAG}"
APP_IMAGE="${REGISTRY}/${PROJECT}/overleaf:${TAG}"
echo "==> Logging podman into Registry..."
podman login "${REGISTRY}" \
--username admin \
--password "${PASSWORD}" \
--tls-verify=false
# The Dockerfiles expect the build context to be the repo root.
# server-ce/.dockerignore must be present at the repo root before building.
echo ""
echo "==> Copying .dockerignore to repo root..."
cp "${SERVER_CE}/.dockerignore" "${REPO_ROOT}/.dockerignore"
echo ""
echo "==> Building base image (server-ce/Dockerfile-base)..."
podman build \
--progress=plain \
--file "${SERVER_CE}/Dockerfile-base" \
--tag "${BASE_IMAGE}" \
"${REPO_ROOT}"
echo ""
echo "==> Building app image (server-ce/Dockerfile)..."
podman build \
--progress=plain \
--file "${SERVER_CE}/Dockerfile" \
--build-arg "OVERLEAF_BASE_TAG=${BASE_IMAGE}" \
--tag "${APP_IMAGE}" \
"${REPO_ROOT}"
echo ""
echo "==> Pushing images to Registry..."
podman push "${BASE_IMAGE}" --tls-verify=false
podman push "${APP_IMAGE}" --tls-verify=false
echo ""
echo "==> Mirroring mongo and redis into Local Registry..."
for PAIR in "mongo:8.0" "redis:6.2"; do
DST="${REGISTRY}/${PROJECT}/${PAIR}"
echo " ${PAIR} → ${DST}"
podman pull "${PAIR}"
podman tag "${PAIR}" "${DST}"
podman push "${DST}" --tls-verify=false
done
echo ""
echo "Done. Images in Registry:"
echo " ${BASE_IMAGE}"
echo " ${APP_IMAGE}"
echo " ${REGISTRY}/${PROJECT}/mongo:8.0"
echo " ${REGISTRY}/${PROJECT}/redis:6.2"
echo ""
echo "Update k8s/charts/overleaf/values.yaml if TAG is not 'local', then:"
echo " argocd app sync overleaf"
+4
View File
@@ -0,0 +1,4 @@
#!/usr/bin/env bash
echo "Deleting the overleaf cluster"
kind delete cluster -n overleaf
+5
View File
@@ -0,0 +1,5 @@
apiVersion: v2
name: overleaf
description: Overleaf Community Edition — overleaf, mongo, redis
version: 0.1.0
appVersion: "latest"
@@ -0,0 +1,4 @@
{{- define "overleaf.labels" -}}
app.kubernetes.io/managed-by: {{ .Release.Service }}
helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version }}
{{- end }}
@@ -0,0 +1,10 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: mongo-init
labels:
app: mongo
{{- include "overleaf.labels" . | nindent 4 }}
data:
mongodb-init-replica-set.js: |
rs.initiate({ _id: '{{ .Values.mongo.replicaSetName }}', members: [{ _id: 0, host: 'mongo:27017' }] })
@@ -0,0 +1,82 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: mongo
labels:
app: mongo
{{- include "overleaf.labels" . | nindent 4 }}
spec:
replicas: 1
selector:
matchLabels:
app: mongo
strategy:
type: Recreate
template:
metadata:
labels:
app: mongo
spec:
containers:
- name: mongo
image: "{{ .Values.mongo.image.repository }}:{{ .Values.mongo.image.tag }}"
imagePullPolicy: {{ .Values.mongo.image.pullPolicy }}
command:
- mongod
args:
- --replSet
- {{ .Values.mongo.replicaSetName }}
- --bind_ip_all
env:
- name: MONGO_INITDB_DATABASE
value: overleaf
- name: GLIBC_TUNABLES
value: glibc.pthread.rseq=1
ports:
- containerPort: 27017
lifecycle:
postStart:
exec:
command:
- /bin/sh
- -c
- sleep 60; mongosh overleaf /docker-entrypoint-initdb.d/mongodb-init-replica-set.js
|| true
livenessProbe:
exec:
command:
- /bin/sh
- -c
- "echo 'db.stats().ok' | mongosh localhost:27017/test --quiet"
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 10
failureThreshold: 5
readinessProbe:
exec:
command:
- /bin/sh
- -c
- "echo 'db.stats().ok' | mongosh localhost:27017/test --quiet"
initialDelaySeconds: 15
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
volumeMounts:
- name: data
mountPath: /data/db
- name: init-script
mountPath: /docker-entrypoint-initdb.d/mongodb-init-replica-set.js
subPath: mongodb-init-replica-set.js
volumes:
- name: data
persistentVolumeClaim:
claimName: mongo-data
- name: init-script
configMap:
name: mongo-init
hostAliases:
- hostnames:
- mongo
ip: 127.0.0.1
restartPolicy: Always
@@ -0,0 +1,13 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mongo-data
labels:
app: mongo
{{- include "overleaf.labels" . | nindent 4 }}
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: {{ .Values.mongo.persistence.size }}
@@ -0,0 +1,14 @@
apiVersion: v1
kind: Service
metadata:
name: mongo
labels:
app: mongo
{{- include "overleaf.labels" . | nindent 4 }}
spec:
selector:
app: mongo
ports:
- name: mongo
port: 27017
targetPort: 27017
@@ -0,0 +1,33 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis
labels:
app: redis
{{- include "overleaf.labels" . | nindent 4 }}
spec:
replicas: 1
selector:
matchLabels:
app: redis
strategy:
type: Recreate
template:
metadata:
labels:
app: redis
spec:
containers:
- name: redis
image: "{{ .Values.redis.image.repository }}:{{ .Values.redis.image.tag }}"
imagePullPolicy: {{ .Values.redis.image.pullPolicy }}
ports:
- containerPort: 6379
volumeMounts:
- name: data
mountPath: /data
volumes:
- name: data
persistentVolumeClaim:
claimName: redis-data
restartPolicy: Always
@@ -0,0 +1,13 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: redis-data
labels:
app: redis
{{- include "overleaf.labels" . | nindent 4 }}
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: {{ .Values.redis.persistence.size }}
@@ -0,0 +1,14 @@
apiVersion: v1
kind: Service
metadata:
name: redis
labels:
app: redis
{{- include "overleaf.labels" . | nindent 4 }}
spec:
selector:
app: redis
ports:
- name: redis
port: 6379
targetPort: 6379
@@ -0,0 +1,57 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: overleaf
labels:
app: overleaf
{{- include "overleaf.labels" . | nindent 4 }}
spec:
replicas: 1
selector:
matchLabels:
app: overleaf
strategy:
type: Recreate
template:
metadata:
labels:
app: overleaf
spec:
containers:
- name: overleaf
image: "{{ .Values.overleaf.image.repository }}:{{ .Values.overleaf.image.tag }}"
imagePullPolicy: {{ .Values.overleaf.image.pullPolicy }}
ports:
- containerPort: 80
env:
{{- range $key, $val := .Values.overleaf.env }}
- name: {{ $key }}
value: {{ $val | quote }}
{{- end }}
resources:
{{- toYaml .Values.overleaf.resources | nindent 12 }}
volumeMounts:
- name: data
mountPath: /var/lib/overleaf
readinessProbe:
httpGet:
path: /login
port: 80
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 6
livenessProbe:
httpGet:
path: /login
port: 80
initialDelaySeconds: 60
periodSeconds: 30
timeoutSeconds: 10
failureThreshold: 5
volumes:
- name: data
persistentVolumeClaim:
claimName: overleaf-data
terminationGracePeriodSeconds: 60
restartPolicy: Always
@@ -0,0 +1,28 @@
{{- if .Values.ingress.enabled }}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: overleaf
labels:
app: overleaf
{{- include "overleaf.labels" . | nindent 4 }}
{{- with .Values.ingress.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
{{- if .Values.ingress.className }}
ingressClassName: {{ .Values.ingress.className }}
{{- end }}
rules:
- host: {{ .Values.ingress.host }}
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: overleaf
port:
name: http
{{- end }}
@@ -0,0 +1,13 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: overleaf-data
labels:
app: overleaf
{{- include "overleaf.labels" . | nindent 4 }}
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: {{ .Values.overleaf.persistence.size }}
@@ -0,0 +1,18 @@
apiVersion: v1
kind: Service
metadata:
name: overleaf
labels:
app: overleaf
{{- include "overleaf.labels" . | nindent 4 }}
spec:
selector:
app: overleaf
type: {{ .Values.overleaf.service.type }}
ports:
- name: http
port: {{ .Values.overleaf.service.port }}
targetPort: 80
{{- if and (eq .Values.overleaf.service.type "NodePort") .Values.overleaf.service.nodePort }}
nodePort: {{ .Values.overleaf.service.nodePort }}
{{- end }}
+54
View File
@@ -0,0 +1,54 @@
overleaf:
image:
repository: localhost:5001/overleaf/overleaf
tag: local
pullPolicy: Always
persistence:
size: 10Gi
service:
type: NodePort
port: 80
nodePort: 30000
env:
OVERLEAF_APP_NAME: "Overleaf Community Edition"
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"
# Sandboxed compiles require Docker sibling containers — not supported in k8s without DinD
SANDBOXED_COMPILES: "false"
DOCKER_RUNNER: "false"
resources:
requests:
memory: 1Gi
cpu: 500m
limits:
memory: 4Gi
cpu: 2000m
mongo:
image:
repository: localhost:5001/overleaf/mongo
tag: "8.0"
pullPolicy: IfNotPresent
persistence:
size: 10Gi
replicaSetName: overleaf
redis:
image:
repository: localhost:5001/overleaf/redis
tag: "6.2"
pullPolicy: IfNotPresent
persistence:
size: 1Gi
persistence:
size: 1Gi
ingress:
enabled: false
className: nginx
host: overleaf.local
annotations: {}
+40
View File
@@ -0,0 +1,40 @@
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
#featureGates:
# ValidatingAdmissionPolicy: true
#runtimeConfig:
# admissionregistration.k8s.io/v1beta1: true
nodes:
- role: control-plane
image: kindest/node:v1.35.0@sha256:452d707d4862f52530247495d180205e029056831160e22870e37e3f6c1ac31f
extraPortMappings:
# Harbor HTTP NodePort
- containerPort: 30002
hostPort: 30002
protocol: TCP
# ArgoCD UI NodePort
- containerPort: 30080
hostPort: 30080
protocol: TCP
# Overleaf HTTP NodePort
- containerPort: 30000
hostPort: 30000
protocol: TCP
# Tell containerd to resolve localhost:5001 via the NodePort bound on the node itself.
# kube-proxy binds NodePorts to 0.0.0.0 on the node, so localhost:5001 reaches localhost
# from inside the node without needing cluster DNS.
containerdConfigPatches:
- |-
[plugins."io.containerd.grpc.v1.cri".registry]
config_path = "/etc/containerd/certs.d"
#containerdConfigPatches:
# - |-
# [plugins."io.containerd.grpc.v1.cri".registry]
# [plugins."io.containerd.grpc.v1.cri".registry.mirrors]
# [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:5001"]
# endpoint = ["http://localhost:30002"]
# [plugins."io.containerd.grpc.v1.cri".registry.configs]
# [plugins."io.containerd.grpc.v1.cri".registry.configs."localhost:5001".tls]
# insecure_skip_verify = true
# [plugins."io.containerd.grpc.v1.cri".registry.configs."localhost:5001".tls]
# insecure_skip_verify = true
+11 -4
View File
@@ -18,14 +18,22 @@ COPY server-ce/genScript.js server-ce/services.js /overleaf/
# Corepack setup, shared between all the images.
ENV PATH="/overleaf/node_modules/.bin:$PATH"
ENV COREPACK_HOME=/opt/corepack
RUN corepack enable && corepack install -g yarn@4.14.1
RUN corepack enable && corepack prepare yarn@4.14.1 --activate
#RUN corepack enable && corepack prepare yarn --activate
ENV COREPACK_ENABLE_NETWORK=0
# RUN npm install node-fetch
# RUN yarn add node-fetch
# RUN yarn install
#RUN --mount=type=cache,target=/root/.cache \
# --mount=type=cache,target=/root/.yarn/berry/cache,id=server-ce-yarn-cache \
# --mount=type=tmpfs,target=/tmp yarn install | bash
# Install yarn dependencies
# -------------------------
RUN --mount=type=cache,target=/root/.cache \
--mount=type=cache,target=/root/.yarn/berry/cache,id=server-ce-yarn-cache \
--mount=type=cache,target=/usr/local/share/.cache/yarn,id=server-ce-yarn-fallback-cache \
--mount=type=tmpfs,target=/tmp node genScript install | bash
# Add the actual source files
@@ -33,10 +41,9 @@ RUN --mount=type=cache,target=/root/.cache \
COPY --parents libraries/ services/ tools/migrations/ /overleaf/
RUN --mount=type=cache,target=/root/.cache \
--mount=type=cache,target=/root/.yarn/berry/cache,id=server-ce-yarn-cache \
--mount=type=cache,target=/usr/local/share/.cache/yarn,id=server-ce-yarn-fallback-cache \
--mount=type=cache,target=/overleaf/services/web/node_modules/.cache,id=server-ce-webpack-cache \
--mount=type=tmpfs,target=/tmp \
node genScript compile | bash
YARN_CACHE_FOLDER=/tmp/.yarn-cache node genScript compile | bash
# Copy runit service startup scripts to its location
# --------------------------------------------------
+1 -1
View File
@@ -2,7 +2,7 @@
# Overleaf Base Image (sharelatex/sharelatex-base)
# --------------------------------------------------
FROM phusion/baseimage:noble-1.0.3
FROM phusion/baseimage:noble-1.0.2
# Makes sure LuaTex cache is writable
# -----------------------------------
@@ -1,78 +0,0 @@
#!/bin/bash
set -e
POTENTIAL_OLD_PATHS="
/etc/sharelatex
/var/lib/sharelatex
/var/log/sharelatex
"
OLD_ITEMS=""
for path in ${POTENTIAL_OLD_PATHS}; do
if [[ -e "$path" ]]; then
OLD_ITEMS="$OLD_ITEMS $path"
fi
done
if [[ "$OLD_ITEMS" == "" ]]; then
exit 0
fi
OLD_ITEMS=$(echo "$OLD_ITEMS" | xargs -n1 | sed 's/^/ - /')
N=$(echo "$OLD_ITEMS" | wc -l)
cat <<EOF
------------------------------------------------------------------------
ShareLaTeX to Overleaf rebranding
---------------------------------
Starting with version 5.0, ShareLaTeX branded file system paths are no
longer supported as we are migrating to the Overleaf brand.
Your configuration still uses $N ShareLaTeX branded paths:
$OLD_ITEMS
Please update the in-container bind-mount target to refer to the
Overleaf equivalent:
- /etc/sharelatex -> /etc/overleaf
- /var/lib/sharelatex -> /var/lib/overleaf
- /var/log/sharelatex -> /var/log/overleaf
Overleaf toolkit setups:
github.com/overleaf/toolkit$ bin/upgrade
Legacy docker compose setups/Horizontal scaling setups:
before:
services:
sharelatex:
volumes:
- /my/docker-host/path:/var/lib/sharelatex
after:
services:
sharelatex:
volumes:
- /my/docker-host/path:/var/lib/overleaf
Other deployment methods:
Adapt the docker compose example or get in touch with support.
Server Pro: Please update SANDBOXED_COMPILES_HOST_DIR if needed.
Refusing to startup, exiting in 10s.
------------------------------------------------------------------------
EOF
sleep 10
exit 101
@@ -1,56 +0,0 @@
#!/bin/bash
set -e
OLD_ITEMS=$(env | cut -d '=' -f1 | grep SHARELATEX | sed 's/^/ - /')
if [[ "$OLD_ITEMS" == "" ]]; then
exit 0
fi
N=$(echo "$OLD_ITEMS" | wc -l)
cat <<EOF
------------------------------------------------------------------------
ShareLaTeX to Overleaf rebranding
---------------------------------
Starting with version 5.0, ShareLaTeX branded variables are no
longer supported as we are migrating to the Overleaf brand.
Your configuration still uses $N ShareLaTeX environment variables:
$OLD_ITEMS
Please either replace them with the "OVERLEAF_" prefix,
e.g. SHARELATEX_MONGO_URL -> OVERLEAF_MONGO_URL, or
remove old entries from your configuration.
You can use the following script for migrating your config.
Overleaf toolkit setups:
github.com/overleaf/toolkit$ bin/upgrade
github.com/overleaf/toolkit$ bin/rename-env-vars-5-0.sh
Legacy docker compose setups/Horizontal scaling setups:
github.com/overleaf/overleaf$ git pull
github.com/overleaf/overleaf$ server-ce/bin/rename-env-vars-5-0.sh
# When using a docker-compose.override.yml file (or other file name):
github.com/overleaf/overleaf$ server-ce/bin/rename-env-vars-5-0.sh docker-compose.override.yml
Other deployment methods:
Try using the docker compose script or get in touch with support.
Refusing to startup, exiting in 10s.
------------------------------------------------------------------------
EOF
sleep 10
exit 101