Introducing Umbraco's KeepAlive Ping configuration
Tags: umbraco, dotnet, aspnet
Published: 2020-09-15 17:02:00

---
title: Introducing Umbraco's KeepAlive Ping configuration
published: true
date: 2020-09-15 00:00:00 UTC
tags: umbraco, dotnet, aspnet
canonical_url: https://swimburger.net/blog/umbraco/introducing-umbracos-keepalive-ping-configuration
cover_image: https://swimburger.net/media/nu2cdozh/introducing-umbraco-social.png?anchor=center&mode=crop&width=1000&height=420
---

With the release of Umbraco 8.6.0, there's now a way to configure the built-in **KeepAlive** behavior ([pull request #7164](https://github.com/umbraco/Umbraco-CMS/pull/7164)). The new `keepAlive` node can be found inside of `umbracoSettings.config` which has two attributes:

- **keepAlivePingUrl** : Change the URL pinged to keep the Umbraco instance alive. Defaults to `"{umbracoApplicationUrl}/api/keepalive/ping"`.
- **disableKeepAliveTask** : Disable the KeepAlive time interval task by setting it to true. Default to `false`.

Here's what the configuration looks like by out of the box:

```xml
<?xml version="1.0" encoding="utf-8" ?>
<settings>
  ...
  <!--
  keepAlive
    @disableKeepAliveTask
      Disables the periodic KeepAliveTask when set to "true".
      Use this setting to disable the KeepAliveTask in case you already have an alternative.
      For example, Azure App Service has keep alive functionality built-in.
      Defaults to "false".
    @keepAlivePingUrl
      The url of the KeepAlivePing action. By default, the url will use the umbracoApplicationUrl setting as the basis.
      Change this setting to specify an alternative url to reach the KeepAlivePing action. eg http://localhost/umbraco/api/keepalive/ping
      Defaults to "{umbracoApplicationUrl}/api/keepalive/ping".
  -->
  <keepAlive disableKeepAliveTask="false" keepAlivePingUrl="{umbracoApplicationUrl}/api/keepalive/ping" />
</settings>
```

The new configurations help you solve the following two issues:

## 1. KeepAlive doesn't work due to incorrect URL (404)

### Problem

This is how the KeepAlive functionality works with the default configuration:

1. **If the [UmbracoApplicationUrl](https://our.umbraco.com/apidocs/v8/csharp/api/Umbraco.Core.Configuration.UmbracoSettings.IWebRoutingSection.html#Umbraco_Core_Configuration_UmbracoSettings_IWebRoutingSection_UmbracoApplicationUrl) isn't explicitly configured, the first requests made to Umbraco will populate the UmbracoApplicationUrl with whichever FQDN URL was used to make that request.**
2. On a timed schedule, the `ApplicationUrl` is used as the base URL to ping the `KeepAlive` controller. The URL looks like this: `{umbracoApplicationUrl}/api/keepalive/ping`
3. The `OnlyLocalRequests` attribute verifies if the request to the `KeepAliveController.Ping` action came from the local machine.   
**If the request is not made from the local machine, Umbraco returns HTTP 404 response.**
4. The `KeepAliveController.Ping` action receives the request and returns this XML:
```xml
<KeepAlivePingResult xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/Umbraco.Web.Editors">
    <Message>I'm alive!</Message>
    <Success>true</Success>
</KeepAlivePingResult>
```

This is a straightforward process, but **there's no guarantee that the URL to ping will resolve to the local machine as required by the OnlyLocalRequests attribute**. What if the `ApplicationUrl` resolves to a public domain name A but the requests are load balanced among two servers with private domain names B & C?

1. UmbracoApplicationUrl will hold `https://domain-A.tld/umbraco`
2. The KeepAlive timer job will ping `https://domain-A.tld/umbraco/api/keepalive/ping`
3. domain-A.tld will resolve to the public IP of the load balancer which is where the HTTP request will be send to.
4. The `OnlyLocalRequests` attribute will reject the HTTP request and return an HTTP 404 response
5. The KeepAlive job will log the 404 response

**Note 1:** even though the log will be filled with 404 errors, the KeepAlive functionality still 'kinda' works. Any HTTP request made to the Umbraco instance or any ASP.NET website on a regular basis will keep it alive.   
**Note 2:** most load balancers already have built-in health checks which will check whether the website is up and running using HTTP Requests. These requests also would keep the websites alive making the KeepAlive functionality redundant.

When using self-hosted IIS web servers, you could easily resolve these issues by adding internal DNS records that would make the public domain resolve to localhost. But many hosting platforms do not provide the same level of control and customization. This is the case for Azure App Services which would run into the exact same issue as described above, except you can't even request localhost 80 or 443 in an app service.

### Solution

With the new keepAlive configuration, you can configure which URL to ping using the `keepAlivePingUrl` attribute on the `keepAlive` node in the `umbracoSettings.config` file.  
In case of the load balancing scenario, you should configure the `keepAlivePingUrl` with the correct internal domain name that resolves to localhost, or you could simply use localhost if your IIS bindings support that:

```xml
<?xml version="1.0" encoding="utf-8" ?>
<settings>
  ...
  <!--
  keepAlive
    @disableKeepAliveTask
      Disables the periodic KeepAliveTask when set to "true".
      Use this setting to disable the KeepAliveTask in case you already have an alternative.
      For example, Azure App Service has keep alive functionality built-in.
      Defaults to "false".
    @keepAlivePingUrl
      The url of the KeepAlivePing action. By default, the url will use the umbracoApplicationUrl setting as the basis.
      Change this setting to specify an alternative url to reach the KeepAlivePing action. eg http://localhost/umbraco/api/keepalive/ping
      Defaults to "{umbracoApplicationUrl}/api/keepalive/ping".
  -->
  <!-- For Web Server A -->
  <keepAlive disableKeepAliveTask="false" keepAlivePingUrl="https://[INTERNAL_DOMAIN_NAME_A]/api/keepalive/ping" />
</settings>
```

Unfortunately, specifying localhost for Umbraco instances hosted on Azure App Services will not work. Azure App Services won't allow you to request localhost 80 or 443. Luckily, Azure App Service already has its own alternative KeepAlive functionality.

## 2. Redundant KeepAlive functionality

Many platforms already provide their own KeepAlive behavior such as Azure App Services, many load balancers, and reverse proxies. One of the new configuration options allows you to disable Umbraco's KeepAlive functionality. To disable the KeepAlive functionality, change the `disableKeepAliveTask` from `false` to `true`.

```xml
<?xml version="1.0" encoding="utf-8" ?>
<settings>
  ...
  <!--
  keepAlive
    @disableKeepAliveTask
      Disables the periodic KeepAliveTask when set to "true".
      Use this setting to disable the KeepAliveTask in case you already have an alternative.
      For example, Azure App Service has keep alive functionality built-in.
      Defaults to "false".
    @keepAlivePingUrl
      The url of the KeepAlivePing action. By default, the url will use the umbracoApplicationUrl setting as the basis.
      Change this setting to specify an alternative url to reach the KeepAlivePing action. eg http://localhost/umbraco/api/keepalive/ping
      Defaults to "{umbracoApplicationUrl}/api/keepalive/ping".
  -->
  <!-- For Web Server A -->
  <keepAlive disableKeepAliveTask="true" />
</settings>
```

Now that Umbraco's KeepAlive task is disabled, make sure your alternative is enabled. For Azure App Service, enable "Always On" in the General Settings of your app service.

## TL;DR

Umbraco 8.6 introduces the new `keepAlive` configuration inside of `umbracoSettings.config` which allows you to change these two attributes:

- **keepAlivePingUrl** : Change the URL pinged to keep the Umbraco instance alive. Defaults to `"{umbracoApplicationUrl}/api/keepalive/ping"`.
- **disableKeepAliveTask** : Disable the KeepAlive time interval task by setting it to true. Default to `false`.