1
0
Fork 0
mirror of https://github.com/overleaf/toolkit.git synced 2025-04-19 07:18:06 +02:00

Merge pull request #48 from overleaf/csh-issue-4216-toolkit-ssl-proxy

Add a TLS proxy option to the Toolkit
This commit is contained in:
Christopher Hoskin 2021-05-10 15:42:31 +01:00 committed by GitHub
commit 85f960a204
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 251 additions and 32 deletions

View file

@ -22,6 +22,7 @@ function __main__() {
SHARELATEX_IMAGE_VERSION="$(head -n 1 "$TOOLKIT_ROOT/config/version")"
local MONGO_IMAGE="mongo:4.0"
local REDIS_IMAGE="redis:5.0"
local NGINX_IMAGE="nginx:1.19-alpine"
local MONGO_URL="mongodb://mongo/sharelatex"
local REDIS_HOST="redis"
@ -48,6 +49,10 @@ function __main__() {
if [[ "$SIBLING_CONTAINERS_ENABLED" == "true" ]]; then
compose_file_flags+=("-f $TOOLKIT_ROOT/lib/docker-compose.sibling-containers.yml")
fi
if [[ "${NGINX_ENABLED:-false}" == "true" ]]; then
compose_file_flags+=("-f $TOOLKIT_ROOT/lib/docker-compose.nginx.yml")
fi
# Include docker-compose.override.yml if it is present
if [[ -f "$TOOLKIT_ROOT/config/docker-compose.override.yml" ]]; then
@ -68,7 +73,15 @@ function __main__() {
SHARELATEX_DATA_PATH=$(cd "$TOOLKIT_ROOT"; realpath "$SHARELATEX_DATA_PATH")
MONGO_DATA_PATH=$(cd "$TOOLKIT_ROOT"; realpath "$MONGO_DATA_PATH")
REDIS_DATA_PATH=$(cd "$TOOLKIT_ROOT"; realpath "$REDIS_DATA_PATH")
if [[ -n "${TLS_PRIVATE_KEY_PATH-}" ]]; then
TLS_PRIVATE_KEY_PATH=$(cd "$TOOLKIT_ROOT"; realpath "$TLS_PRIVATE_KEY_PATH")
fi
if [[ -n "${TLS_CERTIFICATE_PATH-}" ]]; then
TLS_CERTIFICATE_PATH=$(cd "$TOOLKIT_ROOT"; realpath "$TLS_CERTIFICATE_PATH")
fi
if [[ -n "${NGINX_CONFIG_PATH-}" ]]; then
NGINX_CONFIG_PATH=$(cd "$TOOLKIT_ROOT"; realpath "$NGINX_CONFIG_PATH")
fi
# Print debug info
if [[ "${RC_DEBUG:-null}" != "null" ]]; then
echo ">>>>>>VARS>>>>>>"
@ -83,17 +96,22 @@ function __main__() {
fi
# Export vars for use in docker-compose files
export IMAGE="$full_image_spec"
export SHARELATEX_DATA_PATH
export SHARELATEX_PORT
export DOCKER_SOCKET_PATH
export MONGO_IMAGE
export IMAGE="$full_image_spec"
export MONGO_DATA_PATH
export MONGO_IMAGE
export MONGO_URL
export REDIS_IMAGE
export NGINX_CONFIG_PATH
export NGINX_IMAGE
export REDIS_DATA_PATH
export REDIS_HOST
export REDIS_IMAGE
export REDIS_PORT
export SHARELATEX_DATA_PATH
export SHARELATEX_PORT
export TLS_CERTIFICATE_PATH
export TLS_PORT
export TLS_PRIVATE_KEY_PATH
# shellcheck disable=SC2068
exec docker-compose -p "$project_name" ${compose_file_flags[@]} "$@"

View file

@ -76,6 +76,8 @@ function check_dependencies() {
bash -c 'echo $BASH_VERSION'
elif [[ "perl" == "$binary_name" ]]; then
perl -e 'print $];'
elif [[ "openssl" == "$binary_name" ]]; then
openssl version
elif [[ "awk" == "$binary_name" ]]; then
if awk -Wversion > /dev/null 2>&1; then
awk -Wversion 2>&1 | head -n 1
@ -115,6 +117,7 @@ function check_dependencies() {
realpath
perl
awk
openssl
)
for binary in "${binaries[@]}"; do
@ -225,6 +228,17 @@ function check_config_files() {
if [[ "${REDIS_DATA_PATH:-null}" != "null" ]]; then
print_point 2 "REDIS_DATA_PATH: $REDIS_DATA_PATH"
fi
print_point 2 "NGINX_ENABLED: ${NGINX_ENABLED:-null}"
if [[ "${NGINX_CONFIG_PATH:-null}" != "null" ]]; then
print_point 2 "NGINX_CONFIG_PATH: $NGINX_CONFIG_PATH"
fi
if [[ "${TLS_PRIVATE_KEY_PATH:-null}" != "null" ]]; then
print_point 2 "TLS_PRIVATE_KEY_PATH: $TLS_PRIVATE_KEY_PATH"
fi
if [[ "${TLS_CERTIFICATE_PATH:-null}" != "null" ]]; then
print_point 2 "TLS_CERTIFICATE_PATH: $TLS_CERTIFICATE_PATH"
fi
fi
fi
done

View file

@ -16,35 +16,89 @@ if [[ ! -d "$TOOLKIT_ROOT/bin" ]] || [[ ! -d "$TOOLKIT_ROOT/config" ]]; then
fi
function usage() {
echo "Usage: bin/init"
echo ""
echo "Initialises local configuration files in the 'config/' directory"
echo ""
echo "Usage: bin/init [OPTION]"
echo ""
echo "Initialises local configuration files in the 'config/' directory"
echo ""
echo "--help display this help and exit"
echo "--tls Initialises local configuration with NGINX config, or"
echo " adds NGINX config to an existing local configuration"
}
function check_existing_config() {
if [[ -f "$TOOLKIT_ROOT/config/overleaf.rc" ]] \
|| [[ -f "$TOOLKIT_ROOT/config/variables.env" ]] \
|| [[ -f "$TOOLKIT_ROOT/config/version" ]]; then
echo "ERROR: Config files already exist, exiting "
exit 1
fi
function config_exists() {
[ -f "$TOOLKIT_ROOT/config/overleaf.rc" ] \
|| [ -f "$TOOLKIT_ROOT/config/variables.env" ] \
|| [ -f "$TOOLKIT_ROOT/config/version" ]
}
function tls_config_exists() {
[ -f "$TOOLKIT_ROOT/config/nginx/nginx.conf" ] \
|| [ -f "$TOOLKIT_ROOT/config/nginx/certs/overleaf_certificate.pem" ] \
|| [ -f "$TOOLKIT_ROOT/config/nginx/certs/overleaf_key.pem" ]
}
function set_up_config_files() {
echo "Copying config files to 'config/'"
cp "$TOOLKIT_ROOT/lib/config-seed/overleaf.rc" "$TOOLKIT_ROOT/config/"
cp "$TOOLKIT_ROOT/lib/config-seed/variables.env" "$TOOLKIT_ROOT/config/"
cp "$TOOLKIT_ROOT/lib/config-seed/version" "$TOOLKIT_ROOT/config/"
echo "Copying config files to 'config/'"
cp "$TOOLKIT_ROOT/lib/config-seed/overleaf.rc" "$TOOLKIT_ROOT/config/"
cp "$TOOLKIT_ROOT/lib/config-seed/variables.env" "$TOOLKIT_ROOT/config/"
cp "$TOOLKIT_ROOT/lib/config-seed/version" "$TOOLKIT_ROOT/config/"
}
function set_up_tls_proxy() {
PRIVATE_KEY="$TOOLKIT_ROOT/config/nginx/certs/overleaf_key.pem"
CERT_SIGN_REQ="$TOOLKIT_ROOT/config/nginx/certs/overleaf_csr.pem"
CERT="$TOOLKIT_ROOT/config/nginx/certs/overleaf_certificate.pem"
echo "Generate example self-signed TLS cert"
mkdir -p config/nginx/certs
cp "$TOOLKIT_ROOT/lib/config-seed/nginx.conf" "$TOOLKIT_ROOT/config/nginx/"
openssl req -new -nodes -keyout "$PRIVATE_KEY" -out "$CERT_SIGN_REQ" -batch
chmod 600 "$PRIVATE_KEY"
openssl x509 -req -days 365 -in "$CERT_SIGN_REQ" -signkey "$PRIVATE_KEY" -out "$CERT"
}
HELP=false
TLS=false
function __main__() {
if [[ "${1:-null}" == "help" ]] || [[ "${1:-null}" == "--help" ]]; then
usage
while [[ $# -gt 0 ]] ; do
case "$1" in
help | --help )
HELP=true
shift
;;
--tls )
TLS=true
shift
;;
*)
echo "Unrecognised option $1"
exit
;;
esac
done
if [[ "$HELP" == "true" ]]; then
usage
exit
fi
if [[ "$TLS" == "true" ]]; then
if tls_config_exists; then
echo "ERROR: TLS config files already exist, exiting"
exit 1
else
set_up_tls_proxy
fi
check_existing_config
fi
if config_exists; then
if [[ "$TLS" == "true" ]]; then
echo "Config files already exist, exiting"
exit 0
else
echo "ERROR: Config files already exist, exiting"
exit 1
fi
else
set_up_config_files
fi
}
__main__ "$@"

View file

@ -23,6 +23,7 @@ documentation on the [Overleaf Wiki](https://github.com/overleaf/overleaf/wiki)
- [Configuration Overview](./configuration.md)
- [overleaf.rc](./overleaf-rc.md)
- [TLS proxy](./tls-proxy.md)
## Persistent Data

View file

@ -13,4 +13,4 @@ with `brew install coreutils`, to get a working version of `realpath`.
## Host Environment
The Overleaf toolkit is tested on Ubuntu Linux, but we expect that most modern Linux systems will be able to run the toolkit without problems. Although it is possible to run the toolkit on other platforms, they are not officially supported.
The Overleaf Toolkit is tested on Ubuntu Linux, but we expect that most modern Linux systems will be able to run the toolkit without problems. Although it is possible to run the toolkit on other platforms, they are not officially supported.

View file

@ -1,6 +1,6 @@
# Working with Docker-Compose Services
The Overleaf toolkit runs Overleaf inside a docker container, plus the
The Overleaf Toolkit runs Overleaf inside a docker container, plus the
supporting databases (MongoDB and Redis), in their own containers. All of this
is orchestrated with `docker-compose`.

View file

@ -27,6 +27,8 @@ Sets the path to the directory that will be mounted into the main `sharelatex` c
Sets the host port that the container will bind to. For example, if this is set to `8099`, then the web interface will be available on `http://localhost:8099`.
When used in conjunction with the [TLS Proxy](tls-proxy.md), the `proxy_pass` port in [nginx.conf](config/nginx/nginx.conf) also needs to be changed.
- Default: 80
@ -106,3 +108,33 @@ Specifies the Redis port to use when `REDIS_ENABLED` is `false`
Sets the path to the directory that will be mounted into the `redis` container, and used to store the Redis database. This can be either a full path (beginning with a `/`), or relative to the base directory of the toolkit. This option only affects the local `redis` container that is created when `REDIS_ENABLED` is `true`.
- Default: data/redis
### `NGINX_ENABLED`
When set to `true`, tells the toolkit to create an NGINX container, to act as a [TLS Proxy](tls-proxy.md).
- Default: false
### `NGINX_CONFIG_PATH`
Path to the NGINX config file to use for the [TLS Proxy](tls-proxy.md).
- Default: config/nginx/nginx.conf
### `TLS_PRIVATE_KEY_PATH`
Path to the private key to use for the [TLS Proxy](tls-proxy.md).
- Default: config/nginx/certs/overleaf_key.pem
### `TLS_CERTIFICATE_PATH`
Path to the public certificate to use for the [TLS Proxy](tls-proxy.md).
- Default: config/nginx/certs/overleaf_certificate.pem
### `TLS_PORT`
Sets the host port that the [TLS Proxy](tls-proxy.md) container will bind to. For example, if this is set to `8443`, then the https web interface will be available on `https://localhost:8443`.
- Default: 443

View file

@ -1,6 +1,6 @@
# Persistent Data Overview
The Overleaf toolkit needs to store persistent data, such as the files required to compile LaTeX projects, and the contents of the MongoDB database. This is achieved by mounting a few directories from the host machine into the docker containers, and writing the data to those directories.
The Overleaf Toolkit needs to store persistent data, such as the files required to compile LaTeX projects, and the contents of the MongoDB database. This is achieved by mounting a few directories from the host machine into the docker containers, and writing the data to those directories.
## Data Directories

View file

@ -2,7 +2,7 @@
## Prerequisites
The overleaf toolkit depends on the following programs:
The Overleaf Toolkit depends on the following programs:
- bash
- docker
@ -76,7 +76,7 @@ These are the three configuration files you will interact with:
## Starting Up
The overleaf toolkit uses `docker-compose` to manage the overleaf docker containers. The toolkit provides a set of scripts which wrap `docker-compose`, and take care of most of the details for you.
The Overleaf Toolkit uses `docker-compose` to manage the overleaf docker containers. The toolkit provides a set of scripts which wrap `docker-compose`, and take care of most of the details for you.
Let's start the docker services:
@ -123,6 +123,17 @@ You can also look at the logs for multiple services at once:
$ bin/logs -f filestore docstore web clsi
```
## TLS Proxy
The Overleaf Toolkit includes optional configuration to run an NGINX proxy, which presents Server Pro over HTTPS. Initial configuration can be generated by running
```
bin/init --tls
```
This creates minimal NGINX config in `config/nginx/nginx.conf` and a sample TLS certificate and private key in `config/nginx/certs/overleaf_certificate.pem` and `config/nginx/certs/overleaf_key.pem` respectively. If you already have a signed TLS certificate for use with Server Pro, replace the sample key and certificate with your key and certificate.
In order to run the proxy, change the value of the `NGINX_ENABLED` variable in `config/overleaf.rc` from `false` to `true` and re-run `bin/up`.
Further information about the TLS proxy can be found in the [docs](tls-proxy.md).
## Consulting the Doctor

View file

@ -1,6 +1,6 @@
# The Doctor
The Overleaf toolkit comes with a handy `doctor` script, to help with debugging. Just run `bin/doctor` and the script will print out information about your host environment, your configuration, and the dependencies the toolkit needs. This output can also help the Overleaf support team to help you figure out what has gone wrong, in the case of a Server Pro installation.
The Overleaf Toolkit comes with a handy `doctor` script, to help with debugging. Just run `bin/doctor` and the script will print out information about your host environment, your configuration, and the dependencies the toolkit needs. This output can also help the Overleaf support team to help you figure out what has gone wrong, in the case of a Server Pro installation.
## Getting Help

29
doc/tls-proxy.md Normal file
View file

@ -0,0 +1,29 @@
## TLS Proxy for Overleaf Toolkit environment
An optional TLS proxy for terminating https connections, based on NGINX.
Run `bin/init --tls` to initialise local configuration with NGINX proxy configuration, or to add NGINX proxy configuration to an existing local configuration. A sample private key is created in `config/nginx/certs/overleaf_key.pem` and a dummy certificate in `config/nginx/certs/overleaf_certificate.pem`. Either replace these with your actual private key and certificate, or set the values of the `TLS_PRIVATE_KEY_PATH` and `TLS_CERTIFICATE_PATH` variables to the paths of your actual private key and certificate respectively.
A default config for NGINX is provided in `config/nginx/nginx.conf` which may be customised to your requirements. The path to the config file can be changed with the `NGINX_CONFIG_PATH` variable.
In order for Overleaf to run correctly behind the proxy, the following variables should be uncommented in `config/variables.env`
```
SHARELATEX_BEHIND_PROXY=true
SHARELATEX_SECURE_COOKIE=true
```
Add the following section to your `config/overleaf.rc` file if it is not there already:
```
# TLS proxy configuration (optional)
# See documentation in doc/tls-proxy.md
NGINX_ENABLED=false
NGINX_CONFIG_PATH=config/nginx/nginx.conf
TLS_PRIVATE_KEY_PATH=config/nginx/certs/overleaf_key.pem
TLS_CERTIFICATE_PATH=config/nginx/certs/overleaf_certificate.pem
TLS_PORT=443
```
In order to run the proxy, change the value of the `NGINX_ENABLED` variable in `config/overleaf.rc` from `false` to `true` and re-run `bin/up`.
When the [SHARELATEX_PORT](overleaf-rc.md#sharelatex_port) variable is set, the port in the `proxy_pass` statement in `nginx.conf` needs to be changed to match.
By default the https web interface will be available on `https://localhost:443`. The port can be changed via the `TLS_PORT` variable.

View file

@ -0,0 +1,35 @@
events {}
http {
server {
listen 443 ssl;
ssl_certificate /certs/nginx_certificate.pem;
ssl_certificate_key /certs/nginx_key.pem;
ssl_protocols TLSv1 TLSv1.1 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;
client_max_body_size 50M;
location / {
proxy_pass http://sharelatex:80; # The port must match the value of SHARELATEX_PORT.
proxy_set_header X-Forwarded-Proto $scheme;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_read_timeout 3m;
proxy_send_timeout 3m;
}
}
}

View file

@ -18,3 +18,11 @@ MONGO_DATA_PATH=data/mongo
# Redis configuration
REDIS_ENABLED=true
REDIS_DATA_PATH=data/redis
# TLS proxy configuration (optional)
# See documentation in doc/tls-proxy.md
NGINX_ENABLED=false
NGINX_CONFIG_PATH=config/nginx/nginx.conf
TLS_PRIVATE_KEY_PATH=config/nginx/certs/overleaf_key.pem
TLS_CERTIFICATE_PATH=config/nginx/certs/overleaf_certificate.pem
TLS_PORT=443

View file

@ -16,8 +16,9 @@ TEXMFVAR=/var/lib/sharelatex/tmp/texmf-var
# NGINX_WORKER_PROCESSES=4
# NGINX_WORKER_CONNECTIONS=768
## Set for SSL via nginx-proxy
#VIRTUAL_HOST=103.112.212.22
## Set for TLS via nginx-proxy
# SHARELATEX_BEHIND_PROXY=true
# SHARELATEX_SECURE_COOKIE=true
# SHARELATEX_SITE_URL=http://overleaf.example.com
# SHARELATEX_NAV_TITLE=Our Overleaf Instance

View file

@ -0,0 +1,16 @@
---
version: '2.2'
services:
nginx:
image: "${NGINX_IMAGE}"
ports:
- "127.0.0.1:${TLS_PORT:-443}:443"
volumes:
- "${TLS_PRIVATE_KEY_PATH}:/certs/nginx_key.pem:ro"
- "${TLS_CERTIFICATE_PATH}:/certs/nginx_certificate.pem:ro"
- "${NGINX_CONFIG_PATH}:/etc/nginx/nginx.conf:ro"
restart: always
container_name: nginx
depends_on:
- sharelatex