From 1a9b141d835cf3bfe9bdca67f881b520975f9058 Mon Sep 17 00:00:00 2001 From: Rigel Kent Date: Tue, 3 Mar 2020 00:29:52 +0100 Subject: [PATCH] Add nginx behind traefik in docker-compose + image updates - support/docker/production/docker-compose.yml: addition of a nginx image reusing support/nginx/peertube nginx conf to improve performance, and lessen setup differences between the docker-compose install and the typical production install. - support/docker/production/docker-compose.yml: postgres 10 -> postgres 12, redis 4 -> redis 5. Postgres major updates implies manual upgrade. - support/nginx/peertube: HTTP -> HTTPS redirection is now commented by default, to allow its reuse in support/docker/production/docker-compose.yml. --- support/doc/production.md | 3 +- support/docker/production/Dockerfile.buster | 4 +- support/docker/production/Dockerfile.nginx | 8 +++ support/docker/production/config/traefik.toml | 2 +- support/docker/production/docker-compose.yml | 72 +++++++++++++------ support/docker/production/entrypoint.nginx.sh | 17 +++++ .../{docker-entrypoint.sh => entrypoint.sh} | 0 support/nginx/peertube | 42 ++++++----- 8 files changed, 99 insertions(+), 49 deletions(-) create mode 100644 support/docker/production/Dockerfile.nginx create mode 100644 support/docker/production/entrypoint.nginx.sh rename support/docker/production/{docker-entrypoint.sh => entrypoint.sh} (100%) diff --git a/support/doc/production.md b/support/doc/production.md index b8877ca8b..0ee275e9e 100644 --- a/support/doc/production.md +++ b/support/doc/production.md @@ -100,7 +100,8 @@ Then set the domain for the webserver configuration file. Replace `[peertube-domain]` with the domain for the peertube server. ``` -$ sudo sed -i 's/peertube.example.com/[peertube-domain]/g' /etc/nginx/sites-available/peertube +$ sudo sed -i 's/${WEBSERVER_HOST}/[peertube-domain]/g' /etc/nginx/sites-available/peertube +$ sudo sed -i 's/${PEERTUBE_HOST}/localhost:9000/g' /etc/nginx/sites-available/peertube ``` Then modify the webserver configuration file. Please pay attention to the `alias` keys of the static locations. diff --git a/support/docker/production/Dockerfile.buster b/support/docker/production/Dockerfile.buster index 414bf9aac..5af8aa29a 100644 --- a/support/docker/production/Dockerfile.buster +++ b/support/docker/production/Dockerfile.buster @@ -38,8 +38,8 @@ ENV NODE_CONFIG_DIR /config VOLUME /data VOLUME /config -COPY ./support/docker/production/docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh -ENTRYPOINT ["/usr/local/bin/docker-entrypoint.sh"] +COPY ./support/docker/production/entrypoint.sh /usr/local/bin/entrypoint.sh +ENTRYPOINT ["/usr/local/bin/entrypoint.sh"] # Run the application CMD ["npm", "start"] diff --git a/support/docker/production/Dockerfile.nginx b/support/docker/production/Dockerfile.nginx new file mode 100644 index 000000000..36ae3c3bc --- /dev/null +++ b/support/docker/production/Dockerfile.nginx @@ -0,0 +1,8 @@ +FROM nginx:alpine + +COPY entrypoint.nginx.sh . +RUN chmod +x entrypoint.nginx.sh + +EXPOSE 80 +ENTRYPOINT [] +CMD ["/bin/sh", "entrypoint.nginx.sh"] \ No newline at end of file diff --git a/support/docker/production/config/traefik.toml b/support/docker/production/config/traefik.toml index 1d7d207fd..d2437fdf8 100644 --- a/support/docker/production/config/traefik.toml +++ b/support/docker/production/config/traefik.toml @@ -61,4 +61,4 @@ entryPoint = "https" # # Required # - entryPoint = "http" + entryPoint = "http" \ No newline at end of file diff --git a/support/docker/production/docker-compose.yml b/support/docker/production/docker-compose.yml index e937c8b9c..62be02467 100644 --- a/support/docker/production/docker-compose.yml +++ b/support/docker/production/docker-compose.yml @@ -2,44 +2,65 @@ version: "3.3" services: + # The reverse-proxy only does SSL termination and automatic certificate generation. You can + # replace it with any other reverse-proxy, in which case you can remove 'traefik.*' labels. reverse-proxy: image: traefik:v1.7 network_mode: "host" command: - - "--docker" # Tells Træfik to listen to docker - - "--acme.email=${TRAEFIK_ACME_EMAIL}" # Let's Encrypt ACME email - - "--acme.domains=${TRAEFIK_ACME_DOMAINS}" # Let's Encrypt ACME domain list + - "--docker" # Tells Træfik to listen to docker + - "--acme.email=${TRAEFIK_ACME_EMAIL}" # Let's Encrypt ACME email + - "--acme.domains=${TRAEFIK_ACME_DOMAINS}" # Let's Encrypt ACME domain list ports: - - "80:80" # The HTTP port - - "443:443" # The HTTPS port + - "80:80" # The HTTP port + - "443:443" # The HTTPS port volumes: - - /var/run/docker.sock:/var/run/docker.sock # So that Traefik can listen to the Docker events + - /var/run/docker.sock:/var/run/docker.sock # So that Træfik can listen to the Docker events - ./docker-volume/traefik/acme.json:/etc/acme.json - ./docker-volume/traefik/traefik.toml:/traefik.toml restart: "always" - # If you want to use the Traefik dashboard, you should expose it on a - # subdomain with HTTPS and authentification: - # https://medium.com/@xavier.priour/secure-traefik-dashboard-with-https-and-password-in-docker-5b657e2aa15f - # https://github.com/containous/traefik/issues/880#issuecomment-310301168 - peertube: - # If you don't want to use the official image and build one from sources - # build: - # context: . - # dockerfile: ./support/docker/production/Dockerfile.buster - image: chocobozzz/peertube:production-buster + # The webserver is not required, but recommended since a lot of optimizations went to its + # nginx configuration file. It runs the default nginx configuration without HTTPS nor SSL, + # so use it in production in tandem with an SSL-terminating reverse-proxy like above. + webserver: + build: + context: . + dockerfile: Dockerfile.nginx env_file: - .env - # Traefik labels are suggested as an example for people using Traefik, - # remove them if you are using another reverse proxy. + # If you provide your own reverse-proxy, otherwise not suitable for production: + #ports: + # - "80:80" + volumes: + - type: bind + # Switch sources if you downloaded the nginx configuration without the whole repository + #source: ./peertube + source: ../../nginx/peertube + target: /etc/nginx/conf.d/peertube.template + - assets:/var/www/peertube/peertube-latest/client/dist:ro + - ./docker-volume/data:/var/www/peertube/storage + depends_on: + - peertube + restart: "always" labels: traefik.enable: "true" traefik.frontend.rule: "Host:${PEERTUBE_WEBSERVER_HOSTNAME}" - traefik.port: "9000" - # If you don't want to use a reverse proxy (not suitable for production!) - # ports: - # - "80:9000" + traefik.port: "80" + + peertube: + # If you don't want to use the official image and build one from sources: + #build: + # context: . + # dockerfile: ./support/docker/production/Dockerfile.buster + image: chocobozzz/peertube:production-buster + env_file: + - .env + # If you provide your own webserver and reverse-proxy, otherwise not suitable for production: + #ports: + # - "80:9000" volumes: + - assets:/app/client/dist - ./docker-volume/data:/data - ./docker-volume/config:/config depends_on: @@ -47,6 +68,8 @@ services: - redis - postfix restart: "always" + labels: + traefik.enable: "false" postgres: image: postgres:10-alpine @@ -59,7 +82,7 @@ services: traefik.enable: "false" redis: - image: redis:4-alpine + image: redis:5-alpine volumes: - ./docker-volume/redis:/data restart: "always" @@ -82,3 +105,6 @@ networks: driver: default config: - subnet: 172.18.0.0/16 + +volumes: + assets: diff --git a/support/docker/production/entrypoint.nginx.sh b/support/docker/production/entrypoint.nginx.sh new file mode 100644 index 000000000..744385ec8 --- /dev/null +++ b/support/docker/production/entrypoint.nginx.sh @@ -0,0 +1,17 @@ +#!/bin/sh +set -e + +# Process nginx template +SOURCE="/etc/nginx/conf.d/peertube.template" +TARGET="/etc/nginx/conf.d/default.conf" +export WEBSERVER_HOST="default_server" +export PEERTUBE_HOST="peertube:9000" + +envsubst '${WEBSERVER_HOST} ${PEERTUBE_HOST}' < $SOURCE > $TARGET + +# Remove HTTPS/SSL from nginx conf +sed -i 's/443 ssl http2/80/g;/ssl_/d' $TARGET + +cat $TARGET + +nginx -g "daemon off;" \ No newline at end of file diff --git a/support/docker/production/docker-entrypoint.sh b/support/docker/production/entrypoint.sh similarity index 100% rename from support/docker/production/docker-entrypoint.sh rename to support/docker/production/entrypoint.sh diff --git a/support/nginx/peertube b/support/nginx/peertube index a17868c5a..7f2c0f263 100644 --- a/support/nginx/peertube +++ b/support/nginx/peertube @@ -1,26 +1,24 @@ -server { - listen 80; - listen [::]:80; - server_name peertube.example.com; - - access_log /var/log/nginx/peertube.example.com.access.log; - error_log /var/log/nginx/peertube.example.com.error.log; - - location /.well-known/acme-challenge/ { - default_type "text/plain"; - root /var/www/certbot; - } - location / { return 301 https://$host$request_uri; } -} +# Uncomment in production to redirect HTTP to HTTPS. Leave commented for docker-compose. +#server { +# listen 80; +# listen [::]:80; +# server_name ${WEBSERVER_HOST}; +# +# location /.well-known/acme-challenge/ { +# default_type "text/plain"; +# root /var/www/certbot; +# } +# location / { return 301 https://$host$request_uri; } +#} server { listen 443 ssl http2; listen [::]:443 ssl http2; - server_name peertube.example.com; + server_name ${WEBSERVER_HOST}; # For example with certbot (you need a certificate to run https) - ssl_certificate /etc/letsencrypt/live/peertube.example.com/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/peertube.example.com/privkey.pem; + ssl_certificate /etc/letsencrypt/live/${WEBSERVER_HOST}/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/${WEBSERVER_HOST}/privkey.pem; # Security hardening (as of 11/02/2018) ssl_protocols TLSv1.2; # TLSv1.3, TLSv1.2 if nginx >= 1.13.0 @@ -51,8 +49,8 @@ server { # See https://nginx.org/en/docs/http/ngx_http_core_module.html#client_body_temp_path # client_body_temp_path /var/www/peertube/storage/nginx/; - access_log /var/log/nginx/peertube.example.com.access.log; - error_log /var/log/nginx/peertube.example.com.error.log; + access_log /var/log/nginx/${WEBSERVER_HOST}.access.log; + error_log /var/log/nginx/${WEBSERVER_HOST}.error.log; location ^~ '/.well-known/acme-challenge' { default_type "text/plain"; @@ -92,7 +90,7 @@ server { } location / { - proxy_pass http://127.0.0.1:9000; + proxy_pass http://${PEERTUBE_HOST}; proxy_set_header X-Real-IP $remote_addr; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; @@ -177,14 +175,14 @@ server { proxy_http_version 1.1; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $host; - proxy_pass http://127.0.0.1:9000; + proxy_pass http://${PEERTUBE_HOST}; } location /socket.io { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $host; - proxy_pass http://127.0.0.1:9000; + proxy_pass http://${PEERTUBE_HOST}; # enable WebSockets proxy_http_version 1.1; -- 2.41.0