DS Server

Multiple Servers With Load Balancing

Topic

When one DS Server is not enough, you run several instances behind a load balancer. Each instance is a complete DS Server with its own admin database, so two things need planning: every instance must accept the credentials and access tokens of your applications, and every request of a Document Editor session must reach the instance that holds the session.

What follows sets up a group of servers for administrators and DevOps engineers: licensing each instance, sharing the security profiles by cloning or through authentication servers, and configuring the load balancer.

Prepare Each Server

  1. Install DS Server on every server, in the same version, with Docker or any other way from the Installation Guide.
  2. Change the admin password of each instance. See Default Admin Password.
  3. License each instance. DS Server is licensed per server installation, and a container instance counts as one. Register each instance as described in Licensing, or with the licensing endpoints of the Web API when you create instances by script. The Licensing Overview explains the licensing model.

How Instances Share Security Profiles

Each instance keeps its security profiles in its own Admin.db, and it keeps the access tokens it issues there as well. A client that requests a token from one instance and sends it to another instance with OAuth enabled is refused with 401 Unauthorized, unless the second instance can check the token with the first. DS Server offers two ways to set up a group:

Cloned security profilesAuthentication servers
Available sinceAll versionsVersion 3.1.0
Where the profiles areThe same profiles, with the same client IDs and secrets, on every instanceOn one or more instances that act as authentication servers
TokensValid only on the instance that issued themAccepted by every instance that has the issuing server registered
Changing a profileChange it on every instanceChange it on the authentication server
Load balancerSends every request of a client to the same instanceCan send token requests and API calls to any instance; Document Editor connections still need sticky sessions

Clone the Security Profiles

Create the security profiles on one instance, the master server, in the admin portal or with the Web API. Then copy them to the other instances with the admin endpoints GET admin/securityprofiles, GET admin/securityprofiles/{id} and POST admin/securityprofiles. The admin endpoints take the admin user name and password in a Basic authorization header.

The following Bash script copies every profile of one instance to another. It needs curl and jq:

#!/bin/bash
# Copy every security profile from one DS Server to another
SOURCE="http://dsserver1:5000"
TARGET="http://dsserver2:5000"
SOURCE_ADMIN="admin:<admin password of dsserver1>"
TARGET_ADMIN="admin:<admin password of dsserver2>"

for id in $(curl -s --user "$SOURCE_ADMIN" "$SOURCE/admin/securityprofiles" | jq '.[]'); do
  curl -s --user "$SOURCE_ADMIN" "$SOURCE/admin/securityprofiles/$id" \
    | jq '{name, allowClientCredentialsGrantType, expiryDate, clientCredentials}' \
    | curl -s --user "$TARGET_ADMIN" --header "Content-Type: application/json" \
        --data-binary @- "$TARGET/admin/securityprofiles"
  echo
done

The script works as follows:

  • GET admin/securityprofiles returns the IDs of all profiles as a JSON array, such as [1,2].
  • GET admin/securityprofiles/{id} returns one profile with its name, the client credentials (client ID, client secret and authorized redirect URIs), the client credentials grant setting and the expiry date.
  • jq keeps the fields that a new profile takes. allowClientCredentialsGrantType and expiryDate belong at the top level of the body, not inside clientCredentials.
  • POST admin/securityprofiles creates the profile on the target with the same client ID and secret, and returns its new ID. A profile whose client ID already exists on the target is refused with 400 Bad Request and the message "A profile with the given client ID already exists.", so the script can run again after you add profiles.

The OAuth setting is not part of a profile: enable OAuth on each instance, in the admin portal as described in Enable OAuth or with POST admin/oauth. A setting changed through the endpoint takes effect after a restart of the instance.

With cloned profiles, every instance issues its own tokens, and a client must send a token to the instance that issued it. Configure the load balancer to keep each client on one instance, as described below.

Use Authentication Servers

Since version 3.1.0, an instance can ask other DS Server instances whether a request is authorized. You register those instances as authentication servers:

  • When POST oauth/token or GET oauth/authorize can't authorize a request with the instance's own profiles, the instance forwards the request to its registered authentication servers.
  • When a request carries an access token that the instance didn't issue, and OAuth is enabled on the instance, it asks its authentication servers whether the token is valid.

This allows a central authentication server: one instance holds all security profiles, and the other instances have no profiles and register the central one. The processing load stays on the instance that received the request. For redundancy, several or all instances can be authentication servers, so that requests can be authorized when one of them is unavailable.

You register authentication servers on the Authentication page of the admin portal with + Register, a name and the URL of the other instance, or with the admin endpoint POST admin/authenticationservers:

curl --request POST 'http://dsserver2:5000/admin/authenticationservers' \
    --user 'admin:<admin password of dsserver2>' \
    --header 'Content-Type: application/json' \
    --data-raw '{"name": "Authentication server", "serverUrl": "http://dsserver1:5000"}'

The Authentication page of the DS Server admin portal with the heading Authentication Servers, the button Register and an empty table with the columns Name and Url.

Authentication Servers describes the page and the endpoints.

Configure Sticky Sessions

A Document Editor session lives on the instance that opened it: the editor keeps a WebSocket connection to that instance. The load balancer must send every connection of a client to the same instance.

Line-of-business applications are often deployed behind a load balancer that distributes incoming traffic to healthy virtual machines or cloud services. Most cloud providers, such as Azure, offer a distribution mode called source IP affinity, also known as session affinity or client IP affinity. The load balancer uses a 2-tuple (source IP and destination IP) or a 3-tuple (source IP, destination IP and protocol) to choose the server, so connections from the same client always reach the same instance.

A diagram of layer-4 load balancing with session persistence in Microsoft Azure: a client's connections pass a load balancer that uses a 2-tuple hash of source and destination IP, and all reach the same of three virtual machines in an availability set.

With cloned security profiles, source IP affinity also keeps a client's token requests and API calls on the same instance.

Next Steps