Earlier this year we decided to migrate our source control from an in-house Team Foundation Server 2015 installation running on Windows Server 2012R2 to Visual Studio Team Services. One of the key benefits for us was reducing the overhead of managing the TFS server itself (e.g. Windows updates, TFS updates, SQL Server updates, SQL backups, machine backups) as well as ensuring we can easily get to our code from anywhere and also having the ability to integrate various aspects of Office 365 and Team Services using Microsoft Flow.
The overall process to migrate from TFS to VSTS is a little involved, but basically requires you to package up the TFS collection database alongside some configuration files, upload them to Azure and kick off the import process. Microsoft provides this general migration overview, which links to this migration guide.
The migration guide assumes that you are migrating from an Active Directory environment and that you have an Azure Active Directory tenant already setup - we had the latter as we had an Office 365 subscription, but not the former. Our TFS installation was built in a workgroup environment - our local infrastructure had grown somewhat organically and we'd never used Active Directory as it seemed overkill for our limited number of users and servers.
One of the steps in the migration process is to generate a number of configuraton files including an Identity Mapping file, by running the
TfsMigrator prepare command. This is the key step, without having an AD environment this mapping file does not correlate local windows users to valid users in the AAD.
When we ran the TFSMigrator command originally, without doing any of the steps below, it generated an IdentityMap.csv file that contained lines like these:
The key text here is the 'NO MATCH' - which means the tool couldn't map a local windows account to an Azure AD user, it needs to be able to do that if you want to migrate the ownership/assignment of work items. Without a match the import would still work, but the migrated work items would refer to 'ghost' users. We wanted to ensure we had some continuity and that our Office365/AAD users could seamlessley manage work items created by the original local windows users as if they were their own.
So, our challenge was to convert our single-server TFS installation from a workgroup-based one to an AD environment. The approach taken was to:
- Create a new VM running as an AD controller.
- Configure the AD and add users.
- Add the TFS machine to the domain.
- Map the TFS users to domain users.
- Proceed with the TFS migration commands.
I'm not going to go through all of the steps in the TFS migration itself, as the guides cover most of the setup and the details really will vary based on how large your company is, the complexity of your TFS infrastructure and configuration etc. I shall however recommend a few things you should do when performing a TFS Migration (whether you perform the steps below or not):
- Backup your servers and databases. Clearly do this before proceeding with the migration, but also before/after key steps in the process.
- If using VMs then checkpoint them! Do this frequently so you can revert and try again if something hasn't gone to plan.
- Take notes and be methodical. Document every step you make, every server configuration change, every command you execute.
So, without any further ado here are the steps we undertook to convert a workgroup-based TFS 2015 installation to a domain-based TFS 2017 installation:
- Upgrade TFS to the latest version as per the migration documentation (TFS2017 in our case).
- Create a new VM and install Windows Server 2016 Standard edition.
- Configure the new server with a static IP and perform any windows updates.
- The simplest way to create an AD Controller is to install the 'Windows Server Essentials Experience' role using the server manager to Add Roles/Features:
- Once that has installed you'll see a notification that this role need configuring:
- Enter the company details and the Full DNS Name - use the primary domain that is associated with your Azure AD:
- Using Server Manager -> Tools, Create all of the AD users necessary that are referenced in TFS, making sure that you mirror your AAD users exactly: (You might also want to create a test user for the purposes of validating connections to the AD)
- Ensure that the users' Account details are correct and replicate exactly the user information in the Azure AAD:
- The TFS migration guide recommends using the AD Connect tool to synchronize users - and this certainly seemd to be required in order to ensure that the users were mapped correctly. The guide for installing and configuring this is here. For the initial install perform a custom setup and leave all the options empty:
- Once that has completed the AD Connect wizard will continue and we want to make sure that just a basic synchronization is setup. For the 'User Sign-In' page, select 'Do not configure'. Next, supply global administrator credentials for the Azure AD. Once they have been verirfied you'll get to specify the directory to connect - there should be just the one so add that in:
- The next step is the crucial one that will help us ensure we have matching users - make sure this is set as 'userPrincipalName'.
- The remaining steps can all be left as default settings and then allow the synchronization to commence once you're happy with the configuration. To check this has run successfully, you can:
- View details of the AD Connect synchronization in the Azure portal
- Use the Synchronization Service tool on the AD server - although this hasn't been written with any expectation of a pleasant user experience...
- Back to TFS, now we need to add this server to a domain. Log in to the TFS server using a normal administrator account and browse to the AD server: http://<ADservername>/Connect
- Follow the instructions and then to validate, log off, then log back in with your test AD user that you created earlier.
- Map TFS users to domain users.
On your TFS machine, navigate to to the TFS tools directory (e.g. C:\Program Files\Microsoft Team Foundation Server 15.0\Tools)
We'll be using the TFSConfig command in this format to map users from their original local windows accounts to their new AD accounts:
TFSConfig identities /change /fromdomain:<TFShostname> /todomain:<mycompany.com> /account:<oldaccountname> /toaccount:<newaccountname>
TFSConfig identities /change /fromdomain:TFS2012 /todomain:mycompany.com /account:winuser01 /toaccount:andy.mason
Repeat this step for each local windows user that is referenced in TFS and that needs to be mapped to an AD user and hence to an AAD user.
- Assuming by now you have been following the TFS Migration guide and have downloaded the latest TFS Migration tools, run a prepare command in order to generate an IdentityMap.csv file e.g.:
TfsMigrator prepare /collection:https://<TFShostname>/DefaultCollection /tenantDomainName:<mycompany.com>
- Hopefully now your IdentityMap.csv file contains entries like these that map from the on-premises domain users to AAD users:
- At this point, log in to the azure portal and turn off the AD Connect synchronization as well as disabling it on the AD server.
Microsoft allow you to perform 2 TFS migrations by default - a dry run and a production run. Once you've completed your production run and everything is working smoothly and has been checked, double-checked and triple-checked then you can pension off the AD VM and your TFS machine(s).
The steps listed above have only been tested on a single-server TFS installation, where SQL Server was installed on the same machine and there was no Sharepoint instance. Only the TFS machine was added to the local AD and no other machines on the network were affected.
Also, the intent here was to throw away the AD and TFS machines post-migration. In some cases it might be preferable to perform a company-wide migration to an AD environment anyway, which was permanently synchronized with the Azure AD. In which case, clearly the AD Connect setup would be different.