Tested on Debian 12.6 I started with another guide (https://gist.github.com/gelim/a840a99d15cb765cb7b65105b72f00c4), but quickly realized, I wanted to go another route (no runit for example)
Following this guide, it is possible to deploy Overleaf without Docker, but there are no guarantuees it will work nor is there any support for this method by the great folds of Overleaf. This procedure was tested by me on various machines and I did not find any problems with it, all services are running, everything seems to be stable.
TODO
- cron jobs in /root/source/overleaf/server-ce/cron:
- copy them
- alter them (to non-docker deployment)
those are the commits found in /var/www/revisions.txt in the corresponding docker container, it's the same one every time, but this might change in the future, so always check.
docker version | git commit |
---|---|
5.0.4 | cf227e2d085a859d360c51a4dfce13701fa6d41e |
5.0.5 | cf227e2d085a859d360c51a4dfce13701fa6d41e |
5.0.6 | cf227e2d085a859d360c51a4dfce13701fa6d41e |
5.0.7 | cf227e2d085a859d360c51a4dfce13701fa6d41e |
5.1 | a55d9fcf38755c6d982ddcbb0cd092b37d9879fa |
(tested with versions up to 5.0.4, table is for reference, versions >5.0.4 should work too, but need testing. 5.0.4 is the version currently being used by overleaf-toolkit's deployment, as referenced in the overleaf repo)
- install packages
apt-get install gnupg curl build-essential wget net-tools unzip time imagemagick optipng strace nginx git python3 zlib1g-dev libpcre3-dev qpdf aspell supervisor nodejs redis-server sqlite3 node-jsdom npm
- install mongodb
- import public repo key
curl -fsSL https://www.mongodb.org/static/pgp/server-7.0.asc | gpg -o /usr/share/keyrings/mongodb-server-7.0.gpg --dearmor
- create apt list file
echo "deb [ signed-by=/usr/share/keyrings/mongodb-server-7.0.gpg ] http://repo.mongodb.org/apt/debian bookworm/mongodb-org/7.0 main" | tee /etc/apt/sources.list.d/mongodb-org-7.0.list
- update repos and install mongodb
apt-get update && apt-get install mongodb-org
- import public repo key
- the next part is only relevant if you're using sysvinit like I do:
- create init file /etc/init.d/mongod) from https://raw.githubusercontent.com/mongodb/mongo/ac99f0b697e689dc950a22def4c882c7b3bea9e4/debian/init.d
- change permissions of init file
chmod +x /etc/init.d/mongod
- make mongodb start at boot
update-rc.d mongod defaults
- configure mongodb for replication sets
- add to /etc/mongod.conf:
# overleaf replication set
replication:
replSetName: "overleaf"
- afterwards, start mongodb and establish this node as the first member of the replica set
/etc/init.d/mongod start
mongosh
rs.initiate()
quit;
this guide assumes two locations:
-
/root/source/overleaf for the cloned Github repo
-
/var/www/overleaf for the actual files for production
-
clone overleaf repo in prepared folder
mkdir /root/source
cd /root/source
git clone https://github.com/overleaf/overleaf.git
- checkout correct state of repo (taken from /var/www/revisions.txt in docker container)
git checkout cf227e2d085a859d360c51a4dfce13701fa6d41e
- copy overleaf directory
cp -a /root/source/overleaf/server-ce /var/www/overleaf
- create overleaf user and directories
adduser --system --group --home /var/www/overleaf --no-create-home overleaf
- copy logrotate settings for overleaf
cp -a /root/source/overleaf/server-ce/logrotate/overleaf /etc/logrotate.d/overleaf
chmod 644 /etc/logrotate.d/overleaf
-
install texlive
apt-get install texlive latexmk texlive-full
-
create additional directories
mkdir -p /var/lib/overleaf/{data,tmp} && \
mkdir -p /var/log/overleaf && \
chown overleaf: /var/log/overleaf && \
mkdir -p /var/lib/overleaf/data/{cache,compiles,history,output,template_files,user_files} && \
mkdir -p /var/lib/overleaf/data/history/overleaf-chunks && \
mkdir -p /var/lib/overleaf/tmp/{dumpFolder,uploads,projectHistories} && \
mkdir -p /var/www/overleaf/services/clsi/{compiles,output} && \
mkdir -p /var/lib/overleaf/data/history/{overleaf-global-blobs,overleaf-project-blobs,overleaf-chunks,overleaf-zips} && \
chown -R overleaf: /var/lib/overleaf/
- copy services folder
cp -a /root/source/overleaf/services /var/www/overleaf/
- copy patches folder
cp -a /root/source/overleaf/patches /var/www/overleaf/
- copy libaries folder
cp -a /root/source/overleaf/libraries /var/www/overleaf/
- prepare overleaf settings folder
mkdir /etc/overleaf
- create overleaf site status file
touch /etc/overleaf/site_status
- copy settings.js file
cp /root/source/overleaf/server-ce/config/settings.js /etc/overleaf/
- copy env.sh file
cp /root/source/overleaf/server-ce/config/env.sh /etc/overleaf/env.sh
- copy history-v1 config files
cp /root/source/overleaf/server-ce/config/custom-environment-variables.json /var/www/overleaf/services/history-v1/config/
- copy package.json file
cp /root/source/overleaf/package.json /var/www/overleaf/
- copy history-v1 production file
cp /root/source/overleaf/server-ce/config/production.json /var/www/overleaf/services/history-v1/config/production.json
- copy cron files
cp -a /root/source/overleaf/server-ce/cron /var/www/overleaf/
- copy node files
cp /root/source/overleaf/package-lock.json /var/www/overleaf/
cp /root/source/overleaf/package.json /var/www/overleaf/
- install node dependencies
cd /var/www/overleaf
NODE_ENV=production npm ci --quiet
node genScript install | bash
node genScript compile | bash
- afterwards chown files
chown -R root: /var/www/overleaf/
- go to spelling service directory and install
cd /var/www/overleaf/services/spelling
chmod +x install_deps.sh
./install_deps.sh
/etc/nginx/sites-available/overleaf
server {
listen 443 ssl;
server_name _; # Catch all, see http://nginx.org/en/docs/http/server_names.html
root /var/www/overleaf/services/web/public/;
server_name _;
ssl_certificate /etc/ssl/certs/overleaf.example.com.crt;
ssl_certificate_key /etc/ssl/private/overleaf.example.com.key;
ssl_protocols TLSv1.2;
ssl_prefer_server_ciphers on;
# used cloudflares ciphers https://github.com/cloudflare/sslconfig/blob/master/conf
ssl_ciphers EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
# config to enable HSTS(HTTP Strict Transport Security) https://developer.mozilla.org/en-US/docs/Security/HTTP_Strict_Transport_Security
# to avoid ssl stripping https://en.wikipedia.org/wiki/SSL_stripping#SSL_stripping
add_header Strict-Transport-Security "max-age=31536000; includeSubdomains;";
server_tokens off;
add_header X-Frame-Options SAMEORIGIN;
add_header X-Content-Type-Options nosniff;
client_max_body_size 50M;
location / {
proxy_pass http://127.0.0.1:4000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 10m;
proxy_send_timeout 10m;
}
location /socket.io {
proxy_pass http://127.0.0.1:3026;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_read_timeout 10m;
proxy_send_timeout 10m;
}
location /stylesheets {
expires 1y;
}
location /minjs {
expires 1y;
}
location /img {
expires 1y;
}
# handle output files for specific users
location ~ ^/project/([0-9a-f]+)/user/([0-9a-f]+)/build/([0-9a-f-]+)/output/output\.([a-z]+)$ {
proxy_pass http://127.0.0.1:8080; # clsi-nginx.conf
proxy_http_version 1.1;
}
# handle output files for anonymous users
location ~ ^/project/([0-9a-f]+)/build/([0-9a-f-]+)/output/output\.([a-z]+)$ {
proxy_pass http://127.0.0.1:8080; # clsi-nginx.conf
proxy_http_version 1.1;
}
# PDF range for specific users
location ~ ^/project/([0-9a-f]+)/user/([0-9a-f]+)/content/([0-9a-f-]+/[0-9a-f]+)$ {
proxy_pass http://127.0.0.1:8080; # clsi-nginx.conf
proxy_http_version 1.1;
}
# PDF range for anonymous users
location ~ ^/project/([0-9a-f]+)/content/([0-9a-f-]+/[0-9a-f]+)$ {
proxy_pass http://127.0.0.1:8080; # clsi-nginx.conf
proxy_http_version 1.1;
}
# Load any extra configuration for this vhost
include /etc/nginx/vhost-extras/overleaf/*.conf;
}
- change server name
- create SSL certs and replace dummy certs
- enable config
ln -s /etc/nginx/sites-available/overleaf /etc/nginx/sites-enabled/
- copy the config over from source:
cp /root/source/overleaf/server-ce/nginx/clsi-nginx.conf /etc/nginx/sites-available/clsi
- replace the port
sed -i 's/8080/127.0.0.1:8080/g' /etc/nginx/sites-available/clsi
- activate the config
ln -s /etc/nginx/sites-available/clsi /etc/nginx/sites-enabled/
all microservivces are going to get started/stopped by supervisor
- create supervisor app configs
for service in chat clsi contacts docstore document-updater filestore history-v1 notifications project-history real-time spelling; do cat > /etc/supervisor/conf.d/overleaf-${service}.conf <<EOF
[program:overleaf-${service}]
command=bash -c "source /etc/overleaf/env.sh && cd /var/www/overleaf/services/${service} && node --expose-gc app.js"
autostart=true
autorestart=true
exitcodes=0,2
stopsignal=QUIT
USER=overleaf
log_stdout=true
log_stderr=true
stderr_logfile=/var/log/overleaf/${service}_error.log
stdout_logfile=/var/log/overleaf/${service}_out.log
logfile_maxbytes=10MB
logfile_backups=5
EOF
done
cat > /etc/supervisor/conf.d/overleaf-web.conf <<EOF
[program:overleaf-web]
environment=WEB_PORT=4000
command=bash -c "source /etc/overleaf/env.sh && cd /var/www/overleaf/services/web && node --expose-gc app.js"
autostart=true
autorestart=true
exitcodes=0,2
stopsignal=QUIT
USER=overleaf
log_stdout=true
log_stderr=true
stderr_logfile=/var/log/overleaf/web_error.log
stdout_logfile=/var/log/overleaf/web_out.log
logfile_maxbytes=10MB
logfile_backups=5
EOF
cat > /etc/supervisor/conf.d/overleaf-web-api.conf <<EOF
[program:overleaf-web-api]
command=bash -c "source /etc/overleaf/env.sh && cd /var/www/overleaf/services/web && node --expose-gc app.js"
autostart=true
autorestart=true
exitcodes=0,2
stopsignal=QUIT
USER=overleaf
log_stdout=true
log_stderr=true
stderr_logfile=/var/log/overleaf/web-api_error.log
stdout_logfile=/var/log/overleaf/web-api_out.log
logfile_maxbytes=10MB
logfile_backups=5
EOF
- insert the env section into /etc/supervisor/supervisord.conf
[supervisord]
[...]
; env for overleaf
environment=
ADMIN_PRIVILEGE_AVAILABLE="true",
CRYPTO_RANDOM=TODO,
CYPRESS_INSTALL_BINARY="0",
DEBIAN_FRONTEND="teletype",
EMAIL_CONFIRMATION_DISABLED="true",
ENABLE_CONVERSIONS="true",
ENABLED_LINKED_FILE_TYPES="project_file,project_output_file",
GIT_BRIDGE_ENABLED="false",
HOSTNAME="overleaf.example.com",
INITRD=no,
KILL_ALL_PROCESSES_TIMEOUT="55",
KILL_PROCESS_TIMEOUT="55",
LISTEN_ADDRESS=127.0.0.1,
LOG_LEVEL=info,
NODE_CONFIG_DIR=/var/www/overleaf/services/history-v1/config,
NODE_ENV=production,
OPTIMISE_PDF=true,
OT_JWT_AUTH_KEY=TODO,
OVERLEAF_ADMIN_EMAIL='[email protected]',
OVERLEAF_APP_NAME="Overleaf Instance",
OVERLEAF_BEHIND_PROXY=true,
OVERLEAF_CONFIG="/etc/overleaf/settings.js",
OVERLEAF_MONGO_URL="mongodb://127.0.0.1/sharelatex",
OVERLEAF_REDIS_HOST=127.0.0.1,
OVERLEAF_REDIS_PORT=6379,
OVERLEAF_SECURE_COOKIE=true,
OVERLEAF_SITE_URL="https://overleaf.example.com",
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin,
REDIS_HOST=127.0.0.1,
REDIS_PORT=6379,
SITE_MAINTENANCE_FILE=/etc/overleaf/site_status,
STAGING_PASSWORD=TODO,
TEXMFVAR=/var/lib/overleaf/tmp/texmf-var,
V1_HISTORY_PASSWORD=TODO,
V1_HISTORY_URL=http://sharelatex:3100/api,
V1_HISTORY_USER=staging,
WEB_API_PASSWORD=TODO,
WEB_API_USER="overleaf",
WEB_HOST="10.42.177.100"
- replace these values with (pwgen 32 1):
- WEB_API_PASSWORD
- OT_JWT_AUTH_KEY
- CRYPTO_RANDOM
- V1_HISTORY_PASSWORD = STAGING_PASSWORD
CAUTION! value of V1_HISTORY_PASSWORD must be identical to STAGING_PASSWORD!
- update supervisor
supervisorctl reread
supervisorctl update
- now everything should work
- go to <OVERLEAF-DOMAIN>/launchpad to create your first admin user
sharing links for viewing/editing is always possible, but by default, those links always end up at the login prompt. There are two env variables controlling this behaviour:
OVERLEAF_ALLOW_ANONYMOUS_READ_AND_WRITE_SHARING
OVERLEAF_ALLOW_PUBLIC_ACCESS
possible configurations:
- if both are set to true, users can send out links for projects and everyone with this link can view/edit them (depending on the kind of link sent out).
- if
OVERLEAF_ALLOW_ANONYMOUS_READ_AND_WRITE_SHARING
is set to false andOVERLEAF_ALLOW_PUBLIC_ACCESS
to true, view links are open for everyone, but editing links are only accessible via login
- non-docker deployment: https://gist.github.com/gelim/a840a99d15cb765cb7b65105b72f00c4