diff --git a/Dockerfile b/Dockerfile index a3e7c07f1..f7445cdef 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,7 +3,7 @@ # SPDX-License-Identifier: AGPL-3.0-or-later # Multistage build to reduce image size and increase security -FROM node:lts-alpine AS build +FROM node:lts-slim AS build # Create folder for CryptPad RUN mkdir /cryptpad @@ -14,20 +14,25 @@ COPY . /cryptpad RUN sed -i "s@//httpAddress: 'localhost'@httpAddress: '0.0.0.0'@" /cryptpad/config/config.example.js RUN sed -i "s@installMethod: 'unspecified'@installMethod: 'docker'@" /cryptpad/config/config.example.js +RUN sed -i 's@host: "localhost"@host: "0.0.0.0"@' /cryptpad/config/infra.example.js # Install dependencies RUN npm install --production \ && npm run install:components # Create actual CryptPad image -FROM node:lts-alpine +FROM node:lts-slim +ENV DEBIAN_FRONTEND=noninteractive # Create user and group for CryptPad so it does not run as root -RUN addgroup -S cryptpad -g 4001 && adduser -S cryptpad -G cryptpad --uid 4001 -h /cryptpad +RUN groupadd cryptpad -g 4001 && useradd cryptpad -u 4001 -g 4001 -d /cryptpad # Install curl for healthcheck # Install git, rdfind and unzip for install-office.sh -RUN apk add --no-cache ca-certificates git rdfind unzip bash curl +RUN apt-get update && apt-get install --no-install-recommends -y \ + curl ca-certificates git rdfind unzip && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* # Copy cryptpad with installed modules COPY --from=build --chown=cryptpad /cryptpad /cryptpad @@ -55,7 +60,7 @@ ENTRYPOINT ["/bin/bash", "/cryptpad/docker-entrypoint.sh"] HEALTHCHECK --interval=1m CMD curl -f http://localhost:3000/ || exit 1 # Ports -EXPOSE 3000 3003 +EXPOSE 3000 # Run cryptpad on startup CMD ["npm", "start"] diff --git a/docker-compose.yml b/docker-compose.yml index 33204dbc9..0711cef13 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -28,7 +28,6 @@ services: ports: - "3000:3000" - - "3003:3003" ulimits: nofile: diff --git a/docs/example-advanced.nginx.conf b/docs/example-advanced.nginx.conf index 13ab79678..c8472c569 100644 --- a/docs/example-advanced.nginx.conf +++ b/docs/example-advanced.nginx.conf @@ -8,6 +8,17 @@ # installation (http server by the Nodejs process). If you are using CryptPad # in production and require professional support please contact sales@cryptpad.fr +# CryptPad possesses several nodes that can answer websocket requests. The +# following allows nginx to load-balance between them. +# The different `server` corresponds to the location of the different front +# nodes specified in your CryptPad `config/infra.js` file. If you change this +# setting, don’t forget to update the following list of servers +# The following works with config/infra.example.js: +upstream fronts { + server localhost:3010; + server localhost:3011; +} + server { listen 80; listen [::]:80; @@ -202,7 +213,7 @@ server { # Websocket traffic still needs to be handled by the main process, which means it needs # to be hosted on a different port. By default 3003 will be used, though this is configurable # via config.websocketPort - proxy_pass http://localhost:3003; + proxy_pass http://fronts; proxy_set_header X-Real-IP $remote_addr; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; diff --git a/docs/example.nginx.conf b/docs/example.nginx.conf index 23ccf2182..5e2a3bae9 100644 --- a/docs/example.nginx.conf +++ b/docs/example.nginx.conf @@ -76,15 +76,4 @@ server { proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection upgrade; } - - location ^~ /cryptpad_websocket { - proxy_pass http://localhost:3003; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header Host $host; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection upgrade; - } } diff --git a/package-lock.json b/package-lock.json index d538b6349..1b7f34be5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,6 @@ "@mcrowe/minibloom": "^0.2.0", "@node-saml/node-saml": "^5.1.0", "alertify.js": "1.0.11", - "body-parser": "^1.20.4", "bootstrap": "^4.0.0", "bootstrap-tokenfield": "^0.12.0", "chainpad": "^5.3.1", @@ -25,10 +24,9 @@ "connect-gzip-static": "^4.2.1", "cookie-parser": "^1.4.7", "croppie": "^2.5.0", - "cryptpad-server": "^0.0.1", + "cryptpad-server": "^0.0.2", "dragula": "3.7.2", "drawio": "github:cryptpad/drawio-npm#npm-29.6.7+3", - "express": "~4.22.1", "file-saver": "1.3.1", "fs-extra": "^7.0.0", "get-folder-size": "^2.0.1", @@ -1819,9 +1817,9 @@ } }, "node_modules/cryptpad-server": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/cryptpad-server/-/cryptpad-server-0.0.1.tgz", - "integrity": "sha512-qWhs6zKLbwK58V2nJBj2hkIaexljOgmte0+KKxyprVnaZeE9Qkwg4hyPrSKmKh5EssDtu/1/ol6TodzNPR6OcA==", + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/cryptpad-server/-/cryptpad-server-0.0.2.tgz", + "integrity": "sha512-JpU7Q3N+wtb2Eafy9GEOuBeXk5cy7tqT3VyMyTfj16JT4DyxH7EuvpmzjcgGYomsxYt5xS/dViZ4eGOUp4uXlQ==", "license": "AGPL-3.0+", "dependencies": { "body-parser": "^2.2.0", diff --git a/package.json b/package.json index 79111c716..a61fb66f9 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,6 @@ "@mcrowe/minibloom": "^0.2.0", "@node-saml/node-saml": "^5.1.0", "alertify.js": "1.0.11", - "body-parser": "^1.20.4", "bootstrap": "^4.0.0", "bootstrap-tokenfield": "^0.12.0", "chainpad": "^5.3.1", @@ -28,10 +27,9 @@ "connect-gzip-static": "^4.2.1", "cookie-parser": "^1.4.7", "croppie": "^2.5.0", - "cryptpad-server": "^0.0.1", + "cryptpad-server": "^0.0.2", "dragula": "3.7.2", "drawio": "github:cryptpad/drawio-npm#npm-29.6.7+3", - "express": "~4.22.1", "file-saver": "1.3.1", "fs-extra": "^7.0.0", "get-folder-size": "^2.0.1", diff --git a/scripts/build.js b/scripts/build.js index 5cb823286..dc88fb1b2 100644 --- a/scripts/build.js +++ b/scripts/build.js @@ -7,7 +7,7 @@ var Fse = require("fs-extra"); var Path = require("path"); var OS = require("os"); -var config = require("../lib/load-config"); +const { config, infra } = require("../lib/load-config"); var swap = function (s, o) { return s @@ -108,7 +108,7 @@ var imagePath = `/customize/images/opengraph_preview/`; var appImagePath = a => { var partial = previewExists(`og-${a}.png`) && `og-${a}.png` || `og-default.png`; - return new URL(imagePath + partial, config.httpUnsafeOrigin).href; + return new URL(imagePath + partial, infra.public.origin).href; }; var buildPath = Path.resolve('./customize'); @@ -218,7 +218,7 @@ appIndexesToBuild.forEach(function (app) { var type = types[app]; var built = processPage(src.replace(patt, (current) => { return current + swap(ogData, { - url: new URL(`/${app}/`, config.httpUnsafeOrigin).href, + url: new URL(`/${app}/`, infra.public.origin).href, title: type && `Encrypted ${type}` || 'CryptPad', image: appImagePath(app), description: Messages.og_default, @@ -237,7 +237,7 @@ appIndexesToBuild.forEach(function (app) { var instance; try { - instance = new URL(config.httpUnsafeOrigin).hostname; + instance = new URL(infra.public.origin).hostname; } catch (err) { console.error("Failed to parse instance domain name\nAborting..."); return void process.exit(1); @@ -284,12 +284,12 @@ try { console.log(`Parsing ${srcPath}`); var src = Fs.readFileSync(srcPath, 'utf8'); var patt = /<\/title>/; - var href = new URL(obj.url, config.httpUnsafeOrigin).href; + var href = new URL(obj.url, infra.public.origin).href; var built = processPage(src.replace(patt, (current) => { return current + swap(ogData, { url: href, title: obj.title || "CryptPad", - image: new URL(imagePath + 'og-default.png', config.httpUnsafeOrigin).href, + image: new URL(imagePath + 'og-default.png', infra.public.origin).href, description: Messages.og_default, }); }));