Configuring LymeStack Based App in OctopusDeploy

This guide is intended to walk you through setting up the Octopus Deploy portion of an on-premesis hosted automated deployment pipeline.

This guide is in draft form. I am writing the first part of this guide mostly from memory so YRMV.

Setup Infrastructure in Octopus

Before configuring your app deployment, you'll need to configure the infrastructure on your Octopus server and deployment targets.

Step 1 - Setup Environments

  1. Go to the "Infrastructure" menu, then "Environments" and click "Add Environment".
  2. Enter the name of the environment. I use "UAT", "Staging" (optional), or "Production". For an explantion of the intention for each environment, view our Environments page. Repeat this step for each environment you intend to set up.

Step 2 - Setup Listening Octopus Tentacles

On each machine that will host an environment, install the Octopus Tentacle. Setup as a listening tentacle and paste the thumbprint of your Octopus server. This can be found in the Octopus Settings (gear icon in upper left of Octopus menu) and "Configuration" and "Thumbprint". You may need to setup firewall rules to allow your tentacles to listen on port 10933 (default).

Step 3 - Setup Deployment Targets for each tentacle on the Octopus server

For each environment, you will need to set up at least one deployment target. For this example, there is a one-to-one relationship between environments, listening tentacles and deployment targets. Repeat this process for each deployment target:

  1. Go to the "Infrastructure" menu, then "Deployment Targets" and click "Add Deployment Target".
  2. For our example, we are using Windows, so select "Windows" and then "Listening Tentacle".
  3. Enter the IP Address of host name for the machine where the listening tentacle us running. If the tentacle is configured properly, Octopus should detect the tentacle settings and all that's needed is to select which environment this deployment target is associated with and specify a target tag. For target tag, I usually specify webserver.

Step 4 - Setup API Key for TeamCity

In order for TeamCity to push packages and create releases in Octopus, you must configure Octopus to allow for it by:

  1. Go to the Octopus settings (gear icon in uppler left of Octopus menu) and "Users" and then click "Add Users".
  2. Enter the name of the user. I use TeamCity.
  3. Select the "The user is a service account" checkbox, which should eliminate the need to enter further details.
  4. Click save and copy / paste the API key to a safe place for use when Configuring TeamCity.
  5. At this point we are almost done, but need to complete one last step in granting the new service account role based access. To do this, return to the Settings menu and then "Teams". You can probably do this differently, but for purposes of this documentation, find the "Octopus Administrators" team.
  6. On the "Members" tab, click "Add member" and select the newly created TeamCity user account. This will give TeamCity full access to interact with Octopus.

Setup a LymeStack Based Deployment Project in Octopus

Now that Octopus is set up, it's time to configure your app's deployment process.

Step 1 - Create a New Project in Octopus

First, we will need to create a new project named after your LymeStack instance name. For this documentation we will use the continued example named "MyCompany". Go to the "Projects" menu in Octopus and enter MyCompany for the company name and optionally "Use version control for this project" (requires some git know-how).

Step 2 - Configure Deployment Steps

There are a few steps involved in this process.

Step 2a - Configure API Deployment

First we will configure the process to deploy the API to the IIS web application.

  1. In the "MyCompany" projet in Octopus, click the "Process" menu option from the left menu and click "Add Step".
  2. You will be asked: "What type of step do you want to add?". Select "Package" and then from the "Installed Step Templates", select "Deploy to IIS".
  3. For the Step name, type Deploy Web API.
  4. For the Target Tags input entry, type webserver.
  5. Under the "Package Details" section
    1. For the "Package Feed" input entry, select the Octopus Server (built-in) option.
    2. For the "Package ID" type MyCompanyApi.
  6. Under the "IIS Web Site and Application Pool" Section.
    1. For IIS Deployment Type, select the IIS Web Application option.
    2. Under the "Web Application" sub-section:
      1. For "Parent web site name" specify the value MyCompany.
      2. For the "Virtual path" specify th value /api.
      3. For the "Physical Path" the default Package installation directory should already be selected.
    3. Under the "Application Pool" sub-section:
      1. For "Application Pool name" specify the value MyCompanyApi.
      2. For ".NET CLR version" specify the No Managed Code option.
      3. For "Identity", specify the credentials you specified when setting up your devops server. In our example, for the username, we will specify iis and then the password for the account. I usually keep the iis user account passowrd the same on both the devops (UAT) server as well as production server. NOTE: If you are using source control to store your Octopus configuration, you will need to store the password in a sensitive Octpus variable when you are setting up project variables. In this case, I would specify the value #{IisAppPoolPassword} and setup a project variable named IisAppPoolPassword containing the sensitve password value there.
  7. Scroll down and click the "Configure features" button. A modal will appear and make sure the "Structured Configuration Variables" option is selected and press "Ok". A new section should appear named "Structured Configuration Variables". Under that section, for the "Target files" input entry, specify the value appsettings.json.
  8. Click "Save" (or "Commit" if using source control) to complete the configuration of this deployment step.

Step 2b - Configure Angular App Deployment

Next we will configure the process to deploy the Angular app to the IIS web application.

  1. In the "MyCompany" projet in Octopus, click the "Process" menu option from the left menu and click "Add Step".
  2. You will be asked: "What type of step do you want to add?". Select "Package" and then from the "Installed Step Templates", select "Deploy to IIS".
  3. For the Step name, type Deploy Angular App.
  4. For the Target Tags input entry, type webserver.
  5. Under the "Package Details" section
    1. For the "Package Feed" input entry, select the Octopus Server (built-in) option.
    2. For the "Package ID" type MyCompanyAngularApp.
  6. Under the "IIS Web Site and Application Pool" Section.
    1. For IIS Deployment Type, select the IIS Web Application option.
    2. Under the "Web Application" sub-section:
      1. For "Parent web site name" specify the value MyCompany.
      2. For the "Virtual path" specify th value /app.
      3. For the "Physical Path" the default Package installation directory should already be selected.
    3. Under the "Application Pool" sub-section:
      1. For "Application Pool name" specify the value MyCompanyApi.
      2. For ".NET CLR version" specify the No Managed Code option.
    4. For "Identity", specify the Application Pool Identity option.
  7. Click "Save" (or "Commit" if using source control) to complete the configuration of this deployment step.

Step 2c - Configure DbUp Console App Deployment

Next we will configure the process to deploy the console app that will be used to execute the DbUp Database Upgrade.

  1. In the "MyCompany" projet in Octopus, click the "Process" menu option from the left menu and click "Add Step".
  2. You will be asked: "What type of step do you want to add?". Select "Package" and then from the "Installed Step Templates", select "Deploy to IIS".
  3. For the Step name, type Deploy a Package.
  4. For the Target Tags input entry, type webserver.
  5. Under the "Package Details" section
    1. For the "Package Feed" input entry, select the Octopus Server (built-in) option.
    2. For the "Package ID" type MyCompany.DbUp.
  6. Scroll down and click the "Configure features" button. A modal will appear and make sure the "Structured Configuration Variables" option is selected and press "Ok". A new section should appear named "Structured Configuration Variables". Under that section, for the "Target files" input entry, specify the value appsettings.json.
  7. Click "Save" (or "Commit" if using source control) to complete the configuration of this deployment step.

Step 2d - Configure DbUp Powershell Script

In order to make database changes as part of a deployment, LymeStack prefers DbUp. We will make use of the "MyCompany.DbUp" project in the "MyCompanyApi" Visual Studio solution.

  1. In the "MyCompany" projet in Octopus, click the "Process" menu option from the left menu and click "Add Step".
  2. You will be asked: "What type of step do you want to add?". Select "Package" and then from the "Installed Step Templates", select "Script".
  3. For the "Step Name" specify Run DbUp Database Upgrade.
  4. Paste the following script source code (file is in source control as MyCompanyApi/MyCompanyApi.DbUp/DeployDatabase.ps1)
## Configuration Variables:
$releaseNumber = $OctopusParameters["Octopus.Release.Number"]
Write-Host "`$releaseNumber: $releaseNumber"

$appDirectory = $OctopusParameters["Octopus.Tentacle.Agent.ApplicationDirectoryPath"]
Write-Host "`$appDirectory: $appDirectory"

$projectName = "MyCompany.DbUp"
Write-Host "`$projectName: $projectName"

$environmentName = $OctopusParameters["Octopus.Environment.Name"]
Write-Host "`$environmentName: $environmentName"

$baseDir = "$appDirectory\$environmentName\$projectName\$releaseNumber"
Write-Host "`$baseDir: $baseDir"

$escapedText = $baseDir.replace('\', '\\')
Write-Host "`$escapedText: $escapedText"

$scriptsFolderPath = "$escapedText\\Scripts"
Write-Host "`$scriptsFolderPath: $scriptsFolderPath"

$exePath = "$baseDir\$projectName.exe"
Write-Host "`$exePath: $exePath"

Write-Host "`$DbUpDatabasePassword: $DbUpDatabasePassword"
Write-Host "------------------------------------------------------"
Write-Host "Running DbUp... $exePath $scriptsFolderPath $DbUpDatabasePassword"

& $exePath $scriptsFolderPath $DbUpDatabasePassword | Write-Host
Write-Host "Done Running DbUp..."
  1. For "Execution Location" select the "Run on each deployment target"
  2. For Target Tags enter the value webserver.

Step 3 - Setup DbUp SQL Server user and password

In SSMS, execute this script on the SQLEXPRESS insteance of each environment's SQL Server. Remember to specify a secure password and store that password in a secure location for reference when setting up future deployments.:

USE master;
GO

-- Check if the login already exists; if not, create it
IF NOT EXISTS (SELECT * FROM sys.server_principals WHERE name = 'dbup')
BEGIN
    CREATE LOGIN dbup WITH PASSWORD = 'SPECIFYASECUREPASSWORDHERE';
    PRINT 'Login dbup created.';
END
ELSE
BEGIN
    PRINT 'Login dbup already exists.';
END
GO

-- Switch to the target database
USE MyCompany;
GO

-- Check if the user already exists in the target database; if not, create it
IF NOT EXISTS (SELECT * FROM sys.database_principals WHERE name = 'dbup')
BEGIN
    CREATE USER dbup FOR LOGIN dbup
    PRINT 'User dbup created in MyCompany database.'
END
ELSE
BEGIN
    PRINT 'User dbup already exists in MyCompany database.'
END
GO

-- Check if the user is already a member of the db_owner role; if not, add them
IF NOT EXISTS (
    SELECT dp.name 
    FROM sys.database_role_members AS drm
    JOIN sys.database_principals AS dp ON drm.member_principal_id = dp.principal_id
    JOIN sys.database_principals AS rp ON drm.role_principal_id = rp.principal_id
    WHERE rp.name = 'db_owner' AND dp.name = 'dbup'
)
BEGIN
    ALTER ROLE db_owner ADD MEMBER dbup;
    PRINT 'User dbup added to db_owner role in MyCompany database.'
END
ELSE
BEGIN
    PRINT 'User dbup is already a member of db_owner role in MyCompany database.'
END
GO

Step 4 - Configure Project Variables

Project variables are perhaps one of Octopus's most valuable and powerful features. It allows Octopus to specify overriding values in configuration files for differing environments. LymeStack only requires one variable to be defined in its default set up, but this area will probably be more heavily used in the production environment when it comes to this such as SMTP settings, payment processing keys or any other API keys used to integrate with third party services.

At minimum, the ApiConfig:environment variable must be defined. The value for that variable should match the environment name.

Also, add the DbUpDatabasePassword variable as a sensitive variable to hide the value of the password. Specify the value as the password you edited in the script above.

Here's a screenshot of my configuration variables as an example:

Environment Variable Screenshot

Next, you are ready to Configure TeamCity.