Naar kennisoverzicht

Deploying your ASP.Net Web App and database to an on-premise VM using VSTS

In one of my previous blogs I showed you how to use VSTS to deploy your ASP.Net Web application and your SQL database to Azure. Not everyone however is that lucky to be able to use Microsoft’s Cloud platform. With the recent addition of Deployment Groups to VSTS Release Management (or TFS 2018 RC1 if you’re running TFS on-premise), deployments to virtual machines got a lot easier and more manageable. In this blog, we will see how we can install a release agent on the server, connect it to VSTS (or TFS), manage the machines state using PowerShell DSC and deploy a Web application to IIS. I’ll be using this demo application.

Create a deployment group in VSTS

The first thing we will have to do is prepare a machine to which our application will be deployed. On this machine, we will install a release agent. VSTS will instruct this agent to perform tasks during the release. I created a Windows 2016 VM in Azure and use this to run the agent and deploy my website to. Go to the release hub in VSTS and click ‘Deployment groups’. Click new and enter the details, use Test for the name and hit Generate. On the right, you’ll find a PowerShell script which installs the agent. Copy this snippet and save it for later. Although you could check ‘Use a personal access token in the script for authentication’ I think you shouldn’t as this will create a Personal Access Token (pat) for the current user you are logged in with. You will probably want to use a different account to create these tokens for. Login with this account and hover over your user menu in the right top corner, click security. Click add to create a new token. Make sure to only select ‘Deployment group (read, manage)’ under Selected Scopes. Save the token that’s created. Now switch users again and go back to Deployment Groups and click Security. Add the use for which you just created a token as an Administrator to this list of users. Now it’s time to run the PowerShell snippet you just saved. Log in to your server and run the script. Be sure to enter ‘pat’ when asked for the authentication method. One thing to note when using TFS on-premise; communication between server and TFS will use https. Make sure you have a valid SSL certificate configured in IIS. Once the script was run successfully you should see your machine in your Deployment Groups.

The release

 It’s time to create a release. I’m assuming you already have a build like explained in this blog post. We will use that one to create a release for. Go to Releases, click the plus sign and ‘Create deployment definition’. The select template window will be shown, select ‘IIS Website and SQL Database Deployment’. Name your environment Test and close the pane. Click on Add artifact and select the correct build. In your Test-environment, click on ‘2 phases, 3 tasks’. This will bring you to your deployment pipeline. On the right you’ll see the linked variables, fill in the required ones, these will be reused in the steps. You can skip the ones under SQL DB Deploy as you may now remove that step. Click on ‘IIS Deployment’ and select the correct deployment group.

The database and Entity Framework Migrations

We are going to use a SQL database on Azure and Entity Framework Migrations. Delete the phase ‘SQL Deployment’ as this is a deployment group phase whereas the steps required to create and migrate our database can perfectly be run on agent within TFS. So, click on ‘…’ in the environment header and click ‘Add agent phase’ and move it above ‘IIS Deployment’ since I want to have my database migrated before I update the application. Add two tasks, one ‘Azure Deployment’-task and one ‘PowerShell Script’-task. In the first task, select your subscription and enter a resource group name. Select database.json as a template and enter the following parameters overrides:

-databaseName $(DatabaseName) -edition "Basic" -requestedServiceObjectiveId dd6d99bb-f193-4ec1-86f2-43d3bccbc49c -maxSizeBytes 2147483648 -serverName $(DatabaseServerName) -serverLocation "West Europe"

Add variables for ‘DatabaseName’ and ‘DatabaseServerName’ The ‘PowerShell Script’ task will run the MigrateDatabase.ps1 we copied in our build. Select this file under Script path and enter ‘-connectionString "$(DatabaseConnectionString)"’ as Arguments. You should off course create a variable for ‘DatabaseConnectionString’ and make sure you mark your password as a private field. More details about these database steps can be found in my previous blog.

Configure your environment using PowerShell DSC

When you create a Windows VM in Azure you cannot just run a ASP.NET application on IIS. There’s stuff missing like ASP.NET 4.5, IIS and the IIS Management Console. The ‘IIS Web App Deploy’-task needs .Net Framework 3.5 installed to run. As I don’t want to configure my server by hand I’ll be using PowerShell DSC to configure the server. We need two PowerShell Scripts to do so. The first one will install some missing DSC Modules, the second one is the actual DSC configuration. Both files are listed below and can be found in the sample app I’m using in this blog on GitHub in the templates folder.

 

 

Install-PackageProvider NuGet -Force
Import-PackageProvider NuGet -Force
Set-PSRepository -Name PSGallery -InstallationPolicy Trusted

Install-Module -Name xWebAdministration

$env:PSModulePath = [System.Environment]::GetEnvironmentVariable("PSModulePath","Machine")
Configuration ServerConfig 
{ 

Import-DscResource -Module xWebAdministration
    Node "localhost" {   

        WindowsFeature installIIS 
        { 
            Ensure="Present" 
            Name="Web-Server" 
        }

        WindowsFeature installIISManagementConsole
        { 
            Ensure="Present" 
            Name="Web-Mgmt-Console" 
        }

        WindowsFeature installWebAspNet45
        { 
            Ensure="Present" 
            Name="Web-Asp-Net45" 
        }

WindowsFeature installNetFramework35
        { 
            Ensure="Present" 
            Name="Net-Framework-Core" 
        }
        
        # Stop the default website 
         xWebsite DefaultSite  
         { 
             Ensure          = 'Present' 
             Name            = 'Default Web Site' 
             State           = 'Stopped' 
             PhysicalPath    = 'C:\inetpub\wwwroot' 
             DependsOn       = '[WindowsFeature]installIIS'
 BindingInfo     = @( MSFT_xWebBindingInformation
                                 {
                                   Protocol              = "HTTP"
                                   Port                  = 81
                                 }
                             )
        }
    }    
}

ServerConfig -OutputPath "C:\DscConfiguration"

Start-DscConfiguration -Wait -Verbose -Path "C:\DscConfiguration"

Add another phase by clicking ‘…’ and ‘Add deployment group phase’. Name it DSC and select the correct Deployment group. Move it above the ‘IIS Deployment’ phase. Add two ‘PowerShell Script’-tasks. In the first one you should select ‘InstallDSCModules.ps1’ under Script path. The second task will be used to run ‘webserver-dsc.ps1’ so select that under Script path. Your complete release definition should now look like mine on the left. Now it’s time to create a release. This first release will take some time since running the DSC config will require some work on the server. Every subsequent release will run a lot faster since the DSC configuration will then only check to see if your server is in the correct state.