docs(docker): add instructions on how to serve over HTTPS

* Added a script to generate a self-signed certificate
* Added *.pem, *.key and *.crt files to .gitignore and .dockerignore
* Stopped setting PUB_PLAUSIBLE_URL to https://plausible.example.com on Docker Compose builds by default
* Modified "Building on Production" to mention that HTTPS is required on most cases
* Added a base HTTPS config for nginx
This commit is contained in:
azurejelly 2025-04-26 14:57:04 -04:00
parent 262b2a3c53
commit cc8145d576
No known key found for this signature in database
GPG Key ID: 78C7CB2FBB62D96D
8 changed files with 133 additions and 16 deletions

View File

@ -6,6 +6,7 @@ dist/
.output/ .output/
.vercel/ .vercel/
.vscode/ .vscode/
ssl/
LICENSE LICENSE
README.md README.md
@ -18,4 +19,10 @@ docker-compose.yml
.env .env
.DS_Store .DS_Store
Thumbs.db Thumbs.db
*.crt
*.key
*.pem
setup-self-signed.sh

5
.gitignore vendored
View File

@ -1,5 +1,10 @@
node_modules node_modules
# SSL
*.crt
*.key
*.pem
# Output # Output
.output .output
.vercel .vercel

View File

@ -22,6 +22,6 @@ RUN bun run build
FROM nginx:stable-alpine FROM nginx:stable-alpine
COPY ./nginx.conf /etc/nginx/conf.d/default.conf COPY ./nginx/default.conf /etc/nginx/conf.d/default.conf
COPY --from=builder /app/build /usr/share/nginx/html COPY --from=builder /app/build /usr/share/nginx/html

View File

@ -27,10 +27,11 @@ Make sure you have the following installed:
### Installation ### Installation
```sh ```sh
# Clone the repository # Clone the repository
git clone https://github.com/VERT-sh/vert.git $ git clone https://github.com/VERT-sh/vert.git
cd vert $ cd vert
# Install dependencies # Install dependencies
bun i $ bun i
``` ```
### Running Locally ### Running Locally
@ -54,7 +55,7 @@ To build the project for production, run `bun run build`
This will build the site to the `build` folder. You should then use a web server like [nginx](https://nginx.org) to serve the files inside that folder. This will build the site to the `build` folder. You should then use a web server like [nginx](https://nginx.org) to serve the files inside that folder.
If using nginx, you can use the [nginx.conf](./nginx.conf) file as a starting point. Make sure you keep [cross-origin isolation](https://web.dev/articles/cross-origin-isolation-guide) enabled. If using nginx, you can use the [default-ssl.conf](./nginx/default-ssl.conf) file (or [default.conf](./nginx/default.conf) if you don't need to serve the site over HTTPS) as a starting point. Make sure you keep [cross-origin isolation](https://web.dev/articles/cross-origin-isolation-guide) enabled, which **requires** HTTPS on most cases.
### With Docker ### With Docker
@ -81,7 +82,9 @@ This will do the following:
- Continuously restart the container until manually stopped - Continuously restart the container until manually stopped
- Map `3000/tcp` (host) to `80/tcp` (container) - Map `3000/tcp` (host) to `80/tcp` (container)
We also have a [`docker-compose.yml`](./docker-compose.yml) file available. Use `docker compose up` if you want to start the stack, or `docker compose down` to bring it down. You can pass `--build` to `docker compose up` to rebuild the Docker image (useful if you've changed any of the environment variables) as well as `-d` to start it in detached mode. You can read more about Docker Compose in general [here](https://docs.docker.com/compose/intro/compose-application-model/). We also have a [`docker-compose.yml`](./docker-compose.yml) file available. Use `docker compose up` if you want to start the stack, or `docker compose down` to bring it down. You can pass `--build` to `docker compose up` to rebuild the Docker image (useful if you've changed any of the environment variables) as well as `-d` to start it in detached mode. Feel free to read more about Docker Compose in general [here](https://docs.docker.com/compose/intro/compose-application-model/).
#### Pulling instead of building
While there's an image you can pull instead of cloning the repo and building the image yourself, you will not be able to update any of the environment variables (e.g. `PUB_PLAUSIBLE_URL`) as they're baked directly into the image and not obtained during runtime. If you're okay with this, you can simply run this command instead: While there's an image you can pull instead of cloning the repo and building the image yourself, you will not be able to update any of the environment variables (e.g. `PUB_PLAUSIBLE_URL`) as they're baked directly into the image and not obtained during runtime. If you're okay with this, you can simply run this command instead:
```shell ```shell
@ -92,6 +95,63 @@ $ docker run -d \
ghcr.io/vert-sh/vert:latest ghcr.io/vert-sh/vert:latest
``` ```
#### Serving the site over HTTPS
If you're running the container in your local machine and accessing it from `localhost`, this isn't really required. However, any other origin will cause cross-origin
isolation to be disabled unless you serve the site over HTTPS, which in turn will cause image conversions to fail. There are a few options to get around this:
- Using something like Tailscale's [HTTPS feature](https://tailscale.com/kb/1153/enabling-https)
- Using a self-signed certificate (not recommended for public instances and your browser will likely yell at you)
- Using Let's Encrypt or Cloudflare as a TLS proxy with your own domain
If you want to use a self-signed certificate, there's a little [script](./nginx/setup-self-signed.sh) you can run in order to generate one. Make sure you have `openssl` installed, then run:
```shell
$ cd ./nginx/
$ ./setup-self-signed.sh
```
This will generate the following files inside `./ssl/`:
```shell
$ ls ./ssl
self-signed.crt self-signed.key
```
If you don't want to use a self-signed certificate, simply copy your own key and certificate files into `./nginx/ssl/` instead. Make sure to then modify the default SSL config under [./nginx/default-ssl.conf](./nginx/default-ssl.conf) to match the file names:
```conf
server {
...
ssl_certificate /etc/ssl/vert/self-signed.crt;
ssl_certificate_key /etc/ssl/vert/self-signed.key;
...
}
```
Finally, update your Docker Compose configuration:
```yaml
services:
vert:
# ...
ports:
# map to port 443 instead of 80
- "${PORT:-3000}:443"
volumes:
# map the ssl folder with our certificates to /etc/ssl/vert in read-only mode
- "./nginx/ssl:/etc/ssl/vert:ro"
# overwrite the default HTTP configuration of the container
- "./nginx/default-ssl.conf:/etc/nginx/conf.d/default.conf"
```
For `docker run`, use:
```shell
$ docker run ... \
-p 3000:443 \
-v "./nginx/ssl:/etc/ssl/vert" \
-v "./nginx/default-ssl.conf:/etc/nginx/conf.d/default.conf" \
...
```
## License ## License
This project is licensed under the AGPL-3.0 License, please see the [LICENSE](LICENSE) file for details. This project is licensed under the AGPL-3.0 License, please see the [LICENSE](LICENSE) file for details.

View File

@ -1,20 +1,14 @@
services: services:
vert: vert:
container_name: vert container_name: vert
image: vert-sh/vert:latest image: gchr.io/vert-sh/vert:latest
environment: restart: unless-stopped
- PUB_HOSTNAME=${PUB_HOSTNAME:-vert.sh}
- PUB_PLAUSIBLE_URL=${PUB_PLAUSIBLE_URL:-https://plausible.example.com}
- PUB_ENV=${PUB_ENV:-production}
- PORT=${PORT:-3000}
- PUB_VERTD_URL=${PUB_VERTD_URL:-https://vertd.vert.sh}
build: build:
context: . context: .
args: args:
PUB_HOSTNAME: ${PUB_HOSTNAME:-vert.sh} PUB_HOSTNAME: ${PUB_HOSTNAME:-vert.sh}
PUB_PLAUSIBLE_URL: ${PUB_PLAUSIBLE_URL:-https://plausible.example.com} PUB_PLAUSIBLE_URL: ${PUB_PLAUSIBLE_URL:-}
PUB_ENV: ${PUB_ENV:-production} PUB_ENV: ${PUB_ENV:-production}
PUB_VERTD_URL: ${PUB_VERTD_URL:-https://vertd.vert.sh} PUB_VERTD_URL: ${PUB_VERTD_URL:-https://vertd.vert.sh}
restart: unless-stopped
ports: ports:
- ${PORT:-3000}:80 - ${PORT:-3000}:80

30
nginx/default-ssl.conf Normal file
View File

@ -0,0 +1,30 @@
server {
listen 80;
server_name vert;
# Redirect all HTTP traffic to HTTPS
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name vert;
ssl_certificate /etc/ssl/vert/self-signed.crt;
ssl_certificate_key /etc/ssl/vert/self-signed.key;
root /usr/share/nginx/html;
index index.html;
client_max_body_size 10M;
location / {
try_files $uri $uri/ /index.html;
}
error_page 404 /index.html;
add_header Cross-Origin-Embedder-Policy "require-corp";
add_header Cross-Origin-Opener-Policy "same-origin";
add_header Cross-Origin-Resource-Policy "cross-origin";
}

View File

@ -0,0 +1,21 @@
#!/bin/bash
OUT_DIR="./ssl"
KEY_OUT="$OUT_DIR/self-signed.key"
CRT_OUT="$OUT_DIR/self-signed.crt"
if ! which openssl > /dev/null 2>&1; then
echo "Could not find openssl in your PATH. Exiting."
exit 1
fi
mkdir -p "$OUT_DIR"
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout "$KEY_OUT" \
-out "$CRT_OUT"
chmod 600 "$KEY_OUT" \
"$CRT_OUT"
echo "Finished generating self-signed certificate."