Iris Role Usage Guide
Tags
Unlike most other roles in this repo, tasks/main.yml does not fail fast when run without --tags or with --tags all — every task file below executes in sequence, including the InstaServer install itself.
define_variables carries the special always tag, so it runs regardless of which other tags are selected — later steps (extract, tuned, install_iris, fix_cpf_ports, ha_scripts) all depend on the fact it sets (iris_extracted_install_files_path).
prerequisites is also always-tagged and runs first: it probes the instance metadata endpoint to set iris_is_aws/iris_is_azure, which the tuned and cloud_cli steps branch on. Being always, it runs even under a scoped --tags tuned or --tags cloud_cli, so those facts are set before their consumers regardless of which tags you select.
iris is the shared tag across the core install pipeline (filesystem, download, extract, tuned, install_iris, fix_cpf_ports, ha_scripts). Running --tags iris executes that whole pipeline, but skips the host-prep steps (selinux, users/groups, sudoers, hosts, keys, sshd, known_hosts).
| Tag(s) | Task file | Description |
|---|---|---|
always |
prerequisites.yml |
Detects the cloud platform (iris_is_aws/iris_is_azure) from the instance metadata endpoint. Runs first, always — see the note above. |
selinux |
configure_selinux.yml |
Sets SELinux policy/state on RHEL hosts. Transitions to/from disabled only fully apply at next boot. |
dependencies, packages |
install_dependencies.yml |
Installs iris_dependencies via dnf. |
cloud_cli |
cloud_cli/main.yml |
Installs the cloud provider CLI matching the detected platform — AWS CLI v2 (official installer) on AWS, Azure CLI (Microsoft repo) on Azure. Gated on iris_install_cloud_cli (default true); skip with --skip-tags cloud_cli. Validated on RHEL; the Ubuntu path is present but not yet tested. |
users, groups |
provision_users_and_groups.yml |
Creates iris_groups/iris_users, optionally sets the root password, and enforces Epic's required umask 0022 for epicuser group members. |
sudoers, sudo |
configure_sudoers.yml |
Templates (or removes) /etc/sudoers.d drop-ins per iris_sudoers, validated with visudo -cf. |
hosts |
configure_hosts_file.yml |
Adds an /etc/hosts entry for every host in the play, self and others. |
keys |
ssh_keys.yml |
Generates SSH keypairs for users with generate_keys set, then distributes the public keys to other hosts via distribute_ssh_keys.yml. |
sshd |
configure_sshd.yml |
Templates sshd_config, validated with sshd -t, and restarts sshd on change. |
known_hosts |
populate_known_hosts.yml |
ssh-keyscans every other host in the play and populates /etc/ssh/ssh_known_hosts. |
filesystem, directories, permissions, iris |
prepare_filesystem.yml |
Creates iris_directories and mounts /tmp as a dedicated tmpfs (Epic OS Setup Guide §3.M). |
download, iris |
download_install_files.yml |
Downloads or copies the IRIS install, InstaServer, and license key files to iris_install_files_path. |
define_variables, always |
define_variables.yml |
Computes iris_extracted_install_files_path. Always runs — see note above. |
extract, iris |
extract_install_files.yml |
Extracts the InstaServer .sh package, if not already extracted. |
tuned, hugepages, iris |
install_and_configure_tuned.yml |
Installs the epic-config RPM, configures the tuned profile/hugepages/cloud-specific kernel settings, and reboots if tuned-adm verify fails. |
iris, install_iris |
install_iris.yml |
Builds the InstaServer answer file, runs --validate, then installs any instance in iris_instaserver_variables.Instances not already present. |
iris, fix_cpf_ports |
fix_cpf_ports.yml |
Patches iris.cpf's DefaultPort to match the answer file's SuperServerPort — a workaround for an Epic InstaServer bug, see roles/iris/CLAUDE.md. |
ha_scripts, iris |
install_ha_scripts.yml |
Copies start_epic_all.ksh/stop_epic_all.ksh to /epic/bin, if present in the extracted install. |
certmgr |
configure_certmgr_ca.yml |
Initializes the Epic ESMP certificate authority (certmgr --initialize_ca) and creates the local ESMP certificates (certmgr --auto_config_local). Opt-in — see certmgr certificate authority below. |
Required collections and roles
These must be available on the control node before the role runs:
| Type | Name | Used for |
|---|---|---|
| Collection | ansible.utils |
Filter/utility plugins used by the deployment stack |
| Collection | community.crypto |
The keys step generates user SSH keypairs with community.crypto.openssh_keypair |
| Role | linux-system-roles.storage |
Provisions the Epic storage layout (LVM, filesystems, mounts) before this role runs — iris only creates its directory tree on whatever mounts exist. See the Storage usage guide. |
Usage
-
Configure the path the the shared files directory in
group_vars/all/vars.yml: -
Copy the following files to the shared files directory defined in step 1. Skip this step if the files will be downloaded from a web server.
- Iris license key file
- Iris install
- Instaserver
-
Create a file in
host_varsfor each host Iris will be installed on. The file should be named after the host's inventory name (e.g.host_vars/iris1.yml). See Variables for theiris_instaserver_variablesshape it must contain. -
Run the deploy playbook:
Running specific tags
Re-run with --tags to target just the steps you need — see the Tags table above for what each one does:
ansible-playbook --limit=<host> playbooks/deploy-iris.yml --become -e @extra_vars/users.yml --tags filesystem
-e @extra_vars/users.yml is only needed for tags that touch iris_users/iris_groups/iris_sudoers (users, groups, sudoers, keys) — harmless to include on every run otherwise.
certmgr certificate authority
configure_certmgr_ca.yml is the only task file in this role that does not run by default, and the only one whose behavior depends on which host it lands on. Epic's model requires exactly one primary certificate authority, so the role is driven by two settings with deliberately separate jobs:
# group_vars/all/vars.yml
iris_certmgr_initialize_ca: true # on/off for the whole feature
iris_certmgr_ca_host: TSTODB.sapphire.dev # ...and this host is the CA
iris_certmgr_initialize_ca defaults to false, so the step is opt-in. iris_certmgr_ca_host selects the CA. Keep both in group_vars rather than the CA host's host_vars — non-CA hosts need to see the designation in order to report that they are skipping and why.
Only the designated host is ever initialized as a CA. Every host in the play compares its own inventory_hostname against iris_certmgr_ca_host; the one that matches does the work, and every other host prints a skip notice and moves on. This holds regardless of --limit:
| Command | Result |
|---|---|
--limit=TSTODB.sapphire.dev |
TSTODB initializes the CA |
--limit=TSTODB.sapphire.dev:PRDODB.sapphire.dev |
TSTODB initializes the CA; PRDODB reports it is not the CA |
--limit=PRDODB.sapphire.dev |
Nobody initializes a CA |
You can't end up with two CAs because iris_certmgr_ca_host holds a single name — there's nowhere to put a second one. That's a stronger guarantee than a check the role performs at run time, since there's nothing to bypass. Either the full name or the short one works, in any capitalization: TSTODB.sapphire.dev and tstodb both match. Both are accepted because a name that matched nothing would make the run quietly do nothing at all, which is easy to miss.
The step is also deliberately left off the shared iris tag, so --tags iris never attempts CA initialization. To run just this step:
The task file requires RedAlert to already be installed (it invokes /epic/redalert/bin/certmgr), which is why it runs last in tasks/main.yml. On the designated CA it:
- Creates
{{ iris_certmgr_ca_location }}(/epic/pki/ca) owned byepicadm:epicsys. This directory is CA-server-only, so it is not part of the universaliris_directorieslist. - Reads
certmgr --showto decide whether the host is already a CA. - Runs
certmgr --initialize_cawith theiris_certmgr_*organization metadata if it is not. - Runs
certmgr --auto_config_localwhen the host is a CA (either already, or as of step 3) and{{ iris_certmgr_esmp_cert_path }}is missing. - Asserts the end state — that
certmgr --shownow reports a certificate authority and the local ESMP certificate exists.
Re-running is safe and never creates a second CA: step 2 finds the CA that already exists, so step 3 is skipped.
The two read-only certmgr --show calls are marked check_mode: false so that a --check run still reads real state instead of failing on an empty result. Under --check the two commands that would change something are skipped (Ansible's command module can't simulate them), and the final check is skipped along with them.
If iris_certmgr_initialize_ca is true but iris_certmgr_ca_host is empty, the run fails with an explicit error rather than silently doing nothing on every host.
certmgr --auto_config_local hangs unless given empty input
Step 4 runs a second certmgr command underneath itself, and that one waits for typed input that never arrives — so the playbook hangs forever rather than failing. The task passes stdin: "" to get past it, which makes certmgr use its defaults and finish. There is no --yes option for this command. Don't remove that setting.
Why every epicadm command sits behind the CA check
All the certmgr commands switch to the epicadm user, and they all sit inside the "am I the CA?" block. That's deliberate: a server that isn't the CA may have no IRIS installed at all — no epicadm user, no certmgr program — and switching users fails outright there. Only plain debug and assert tasks run outside that block. Keep it that way when adding to this file.
See Variables for the full variable list. Broader ESMP setup — remote hosts, alternate CA, ESMP passwords, mirroring certificates — is not yet automated; roles/iris/gap_analysis/esmp-certmgr-gap-analysis.md tracks what remains.