Set up
Set up the HUB
The HUB is the deployment's control plane and discovery authority. Every client and service resolves through it, and its domain is the discovery URL, chosen once for the whole deployment.
The HUB binary is appserv. Install it with the install pattern, using the package mountos-appserv. It needs two things of its own, an admin database
and a Hub vault that holds its secrets (the database connection and its signing
and verification keys).
Database and dialect
Create an empty database, then put two values in the Hub vault, DB_URL (the connection) and DB_DIALECT. The dialect is
a deployment choice between two dialects, postgresql and mysql (the MySQL dialect covers any MySQL-wire store). Use PostgreSQL when there is no database preference. The schema ships for both, so the choice costs no capability.
Then run appserv db install once. It reads DB_URL and DB_DIALECT from the vault, downloads the schema for that dialect, and
applies it, all in one step. The schema is cached, so it is fetched once and reused.
./mountos-install --pkg mountos-appserv
mountos-appserv env -w .env # config template (the Hub vault serves the sensitive values)
export MOUNTOS_LICENSE_PATH=$PWD/license
set -a
. ./.env
mountos-appserv db install # download + apply the admin schema (dialect from the vault)
mountos-appserv # start the HUBConfiguration
appserv env prints the full template.
The Hub vault (key mountos/appserv) holds these values.
DB_URLis the admin database connection.DB_DIALECTpicks the schema,postgresqlormysql.DB_PROVIDER_VERSIONis the engine version for capability detection, like16or8.0.32.ED25519_SIGNING_KEYis the HUB's private signing key.ED25519_VERIFICATION_KEYis its matching public key.PROVIDER_VERIFICATION_KEYis the admin public key. appserv checks SDK-signed Admin API calls against it (see Admin API access).
The environment file carries these values.
VAULT_PROVIDERnames the secret store and carries its address and role credentials.HTTPS_PORTis the discovery and Admin API listen port.TLS_CERT_FILEis the TLS certificate path.TLS_KEY_FILEis the TLS private key path.MOUNTOS_LICENSE_PATHis the license path, a file or a directory of stacked license files.ADVERTISE_ADDRis the public IPv4 the HUB advertises.
Connection-pool and rate-limit tuning are optional, in the same template.
To upgrade an existing HUB later, run db migrate. It applies only the
new migrations in range for the binary. The command is idempotent and safe to run
from more than one instance at once.
mountos-appserv db migrate # apply pending schema changes, then restartPublish the HUB behind a stable domain. That domain is the discovery URL every client is handed, so it is chosen once and kept. See Control plane and Vault and handshake.
Admin API access
After the HUB is published, administration is performed through the Admin API.
Only trusted backends sign Admin API requests with the admin key. appserv verifies
those signatures against PROVIDER_VERIFICATION_KEY.
The Admin SDK and the dashboard are covered on the Admin SDK and dashboard page.
Create an account and a region
An account is the tenant. Create it, add a user, then create a region. The region's
default cluster, uno, is created with it.
// an account is the tenant
const { id: accountId } = await client.accounts.create({ name: 'mountOS' })
const { id: userId } = await client.users.add({
accountId, username: 'jason', email: 'jason@mountos.io', name: 'Jason Ryan',
})
// creating the region auto-creates its default cluster, "uno"
const { id: regionId } = await client.regions.create({
accountId, name: 'us-east-1', dns: 'us-east-1.example.com',
})// an account is the tenant
acct, err := client.Accounts.Create(ctx, &sdk.CreateAccountRequest{Name: "mountOS"})
user, err := client.Users.Add(ctx, &sdk.AddUserRequest{
AccountID: acct.ID, Username: "jason", Email: "jason@mountos.io", Name: "Jason Ryan",
})
// creating the region auto-creates its default cluster, "uno"
region, err := client.Regions.Create(ctx, &sdk.CreateRegionRequest{
AccountID: acct.ID, Name: "us-east-1", DNS: "us-east-1.example.com",
})// an account is the tenant
let acct = client.accounts.create(&CreateAccountRequest {
name: "mountOS".into(),
description: None,
icon_url: None,
provider_info: None,
}).await?;
let user = client.users.add(&AddUserRequest {
account_id: acct.id,
username: "jason".into(),
email: "jason@mountos.io".into(),
name: Some("Jason Ryan".into()),
provider_info: None,
}).await?;
// creating the region auto-creates its default cluster, "uno"
let region = client.regions.create(&CreateRegionRequest {
account_id: acct.id,
name: "us-east-1".into(),
dns: "us-east-1.example.com".into(),
}).await?;These calls write records only, in the HUB's admin database. The region's own
database, vault, storage, and servers come up separately. uno stays not
ready until a service registers into it.
How trust works
Region services self-register with the HUB. No passwords are issued.
Each service is born with its own signing key in its vault, and the HUB holds the matching public keys. A service joins by signing a hello with its key, which the HUB checks against that set. A client carries no service credential. It discovers its region with an access key, then opens an encrypted session to the cluster. The Hub vault is the source of truth for the verifier set. See Vault and handshake.