Host Your Own LaTeX Server

A Good Practice to use Docker

Hongjian
5 min readMar 18, 2019
A screenshot of local ShareLaTeX server with full texlive package installed. Tex file available in GithubGist.

If you use LaTeX a lot, you probably already know Overleaf and ShareLaTeX, which provide easy to use, online, collaborative LaTeX editor for free. In 2017, they joined forces to build the best collaborative writing tool. Now, you would ask why would I want to setup my own LaTeX server, if there is free service already? Well, I commend you for your critical thinking, and here are the reasons I can think of.

  • Be cool.
  • Privacy concern. You need physical isolation of your documents.
  • Development. You want to make open-source contribution.

In this post, I will show the process to set up ShareLaTeX on your own machine. The open-source sharelatex repo is the centerpiece to enable us deploying our locally hosted online LaTeX editing server. The said repository only wraps various shareLaTeX services into a docker compose file, and does not contain any source code by itself. There is a quick start guide in the repo, but assumes good background knowledge on related techniques (docker etc.). This post will present my own experience to set this up, since

If you did not document it, it did not happen.

Steps 1: Install docker

Assume using Debian-based Linux, sudo apt install docker will install docker and start docker daemon. In order for later steps (docker-compose) to work, we need to make sure the docker daemon is actually running. We can check this by sudo systemctl status docker , and we should see something like

● docker.service - Docker Application Container Engine
Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled)
Active: active (running) since Sun 2019-03-17 13:50:38 PDT; 3h 59min ago
...

Step 2: Pull the sharelatex repo

With git clone git@github.com:sharelatex/sharelatex.

The docker-compose.yml file defines everything we need for our local ShareLaTeX server to run. Inside this file, there is a services section and three service are available, i.e. sharelatex, redis, mongo. The sharelatex is the main service running in Node.js server, which are also how various sharelatex components are implemented in. The redis service is an in-memory cache/message broker. Fincally, the mongodb is used as persistent story for tex documents. Interested readers could refer the official docker compose guide for more information.

Step 3: Start ShareLeTeX server

With sudo docker-compose up .

The first time execution will try to pull three images through sudo docker pull <image name> , where image names are sharelatex/sharelatex, library/redis, library/mongo. After the images are pulled, docker will start each of them. Keep an eye in the docker start log for any errors.

If everything works out fine, you should be able to connect to your local sharelatex server at http://0.0.0.0. As the first time run, visit the /launchpad page to set up your admin user. Now you can write LaTeX in your browser. However complicated tex example shown at the beginning of this post won’t work, since the default sharelatex image only have a minimum installation of TexLive. Next, we will update the installed Tex Live with full installation.

Step 4: Fully install TeX Live

Run sudo docker exec sharelatex tlmgr install scheme-full , while your sharelatex container is running. Note in the command above, docker only executes command within live containers and thus we need the container name. To check a list of running containers, use sudo docker container list.

If you are lucky, your sharelatex container will start installing new tex packages. However, since the sharelatex comes with 2017 Tex Live, you are more likely to run into the “Tex version mismatch” complain. The principal solution is to re-install the Tex Live 2018, which is too complicated for me. The alternative is to stick with Tex Live 2017. To do so, use sudo docker exec sharelatex tlmgr option repository ftp://tug.org/historic/systems/texlive/2017/tlnet-final to set upstream with 2017 Tex packages. Then start a scheme-full install.

The above process runs for hours, since there are tens of thousands of tex packages to install. You can, of course, only install the package you need through sudo docker exec sharelatex tlmgr install <package name> . Whenever you installed a package but the sharelatex compiler could not pick up the package, i.e. complaining package missing, try use sudo docker exec sharelatex texhash to build new package index.

When the Tex full installation finished, you can commit your change on the running container to new image through sudo docker commit sharelatex sharelatex/sharelatex:full-texlive-install . Here is the final images I have to give you a sense how large is the full installation on Tex Live.

$ sudo docker images --format 'table {{.Repository}}\t{{.Tag}}\t{{.Size}}'
REPOSITORY TAG SIZE
sharelatex/sharelatex full-texlive-install 8.49GB
redis latest 95MB
mongo latest 394MB
sharelatex/sharelatex latest 3.46GB

Now, your local ShareLaTeX server should be running with full Tex packages. And the test tex file in the beginning of this post should compile to a beautiful pdf. Before we conclude, let’s try to understand the two dependency data services that ShareLaTeX relies on.

Explore Data Services

When ShareLaTeX server is up and running, we also have redis and mongo service running. We should be able to see what are stored inside each of them. First, we should figure out the IP address that these two data services listening to. We can find the IP by sudo docker inspect <container name> . Look for IPAddress under NetworkSettings.

In my case, the mongo container is serving through 172.18.0.4. You may need to download mongoDB client first with sudo apt install mongodb-clients . Then, we can directly connect to it.

$ mongo 172.18.0.4
MongoDB shell version: 2.6.10
connecting to: 172.18.0.4/test
.......
> show databases;
admin 0.000GB
config 0.000GB
local 0.000GB
sharelatex 0.000GB
> use sharelatex
switched to db sharelatex
> show tables
docs
rooms
users
projects
projectHistoryMetaData
docOps
docHistory
_migrations

The docs table store every line of our testing tex file, while the projects table track every project.

Similar for redis service (running on 172.18.0.2 in my case). I have one session open in my browser, and various run-time messages are tracked in redis.

$ redis-cli -h 172.18.0.2
172.18.0.2:6379> info keyspace
# Keyspace
db0:keys=13,expires=7,avg_ttl=89009937367
172.18.0.2:6379> keys *
1) "connected_user:5c8340567c9260008a351b14:n6LPQnWZdMsDCm6Ha8fW"
2) "doclines:5c8340567c9260008a351b15"
3) "clients_in_project:5c8340567c9260008a351b14"
4) "RateLimit:open-project:{5c8340567c9260008a351b14:5c833fd67c9260008a351b12}"
5) "DocsIn:5c8340567c9260008a351b14"
6) "UserSessions:{5c833fd67c9260008a351b12}"
7) "ProjectId:5c8340567c9260008a351b15"
8) "RateLimit:compile-project-http:{5c8340567c9260008a351b14:5c833fd67c9260008a351b12}"
9) "ProjectState:5c8340567c9260008a351b14"
10) "DocHash:5c8340567c9260008a351b15"
11) "sess:qP7owMjcXH3du0sM8aKGnqdqbZhY2eCs"
12) "Pathname:5c8340567c9260008a351b15"
13) "DocVersion:5c8340567c9260008a351b15"
172.18.0.2:6379>

Thanks for staying until the end. Happy hacking.

--

--