Install Observe Agent using Ansible on Windows¶
Note
These instructions apply to tenants created on or after June 6, 2025. Interested in upgrading to the new experience? Open Docs & Support → Contact Support in the product and let us know.
This page provides instructions for installing the Observe Agent on Windows systems via Ansible to collect metrics, logs, and application telemetry—including OpenTelemetry traces—and forward them to Observe.
Once you follow instructions, here’s how the directory layout should look.
/etc/ansible/
├─ hosts/
│ ├─ windows.aws_ec2.ini # ← inventory
│ └─ group_vars/
│ └─ windows.yaml # creds + overrides
├─ roles/
│ └─ agent/
│ ├─ tasks/
│ │ ├─ main.yaml # imports install_with_ps1.yaml
│ │ ├─ install_with_ps1.yaml
│ │ └─ update_config.yaml
│ └─ templates/
│ └─ observe-agent.yaml.j2
├─ install-observe-agent-windows.yaml
├─ update-observe-agent-windows.yaml # ← update playbook
└─ uninstall-observe-agent-windows.yaml # ← uninstall playbook
Prerequisites¶
Install Ansible on your control node. The control node used on this page is Ubuntu 24.04.
Install the Python WinRM client libraries on the control node.
python -m pip install "pywinrm>=0.4.3" requests requests-ntlm
Create an inventory file (
/etc/ansible/hosts/windows.aws_ec2.ini
) on the control node
; --------------------------
; WINDOWS INVENTORY EXAMPLE
; --------------------------
[win_proxy_servers]
ansible-managed-node-2 ansible_host=172.31.34.10
[win_load_balancer]
ansible-managed-node-1 ansible_host=172.31.35.121
[windows:children]
win_proxy_servers
win_load_balancer
[windows:vars]
; use WinRM instead of ssh
ansible_connection=winrm
; 5986 = HTTPS listener (recommended)
ansible_port=5986
ansible_winrm_scheme=https
; escape backslash in INI
ansible_user=Administrator
; store in Ansible Vault in real life
ansible_password=<YOUR_PASSWORD>
; or ntlm / credssp / basic
ansible_winrm_transport=ntlm
; OK for self-signed lab certs
ansible_winrm_server_cert_validation=ignore
Enable WinRM HTTPS on each Windows host (run once). If your control node can already reach the managed Windows hosts over WinRM, you can skip directly to Step 5.
### 1. Create a self-signed cert (CN & SAN = computer name + FQDN)
$dnsName = "$env:COMPUTERNAME"
$dnsFqdn = "$env:COMPUTERNAME.$((Get-WmiObject Win32_ComputerSystem).Domain)"
$cert = New-SelfSignedCertificate `
-DnsName $dnsName,$dnsFqdn `
-CertStoreLocation Cert:\LocalMachine\My `
-KeyLength 2048 `
-NotAfter (Get-Date).AddYears(3) `
-FriendlyName "WinRM HTTPS"
### 2. Remove any old HTTPS listeners (optional cleanup)
Get-ChildItem WSMan:\Localhost\Listener | Where-Object { $_.Keys -match 'Transport=HTTPS' } | Remove-Item -Recurse -Force
### 3. Bind the new cert to an HTTPS listener on all addresses
New-Item -Path WSMan:\Localhost\Listener `
-Transport HTTPS `
-Address * `
-CertificateThumbprint $cert.Thumbprint `
-Force
### 4. Remove any half-created rule so we start clean
Get-NetFirewallRule -DisplayName 'WinRM HTTPS (TCP 5986)' -ErrorAction SilentlyContinue |
Remove-NetFirewallRule
### 5. Create a fresh inbound rule that allows ALL profiles
New-NetFirewallRule -DisplayName 'WinRM HTTPS (TCP 5986)' `
-Name 'WinRM-HTTPS-TCP-5986' `
-Protocol TCP -LocalPort 5986 `
-Direction Inbound -Action Allow `
-Profile Any
### 6. Verify
winrm enumerate winrm/config/listener
Test-NetConnection -ComputerName $env:COMPUTERNAME -Port 5986
Test connectivity
ansible windows -i /etc/ansible/hosts/windows.aws_ec2.ini -m ansible.windows.win_ping
A successful check returns output similar to:
ansible-managed-node-2 | SUCCESS => {
"changed": false,
"ping": "pong"
}
ansible-managed-node-1 | SUCCESS => {
"changed": false,
"ping": "pong"
}
Create
windows.yaml
under/etc/ansible/hosts/group_vars
.
Replace <YOUR_INGEST_TOKEN>
with your instance’s ingest token you create from the Add Data for Windows page (ex: a1b2c3d4e5f6g7h8i9k0:l1m2n3o4p5q6r7s8t9u0v1w2x3y4z5a6) and <YOUR_OBSERVE_COLLECTION_ENDPOINT>
with your instance’s collection endpoint (ex: https://123456789012.collect.observeinc.com/). For more information on configuring the agent, see Configuration.
YOUR_OBSERVE_COLLECTION_ENDPOINT: "<YOUR_OBSERVE_COLLECTION_ENDPOINT>"
YOUR_INGEST_TOKEN: "<YOUR_INGEST_TOKEN>"
Installation¶
Install the Observe Agent¶
Create
install_with_ps1.yaml
under/etc/ansible/roles/agent/tasks/
############################################################
# roles/agent/tasks/install_with_ps1.yaml (ZIP workflow)
############################################################
- name: Ensure staging directory exists
ansible.windows.win_file:
path: C:\Temp\Observe
state: directory
# 1. Download the latest Observe Agent ZIP
- name: Download latest Observe Agent ZIP
ansible.windows.win_get_url:
url: https://github.com/observeinc/observe-agent/releases/latest/download/observe-agent_Windows_x86_64.zip
dest: C:\Temp\Observe\observe-agent.zip
force: yes
# 2. Download install.ps1
- name: Download install.ps1
ansible.windows.win_get_url:
url: https://github.com/observeinc/observe-agent/releases/latest/download/install.ps1
dest: C:\Temp\Observe\install.ps1
force: yes
# 3. Run the script (enable TLS 1.2 first)
- name: Run install.ps1 with token, endpoint, and zip_dir
ansible.windows.win_shell: |
[Net.ServicePointManager]::SecurityProtocol = 'Tls, Tls11, Tls12, Ssl3'
C:\Temp\Observe\install.ps1 `
-observe_token "{{ YOUR_INGEST_TOKEN }}" `
-observe_collection_endpoint "{{ YOUR_OBSERVE_COLLECTION_ENDPOINT }}" `
-zip_dir "C:\Temp\Observe\observe-agent.zip"
args:
executable: powershell.exe
register: ps_install
# 4. Reboot only when the script returns 3010
- name: Reboot if install.ps1 returned 3010
ansible.windows.win_reboot:
when: ps_install.rc == 3010
# 5. Make sure the service is up (covers non-reboot cases)
- name: Ensure ObserveAgent service is running
ansible.windows.win_service:
name: ObserveAgent
start_mode: auto
state: started
Create
main.yaml
under/etc/ansible/roles/agent/tasks/
---
- import_tasks: install_with_ps1.yaml
Create
install-observe-agent-windows.yaml
---
# install-observe-agent-windows.yaml
#
# Launch from the control node:
#
# ansible-playbook install-observe-agent-windows.yaml \
# -i /etc/ansible/hosts/windows.aws_ec2.ini \
# --ask-vault-pass # only if token / password are vaulted
#
# What this playbook does
# ─────────────────────────────────────────────────────────
# • Targets every host in the [windows] group (defined in
# windows.aws_ec2.ini).
# • Loads variables from /etc/ansible/hosts/group_vars/windows.yaml
# – YOUR_OBSERVE_COLLECTION_ENDPOINT
# – YOUR_INGEST_TOKEN
# • Executes the “agent” role, whose sole task-file
# (install_with_ps1.yaml) does:
# 1. Download the latest install.ps1 from GitHub
# 2. Run the script with token & endpoint
# – If the agent is missing, it installs it.
# – If the agent is older, it upgrades in place.
# 3. Reboot only when the script returns exit-code 3010
#
# Idempotent: re-running the playbook simply ensures the
# agent is at the newest version and running.
- name: Install or upgrade Observe Agent on Windows fleet
hosts: windows
gather_facts: no # WinRM fact-gathering not required here
roles:
- agent # looks under /etc/ansible/roles/agent/
Use
ansible-playbook
to install the Observe Agent withinstall-observe-agent-windows.yaml
. A typical command looks like this:
$ ansible-playbook install-observe-agent-windows.yaml -i /etc/ansible/hosts/windows.aws_ec2.ini
PLAY [Install or upgrade Observe Agent on Windows fleet] **********************************************************************************************************************************************************
TASK [agent : Ensure staging directory exists] ********************************************************************************************************************************************************************
ok: [ansible-managed-node-2]
ok: [ansible-managed-node-1]
TASK [agent : Download latest Observe Agent ZIP] ******************************************************************************************************************************************************************
ok: [ansible-managed-node-2]
ok: [ansible-managed-node-1]
TASK [agent : Download install.ps1] *******************************************************************************************************************************************************************************
ok: [ansible-managed-node-2]
ok: [ansible-managed-node-1]
TASK [agent : Run install.ps1 with token, endpoint, and zip_dir] **************************************************************************************************************************************************
changed: [ansible-managed-node-2]
changed: [ansible-managed-node-1]
TASK [agent : Reboot if install.ps1 returned 3010] ****************************************************************************************************************************************************************
skipping: [ansible-managed-node-2]
skipping: [ansible-managed-node-1]
TASK [agent : Ensure ObserveAgent service is running] *************************************************************************************************************************************************************
changed: [ansible-managed-node-2]
changed: [ansible-managed-node-1]
PLAY RECAP ********************************************************************************************************************************************************************************************************
ansible-managed-node-1 : ok=5 changed=2 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
ansible-managed-node-2 : ok=5 changed=2 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
Configure the Observe Agent¶
The installation PowerShell script will automatically start the agent for you. You can find the
observe-agent.yaml
config file in the${Env:Programfiles}\Observe\observe-agent
directory. To push custom settings with Ansible, createobserve-agent.yaml.j2
under/etc/ansible/roles/agent/templates
. The following example will collect metrics about the processes running on the host system. Adjust the template as needed for your own logging, forwarding, or telemetry requirements. For more information on configuring the agent, see Configuration.
# Observe data token (ex: a1b2c3d4e5f6g7h8i9k0:l1m2n3o4p5q6r7s8t9u0v1w2x3y4z5a6)
token: "{{ YOUR_INGEST_TOKEN }}"
# Target Observe collection url (ex: https://123456789012.collect.observeinc.com/)
observe_url: "{{ YOUR_OBSERVE_COLLECTION_ENDPOINT }}"
health_check:
enabled: true
endpoint: localhost:13133
path: /status
internal_telemetry:
enabled: true
metrics:
enabled: true
host: localhost
port: 8888
level: detailed
logs:
enabled: true
level: ${env:OTEL_LOG_LEVEL}
# Debug mode - Sets agent log level to debug
debug: false
# collect metrics and logs pertaining to the agent itself
self_monitoring:
enabled: true
# collect metrics and logs about the host system
host_monitoring:
enabled: true
# collect logs of all running processes from the host system
logs:
enabled: true
metrics:
# collect metrics about the host system
host:
enabled: true
# collect metrics about the processes running on the host system
process:
enabled: true
# Enable forwarding of local app metrics and traces
forwarding:
enabled: true
metrics:
output_format: otel
# otel_config_overrides:
# exporters:
# debug:
# verbosity: detailed
# sampling_initial: 5
# sampling_thereafter: 200
# service:
# pipelines:
# metrics:
# receivers: [hostmetrics]
# processors: [memory_limiter]
# exporters: [debug]
Create
update_config.yaml
under/etc/ansible/roles/agent/tasks/
- name: Make sure config dir exists
ansible.windows.win_file:
path: "{{ lookup('env','SystemDrive') }}\\Program Files\\Observe\\observe-agent"
state: directory
- name: Render observe-agent.yaml
ansible.windows.win_template:
src: /etc/ansible/roles/agent/templates/observe-agent.yaml.j2
dest: "{{ lookup('env','SystemDrive') }}\\Program Files\\Observe\\observe-agent\\observe-agent.yaml"
force: yes
notify: restart observe agent
Create
update-observe-agent-windows.yaml
---
# update-observe-agent-windows.yaml
#
# Push the rendered observe-agent.yaml to every Windows host.
# The service restarts only when the file content changes.
#
# ansible-playbook update-observe-agent-windows.yaml \
# -i /etc/ansible/hosts/windows.aws_ec2.ini \
# --ask-vault-pass # only if secrets are vaulted
- name: Update Observe Agent configuration on Windows hosts
hosts: windows
gather_facts: no
tasks:
- name: Render config template and restart when needed
import_tasks: /etc/ansible/roles/agent/tasks/update_config.yaml
handlers:
- name: restart observe agent
ansible.windows.win_service:
name: ObserveAgent
state: restarted
Use
ansible-playbook
to apply your custom settings of the Observe Agent withupdate-observe-agent-windows.yaml
. A typical command looks like this:
$ ansible-playbook update-observe-agent-windows.yaml -i /etc/ansible/hosts/windows.aws_ec2.ini --flush-cache --diff
PLAY [Update Observe Agent configuration on Windows hosts] ********************************************************************************************************************************************************
TASK [Make sure config dir exists] ********************************************************************************************************************************************************************************
ok: [ansible-managed-node-2]
ok: [ansible-managed-node-1]
TASK [Render observe-agent.yaml] **********************************************************************************************************************************************************************************
changed: [ansible-managed-node-2]
changed: [ansible-managed-node-1]
RUNNING HANDLER [restart observe agent] ***************************************************************************************************************************************************************************
--- before
+++ after
@@ -18,6 +18,6 @@
"service_type": "win32_own_process",
"sid_info": "none",
"start_mode": "auto",
- "state": "started",
+ "state": "restarted",
"username": "NT AUTHORITY\\SYSTEM"
}
changed: [ansible-managed-node-2]
--- before
+++ after
@@ -18,6 +18,6 @@
"service_type": "win32_own_process",
"sid_info": "none",
"start_mode": "auto",
- "state": "started",
+ "state": "restarted",
"username": "NT AUTHORITY\\SYSTEM"
}
changed: [ansible-managed-node-1]
PLAY RECAP ********************************************************************************************************************************************************************************************************
ansible-managed-node-1 : ok=3 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
ansible-managed-node-2 : ok=3 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Configure application instrumentation¶
Once the Observe Agent is deployed, configure your application instrumentation or set the OTEL_EXPORTER_OTLP_ENDPOINT
environment variable to one of the following addresses to send application telemetry including traces to the Observe Agent.
Note
When setting up the endpoint to send traces, make sure you use the path that your OTLP library requires. Some libraries need traces to go to /v1/traces
, while others expect them at the root path /
.
OTLP/HTTP endpoint:
http://localhost:4318
OTLP/grpc endpoint:
http://localhost:4317
Learn more about how to instrument your app
Uninstall the Observe Agent¶
Create
uninstall-observe-agent-windows.yaml
---
# uninstall-observe-agent-windows.yaml
# Completely removes the Observe Agent from Windows hosts.
#
# ansible-playbook uninstall-observe-agent-windows.yaml \
# -i /etc/ansible/hosts/windows.aws_ec2.ini
- name: Uninstall Observe Agent completely
hosts: windows
gather_facts: no
tasks:
# 1 ── Stop & disable the service (ignore if it’s already gone)
- name: Stop ObserveAgent service
ansible.windows.win_service:
name: ObserveAgent
state: stopped
start_mode: disabled
ignore_errors: yes
# 2 ── Delete the service definition so it can’t restart
- name: Remove ObserveAgent service entry
ansible.windows.win_service:
name: ObserveAgent
state: absent
ignore_errors: yes
# 3 ── Kill any stray process that still has the binary open
- name: Kill leftover observe-agent.exe processes (if any)
ansible.windows.win_shell: |
$p = Get-Process observe-agent -ErrorAction SilentlyContinue
if ($p) { $p | Stop-Process -Force }
exit 0 # ← forces exit-code 0
args:
executable: powershell.exe
# 4 ── Force-remove Program Files\Observe on the remote host
- name: Remove C:\Program Files\Observe tree (force)
ansible.windows.win_shell: |
$pf = $env:ProgramFiles
$path = Join-Path $pf 'Observe'
if (Test-Path $path) {
Remove-Item -LiteralPath $path -Recurse -Force
}
args:
executable: powershell.exe
# 5 ── Optional: wipe configs / logs
# - name: Remove %ProgramData%\Observe
# ansible.windows.win_shell: |
# $pd = $env:ProgramData
# $path = Join-Path $pd 'Observe'
# if (Test-Path $path) {
# Remove-Item -LiteralPath $path -Recurse -Force
# }
# args:
# executable: powershell.exe
Use
ansible-playbook
to uninstall the Observe Agent withuninstall-observe-agent-windows.yaml
. A typical command looks like this:
$ ansible-playbook uninstall-observe-agent-windows.yaml -i /etc/ansible/hosts/windows.aws_ec2.ini
PLAY [Uninstall Observe Agent completely] *************************************************************************************************************************************************************************
TASK [Stop ObserveAgent service] **********************************************************************************************************************************************************************************
changed: [ansible-managed-node-2]
changed: [ansible-managed-node-1]
TASK [Remove ObserveAgent service entry] **************************************************************************************************************************************************************************
changed: [ansible-managed-node-2]
changed: [ansible-managed-node-1]
TASK [Kill leftover observe-agent.exe processes (if any)] *********************************************************************************************************************************************************
changed: [ansible-managed-node-2]
changed: [ansible-managed-node-1]
TASK [Remove C:\Program Files\Observe tree (force)] ***************************************************************************************************************************************************************
changed: [ansible-managed-node-2]
changed: [ansible-managed-node-1]
PLAY RECAP ********************************************************************************************************************************************************************************************************
ansible-managed-node-1 : ok=4 changed=4 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
ansible-managed-node-2 : ok=4 changed=4 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Upgrade the Observe Agent¶
Use ansible-playbook
to upgrade the Observe Agent with install-observe-agent-windows.yaml
. The script will stop the service before installing the new version of the agent and restarting the service.
$ ansible-playbook install-observe-agent-windows.yaml -i /etc/ansible/hosts/windows.aws_ec2.ini
Next steps¶
Use both the Log Explorer and the Metric Explorer to monitor your systems. To analyze your trace data, explore both the Trace Explorer and the Service Explorer
For additional installation patterns and advanced examples, see the Observe Windows Ansible Playbook