From e1691d548c68a4c3acc3b6d2ddbd999f395935c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20Gustav=20Str=C3=A5b=C3=B8?= Date: Fri, 27 Sep 2024 11:23:05 +0200 Subject: [PATCH] server docusaurus static files with nginx add security headers fix docker compose --- public-site/Dockerfile | 10 ++++-- public-site/README.md | 21 ++++++------- public-site/dev.Dockerfile | 8 ----- public-site/docker-compose.yml | 51 +++++++++++++++++++++++++------ public-site/docusaurus.config.ts | 9 ------ public-site/nginx.conf | 23 -------------- public-site/package.json | 4 +-- public-site/proxy/securityheaders | 7 +++++ public-site/proxy/server.conf | 16 ++++++++++ public-site/proxy/server.dev.conf | 21 +++++++++++++ 10 files changed, 104 insertions(+), 66 deletions(-) delete mode 100644 public-site/dev.Dockerfile delete mode 100644 public-site/nginx.conf create mode 100644 public-site/proxy/securityheaders create mode 100644 public-site/proxy/server.conf create mode 100644 public-site/proxy/server.dev.conf diff --git a/public-site/Dockerfile b/public-site/Dockerfile index 5e70c08d..2bc52c09 100644 --- a/public-site/Dockerfile +++ b/public-site/Dockerfile @@ -1,10 +1,14 @@ -FROM docker.io/node:20.14.0-alpine3.20 as builder +FROM docker.io/node:20.14.0-alpine3.20 AS builder WORKDIR /site COPY . . RUN npm install RUN npm run build +FROM docker.io/nginxinc/nginx-unprivileged:1.26.2-alpine +WORKDIR /site +COPY --from=builder /site/build /site +COPY /proxy/server.conf /etc/nginx/conf.d/default.conf +COPY /proxy/securityheaders /etc/nginx/conf.d/ EXPOSE 8080 -USER 1000 -CMD ["npm", "run", "serve"] \ No newline at end of file +USER 101 \ No newline at end of file diff --git a/public-site/README.md b/public-site/README.md index 375ffc16..85a8fe2a 100644 --- a/public-site/README.md +++ b/public-site/README.md @@ -7,25 +7,22 @@ platform. It is a static site built with [VuePress 2](https://v2.vuepress.vuejs. ### The easy way - docker-compose up --build +`docker compose --profile dev up --build` -This builds a Docker image `radix-public-site`, runs it in the container -`radix-public-site_container`, mounts the local directory into `/site` in the -container. +This starts the Docusaurus developer server on port 8000, and NGINX on port 8080 which proxies requests to the docusaurus server. This ensures that your browser receives the same security related headers (defined in ./proxy/headers) as when you build and run the Dockerfile container image. Changes to source files are immediatly shown in the browser. -You can see the site on <http://localhost:8081> +You can see the site on <http://localhost:8080> -Stop the server with Ctrl+C, but also run `docker-compose down` to clean up the +Stop the server with Ctrl+C, but also run `docker compose --profile dev down` to clean up the Docker state. If you need a shell in the container: - docker exec -ti radix-public-site_container sh + `docker exec -ti radix-public-site_container sh` -If you change the `package.json` (e.g. add a dependency), or want to force a clean -dev environment, you will need to rebuild the dev image: +NB: The search plugin does not work when running the docusaurus development server. - docker-compose up --build +You can also build and run the container image intended for production environments by running `docker compose --profile prod up --build`. To stop and cleanup you run `docker compose --profile prod down`. **Windows**: There is currently [a problem](https://github.com/docker/for-win/issues/56) with Docker that prevents @@ -35,7 +32,7 @@ process](https://github.com/FrodeHus/docker-windows-volume-watcher/releases). ### The other way -You can also run Vuepress locally. All that is needed is NodeJS and NPM. In the root folder of the project run `npm i` to fetch dependencies followed by `npm run dev` to start serving the development environment of the Public Site. +You can also run docusurus locally. All that is needed is NodeJS and NPM. In the root folder of the project run `npm i` to fetch dependencies followed by `npm run start` to start serving the development environment of the Public Site. The disadvantage is that you will not catch errors caused by the security headers set by NGINX. ## Folder structure @@ -53,7 +50,7 @@ But the interesting bits are the actual content: - `/references/`: Reference documentation for end-users. - `/other/`: Documentation not directly related to any specific category. -## ducusaurus +## docusaurus This website is built using [Docusaurus](https://docusaurus.io/), a modern static website generator. [Create an application](https://docusaurus.io/docs/installation) diff --git a/public-site/dev.Dockerfile b/public-site/dev.Dockerfile deleted file mode 100644 index 320f54c0..00000000 --- a/public-site/dev.Dockerfile +++ /dev/null @@ -1,8 +0,0 @@ -FROM docker.io/node:20.14.0-alpine3.20 as builder - -WORKDIR /site -COPY . . -RUN npm install -RUN npm run build - -CMD npm run dev diff --git a/public-site/docker-compose.yml b/public-site/docker-compose.yml index 6aa61d55..41909c7f 100644 --- a/public-site/docker-compose.yml +++ b/public-site/docker-compose.yml @@ -1,16 +1,49 @@ -version: "3.5" - services: - radix-public-site: - build: - context: . - dockerfile: dev.Dockerfile - image: radix-public-site - container_name: radix-public-site_container + docusaurus: + image: docker.io/node:20.14.0-alpine3.20 + container_name: docusaurus + working_dir: /app + command: ["sh", "-c", "npm run start"] + profiles: + - dev + networks: + - radix-public-site + ports: + - "8000:8000" + volumes: + - type: bind + source: . + target: /app + + proxy: + image: nginxinc/nginx-unprivileged:1.26-alpine + container_name: proxy + profiles: + - dev networks: - radix-public-site ports: - - "8081:8080" + - "8080:8080" + depends_on: + - docusaurus + volumes: + - type: bind + read_only: true + target: /etc/nginx/conf.d/default.conf + source: ./proxy/server.dev.conf + - type: bind + read_only: true + target: /etc/nginx/conf.d/securityheaders + source: ./proxy/securityheaders + + production: + build: + context: . + dockerfile: Dockerfile + profiles: + - prod + ports: + - "8080:8080" networks: radix-public-site: diff --git a/public-site/docusaurus.config.ts b/public-site/docusaurus.config.ts index bc933c53..c22e47e4 100644 --- a/public-site/docusaurus.config.ts +++ b/public-site/docusaurus.config.ts @@ -48,15 +48,6 @@ const config: Config = { // Replace with your project's social card // image: 'img/docusaurus-social-card.jpg', - metadata:[ - {"http-equiv": 'Content-Security-Policy', content: `default-src 'self';script-src 'self' 'unsafe-eval' 'unsafe-inline'; object-src 'none'; img-src 'self' data:; style-src 'self' https://cdn.eds.equinor.com/font/; font-src 'self' https://cdn.eds.equinor.com/font/; upgrade-insecure-requests; block-all-mixed-content`}, - {"http-equiv": 'Permissions-Policy', content: 'none'}, - {"http-equiv": 'Cross-Origin-Resource-Policy', content: 'same-origin'}, - {"http-equiv": 'Referrer-Policy', content: 'no-referrer'}, - {"http-equiv": 'X-Content-Type-Options', content: 'nosniff'}, - {"http-equiv": 'X-Permitted-Cross-Domain-Policies', content: 'none'}, - ], - navbar: { title: 'Omnia Radix', logo: { diff --git a/public-site/nginx.conf b/public-site/nginx.conf deleted file mode 100644 index 874a7545..00000000 --- a/public-site/nginx.conf +++ /dev/null @@ -1,23 +0,0 @@ -server { - listen 8080; - server_name localhost; - absolute_redirect off; - root /site; - - server_tokens off; - - add_header X-Frame-Options deny always; - add_header X-Content-Type-Options nosniff always; - add_header X-Permitted-Cross-Domain-Policies none always; - add_header Content-Security-Policy "default-src 'self'; object-src 'none'; img-src 'self' data:; style-src 'self' https://cdn.eds.equinor.com/font/; font-src 'self' https://cdn.eds.equinor.com/font/; frame-ancestors 'none'; upgrade-insecure-requests; block-all-mixed-content" always; - add_header Cross-Origin-Resource-Policy same-origin always; - add_header Permissions-Policy "camera=(),display-capture=(),fullscreen=(),geolocation=(),microphone=()" always; - add_header Referrer-Policy no-referrer always; - - location / { - index index.html - try_files $uri $uri/ =404; - } - - error_page 404 /404.html; -} diff --git a/public-site/package.json b/public-site/package.json index 313c6c54..e1972219 100644 --- a/public-site/package.json +++ b/public-site/package.json @@ -4,12 +4,12 @@ "private": true, "scripts": { "docusaurus": "docusaurus", - "start": "docusaurus start --port 8080", + "start": "docusaurus start --port 8000 --host 0.0.0.0", "build": "docusaurus build", "swizzle": "docusaurus swizzle", "deploy": "docusaurus deploy", "clear": "docusaurus clear", - "serve": "docusaurus serve --port 8080", + "serve": "docusaurus serve --port 8000", "write-translations": "docusaurus write-translations", "write-heading-ids": "docusaurus write-heading-ids", "typecheck": "tsc" diff --git a/public-site/proxy/securityheaders b/public-site/proxy/securityheaders new file mode 100644 index 00000000..61140d0b --- /dev/null +++ b/public-site/proxy/securityheaders @@ -0,0 +1,7 @@ +add_header X-Frame-Options deny always; +add_header X-Content-Type-Options nosniff always; +add_header X-Permitted-Cross-Domain-Policies none always; +add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-eval' 'unsafe-inline'; object-src 'none'; img-src 'self' data:; style-src 'self' 'unsafe-inline' https://cdn.eds.equinor.com/font/; font-src 'self' https://cdn.eds.equinor.com/font/; frame-ancestors 'none'; upgrade-insecure-requests; block-all-mixed-content" always; +add_header Cross-Origin-Resource-Policy same-origin always; +add_header Permissions-Policy "camera=(),display-capture=(),fullscreen=(),geolocation=(),microphone=()" always; +add_header Referrer-Policy no-referrer always; \ No newline at end of file diff --git a/public-site/proxy/server.conf b/public-site/proxy/server.conf new file mode 100644 index 00000000..244b9d95 --- /dev/null +++ b/public-site/proxy/server.conf @@ -0,0 +1,16 @@ +server { + listen 8080; + absolute_redirect off; + root /site; + + server_tokens off; + + include /etc/nginx/conf.d/securityheaders; + + location / { + index index.html + try_files $uri $uri/ =404; + } + + error_page 404 /404.html; +} diff --git a/public-site/proxy/server.dev.conf b/public-site/proxy/server.dev.conf new file mode 100644 index 00000000..ddd73223 --- /dev/null +++ b/public-site/proxy/server.dev.conf @@ -0,0 +1,21 @@ +server { + listen 8080; + absolute_redirect off; + # root /site; + + server_tokens off; + + include /etc/nginx/conf.d/securityheaders; + + location / { + proxy_pass http://docusaurus:8000/; + + proxy_read_timeout 3600s; + proxy_send_timeout 3600s; + + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $http_connection; + } + + # error_page 404 /404.html; +}