CI/CD an ASP.NET Core application to Plesk/Azure

Pieterjan De Clippel
5 min readOct 13, 2023

This article will cover what you need to do to continuously deploy your ASP.NET Core application to a Plesk or Azure environment.

Creating the project

ASP.NET Core Web Api
  • Just create the project with the default settings.
  • Add the project to your github account

Setup github action

We’ll now setup a github action that does the following:

  • Build the project
  • Checkout a deploy branch
  • Commit the build on the deploy branch

As you can see, we need an SSH keypair. Let’s create it:

ssh-keygen -t rsa -f deploy

This gives us a

  • deploy file containing the private key
  • containing the public key

We need to add the SSH_PRIVATE_KEY as a repository secret. So in your github repository under Settings → Security → Secrets and variables → Actions we can add it:

Paste your SSH private key here (deploy file)

And the SSH_PUBLIC_KEY needs to be added under Deploy keys

Make sure “Allow write access” is checked

Before we go further, we can simply create a deploy branch through the github website:

View all branches
New branch

Create a deploy branch.

We can now commit and push this project setup to github, and check if the branch gets a new commit with the published files.

The workflow succeeded, and we can now see our build in the deploy branch:

Creating the website in Plesk

Add a new domain or subdomain

Configuring the git-hook

You can copy below Deploy actions

This brings you to the following overview

You can now click the Deploy now button:

  • This pulls the files from the deploy branch to the document root
  • Since we have the deployment inside a deploy folder, and not straight under the repo-root, this doesn’t cause any file conflicts
  • After this, the post-deployment script is executed
  • The app-offline.htm file shuts down the website, and releases the lock on the exe and dll files
  • Somehow, the recommended way to have a delay in batch, is by using a ping. Here we wait 2 seconds until the application pool has fully shutdown
  • We delete all dll’s, exe’s and pdb’s from the application root, then wait another 2 seconds (it’s necessary)
  • We use XCOPY to copy the files inside the publish folder to the webroot. I think MOVE would also do it okay
  • Then we once again wait 2 seconds, before deleting the app-offline.htm and publish folder

Note that we (or at least I) cannot use dotnet in this script. Otherwise it would be pretty easy, right? This is why we have to do the build in Github, and push the result to another branch

Configure the webhook

Last but not least, we have to setup a webhook that sends a notification from Github to plesk to indicate that there’s a new commit on a branch. Go to the git module in your plesk website and click the switches in the bottom-right of the card.

Here you need to copy the Webhook URL, then in Github go to your repository → Settings → Webhooks → Create webhook → Pastte the url under Payload URL

  • Content-type: application/json
  • Just the push event is okay
  • Make sure the webhook is active


Now try doing some changes to the project and verify that they’re being deployed fine, without the script exiting in advance. This is why the delays (pings) are added to the script.


Obviously you need to make sure nobody else can push commits to your master/deploy branch.


We have successfully configured our repository to deploy the master branch to a Plesk/Azure environment. We leveraged app_offline.htm to suspend the web application, which releases the lock on the exe and dll files.

I have considered using Github actions rightaway to deploy the files to the webserver, but since the exe and dll files are locked by the webserver, they cannot be overwritten. An untested option is to do the following in our github action:

  • Create app_offline.htm using echo
  • Upload this file through FTP
  • Delay by using sleep 2s or Start-Sleep -s 2
  • Upload the files through FTP, fingers-crossed existing files can be overwritten and are no longer locked
  • Delay 2 seconds again
  • Remove app_offline.htm

By organizing the deploy branch so that the files are inside a subfolder, we no longer need a pre-checkout script to create app_offline.htm to suspend the application pool. We don’t have a pre-checkout script, so this is a nifty workaround.

We can’t use dotnet in the post-deploy script.