Skip to main content

Installation

Prerequisites​

  • A Linux host with Docker Engine 24+ and the compose plugin.
  • Three DNS names pointing to the host (A/AAAA records):
    • PLATFORM_DOMAIN, for example hub.example.com: Entrosity Hub (sign-in) at /, Axis at /axis (portal, API, agents), the documentation at /docs;
    • RMM_DOMAIN, for example rmm.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 example files.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.

deploy/.env
# 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.

danger
Keep a copy of .env

RMM_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-agent and entrosity-axis-connector do it: set the repository variables RMM_API_URL and RELEASE_PUBLISH_ENABLED=true and the secrets RMM_RELEASE_TOKEN (the server's) and RELEASE_PUBLIC_KEY (the public half of RMM_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.