Deploy Wyam to an Azure Web App

Easy deployment with Git and Kudu

Published on Wednesday, April 18, 2018

Now that I've got Wyam running on my workstation, I need to work out the deployment methodology for publishing content to my Azure Web App. My objective is to have a painless, largely automated process that allows me to focus on writing.

Why web apps?

First, I think it's important to touch on why I'm hosting via an Azure Web App, especially when there are other options for hosting static sites that probably cost less. My reasoning is simpler than you might think; Web Apps are easy and I'm comfortable with them. I could go into all the benefits of a PaaS IIS model, but there are hundreds of articles out there on that topic.

Google is your friend and can find things for you...

I had seriously considered hosting the site via CDN / Azure Storage for a few pennies per month, but the Web App has one huge benefit for me; if needed I can run an MVC application along side the content generated by Wyam. This would allow me the luxury of some element of dynamic functionality without the overhead of a full CMS.

I think a retro, 90's style page hit counter is in order.

Deployment options

Deployment to a Web App can be done a number of ways, and like anything you'll need to pick the one that makes the most sense for you. For the Wyam use case, I think these options are the most practical, but YMMV.

Visual Studio Publishing

For me, the least desirable option is to deploy using Visual Studio. You could load your generated content into a Visual Studio solution and use it's publish functionality to push everything up to the Azure Web App.

Considering the other options available, I think this idea is dumb. Don't be dumb. Just. Don't.

Will it work? Yes.

FTP

Arguably the simplest and most ancient of our options, FTP is how us old-timers moved things around back in the 1200's. I'm pretty sure the Magna Carta was distributed via plain text on a public FTP server.

FTP is a completely viable option for our Wyam generated site. Create deployment credentials for your Web App, look up your FTP info in the Azure portal and load them into your favorite FTP application to upload the content of your output directory to wwwroot on the server.

If you're feeling like a masochistic internet archaeologist, command line could be fun. Just upload the contents of Wyam's output directory to the wwwroot folder on the Web App and you're golden.

Git, IIS and Kudu

This is the option I've decided to go with.

Each Web Application has an associated service site that runs Kudu as well as a series of other supporting site extensions. Kudu is a significant topic itself and could warrant many posts on what you can do with it. Those are already written by folks with more Kudu smarts than me. Again, do some Googling.

For our purposes, let's consider Kudu in the context of deploying code that exists in a local (on the server) Git repository. I'll walk through workflow a bit later on, but essentially you'll leverage a Git repository on your workstation to manage your Wyam site (not Wyam itself) using whatever Git workflow you use. When you're ready to deploy to your site, you'll push your local master branch up to Azure, watch some wheels spin, and in short order your updates will be live.

Getting code to the server

There are two ways to get your workstation's Git repo onto the server:

  1. Create a public or private repo on Github and push your repo to it, then configure a web hook to link your Web App and your Git repo
  2. Push your code directly to the repo that sits alongside your site in Azure

I won't get into the nitty gritty of setting this up, because again, it's documented everywhere. Just pick one of those options, and get either a web hook configured with your Github repo, or set up some deployment credentials and configure a remote on your workstation repo.

I went with option 2; push directly to the Azure repo.

For me, this was just simpler. Not that Github repos are hard by any stretch, but it felt like an unneeded middleman with a lot of functionality that I'm never going to need for my blog; It's just a blog.

Building with Kudu and Configuring IIS

This is the part where things get fancy; we're going to modify the default Kudu deployment process. Don't worry, it's not hard or scary.

When your Azure repository gets updated, either by you pushing to it, or by the Github web hook doing whatever it does, the build process will start. It's awesome, but we need to do some work before Wyam will build anything.

  1. Upload a release of Wyam - Preferably a new one

    Before we get started, here's the directory structure for an Azure Web App as it relates to our Wyam setup. Yes there are more directories in there, but we don't care about them right now, we only care about these three.

    > D:\home\site
    > D:\home\site\repository
    > D:\home\site\wwworoot
    

    We need to get a compiled version of Wyam onto the server. For a Web App you can either FTP it up with whatever program you use or if you are especially lazy you can do it via the Kudo service site. Find it via the portal, or just cheat and enter this URL making sure to change "your-app-name-goes-here" to the actual app name you configured in Azure.

    https://your-app-name-goes-here.scm.azurewebsites.net
    

    Click on the Debug console in the header, and then CMD or PowerShell, whichever you are most comfortable with.

    Just drag the Wyam.zip file onto the folder you want to upload to, and boom, it will upload and unzip for you. I dragged Wyam.zip to the 'site' directory, which gives me this directory structure where the Wyam directory is filled with the contents of the zip.

    > D:\home\site
    > D:\home\site\repository
    > D:\home\site\wwworoot
    > D:\home\site\Wyam
    
  2. Configure IIS

    To host a Wyam generated static site in IIS, you'll need to configure it to support extensionless URL's and the specific MIME types used by Font Awesome. To do this, we're going to create a web.config file and put it in the "input" directory of your Wyam site.

    Here's mine, tweak yours as needed (you shouldn't need to):

    <configuration>
        <system.webServer>
            <rewrite>
                <rules>
                    <rule name="html">
                        <match url="(.*)" />
                        <conditions>
                            <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
                            <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
                        </conditions>
                        <action type="Rewrite" url="{R:1}.html" />
                    </rule>
                </rules>
            </rewrite>
            <staticContent>
                <remove fileExtension=".svg" />
                <remove fileExtension=".eot" />
                <remove fileExtension=".woff" />
                <remove fileExtension=".woff2" />
                <remove fileExtension=".rss" />
                <mimeMap fileExtension=".svg" mimeType="image/svg+xml"  />
                <mimeMap fileExtension=".eot" mimeType="application/vnd.ms-fontobject" />
                <mimeMap fileExtension=".woff" mimeType="application/font-woff" />
                <mimeMap fileExtension=".woff2" mimeType="application/font-woff2" />
                <mimeMap fileExtension=".rss" mimeType="application/rss+xml" />
            </staticContent>
        </system.webServer>
    </configuration>
    
  3. Modify the Kudu build process

    Now that we have a Wyam release on the server and a web.config that will set up IIS for serving static content, we need to tweak our Kudu deployment. All we need to do is add two text files to the root of our workstation repository.

    1. .deployment
    2. deploy.cmd

    The .deployment file is a configuration file (old school INI) that lets you configure the deployment process. The command value is just a relative pointer to our command file. There are other options that will work here, but this is simple and I like simple.

    [config]
    command = deploy.cmd
    

    The deploy.cmd file will contain all of the command line instructions for building and deploying our site with the copy of Wyam we just uploaded.

    It's been about 92 years since I wrote any windows command line scripts that weren't PowerShell, so I'm sure someone can tell me all the reasons that this is crap. I based this on the default Kudu deployment command, so for now it works and I'm too lazy to pretty it up.

    @if "%SCM_TRACE_LEVEL%" NEQ "4" @echo off
    
    setlocal enabledelayedexpansion
    
    IF NOT DEFINED WYAM_EXE (
    SET WYAM_EXE=D:\home\site\Wyam\wyam.exe
    )
    
    IF NOT DEFINED WYAM_CONFIG (
    SET WYAM_CONFIG=D:\home\site\repository\config.wyam
    )
    
    IF NOT DEFINED WYAM_OUTPUT (
    SET WYAM_OUTPUT=D:\home\site\repository\output
    )
    
    IF NOT DEFINED WWWROOT (
    SET WWWROOT=D:\home\site\wwwroot
    )
    
    ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    :: Deployment
    :: ----------
    echo Handling Wyam Based Web Site deployment.
    
    echo Generating the site and outputing it to the output directory.
    call %WYAM_EXE% %WYAM_CONFIG%
    
    echo Copying files to wwwroot.
    xcopy %WYAM_OUTPUT% %WWWROOT% /S /Y 
    ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    goto end
    
    :end
    endlocal
    echo Finished successfully.
    

    My recommendation here is to just take my two files, put them in the root of your repository and be done with it. If you want to get clever, play with it after you know things are working.

    Now that you have those two files added, your workstation repository working directory should look something like this:

    input
    output
    .deployment
    .gitattributes
    .gitignore
    config.wyam
    config.wyam.dll
    config.wyam.hash
    config.wyam.packages.xml
    deploy.cmd
    

    BTW, make sure your .gitignore looks like this:

    tools/
    output/
    config.wyam.packages.xml
    config.wyam.hash
    config.wyam.dll
    
  4. Time to deploy

    Commit it all to the master branch and push it to Azure. NOTE: When I named the remote for the Azure repo on my workstation repo, I called it "azure".

    > git push azure master
    

    As your repo is being pushed to Azure, you'll see it print out the standard Git statuses to your shell. What's cool here is that once Wyam starts running, you'll also see its output as well which is awesome for remote troubleshooting.

    Be aware that the first time Wyam runs, it's going to download all of its dependent .nuget packages just like it does on your workstation. It might take a few minutes, so be patient and let it do it's thing, it will go much faster in subsequent deployments.

    Once it's done and prints out the success message, open up a browser, visit your site, and marvel at how easy publishing your site is.

  5. Lazy people extra credit

    I believe we only have a limited number of keystrokes in us, and I don't want to type "git push azure master" every time I am ready to publish the site, so I made a Git alias:

    > git config --global alias.deploytoazure push azure master
    

    Now I can deploy the site by simply typing:

    > git deploytoazure
    

Final thoughts

I'm really happy with how this turned out. I've got my Web App purring along, hosting my static site and I can focus on writing rather than running my blog. When I'm ready to publish content I only type in two words and watch the status messages flow. The site is simple and scalable and I don't worry about backups or plugins or updating or patching or any of the maintenance issues that you have with a more traditional blogging platform.

I'd love to hear what you think, drop me a comment below.