From 2a2bb6b1c169ace47f3fa5105eb8a0a5fc4cd056 Mon Sep 17 00:00:00 2001 From: Martin Kleinschrodt Date: Tue, 12 Apr 2022 14:59:17 +0200 Subject: [PATCH] Add examples of docker-based hosting setup --- Dockerfile-pwa | 11 ++- Dockerfile-server | 18 ++-- docs/examples/hosting/docker/basic/README.md | 17 ++++ .../hosting/docker/basic/docker-compose.yml | 34 ++++++++ docs/examples/hosting/docker/nginx/README.md | 21 +++++ .../hosting/docker/nginx/docker-compose.yml | 46 +++++++++++ docs/examples/hosting/docker/nginx/nginx.conf | 50 +++++++++++ .../postgres-nginx-letsencrypt/README.md | 43 ++++++++++ .../docker-compose.yml | 82 +++++++++++++++++++ .../postgres-nginx-letsencrypt/get-cert.sh | 6 ++ .../postgres-nginx-letsencrypt/nginx.conf | 64 +++++++++++++++ 11 files changed, 373 insertions(+), 19 deletions(-) create mode 100644 docs/examples/hosting/docker/basic/README.md create mode 100644 docs/examples/hosting/docker/basic/docker-compose.yml create mode 100644 docs/examples/hosting/docker/nginx/README.md create mode 100644 docs/examples/hosting/docker/nginx/docker-compose.yml create mode 100644 docs/examples/hosting/docker/nginx/nginx.conf create mode 100644 docs/examples/hosting/docker/postgres-nginx-letsencrypt/README.md create mode 100644 docs/examples/hosting/docker/postgres-nginx-letsencrypt/docker-compose.yml create mode 100644 docs/examples/hosting/docker/postgres-nginx-letsencrypt/get-cert.sh create mode 100644 docs/examples/hosting/docker/postgres-nginx-letsencrypt/nginx.conf diff --git a/Dockerfile-pwa b/Dockerfile-pwa index 34e535e9..fca69310 100644 --- a/Dockerfile-pwa +++ b/Dockerfile-pwa @@ -1,11 +1,9 @@ -FROM node:16 - -ENV PL_PWA_PORT=8080 -ENV PL_PWA_DIR=/pwa +FROM node:16-bullseye EXPOSE 8080 -VOLUME ["/pwa"] +ENV PL_ASSETS_DIR=/assets +ENV PL_PWA_DIR=/pwa WORKDIR /padloc @@ -33,8 +31,9 @@ COPY packages/core/tsconfig.json ./packages/core/ COPY packages/locale/src ./packages/locale/src COPY packages/locale/res ./packages/locale/res COPY packages/locale/tsconfig.json ./packages/locale/ +COPY assets /assets -WORKDIR packages/pwa +WORKDIR /padloc/packages/pwa ENTRYPOINT ["npm", "run"] diff --git a/Dockerfile-server b/Dockerfile-server index 5a74b96d..a7ceb5ad 100644 --- a/Dockerfile-server +++ b/Dockerfile-server @@ -1,16 +1,9 @@ -FROM node:16 - -ENV PL_SERVER_PORT=3000 -ENV PL_BILLING_PORT=4000 -ENV PL_DB_PATH=/data -ENV PL_ATTACHMENTS_PATH=/attachments -ENV PL_LOG_DIR=/logs -ENV PL_REPL_HISTORY=.pl_repl_history +FROM node:16.13.1 EXPOSE 3000 -EXPOSE 4000 -VOLUME ["/data", "/attachments", "/logs"] +ENV PL_ASSETS_DIR=/assets +ENV PL_ATTACHMENTS_DIR=/attachments WORKDIR /padloc @@ -34,10 +27,9 @@ COPY packages/core/tsconfig.json ./packages/core/ COPY packages/locale/src ./packages/locale/src COPY packages/locale/res ./packages/locale/res COPY packages/locale/tsconfig.json ./packages/locale/ +COPY assets /assets -COPY packages/server/do-ca.crt ./packages/server/ - -WORKDIR packages/server +WORKDIR /padloc/packages/server ENTRYPOINT ["npm", "run"] diff --git a/docs/examples/hosting/docker/basic/README.md b/docs/examples/hosting/docker/basic/README.md new file mode 100644 index 00000000..b1563709 --- /dev/null +++ b/docs/examples/hosting/docker/basic/README.md @@ -0,0 +1,17 @@ +# Basic Docker Example + +This is a basic example of running an instance of the Padloc server component +and web app via Docker + Docker Compose. + +## Setup Instructions + +0. Install [Docker](https://docs.docker.com/get-docker/) and + [Docker Compose](https://docs.docker.com/compose/install/): +1. Clone or download this folder and `cd` into it. +2. Start the server and pwa: + + ```sh + docker-compose up + ``` + +Thats it! The web app is now available at http://localhost:8080. diff --git a/docs/examples/hosting/docker/basic/docker-compose.yml b/docs/examples/hosting/docker/basic/docker-compose.yml new file mode 100644 index 00000000..9f66d7a2 --- /dev/null +++ b/docs/examples/hosting/docker/basic/docker-compose.yml @@ -0,0 +1,34 @@ +version: "3.7" +services: + server: + image: padloc/server + build: + context: github.com/padloc/padloc.git#docs/docker-examples + dockerfile: Dockerfile-server + depends_on: + - db + environment: + PL_DATA_BACKEND: leveldb + PL_DATA_LEVELDB_DIR: /data + PL_DATA_ATTACHMENTS_BACKEND: fs + PL_DATA_ATTACHMENTS_DIR: /attachments + PL_SERVER_CLIENT_URL: http://localhost:8080 + ports: + - 3000:3000 + volumes: + - attachments:/attachments + - data:/data + restart: unless-stopped + pwa: + image: padloc/pwa + build: + context: github.com/padloc/padloc.git#docs/docker-examples + dockerfile: Dockerfile-pwa + environment: + PL_SERVER_URL: http://localhost:3000 + ports: + - 8080:8080 + restart: on-failure +volumes: + data: + attachments: diff --git a/docs/examples/hosting/docker/nginx/README.md b/docs/examples/hosting/docker/nginx/README.md new file mode 100644 index 00000000..207c21c1 --- /dev/null +++ b/docs/examples/hosting/docker/nginx/README.md @@ -0,0 +1,21 @@ +# Docker + NGINX + +This is a basic example of running an instance of the Padloc server component +and web app with Docker Compose, using [NGINX](https://www.nginx.com/) as a +reverse proxy. + +This is a basic example of running an instance of the Padloc server component +and web app via Docker + Docker Compose. + +## Setup Instructions + +0. Install [Docker](https://docs.docker.com/get-docker/) and + [Docker Compose](https://docs.docker.com/compose/install/) +1. Clone or download this folder and `cd` into it. +2. Start the server and pwa: + + ```sh + docker-compose up + ``` + +Thats it! The web app is now available at http://localhost. diff --git a/docs/examples/hosting/docker/nginx/docker-compose.yml b/docs/examples/hosting/docker/nginx/docker-compose.yml new file mode 100644 index 00000000..a38d0458 --- /dev/null +++ b/docs/examples/hosting/docker/nginx/docker-compose.yml @@ -0,0 +1,46 @@ +version: "3.7" +services: + server: + image: padloc/server + build: + context: github.com/padloc/padloc.git#docs/docker-examples + dockerfile: Dockerfile-server + depends_on: + - db + environment: + PL_DATA_BACKEND: leveldb + PL_DATA_LEVELDB_DIR: /data + PL_DATA_ATTACHMENTS_BACKEND: fs + PL_DATA_ATTACHMENTS_DIR: /attachments + PL_SERVER_CLIENT_URL: http://localhost + expose: + - 3000 + volumes: + - attachments:/attachments + - data:/data + restart: unless-stopped + pwa: + image: padloc/pwa + environment: + PL_SERVER_URL: http://localhost/server + build: + context: github.com/padloc/padloc.git#docs/docker-examples + dockerfile: Dockerfile-pwa + volumes: + - pwa:/pwa + command: ["build"] + restart: on-failure + nginx: + image: nginx + depends_on: + - server + restart: always + volumes: + - pwa:/pwa + - ./nginx.conf:/etc/nginx/nginx.conf + ports: + - 80:80 +volumes: + data: + attachments: + pwa: diff --git a/docs/examples/hosting/docker/nginx/nginx.conf b/docs/examples/hosting/docker/nginx/nginx.conf new file mode 100644 index 00000000..a202342d --- /dev/null +++ b/docs/examples/hosting/docker/nginx/nginx.conf @@ -0,0 +1,50 @@ +user nginx; +worker_processes auto; + +http { + # BASIC SETTINGS + sendfile on; + tcp_nopush on; + tcp_nodelay on; + keepalive_timeout 65; + + types_hash_max_size 2048; + + # Required for attachments + client_max_body_size 10m; + + # Enable gzip + gzip on; + gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; + + include mime.types; + + # Disallow embedding in iFrames + add_header X-Frame-Options deny; + + server { + # We don't need a host name here since we're only + # dealing with one domain, but you may insert your domain here. + server_name _; + + # Both server and pwa are served over https + listen 80; + + # This will resolve to the server instance + location /server { + resolver 127.0.0.11 valid=60s; + set $server "http://server:3000"; + proxy_pass $server; + } + + # This will resolve to the web app + location / { + root /pwa; + index index.html; + try_files $uri /index.html; + } + } +} + +events { +} diff --git a/docs/examples/hosting/docker/postgres-nginx-letsencrypt/README.md b/docs/examples/hosting/docker/postgres-nginx-letsencrypt/README.md new file mode 100644 index 00000000..f81e2946 --- /dev/null +++ b/docs/examples/hosting/docker/postgres-nginx-letsencrypt/README.md @@ -0,0 +1,43 @@ +# Docker + Postgres + NGINX + Letsencrypt + +This is a more advanced example of running an instance of the Padloc server +component and web app with [Docker](https://www.docker.com/) and +[Docker Compose](https://docs.docker.com/compose/), using: + +- [PostgreSQL](https://www.postgresql.org/) as the datababase backend +- [NGINX](https://www.nginx.com/) as a reverse proxy. +- [Letsencrypt](https://letsencrypt.org/) for obtaining a TLS certificate. + +## Setup Instructions + +0. Install [Docker](https://docs.docker.com/get-docker/) and + [Docker Compose](https://docs.docker.com/compose/install/) +1. Clone or download this folder and `cd` into it. +2. Edit the `.env` file to set your STMP settings, Postgres database name, + username and password, and the host name / domain you want to host the web + app and server under. + +3. Obtain an TLS certificate + + ```sh + docker-compose up cerbot + ``` + +4. Start the server, pwa, database and reverse proxy: + + ```sh + docker-compose up -d + ``` + +Thats it! The web app is now available at `https://$PL_HOSTNAME` + +## Renewing the TLS certificate + +TLS certificates issued by Letsencrypt are usually valid for 90 days, so you'll +have to regularly renew your certificate. To do so, simply run the following: + +```sh +docker-compose down && \ +docker-compose up certbot && \ +docker-compose up -d +``` diff --git a/docs/examples/hosting/docker/postgres-nginx-letsencrypt/docker-compose.yml b/docs/examples/hosting/docker/postgres-nginx-letsencrypt/docker-compose.yml new file mode 100644 index 00000000..ed736d33 --- /dev/null +++ b/docs/examples/hosting/docker/postgres-nginx-letsencrypt/docker-compose.yml @@ -0,0 +1,82 @@ +version: "3.7" +services: + db: + image: postgres:13 + expose: + - 5432 + environment: + - POSTGRES_USER=$PL_DATA_POSTGRES_USER + - POSTGRES_DB=$PL_DATA_POSTGRES_DATABASE + - POSTGRES_PASSWORD=$PL_DATA_POSTGRES_PASSWORD + volumes: + - data:/var/lib/postgresql/data + restart: unless-stopped + server: + image: padloc/server + build: + context: github.com/padloc/padloc.git#docs/docker-examples + dockerfile: Dockerfile-server + depends_on: + - db + environment: + - PL_DATA_BACKEND=postgres + - PL_DATA_POSTGRES_HOST=db + - PL_DATA_POSTGRES_PORT=5432 + - PL_DATA_POSTGRES_DATABASE + - PL_DATA_POSTGRES_USER + - PL_DATA_POSTGRES_PASSWORD + - PL_SERVER_CLIENT_URL=https://$PL_HOSTNAME + - PL_SERVER_REPORT_ERRORS=$PL_ADMIN_EMAIL + - PL_EMAIL_BACKEND + - PL_EMAIL_SMTP_HOST + - PL_EMAIL_SMTP_PORT + - PL_EMAIL_SMTP_USER + - PL_EMAIL_SMTP_PASSWORD + - PL_EMAIL_SMTP_FROM + expose: + - 3000 + volumes: + - attachments:/attachments + restart: unless-stopped + pwa: + image: padloc/pwa + env_file: .env + environment: + PL_PWA_DIR: /pwa + PL_SERVER_URL: https://$PL_HOSTNAME/server + build: + context: github.com/padloc/padloc.git#docs/docker-examples + dockerfile: Dockerfile-pwa + volumes: + - pwa:/pwa + command: ["build"] + restart: on-failure + nginx: + env_file: .env + image: nginx + depends_on: + - server + restart: always + volumes: + - pwa:/pwa + - ./nginx.conf:/etc/nginx/nginx.conf + - /etc/letsencrypt/live/$PL_HOSTNAME/fullchain.pem:/tls/cert + - /etc/letsencrypt/live/$PL_HOSTNAME/privkey.pem:/tls/key + ports: + - 80:80 + - 443:443 + certbot: + env_file: .env + image: certbot/certbot + volumes: + - /etc/letsencrypt:/etc/letsencrypt + - /var/lib/letsencrypt:/var/lib/letsencrypt + command: "certonly --standalone -d $PL_HOSTNAME --expand --non-interactive --agree-tos -m $PL_ADMIN_EMAIL" + ports: + - 80:80 + - 443:443 + profiles: ["certbot"] +volumes: + data: + attachments: + pwa: diff --git a/docs/examples/hosting/docker/postgres-nginx-letsencrypt/get-cert.sh b/docs/examples/hosting/docker/postgres-nginx-letsencrypt/get-cert.sh new file mode 100644 index 00000000..cfa680a5 --- /dev/null +++ b/docs/examples/hosting/docker/postgres-nginx-letsencrypt/get-cert.sh @@ -0,0 +1,6 @@ +sudo docker run --rm --name certbot -p 80:80 \ + -v "/etc/letsencrypt:/etc/letsencrypt" \ + -v "/var/lib/letsencrypt:/var/lib/letsencrypt" \ + certbot/certbot certonly --standalone \ + -d test.padloc.app \ + --expand --non-interactive --agree-tos -m martin@pentacode.app diff --git a/docs/examples/hosting/docker/postgres-nginx-letsencrypt/nginx.conf b/docs/examples/hosting/docker/postgres-nginx-letsencrypt/nginx.conf new file mode 100644 index 00000000..33166d39 --- /dev/null +++ b/docs/examples/hosting/docker/postgres-nginx-letsencrypt/nginx.conf @@ -0,0 +1,64 @@ +user nginx; +worker_processes auto; + +http { + # BASIC SETTINGS + sendfile on; + tcp_nopush on; + tcp_nodelay on; + keepalive_timeout 65; + + types_hash_max_size 2048; + + # Required for attachments + client_max_body_size 10m; + + # Enable gzip + gzip on; + gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; + + include mime.types; + + # Disallow embedding in iFrames + add_header X-Frame-Options deny; + + server { + listen 80 default_server; + listen [::]:80 default_server; + server_name _; + + # Redirect all http traffic to https + return 301 https://$host$request_uri; + } + + server { + # We don't need a host name here since we're only + # dealing with one domain, but you may insert your domain here. + server_name _; + + # Both server and pwa are served over https + listen 443 ssl http2; + + # This will resolve to the server instance + location /server { + resolver 127.0.0.11 valid=60s; + set $server "http://server:3000"; + proxy_pass $server; + } + + # This will resolve to the web app + location / { + root /pwa; + index index.html; + try_files $uri /index.html; + } + + # SSL certificate + ssl_certificate /tls/cert; + # SSL private key + ssl_certificate_key /tls/key; + } +} + +events { +}