Starting the controller manually

Controller is started with


Any arguments passed to the scripts will be passed as-is to the java process.

When you don’t intend to run distributed benchmarks you can start the controller in standalone mode:


This variant won’t deploy any agents remotely and therefore it does not need any agents: section in the benchmark definition; instead it will use single agent started in the same JVM.

Below is the comprehensive list of all the properties Hyperfoil recognizes. All system properties can be replaced by environment variables, uppercasing the letters and replacing dots and dashes with underscores: e.g. io.hyperfoil.controller.host becomes IO_HYPERFOIL_CONTROLLER_HOST.

Property Default Description
io.hyperfoil.controller.host Host for Controller REST server
io.hyperfoil.controller.port 8090 Port for Controller REST server
io.hyperfoil.rootdir /tmp/hyperfoil Root directory for stored files
io.hyperfoil.benchmarkdir root/benchmark Benchmark files (YAML and serialized)
io.hyperfoil.rundir root/run Run result files (configs, stats…)
io.hyperfoil.deployer ssh Implementation for agents deployment
io.hyperfoil.deployer.timeout 15000 ms Timeout for agents to start
io.hyperfoil.agent.debug.port   If set, agent will be started with JVM debug port open
io.hyperfoil.agent.debug.suspend n Suspend parameter for the debug port
io.hyperfoil.controller.cluster.ip first non-loopback Hostname/IP used for clustering with agents
io.hyperfoil.controller.cluster.port 7800 Default JGroups clustering port
io.hyperfoil.controller.external.uri   Externally advertised URI of REST server
io.hyperfoil.controller.keystore.path   File path to Java Keystore
io.hyperfoil.controller.keystore.password   Java Keystore password
io.hyperfoil.controller.pem.keys   File path(s) to private TLS key(s) in PEM format
io.hyperfoil.controller.pem.certs   File path(s) to server TLS certificate(s) in PEM format
io.hyperfoil.controller.password   Password used for Basic authentication
io.hyperfoil.controller.secured.via.proxy   This must be set to true for Basic auth without TLS encryption
io.hyperfoil.trigger.url   See below

If io.hyperfoi.trigger.url is set the controller does not start benchmark run right away after hitting /benchmark/my-benchmark/start ; instead it responds with status 301 and header Location set to concatenation of this string and BENCHMARK=my-benchmark&RUN_ID=xxxx. CLI interprets that response as a request to hit CI instance on this URL, assuming that CI will trigger a new job that will eventually call /benchmark/my-benchmark/start?runId=xxxx with header x-trigger-job. This is useful if the the CI has to synchronize Hyperfoil to other benchmarks that don’t use this controller instance.


Since Hyperfoil accepts and invoked any serialized Java objects you must not run it exposed to public to prevent a very simple remote code execution. Even if using HTTPS and password protection (see below) we recommend to limit access and privileges of the process to absolute minimum.

You can get confidential access to the server using TLS encryption, providing the certificate and keys either using Java Keystore mechanism (properties above starting with io.hyperfoil.controller.keystore) or via PEM files (properties starting with io.hyperfoil.controller.pem). These options are mutually exclusive. In the latter case it is possible to use multiple certificate/key files, separated by comma (,).

Authentication uses Basic authentication scheme accepting any string as username. The password is set using io.hyperfoil.controller.password or respective environment variable. If you’re exposing the server using plaintext HTTP you must set -Dio.hyperfoil.controller.secured.via.proxy=true to confirm that this is a desired configuration (e.g. if the TLS is terminated at proxy and the connection from proxy does not require confidentiality).