> ## Documentation Index
> Fetch the complete documentation index at: https://docs.arct.cloud/llms.txt
> Use this file to discover all available pages before exploring further.

# Windows Server Migration

> Move IIS sites, SQL Server databases, and scheduled tasks to a Windows Server.

This guide moves data, roles, and configuration from an existing Windows Server to an Arct Cloud Windows Server. Read the [migration overview](/migration/overview) first.

<Note>Windows Server images are offered on plans with 2 or more vCPUs. Windows images deploy in 2 to 4 minutes, depending on the image size.</Note>

<Warning>Stop or pause any service that writes while you copy its data. Anything written after the copy starts is left behind. See [why a clean target beats a disk clone](/migration/overview#choose-your-approach).</Warning>

## Deploy the Target Server

Deploy a Windows Server image on a plan with at least the disk and memory the source uses. See [Deploy a Server](/compute/virtual-machines/deploy), then [connect over RDP](/compute/virtual-machines/connect-rdp) as `Administrator`.

## Install Roles and Features First

Export the source server's role list in PowerShell:

```powershell theme={null}
Get-WindowsFeature | Where-Object InstallState -eq Installed |
  Select-Object -ExpandProperty Name > C:\features.txt
```

Install the ones you need on the Arct Cloud server:

```powershell theme={null}
Install-WindowsFeature Web-Server, Web-Asp-Net45 -IncludeManagementTools
```

Reboot if the installer asks for it, before you copy any data.

## Transfer Files

<Warning>Do not expose SMB (port 445) to the public internet to run a file copy. Transfer over SSH or through storage you already trust.</Warning>

Compress the data on the source, then pull it over SSH. The OpenSSH client ships with Windows Server 2019 and later:

```powershell theme={null}
Compress-Archive -Path C:\inetpub\wwwroot -DestinationPath C:\wwwroot.zip
```

From the Arct Cloud server:

```powershell theme={null}
scp Administrator@SOURCE_IP:C:/wwwroot.zip C:\
Expand-Archive -Path C:\wwwroot.zip -DestinationPath C:\inetpub\ -Force
```

If both servers sit on a private network or VPN, `robocopy` is faster for repeat syncs and preserves ACLs:

```powershell theme={null}
robocopy \\SOURCE_HOST\c$\inetpub\wwwroot C:\inetpub\wwwroot /MIR /COPYALL /R:2 /W:5 /LOG:C:\copy.log
```

<Warning>`/MIR` deletes files in the destination that no longer exist in the source. Confirm the destination path before running it.</Warning>

## Move IIS Sites

Export the site configuration on the source:

```powershell theme={null}
& $env:windir\system32\inetsrv\appcmd.exe list site /config /xml > C:\sites.xml
& $env:windir\system32\inetsrv\appcmd.exe list apppool /config /xml > C:\apppools.xml
```

Copy both files across, then import them in this order:

```powershell theme={null}
& $env:windir\system32\inetsrv\appcmd.exe add apppool /in < C:\apppools.xml
& $env:windir\system32\inetsrv\appcmd.exe add site /in < C:\sites.xml
```

Application pool identities do not carry passwords across. Reset them under **IIS Manager** > **Application Pools** > **Advanced Settings**.

## Move SQL Server Databases

Back up each database on the source:

```sql theme={null}
BACKUP DATABASE [AppDb] TO DISK = 'C:\backup\AppDb.bak' WITH COMPRESSION, INIT;
```

Copy the `.bak` file to the Arct Cloud server and restore it:

```sql theme={null}
RESTORE DATABASE [AppDb] FROM DISK = 'C:\backup\AppDb.bak'
WITH MOVE 'AppDb' TO 'C:\Data\AppDb.mdf',
     MOVE 'AppDb_log' TO 'C:\Data\AppDb_log.ldf', REPLACE;
```

SQL logins are stored on the instance, not in the database, so recreate them and repair the orphaned users:

```sql theme={null}
ALTER USER [appuser] WITH LOGIN = [appuser];
```

Restore to the same SQL Server major version or newer. A backup cannot be restored to an older version.

## Scheduled Tasks, Users, and Firewall

Export a scheduled task on the source and recreate it on the target:

```powershell theme={null}
schtasks /query /tn "NightlyJob" /xml > C:\NightlyJob.xml
```

```powershell theme={null}
schtasks /create /tn "NightlyJob" /xml C:\NightlyJob.xml /ru "DOMAIN\user" /rp
```

Export the firewall policy and import it on the new server:

```powershell theme={null}
netsh advfirewall export "C:\firewall.wfw"
```

```powershell theme={null}
netsh advfirewall import "C:\firewall.wfw"
```

Recreate local users and group memberships by hand. Local account passwords do not transfer.

## Verify Before DNS

Add an entry to `C:\Windows\System32\drivers\etc\hosts` on your own machine, opened in an elevated editor:

```
NEW_SERVER_IP example.com www.example.com
```

Browse the site, sign in, and check **Event Viewer** > **Windows Logs** > **Application** for errors. Remove the entry after testing.

## Cut Over

<Steps>
  <Step title="Stop Writes on the Source">
    Stop the site in IIS Manager so no new data lands on the old server.
  </Step>

  <Step title="Run a Final Copy">
    Repeat the file transfer and take a fresh database backup and restore.
  </Step>

  <Step title="Update DNS">
    Change the A and AAAA records to the new IP. See [Website and DNS Migration](/migration/website-dns).
  </Step>

  <Step title="Watch the New Server">
    Follow Event Viewer and the metrics on the server detail page for the first hour.
  </Step>

  <Step title="Decommission the Source">
    Keep the old server for a few days, then run the [checks before you delete it](/migration/overview#before-you-delete-the-old-server).
  </Step>
</Steps>

## Troubleshooting

<AccordionGroup>
  <Accordion title="The site returns HTTP 503">
    The application pool stopped. Open **IIS Manager** > **Application Pools** and check the identity credentials, which do not survive an `appcmd` import.
  </Accordion>

  <Accordion title="SQL Server login fails after restore">
    The database user is orphaned from its instance login. Run `ALTER USER [name] WITH LOGIN = [name];` against the restored database.
  </Accordion>

  <Accordion title="RDP will not connect">
    Confirm the server status is **Running**, then use the **VNC Console** on the server detail page to check that Remote Desktop and the firewall rule are enabled. See [Connect via RDP](/compute/virtual-machines/connect-rdp).
  </Accordion>

  <Accordion title="robocopy reports access denied on every file">
    `/COPYALL` needs backup privileges. Run the shell as Administrator, or drop to `/COPY:DAT` if you do not need to preserve auditing and ownership data.
  </Accordion>

  <Accordion title="A scheduled task never runs">
    The task was imported without stored credentials. Recreate it with `/ru` and `/rp` so the password is set on the new server.
  </Accordion>
</AccordionGroup>
