United Kingdom: +44 (0)208 088 8978

How to deploy F# web apps to Linux Azure App Service

Isaac gives a brief overview of how Azure App Service for Linux works with F# web apps

We're hiring Software Developers

Click here to find out more

Azure App Service is a great general-purpose web application hosting service, with in-built support for many common features such as deployment, authentication, logging and scaling. In recent years, Microsoft have gradually made more and more of an effort to support Linux for most of their compute services, including App Service. There are many reasons to strongly consider using Linux rather than Windows for hosting F# (and by implication SAFE Stack) applications, not least because the price you'll pay is lower - sometimes by as much as 20% of the equivalent Windows price.

Deploying a .NET web app in Azure

App Service on Windows is essentially a Windows VM with IIS installed, although these days within modern .NET applications, we'll normally use IIS in "passthru" mode and let ASP .NET handle cross-cutting concerns for us. On Linux, there's no IIS, and instead your applications are hosted in Docker containers. This is important insofar as even if you don't supply your application as a docker image (which you can do) and instead supply a zip to the App Service, Azure will automatically create a Docker image based on a template that contains e.g. .NET 6, add your application code to it, and then deploy that image into Docker on the App Service.

In Farmer, we make this very, very easy to do from scratch:

open Farmer
open Farmer.Builders

let web =
    webApp {
        name "mywebapp"
        operating_system Linux
        sku WebApp.Sku.P3V3
        runtime_stack Runtime.DotNet60
        zip_deploy "path_to_compiled_app"

let deployment =
    arm {
        location Location.WestEurope
        add_resource web

|> Deploy.execute "my-resource-group" Deploy.NoParameters

Note: There's nothing stopping you building an app on Windows for deployment on Linux!

This will create an App Service instance with a service plan using the P3V3 SKU and an Application Insights instance with the instrumentation key set as a configuration setting which you can reference from within your application.

Compiling and preparing an F# web app in Azure

But how do you configure the App Service to launch your application? And what do you need to do with your application to "prepare" it for use within the App Service? As it turns out, not a great deal - but the documentation is scattered in a few places, so I figured it was a good idea to include it all in one place. So here's a simple step-by-step guide for deploying a basic F# ASP .NET web app into the app service.

  1. Create an F# Console App: dotnet new console -lang F#.
  2. Change the SDK in the .fsproj to Microsoft.NET.Sdk.Web.
  3. Add Saturn to the project: dotnet add package Saturn.
  4. Create a basic Saturn web app:
open Saturn
open Giraffe

let app = application {
    use_router (text "Hello from Saturn, Giraffe and ASP .NET!")

run app

You don't have to use Saturn (or even ASP .NET Core) here. Any web framework will work, but of course ones such as ASP .NET Core, Giraffe and Falco etc. will all work with an approach similar to the above.

  1. Publish (not just build) your application: dotnet publish -c Release.

This will create a publish folder inside bin/release, that contains all of the build outputs but importantly also a web.config file which contains a startup command that the Linux App Service will use. A simplified version is shown here:

      <aspNetCore processPath="dotnet" arguments=".\name_of_your_app.dll"/>
  1. Deploy your app using either Farmer (see above) or Azure CLI etc.

That should be everything needed to host your F# ASP .NET web application in Azure App Service Linux. An example repository is available here.


App Service on Linux is a relatively low-cost and feature-rich application hosting service that works well with .NET web applications. There are however a few steps that you must follow in order to successfully deploy your code into the service. Once understood, and with an appropriate deployment mechanism such as Farmer or the Azure CLI, you can create and deploy applications quickly and easily in a code-first manner.