TL;DR
https://github.com/dirien/octopus-deploy-hackathon
Motivation
Some background story, before we start to dig into the components of my Octopus hackathon entry:
I saw this tweet from the great Sarah Lean
And found following conditions, in the fine print:
Octopus Deploy is part of this year’s Festive Tech Calendar, running a hackathon competition.
The aim of the hackathon is to deploy an Azure Web App using Octopus Deploy.
That sounds very interesting for me, It's really a long time, since I used the Azure App Service and on top I did absolutely nothing with Octopus Deploy. Ever!
Time to start:
The Web App
So let me see, what I should do for the web app! I quickly draw the idea, that I wanted to create a golang webservice, which just delivers a Lofi gif. Quick and cool!
In particular this gif. I don't know, but I am really fascinated from the type of 8-bit pixel art.
So in the https://github.com/dirien/octopus-deploy-hackathon/tree/main/app
folder, you will find the mini go app and the Dockerfile to build the container.
Because now comes one downside: App Service has first-class support for ASP.NET, ASP.NET Core, Java, Ruby, Node.js, PHP, or Python. And no golang support! Now I remember, why I never worked further with Azure App Service, welp! But I can dockerize my app. And that's what I am going to do!
Infrastructure as Code
Terraform is first class citizen in Octopus Deploy:
So I am going to use Terraform this time, for all my deployments in Azure. Octopus Deploy offers many more dedicated, so called steps
and the corresponding step templates
. But since Jenkins, I don't feel it anymore to split my deployments into different providers (Plugins etc.). I want everything in one place.
So in the under https://github.com/dirien/octopus-deploy-hackathon
will you find a very simple terraform deployment.
Terraform Cloud
As backend, I use Terraform Cloud
. I really love it, that it takes care of my state file, and I don't need to look out for them.
There are much more stuff, Terraform Cloud offers. But I think this is material for another blog entry.
There are some variables I want to handle in Octopus Deploy
. Octopus Deploy
will replace variables in all .tf, .tfvars, .tf.json and .tfvars.json files using the #{Variable} substitution syntax. That's great!
So my main.tf looks like this:
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "2.46.0"
}
}
backend "remote" {
hostname = "app.terraform.io"
organization = "dirien"
token = "#{TOKEN}"
workspaces {
name = "octopus-hackathon"
}
}
}
provider "azurerm" {
subscription_id = "#{Azure.SubscriptionNumber}"
client_id = "#{Azure.Client}"
client_secret = "#{Azure.Password}"
tenant_id = "#{Azure.TenantId}"
features {}
}
As you see, the token for the TF Cloud and the credentials for the service principal
of Azure are all variables, which gets substituted from Octopus Deploy
.
The rest of the deployment, is really default. Then only additional value, I hold in Octopus Deploy
is the version of the app via linux_fx_version = "DOCKER|dirien/lofi-go:#{APP_VERSION}"
in the azure.tf
file.
Before committing the code, I always run tfsec
! Please do this too! I love how tfsec
is giving me instant feedback about my terraform script.
Here a little extract:
Result 3
[azure-appservice-require-client-cert][LOW] Resource 'azurerm_app_service.octopus-deploy-as' has attribute client_cert_enabled that is false
/Users/dirien/Tools/repos/octopus-deploy-hackathon/azure.tf:60
57 | dotnet_framework_version = "v4.0"
58 | http2_enabled = true
59 | }
60 | client_cert_enabled = false bool: false
61 | logs {
62 | detailed_error_messages_enabled = true
63 | failed_request_tracing_enabled = true
Impact: Mutual TLS is not being used
Resolution: Enable incoming certificates for clients
More Info:
- https://aquasecurity.github.io/tfsec/latest/checks/azure/appservice/require-client-cert
- https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/app_service#client_cert_enabled
`
Octopus Deploy
Now comes the last part, putting everything together in Octopus Deploy
.
You can sign up for an Octopus Cloud free trial and can play easily for 30d around. That's very nice from the people of Octopus Deploy
.
So I created a Cloud Instance for me:
And with the url https://dirien.octopus.app
I can access my instance.
I added under Infrastructure -> Accounts
my personal Azure subscription via a service principal
and I am good to go, to create project.
Under Project
, I created my two Octopus Deploy
projects
One is to create the infrastructure (including the app deployment) and the other one is to destroy the whole infrastructure. The rest, is all handled in my terraform via PR through a GitOps way of working. State changes, drifts etc. will be all handled by Terraform and Terraform Cloud.
Not surprisingly, my process is straight forward und very simple. Terraform plan, ask for a manual improvement and then Terraform plan. That's it.
The whole logging and auditing, is really nice done in Octopus Deploy
. And I am sure, in a more real life scenario I got spend much more time to create an even more sophisticated deployment process. Really nice!
Azure
When everything went through you will see in the Azure portal your infrastructure:
Same goes for Terraform Cloud.
And with https://octopus-deploy-as.azurewebsites.net/
I can finally call my Web App.