feat: documentation site
Docusaurus 3 docs-only site at docsite/, served statically by nginx under /docs on the marketing host. Covers getting started (self-hosted install through first server and first licence), the control plane, Vantage HQ, a reference section and operations. Wired into docker-compose.site.yml as docsite (3005:80) and into the image build workflow, rebuilding on its own directory only. Never added to the self-hosted compose file.
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
---
|
||||
id: accounts-and-signup
|
||||
title: Accounts and signup
|
||||
sidebar_label: Accounts and signup
|
||||
---
|
||||
|
||||
Vantage HQ, at `vantage-hq.hostxtra.co.uk`, is where you manage the **account**
|
||||
behind your instances: your team, your instances, their licences and billing.
|
||||
|
||||
## An account is a team, not a person
|
||||
|
||||
One account holds many people and many instances. Everyone in it has an account
|
||||
role:
|
||||
|
||||
| Role | Can |
|
||||
| --- | --- |
|
||||
| `owner` | Everything, including billing |
|
||||
| `admin` | Invite people, create instances, grant instance access |
|
||||
| `member` | Read what the account holds |
|
||||
|
||||
Reading is open to any signed-in member. Every mutation except changing your own
|
||||
password requires `owner` or `admin`. Billing is owner-only.
|
||||
|
||||
The three words are the same as the control plane's roles, on purpose — but they
|
||||
are separate things. Your account role governs the portal; your role *inside* an
|
||||
instance governs that instance.
|
||||
|
||||
## Signing up
|
||||
|
||||
Signup is **account-first**. Creating an account creates the account and you;
|
||||
it does not create a Vantage instance. Nothing exists in any control plane until
|
||||
you later create or link one.
|
||||
|
||||
1. Go to the signup form.
|
||||
2. Enter your name, email and a password.
|
||||
3. Check your email and click the verification link.
|
||||
|
||||
:::info Verify before you can sign in
|
||||
An unverified account gets a distinct "check your email" message rather than a
|
||||
generic authentication failure — the address is already known to be yours, so
|
||||
there is nothing to protect by being vague.
|
||||
:::
|
||||
|
||||
Verification links are valid for **24 hours**. The token is 32 random bytes and
|
||||
only its SHA-256 hash is stored, so a leaked database yields no working links.
|
||||
|
||||
If the verification email cannot be sent, the signup is rolled back rather than
|
||||
left stranded — retry rather than assuming a half-created account is in the way.
|
||||
|
||||
## Signing in
|
||||
|
||||
Email and password. The session is a cookie, separate from the control plane's:
|
||||
signing in to HQ does not sign you in to an instance, and vice versa.
|
||||
|
||||
## What comes next
|
||||
|
||||
| You want | Go to |
|
||||
| --- | --- |
|
||||
| A Vantage instance we run | [Cloud instances](./cloud-instances.md) |
|
||||
| To license an install you run | [Self-hosted instances](./self-hosted-instances.md) |
|
||||
| To add colleagues | [People and roles](./people-and-roles.md) |
|
||||
| To understand tiers and limits | [Licensing and entitlements](./licensing-and-entitlements.md) |
|
||||
|
||||
## The portal layout
|
||||
|
||||
Three destinations: **Overview**, **People**, **Billing**.
|
||||
|
||||
Settings lives in the account menu rather than the nav, because it is your
|
||||
password rather than a place. The appearance toggle is there too.
|
||||
|
||||
Overview lists your instances. Each is one record, closed to a row and open to
|
||||
its licence contents, members and actions. It opens by default when it is your
|
||||
only instance or when it needs attention, and your manual choice is remembered.
|
||||
|
||||
There is deliberately no "your plan" card in the sidebar: tier, limits and
|
||||
expiry belong to a **licence**, and a licence belongs to one instance. An
|
||||
account with a Free cloud instance and a Professional self-hosted one has no
|
||||
single plan to show.
|
||||
@@ -0,0 +1,83 @@
|
||||
---
|
||||
id: billing
|
||||
title: Billing
|
||||
sidebar_label: Billing
|
||||
---
|
||||
|
||||
Paid plans are billed through **Paddle**, which is the merchant of record. Your
|
||||
invoice, your card details and your tax handling are all Paddle's; HQ holds a
|
||||
customer reference and nothing sensitive.
|
||||
|
||||
Billing is **owner-only**.
|
||||
|
||||
## Buying
|
||||
|
||||
### Cloud
|
||||
|
||||
Open the instance, change its configuration to what you want, and check out.
|
||||
Checkout runs in the browser.
|
||||
|
||||
### Self-hosted
|
||||
|
||||
**Buy self-hosted**, then bind the purchase to your install's UUID. See
|
||||
[Self-hosted instances](./self-hosted-instances.md).
|
||||
|
||||
## What you are buying
|
||||
|
||||
A subscription's line items are the configuration: the plan base, the metered
|
||||
server count above the base, and any per-instance features. Changing the
|
||||
configuration changes the line items.
|
||||
|
||||
## Changing configuration
|
||||
|
||||
**Instance → Configuration**, adjust servers or features, and save.
|
||||
|
||||
- **Increases** take effect when the payment confirms.
|
||||
- **Reductions** are scheduled for the end of the term. The portal shows the
|
||||
date and the new value.
|
||||
|
||||
## The customer portal
|
||||
|
||||
**Billing → Manage** mints a Paddle customer-portal session where you can
|
||||
update your payment method, see invoices and cancel.
|
||||
|
||||
## How a licence follows a payment
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
C["Checkout / change"] --> P["Paddle"]
|
||||
P -->|signed webhook| H["HQ"]
|
||||
H --> G["Entitlement: desired → granted"]
|
||||
G --> L["Licence signed from granted"]
|
||||
```
|
||||
|
||||
The webhook is the **only** issuing path for paid plans. It is signature
|
||||
verified, processed exactly once, and resolved from the subscription's *current*
|
||||
line items — so a webhook that arrives out of order still produces the right
|
||||
answer rather than replaying a stale state.
|
||||
|
||||
A licence is signed from **granted** only. A checkout you abandon changes
|
||||
nothing.
|
||||
|
||||
## Cancelling and failed payments
|
||||
|
||||
Cancelling, or a payment going past due, takes **no immediate licence action**.
|
||||
Your licence runs to its grace-padded expiry and then lapses normally. There is
|
||||
no mid-term cut-off.
|
||||
|
||||
For a cloud Free instance, lapsing eventually leads to deletion — see
|
||||
[Free tier](./free-tier.md). Paid instances are not reaped.
|
||||
|
||||
## Renewals
|
||||
|
||||
At renewal the subscription bills again and the licence is reissued for the new
|
||||
term. It is also the only moment a scheduled **reduction** takes effect.
|
||||
|
||||
Self-hosted customers: download and paste the reissued licence. Cloud customers:
|
||||
nothing to do.
|
||||
|
||||
## Free is not in Paddle at all
|
||||
|
||||
Free has no subscription, no £0 line item and no Paddle record. It has its own
|
||||
renewal, in the portal. An account only acquires a Paddle customer reference
|
||||
with its first paid purchase.
|
||||
@@ -0,0 +1,78 @@
|
||||
---
|
||||
id: cloud-instances
|
||||
title: Cloud instances
|
||||
sidebar_label: Cloud instances
|
||||
---
|
||||
|
||||
A cloud instance is a Vantage control plane we run for you, reachable at
|
||||
`<your-slug>.vantage.hostxtra.co.uk`.
|
||||
|
||||
## Creating one
|
||||
|
||||
1. **Overview → New instance**.
|
||||
2. Choose a name and a slug.
|
||||
3. Create.
|
||||
|
||||
The instance is provisioned with you as its owner, and a Free licence is issued
|
||||
immediately. The owner user inside it gets your HQ password hash **copied**, not
|
||||
shared — see [People and roles](./people-and-roles.md).
|
||||
|
||||
### Slugs
|
||||
|
||||
The slug becomes your hostname label, so it is lowercase, and some names are
|
||||
reserved. Pick something you can say on a phone call.
|
||||
|
||||
:::warning One Free instance per account, per deployment
|
||||
Creating a second Free cloud instance is refused. If you want another, it needs
|
||||
a paid plan — or free up the first.
|
||||
:::
|
||||
|
||||
## Using it
|
||||
|
||||
Sign in at your instance's hostname with the email and password you use for HQ.
|
||||
It is a normal Vantage install from that point: see
|
||||
[Getting started](../getting-started/first-login.md) and the
|
||||
[Vantage](../vantage/servers.md) section.
|
||||
|
||||
The instance does not depend on HQ at runtime. HQ being unreachable does not
|
||||
affect anyone signing in or any agent syncing.
|
||||
|
||||
## The instance record
|
||||
|
||||
Each instance on Overview is one record. Closed, it is a row. Open, it shows:
|
||||
|
||||
- **Licence contents** — tier, server allowance, features, expiry.
|
||||
- **Members** — who has access and with what instance role.
|
||||
- **Actions** — grant access, change configuration, renew.
|
||||
|
||||
## Members
|
||||
|
||||
Granting access writes a real user into the instance. Covered fully in
|
||||
[People and roles](./people-and-roles.md).
|
||||
|
||||
## Changing what it can do
|
||||
|
||||
Server allowance and per-instance features (browser console, single sign-on) are
|
||||
part of the instance's **entitlement**. Changing it goes through billing — see
|
||||
[Licensing and entitlements](./licensing-and-entitlements.md) and
|
||||
[Billing](./billing.md).
|
||||
|
||||
## Renaming
|
||||
|
||||
The display name is free to change. The slug is the hostname and is not
|
||||
casually changed — ask support if you need it.
|
||||
|
||||
## What happens if the licence lapses
|
||||
|
||||
A cloud instance whose Free licence expires enters degraded mode, then, after a
|
||||
grace period, the instance and all its data are deleted. Warning emails go out
|
||||
first. See [Free tier](./free-tier.md).
|
||||
|
||||
Paid instances do not get reaped by that mechanism. A cancelled subscription
|
||||
runs to its grace-padded expiry and then lapses.
|
||||
|
||||
## Deleting
|
||||
|
||||
Ask support. Deletion is performed by the control plane, not by HQ — the control
|
||||
plane is the only service that knows which collections carry the instance ID,
|
||||
and duplicating that list into HQ would be a list that drifts.
|
||||
@@ -0,0 +1,79 @@
|
||||
---
|
||||
id: free-tier
|
||||
title: Free tier
|
||||
sidebar_label: Free tier
|
||||
---
|
||||
|
||||
Free is a real tier in both deployments — not a trial that turns into nothing.
|
||||
|
||||
## What you get
|
||||
|
||||
| | Free |
|
||||
| --- | --- |
|
||||
| Servers | 3 |
|
||||
| Monitors | 3 |
|
||||
| Secret groups | 1 |
|
||||
| Notification channels | 1 |
|
||||
| Audit retention | 30 days |
|
||||
| Support | Community |
|
||||
|
||||
Browser console and single sign-on are not included; they are per-instance
|
||||
features on a paid plan.
|
||||
|
||||
## One per account, per deployment
|
||||
|
||||
The limit is enforced per account **and** deployment. A Free cloud instance does
|
||||
not prevent a Free self-hosted one — they are separate slots.
|
||||
|
||||
## Free is outside Paddle
|
||||
|
||||
There is no subscription, no £0 line item and no invoice. Your account acquires
|
||||
a Paddle customer reference only with its first paid purchase.
|
||||
|
||||
## Renewing
|
||||
|
||||
Free licences have a term and must be renewed from the portal.
|
||||
|
||||
- The renew button appears **7 days before expiry**.
|
||||
- It stays available **after** expiry, right up until the instance is reaped —
|
||||
so the same button rescues a lapsed instance rather than needing a second
|
||||
mechanism.
|
||||
- Renewing outside that window is refused, and the message names the date it
|
||||
opens.
|
||||
|
||||
:::tip Put the expiry in a calendar
|
||||
Warning emails go to the account address. If nobody watches that inbox, a Free
|
||||
cloud instance can lapse and eventually be deleted without anyone noticing.
|
||||
:::
|
||||
|
||||
## What happens when it lapses
|
||||
|
||||
**Self-hosted:** the instance goes into degraded mode after the grace period and
|
||||
stays that way. Nothing is deleted, ever — the reaper is disabled by default on
|
||||
a self-hosted install and must stay that way.
|
||||
|
||||
**Cloud:** the instance goes into degraded mode, and after a further period the
|
||||
instance **and all its data are deleted**. Warning emails are sent first, naming
|
||||
the date.
|
||||
|
||||
:::danger Deletion is permanent
|
||||
There is no restore. If a cloud Free instance is approaching that date and you
|
||||
want to keep it, renew it, or move it to a paid plan.
|
||||
:::
|
||||
|
||||
Deletion is carried out by the control plane rather than by HQ. HQ sends the
|
||||
warnings because it knows the billing address; the control plane performs the
|
||||
delete because it is the only service that knows which collections carry the
|
||||
instance ID.
|
||||
|
||||
## Moving off Free
|
||||
|
||||
Change the instance's configuration to a paid tier and check out. Your data
|
||||
stays where it is — a tier change reissues a licence, it does not rebuild
|
||||
anything.
|
||||
|
||||
## Relinks
|
||||
|
||||
Free instances get the same relink allowance as paid ones: three per term. That
|
||||
cap exists to put a human in front of a fourth attempt, not to obstruct a
|
||||
genuine rebuild.
|
||||
@@ -0,0 +1,95 @@
|
||||
---
|
||||
id: licensing-and-entitlements
|
||||
title: Licensing and entitlements
|
||||
sidebar_label: Licensing and entitlements
|
||||
---
|
||||
|
||||
A **licence** is a signed statement of what one instance may do. An
|
||||
**entitlement** is the configuration a licence is cut from.
|
||||
|
||||
## Tiers
|
||||
|
||||
Three tiers, in both deployments. The allowances are identical across cloud and
|
||||
self-hosted — what differs is the term on offer, not what you get.
|
||||
|
||||
| | Free | Professional | Enterprise |
|
||||
| --- | --- | --- | --- |
|
||||
| Servers (base) | 3 | 3 | 10 |
|
||||
| Monitors | 3 | unlimited | unlimited |
|
||||
| Secret groups | 1 | unlimited | unlimited |
|
||||
| Notification channels | 1 | unlimited | unlimited |
|
||||
| Audit retention | 30 days | 365 days | unlimited |
|
||||
| Support | Community | Email, 24×5 | Email and phone, 24×7 |
|
||||
|
||||
The server count is **metered**: the base allowance comes with the tier, and you
|
||||
buy additional servers on top. That is why Professional shows a real number
|
||||
rather than "unlimited" — the number you actually have is the one in your
|
||||
entitlement.
|
||||
|
||||
## Features
|
||||
|
||||
Two are per-instance toggles rather than tier bundles:
|
||||
|
||||
| Feature | What it enables |
|
||||
| --- | --- |
|
||||
| `console` | The [browser console](../vantage/browser-console.md) |
|
||||
| `oidc` | Per-instance [single sign-on](../vantage/settings.md#single-sign-on-oidc) |
|
||||
|
||||
No tier includes them by default; you enable them on the instances that need
|
||||
them.
|
||||
|
||||
## Entitlements: desired and granted
|
||||
|
||||
Each instance has one entitlement row holding two configurations:
|
||||
|
||||
| | Meaning |
|
||||
| --- | --- |
|
||||
| **Desired** | What you last asked for |
|
||||
| **Granted** | What a payment has confirmed |
|
||||
|
||||
Checkout is built from **desired**. A licence is only ever signed from
|
||||
**granted**. An abandoned checkout therefore leaves a desired that reached
|
||||
nothing and changed nothing.
|
||||
|
||||
### Increases and reductions
|
||||
|
||||
An increase takes effect when payment confirms, and the entitlement is promoted
|
||||
desired → granted.
|
||||
|
||||
A **reduction** is scheduled rather than immediate: you keep what you paid for
|
||||
until the end of the term, and the portal shows the date it drops. The collapse
|
||||
happens at renewal.
|
||||
|
||||
## What a licence carries
|
||||
|
||||
Instance UUID, deployment, tier, resolved limits, features, term and expiry —
|
||||
all signed.
|
||||
|
||||
Two properties follow from that:
|
||||
|
||||
- **A licence is bound to one instance UUID.** Moving it takes a
|
||||
[relink](./self-hosted-instances.md#relinking).
|
||||
- **A licence is a snapshot.** Editing a plan later never rewrites an issued
|
||||
licence, the same way editing a workflow step never rewrites a past run.
|
||||
|
||||
Verification is local. Your instance does not call HQ to check a licence, and
|
||||
signing happens only in HQ.
|
||||
|
||||
## Expiry and grace
|
||||
|
||||
Expiry is padded with a grace period. Past that, the instance goes into degraded
|
||||
mode: it keeps running and keeps your data, but stops letting you do everything.
|
||||
|
||||
The way out is a current licence — renew or purchase, then paste it (self-hosted)
|
||||
or let it be written for you (cloud).
|
||||
|
||||
## Server limits in practice
|
||||
|
||||
When you exceed your server allowance, enrolling another one is refused. The
|
||||
existing fleet is unaffected. Raise the allowance in the portal, or remove a
|
||||
server you are not using.
|
||||
|
||||
## Legacy tiers
|
||||
|
||||
An older `self_hosted` tier is mapped forward to self-hosted Professional
|
||||
wherever it appears. Nothing needs doing about it.
|
||||
@@ -0,0 +1,98 @@
|
||||
---
|
||||
id: people-and-roles
|
||||
title: People and roles
|
||||
sidebar_label: People and roles
|
||||
---
|
||||
|
||||
Two separate things live here: who is in your **account**, and who has access to
|
||||
each **instance**.
|
||||
|
||||
## Account members
|
||||
|
||||
**People** lists everyone in the account.
|
||||
|
||||
| Role | Can |
|
||||
| --- | --- |
|
||||
| `owner` | Everything, including billing |
|
||||
| `admin` | Invite, create instances, grant instance access |
|
||||
| `member` | Read |
|
||||
|
||||
Owners and admins invite; billing is owner-only.
|
||||
|
||||
### Inviting someone
|
||||
|
||||
1. **People → Invite**.
|
||||
2. Enter their email and pick a role.
|
||||
3. They receive a link and set their own password at `/accept-invite`.
|
||||
|
||||
:::info Why you cannot set their password
|
||||
An invitation creates a person with an **empty password hash**, which cannot
|
||||
authenticate at all until they set one. If the inviter chose it, that password
|
||||
would be a shared credential to every instance the person is later granted
|
||||
access to.
|
||||
|
||||
The verification endpoint knows the difference: a token belonging to a
|
||||
passwordless person reports that a password is needed and is left unspent, so
|
||||
the link still works when they get to it.
|
||||
:::
|
||||
|
||||
### Removing someone
|
||||
|
||||
Removing them from the account removes their portal access. See below for what
|
||||
happens to their instance access.
|
||||
|
||||
## Instance access
|
||||
|
||||
Granting access to a **cloud** instance creates a real user inside that
|
||||
instance's control plane, with `auth_source: "hq"`.
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
P["HQ account member"] -->|grant| U["Control-plane user<br/>auth_source: hq"]
|
||||
U --> I["The instance authenticates<br/>this user like any other"]
|
||||
```
|
||||
|
||||
The instance authenticates that user exactly as it authenticates anyone else,
|
||||
with **no runtime dependency on HQ**. Revoking deletes the row — the control
|
||||
plane has no disabled state, and a row that exists is a row that can sign in.
|
||||
|
||||
### Granting
|
||||
|
||||
On an instance record, **Members → Add**, choose an account member and an
|
||||
instance role (`owner`, `admin`, `member`).
|
||||
|
||||
One person holds at most one user per instance, so granting twice is refused
|
||||
rather than quietly creating a second user.
|
||||
|
||||
### Roles inside an instance
|
||||
|
||||
Independent of the account role. Someone can be an account `member` and an
|
||||
instance `owner`, or the reverse.
|
||||
|
||||
### Revoking
|
||||
|
||||
Removes the user from the instance immediately. Any live session ends with the
|
||||
session, since the user row backing it is gone.
|
||||
|
||||
:::warning Self-hosted instances cannot be granted from HQ
|
||||
All three member endpoints refuse when the instance is self-hosted. Manage those
|
||||
users in the instance itself, at **Settings → Access**.
|
||||
:::
|
||||
|
||||
## Passwords
|
||||
|
||||
Your HQ password is the single source of truth for every user projected from it.
|
||||
Changing it in the portal rehashes it and copies the hash to every instance you
|
||||
have been granted.
|
||||
|
||||
Propagation is best-effort and immediate; a background pass compares and repairs
|
||||
every 15 minutes, so a temporarily unreachable instance catches up on its own.
|
||||
|
||||
There is no local password-change endpoint for those users in the control plane,
|
||||
so there is never a second writer for the hash.
|
||||
|
||||
:::warning HQ-managed users are read-only in the instance
|
||||
Changing the role of, or deleting, an `hq`-sourced user inside the control plane
|
||||
is refused with `409`. Do it from the portal. The UI shows those rows read-only
|
||||
with a link back here, but the API is the boundary; the UI is the courtesy.
|
||||
:::
|
||||
@@ -0,0 +1,74 @@
|
||||
---
|
||||
id: self-hosted-instances
|
||||
title: Self-hosted instances
|
||||
sidebar_label: Self-hosted instances
|
||||
---
|
||||
|
||||
A self-hosted instance is your install, licensed through HQ. HQ never touches
|
||||
it: it issues a signed file that your install verifies locally.
|
||||
|
||||
## Free
|
||||
|
||||
Install first, then link and claim. Step by step in
|
||||
[Claim a Free licence](../getting-started/claim-free-licence.md).
|
||||
|
||||
## Paid
|
||||
|
||||
Buying happens **before** the install has to exist, because you may well be
|
||||
buying in order to build it.
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
A["Buy in HQ"] --> B["Placeholder instance<br/>awaiting_link, no licence"]
|
||||
B --> C["Install Vantage<br/>get its instance UUID"]
|
||||
C --> D["Paste the UUID<br/>claim-link"]
|
||||
D --> E["Licence issued<br/>bound to that UUID"]
|
||||
```
|
||||
|
||||
1. **Overview → Buy self-hosted**, choose tier, term and configuration.
|
||||
2. Complete checkout. HQ creates a **placeholder** instance in state
|
||||
`awaiting_link` with no licence attached.
|
||||
3. [Install Vantage](../getting-started/self-hosted-install.md) if you have not
|
||||
already, and find its instance UUID at **Settings → Licence**.
|
||||
4. Back in HQ, open the placeholder and paste the UUID.
|
||||
5. The licence is issued, bound to that UUID. Download it and paste it into your
|
||||
install.
|
||||
|
||||
:::info Why there is a placeholder at all
|
||||
A licence binds to an instance UUID, and at the moment of payment that UUID may
|
||||
not exist yet. Issuing early would mean issuing to nothing; refusing to sell
|
||||
until you had installed would be the wrong order. The placeholder holds the
|
||||
purchase until there is something to bind to.
|
||||
:::
|
||||
|
||||
## Linking an existing install
|
||||
|
||||
If the install already exists, **Link an instance** takes the UUID directly. A
|
||||
UUID already claimed by another account is refused with a conflict.
|
||||
|
||||
## Relinking
|
||||
|
||||
Rebuilding the host produces a new instance UUID, and the old licence no longer
|
||||
matches. **Relink** moves the licence to the new UUID and reissues.
|
||||
|
||||
The number of relinks per term is capped, and the portal shows how many you have
|
||||
left. This is not meant to obstruct disaster recovery — if you have exhausted
|
||||
them for a real reason, ask support.
|
||||
|
||||
## Installing the licence
|
||||
|
||||
Paste it at **Settings → Licence** in your install. The instance verifies the
|
||||
signature and checks that the UUID matches its own.
|
||||
|
||||
Pasting works even while the current licence is expired — that endpoint is
|
||||
exempt from the licence check, because it is the route out of degraded mode.
|
||||
|
||||
## Keeping it current
|
||||
|
||||
Your install does not fetch licences. When a licence is reissued — renewal,
|
||||
configuration change, relink — download the new one from HQ and paste it in.
|
||||
|
||||
:::warning Nothing reminds your install
|
||||
The control plane knows only what its licence says. Expiry emails come from HQ,
|
||||
to the account's address. Make sure someone reads them.
|
||||
:::
|
||||
Reference in New Issue
Block a user