Automate deployment with Fake.Deploy

Note! Fake deploy is only in Fake 4 and not been implemented in Fake 5.

I have had several projects building and packing applications using TeamCity for a while, but automated the deployment process have not been on the to-do list so far. Now I am tired of doing deployments to the development- and testing environment manually. Looking around for an easy lightweight solution to do deployment automation, I found Fake.Deploy. Fake.Deploy is installed as a windows service and then it is possible to push applications that should be deployed. The application that should be deployed should be packaged into a NuGet package and inside that package it should be a deploy.fsx script.

Fake.Deploy is not yet available in Fake 5, so Fake 4 is needed so far.

Make application ready for Fake.Deploy

Fake.Deploy works with NuGet packages and the file type that is specified to Fake.Deploy to deploy the application should be a NuGet package of the deployed content. The first thing that is needed is a F# script file (.fsx) with the name deploy.fsx.

#r @"C:\FAKE\tools\FakeLib.dll"

open Fake
open Fake.ConfigurationHelper
open System
open System.IO

let targetDirectory = "C:/PATH/TO/DEPLOY/FOLDER/deployments/PackageName/active"

Target "EnsureDirectory" (fun () ->
    trace <| sprintf " --- Passer på at mappen '%s' finnes ---" targetDirectory
    CreateDir targetDirectory
)

Target "InstallServices" (fun () ->
    trace " --- Install Service ---"
)

Target "Deploy" DoNothing

"EnsureDirectory"
    ==> "InstallServices"
    ==> "Deploy"

The **deploy.fsx ** file is a F# script and is using Fake to define targets. In this file all the steps needed to install the application on the remote server can be done in this file. I normally need to first stop the IIS site and change some Web.config values and start the IIS site again.

The next file that is needed to generate a package that can be deployed using Fake.Deploy is a nuspec file. To create a nuspec file the following command can be used nuget init.

<?xml version="1.0"?>
<package >
  <metadata>
    <id>PackageName</id>
    <version>1.0.0</version>
    <authors>YOUR NAME</authors>
    <owners>YOUR NAME / COMPANY</owners>
    <requireLicenseAcceptance>false</requireLicenseAcceptance>
    <description>FAKE Deploy package</description>
  </metadata>
  <files>
    <file src="Deploy.fsx" target="Deploy.fsx" />
    <!-- Define the file structure needed for the application that should be -->
    <!-- deployed here. -->
  </files>
</package>

The only requirement is that the deploy.fsx file is on the root in the NuGet package.

After the nuspec file is created and all the required files are defined that can be used to package the nupkg package.

nuget pack PackageName.nuspec -Version 1.0.0 -OutputDirectory C:\OUTPUTPATH

When the NuGet package exists it is time to continue setting up Fake.Deploy on the remote server and test the deployment process.

Fake.Deploy setup on the remote server

Go and grab the latest Fake 4 version from NuGet.org. When I am setting up Fake, I place it directly on C:\FAKE.

nuget install FAKE -Version 4.63.2 -ExcludeVersion -OutputDirectory C:\FAKE

Download and configure

When FAKE is in place, it should be some content inside C:\FAKE and one folder should be tools. Open the file C:\FAKE\tools\Fake.Deploy.exe.config. This is the configuration file that it is needed to do all the configurations. Below is the fields that should be set in the configuration. First time and for configuration, I turn off authorization and I turn that on later on when I see that everything works as expected.

<appSettings>
    <add key="ServerName" value="REMOTE.SERVERNAME" />
    <add key="Port" value="8180" />
    <add key="WorkDirectory" value="C:\PATH\TO\DEPLOY\FOLDER" />
    <add key="LogDirectory" value="~/log" />
    <add key="Authorization" value="Off" />
    <add key="AuthorizedKeysFile" value="~/.ssh/authorized_keys" />
</appSettings>

The server name is the name of the server / address that you reach your server from the location that should trigger the deployments. The port number may also needed to be changed and may also need to open that in the firewall. The WorkDirectory is the directory where Fake.Deploy is going to deploy the application that is pushed to the server.

Fake.Deploy.exe /help

When Fake is extracted to C:\FAKE you can see all the options with Fake.Deploy executing the command above in the command prompt.

Install Windows Service

When the configuration is done, it is time to install the Windows Service. This is done by executing the Fake.Deploy.exe from the command line (the command line may be running as Administrator).

.\Fake.Deploy.exe /install

What this command do is install A Windows Service. I have specific users used to everything from building, packaging and deployment. What I then do is located the Fake Deploy service and open the properties window. Then I change the user running the service to my deployment user. That makes it easy to set the permission to what ever I need to do in the deploy script.

Windows Service Window

Uninstalling Fake.Deploy is done with Fake.Deploy.exe /uninstall

When the service is installed it is ready to get applications to deploy. From the configuration values above deploying an application can be done with a command like this:

Fake.Deploy.exe /deployRemote http://REMOTE.SERVERNAME:8180/fake Package.1.0.0.nupkg

Securing Fake.Deploy

So far Fake.Deploy has been configured not using authorization at all. For anything else than testing the deployment setup and make it work, that is a bad idea. So the next thing to do is adding authorization to the Fake.Deploy pipeline.

First you must perform a HTTP-GET to: fake/login/yourUserId [1]

GET: http://REMOTE.SERVERNAME:8180/fake/login/userid

The response from this GET request is a pretty long string value and this needs to be base64 encoded and signed by the private key you should use.

The next step is to make a POST request to /fake/login/youruserid. In the POST request it should contain the base64 encoded value that was received from the GET request and also the signed value.

In the response from the POST request is a GUID and this GUID should be passed in the header of each request to the Fake.Deploy with the header key AuthToken. To logout, it is just to make a GET request to /fake/logout.

That is it, now it should be up and running

I have been using Fake.Deploy for a while now and after I have been setting it up, it has been running non stop and just do what I want it to do. The only thing that I had some issues with (but not related to Fake.Deploy at all) was deploying IIS Sites. I had issues that IIS was holding the process of the sites I needed to deploy. That was solved installing and using the IIS Administration API.

Then it is just to say, happy configuring and happy coding!


  1. HOW TO AUTHORIZE AGAINST FAKE.DEPLOY ↩︎

Teis Lindemark

Software developer, beer brewer and AGENT backer

Bergen, Norway https://teilin.net

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer’s view in any way.