Install Optimizely Agent
How to install Optimizely Agent on Linux, macOS, Windows, Docker, Kubernetes, and AWS Elastic Beanstalk.
Run Agent from source (Linux and macOS)
To develop and compile Optimizely Agent from source complete the following:
- Install Golang version 1.24+.
- Clone the Optimizely Agent repository locally.
- From the repository directory, open a terminal and start Optimizely Agent.
make setupThen run the following:
make runThis starts the Optimizely Agent with the default configuration in the foreground.
Run Agent from source (Windows)
You can use a helper script to install the prerequisites (Golang and Git) and compile Agent in a Windows environment.
-
Clone the Optimizely Agent repo locally.
-
From the repo directory, open a Powershell terminal and run the following:
Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Scope CurrentUser .\scripts\build.ps1 .\bin\optimizely.exe
Run Agent locally with Docker
If you have Docker installed, you can start Optimizely Agent as a container.
- Pull the Docker image.
By default, this will pull the "latest" tag. You can also specify a specific version of Agent by providing the version as a tag to the docker command.
docker pull optimizely/agentdocker pull optimizely/agent:X.Y.Z - Run the docker container with the following:
This starts Agent in the foreground and expose the container API port 8080 to the host.
docker run -p 8080:8080 --env OPTIMIZELY_LOG_PRETTY=true --env OPTIMIZELY_SERVER_HOST=0.0.0.0 --env OPTIMIZELY_SERVER_ALLOWEDHOSTS=127.0.0.1 optimizely/agent - (Optional) You can alter the configuration by passing in environment variables to the preceding command without having to create a
config.yamlfile. See configure Optimizely Agent for more options.
Docker versions
When a new version is released, two images are pushed to Docker Hub. Their tags distinguish them.
- :latest (same as :X.Y.Z)
- :alpine (same as :X.Y.Z-alpine)
The difference between latest and alpine is that latest is built FROM scratch while alpine is FROM alpine.
Run Agent in a Kubernetes cluster
If you run Kubernetes as part of your infrastructure and have Helm installed, you can host Optimizely Agent in your cluster using Optimizely's Helm Chart.
-
Add the
optimizely-agentHelm Chart from Optimizely's repository.helm repo add optimizely-agent https://optimizely.github.io/optimizely-agent-helmThe output should be similar to the following:
"optimizely-agent" has been added to your repositories -
Then, install the Optimizely Agent chart, giving your deployment a name like
my-agent.helm install my-agent optimizely-agent/agentThe output should be similar to the following:
NAME: my-agent LAST DEPLOYED: Tue Jul 12 18:24:27 2022 NAMESPACE: default STATUS: deployed REVISION: 1 NOTES: *** Configuration Summary *** Name Override: [no name override; using generated name] Full Name Override: [no full name override; using generated full name] Image Used: optimizely/agent:latest Service Account: [account name will be generated] Replica Count: 1 Auto-Scaling: [auto-scaling is disabled] Node Selector: [no node selectors applied] Node Affinity: [no node affinity applied] Node Tolerations: [no node tolerations applied] Pod Annotations Applied: [no annotations applied] Pod Security Context: [no pod security context applied] Container Security Context: [no container security context applied] Network Service: Type: ClusterIP Ports: api: 8080 [internal] <== 8080 [external] webhook: 8089 [internal] <== 8089 [external] admin: 8088 [internal] <== 8088 [external] Network Ingress: Run the following in a *nix terminal to access the running ClusterIP service IP address export CLUSTER_IP=$(kubectl get svc --namespace default my-agent -o jsonpath='{.spec.clusterIP}') echo http://$CLUSTER_IP:8080 Resources: [no resources declarations applied] Logging: Level set to DEBUG with friendly formatting ON. SDK Key WILL be included in logs. Environment Variables: [no environment variables applied] Secrets: -
(Optional) You can change the default values in the chart by modifying the
--valuesusing a custom YAML file or individually when you--setflags directly in thehelm installcommand. See modifying values in the GitHub Readme for more options.
Run Agent on AWS Elastic Beanstalk
Deploy Optimizely Agent to AWS Elastic Beanstalk in a Docker container with graceful shutdown handling. This configuration helps Agent finish in-flight requests and release resources cleanly during deployments, scaling events, and maintenance.
Agent listens for SIGTERM and SIGINT in its Go runtime and runs a shutdown routine when either signal arrives. The files in this section make Docker and Elastic Beanstalk forward those signals to Agent. They also extend the timeout so the shutdown routine can finish.
Prerequisites
Before you start, confirm the following:
- A Docker image for Optimizely Agent. The public
optimizely/agentimage works for most deployments. - An AWS Elastic Beanstalk environment that runs Docker containers.
- Permission to add a Dockerfile, an entrypoint script, and an
.ebextensionsconfiguration to your project.
Signal flow
A graceful shutdown crosses the following three layers:
-
Elastic Beanstalk sends
SIGTERMto the Docker container during a deployment, a scaling event, or instance replacement. -
Docker forwards the signal to process ID 1, which is the entrypoint script.
-
The entrypoint script forwards
SIGTERMto the Agent process and waits for the shutdown routine to complete.Agent exits with the same status code as its shutdown routine.
Create the entrypoint script
Create a file named docker-entrypoint.sh in your project root. The script starts Agent, traps SIGTERM and SIGINT, and forwards the signal to the Agent process.
#!/bin/bash
set -e
graceful_shutdown() {
echo "Received termination signal, forwarding to Optimizely Agent..."
kill -TERM "$child_pid" 2>/dev/null || true
wait "$child_pid"
exit_code=$?
echo "Optimizely Agent exited with code $exit_code"
exit $exit_code
}
trap graceful_shutdown SIGTERM SIGINT
echo "Starting Optimizely Agent..."
/opt/optimizely/agent "$@" &
child_pid=$!
wait "$child_pid"
exit_code=$?
echo "Optimizely Agent exited with code $exit_code"
exit $exit_codeBuild the Dockerfile
Add a Dockerfile to your project root. It builds on the public Optimizely Agent image and uses the entrypoint script as the container entrypoint.
FROM optimizely/agent:latest
RUN apt-get update && apt-get install -y \
procps \
&& rm -rf /var/lib/apt/lists/*
COPY docker-entrypoint.sh /usr/local/bin/
RUN chmod +x /usr/local/bin/docker-entrypoint.sh
ENTRYPOINT ["/usr/local/bin/docker-entrypoint.sh"]
CMD ["--config", "/etc/optimizely/config.yaml"]Configure the Elastic Beanstalk Docker timeout
Create an .ebextensions directory in your project root if it does not exist. Then add the file .ebextensions/01-docker-timeout.config. This file extends the Docker stop timeout so Agent finishes its shutdown routine before the platform kills the container.
files:
"/etc/systemd/system/docker.service.d/timeout.conf":
mode: "000644"
owner: root
group: root
content: |
[Service]
TimeoutStopSec=90s
container_commands:
01_increase_docker_stop_timeout:
command: |
echo 'DOCKER_STOP_TIMEOUT=60' >> /opt/elasticbeanstalk/deployment/env
option_settings:
aws:elasticbeanstalk:application:environment:
OPTIMIZELY_SHUTDOWN_TIMEOUT: 30The timeout values work as follows:
OPTIMIZELY_SHUTDOWN_TIMEOUT(30 seconds) – Caps how long Agent waits for in-flight work during shutdown.DOCKER_STOP_TIMEOUT(60 seconds) – Caps how long Docker waits for the container to exit after sendingSIGTERM.TimeoutStopSec(90 seconds) – Caps how longsystemdwaits for Docker to stop.
Each layer must allow more time than the layer it wraps. Otherwise, the platform kills Agent before the shutdown routine finishes.
Deploy and verify
After you save all three files in your project root, verify the signal flow with the following steps:
- Deploy the application to Elastic Beanstalk.
- Trigger a deployment or a scaling event to force a container restart.
- Open the container logs in the Elastic Beanstalk console.
- Confirm the logs show
Received termination signal, forwarding to Optimizely Agent...followed byOptimizely Agent exited with code 0.
Troubleshoot graceful shutdown
- Container exits before shutdown completes – Increase
TimeoutStopSecintimeout.conf, increaseDOCKER_STOP_TIMEOUT, or both. Each value must exceedOPTIMIZELY_SHUTDOWN_TIMEOUT. SIGTERMdoes not reach Agent – Confirm the entrypoint script runs as process ID 1. Rundocker inspecton the container to verify the entrypoint path matches/usr/local/bin/docker-entrypoint.sh.- Agent does not respond to signals – Confirm the Agent binary runs as the direct child of the entrypoint script. Confirm no process manager such as
supervisordortiniwraps the binary.
Updated 18 days ago
