Skip to content

Setup wizard

The first time you open a new instance, Steward shows a six-step wizard in the browser. It connects the console to the client's Active Directory, sets the outer boundary of what the console may ever touch, and makes you its first administrator. Every step is checked against the real directory before anything is saved. Once it finishes, the wizard closes for good.

Plan about 10 minutes, with these at hand (a domain administrator of the client usually prepares them):

You need Notes
The setup token Printed by install.sh, see step 1.
Domain DNS name, NetBIOS name, UPN suffixes For example corp.client-example.ch, CORP, client-example.ch.
The FQDN of 1 to 5 domain controllers LDAPS (TCP 636) must be reachable from the Docker host.
The CA certificate (PEM) that issued the DC certificates The console trusts only this CA for LDAPS.
A read service account (UPN + password) A standard user, never an administrator.
A write service account (optional) Only if operators will change attributes, groups, create or move accounts. A standard user too: its AD rights come later, from the AD delegation.
The DNs of the OUs to manage For example OU=Users,OU=Client,DC=corp,DC=client-example,DC=ch.
Your own non-privileged AD account Or a Teleport session, if the console is published through Teleport.

Collecting these values on the client's domain

Run these on a domain controller (or any machine with the ActiveDirectory module), in PowerShell:

(Get-ADDomain).DNSRoot, (Get-ADDomain).NetBIOSName            # domain DNS name, NetBIOS name
(Get-ADForest).UPNSuffixes                                    # extra UPN suffixes (the domain's own name is always one)
Get-ADDomainController -Filter * | Select-Object HostName, IPv4Address   # the DCs (FQDN) to type, never the IP

Service accounts. Create ordinary users; the UPN field of the wizard is their full sign-in name, as shown by Get-ADUser <name> | Select UserPrincipalName (for example svc-steward-read@corp.client-example.ch):

$d = 'corp.client-example.ch'
foreach ($n in 'svc-steward-read','svc-steward-write') {
  New-ADUser -Name $n -SamAccountName $n -UserPrincipalName "$n@$d" -AccountPassword (Read-Host "Password for $n" -AsSecureString) `
    -Enabled $true -PasswordNeverExpires $true -CannotChangePassword $true
}

Without -Path, New-ADUser creates the account in the default Users container (CN=Users), which Active Directory Users and Computers shows as a plain folder, not as an OU. Add -Path 'OU=Service accounts,DC=...' to put them elsewhere.

The CA certificate (PEM). It is the certificate of the authority that issued the DC certificates, not a DC certificate:

  • On a domain-joined Windows machine, an enterprise root CA is already in the Trusted Root store. This prints it as PEM, ready to paste (adjust the name to your CA):

    $c = Get-ChildItem Cert:\LocalMachine\Root | Where-Object Subject -like '*<your CA name>*'
    "-----BEGIN CERTIFICATE-----`n" + [Convert]::ToBase64String($c.RawData, 'InsertLineBreaks') + "`n-----END CERTIFICATE-----"
    
  • On the CA server: certutil '-ca.cert' ca.cer; certutil -encode ca.cer ca.pem. Keep the quotes: PowerShell splits an unquoted -ca.cert at the dot and certutil answers "Too many arguments".

  • openssl s_client -connect dc1.corp.example:636 -showcerts is not a way to get it: a DC usually sends only its own certificate, without the chain. If the block you see has a subject equal to the DC's name, it is the wrong one.

Before pasting, check on the Docker host that the certificate really signed the DC's (the line must end with OK):

openssl s_client -connect dc1.corp.example:636 </dev/null 2>/dev/null | openssl x509 > dc.pem
openssl verify -CAfile ca.pem -no-CApath dc.pem

The host must resolve the DC names (the container uses the host's DNS) and reach TCP 636: getent hosts dc1.corp.example and nc -zv dc1.corp.example 636. Otherwise point the host's DNS at a DC, or add extra_hosts entries (--add-host at install).

Never a privileged account

The service accounts and the first administrator must be ordinary accounts. Members of Domain Admins, Enterprise Admins, Schema Admins, Administrators and the other privileged groups cannot sign in to the console, and the AD delegation script refuses them as service accounts.

1. Setup token

The wizard is protected by a one-time token, so that nobody else on the network can configure the instance before you do.

  • install.sh prints it at the end of the installation. It is also stored in the container, in /data/setup-token (readable by the container user only), and written once to the container output at start:

    cd <instance folder> && docker compose exec steward cat /data/setup-token
    # or, by container name: docker exec steward-<name>-steward-1 cat /data/setup-token
    
  • A new token is generated at every start of the container while setup is not finished: after a restart, read the file again; the previous token no longer works.

  • Five wrong tokens lock the wizard. The page then answers "Invalid setup token, or the wizard is locked" whatever you type (a wrong token and a locked wizard look the same from the browser; the audit log tells them apart). To unlock it, re-open the wizard from the host, which prints a fresh token:

    docker exec steward-<name>-steward-1 dotnet Steward.Api.dll reset-setup --confirm
    

    Data already entered is kept. The same command is the recovery path when no administrator is left (see Operations).

Entering the right token opens a short-lived wizard session in this browser. It is tied to the current token: a restart or a reset-setup ends it, and you enter the new token.

2. Domain and LDAPS

Field What to enter
Domain DNS name The AD domain, e.g. corp.client-example.ch.
NetBIOS name Up to 15 characters, e.g. CORP. Lets operators sign in as CORP\jdoe.
UPN suffixes (one per line) 1 to 10 suffixes users sign in with (client-example.ch, ...). Onboarding templates use them too.
Domain controllers (FQDN, one per line) 1 to 5 DCs. A name, never an IP address: the name must match the DC's certificate.
Certificate authority (PEM) The certificate (or chain) of the CA that issued the DC certificates. Paste it, or choose the file.

When you click Next, the console opens an LDAPS connection (port 636) to each DC and validates its certificate strictly against that CA. The result is shown per DC; the step is saved only when every DC passes:

Result Meaning and fix
unreachable No TCP connection to 636: firewall, wrong name, or the Docker host cannot resolve the DC name (add it to the host's DNS, or re-run install.sh with --add-host dc1.corp.example.ch:10.0.0.10).
untrusted authority The DC certificate was not issued by the CA you pasted (wrong CA, or an intermediate is missing: paste the chain).
name does not match the certificate The DC's certificate does not contain the FQDN you typed.
expired / not yet valid Renew the DC certificate, or check the host's clock.

There is no "ignore certificate errors" option, by design. More cases: Troubleshooting.

3. Service accounts

Account Required Used for
Read account Yes Searching and reading users, groups and computers in the managed OUs, and classifying accounts (privileged or not).
Attribute write account No Every change made through the console's own rights: attributes, group members, creating, moving and renaming accounts, groups. Without it the console is read-only (plus the helpdesk actions, which use their own account).

Each password is tested with a real LDAPS bind before anything is saved ("The service account could not authenticate" means the bind was refused: password, disabled or locked account). Passwords are stored encrypted with the instance's master key and are never shown again. You can change them later in Configuration › Directory.

Accounts managed on the host

If the host provides an account as a Docker secret (Directory:ReadIdentity / Directory:WriteAttributesIdentity in the configuration), the wizard shows "Provided by a secret mounted on the host" and does not ask for it.

The helpdesk's password-reset account and the LAPS account are not entered here: they belong to the separate password service and are given to install.sh (--reset-upn, --laps-upn). See Helpdesk and LAPS.

4. Managed organizational units

The DNs of the OUs this instance manages, one per line (1 to 20). This is the outer boundary of the instance: no role, delegation or template can ever reach an object outside these OUs (and their sub-OUs). Each OU is looked up in AD with the read account and stored by its GUID, so a later rename or move of the OU does not break anything.

The domain root (DC=corp,DC=client-example,DC=ch) and anything outside the domain are refused ("This organizational unit is not allowed"). Keep the boundary as small as the contract: for example the client's user OUs, not the OU that holds servers or administrators. You can change the list later in Configuration › Directory (removing an OU still used by a delegation asks for a confirmation).

5. Sensitive groups

The well-known privileged groups are always protected and cannot be removed: Domain Admins, Schema Admins, Enterprise Admins, Administrators, and when they exist Account/Server/Print/Backup Operators, Group Policy Creator Owners, Domain Controllers, read-only DCs, Protected Users, Key Admins and Enterprise Key Admins. Their members (direct or nested) are treated as privileged: no operator can ever change them.

Here you add, by typing part of a name and picking from the list (a full DN or a SID also works), up to 20 groups of each kind:

  • VIP groups: accounts that are not administrators but deserve extra care (management, finance...). Their members can be changed only through a delegation that explicitly includes the VIP override (vip.manage).
  • Additional privileged groups: the client's own admin groups (server admins, tier-1 operators...). Their members are treated exactly like Domain Admins: never reachable.

Both lists may stay empty. You can edit them later in Configuration › Account protection, which also lets you declare Tier 0/1 OUs (every account below them is treated as privileged).

6. First administrator

Sign in with your own AD account (first.last@domain or DOMAIN\user). The sign-in goes through the same checks as any login: a privileged account is refused, and wrong passwords count against the normal throttling. If the console is published through Teleport and you opened it from Teleport, the wizard says so and your Teleport identity becomes the first administrator instead (no password typed).

This account receives the built-in Administrators role: it manages the application (configuration, roles and delegations, audit) and has no rights on AD objects. Nobody can touch a single AD account until you design roles.

Optional: tick "Also make this administrator a Super administrator" (unchecked by default) to receive, in addition, every directory action on every managed OU right away (VIP accounts included; privileged accounts stay out of reach). This is convenient for a small client, but it is a powerful role: you can remove it later in Delegations › Operators, and it is recorded in the audit log. See Delegation model.

Finish setup completes the wizard in one transaction: the token and its file are deleted, the wizard endpoints disappear, and you are signed in. Every wizard step is in the audit log (setup.unlock, setup.directory, setup.identities, setup.managed_ous, setup.groups, setup.completed).

After the wizard

  1. Enrol your authenticator app. Sensitive changes (roles, protections, resets...) ask for a 6-digit code. Right after setup none is enrolled: the first confirmation dialog sends you to Security, where you type your AD password once and scan a QR code. Teleport operators skip this: their Teleport session is the confirmation.
  2. Design roles in Delegations: what each group of operators may do, on which OUs. Check them with the Simulator. See Delegation model.
  3. Apply the AD rights: Configuration › Diagnostics › Export AD delegation, then a domain administrator runs Grant-StewardDelegation.ps1 -ModelPath .\steward-delegation.json -ManagedOu <managed OUs> -Identity @{ read = ...; write = ...; reset = ... } (the OUs and accounts must match the file exactly). See Apply the AD rights.
  4. Run the diagnostics (Configuration › Diagnostics) until every line is green.
  5. Optional features: Helpdesk, LAPS, Notifications, Teleport sign-in.