Endrias Bridge · June 2026

Windows Guest Initialization &
Database Migration

From first boot to a fully configured, migrated environment — automatically. Covers AWS EC2, Azure VM, and on-premises Windows Server deployments.

🪟 OS: Windows Server 2019 / 2022 Platforms: AWS · Azure · On-Prem 🔧 Script: Endrias Bridge_FirstBoot_Setup.ps1 📦 Engine: Python 3.11 · SQLAlchemy 2.0
Automated Init EC2 User Data Azure Custom Script SQL Server Migration PostgreSQL · MySQL Headless Mode Constraint Migration
What This Document Covers

End-to-end automation: Windows VM first-boot configuration (hostname, timezone, NTP, WinRM, volumes, service account) → prerequisite software installation (Python, ODBC Driver, pip packages) → database migration execution (schema, data, constraints) → post-migration validation and reporting. A single PowerShell script handles the entire flow unattended.

Manual Setup vs. Endrias Bridge Automated Init

TaskManual ProcessEndrias Bridge Automated
Hostname configurationRDP → System Properties → rename✔ Auto from cloud metadata
Timezone / NTPControl Panel → Date/Time✔ tzutil + w32tm configured
WinRM / PS Remotingwinrm quickconfig manually✔ Enabled & hardened automatically
Disk volume extensionDisk Management GUI✔ Resize-Partition to max
Python + ODBC installDownload, run installer, configure PATH✔ Silent MSI install, verified
Migration configManually edit JSON / set up GUI✔ Read from JSON or cloud user-data
Run migrationLaunch GUI, step through wizard✔ Headless CLI, streamed log
IdempotencyRisk of running twice → duplicates✔ Sentinel file prevents re-run
Total time (human)2–4 hours✔ ~15 min unattended

Architecture Diagram

WINDOWS VM FIRST BOOT MIGRATIONBRIDGE INIT ENGINE DATABASE MIGRATION BOOT TRIGGERS 🌿AWS EC2 User Data PowerShell in user-data field · runs as SYSTEM Azure Custom Script Ext. ARM template / portal upload · runs on boot 🖥Sysprep + SetupComplete.cmd On-prem golden image · C:\Windows\Setup\Scripts\ Scheduled Task (one-time) Create task → runs on next boot → self-deletes WHAT RUNS Endrias Bridge_FirstBoot_Setup.ps1 • Reads migration_config.json or user-data • Sentinel .init_complete prevents re-run • Logs to C:\Endrias Bridge\Logs\ ⚡ 10 PLUGIN PHASES Set HostnameFrom cloud metadata · computer rename Set Timezone & NTPtzutil · w32tm /config /resync Network ConfigDNS servers · static IP from metadata Enable WinRMPS remoting · HTTPS listener Extend VolumesResize-Partition to max · idempotent Windows Features.NET 4.8 · MSMQ Create Service AccountEndrias BridgeSvc · least privilege Install Python 3.11 + ODBC 18Silent MSI · pip install requirements Read Migration ConfigJSON file or decoded cloud user-data Run & Finalize Execute migration · write sentinel · tag instance DATABASE MIGRATION ENGINE ① Assess · Compat check · Type preview ② Connect · Test src & tgt · Ensure DB ③ Schema Extract · PK/FK/CHECK/IDX ④ Type Convert · 25+ cross-engine rules ⑤ Load · Full / Incremental / CDC ⑥ Verify · Rows · Constraint count diff ⑦ Schema Objects · Views/Procs/Triggers SUPPORTED TARGETS SQL Server family PostgreSQL family MySQL family NoSQL / Analytics OUTPUT migration_run.log · HTML report .init_complete · init_summary.json 🌿 AWS EC2 IMDSv2 · EC2 User Data · RDS targets CloudWatch · IAM role · VPC SG 🖥 On-Premises Windows Server 2019 / 2022 Sysprep · SetupComplete.cmd · Scheduled Task ODBC Driver 18 · Python 3.11 · pyodbc · psycopg2 ☁ Azure VM IMDS · Custom Script Extension Key Vault · Managed Identity · NSG

Prerequisites

CategoryRequirementNotes
OSWindows Server 2019 or 2022Desktop Experience or Server Core
RAM8 GB minimum · 16 GB recommended16 GB+ for 1 TB+ database migrations
Disk50 GB free on C:\For Python, ODBC driver, logs, and migration temp space
Network outboundHTTPS (443) to python.org, Microsoft downloadAlso outbound to source/target DB ports
PowerShell5.1 minimum · 7.x recommendedScript uses #Requires -RunAsAdministrator
Source DB permissiondb_datareader + VIEW DEFINITIONRequired to reflect schema and read rows
Target DB permissiondb_owner or db_ddladmin + db_datawriterRequired to create tables and insert rows
Execution PolicyRemoteSigned or BypassSet-ExecutionPolicy RemoteSigned -Force

Required Firewall / Security Group Ports

Target EnginePortProtocolDirection
SQL Server / Azure SQL / AWS RDS SQL1433TCPOutbound from migration VM
PostgreSQL / RDS PG / Aurora PG5432TCPOutbound from migration VM
MySQL / RDS MySQL / Aurora MySQL3306TCPOutbound from migration VM
WinRM HTTP (init phase)5985TCPInbound (management)
WinRM HTTPS5986TCPInbound (management)
Python / pip install443TCPOutbound to pypi.org, python.org

First-Boot Trigger Methods

A

AWS EC2 — User Data

Paste the PowerShell script (or a bootstrap stub) into the EC2 instance User Data field at launch. Runs as NT AUTHORITY\SYSTEM on first boot.

AWSAutomated
<powershell>
# Option A: run the script directly from S3
$url = "https://your-bucket.s3.amazonaws.com/Endrias Bridge_FirstBoot_Setup.ps1"
Invoke-WebRequest -Uri $url -OutFile "C:\Endrias Bridge_FirstBoot_Setup.ps1"
powershell.exe -ExecutionPolicy Bypass -File "C:\Endrias Bridge_FirstBoot_Setup.ps1"
</powershell>
B

Azure VM — Custom Script Extension

Deploy via ARM template or Azure Portal → Extensions → Custom Script Extension. The script runs as SYSTEM on first boot or on-demand.

AzureARM Template
{
  "type": "Microsoft.Compute/virtualMachines/extensions",
  "name": "Endrias BridgeInit",
  "properties": {
    "publisher": "Microsoft.Compute",
    "type": "CustomScriptExtension",
    "typeHandlerVersion": "1.10",
    "settings": {
      "fileUris": ["https://yourstorage.blob.core.windows.net/scripts/Endrias Bridge_FirstBoot_Setup.ps1"],
      "commandToExecute": "powershell.exe -ExecutionPolicy Bypass -File Endrias Bridge_FirstBoot_Setup.ps1"
    }
  }
}
C

On-Premises — Sysprep + SetupComplete.cmd

Add the PowerShell call to C:\Windows\Setup\Scripts\SetupComplete.cmd in your Windows golden image before Sysprep. Runs once after OOBE completes.

On-PremGolden Image
:: SetupComplete.cmd
powershell.exe -ExecutionPolicy Bypass -File "C:\Endrias Bridge\Endrias Bridge_FirstBoot_Setup.ps1" -HeadlessMode $true
D

Scheduled Task (One-Time, Any Platform)

Create a one-time scheduled task that runs at next boot, executes the script, then deletes itself. Works on any Windows Server.

$action  = New-ScheduledTaskAction -Execute "powershell.exe" `
    -Argument "-ExecutionPolicy Bypass -File C:\Endrias Bridge\Endrias Bridge_FirstBoot_Setup.ps1"
$trigger = New-ScheduledTaskTrigger -AtStartup
$settings = New-ScheduledTaskSettingsSet -RunOnlyIfNetworkAvailable
Register-ScheduledTask -TaskName "Endrias BridgeInit" -Action $action `
    -Trigger $trigger -Settings $settings -RunLevel Highest -User "SYSTEM"

10 Plugin Phases — Detail

1

Set Hostname

Reads the desired hostname from cloud metadata (EC2: /meta-data/local-hostname, Azure: /metadata/instance/compute/name) or from the migration config. Renames the computer using Rename-Computer. Skip if already matching. A reboot is deferred to end of init run.

AWS / AzureIdempotent
2

Set Timezone & NTP

Sets timezone via tzutil /s "UTC" (or from $TimeZone param). Configures NTP: w32tm /config /manualpeerlist:"time.windows.com,0x1" /syncfromflags:manual /reliable:YES /update then forces sync with w32tm /resync /force.

3

Network Config & DNS

Reads preferred DNS from metadata or config. Falls back to 8.8.8.8, 8.8.4.4 if not specified. Sets via Set-DnsClientServerAddress. Validates connectivity with Test-NetConnection to source and target DB hosts.

4

Enable WinRM

Runs winrm quickconfig -quiet if $EnableWinRM = $true. Sets WinRM service to auto-start. Adds Windows Firewall exception for port 5985. Optionally configures HTTPS listener on 5986 with a self-signed certificate.

5

Extend Volumes

If $ResizeVolumes = $true, uses Get-Partition | Resize-Partition -Size (Get-PartitionSupportedSize).SizeMax for each volume. Safe on cloud VMs where the EBS/Azure disk was expanded after provisioning. Skips if already at max size.

6

Install Windows Features

Installs .NET Framework 4.8 (if not present), optionally MSMQ. Uses Install-WindowsFeature (Server) or Enable-WindowsOptionalFeature (Desktop). Checks current state before installing — fully idempotent.

7

Create Service Account

Creates local user Endrias BridgeSvc with a cryptographically random password (never stored in log). Adds to Users group only — not Administrators. The account is used to run Endrias Bridge in scheduled/service mode.

8

Install Prerequisites

Downloads and silently installs in order:

Each install checks "already present" via registry or command test before downloading.

9

Read Migration Config

Reads migration_config.json from $MigrationConfigPath. Falls back to JSON decoded from cloud user-data (saved in Phase 4). Validates required fields: source host/database/username, target host/database/username. Exits with error code 3 on missing critical fields.

10

Run Migration & Finalize

Executes python -m migrationbridge.headless --config migration_config.json in headless mode, streaming output to the log in real time. Parses exit code and log for FATAL/ERROR/MISMATCH lines. Writes .init_complete sentinel and init_summary.json. Tags EC2 instance with MigrationStatus tag via AWS CLI.

Migration Config Reference

{
  "source": {
    "db_type":   "SQL Server 2019",
    "host":      "sqlserver01.corp.yourcompany.com",
    "port":      1433,
    "database":  "Enterprise_Prod",
    "username":  "migration_reader",
    "password":  "READ_FROM_SECRETS_MANAGER"
  },
  "target": {
    "db_type":   "Azure SQL Database",
    "host":      "prod.database.windows.net",
    "port":      1433,
    "database":  "Enterprise_Migrated",
    "username":  "migration_writer",
    "password":  "READ_FROM_SECRETS_MANAGER"
  },
  "tables":          [],
  "sync_mode":       "full",
  "do_schema":       true,
  "do_data":         true,
  "migration_path":  "SQL Server 2019 → Azure SQL Database"
}
FieldTypeRequiredDescription
source.db_typestringFull engine name e.g. "SQL Server 2019", "PostgreSQL (VM / On-Prem)"
source.hoststringHostname or IP of source database server
source.portint~Default: 1433 SQL, 5432 PG, 3306 MySQL
source.databasestringSource database name
source.usernamestringLeast-privilege read account
source.passwordstringUse Secrets Manager reference — never hardcode
tablesarrayEmpty array = migrate all tables. Or list specific table names.
sync_modestringfull · incremental · cdc. Default: full
do_schemaboolCreate tables + constraints on target. Default: true
do_databoolCopy rows. Default: true
migration_pathstringHuman-readable label e.g. "SQL Server 2019 → Azure SQL Database"

Example: SQL Server 2019 → AWS RDS for PostgreSQL

{
  "source": { "db_type": "SQL Server 2019", "host": "10.0.1.50", "port": 1433,
              "database": "SalesDB", "username": "sa_readonly", "password": "..." },
  "target": { "db_type": "AWS RDS for PostgreSQL", "host": "sales.abc123.us-east-1.rds.amazonaws.com",
              "port": 5432, "database": "salesdb_pg", "username": "pgadmin", "password": "..." },
  "tables": [], "sync_mode": "full", "do_schema": true, "do_data": true
}

Example: Azure SQL Database → AWS RDS for SQL Server (Reverse)

{
  "source": { "db_type": "Azure SQL Database", "host": "he-source.database.windows.net", "port": 1433,
              "database": "HE_Azure", "username": "reader", "password": "..." },
  "target": { "db_type": "AWS RDS for SQL Server", "host": "he-rds.xyz.us-west-2.rds.amazonaws.com",
              "port": 1433, "database": "HE_RDS", "username": "admin", "password": "..." },
  "sync_mode": "full", "do_schema": true, "do_data": true
}

Running Headless Migration

python -m migrationbridge.headless `
    --config  "C:\Endrias Bridge\migration_config.json" `
    --log     "C:\Endrias Bridge\Logs\migration_run.log" `
    --tables  "" `
    --mode    full
FlagDefaultDescription
--configmigration_config.jsonPath to JSON migration config
--logmigration_run.logPath for detailed migration log output
--tables(all)Comma-separated table list; empty = all tables
--modefullfull · incremental · cdc · verify
--no-schemafalseSkip schema creation (data only)
--no-datafalseSkip data copy (schema only)

Exit Codes

CodeMeaning
0SUCCESS — migration completed with no errors
1MIGRATION ERRORS — completed with row/constraint mismatches
2CONNECTION FAILURE — could not connect to source or target
3CONFIG ERROR — required config fields missing or invalid

Post-Migration Validation

Sentinel File — C:\Endrias Bridge\.init_complete

Written at end of successful init run. Contains timestamp, platform, and migration status. If this file exists and $SkipIfAlreadyRun = $true, the init script exits immediately on next run — prevents duplicate migrations.

init_summary.json

{
  "timestamp":        "2026-06-13T08:32:11Z",
  "platform":         "AWS",
  "instance_id":      "i-0abc123456789def0",
  "region":           "us-east-1",
  "python_version":   "3.11.9",
  "odbc_driver":      "ODBC Driver 18 for SQL Server",
  "migration_status": "SUCCESS",
  "tables_migrated":  42,
  "rows_copied":      18473921,
  "log_file":         "C:\\Endrias Bridge\\Logs\\migration_run.log"
}

Manual Validation Queries (T-SQL on Target)

-- Row count spot check
SELECT TABLE_SCHEMA, TABLE_NAME,
       SUM(p.rows) AS row_count
FROM   INFORMATION_SCHEMA.TABLES t
JOIN   sys.partitions p ON OBJECT_ID(t.TABLE_SCHEMA+'.'+t.TABLE_NAME) = p.object_id
WHERE  TABLE_TYPE = 'BASE TABLE' AND p.index_id IN (0,1)
GROUP  BY TABLE_SCHEMA, TABLE_NAME
ORDER  BY row_count DESC;

-- Constraint count check
SELECT TABLE_NAME,
       SUM(CASE WHEN CONSTRAINT_TYPE='PRIMARY KEY' THEN 1 ELSE 0 END) AS pk,
       SUM(CASE WHEN CONSTRAINT_TYPE='UNIQUE'      THEN 1 ELSE 0 END) AS uq,
       SUM(CASE WHEN CONSTRAINT_TYPE='FOREIGN KEY' THEN 1 ELSE 0 END) AS fk,
       SUM(CASE WHEN CONSTRAINT_TYPE='CHECK'       THEN 1 ELSE 0 END) AS ck
FROM   INFORMATION_SCHEMA.TABLE_CONSTRAINTS
GROUP  BY TABLE_NAME
ORDER  BY TABLE_NAME;

AWS EC2 — Specific Notes

🌿
IAM Role Requirements

Attach an IAM role to the EC2 instance with: ec2:CreateTags (to tag instance with MigrationStatus), s3:GetObject (to download scripts/config from S3), secretsmanager:GetSecretValue (to read DB passwords). No AWS access keys in the script — use the instance role exclusively.

Azure VM — Specific Notes

Managed Identity + Key Vault

Assign a system-managed identity to the VM. Grant the identity Key Vault Secrets User role on the Key Vault containing DB credentials. In the init script, retrieve secrets via az keyvault secret show — never store passwords in the custom data field.

On-Premises — Specific Notes

Security & Least Privilege

🔐
Never Store Passwords in User Data or Config Files

EC2 user-data is visible to anyone with ec2:DescribeInstanceAttribute. Azure custom data is stored in plain text in the extension logs. Always reference AWS Secrets Manager or Azure Key Vault and retrieve at runtime.

Retrieve from AWS Secrets Manager (PowerShell)

$secret = aws secretsmanager get-secret-value --secret-id "prod/migrationbridge/source-db" `
          --query SecretString --output text | ConvertFrom-Json
$sourcePassword = $secret.password

Service Account Minimum Permissions

AccountPermissionScope
Source DB accountdb_datareader + VIEW DEFINITIONSource database only
Target DB accountdb_ddladmin + db_datawriterTarget database only
Endrias BridgeSvc (local)Users group onlyLocal machine
EC2 IAM Roleec2:CreateTags · s3:GetObject · secretsmanager:GetSecretValueSpecific resources only
Azure Managed IdentityKey Vault Secrets UserSpecific Key Vault

Troubleshooting

SymptomCauseResolution
Python install fails silentlyTLS 1.2 disabled or proxy blocking downloadsEnable TLS 1.2: [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 · configure $env:HTTPS_PROXY
ODBC driver not found after installRegistry not refreshed; reboot neededRestart the WinRM service or reboot. Verify: Get-OdbcDriver -Name "ODBC Driver 18*"
Connection refused to RDS/Azure SQLSecurity group / NSG / firewall blocking port 1433Add outbound rule for port 1433 from migration VM to RDS endpoint. Check VPC route table.
Migration hangs on large tableNetwork timeout or chunk size too largeSet MIGRATIONBRIDGE_CHUNK_SIZE=5000 env var. Check source query timeout settings.
Constraint mismatch in verify logExpected for cross-engine (MySQL CHECK pre-8.0.16)Review log — if only CHECK counts differ on MySQL < 8.0.16, this is expected. Constraints are stored, not enforced.
Script runs again on rebootSentinel file missing or SkipIfAlreadyRun = $falseCheck C:\Endrias Bridge\.init_complete exists. Set -SkipIfAlreadyRun $true.
pip install fails: "No module named pip"Python installed but PATH not refreshedRestart shell / open new PowerShell window. Or call python -m ensurepip --upgrade
WinRM access deniedLocalAccountTokenFilterPolicy not setSet-ItemProperty HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System -Name LocalAccountTokenFilterPolicy -Value 1

Appendix — Quick Reference

All File Paths Used

PathPurpose
C:\Endrias Bridge\Root install directory
C:\Endrias Bridge\migration_config.jsonMigration source/target/options config
C:\Endrias Bridge\user_data.jsonDecoded cloud user-data (if present)
C:\Endrias Bridge\.init_completeSentinel file — prevents re-run
C:\Endrias Bridge\Logs\Endrias Bridge_Init_YYYYMMDD.logInit phase log
C:\Endrias Bridge\Logs\migration_run.logDatabase migration engine log
C:\Endrias Bridge\Logs\init_summary.jsonFinal status summary
C:\Endrias Bridge\Endrias Bridge_FirstBoot_Setup.ps1The init + migration script

Environment Variable Overrides

VariableDefaultDescription
MIGRATIONBRIDGE_CHUNK_SIZE10000Rows per batch during full copy
MIGRATIONBRIDGE_CONFIGC:\Endrias Bridge\migration_config.jsonOverride config file path
HTTPS_PROXY(none)Proxy for Python/ODBC downloads
NO_PROXY(none)Bypass proxy for specific hosts

Official Download URLs

PackageOfficial URL
Python 3.11.x (64-bit)https://www.python.org/ftp/python/3.11.9/python-3.11.9-amd64.exe
ODBC Driver 18 for SQL Serverhttps://aka.ms/odbc18 (Microsoft official redirect)
Visual C++ Redistributable 2022https://aka.ms/vs/17/release/vc_redist.x64.exe
Git for Windowshttps://git-scm.com/download/win