Overleaf is an online collaborative LaTeX editing platform. This article covers ShareLaTeX — a tool with the same functionality as Overleaf — deployed on a server using Docker.
1. Repackaging the ShareLaTeX Docker Image
ShareLaTeX has since been renamed Overleaf, and the official recommendation is to install it using the Overleaf Toolkit. The Overleaf Toolkit modifies the Linux environment, which is fairly involved. Here, Docker is used to deploy it instead, minimizing the impact on the existing Linux environment.
Reference the official docker-compose.yaml file.
However, running docker-compose directly can’t typeset Chinese, mainly because the xelatex-related packages are missing. Since this is inside a Docker container, working with it directly isn’t very convenient. Here, a new Docker image is built directly on top of the original ShareLaTeX Docker image.
In the new Docker image, texlive gets updated, and the xelatex-related packages get added to the environment. The corresponding Dockerfile is as follows:
Dockerfile
FROM sharelatex/sharelatex
RUN tlmgr option repository https://mirrors.tuna.tsinghua.edu.cn/CTAN/systems/texlive/tlnet
RUN tlmgr update --self --all
RUN tlmgr install scheme-full
WORKDIR /
ENTRYPOINT ["/sbin/my_init"]
In the folder holding the Dockerfile, build the new Docker image:
docker build --tag chinglin/sharelatex:latest --progress=plain . 2>&1 | tee build.log
2. Solving the MongoDB Issue
An additional image needs to be added alongside MongoDB, to initialize it:
mongoinit:
restart: "no"
image: mongo:4.4
depends_on:
mongo:
condition: service_healthy
entrypoint:
[
"mongo",
"--host",
"mongo:27017",
"--eval",
'rs.initiate({ _id: "overleaf", members: [ { _id: 0, host: "mongo:27017" } ] })',
]
3. Running docker-compose
Reference the official docker-compose.yaml file, plus our modification above:
docker-compose.yaml
version: '2.2'
services:
sharelatex:
restart: always
# Server Pro users:
# image: quay.io/sharelatex/sharelatex-pro
image: chinglin/sharelatex
container_name: sharelatex
depends_on:
mongo:
condition: service_healthy
redis:
condition: service_started
ports:
- 8089:80
links:
- mongo
- redis
stop_grace_period: 60s
volumes:
- ./data/sharelatex_data:/var/lib/sharelatex
# - ./data/sharelatex_texlive:/texlive
########################################################################
#### Server Pro: Uncomment the following line to mount the docker ####
#### socket, required for Sibling Containers to work ####
########################################################################
# - /var/run/docker.sock:/var/run/docker.sock
environment:
SHARELATEX_APP_NAME: Overleaf Community Edition
SHARELATEX_MONGO_URL: mongodb://mongo/sharelatex
# Same property, unfortunately with different names in
# different locations
SHARELATEX_REDIS_HOST: redis
REDIS_HOST: redis
ENABLED_LINKED_FILE_TYPES: 'project_file,project_output_file'
# Enables Thumbnail generation using ImageMagick
ENABLE_CONVERSIONS: 'true'
# Disables email confirmation requirement
EMAIL_CONFIRMATION_DISABLED: 'true'
# temporary fix for LuaLaTex compiles
# see https://github.com/overleaf/overleaf/issues/695
TEXMFVAR: /var/lib/sharelatex/tmp/texmf-var
## Set for SSL via nginx-proxy
#VIRTUAL_HOST: 103.112.212.22
# SHARELATEX_SITE_URL: http://sharelatex.mydomain.com
# SHARELATEX_NAV_TITLE: Our ShareLaTeX Instance
# SHARELATEX_HEADER_IMAGE_URL: http://somewhere.com/mylogo.png
# SHARELATEX_ADMIN_EMAIL: [email protected]
# SHARELATEX_LEFT_FOOTER: '[{"text": "Powered by <a href=\"https://www.sharelatex.com\">ShareLaTeX</a> 2016"},{"text": "Another page I want to link to can be found <a href=\"here\">here</a>"} ]'
# SHARELATEX_RIGHT_FOOTER: '[{"text": "Hello I am on the Right"} ]'
# SHARELATEX_EMAIL_FROM_ADDRESS: "[email protected]"
# SHARELATEX_EMAIL_AWS_SES_ACCESS_KEY_ID:
# SHARELATEX_EMAIL_AWS_SES_SECRET_KEY:
# SHARELATEX_EMAIL_SMTP_HOST: smtp.mydomain.com
# SHARELATEX_EMAIL_SMTP_PORT: 587
# SHARELATEX_EMAIL_SMTP_SECURE: false
# SHARELATEX_EMAIL_SMTP_USER:
# SHARELATEX_EMAIL_SMTP_PASS:
# SHARELATEX_EMAIL_SMTP_TLS_REJECT_UNAUTH: true
# SHARELATEX_EMAIL_SMTP_IGNORE_TLS: false
# SHARELATEX_EMAIL_SMTP_NAME: '127.0.0.1'
# SHARELATEX_EMAIL_SMTP_LOGGER: true
# SHARELATEX_CUSTOM_EMAIL_FOOTER: "This system is run by department x"
# ENABLE_CRON_RESOURCE_DELETION: true
################
## Server Pro ##
################
# SANDBOXED_COMPILES: 'true'
# SANDBOXED_COMPILES_SIBLING_CONTAINERS: 'true'
# SANDBOXED_COMPILES_HOST_DIR: '/var/sharelatex_data/data/compiles'
# DOCKER_RUNNER: 'false'
# Works with test LDAP server shown at bottom of docker compose
# SHARELATEX_LDAP_URL: 'ldap://ldap:389'
# SHARELATEX_LDAP_SEARCH_BASE: 'ou=people,dc=planetexpress,dc=com'
# SHARELATEX_LDAP_SEARCH_FILTER: '(uid={{username}})'
# SHARELATEX_LDAP_BIND_DN: 'cn=admin,dc=planetexpress,dc=com'
# SHARELATEX_LDAP_BIND_CREDENTIALS: 'GoodNewsEveryone'
# SHARELATEX_LDAP_EMAIL_ATT: 'mail'
# SHARELATEX_LDAP_NAME_ATT: 'cn'
# SHARELATEX_LDAP_LAST_NAME_ATT: 'sn'
# SHARELATEX_LDAP_UPDATE_USER_DETAILS_ON_LOGIN: 'true'
# SHARELATEX_TEMPLATES_USER_ID: "578773160210479700917ee5"
# SHARELATEX_NEW_PROJECT_TEMPLATE_LINKS: '[ {"name":"All Templates","url":"/templates/all"}]'
# SHARELATEX_PROXY_LEARN: "true"
mongo:
restart: always
image: mongo:4.4
container_name: mongo
command: "--replSet overleaf"
expose:
- 27017
volumes:
- ./data/mongo_data:/data/db
healthcheck:
test: echo 'db.stats().ok' | mongo localhost:27017/test --quiet
interval: 10s
timeout: 10s
retries: 5
mongoinit:
restart: "no"
image: mongo:4.4
depends_on:
mongo:
condition: service_healthy
entrypoint:
[
"mongo",
"--host",
"mongo:27017",
"--eval",
'rs.initiate({ _id: "overleaf", members: [ { _id: 0, host: "mongo:27017" } ] })',
]
redis:
restart: always
image: redis:6.2
container_name: redis
expose:
- 6379
volumes:
- ./data/redis_data:/data
# ldap:
# restart: always
# image: rroemhild/test-openldap
# container_name: ldap
# expose:
# - 389
# See https://github.com/jwilder/nginx-proxy for documentation on how to configure the nginx-proxy container,
# and https://github.com/overleaf/overleaf/wiki/HTTPS-reverse-proxy-using-Nginx for an example of some recommended
# settings. We recommend using a properly managed nginx instance outside of the Overleaf Server Pro setup,
# but the example here can be used if you'd prefer to run everything with docker-compose
# nginx-proxy:
# image: jwilder/nginx-proxy
# container_name: nginx-proxy
# ports:
# #- "80:80"
# - "443:443"
# volumes:
# - /var/run/docker.sock:/tmp/docker.sock:ro
# - /home/sharelatex/tmp:/etc/nginx/certs
Run docker-compose:
docker-compose up -d
To make the deployed service reachable from other machines, the corresponding port on the server also needs to be opened — 8090 in this case.
4. Creating a User
The previous step already started ShareLaTeX with docker-compose; at this point, an account still needs to be created from inside the container. On the server, run:
docker exec -i -t sharelatex /bin/bash
grunt user:create-admin --email [email protected]
At this point a URL is shown. Replace the localhost part of the URL with the server’s address, and enter the account and password in the browser to log in. From there, happy writing.
5. Experience
Pros:
- Works out of the box — no need to install and configure texlive on every computer.
- Shareable, making collaboration easy.
- Data is deployed on your own server (which, on the surface, looks more secure).
Cons:
- The web front-end editor is too naive — it can’t really be a great editor after all.
- Also related to the editor front-end: there doesn’t seem to be a way to take advantage of current large language models’ code-generation capabilities.
6. Summary
This article covered setting up ShareLaTeX on a server, solving ShareLaTeX’s inability to compile Chinese by repackaging the image, and fixing the MongoDB issue by modifying the official docker-compose.yaml file.