Dr_Cox1911
Dr_Cox1911

Reputation: 33

Deploy website to IIS from linux build agent

Problem description

I have a jenkins master that uses a linux build agent to build my ASP.NET Core websites using official MS linux docker containers.

I previously used a windows VM with the necessary tooling installed to build these projects and used MSDeploy.exe to deploy the sites to an IIS webserver. For this deployment I created a web package.

In my linux docker container I obviously can't use MSDeploy.exe.

Question

How can I savely deploy an ASP.NET Core website to an IIS webserver from a linux docker container?

MSDeploy.exe connects to the IIS using a local IIS Users credentials, shutsdown the app, replaces all files that are also present in the new package, so it not just replaces the files but also does some safety settings around the actual replacement.

Misc

I've found this question here, but unfortunately no real answer was found there.

Thanks in advance

Upvotes: 0

Views: 1784

Answers (1)

iinuwa
iinuwa

Reputation: 637

(This all assumes you're using the dotnet CLI to build your application for .NET 8. If you're using another framework or Mono, these steps still apply, but the publish command would change.)

Manually deploying

Deploying to IIS just means copying files into the right place, so if you have a Samba/CIFS (for example using /etc/fstab or gio mount, which doesn't require root and supports Kerberos credentials) or some other remote share to read and write files, you can deploy compiled applications manually.

You can do a clean shutdown using the app_offline.htm file.

  1. Mount application (example using gio mount):
    gio mount smb://iiswebserver.example.com/C\$
    
  2. Build and publish application for Windows:
    dotnet publish --runtime win-x64 --configuration Release --framework net8.0
    
  3. Copy files to server:
    SRC=bin/Release/net8.0/publish/win-x64
    HOSTNAME=iiswebserver.example.com
    DEST=/run/user/$(id -u)/smb-share:server=$HOSTNAME,share=C\$/inetpub/wwwroot/deploypath
    OFFLINE_FILE="${DEST}/app_offline.htm"
    # Stop application temporarily and wait a bit for shutdown
    touch $OFFLINE_FILE
    sleep 5
    cp $SRC/* $DEST
    rm $OFFLINE_FILE
    

(Depending on how you connect, you may need to use sudo for some of these commands.)

Using msdeploy from a Linux server to a Windows IIS server

Installing

If you want to use this from a Linux machine (whether desktop or CI server), you need to copy the files from a Windows computer with msdeploy installed. (You could also download the installer from the website and extract the files from the .msi file. That is left as an exercise for the reader.)

  1. Install Mono onto the Linux machine using the OS instructions from mono-project.com.
  2. Create a directory for the MSDeploy application: sudo mkdir /opt/microsoft/msdeploy
  3. Copy all files from C:\Program Files\IIS\Microsoft Web Deploy V3\* on a Windows machine to /opt/microsoft/msdeploy on the Linux machine.
  4. Write this script to /opt/microsoft/msdeploy/msdeploy:
     #!/bin/bash
     mono $(dirname $(readlink -f $0))/msdeploy.exe $@
    
  5. Create a symbolic link to add it to the PATH: sudo ln -s /opt/microsoft/msdeploy/msdeploy /usr/local/bin/msdeploy

Deploying

Here is an example of how to use this (assuming you're building .NET 8.0; you could also use other frameworks or Mono):

  1. Publish your project for Windows x64 using the dotnet CLI:
    dotnet publish --runtime win-x64 --framework net8.0 --configuration Release
    
  2. Call the executable:
    #!/usr/bin/bash
    SOURCE_FOLDER=/path/to/project/bin/Release/net8.0/publish/win-x64
    SITE_NAME="SITE\\path"
    # I haven't figured out how to do Kerberos authentication, so just doing basic auth here
    USERNAME="[email protected]"
    PASSWORD='good-password!@#$'
    SERVER_HOSTNAME="iisserver01.example.com"
    # If you haven't set up certificates for your Web Deploy endpoint,
    # you'll need to skip cert hostname verification
    ALLOW_UNTRUSTED_CERTIFICATES="true"
    
    # WebDeploy defaults to listen on port 8172 with HTTPS
    ENDPOINT="https://$SERVER_HOSTNAME:8172/msdeploy.axd"
    
    DEST_PARAMS='contentPath="'"${SITE_NAME}"'",ComputerName="'"${ENDPOINT}"'",AuthType="Basic",UserName="'"${USERNAME}"'",Password="'"${PASSWORD}"'"'
    
    msdeploy -verb:sync \
      -source:contentPath=$SOURCE_FOLDER \
      -dest:${DEST_PARAMS} \
      -enableRule:AppOffline \
      -allowUntrusted=$ALLOW_UNTRUSTED_CERTIFICATES
    

Upvotes: 0

Related Questions