Installation
Prerequisites
- A Linux host with Docker Engine 24+ and the compose plugin.
- Three DNS names pointing to the host (
A/AAAArecords):PLATFORM_DOMAIN, for examplehub.example.com: Entrosity Hub (sign-in) at/, Axis at/axis(portal, API, agents), the documentation at/docs;RMM_DOMAIN, for examplermm.example.com: only the API for agents, connectors and scripts that were enrolled against it (an installation from before the Hub); browsers are redirected to the Hub's name;RMM_FILES_DOMAIN, for examplefiles.rmm.example.com: downloads and uploads.
- Ports 80 and 443 open from the Internet (ACME HTTP-01, agents, browsers).
- An SMTP account for the Hub's invitations and password resets and Axis's alert e-mails.
Steps
1. Get the files
sudo git clone https://github.com/entrosity/entrosity-infra.git /opt/entrosity
cd /opt/entrosity/deploy
2. Write deploy/.env
Create deploy/.env with mode 600 and fill it in. Generate every secret
with openssl rand -base64 32.
Start from the template: cp deploy/.env.prod.example deploy/.env. It
holds the values below; all of them are required except the optional
block.
# Names and certificates
PLATFORM_DOMAIN=hub.example.com # Entrosity Hub; Axis at /axis, the docs at /docs
RMM_DOMAIN=rmm.example.com # API for agents enrolled against it; browsers go to the Hub
# PLATFORM_OLD_DOMAINS=portal.example.com # earlier Hub names (set by platform-cutover.sh move)
RMM_FILES_DOMAIN=files.rmm.example.com
# Database
POSTGRES_PASSWORD=<random> # owner "rmm": migrations and backups
RMM_APP_DATABASE_PASSWORD=<random> # "rmm_app": what the backends use
# Object storage
MINIO_ROOT_USER=rmm
MINIO_ROOT_PASSWORD=<random>
# Secrets (keep a copy of this file somewhere safe!)
RMM_JWT_SECRET=<random, 32+ bytes>
RMM_MASTER_KEY=<exactly 32 bytes, base64>
RMM_RELEASE_SIGNING_KEY=<from make release-keygen>
RMM_RELEASE_TOKEN=<random, 32+ characters>
# Mail
RMM_SMTP_HOST=smtp.example.com
RMM_SMTP_PORT=587
RMM_SMTP_PASS=<password>
# Entrosity Hub (sign-in for all Entrosity products; mails through RMM_SMTP_*)
PLATFORM_APP_DATABASE_PASSWORD=<random> # "platform_app": what the Hub uses
PLATFORM_JWT_SIGNING_KEY=<random> # Ed25519 seed (32 bytes, base64): signs every Hub token
PLATFORM_MASTER_KEY=<random> # exactly 32 bytes, base64: TOTP seeds, queued e-mails
PLATFORM_PRODUCT_TOKEN_RMM=<random> # 32+ characters: Axis's access to the Hub's internal API
# [email protected] # default: RMM_SMTP_FROM
# Optional
# RMM_VERSION=1.0.0 # image tag (set by upgrade.sh / deploy.sh)
# PG_SHARED_BUFFERS=1GB PG_EFFECTIVE_CACHE_SIZE=3GB PG_WORK_MEM=16MB
# PG_MAINTENANCE_WORK_MEM=256MB PG_MAX_CONNECTIONS=200
# PG_ARCHIVE_MODE=on PG_ARCHIVE_COMMAND=... # point-in-time recovery
# RMM_BACKEND_MEMORY=2g RMM_BACKEND_GOMEMLIMIT=1400MiB PLATFORM_MEMORY=512m
# RMM_BACKUP_DIR=./backups RMM_BACKUP_KEEP_DAYS=14
# RMM_BACKUP_S3_ENDPOINT= RMM_BACKUP_S3_BUCKET= RMM_BACKUP_S3_ACCESS_KEY= RMM_BACKUP_S3_SECRET_KEY=
The backend reads the whole file (env_file: .env); compose derives
RMM_PUBLIC_URL and RMM_PORTAL_URL (https://$PLATFORM_DOMAIN/axis),
RMM_CORS_ORIGINS, the RMM_PLATFORM_* settings, the Hub's settings, the
S3 settings and the database URLs from the values above. Users sign in at
https://$PLATFORM_DOMAIN/ and open Axis at https://$PLATFORM_DOMAIN/axis/;
new agents and connectors enroll with SERVER_URL=https://$PLATFORM_DOMAIN/axis.
Everything else is in the Configuration reference.
.envRMM_MASTER_KEY encrypts Axis's stored secrets (AD passwords, queued
e-mails), PLATFORM_MASTER_KEY the Hub's (TOTP seeds, queued e-mails). A
backup cannot be decrypted without the keys it was made with.
With RMM_ENV=prod (set by compose) the backend refuses the development
example secrets from deploy/.env.example.
3. Start the stack
docker compose -f docker-compose.prod.yml --env-file .env up -d
migrate runs first; platform-db-init creates the Hub's platform
database and platform-migrate its schema. The Hub (platform) and the
backends start once their schemas are current, and web once a backend
is healthy. Caddy obtains the certificates on the first request.
4. Create the first admin
The first admin is a platform admin of Entrosity Hub, which makes them a global admin in Axis:
docker compose -f docker-compose.prod.yml --env-file .env run --rm platform \
bootstrap-admin --email [email protected] --password-stdin
Type the password (12+ characters) and press Enter. This only works while
no platform admin exists. Then open https://hub.example.com, sign in,
set up two-factor authentication on the Account page, and create the
first organization with Entrosity Axis enabled
(Platform administration): it appears in Axis
as a tenant within a minute. Open Axis from the product list or at
https://hub.example.com/axis/.
5. Start at boot
The systemd unit runs compose from /opt/entrosity:
sudo cp /opt/entrosity/deploy/systemd/rmm.service /etc/systemd/system/
sudo systemctl daemon-reload && sudo systemctl enable --now rmm
6. Publish the agent and connector
Agents are installed from the newest published stable release. Publish one before creating enrollment tokens:
- let the release workflows of
entrosity-axis-agentandentrosity-axis-connectordo it: set the repository variablesRMM_API_URLandRELEASE_PUBLISH_ENABLED=trueand the secretsRMM_RELEASE_TOKEN(the server's) andRELEASE_PUBLIC_KEY(the public half ofRMM_RELEASE_SIGNING_KEY); or - upload the MSIs under Admin → Agent releases; or
- in a checkout of
entrosity-axis.backend:go run ./cmd/publish-agent --product agent --file rmm-agent.msi --version 1.0.0 --channel stable.
See Agent releases.
7. Host App Installer for winget (optional)
Devices without winget install it from files the server hosts. Upload the
App Installer .msixbundle and its dependency .appx files (VCLibs,
UI.Xaml) to the bucket under releases/winget/, e.g. with the MinIO
client in the minio-init container.
8. Back up and monitor
Set up the nightly backup and, optionally, monitoring.
Lab installation without public DNS
Set PLATFORM_DOMAIN=localhost, RMM_DOMAIN=rmm.localhost and
RMM_FILES_DOMAIN=files.localhost. Caddy then issues certificates from
its own CA. Agents need that CA trusted:
docker compose -f docker-compose.prod.yml cp web:/data/caddy/pki/authorities/local/root.crt .
Install root.crt in Trusted Root Certification Authorities on the test
machines.