Running the service as a dedicated account
By default the curiosity service runs as LocalSystem, which has full access to the local machine and needs no preparation. Run it under a dedicated identity instead when it must reach domain resources — an SMB path for MSK_GRAPH_STORAGE, or a PEM certificate on a share — or when policy requires a least-privilege account. Three kinds of identity work:
- A local user on the host.
- A domain user, with a password you manage and rotate.
- A Group Managed Service Account (gMSA), a domain account whose password Active Directory generates and rotates itself. There is no password to type into a service definition, store in a script, or rotate by hand. See Running as a gMSA for the Active Directory side.
The file access and the logon right below are the same for all three. .\configure-windows-service.ps1 setup (Install, step 3) grants both when you pick the account, skipping whatever is already in place; this page is the same work by hand, and the reference for what the script checks.
Do this before the first start
The first start creates the workspace data, and creates it owned by whichever account is running. Grant the identity its access before the service starts for the first time.
If the service already ran as LocalSystem, stop it, run the icacls grants below with /T so the existing files are rewritten as well, then switch the account.
Grant file access
The installer created only the binaries folder. Create the data folder's contents now (the setup script creates missing ones itself, but the grants need them first), then grant the service account read and execute on the install folder and write access under E:\CuriosityData, per the Directory layout. The commands are shown for a gMSA; for a regular account, drop the trailing $:
mkdir E:\CuriosityData\Storage
mkdir E:\CuriosityData\Logs\Audit
mkdir E:\CuriosityData\Temp
mkdir E:\CuriosityData\www
icacls "E:\Curiosity" /grant "CORP\svc-curiosity$:(OI)(CI)RX"
icacls "E:\CuriosityData\Storage" /grant "CORP\svc-curiosity$:(OI)(CI)F"
icacls "E:\CuriosityData\Logs" /grant "CORP\svc-curiosity$:(OI)(CI)M"
icacls "E:\CuriosityData\Temp" /grant "CORP\svc-curiosity$:(OI)(CI)F"
icacls "E:\CuriosityData\www" /grant "CORP\svc-curiosity$:(OI)(CI)M"
| Path | Access |
|---|---|
E:\Curiosity (binaries) |
Read + execute (see the note on language models below) |
E:\CuriosityData\Storage |
Full control |
E:\CuriosityData\Logs |
Modify |
E:\CuriosityData\Temp |
Full control |
E:\CuriosityData\www |
Modify — the served front-end is rewritten on every start |
TLS certificate files (MSK_CERT_FILE, MSK_CERT_FILE_PRIVATE_KEY) |
Read — only if TLS is terminated in the workspace itself |
Read and execute is enough on the install folder only while MSK_WWW_FOLDER and MSK_LOG_PATH point outside it — see Keeping the install folder read-only. Without MSK_WWW_FOLDER, grant Modify on E:\Curiosity\wwwroot instead of on E:\CuriosityData\www; without MSK_LOG_PATH, on E:\Curiosity\logs as well.
Language models are the one write the install folder cannot avoid
The first start downloads the English language models (Catalyst.Models.English.dll and Catalyst.ConceptNet.English.dll) into the install folder, and enabling another language later does the same. With read-only access the download fails and English cannot be enabled. Either grant the service account Modify on E:\Curiosity as well, or download the models once as an administrator before the first start (download-all-languages fetches every language instead):
E:\Curiosity\curiosity.exe download-default-languages
icacls with (OI)(CI) also reaches the files already in the folder, as long as they inherit their permissions. Files moved in from a user profile on the same volume keep the profile's permissions and stay readable by that user only — add /T to rewrite every existing file.
Grant the logon right
The account needs the Log on as a service right: secpol.msc → Local Policies → User Rights Assignment → Log on as a service. Setting the account through services.msc or .\configure-windows-service.ps1 setup grants it automatically; sc.exe does not on all Windows versions. Where Group Policy controls this right, add the account to the GPO instead — a local grant is overwritten on the next policy refresh.
Switch the service account
Install the workspace as a service first (Install), then change the identity and restart it, from an elevated Command Prompt:
sc config curiosity obj= "CORP\svc-curiosity" password= "<password>"
net stop curiosity
net start curiosity
For a gMSA the account name ends in $ and the password is the empty string — Windows fetches the managed password from Active Directory itself:
sc config curiosity obj= "CORP\svc-curiosity$" password= ""
net stop curiosity
net start curiosity
.\configure-windows-service.ps1 setup does the same with checks: choose the account when asked and it resolves the name, runs Test-ADServiceAccount for a gMSA, grants the file access and the Log on as a service right where they are missing, and sets the account on the service. Re-running the script later keeps the account.
If the start fails, sc query curiosity shows the state and Service start errors decodes the code. Error 1069 is a wrong account name or password, or a missing logon right; error 1053 is usually a folder the account cannot use.
Running as a gMSA
A Group Managed Service Account is a domain account whose password Active Directory generates and rotates itself (every 30 days by default). Services log on with the account name alone. This section prepares the account in Active Directory and on the host; the file access, logon right and account switch above are then the same as for any other identity.
The CLI connector that syncs a file share and its NTFS permissions into the workspace also benefits from a gMSA, because it replaces the --username / --password / --domain impersonation flags. That setup is on monitor-with-permissions → Running it as a service.
gMSA requirements
| Requirement | Notes |
|---|---|
| Active Directory domain | Domain functional level Windows Server 2012 or later. |
| KDS root key | Created once per forest; gMSA passwords are derived from it. |
| Domain-joined host | The machine running the Workspace must be joined to the domain. |
| Windows Server 2012+ on the host | Client SKUs also support gMSAs, but a server SKU is typical. |
| RSAT Active Directory PowerShell module | Needed on the host to install and test the account. |
| AD permissions | Creating the gMSA requires rights to create msDS-GroupManagedServiceAccount objects (typically Domain Admins or a delegated OU admin). |
Create the gMSA in Active Directory
Run these on a domain controller (or any machine with the AD PowerShell module and sufficient rights).
If your forest has never used gMSAs, create the KDS root key first:
Get-KdsRootKey # anything listed? then skip the next line
Add-KdsRootKey -EffectiveImmediately
KDS root key propagation
-EffectiveImmediately still means a 10-hour wait before domain controllers will issue gMSA passwords, to allow AD replication. In a single-DC lab you can bypass the wait with Add-KdsRootKey -EffectiveTime ((Get-Date).AddHours(-10)) — do not do this in production.
Create a security group for the hosts allowed to retrieve the account's password, add the machine account(s), then create the gMSA:
New-ADGroup -Name "CuriosityHosts" -GroupScope Global -GroupCategory Security
Add-ADGroupMember -Identity "CuriosityHosts" -Members "WORKSPACE01$" # the host's computer account
New-ADServiceAccount -Name "svc-curiosity" `
-DNSHostName "svc-curiosity.corp.example.com" `
-PrincipalsAllowedToRetrieveManagedPassword "CuriosityHosts"
Reboot the host after adding its computer account to the group — group membership is only picked up on the machine's next Kerberos ticket.
You can also point -PrincipalsAllowedToRetrieveManagedPassword at a single computer account ("WORKSPACE01$") instead of a group; the group form scales to several hosts sharing one account.
Prepare the host for the gMSA
On the machine that will run the service:
# RSAT AD PowerShell module (server SKU)
Install-WindowsFeature RSAT-AD-PowerShell
# Link the account to this host and verify the password can be retrieved
Install-ADServiceAccount -Identity "svc-curiosity"
Test-ADServiceAccount -Identity "svc-curiosity" # must return True
If Test-ADServiceAccount returns False, the host cannot retrieve the managed password — see gMSA troubleshooting.
Then grant the file access and the logon right, and switch the service account using the $ form.
The trailing `$`
A gMSA is referenced everywhere as DOMAIN\name$ — with a trailing dollar sign and an empty password. Forgetting the $ is the most common configuration mistake.
Running a command as the gMSA
A gMSA cannot log on interactively, so anything that has to be done as the account — importing a certificate into its personal store for MSK_CERT_FROM_STORE_NAME, or storing a CLI token in its profile — runs through a one-off scheduled task:
$a = New-ScheduledTaskAction -Execute "certutil.exe" -Argument "-user -importPFX E:\CuriosityData\workspace.pfx"
$p = New-ScheduledTaskPrincipal -UserId "CORP\svc-curiosity$" -LogonType Password
Register-ScheduledTask -TaskName "curiosity-import-cert" -Action $a -Principal $p
Start-ScheduledTask -TaskName "curiosity-import-cert"
Unregister-ScheduledTask -TaskName "curiosity-import-cert" -Confirm:$false
-LogonType Password is correct for a gMSA — Windows fetches the managed password itself.
gMSA troubleshooting
| Symptom | Likely cause |
|---|---|
Test-ADServiceAccount returns False |
The host's computer account is not in the PrincipalsAllowedToRetrieveManagedPassword group, the host was not rebooted after being added, or the KDS root key is not yet effective (10-hour wait). |
| Service fails to start with error 1069 (logon failure) | Missing trailing $ in the account name, a non-empty password was configured, or the account lacks the Log on as a service right. |
| Service fails to start with error 1053 (did not respond in time) | --MSK_RUN_AS_SERVICE=true is missing from the service binPath (sc.exe qc curiosity shows it), or the process crashed during startup — usually because the account cannot read the install directory or write the data/log/temp paths. Check the gMSA's access with icacls on the install, data, log and temp folders, and look for error.log in the log folder or next to curiosity.exe. Binaries or data still under another user's C:\Users\<name> profile is the most common cause — see Directory layout and Service start errors. |
Access is denied reading a share |
Check both the share permission and the NTFS ACL for the gMSA; also confirm the path is a UNC path, not a drive letter mapped for another user (drive mappings are per-logon and invisible to the service). |
See also
- Install — the install steps this page extends.
- Service reference — what the setup script checks, the service command line, start error codes.
monitor-with-permissions→ Running it as a service — the CLI connector under a gMSA.- Security — hardening the deployment.
- Microsoft: Group Managed Service Accounts overview — upstream reference.