Choosing a Windows Service Account — LocalSystem, Virtual Accounts, and gMSA

· · Windows, Windows Service, Service Accounts, gMSA, LocalSystem, Virtual Accounts, Security, Active Directory, Least Privilege

“An in-house service we had been running as LocalSystem for now was flagged in a security audit as ‘excessive privilege’. What should we change it to?” “The service could not access a shared folder, so we are running it as a domain user. When the password expires the service stops, so we made it never expire and wrote it in plaintext in the runbook.” — Among consultations around customers’ Windows services, these two are staples.

What both sites have in common is that the service’s logon account is frozen as “the setting that happened to work”, not as a design decision. A Windows service always runs in the security context of some account, and that account decides all of what it can do locally, who it looks like from the far side of the network, and who manages the password. Leave this at the default and a vulnerability in one service leads directly to taking over the whole machine, and plaintext passwords scatter into runbooks and scripts.

Three things the logon account decidesA service always runs in the security context of some account, and that account decides all of what it can do locally, who it looks like from the far side of the network, and who manages the passwordThe service's logon accountWhat it can do locallyWho it looks like from the far side of the networkWho manages the password

Figure 1: Choosing the logon account is a design decision that simultaneously decides local privileges, network identity, and password management.

There are effectively six choices — LocalSystem, LocalService, NetworkService, a virtual account (NT SERVICE\), a domain user, and a gMSA (group Managed Service Account). Aimed at IT staff in small and medium businesses and at Windows app developers, this article organizes the privileges, network identity, and password management of these six into a single table and summarizes a decision flow, based on Microsoft Learn primary sources as of August 2026.

How to build the service itself (choosing between Task Scheduler and a service, implementing with a .NET Worker Service) is covered in “How to Build and Operate Windows Services”. This article concentrates on the “logon account”, which is where the most accidents happen.

1. The Bottom Line First

  • When in doubt, a virtual account is the first candidate for a service that finishes inside a single machine, and a gMSA is the first candidate for a service that accesses a resource inside the domain with a service-specific identity. Microsoft also gives the guidance to use a managed account (MSA / virtual account) wherever possible.12
  • Do not choose LocalSystem because “it works”. The token includes SYSTEM and BUILTIN\Administrators and holds strong privileges such as SeDebugPrivilege, so a takeover loses almost everything on that machine. The default of sc.exe create being LocalSystem is the breeding ground for this accident.34
  • The difference between LocalService and NetworkService is network identity. Local privileges are minimal for both, but to the remote side LocalService looks anonymous and NetworkService looks like the computer account.5
  • **A virtual account (NT SERVICE\) is the modern default that can separate identity per service while needing no password management.** You can specify "NT SERVICE\\service-name" directly on an ACL, and SQL Server's default service account is this as well.[^understand-service-accounts][^sql-service-accounts]
  • When LocalSystem, NetworkService, or a virtual account goes onto the network, it becomes the computer account (DOMAIN\computer-name$). Granting PC$ on the ACL of a shared folder or SQL Server often lets you do without a domain user.36
  • A configuration that uses a domain user for a service becomes debt on both password operations and Kerberoasting. SCM logs on with the stored password, so expiry becomes a start failure, and the “never expire + plaintext memo” that avoids that becomes a gift to an attacker.78
  • A gMSA has Active Directory generate and rotate the password automatically. The requirements are a domain and a KDS root key, and you set the service to “DOMAIN\account-name$” with the password field empty. Some apps do not support it, so you need to validate in advance.910
  • Changing the account changes the assumptions of the profile, %TEMP%, and DPAPI. Data protected with the old account’s DPAPI cannot be decrypted by the new account.
  • An inventory of the current state can be confirmed from the logon accounts of the service list and from event ID 4624 (logon type 5).11

In one sentence, this article’s conclusion is: make a configuration that “does not give a service a human password” (built-in accounts, a virtual account, a gMSA) the default, and treat a domain user as a last resort.

2. The Big Picture of the Choices — Six Logon Accounts in a Single Table

One step of review first. At service start, the Service Control Manager (SCM) logs on as the configured account and, on success, creates an access token and assigns it to the service process. Thereafter, every resource access — files, pipes, and the like — is decided by matching this token against the ACL.7 So choosing the logon account is a design that decides the contents of the token passed to the service process. Here are the six choices.

What SCM does at service startSCM logs on as the configured account, on success creates an access token and assigns it to the service process, and thereafter resource access is decided by matching the token against the ACLYesNoSCMLog on as the configured accountCreate an access tokenAssign it to the service processAccess to a file or a pipeDoes the ACL permit it?Access succeedsAccess is denied

Figure 2: Every resource access of the service is decided by matching the token SCM created at start against the ACL.

Account Local privileges Network identity Password management Typical use
LocalSystem Almost unlimited (SYSTEM+Administrators) Computer account (PC$) Not needed (no password) Exceptional services that run as one with the OS
LocalService Minimal (Users-class) Anonymous Not needed Local processing that does not need a network identity
NetworkService Minimal (Users-class) Computer account (PC$) Not needed Low-privilege processing where a machine-level identity is enough
Virtual account NT SERVICE\ Minimal + grant individually on the ACL Computer account (PC$) Not needed (managed automatically) The default for a business service that runs on a single server
Domain user Only what you grant That user itself Manual (expiry, leak, and rotation are all left to people) A last resort for an app that does not support a gMSA
gMSA Only what you grant That gMSA itself AD generates and rotates automatically When a domain environment needs a service-specific identity

LocalSystem, LocalService, NetworkService, and a virtual account all have no concept of a password at all. The only ones that log on with a password stored in SCM (= expiry and leak are possible) are a domain user and a local user.73

Below we dig into this table one row at a time.

3. What Is Wrong with LocalSystem

3.1. Stronger Still Than “Run as Administrator”

LocalSystem (display name Local System, NT AUTHORITY\SYSTEM) is a predefined account SCM uses, and it holds extensive privileges on the local computer. The token includes the SIDs of NT AUTHORITY\SYSTEM and BUILTIN\Administrators, and it can access most objects on the system. Further, SeDebugPrivilege, which can debug other processes, and SeTcbPrivilege, which acts as part of the OS, are enabled by default.3

This strength is synonymous with the size of the damage when it is taken over. If a service running as LocalSystem has one arbitrary-code-execution vulnerability, an attacker reaches, in one breath, reading and tampering with every user’s files on that machine (SYSTEM has Full Control by default on NTFS5), reading other processes’ memory via SeDebugPrivilege, and stealing credentials and moving laterally from there (a starting point for Pass-the-Hash and the like). The chain of credential theft and lateral movement is as covered in “NTLM and Kerberos Explained with Diagrams” and “A Practical Guide to Windows LAPS”.

The damage when a LocalSystem service is taken overIf a service running as LocalSystem has one arbitrary-code-execution vulnerability, an attacker reaches reading and tampering with every user's files, reading other processes' memory, and stealing credentials and moving laterallyOne arbitrary-code-execution vulnerabilityThe attacker obtains SYSTEM privilegesReading and tampering with filesReading other processes' memoryStealing credentialsLateral movement to another machine

Figure 3: One vulnerability in a LocalSystem service lets an attacker reach, in one breath, taking the whole machine and a starting point for lateral movement.

3.2. Why It Is Still Chosen

The reason is simple: it is the default, and an access-denied never appears. The default when you omit obj= on sc.exe create is LocalSystem,4 and many old sample-code and installer templates still assume LocalSystem. Because you can stay free of privilege errors during development, the structure that mass-produces “it worked, so leave it” is there. Microsoft’s own documentation also states that most services do not need this high a privilege level, and that if you do not need it you should consider using LocalService or NetworkService.3

The structure that keeps LocalSystem being chosenThe default of sc.exe create is LocalSystem, and old sample code and templates also assume LocalSystem, so no access-denied appears during development and a configuration of it worked so leave it is mass-producedThe default of sc.exe createCreated as LocalSystemOld samples and templatesNo access-denied during developmentIt worked, so leave itServices with excessive privilege are mass-produced

Figure 4: The default and a development experience of “no access-denied” mass-produce services frozen as LocalSystem.

3.3. The Difference from TrustedInstaller — LocalSystem Is Not Unlimited Either

Calling LocalSystem “Windows’ strongest account” is not accurate. Windows Resource Protection (WRP) since Windows Vista permits changes to important OS system files, folders, and registry keys only to TrustedInstaller (the Windows Modules Installer service), and even SYSTEM or an administrator gets access denied on a rewrite.12 Explorer’s “You need permission from TrustedInstaller” is this mechanism. Put the other way around, LocalSystem can reach almost everything outside the WRP-protected area, and there is usually no reason to give that to a business service.

The relationship between the WRP-protected area and TrustedInstallerChanges to important system files and registry keys that WRP protects are permitted only to TrustedInstaller, and even SYSTEM or an administrator gets access deniedCan changeAccess deniedAlmost everything is allowedTrustedInstallerWRP-protected system files and the likeSYSTEM and administratorsOutside the WRP-protected area

Figure 5: LocalSystem is not unlimited either; changes to the WRP-protected area are permitted only to TrustedInstaller.

3.4. Cases Where LocalSystem Is Reasonable

What is exceptionally reasonable is a service whose required privileges exceed administrator-class in the first place — working closely with a device driver, operating the OS security foundation, managing other services or sessions, and the like. Software such as a backup agent or an EDR applies. Even then, it is worth confirming that there is a code path that truly uses that privilege, and considering whether the work that needs the privilege can be separated (for how to tell, see “When Do You Actually Need Administrator Privileges on Windows?”).

4. LocalService and NetworkService — Built-in Accounts with Least Privilege

LocalService (NT AUTHORITY\LOCAL SERVICE, SID: S-1-5-19) and NetworkService (NT AUTHORITY\NETWORK SERVICE, SID: S-1-5-20) are built-in accounts prepared for low-privilege services. Both hold only minimal privileges locally, and can do little more than a member of the Users group.51

The difference between the two is one point: who they look like from the far side of the network.5

  • LocalService: Connects to the remote side with anonymous credentials. It cannot access a resource that requires authentication.
  • NetworkService: Presents the computer’s credentials to the remote side (in a domain environment, DOMAIN\computer-name$).

The split is LocalService if “it does not go onto the network, or if it does it does not need an identity”, and NetworkService if “you want to access a resource inside the domain with the machine’s identity”.

The difference between LocalService and NetworkServiceLocal privileges are minimal for both, but to the remote side LocalService connects with anonymous credentials and NetworkService presents the computer's credentialsLocalServiceConnects with anonymous credentialsA resource that requires authentication is not possibleNetworkServicePresents the computer's credentialsIn a domain environment it looks like PC$

Figure 6: Local privileges are the same minimum, but the identity visible from the far side of the network splits into anonymous or the computer account.

These two, however, have a weakness from a modern point of view. The same account is shared by many services. If five services run as LocalService, then as long as the ACL is per-account, the five can access one another’s resources. SQL Server does not support the Local Service account for the same reason: it is a shared account and cannot be separated from other services.1

A shared account cannot be separatedIf several services share the same LocalService, then as long as the ACL is per-account they can access one another's resourcesService AThe same LocalServiceService BService CCan access one another's resourcesBecause the ACL is per-account

Figure 7: Services that share the same account cannot be separated from one another’s resources by an ACL.

Solving this “stay low-privilege, but separate per service” is the next topic, the virtual account.

5. Virtual Accounts (NT SERVICE\) — The Modern Default

5.1. You Can Have a Per-Service Identity with No Password

A virtual account is a “managed local account” available from Windows Server 2008 R2 / Windows 7 onward. There are three characteristics.6

  • The account is managed automatically; neither creation nor setting a password is needed
  • The name is NT SERVICE\<service-name>, and it becomes an identity unique to each service
  • In a domain environment, it can access the network with the computer account’s credentials (DOMAIN\computer-name$)

In other words, it keeps the “no password management” merit of LocalService/NetworkService and removes the “cannot separate because the account is shared” demerit. That is also why SQL Server setup defaults to a virtual account such as NT SERVICE\MSSQLSERVER.1

What a virtual account makes compatibleA virtual account keeps the no-password-management merit of LocalService and NetworkService, removes the cannot-separate-because-shared demerit, and has an identity unique to each serviceKeepRemoveMerit (no password management)Virtual accountDemerit (cannot separate because shared)An identity unique to each serviceNeither creation nor setting a password is needed

Figure 8: A virtual account keeps the merits of the built-in accounts and removes only the cannot-separate-because-shared demerit.

5.2. You Can Write “NT SERVICE\service-name” Directly on an ACL

The practical convenience is that you can add only that service to an ACL by name. “Only this service can write this data folder” can be realized with neither creating a group nor managing a password.

# Change the service's logon account to a virtual account
# The value of obj= is "NT SERVICE\service-name". Do not specify a password
sc.exe config MyAppService obj= "NT SERVICE\MyAppService"

# Confirm the configuration (check SERVICE_START_NAME)
sc.exe qc MyAppService

# Grant modify rights on the data folder to this service only
icacls "C:\ProgramData\MyApp" /grant "NT SERVICE\MyAppService:(OI)(CI)M"

In the GUI, in services.msc open the service’s properties → the “Log On” tab → enter NT SERVICE\service-name in “This account”, and leave the password fields empty (for a virtual account or an MSA, not specifying a password is SCM’s specification). After the change, a service restart applies it.

5.3. The Constraint — Outside the Machine It Is Not “That Service”

A virtual account’s identity is machine-local and is not recognized from the domain. On the network it collapses to the computer account as described later, so the remote side cannot tell “which service it is”, and you also cannot share the same identity across several servers.10

A virtual account's identity collapses outside the machineA virtual account that is unique per service inside the machine also collapses to the computer account on the network, and the remote side cannot tell which service it isVirtual account AComputer account PC$Virtual account BThe identity visible to the remote sideCannot tell which service it is

Figure 9: Even with a unique identity inside the machine, on the far side of the network every service looks like the same PC$.

The moment this constraint — needing a service-specific identity on the far side of the network, needing the same identity on several servers — becomes a problem is when a gMSA (Chapter 8) is called for.

6. Identity When Going onto the Network — The Practice of the Computer Account (PC$)

6.1. “A Service Cannot Access a Shared Folder” Is a Misunderstanding

On a domain-joined machine, when a service running as LocalSystem, NetworkService, or a virtual account accesses a remote resource, it authenticates as the computer account (DOMAIN\computer-name$).36 Many of the opening consultations of “it could not access a shared folder, so we made it a domain user” are in fact solved by this. The destination ACL simply was not permitting PC$.

Remote access as the computer accountA LocalSystem, NetworkService, or virtual-account service on a domain-joined machine authenticates to the remote side as the computer account, and if the destination ACL permits PC$ it can accessYesNoService (LocalSystem, a virtual account, and the like)Authenticate as PC$Does the destination ACL permit PC$?Access to a shared folder or a DB succeedsAccess is denied

Figure 10: In a domain environment, granting PC$ on the destination ACL alone establishes remote access without a domain user.

Granting on the file-server side is the same as an ordinary ACL operation; specify computer-name$ as the account name (in the GUI object-picker dialog, include “Computers” in the object types).

# On the file-server side: grant a service on APPSV01 modify rights on the shared folder
# You need to grant both share permissions and NTFS permissions
Grant-SmbShareAccess -Name "AppData" -AccountName "CORP\APPSV01$" -AccessRight Change -Force
icacls "D:\Shares\AppData" /grant "CORP\APPSV01$:(OI)(CI)M"

SQL Server is the same: create the computer account as a login and the connection string goes through with Integrated Security=true and no password.

-- On the DB-server side: permit Windows integrated authentication from a service on APPSV01
CREATE LOGIN [CORP\APPSV01$] FROM WINDOWS;

6.2. Know the Limits of the PC$ Approach

This approach has two limits.

  1. Granularity is per machine. LocalSystem, NetworkService, and every virtual-account service running on the same machine all look like the same PC$ from the remote side. You cannot “permit only this service” on the destination, and you also cannot audit which service used that account.2
  2. It cannot be used in a workgroup environment. A computer account is an Active Directory object, so a machine that is not domain-joined does not have one. You need a design that handles the destination account’s credentials explicitly.

When you want to go beyond limit 1, the 2026 answer is not the next chapter’s domain user… but to skip that problem and proceed to a gMSA.

Two limits of the PC$ approachAuthentication as PC$ has machine-level granularity so neither per-service permission nor audit is possible, and in a workgroup environment the computer account itself does not exist so it cannot be usedThe PC$ approachLimit 1: per machineLimit 2: no workgroupNo per-service permitno per-service auditUse explicit credsBeyond this: a gMSA

Figure 11: When you want to go beyond the two limits of machine-level granularity and a domain prerequisite, skip the domain user and proceed to a gMSA.

7. The Problem of Using a Domain User for a Service

7.1. The Structural Problem of the Password

If you assign a domain user (or a local user) to a service, SCM stores that password and uses it to log on at every start. SCM does not manage expiry, so when the password expires the logon fails and the service will not start.7

From there, the negative spiral you often see in the field begins.

  1. An accident of the service stopping because of expiry occurs
  2. As recurrence prevention, “password never expires” is set
  3. A change procedure is never established, and the same password is written in plaintext into the runbooks, scripts, and Task Scheduler of several servers
  4. Even when someone leaves, the password does not change (if you change it, you do not know what will stop)
The negative spiral of operating with a domain userThe password expires and the service stops, never-expire is set as recurrence prevention, a plaintext password spreads into runbooks and scripts, and even when someone leaves it cannot be changed1. Expiry stops the service2. Never-expire is set as recurrence prevention3. A plaintext password spreadsRunbooks, scripts, tasks4. Even when someone leaves, it cannot be changed

Figure 12: Starting from an expiry accident, never-expire and the spread of a plaintext password become fixed.

Microsoft also points out that a configuration that uses a domain account for a service costs considerable operational effort in the manual management of the password and the SPN, and that maintenance can lead to a service stop.1

7.2. Kerberoasting — A Service Account Is Targeted

Another attack specific to a domain-user service account is Kerberoasting. A service that receives Kerberos authentication registers an SPN (service principal name) on the logon account. Any authenticated user in the domain can request a service ticket to an account that has an SPN registered, so an attacker obtains the ticket and tries an offline brute-force of the password. A 10-to-16-character password a human decided will not withstand this attack.

The flow of KerberoastingA service ticket to a service account that has an SPN registered can be requested by any authenticated user, so an attacker obtains the ticket and tries an offline brute-force of the passwordAn authenticated user in the domainRequest a ticket for the SPNObtain a service ticketOffline brute-force10 to 16 characters or so will be cracked

Figure 13: Any authenticated user can request a ticket, and a password of a length a human decided will not withstand an offline brute-force.

The effective response is to make the password a strength a human cannot guess or crack. Microsoft also lists forcing a long password, and using a gMSA whose password becomes a long machine-generated random value.8 The same document also mentions Kerberos armoring (FAST), but FAST protects pre-authentication data and resistance to KDC spoofing; it does not prevent an authenticated user requesting a service ticket to an SPN, so it is not a substitute for the password strength of a service account. The relationship between SPNs and Kerberos, and the conditions under which authentication falls back to NTLM, are diagrammed in “NTLM and Kerberos Explained with Diagrams”.

7.3. If You Still Use a Domain User

If you have no choice but to use a domain user, for reasons such as the application not supporting a gMSA, treat the following as the minimum mitigation.

  • Make the password a randomly generated 25 characters or more, and do not write it anywhere other than a password-management tool (runbooks, scripts, a shared Excel)
  • Make it a service-dedicated account and split it per service (do not share it with a human account2)
  • Deny interactive logon and Remote Desktop, and permit only “Log on as a service”
  • Minimize the groups it belongs to (adding it to Domain Admins is out of the question)
  • Establish a periodic-rotation procedure and put the places a change will affect into a ledger

Doing all of this is less safe and less easy than migrating to a gMSA — that is the next chapter.

8. gMSA — Leaving Password Management to Active Directory

8.1. The Mechanism and the Effect

A gMSA (group Managed Service Account) is a domain account that leaves password management to the domain controller. The password is computed by the domain controller from the KDS (Key Distribution Service) root key, and only permitted hosts obtain it.13

How a gMSA manages the passwordThe domain controller computes the password from the KDS root key, only permitted hosts obtain it and use it to run the service, and the password is rotated automatically every 30 days by defaultKDS root keyThe DC computes the passwordA permitted host obtains itUsed to run the serviceAutomatic rotation every 30 days by default

Figure 14: The domain controller takes on generating, distributing, and updating the password, and humans can operate without knowing the password.

The effects are clear.9

  • A 240-byte randomly generated password: brute-force and dictionary attacks become unrealistic, and Kerberoasting resistance rises substantially
  • Automatic rotation every 30 days by default: a human does not need to plan a change, and the service does not need to be stopped
  • The same identity can be shared across several servers: a server farm under load balancing can mutually authenticate as the same principal
  • Simpler SPN management: registration and management of SPNs can also be delegated and simplified

Humans can operate without knowing the password — if you take it as the mechanism that does for a service account what Windows LAPS does for a local administrator password, the placement is easier to grasp.

8.2. Requirements

A gMSA has prerequisites.10

  • An Active Directory domain environment (not possible in a workgroup)
  • Domain and forest functional levels of Windows Server 2012 or higher
  • A KDS root key has already been created
  • The gMSA name is unique in the forest, not merely in the domain
  • The password-change interval can be set only at creation time

Creating the KDS root key is a one-time task, but for up to 10 hours after creation you cannot create a gMSA, because you wait for replication to every domain controller. It is a safety device to prevent the accident of password retrieval failing before replication has finished.14

From creating the KDS root key to creating a gMSAAfter the KDS root key is created you wait for replication to every domain controller, so for up to 10 hours you cannot create a gMSA; after replication completes you can create oneCreate the KDS root keyUp to 10 hours of waiting for replicationA safety device to prevent a retrieval-failure accidentReplication to every DC has completedYou can create a gMSA

Figure 15: The up-to-10-hour wait after creating the root key is waiting time to prevent a retrieval failure while replication has not finished.

# Run as a domain administrator, on a domain controller (or an administrative
# workstation with the AD PowerShell module)

# Confirm whether a KDS root key exists, and create one if not (once per forest)
Get-KdsRootKey
Add-KdsRootKey -EffectiveImmediately   # Actually usable after up to 10 hours

8.3. The Procedure from Creation to Configuration

The procedure is four stages: “① create a group permitted to retrieve → ② create the gMSA → ③ install it on the servers → ④ set it on the service”.10

The four stages of introducing a gMSAIntroduce it in four stages: creating a group permitted to retrieve the password, creating the gMSA, installing it on each server, and setting it as the service's logon account① Create a group permitted to retrieve② Create the gMSAAdd the servers' PC$③ Install on each serverValidate retrieval with the Test command④ Set it on the service

Figure 16: From creating the group to setting the service, introducing a gMSA proceeds in four stages.

# ① Create a security group permitted to retrieve the password,
#    and add the computer accounts of the servers that will run the service
New-ADGroup -Name "GG-SvcBatchHosts" -GroupScope Global
Add-ADGroupMember -Identity "GG-SvcBatchHosts" -Members "APPSV01$", "APPSV02$"
# Group membership is evaluated at computer logon, so
# restarting the target servers after adding is the reliable approach

# ② Create the gMSA
New-ADServiceAccount -Name "svc-batch" `
    -DNSHostName "svc-batch.corp.example.com" `
    -PrincipalsAllowedToRetrieveManagedPassword "GG-SvcBatchHosts"

# ③ On each server that will run the service, install the gMSA and validate
Install-ADServiceAccount -Identity "svc-batch"
Test-ADServiceAccount -Identity "svc-batch"   # True means retrieval is working

# ④ Set it as the service's logon account. Append $ to the name, and do not specify a password
sc.exe config MyBatchService obj= "CORP\svc-batch$"
Restart-Service MyBatchService

When setting from services.msc as well, the account name is like CORP\svc-batch$append $ at the end, and leave the password fields empty. An MSA-family account cannot be used for an interactive sign-in.1 After that, grant CORP\svc-batch$ on the ACL of a shared folder or SQL Server in place of PC$, and network access with a service-specific identity is complete, passwordless.

8.4. Some Apps Do Not Support It

As a caveat, not every piece of software will run as a gMSA. Things that configure the logon identity through a standard mechanism — a Windows service, an IIS application pool, a Task Scheduler task — are widely supported, but there are constraints such as failover clustering itself not supporting a gMSA, and an app whose internals demand a password cannot use it.10 Microsoft also states plainly that you should confirm behavior as a gMSA in a test environment before production.9

Telling whether something supports a gMSAAn app that configures the logon identity through a standard mechanism widely supports a gMSA, but failover clustering and an app whose internals demand a password cannot use it, so confirm in a test environment before productionStandard mechanismPassword demandedThe target appHow is logon set?gMSA supportedService, IIS, a taskgMSA not possibleFailover clusteringTest before production

Figure 17: An app that configures logon through a standard mechanism is widely supported, but some designs are unsupported, so validation before production is indispensable.

There are also siblings: the sMSA (standalone Managed Service Account) for a single server, and the dMSA (delegated Managed Service Account, introduced in Windows Server 2025, which ties to device identity to counter credential theft). For a new build, take a gMSA as the baseline and consider according to the requirements.6

9. Accompanying Design — Logon Rights, the Profile, DPAPI, and Auditing

Four more things that change with the account, to keep.

9.1. The “Log on as a Service” Right (SeServiceLogonRight)

To start as a service, the account needs the “Log on as a service” user right. LocalSystem, LocalService, and NetworkService have it built in, but any other account (a domain user, a gMSA, and the like) needs an explicit assignment.15

If you set it from the “Log On” tab of the services.msc GUI, the snap-in grants this right automatically. On the other hand, CreateService / ChangeServiceConfig (the APIs sc.exe config calls) do not verify that the specified account has this right. The typical cause of a service configured by a script stopping at start with “the service did not start due to a logon failure” is this. Do not rely on a tool’s side effect; include in the deploy procedure, explicitly, adding to “Log on as a service” in Local Security Policy (secpol.msc), or configuration via GPO/Intune (in an environment that configures this right with Group Policy, a local grant is overwritten when the policy applies, so that needs attention as well). Conversely, the standard move for a service-dedicated account is to set “Deny log on locally” together with it.

The difference by the configuration path of the "Log on as a service" rightThe services.msc GUI grants the right automatically, but the API sc.exe config calls does not verify the right, so an account without the right stops the service with a logon failure at startYesNoSet in services.mscThe right is granted automaticallyThe service can startSet with sc.exe configThe right is not verifiedDoes it have the right?The service can startStops with a logon failureGrant explicitly with secpol.msc or a GPO

Figure 18: The GUI grants the right automatically, but a scripted configuration does not verify it, so you need to include an explicit grant in the procedure.

9.2. The Profile, %TEMP%, and HKEY_CURRENT_USER Change

SCM loads that account’s user profile at service start.7 So the real %TEMP%, %APPDATA%, and HKEY_CURRENT_USER are a different thing per logon account, and when you switch accounts, settings and caches saved in the old account’s profile look as if they “disappeared”.

The design response is simple: put the service’s data not under the profile but on an explicit path such as C:\ProgramData\<app-name>, and grant that ACL to the logon account. That way an account change does not come with a data migration.

Profile dependence and the response of data placementThe real profile is a different thing per logon account, so switching accounts makes the old profile's data look as if it disappeared, but placing the data on an explicit path and granting the ACL makes migration unnecessaryResponseSwitching the logon accountA different profile is loadedThe old data looks as if it disappearedPlace it under ProgramDataGrant the ACL to the logon accountNo migration even when the account changes

Figure 19: Avoid the profile and put the data on an explicit path, and an account change no longer comes with a data migration.

9.3. Data Protected with DPAPI Is Bound to the Account

Easier still to miss is DPAPI. Data encrypted with user-scope DPAPI (CryptProtectData or .NET’s ProtectedData) can, in principle, be decrypted only by the same account that protected it. The moment you change the account, a stored connection string or API key can no longer be read — that is DPAPI doing its job correctly, but if it is not in the migration procedure it becomes an incident.

The relationship between DPAPI-protected data and an account changeData protected with user-scope DPAPI can be decrypted only by the same account that protected it, so after you change the logon account you need to re-enter the secretsThe same old accountThe new accountDPAPI-protect with the old accountA protected connection string and the likeWhich account is decrypting?Can decryptCannot decryptRe-enter the secrets

Figure 20: DPAPI-protected data is bound to the account that protected it, and after an account switch you need to re-enter.

The response is to include in the migration plan the procedure of “re-enter the secrets after the account switch” (for the design of where to store them, see “Storing Secrets in Windows Apps”). Also, a configuration that can finish with Windows integrated authentication as a gMSA or PC$ can eliminate storing the secret itself. The correct order is to consider “can we do without storing it” before “where do we store it”.

And if the service wants to process “with the calling user’s privileges”, you use impersonation rather than making the account stronger. For that, see “Handling Windows Impersonation Tokens Correctly”.

9.4. Auditing — Look at 4624 Logon Type 5

A service start is recorded in the Security event log as event ID 4624 (An account was successfully logged on) with logon type 5 (Service: SCM started a service). The “Virtual Account” field in the event indicates whether the logon was by an MSA / virtual account, so it can also be used to watch the use of managed accounts.11

The flow of auditing a service startSCM starting a service is recorded as event ID 4624 logon type 5, and the Virtual Account field can identify whether the logon was by a managed accountSCM starts a serviceRecord event ID 4624Logon type 5 (Service)Virtual Account fieldWatching managed accounts

Figure 21: A service start is recorded as a 4624 of logon type 5, and you can even track the use of managed accounts.

For an inventory of the current state, aggregating the logon accounts of the service list is the quick method.

# Aggregate which services are running as which account
Get-CimInstance Win32_Service |
    Group-Object StartName |
    Sort-Object Count -Descending |
    Select-Object Count, Name

# Inventory non-standard services running as LocalSystem (tell in-house / third-party by the path)
Get-CimInstance Win32_Service |
    Where-Object { $_.StartName -eq 'LocalSystem' -and $_.PathName -notlike '*\Windows\*' } |
    Select-Object Name, DisplayName, PathName

If this output lines up “a business service running as LocalSystem” and “a service running as a domain user”, the next chapter’s decision flow is called for.

10. Decision Flow — Decide with Four Questions

Here is the content so far, as a selection procedure. Answer four questions in order.

The decision flow for the logon accountDecide the logon account by answering in order the four questions of whether there is network access, domain join, whether a machine-level identity is enough, and gMSA supportNoYesNoYesYesNoYesNoWin auth to a peer?Virtual accountLocalSystem if neededDomain-joined?Protect stored credsMachine-level enough?Virtual acct + PC$App supports a gMSA?gMSAUser + mitigations

Figure 22: Answer the four questions in order and which of the six choices you should use is decided.

Question 1: Does that service access another machine on the network (a shared folder, a DB, an API, and the like) with Windows authentication?

If not, a virtual account is the default. Only if a special local privilege is needed, confirm that need and then consider LocalSystem.

Question 2: (If it does access) Is the machine domain-joined?

In a workgroup, neither PC$ nor a gMSA can be used. Use a design that handles the destination account’s credentials explicitly (protect the store with DPAPI or the like), or consider joining the domain.

Question 3: (In a domain) Is a machine-level identity (PC$) enough?

If it is, a virtual account (or NetworkService) + granting PC$ on the destination ACL is complete. If you need a service-specific identity, or a common identity across several servers, go to question 4.

Question 4: Does the application support a gMSA?

If it does (things that configure logon through a standard mechanism — SCM, an IIS app pool, Task Scheduler — generally do), a gMSA. Do not forget a behavior check in a validation environment. If it is unsupported no matter what, use a dedicated domain user after applying every mitigation in section 7.3.

In a table it is as follows.

Situation Recommendation Notes
Local-only, ordinary privileges Virtual account Grant the ACL to NT SERVICE\<name>
Local-only, privilege beyond administrator is required LocalSystem Validate the need for the privilege first
Local processing that does not need a network identity LocalService Acceptable for keeping an existing service as-is
Access a resource inside the domain with the machine’s identity Virtual account (or NetworkService) Grant PC$ on the destination ACL
Access a resource inside the domain with a service-specific identity gMSA KDS root key + confirm support
The same identity on several servers (load balancing and the like) gMSA Not possible with a virtual account
An app that does not support a gMSA + a specific identity is needed A dedicated domain user The mitigations in section 7.3 are required
A workgroup + remote access is needed Protect and store explicit credentials Also consider revisiting the design

11. Summary

  • A service’s logon account is a design decision that simultaneously decides local privileges, network identity, and password management. Do not leave it at the default (LocalSystem).
  • LocalSystem holds a SYSTEM+Administrators token and strong privileges, and the damage when it is taken over is maximized. Most business services do not need this privilege.
  • LocalService and NetworkService are both low-privilege; the difference is network identity (anonymous, or the computer account). Because the account is shared by several services, however, they cannot be separated.
  • A virtual account (NT SERVICE\) is the modern default that can separate per service while needing no password management. You can specify it directly on an ACL, and configuration is only changing the logon-account name.
  • LocalSystem, NetworkService, and a virtual account go onto the network as DOMAIN\PC$ in a domain environment. Granting PC$ on the ACL of a shared folder or SQL Server often lets you do without a domain user.
  • Using a domain user for a service has the structural problems of a stop from expiry, the spread of a plaintext password, and Kerberoasting. If you use one, a dedicated account + a long random password + logon restrictions are required.
  • A gMSA is a mechanism in which AD generates and rotates the password automatically; the requirements are a domain, functional level 2012 or higher, and a KDS root key. Set the service to “DOMAIN\name$” with the password field empty.
  • When you change the account, include the “Log on as a service” right, moving the profile and %TEMP%, and re-entering DPAPI-protected data in the migration procedure. Auditing can be confirmed with event ID 4624 logon type 5.

The next time you install a service, stop for a moment on the logon-settings screen and ask this again. As whom, and how far, should this service be able to access? The answer should be some row of this article’s decision table.

KomuraSoft LLC handles logon-account design and least-privilege hardening for Windows services and resident apps, migrating existing services built on the assumption of LocalSystem to a virtual account or a gMSA, and investigating failures caused by access denied, DPAPI, and the profile after an account change. Starting from the stage of “we were flagged in an audit, but we do not know where to begin” is fine.

References

  1. Microsoft Learn, Configure Windows service accounts and permissions. That SQL Server’s default service account is a virtual account (NT SERVICE\MSSQLSERVER and the like), that when specifying a virtual account or an MSA you leave the password field empty, that an MSA is a name with a trailing $ and cannot be used for an interactive sign-in, that Local Service is a shared account so it cannot be separated and is not supported by SQL Server, that using a domain account costs effort in the manual management of the password and the SPN and maintenance can lead to a service stop, and that you should always run a service as a least-privilege account.  2 3 4 5 6

  2. Microsoft Learn, Securing on-premises service accounts. The priority of first a gMSA for an on-premises service, then an sMSA if that cannot be used, then a computer account, and finally a user account; that when you use a computer account you cannot tell which service is using that account and cannot audit a change; and the roles of a service account (identifying, authenticating, and starting the service).  2 3

  3. Microsoft Learn, LocalSystem Account. That LocalSystem holds extensive privileges on the local computer and the token includes the SIDs of NT AUTHORITY\SYSTEM and BUILTIN\Administrators, that it has no password, that it presents the computer’s credentials to a remote server, a list of privileges including SE_DEBUG_NAME and SE_TCB_NAME, and that most services do not need this privilege level and should consider using LocalService/NetworkService.  2 3 4 5 6

  4. Microsoft Learn, sc.exe config. That you specify the service’s logon account with the obj= parameter, that the default is LocalSystem, and the password= parameter when using a user account other than LocalSystem.  2

  5. Microsoft Learn, Local accounts. That SYSTEM (S-1-5-18) has Full Control by default on an NTFS volume, that NETWORK SERVICE (S-1-5-20) presents the computer’s credentials to a remote server, and that LOCAL SERVICE (S-1-5-19) holds minimal privileges locally and presents anonymous credentials to the network.  2 3 4

  6. Microsoft Learn, Service accounts. That a virtual account is an automatically managed local account that needs no password management, that the name is in the NT SERVICE<SERVICENAME> form, that in a domain environment it accesses the network with the computer account’s credentials (\$), and the criteria for choosing among sMSA, gMSA, dMSA, and a virtual account.  2 3 4

  7. Microsoft Learn, Service User Accounts. That a service runs in the security context of a user account, that SCM logs on to the account at start and associates an access token with the service process, that SCM loads the user profile, and that SCM does not manage password expiry so expiry makes the logon fail and the service will not start.  2 3 4 5

  8. Microsoft Learn, Protect SMB traffic from interception. Recommendations including a gMSA as a service-account protection (a long machine-generated random password making password cracking by brute-force or a dictionary attack unrealistic), forcing a long password, and a mention of Kerberos armoring (FAST).  2

  9. Microsoft Learn, Secure group managed service accounts. That a gMSA password is a 240-byte random generation that is hard to brute-force or dictionary-attack, that the Windows OS changes the password every 30 days so an administrator does not need to plan a change or stop the service, deploying to a server farm and simpler SPN management, that if a service does not support a gMSA you use an sMSA and if that is also not possible a standard user account with strong password management, and that you should confirm behavior as a gMSA in a test environment before production.  2 3

  10. Microsoft Learn, Manage group Managed Service Accounts. The gMSA prerequisites (domain/forest functional level 2012 or higher, creating a KDS root key), that the gMSA name must be unique in the forest, that the password-change interval can be set only at creation, specifying the group permitted to retrieve the password with New-ADServiceAccount’s -PrincipalsAllowedToRetrieveManagedPassword, the Install-ADServiceAccount/Test-ADServiceAccount procedure, that a virtual account’s identity is machine-local and is not recognized from the domain, that a failover cluster does not support a gMSA, and that SCM, an IIS app pool, and Task Scheduler support configuring logon as a gMSA.  2 3 4 5

  11. Microsoft Learn, 4624(S): An account was successfully logged on. That event 4624 is recorded on the accessed computer when a logon session is created, that logon type 5 means a service (SCM starting a service), and that the “Virtual Account” field can identify a logon by an MSA or a virtual account and can be used to watch managed service accounts.  2

  12. Microsoft Learn, About Windows Resource Protection. That Windows Resource Protection (WRP) prevents replacement of important system files, folders, and registry keys, that full access to a WRP-protected resource is restricted to TrustedInstaller and a change can be made only through the supported replacement mechanism via the Windows Modules Installer service, and that an application that tries to change a protected resource receives access denied. 

  13. Microsoft Learn, Group Managed Service Accounts overview. That a gMSA is a domain account that leaves password management to Windows, that the domain controller computes the password from the Key Distribution Service (kdssvc.dll) shared secret and a member host queries the domain controller for the current and previous passwords, and that it enables mutual authentication as the same principal in a server farm. 

  14. Microsoft Learn, Create a Key Distribution Service (KDS) root key. That a root key is needed for the domain controller to begin generating gMSA passwords, the creation procedure with Add-KdsRootKey -EffectiveImmediately, that for up to 10 hours after creation you cannot create a gMSA because you wait for AD replication to converge, and that incomplete replication can make password retrieval fail. 

  15. Microsoft Learn, Policy CSP - UserRights: LogOnAsService. That the “Log on as a service” right lets a security principal log on as a service, that Local System, Local Service, and Network Service have this right built in, that a service run as any other account needs this right assigned, and the Group Policy configuration path. 

Recent articles sharing the same tags. Deepen your understanding with closely related topics.

These topic pages place the article in a broader service and decision context.

This article connects naturally to the following service pages.

Frequently Asked Questions

Common questions about the topic of this article.

Should I change a service that I have been running as LocalSystem for now, immediately?
An immediate change is not always the right answer for every case. First confirm whether that service truly needs LocalSystem-class local privileges (strong privileges beyond an administrator). If it is only file read/write and network communication, moving to a virtual account (NT SERVICE\service-name) is the first candidate. At migration time, confirm granting access to the folders and registry keys you need, how data that depends on a profile or DPAPI is handled, and whether the "Log on as a service" right is present. Confirm start and the main functions in a validation environment, then switch production.
Should I choose a virtual account or NetworkService?
For a new choice, we recommend a virtual account. On the network both appear as the computer account (DOMAIN\computer-name$), and both have small local privileges. NetworkService, however, is shared by several services, so you cannot separate with an ACL that "permits only this service". A virtual account has an identity unique to each service, and you can specify NT SERVICE\service-name directly on an ACL. Recent Microsoft products such as SQL Server also default to a virtual account.
Can I use a gMSA in a workgroup environment (no domain)?
No. A gMSA is a mechanism in which an Active Directory domain controller generates and manages the password, and a domain plus creating a KDS root key are prerequisites. In a workgroup environment, the baseline is to finish local processing with a virtual account or LocalService/NetworkService. If you need access to another machine, you need a different design such as explicitly using credentials of an account prepared on the destination. Network access as the computer account (PC$) is also a story that holds only in a domain environment.
After I changed the service's logon account, settings and credentials I had saved can no longer be read. Why?
Because each logon account is tied to its own user profile, %TEMP%, HKEY_CURRENT_USER, and DPAPI key. In particular, data protected with user-scope DPAPI (CryptProtectData and the like) can, in principle, be decrypted only by the same account that protected it. Files saved under the profile (AppData and the like) are also a different path from the new account. Before you switch accounts, plan the procedure for recreating DPAPI-protected data (re-entering API keys and the like) and migrating files under the profile.
If I only want the service to access a shared folder, do I need a domain user?
In many cases, no. In a domain environment, a service running as LocalSystem, NetworkService, or a virtual account authenticates to the remote side as the computer account (DOMAIN\computer-name$). Add that PC$ to the share permissions and the NTFS permissions of the shared folder and it can read and write. If you want access control with a service-specific identity, or the same identity on several servers, consider a gMSA rather than a domain user.

Author Profile

Profile page for the article author.

Go Komura

Representative of KomuraSoft LLC

Focused on Windows software development, technical consulting, and investigations into failures that are difficult to reproduce.

Back to the Blog