Installing Multiple Instances of InedoAgent on a Single Machine

KB#1146: Last Updated Jan 11, 2018

Sometimes it is helpful to have multiple instances of InedoAgent on the same machine, such as having different instances that run as different user accounts. Although the installation wizard and the manual install process do not support this, it is possible to run multiple instances of InedoAgent as long as they have separate working directories and are listening on separate ports.

Configuring a Second Agent

In the first agent's Program Files folder, there should be three files: agentuninstall.exe, Inedo.Agents.dll, InedoAgentService.exe, and InedoAgentService.exe.config. Create a different Program Files folder and copy these four files there.

We now need to edit the configuration file (InedoAgentService.exe.config). The default file looks like this:

<?xml version="1.0" encoding="utf-8"?>
    <add key="Otter.RootPath" value="C:\ProgramData\InedoAgent\Otter" />
    <add key="BuildMaster.RootPath" value="C:\ProgramData\InedoAgent\BuildMaster" />
    <add key="Port" value="46336" />
    <add key="ServiceName" value="INEDOAGENTSVC" />
    <add key="Encryption" value="aes" />
    <add key="EncryptionKey" value="[randomly generated encryption key]" />
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />

The important things to edit are:

Otter.RootPath This is the temporary directory for Otter. The user that this agent will run as must have full control over this directory. It must not be used for any other agent.
BuildMaster.RootPath This is the temporary directory for BuildMaster. The user that this agent will run as must have full control over this directory. It must not be used for any other agent.
Port This is a TCP port number that the agent will use to listen for connections. The port number must be unique among the services running on the machine, or whichever service tries to use it second will fail to start. It should generally be 4 or 5 digits and cannot be higher than 65535.
ServiceName This tells the agent which service it will be running as. For the purpose of this example, we will use the name INEDOAGENTSVC_LOW, but any name will work as long as it is not already taken. This is not case sensitive.
EncryptionKey An AES-256 key is simply 256 bits (32 bytes) of data. Having a secure key is important for the safety of the machine running the agent, so keys should not be shared between agents or be written anywhere other than InedoAgentService.exe.config and the server settings in BuildMaster or Otter. To generate a cryptographically strong AES-256 key, the below 3-line PowerShell script can be used:

$bytes = [array]::CreateInstance([byte], 32)
[string]::Join("", ($bytes | % {[string]::Format("{0:x2}", $_)}))

Creating the Service

One of the ways to create a service in Windows is the SC.exe command (service control). Other methods exist, but will not be discussed here.

Open a command prompt as administrator. If it is easier to open an administrative PowerShell session, do so and then type cmd to start command prompt.

The command to create the default InedoAgent service is roughly equivalent to this:

sc create INEDOAGENTSVC binPath= "\"C:\Program Files\InedoAgent\InedoAgentService.exe\" run -s" start= auto displayName= "Inedo Agent Service" obj= LocalSystem
sc failure INEDOAGENTSVC reset= 0 actions= restart/60000

This creates a service named INEDOAGENTSVC that runs the InedoAgentService.exe program with run -s as command line arguments. It starts automatically, runs as SYSTEM, and automatically restarts after a minute (60000 milliseconds) if it crashes.

Note that there is always a space after the equals sign when specifying a SC.exe parameter. To create a more restricted InedoAgent service that does not run as SYSTEM, a command like this can be used:

sc create INEDOAGENTSVC_LOW binPath= "\"C:\Program Files\InedoAgent_Low\InedoAgentService.exe\" run -s" start= auto displayName= "Inedo Agent Service (Low Privilege)" obj= "NT Authority\Network Service"
sc failure INEDOAGENTSVC_LOW reset= 0 actions= restart/60000

It is important to note that obj (the user account that the service runs as) must have permission to log in as a service, or the service will not be able to start.