Repository navigation
[QUESTION] Regarding installing the windows service and integrated security #1823
Description
Activity
- addedquestionFurther information is requestedFurther information is requested
on Jul 29, 2026 - added a commit that references this issue
on Jul 29, 2026 You have it exactly right, on both counts.
For any server with
"auth": "integrated"in darling.json (the default), the service connects to your monitored SQL Servers as whatever Windows account the service logs on as. There is no separate place to configure a Windows credential for monitoring. And yes, your preflight ran as you:--test-connectionfrom a console connects as the logged-in user, so it proved your config and reachability, not what the service account can do.The NT SERVICE virtual account in the docs is the default because it is the least-privilege choice, and it is the right one for SQL auth monitoring. For integrated auth to remote servers it is usually the wrong identity: a virtual account reaches the network as the computer account (
DOMAIN\YourCollectorVM$), so you would end up granting the machine account on every monitored server. Your plan to use your own AD service account is the standard setup, and a gMSA is even better if you have them.Sequence for a fresh install:
-
Run
install-darling.ps1as normal. It creates the service under the virtual account. -
Stop the service and change the Log On account: Services.msc > PerformanceMonitor Darling > Log On > This account >
DOMAIN\svc-account. Services.msc also grants the "Log on as a service" right automatically. From a prompt instead (then grant that right yourself via secpol.msc or GPO):sc config "PerformanceMonitor Darling" obj= "DOMAIN\svc-account" password= "ThePassword"A gMSA works with an empty password:
obj= "DOMAIN\gmsa-name$" password= "". Keep the account out of the local Administrators group: the bundled PostgreSQL refuses to run with administrative privileges. -
Grant the account on each monitored server:
USE master; CREATE LOGIN [DOMAIN\svc-account] FROM WINDOWS;
plus the grants from the README permissions table (VIEW SERVER STATE, ALTER ANY EVENT SESSION, optionally the msdb SQLAgentReaderRole for job monitoring, VIEW ANY DEFINITION if the instance hosts AGs).
-
The step people miss: the service locks its own files down to the account it was running as, so after the switch, from an elevated prompt, before starting it:
icacls "C:\ProgramData\PerformanceMonitorDarling" /grant "DOMAIN\svc-account:(OI)(CI)F" icacls "C:\PerformanceMonitorDarling\darling.json" /grant "DOMAIN\svc-account:F"Adjust the second path to wherever you extracted the service. One time only: the service re-asserts the tight ACL itself on the next start, now including the new account.
-
Start the service and watch
C:\ProgramData\PerformanceMonitorDarling\logsfor the per-server connect lines. That log, not--test-connection, is the proof the service account's grants work.
You were not the first to ask (#1802 covered the same ground), so this whole runbook is now in the Darling README on the dev branch, along with the machine-account and
--test-connectioncaveats above: Run the service as a domain account or gMSA. The steps here and that section are the same content, so follow either; it ships in the next release. The same change (#1824) also fixed the installer so future upgrades of a service running under a custom account keep its file grants intact.-
Thanks for the swift and detailed reply. I'm logged off for the day now, so will try this out tomorrow.
I couldn' t wait, so logged back in to try.
I followed all of the above steps, even pont number 4 and those seemed to return with success. However, after I started the service again (point number 5), I checked the log and noticed this critical error regarding the managed Postgres:
2026-07-29 16:51:10.726 [INFO ] [Lifetime] Application started. Hosting environment: Production; Content root path: C:\PerformanceMonitorDarling
2026-07-29 16:51:10.838 [INFO ] [DarlingWorker] Loaded configuration from C:\PerformanceMonitorDarling\darling.json: 2 server(s)
2026-07-29 16:51:11.521 [CRIT ] [DarlingWorker] Managed Postgres bootstrap failed: The managed Postgres credential file C:\ProgramData\PerformanceMonitorDarling\pg-credential.dpapi is not owned by SYSTEM, Administrators, or the service account — it may have been tampered with or pre-planted. Refusing to trust it. Investigate, then restore it from backup or re-initialize the data directory (destroys collected history).Any suggestions? (I'm completely new to PostgreSQL so if it is obvious how to re-initilaize data directory for Postgres-dudes, it is not for me :) )
That error is the runbook being one file short, not tampering and not anything you did wrong. The account-switch steps missed a case that only exists with the bundled Postgres, and your report is what surfaced it. No re-initializing, and your collected data is fine.
What happened: the service keeps its managed Postgres password in
C:\ProgramData\PerformanceMonitorDarling\pg-credential.dpapi, and as an anti-tamper measure it refuses to trust that file unless it is OWNED by SYSTEM, Administrators, or the account the service runs as. The file was created on your first start, so it is still owned byNT SERVICE\PerformanceMonitor Darling. Theicaclsgrants in step 4 add permissions but never change ownership, so after the account switch the owner check fails and the service refuses the password rather than risk trusting a file someone else planted.The fix, from an elevated prompt, with the service stopped:
takeown /f "C:\ProgramData\PerformanceMonitorDarling\pg-credential.dpapi" /a icacls "C:\ProgramData\PerformanceMonitorDarling\pg-credential.dpapi" /grant "DOMAIN\svc-account:F"The
/ahands ownership to the Administrators group, which the service trusts permanently (and which survives any future account change). The second line is needed even though you already granted the folder in step 4: this file carries a protected ACL that does not inherit from the folder, so it needs its own explicit grant.Then start the service. Two things to expect in the log, both normal:
- One-time warnings like
credential ... is not owned by a trusted principal - discarding and regenerating: the sibling role credential files (admin/viewer/mcp) hit the same ownership check, but those the service can regenerate safely by itself, so it does exactly that. - Then the store coming up and the per-server connect lines for your two servers.
If anything else trips after that, paste the log lines here and I will dig in.
And on the product side: that error message will be fixed to recognize this exact case and print these two commands (instead of pointing you at re-initializing the store), and the README runbook gets the missing step.
- One-time warnings like
- added a commit that references this issue
on Jul 29, 2026 That seemed to do the trick and I got further. But I still got some messages in the log that I wonder about.
First, here are the permissions I have set for my service user on the monitored servers (as found in the documentation. I might have missed some other permissions that should have been added?):
USE [master]
GO
CREATE LOGIN [HS\svc_myserviceuser] FROM WINDOWS WITH DEFAULT_DATABASE=[master]
GO
GRANT VIEW SERVER STATE TO [HS\svc_myserviceuser];
GRANT ALTER ANY EVENT SESSION TO [HS\svc_myserviceuser];
goUSE [msdb];
CREATE USER [HS\svc_myserviceuser] FOR LOGIN [HS\svc_myserviceuser];
ALTER ROLE [SQLAgentReaderRole] ADD MEMBER [HS\svc_myserviceuser];The log shows the following warnings:
//This error seems to come one time for each database on the server:
2026-07-29 17:15:34.620 [WARN ] [DarlingWorker] Failed to collect database_scoped_config from [MyDatabase] on 'MYSERVER': The server principal "HS\svc_myserviceuser" is not able to access the database "MyDatabase" under the current security context.//This error shows up for both servers, even though I have added the service-user to the SQLAgentReaderRole as shown above
2026-07-29 17:15:49.289 [INFO ] [DarlingWorker] [MYSERVER] Skipping recently-failed-job check (msdb/SQLAgentReaderRole access needed): The SELECT permission was denied on the object 'sysjobs', database 'msdb', schema 'dbo'.//This following error I guess is related to the last one
2026-07-29 17:16:20.933 [WARN ] [DarlingWorker] [MYSERVER] running_jobs => insufficient permissions (229): The SELECT permission was denied on the object 'sysjobhistory', database 'msdb', schema 'dbo'.2026-07-29 17:16:21.763 [ERROR] [DarlingWorker] [MYSERVER] default_trace_events => ERROR: You do not have permission to run 'SYS.TRACES'.
2026-07-29 17:16:21.793 [WARN ] [DarlingWorker] [MYSERVER] agent_status => insufficient permissions (229): The EXECUTE permission was denied on the object 'agent_datetime', database 'msdb', schema 'dbo'.
The above warnings/errors might appear serveral times in the log.
Good news and an apology: every warning in your log is real, none of them are your fault, and the permissions in the documentation were wrong. I reproduced all five of your failures on a SQL Server 2025 box using a scratch login carrying exactly the grants you applied, then verified the fixes below with that same login. Here is what each one was:
The msdb denials, despite SQLAgentReaderRole. That role turns out to grant access through the
sp_help_jobstored procedures only, and confers no SELECT on the underlying tables. This product never calls those procedures; it readsmsdb.dbo.sysjobs,sysjobhistory, and friends directly, so the role does nothing for it. Microsoft's own low-privilege monitoring script for SCOM grants explicit table SELECTs for the same reason (their script). Theagent_datetimeerror is the same story one step further: it is a scalar function, EXECUTE is its own permission, and no read role covers it.The per-database errors from
database_scoped_config. Several collectors enter each database to read local catalog views, and a login with no user in those databases gets error 916 for each one.CONNECT ANY DATABASEfixes that for every current and future database with no per-database users to maintain.The
SYS.TRACESerror. Reading the default trace requiresALTER TRACE(sys.traces permissions);VIEW SERVER STATEdoes not cover it on any version. One honest caveat before you grant it:ALTER TRACEis not read-only (it also permits creating and altering traces, and implies SHOWPLAN). If you would rather not grant it, that is a supported choice - skip it and that one collector sits out.One more you could not have seen. While verifying, I found that with database access but without
VIEW ANY DEFINITION, catalog views likesys.tablesandsys.indexesreturn zero rows with no error anywhere - on my test login, 0 of 22 tables were visible. That means the index and object statistics collectors were quietly gathering nothing on your service account while everything looked fine. The grant below fixes it.The complete corrected script for your service account (run on each monitored server):
USE [master]; GRANT CONNECT ANY DATABASE TO [HS\svc_myserviceuser]; GRANT VIEW ANY DEFINITION TO [HS\svc_myserviceuser]; /* Optional - see the caveat above */ GRANT ALTER TRACE TO [HS\svc_myserviceuser]; USE [msdb]; GRANT SELECT ON dbo.sysjobs TO [HS\svc_myserviceuser]; GRANT SELECT ON dbo.sysjobactivity TO [HS\svc_myserviceuser]; GRANT SELECT ON dbo.sysjobhistory TO [HS\svc_myserviceuser]; GRANT SELECT ON dbo.sysjobschedules TO [HS\svc_myserviceuser]; GRANT SELECT ON dbo.syscategories TO [HS\svc_myserviceuser]; GRANT SELECT ON dbo.syssessions TO [HS\svc_myserviceuser]; GRANT EXECUTE ON dbo.agent_datetime TO [HS\svc_myserviceuser];
Your existing VIEW SERVER STATE, ALTER ANY EVENT SESSION, and msdb user stay as they are. The SQLAgentReaderRole membership is harmless to leave in place, it just does not do anything for this product. One note for later: the msdb grants live inside a system database that SQL Server setup can rewrite, so re-check them after a CU or version upgrade.
The documentation in both READMEs is being corrected to this verified script, and three code paths are being fixed along with it: the log message that told you SQLAgentReaderRole was what you needed, the per-database 916 warnings (the collector will skip databases the login cannot enter, the way its siblings already do), and the
SYS.TRACESfailure will classify as a permissions skip instead of an error so declining ALTER TRACE does not look like a fault.Thank you for the thorough reports - three real documentation and product defects came out of this issue, which is a very good day's work for a question. If anything still looks off after the grants, paste the log lines.
- added a commit that references this issue
on Jul 29, 2026 That fixed it. Thank you.
Glad it works. Closing as answered.
For anyone landing here later: the full recipe is now in the docs, corrected by exactly what surfaced in this thread. Service account switching (including gMSA and the credential ownership step) is in the Darling README under "Run the service as a domain account or gMSA", and the verified least-privilege grant script is in the permissions sections of both READMEs. The related product fixes (the misleading log messages, the per-database 916 noise, and the sys.traces error classification) ship in the next release.
Thanks for the careful reports - a question issue that surfaced three real defects is the most useful kind. If anything else comes up after the next release, comment here and it can be reopened.
- added 5 commits that reference this issue
on Jul 31, 2026 - added a commit that references this issue
on Aug 19, 2026
Which component is your question about?
Darling
Performance Monitor Version
3.3.0
Is your question about how it works, or the results?
Setup / installation
What's your question?
My apologies if this is already covered in the documentation (I tried to find the answer there). My question is about the installation of the service and which user account is used for logging into the service.
From what I can see in the documentation, it uses the Virtual NT SERVICE account.
I have not yet tried installing it, as I want to make sure I understand this correctly first. I did run the preflight --test-connection, and that worked fine, but I assume that uses my admin account since I am logged into the VM with it.
So my question is: if the service uses the NT SERVICE account, which account will be used when connecting to the monitored servers? I expected to be able to specify my own AD service account for this.
Is this something I may have misunderstood or missed in the documentation?
Additional Context
Windows SErver 2025 and SQL Server 2025 (while testing)