- C# 100%
| .github | ||
| src/SqlLoginSyncer | ||
| .gitattributes | ||
| .gitignore | ||
| CODE_OF_CONDUCT.md | ||
| CONTRIBUTING.md | ||
| Directory.Build.props | ||
| LICENSE | ||
| README.md | ||
| SECURITY.md | ||
| SqlLoginSyncer.slnx | ||
| THIRD-PARTY-NOTICES.md | ||
sql-login-syncer
A small command-line tool that copies SQL Server logins from a source instance to one or more target instances, preserving each login's password (as a hash) and SID.
Because the SID travels with the login, database users mapped to that login continue to work after a restore, log shipping failover, or Availability Group failover - no orphaned users, no sp_change_users_login, no password resets.
Why SIDs matter
SQL Server maps database users to server logins by SID, not by name. If you recreate a login on another server by name alone, it gets a brand-new SID and every database user mapped to the old SID becomes orphaned. For the full story, see the Logins, SIDs, and Kerberos from First Principles series on sqlserverscience.com.
Requirements
- Windows, with .NET 8.0 runtime (or build a self-contained binary)
- Windows authentication to both source and target instances
securityadminorCONTROL SERVERon the source (required to read password hashes viaLOGINPROPERTY)ALTER ANY LOGIN(orsecurityadmin) on each target
Usage
sql-login-syncer --source <instance> --target <instance>[,<instance>...] [options]
| Option | Description |
|---|---|
--source <instance> |
Source SQL Server instance (required) |
--target <list> |
Comma-separated list of target instances (required) |
--login <list> |
Only sync the named login(s); default is all syncable logins |
--script-only |
Print the generated DDL without executing anything on the targets |
--help |
Show usage |
Examples
Copy every syncable login from PROD1 to two secondaries:
sql-login-syncer --source PROD1 --target PROD2,PROD3
Preview the DDL for a single login without changing anything:
sql-login-syncer --source PROD1 --target PROD2 --login app_service --script-only
Behavior
- SQL logins are created with
PASSWORD = 0x... HASHEDand the originalSID, plusDEFAULT_DATABASE,DEFAULT_LANGUAGE,CHECK_POLICY, andCHECK_EXPIRATIONcarried over. - Windows logins and groups are created with
FROM WINDOWS(their SIDs come from Active Directory or the local SAM, so SQL Server resolves them automatically). - Disabled logins are created and then disabled on the target.
- Existing logins on the target are never modified. If a same-named SQL login exists on the target with a different SID, the tool prints a warning: database users mapped to that login will orphan on restore or failover.
- Excluded from syncing:
saand other fixed principals,NT SERVICE\/NT AUTHORITY\accounts,##...##certificate-mapped internal logins, and certificate- or asymmetric-key-mapped logins.
Exit codes
| Code | Meaning |
|---|---|
| 0 | Success |
| 1 | Invalid arguments |
| 2 | Could not read logins from the source |
| 3 | One or more logins failed to sync |
Building
dotnet build -c Release
The executable lands in src\SqlLoginSyncer\bin\Release\net8.0\sql-login-syncer.exe.
Security notes
- The tool never sees or stores plaintext passwords; it moves the salted hash that SQL Server already stores.
--script-onlyoutput contains password hashes. Treat the output as sensitive: a hash can be cracked offline if the password is weak.- Connections use
Encrypt=truewithTrustServerCertificate=trueby default, matching common internal-network configurations. If your instances have proper certificates, consider changingTrustServerCertificatetofalseinBuildConnectionStringand rebuilding.
License
MIT. Third-party dependency licenses are listed in THIRD-PARTY-NOTICES.md.