Ansible Deployment

Deploy OnePAM agents at scale using Ansible playbooks and roles.

OnePAM Ansible Module

Clone the official OnePAM Ansible module from GitHub. Includes tasks, templates, handlers, default variables, and example playbooks.


Clone from GitHub
git clone https://github.com/onepamcom/onepam-ansible.git
cd onepam-ansible

Requirements

Control Node
  • Ansible 2.9 or later
  • Python 3.8+
  • SSH access to managed hosts
Managed Nodes
  • Linux with systemd (Ubuntu 20.04+, Debian 11+, RHEL/CentOS 8+, Amazon Linux 2/2023)
  • Python 3 on managed hosts
  • Root or sudo access

For deprecated or non-systemd distributions, use the Gateway SSH Proxy instead — no agent installation required.

Quick Start

Run the OnePAM role against your inventory in a single command:

# Clone the module
git clone https://github.com/onepamcom/onepam-ansible.git
cd onepam-ansible

# Run the playbook
ansible-playbook -i inventory/hosts site.yml

Minimal playbook (site.yml):

---
- name: Deploy OnePAM agent
  hosts: all
  become: true
  roles:
    - role: agent
      vars:
        onepam_server_url: "https://onepam.com"
        onepam_tenant_id: "00000000-0000-0000-0000-000000000000"

Role Structure

roles/agent/
├── defaults/
│   └── main.yml              # Default variables
├── handlers/
│   └── main.yml              # Service handlers
├── meta/
│   └── main.yml              # Role metadata
├── tasks/
│   ├── main.yml              # Entrypoint (validate, route to install/uninstall)
│   ├── install.yml           # Download binary with SHA256 verification
│   ├── config.yml            # Generate agent ID, render agent.env
│   ├── service.yml           # Deploy systemd unit, enable and start
│   └── uninstall.yml         # Stop service, remove files
└── templates/
    ├── agent.env.j2          # Environment file
    └── onepam-agent.service.j2  # Systemd unit
defaults/main.yml
---
onepam_state: "present"

onepam_server_url: "https://onepam.com"
onepam_tenant_id: ""
onepam_group_uuid: ""
onepam_agent_version: "latest"
onepam_log_level: "info"
onepam_release_url: "https://updates.onepam.com"
onepam_install_dir: "/opt/onepam"
tasks/main.yml
---
# Validate requirements
- name: Validate systemd is present
  ansible.builtin.command: systemctl --version
  changed_when: false

- name: Validate tenant_id is a valid UUID
  ansible.builtin.assert:
    that:
      - onepam_tenant_id | length > 0
      - onepam_tenant_id is match('^[0-9a-f]{8}-...')
    fail_msg: "onepam_tenant_id must be a valid UUID"

- name: Validate log_level
  ansible.builtin.assert:
    that:
      - onepam_log_level in ['debug', 'info', 'warn', 'error']

- name: Validate group_uuid when provided
  ansible.builtin.assert:
    that:
      - onepam_group_uuid is match('^[0-9a-f]{8}-...')
    fail_msg: "onepam_group_uuid must be a valid UUID"
  when: onepam_group_uuid | length > 0

# Detect architecture
- name: Detect system architecture
  ansible.builtin.set_fact:
    onepam_arch: "{{ 'amd64' if ansible_architecture == 'x86_64' else 'arm64' }}"

# Create directories
- name: Create OnePAM directories
  ansible.builtin.file:
    path: "{{ item }}"
    state: directory
    owner: root
    group: root
    mode: "0755"
  loop:
    - "{{ onepam_install_dir }}"
    - "{{ onepam_install_dir }}/bin"
    - "{{ onepam_install_dir }}/data"
    - "{{ onepam_install_dir }}/etc"

# Download binary with SHA256 checksum verification
- name: Download OnePAM agent binary
  ansible.builtin.get_url:
    url: "{{ onepam_release_url }}/agent/{{ onepam_agent_version }}/onepam-agent-linux-{{ onepam_arch }}"
    checksum: "sha256:{{ onepam_release_url }}/agent/{{ onepam_agent_version }}/onepam-agent-linux-{{ onepam_arch }}.sha256"
    dest: "{{ onepam_install_dir }}/bin/onepam-agent"
    owner: root
    group: root
    mode: "0755"
  notify: Restart onepam-agent

# Manage agent ID
- name: Check for existing agent ID
  ansible.builtin.stat:
    path: "{{ onepam_install_dir }}/etc/agent-id"
  register: agent_id_file

- name: Read existing agent ID
  ansible.builtin.slurp:
    src: "{{ onepam_install_dir }}/etc/agent-id"
  register: existing_agent_id
  when: agent_id_file.stat.exists

- name: Generate new agent ID
  ansible.builtin.set_fact:
    onepam_agent_id: "{{ lookup('file', '/proc/sys/kernel/random/uuid') }}"
  when: not agent_id_file.stat.exists

- name: Use existing agent ID
  ansible.builtin.set_fact:
    onepam_agent_id: "{{ existing_agent_id.content | b64decode | trim }}"
  when: agent_id_file.stat.exists

- name: Save agent ID
  ansible.builtin.copy:
    content: "{{ onepam_agent_id }}"
    dest: "{{ onepam_install_dir }}/etc/agent-id"
    owner: root
    group: root
    mode: "0644"

# Deploy configuration and service
- name: Deploy agent configuration
  ansible.builtin.template:
    src: agent.env.j2
    dest: "{{ onepam_install_dir }}/etc/agent.env"
    owner: root
    group: root
    mode: "0600"
  notify: Restart onepam-agent

- name: Deploy systemd service unit
  ansible.builtin.template:
    src: onepam-agent.service.j2
    dest: /etc/systemd/system/onepam-agent.service
    owner: root
    group: root
    mode: "0644"
  notify:
    - Reload systemd
    - Restart onepam-agent

- name: Enable and start OnePAM agent
  ansible.builtin.systemd:
    name: onepam-agent
    enabled: true
    state: started
    daemon_reload: true
handlers/main.yml
---
- name: Reload systemd
  ansible.builtin.systemd:
    daemon_reload: true

- name: Restart onepam-agent
  ansible.builtin.systemd:
    name: onepam-agent
    state: restarted
templates/agent.env.j2
# OnePAM Agent Configuration
# Managed by Ansible — do not edit manually

AGENT_API_URL="{{ onepam_server_url }}"
AGENT_TENANT_ID="{{ onepam_tenant_id }}"
AGENT_ID="{{ onepam_agent_id }}"
AGENT_LOG_LEVEL="{{ onepam_log_level }}"
{{% if onepam_group_uuid | length > 0 %}}
AGENT_GROUP_UUID="{{ onepam_group_uuid }}"
{{% endif %}}
templates/onepam-agent.service.j2
[Unit]
Description=OnePAM Agent
Documentation=https://onepam.com/docs
After=network-online.target
Wants=network-online.target
StartLimitIntervalSec=0

[Service]
Type=notify
User=root
Group=root
EnvironmentFile=-{{ onepam_install_dir }}/etc/agent.env
ExecStart={{ onepam_install_dir }}/bin/onepam-agent \
    --server=${AGENT_API_URL} \
    --tenant-id=${AGENT_TENANT_ID} \
    --agent-id=${AGENT_ID} \
    --data-dir={{ onepam_install_dir }}/data \
    --log-level=${AGENT_LOG_LEVEL}
Restart=always
RestartSec=10
TimeoutStartSec=60
TimeoutStopSec=360
WatchdogSec=120
LimitNOFILE=65536
LimitMEMLOCK=infinity
StandardOutput=journal
StandardError=journal
SyslogIdentifier=onepam-agent

[Install]
WantedBy=multi-user.target

Variables Reference

Variable Default Description
onepam_server_url https://onepam.com OnePAM server URL to connect to
onepam_tenant_id "" (required) Organisation UUID (tenant ID)
onepam_group_uuid "" Optional group UUID to assign the agent to
onepam_agent_version latest Agent version to install
onepam_log_level info Logging verbosity (debug, info, warn, error)
onepam_release_url https://updates.onepam.com Base URL for agent binary downloads
onepam_install_dir /opt/onepam Base installation directory

Inventory Setup

Organise hosts into groups with group-specific variables:

inventory/hosts
[webservers]
web01.example.com
web02.example.com

[databases]
db01.example.com
db02.example.com

[all:vars]
ansible_user=deploy
ansible_become=true
inventory/group_vars/all.yml
---
onepam_server_url: "https://onepam.example.com"
onepam_tenant_id: "00000000-0000-0000-0000-000000000000"
inventory/group_vars/databases.yml
---
onepam_log_level: "debug"

Playbook Examples

---
- name: Deploy OnePAM agent to all hosts
  hosts: all
  become: true
  roles:
    - role: agent
      vars:
        onepam_server_url: "https://onepam.example.com"
        onepam_tenant_id: "00000000-0000-0000-0000-000000000000"

---
- name: Deploy OnePAM to production
  hosts: production
  become: true
  roles:
    - role: agent
      vars:
        onepam_server_url: "https://prod.onepam.example.com"
        onepam_tenant_id: "{{ vault_prod_tenant_id }}"
        onepam_log_level: "warn"

- name: Deploy OnePAM to staging
  hosts: staging
  become: true
  roles:
    - role: agent
      vars:
        onepam_server_url: "https://staging.onepam.example.com"
        onepam_tenant_id: "{{ vault_staging_tenant_id }}"
        onepam_log_level: "debug"

Encrypt sensitive values with Ansible Vault:

# Create encrypted vars file
ansible-vault create inventory/group_vars/all/vault.yml

# Contents of vault.yml
vault_onepam_tenant_id: "your-real-tenant-id"
# Reference in playbook
- name: Deploy OnePAM agent
  hosts: all
  become: true
  roles:
    - role: agent
      vars:
        onepam_tenant_id: "{{ vault_onepam_tenant_id }}"

# Run with vault password
# ansible-playbook -i inventory/hosts site.yml --ask-vault-pass

---
- name: Rolling update of OnePAM agent
  hosts: all
  become: true
  serial: "25%"
  max_fail_percentage: 10
  pre_tasks:
    - name: Verify connectivity
      ansible.builtin.ping:
  roles:
    - role: agent
  post_tasks:
    - name: Verify agent is running
      ansible.builtin.systemd:
        name: onepam-agent
        state: started
      register: agent_status
    - name: Fail if agent not running
      ansible.builtin.assert:
        that: agent_status.status.ActiveState == "active"
        fail_msg: "OnePAM agent failed to start"
Security Note: Always use Ansible Vault to encrypt sensitive values like onepam_tenant_id. Never commit unencrypted secrets to version control.