Getting Started

Because Faction is a designed as a series of micro-services, configuring the development environment can be a little complicated.

An important thing to remember is that every service communicates over RabbitMQ and Postgres, so no matter what you're doing you'll need these services running. The easiest way to do this is through the Faction CLI's setup commands (detailed below). This design does mean that you can work on one service, while the others are running in a container as they would in production.

Setting up your development environment

There are essentially two ways you can setup a Faction development environment. The first example will be a pure development environment that doesn't rely on any containerized services. The second will environment will be all containerized services, and then you'll selectively shutdown the services that you're developing.

If you're not working on Faction itself, but instead are developing modules, agents, transports, etc. You'll probably want to use containerized services so that the environment you're working with is as close to production as possible.

Install development dependencies

If doing development on an Ubuntu 18.04 LTS system, the following packages are required (for setup to complete):

  • python3

  • python3-dev

  • python3-setuptools

  • build-essential

They can be installed via the following command:

sudo apt update
sudo apt install python3 python3-dev python3-setuptools build-essential

Clean Environment (No Containers)

  1. Clone the following repositories to your computer

    git clone
    git clone
    git clone
    git clone
    git clone
  2. From the CLI directory, run sudo python install to install the Faction CLI

  3. Setup Faction by running faction setup --dev --external-address http://factionc2:5000

  4. Setup will install just the RabbitMQ and PostgreSQL instances for Faction, it will then pause so you can apply the database schema

  5. Add the following entries to your hosts file api factionc2 db mq
  6. From the Faction Core directory, run the following commands:

    # This has to be done once, and then you only have to
    # run this again if you change the database schema
    dotnet ef migrations add 'Initial'
    # This applies the database schema to PostgreSQL
    dotnet ef database update
  7. Once the database schema has been applied, return to faction setup and press enter to resume setup

  8. From the Build-Service-Dotnet directory, run the following command to start the build server: dotnet run. The build server will start, and should import any agents and modules found in /opt/faction/

  9. From the Core directory, run the following command to start the Core service: dotnet run

  10. From the API directory, run the following commands to start the API service:

    pipenv install
    pipenv shell
  11. From the Console directory, run the following commands to start the Console application:

    npm install
    npm run dev

Containerized Dev Environment

  1. Run through the normal install process

  2. Clone any Faction services repos that you plan on working on.

  3. Stop the service that you'd like to develop for with: docker stop <service_name>, for example: docker stop faction_core_1.

  4. Start the service that you're working on as detailed above.

How Faction Builds Modules and Agents

Modules and Agents leverage Build Servers to compile the artifacts that Faction is expecting. Build Servers by design are pretty simple, there are two things you need to be familiar with:


When a build server starts up, it searches for the following:

  • FactionAgent.<language_name>.json in /opt/faction/agents/

  • FactionModule.<language_name>.json in /opt/faction/modules/<language_name>/

For example, the .NET build server looks for FactionAgent.dotnet.json and FactionModule.dotnet.json.

These files provide the build server with all the information it needs to register the package with Faction. Details on these files can be found in the development sections for Agents and Modules.

Note that TRANSPORT MODULES are registered as part of the AGENT configuration. This may change in the future, but for now it makes sense that transport modules are agent specific.


When a request comes in for a build server to build something, it references the BuildCommand and BuildLocation parameters from the configuration for the object. The BuildCommand tells Faction what command to run to build the artifact, the BuildLocation tells Faction where to pick up the artifact when its built.

When a Faction Build Server runs a BuildCommand, it will provide the command with a path to a Build Configuration file. This file is json file looks like this:

"PayloadName": "<staging key name>",
"PayloadKey": "<staging password>",
"InitialTransportType": "<initial transport module name>",
"TransportModule": "<base64 enccoded transport module>",
"BeaconInterval": <integer representing beacon period in seconds>,
"Jitter": <jitter value between 0.0 and 1.0>,
"ExpirationDate": "<ISO 8601 UTC Date>",
"Architecture": "<x86|x64>",
"OperatingSystem": "<Windows|MacOS|Linux>",
"Configuration": "<Agent provided configuration names>",
"Version": "<Language Version>",
"Debug": <true|false>,
"TransportConfiguration": "<configuration provided by transport server>"

So for example, if you provide a build command of python, when the Build Server builds this object, it will execute python /tmp/tmpfilename where /tmp/tmpfilename is the contents of the build configuration.

An example of how to handle this can be found in Marauder's github repo:

Accessing Postgres and RabbitMQ

During install, a random password is created for Postgres and RabbitMQ. You can find these passwords in the Faction config file at /opt/faction/global/config.json