Deploy Device Protection with Ansible
Use Ansible to install Device Protection across your Linux fleet. The role below picks the right package for each host, installs it with your user group token, and leaves the service enabled.
Read Deploying on Linux first for the token, the package list, and the reboot behaviour that applies to every method.
Role layout
roles/aikido_device_protection/
├── defaults/main.yml
├── handlers/main.yml
└── tasks/main.yml
group_vars/
└── developer_workstations.yml
site.ymlSet up the role
Add the defaults
---
aikido_release_url: https://github.com/AikidoSec/safechain-internals/releases/latest/download
# Reboot after installing. See "Handle the reboot" below.
aikido_reboot: falseAdd the tasks
The first task decides whether there is anything to do, so repeat runs are cheap and never touch the token.
---
- name: Check whether Device Protection is already installed
ansible.builtin.command: aikido-doctor --simple
register: aikido_installed
changed_when: false
failed_when: false
- name: Install Device Protection
when: aikido_installed.rc != 0
block:
- name: Work out the package architecture
ansible.builtin.set_fact:
aikido_arch: "{{ 'arm64' if ansible_facts['architecture'] == 'aarch64' else 'amd64' }}"
- name: Work out the package name
ansible.builtin.set_fact:
aikido_package: >-
{{
'EndpointProtection-' ~ aikido_arch ~ '.deb'
if ansible_facts['os_family'] == 'Debian'
else 'EndpointProtection-' ~ aikido_arch ~ '.el'
~ ansible_facts['distribution_major_version'] ~ '.rpm'
}}
- name: Download the package
ansible.builtin.get_url:
url: "{{ aikido_release_url }}/{{ aikido_package }}"
dest: "/tmp/{{ aikido_package }}"
mode: "0600"
- name: Install the package on Debian and Ubuntu
ansible.builtin.apt:
deb: "/tmp/{{ aikido_package }}"
environment:
AIKIDO_TOKEN: "{{ aikido_token }}"
no_log: true
when: ansible_facts['os_family'] == 'Debian'
notify: Reboot to activate Device Protection
- name: Install the package on RHEL, Rocky Linux and CentOS
ansible.builtin.dnf:
name: "/tmp/{{ aikido_package }}"
state: present
environment:
AIKIDO_TOKEN: "{{ aikido_token }}"
no_log: true
when: ansible_facts['os_family'] == 'RedHat'
notify: Reboot to activate Device Protection
- name: Remove the downloaded package
ansible.builtin.file:
path: "/tmp/{{ aikido_package }}"
state: absent
- name: Make sure the service is enabled and running
ansible.builtin.systemd_service:
name: aikido-endpoint-protection
state: started
enabled: trueThe role needs facts, so leave gather_facts on. distribution_major_version is what selects the el9 or el10 build.
Store the token in Ansible Vault
Encrypt the token for the inventory group that maps to your Aikido user group:
ansible-vault encrypt_string --name aikido_token '<your-token>'Paste the output into the group's variables:
---
aikido_token: !vault |
$ANSIBLE_VAULT;1.1;AES256
62313365396662343061393464336163383764373764613633653634306231386433626436623361
...Repeat per group if you use more than one user group. Each group gets its own token and its own group_vars file.
Write the playbook and run it
---
- name: Deploy Aikido Device Protection
hosts: developer_workstations
become: true
serial: 20%
roles:
- aikido_device_protectionStart with a few machines, then widen:
ansible-playbook site.yml --ask-vault-pass --limit pilot
ansible-playbook site.yml --ask-vault-passHow the token reaches the package
The package reads AIKIDO_TOKEN while it installs. The task-level environment keyword is what puts it there: Ansible sets those variables around the module invocation on the host, so the dpkg or dnf process the module starts inherits them. This works with become: true, because the variables are set inside the privilege escalation wrapper.
Setting AIKIDO_TOKEN in your own shell before running ansible-playbook does nothing. Ansible does not forward the controller's environment to the host.
no_log: true hides the token, and it hides everything else the task prints. If an install fails and you need the error, set no_log: false on that task temporarily and run it against one test host.
Handle the reboot
Installing sets the Aikido CA environment variables system-wide, and running shells only pick them up after a new login shell or a reboot. The role ships with a handler that stays off by default:
Set aikido_reboot: true for hosts nobody is working on. On developer machines, leave it off and ask people to log out and back in, or reboot in a maintenance window.
Verify the rollout
The devices then appear in your device list with an Active status.
Troubleshooting
The package installs but the device never appears in the dashboard
AIKIDO_TOKEN was not set for the install command. Configuration management tools do not forward your local environment to the host, so set the variable on the task itself, then install the package again
apt or dnf looks for the package in your repositories instead of installing the file
Pass a path, not a name: apt install ./EndpointProtection-amd64.deb. The leading ./ is what makes the package manager treat it as a local file
The install fails on a Red Hat-family host
Match the build to the major version: use the el9 package on version 9 and the el10 package on version 10
The service is not running
Run systemctl status aikido-endpoint-protection, then sudo aikido-doctor diagnostics to send us the details
Node.js or uv still reject the Aikido certificate
Installing sets NODE_EXTRA_CA_CERTS and UV_SYSTEM_CERTS system-wide, and running shells do not pick them up. Open a new login shell or reboot the device
The token shows up in run output or logs
Use your tool's redaction: no_log in Ansible, sensitive true in Chef, Sensitive() in Puppet
Several machines share one entry in the device list
They booted with the same /etc/machine-id. Device identity on Linux follows that file, so clear it in the image you clone from and let systemd write a fresh one on first boot
No tray icon appears
Expected on GNOME outside Ubuntu, and cosmetic. See Tray Icon Support on Linux
Last updated
Was this helpful?