- 4 minutes to read

Migrate Traditional Service Account to gMSA

Use this guide when you already run Nodinite with a traditional service account and want to switch to gMSA without losing encrypted configuration access.

Tip

The best time to switch to gMSA is during the v6 to v7 migration: select the gMSA when you register the environment, and the migration applies it from the start. On an existing v7 installation, changing the account means you apply all secrets and passwords again (Step 4).

Understanding Certificate Store Migration

Traditional service accounts and gMSA accounts use different certificate store contexts. With a traditional account, Nodinite auto-generates the secret-encryption certificate in the account's personal (CurrentUser\My) store; a gMSA has no user profile and reads the certificate from LocalMachine\My. You must move the certificate before you switch identities, or the services can't decrypt the existing secrets.

flowchart TB OLD["fa:fa-user Traditional Service Account"] --> CUR["fa:fa-certificate CurrentUser My store"] CUR --> EXP["fa:fa-file-export Export PFX"] EXP --> IMP["fa:fa-file-import Import PFX"] IMP --> LM["fa:fa-certificate LocalMachine My store"] LM --> ACL["fa:fa-key Grant Private Key Read"] ACL --> GMSA["fa:fa-user-shield gMSA Identity"] GMSA --> IIS["fa:fa-globe IIS Application Pools"] GMSA --> SVC["fa:fa-gear Windows Services"] style OLD fill:#2678BD,color:#fff style CUR fill:#FFD525 style LM fill:#FFD525 style GMSA fill:#93d16d style ACL fill:#93d16d

Diagram: the certificate moves from the old account's CurrentUser\My store to LocalMachine\My (yellow), the gMSA gets Read access to the private key (green), and the IIS application pools and Windows Service agents then run as the gMSA. Scripts for each step: Install Certificates for gMSA.

Migration Workflow

  1. Export certificates from the old account's Cert:\CurrentUser\My store.
  2. Import certificates into Cert:\LocalMachine\My.
  3. Grant the gMSA account read access to certificate private keys.
  4. Update Nodinite service identities to use gMSA.
  5. Verify IIS application pools, Windows Services, and encrypted configuration access.

Step 1: Export Certificates from CurrentUser Store

Run PowerShell as the old service account:

Get-ChildItem Cert:\CurrentUser\My |
  Where-Object { $_.Subject -like "*Nodinite*" -or $_.FriendlyName -like "*Nodinite*" } |
  Format-List Subject, Thumbprint, NotAfter, FriendlyName

$certThumbprint = "1234567890ABCDEF1234567890ABCDEF12345678"
$cert = Get-ChildItem Cert:\CurrentUser\My\$certThumbprint

if ($null -eq $cert) {
    Write-Error "Certificate not found in CurrentUser store"
    exit
}

$pfxPassword = Read-Host "Enter a PFX password" -AsSecureString
$pfxPath = "C:\Temp\NodiniteCert_$certThumbprint.pfx"
Export-PfxCertificate -Cert $cert -FilePath $pfxPath -Password $pfxPassword

Step 2: Import Certificates into LocalMachine Store

Run PowerShell as Administrator:

$pfxPath = "C:\Temp\NodiniteCert_1234567890ABCDEF1234567890ABCDEF12345678.pfx"
$pfxPassword = Read-Host "Enter the PFX password" -AsSecureString

$cert = Import-PfxCertificate -FilePath $pfxPath -CertStoreLocation Cert:\LocalMachine\My -Password $pfxPassword -Exportable

Write-Host "Imported: $($cert.Thumbprint)" -ForegroundColor Green
Remove-Item $pfxPath -Force

Step 3: Grant gMSA Private Key Permissions

Run PowerShell as Administrator:

$gmsaAccount = "CONTOSO\NodiniteProdSvc$"
$certThumbprint = "1234567890ABCDEF1234567890ABCDEF12345678"

$cert = Get-ChildItem Cert:\LocalMachine\My\$certThumbprint
if ($null -eq $cert) {
    Write-Error "Certificate not found in LocalMachine store"
    exit
}

$privateKey = [System.Security.Cryptography.X509Certificates.RSACertificateExtensions]::GetRSAPrivateKey($cert)
if ($privateKey -is [System.Security.Cryptography.RSACng]) {
    # CNG keys -> ProgramData\Microsoft\Crypto\Keys
    $privateKeyFile = Join-Path $env:ProgramData "Microsoft\Crypto\Keys\$($privateKey.Key.UniqueName)"
} else {
    # CSP keys -> ProgramData\Microsoft\Crypto\RSA\MachineKeys
    $privateKeyFile = Join-Path $env:ProgramData "Microsoft\Crypto\RSA\MachineKeys\$($privateKey.CspKeyContainerInfo.UniqueKeyContainerName)"
}

$acl = Get-Acl -Path $privateKeyFile
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule($gmsaAccount, "Read", "Allow")
$acl.SetAccessRule($rule)
Set-Acl -Path $privateKeyFile -AclObject $acl

For detailed certificate ACL guidance, see Microsoft: Grant access to a certificate private key.

Step 4: Update Service Identities to gMSA

Use the Nodinite Portal:

  1. In the Environment, open Step 2: Auth and set Service Account Defaults to the gMSA: Domain mode, the domain, and the account name with the trailing $ (gMSAName$).
  2. If a Core Service uses its own account, update it in Step 4: Servers; turn on Use gMSA for the agents in Step 5: Agents.
  3. Review and download the new package in Step 6: Review and Download.
  4. Run the update with the CLI in elevated PowerShell 7 from the new package. You don't need to uninstall first.
  5. Apply the secrets and passwords again. Changing the service account on v7 means every secret and password must be applied again, for example in the agents' Remote Configuration.

Agents installed with an MSI as Windows Services get the gMSA in the Services console; see Configure Group Managed Service Accounts (gMSA).

Step 5: Verify Migration

$certThumbprint = "1234567890ABCDEF1234567890ABCDEF12345678"
Get-ChildItem Cert:\LocalMachine\My\$certThumbprint | Format-List Subject, Thumbprint, HasPrivateKey, NotAfter

Import-Module WebAdministration
Get-ChildItem IIS:\AppPools |
  Where-Object { $_.Name -like "Nodinite*" } |
  Select-Object Name, State, @{n="Identity";e={$_.ProcessModel.UserName}}

Then verify Web Client login, Monitor Views, Log Views, and that the services can still decrypt their secrets.

Next Steps