mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2025-06-03 08:28:54 -04:00

The API documentation belongs strictly to the API itself. Due to the usage of version-prefixed API endpoints, there is no conflict with existing or future endpoints. The reason behind this is that we already have enough exceptions in the routing (default everything to react-frontend, exceptions for backend) and it is hard to keep it synchronized throughout all relevant places. This came to attention as the dev setup didn't proxy the API docs to the backend. Signed-off-by: Erik Michelson <github@erik.michelson.eu>
214 lines
7.9 KiB
Markdown
214 lines
7.9 KiB
Markdown
# How to use a reverse proxy
|
|
|
|
<!-- markdownlint-disable proper-names -->
|
|
|
|
When having multiple webservers or other applications running, that also use
|
|
port 80 and 443, you probably want to use a reverse proxy to serve HedgeDoc.
|
|
|
|
We'll assume the domain you use for the instance is <https://md.example.com>, so please
|
|
substitute your actual domain anywhere you encounter <https://md.example.com>.
|
|
|
|
## Configuring the reverse proxy
|
|
|
|
We have collected some example configurations for popular reverse proxies below.
|
|
At the end is also a list of generic things the reverse proxy must do, if you prefer
|
|
to write your own config or use a reverse proxy not mentioned here.
|
|
|
|
### Traefik
|
|
|
|
As [traefik][traefik] has direct access to your running Docker containers, there is no need to
|
|
configure extra ports. Instead, you'll only have to add the following labels to the services
|
|
in your `docker-compose.yml`:
|
|
|
|
<!-- markdownlint-disable line-length no-space-in-code -->
|
|
|
|
??? abstract "docker-compose.yml"
|
|
```yaml
|
|
backend:
|
|
image: ghcr.io/hedgedoc/hedgedoc/backend:2.0.0-alpha.2
|
|
volumes:
|
|
- $PWD/.env:/usr/src/app/backend/.env
|
|
- hedgedoc_uploads:/usr/src/app/backend/uploads
|
|
labels:
|
|
traefik.enable: "true"
|
|
traefik.http.routers.hedgedoc_2_backend.rule: "Host(`md.example.com`) && (PathPrefix(`/realtime`) || PathPrefix(`/api`) || PathPrefix(`/public`))"
|
|
traefik.http.routers.hedgedoc_2_backend.tls: "true"
|
|
traefik.http.routers.hedgedoc_2_backend.tls.certresolver: "letsencrypt"
|
|
traefik.http.services.hedgedoc_2_backend.loadbalancer.server.port: "3000"
|
|
traefik.http.services.hedgedoc_2_backend.loadbalancer.server.scheme: "http"
|
|
frontend:
|
|
image: ghcr.io/hedgedoc/hedgedoc/frontend:2.0.0-alpha.2
|
|
environment:
|
|
HD_BASE_URL: "${HD_BASE_URL}"
|
|
labels:
|
|
traefik.enable: "true"
|
|
traefik.http.routers.hedgedoc_2_frontend.rule: "Host(`md.example.com`)"
|
|
traefik.http.routers.hedgedoc_2_frontend.tls: "true"
|
|
traefik.http.routers.hedgedoc_2_frontend.tls.certresolver: "letsencrypt"
|
|
traefik.http.services.hedgedoc_2_frontend.loadbalancer.server.port: "3001"
|
|
traefik.http.services.hedgedoc_2_frontend.loadbalancer.server.scheme: "http"
|
|
```
|
|
|
|
<!-- markdownlint-enable line-length no-space-in-code -->
|
|
|
|
We added [Let's Encrypt][letsencrypt] as a certificate resolver, as it enables you to
|
|
quickly use HTTPS. If you don't want to use that feel free to change
|
|
the `.certresolver` variables accordingly.
|
|
|
|
If you used the `docker-compose.yml` file from the tutorial, please remove
|
|
the service `proxy` and the volume `caddy_data` as caddy is no longer needed when using traefik.
|
|
|
|
### Other reverse proxies
|
|
|
|
In the following we'll also assume that you run a HedgeDoc backend on port `3000`,
|
|
a HedgeDoc frontend on port `3001`.
|
|
Furthermore, we assume that you have TLS certificates located at
|
|
`/etc/letsencrypt/live/md.example.com/fullchain.pem`
|
|
and
|
|
`/etc/letsencrypt/live/md.example.com/privkey.pem` respectively
|
|
and are using [Let's Encrypt][letsencrypt] for your certificates.
|
|
Replace these paths with the actual paths to your certificates.
|
|
|
|
**Preparations when using the default docker-compose.yml:**
|
|
|
|
If your starting with the `docker-compose.yml` file from the tutorial,
|
|
you need to add the `ports` entry for both `backend` and `frontend` as following.
|
|
|
|
<!-- markdownlint-disable no-space-in-code -->
|
|
|
|
??? abstract "docker-compose.yml"
|
|
```yaml
|
|
backend:
|
|
image: ghcr.io/hedgedoc/hedgedoc/backend:2.0.0-alpha.2
|
|
volumes:
|
|
- $PWD/.env:/usr/src/app/backend/.env
|
|
- hedgedoc_uploads:/usr/src/app/backend/uploads
|
|
ports:
|
|
- "3000:3000"
|
|
frontend:
|
|
image: ghcr.io/hedgedoc/hedgedoc/frontend:2.0.0-alpha.2
|
|
environment:
|
|
HD_BASE_URL: "${HD_BASE_URL}"
|
|
ports:
|
|
- "3001:3001"
|
|
```
|
|
|
|
<!-- markdownlint-enable no-space-in-code -->
|
|
|
|
Also, you want to remove the service `proxy` and the volume `caddy_data`
|
|
to avoid port conflicts with your reverse-proxy software.
|
|
|
|
#### nginx
|
|
|
|
Here is an example configuration for [nginx][nginx].
|
|
|
|
<!-- markdownlint-disable code-block-style -->
|
|
|
|
??? abstract "nginx config"
|
|
```
|
|
map $http_upgrade $connection_upgrade {
|
|
default upgrade;
|
|
'' close;
|
|
}
|
|
server {
|
|
server_name md.example.com;
|
|
|
|
location ~ ^/(api|public|uploads)/ {
|
|
proxy_pass http://127.0.0.1:3000;
|
|
proxy_set_header X-Forwarded-Host $host;
|
|
proxy_set_header X-Real-IP $remote_addr;
|
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
proxy_set_header X-Forwarded-Proto $scheme;
|
|
}
|
|
|
|
location /realtime {
|
|
proxy_pass http://127.0.0.1:3000;
|
|
proxy_set_header X-Forwarded-Host $host;
|
|
proxy_set_header X-Real-IP $remote_addr;
|
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
proxy_set_header X-Forwarded-Proto $scheme;
|
|
proxy_set_header Upgrade $http_upgrade;
|
|
proxy_set_header Connection $connection_upgrade;
|
|
}
|
|
|
|
location / {
|
|
proxy_pass http://127.0.0.1:3001;
|
|
proxy_set_header X-Forwarded-Host $host;
|
|
proxy_set_header X-Real-IP $remote_addr;
|
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
proxy_set_header X-Forwarded-Proto $scheme;
|
|
}
|
|
|
|
listen [::]:443 ssl http2;
|
|
listen 443 ssl http2;
|
|
ssl_certificate fullchain.pem;
|
|
ssl_certificate_key privkey.pem;
|
|
include options-ssl-nginx.conf;
|
|
ssl_dhparam ssl-dhparams.pem;
|
|
}
|
|
```
|
|
|
|
<!-- markdownlint-disable code-block-style -->
|
|
|
|
#### Apache
|
|
|
|
You will need these modules enabled: `proxy`, `proxy_http` and `proxy_wstunnel`.
|
|
Here is an example config snippet for [Apache][apache]:
|
|
|
|
<!-- markdownlint-disable code-block-style -->
|
|
|
|
??? abstract "Apache config"
|
|
```
|
|
<VirtualHost *:443>
|
|
ServerName md.example.com
|
|
|
|
RewriteEngine on
|
|
RewriteCond %{REQUEST_URI} ^/realtime [NC]
|
|
RewriteCond %{HTTP:Upgrade} =websocket [NC]
|
|
RewriteRule /(.*) ws://127.0.0.1:3000/$1 [P,L]
|
|
|
|
ProxyPass /api http://127.0.0.1:3000/
|
|
ProxyPass /public http://127.0.0.1:3000/
|
|
ProxyPass /realtime http://127.0.0.1:3000/
|
|
|
|
ProxyPassReverse /api http://127.0.0.1:3000/
|
|
ProxyPassReverse /public http://127.0.0.1:3000/
|
|
ProxyPassReverse /realtime http://127.0.0.1:3000/
|
|
|
|
ProxyPass / http://127.0.0.1:3001/
|
|
ProxyPassReverse / http://127.0.0.1:3001/
|
|
|
|
RequestHeader set "X-Forwarded-Proto" expr=%{REQUEST_SCHEME}
|
|
|
|
ErrorLog ${APACHE_LOG_DIR}/error.log
|
|
CustomLog ${APACHE_LOG_DIR}/access.log combined
|
|
|
|
SSLCertificateFile /etc/letsencrypt/live/md.example.com/fullchain.pem
|
|
SSLCertificateKeyFile /etc/letsencrypt/live/md.example.com/privkey.pem
|
|
Include /etc/letsencrypt/options-ssl-apache.conf
|
|
</VirtualHost>
|
|
```
|
|
|
|
<!-- markdownlint-enable code-block-style -->
|
|
|
|
#### Generic
|
|
|
|
Here is a list of things your reverse proxy needs to do to let HedgeDoc work:
|
|
|
|
- Websocket `Upgrade` requests at path `/realtime`.
|
|
- Passing `/realtime` to <http://localhost:3000>
|
|
- Passing `/api/*` to <http://localhost:3000>
|
|
- Passing `/public/*` to <http://localhost:3000>
|
|
- Passing `/uploads/*` to <http://localhost:3000>
|
|
- Passing `/*` to <http://localhost:3001>
|
|
- Set the `X-Forwarded-Proto` header
|
|
|
|
In essence there are a few special urls that need to be handled by the HedgeDoc backend
|
|
and everything else is handled by the frontend.
|
|
|
|
<!-- markdownlint-enable proper-names -->
|
|
|
|
[traefik]: https://traefik.io/traefik/
|
|
[letsencrypt]: https://letsencrypt.org/
|
|
[nginx]: https://nginx.org/
|
|
[apache]: https://httpd.apache.org/
|