docs: Updated install doc to include nginx instructions
Deploy / deploy (push) Successful in 57s

This commit is contained in:
2026-09-10 08:43:43 +00:00
parent fbfb4b8608
commit e8455c99fe
+158 -9
View File
@@ -13,8 +13,10 @@ You need:
- A Linux host with **Docker** and the **Compose plugin**.
- A DNS name pointing at that host. People use it for the web UI, and your
agents use it too.
- A reverse proxy in front of Vantage that terminates TLS. It needs to handle
both the web UI and the agent port, `9090`, which speaks HTTP/2.
- A way to terminate TLS. The stack ships an nginx reverse proxy that routes
the web UI and API on plain HTTP; you can terminate TLS in that nginx (see
[step 4](#4-the-reverse-proxy)) or in a proxy you already run in front of it.
The agent port, `9090`, speaks HTTP/2.
- Those two ports reachable: the web port from wherever your people are, and
`9090` from every machine you intend to manage.
- Outbound access from the control plane, and from each managed machine, to
@@ -23,13 +25,17 @@ You need:
The stack brings MongoDB, Redis and the console daemon with it, so there is no
database to provide.
## 1. Get the Compose file
## 1. Get the Compose file and proxy config
```bash
mkdir -p /opt/vantage && cd /opt/vantage
mkdir -p /opt/vantage/nginx && cd /opt/vantage
curl -fsSLO https://gitea.hostxtra.co.uk/vantage/vantage-app/raw/branch/main/deploy/docker/docker-compose.yml
curl -fsSL -o nginx/vantage.conf https://gitea.hostxtra.co.uk/vantage/vantage-app/raw/branch/main/deploy/docker/nginx/vantage.conf
```
The Compose file mounts `./nginx/vantage.conf` into the `nginx` service, so it
must sit at that path next to `docker-compose.yml`.
## 2. Write the environment file
Create `/opt/vantage/.env`:
@@ -44,6 +50,9 @@ KEY_ENCRYPTION_KEY=
# The host serving agent downloads.
GITEA_HOST=gitea.hostxtra.co.uk
# Optional: host port for the bundled nginx proxy. Defaults to 80.
# NGINX_HTTP_PORT=80
```
Generate the encryption key:
@@ -82,7 +91,7 @@ docker compose up -d
docker compose ps
```
Five services start: `mongo`, `redis`, `guacd`, `server` and `web`.
Six services start: `mongo`, `redis`, `guacd`, `server`, `web` and `nginx`.
Check the server got through startup:
@@ -94,9 +103,9 @@ On first boot it prepares the database and loads the built-in workflow step
library. If it stops during that, it will say why, and it is meant to stop
rather than run in a half-prepared state.
## 4. Put a proxy in front
## 4. The reverse proxy
Terminate TLS at your reverse proxy and route **one hostname to two backends**:
The `nginx` service routes **one hostname to two backends**:
| Path | Backend |
| -------------------------------------------------------------------------------- | ------------- |
@@ -105,7 +114,119 @@ Terminate TLS at your reverse proxy and route **one hostname to two backends**:
Both rules are required. The web app forwards nothing to the API, so a proxy
that sends the whole hostname to `web:3000` serves the interface and answers
`404` to every request it makes — starting with the login form.
`404` to every request it makes — starting with the login form. If you replace
the bundled nginx with your own proxy, it must route the same way.
This is the shipped `nginx/vantage.conf`:
```nginx
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
upstream vantage_server {
server server:8080;
keepalive 16;
}
upstream vantage_web {
server web:3000;
keepalive 16;
}
server {
listen 80;
listen [::]:80;
server_name _;
client_max_body_size 10m;
proxy_http_version 1.1;
proxy_set_header Host $host;
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;
# REST API. The browser console is a WebSocket and workflow logs stream,
# so no buffering and a long read timeout.
location ^~ /api/ {
proxy_pass http://vantage_server;
proxy_buffering off;
proxy_read_timeout 1h;
proxy_send_timeout 1h;
}
location ^~ /auth/ {
proxy_pass http://vantage_server;
}
location ^~ /public/ {
proxy_pass http://vantage_server;
}
# /install, /install.ps1, /update, /update.ps1
location ~ ^/(install|update)(\.ps1)?$ {
proxy_pass http://vantage_server;
}
location / {
proxy_pass http://vantage_web;
}
}
```
The `Upgrade`/`Connection` headers and `proxy_buffering off` are not optional:
without them the browser console cannot open its WebSocket and live workflow
logs arrive in bursts or not at all.
### Terminating TLS in nginx
The shipped config speaks plain HTTP, which is right when another proxy or load
balancer in front of it already terminates TLS. To terminate TLS in the bundled
nginx instead, mount your certificate and add a `443` server, redirecting `80`
to it.
In `docker-compose.yml`, extend the `nginx` service:
```yaml
nginx:
ports:
- 80:80
- 443:443
volumes:
- ./nginx/vantage.conf:/etc/nginx/conf.d/default.conf:ro
- ./certs:/etc/nginx/certs:ro
```
In `nginx/vantage.conf`, replace the `listen 80` lines of the existing server
with the TLS ones, and add a redirect server:
```nginx
server {
listen 80;
listen [::]:80;
server_name vantage.example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
listen [::]:443 ssl;
http2 on;
server_name vantage.example.com;
ssl_certificate /etc/nginx/certs/fullchain.pem;
ssl_certificate_key /etc/nginx/certs/privkey.pem;
# ... the rest of the shipped server block, unchanged ...
}
```
### Agent traffic on 9090
Agents connect to port `9090`. Vantage does not terminate TLS itself, so put
that port behind your proxy too, with a certificate valid for the name in
@@ -113,6 +234,33 @@ that port behind your proxy too, with a certificate valid for the name in
by default, and the symptom is agents that register once and then stop
responding.
With the bundled nginx, remove `9090:9090` from the `server` service's `ports`,
add `9090:9090` to the `nginx` service, and add this server to
`nginx/vantage.conf`:
```nginx
server {
listen 9090 ssl;
listen [::]:9090 ssl;
http2 on;
server_name vantage.example.com;
ssl_certificate /etc/nginx/certs/fullchain.pem;
ssl_certificate_key /etc/nginx/certs/privkey.pem;
# Command streams are long-lived; do not time them out.
grpc_read_timeout 1h;
grpc_send_timeout 1h;
location / {
grpc_pass grpc://server:9090;
}
}
```
`grpc://` is plain HTTP/2 (h2c) to the container, which is what the server
speaks.
For a private network where TLS is not required, you can instead set
`tls: false` in each [agent's config](../reference/agent-config.md) and let
agents reach the port directly.
@@ -128,8 +276,9 @@ Continue with [First login](./first-login.md).
| Check | Expected |
| ---------------------------------------------- | ------------------------------- |
| `docker compose ps` | five services `running` |
| `docker compose ps` | six services `running` |
| `curl -s localhost:8080/auth/bootstrap-status` | JSON saying bootstrap is needed |
| `curl -s localhost/auth/bootstrap-status` | the same JSON, through nginx |
| `nc -z your-host 9090` | open |
| `docker compose logs server` | no fatal errors |