# Ansible best practices : copy vs. template

**URL:** <https://forums.rockylinux.org/t/ansible-best-practices-copy-vs-template/10187>\
**Category:** Rocky Linux Help & Support\
**Created:** [June 6, 2023, 7:43am UTC](https://forums.rockylinux.org/t/ansible-best-practices-copy-vs-template/10187 "2023-06-06T07:43:04Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![microlinux](https://sea2.discourse-cdn.com/flex020/user_avatar/forums.rockylinux.org/microlinux/32/1244_2.png) [@microlinux](https://forums.rockylinux.org/u/microlinux)\
**Post date:** [June 6, 2023, 7:43am UTC](https://forums.rockylinux.org/t/ansible-best-practices-copy-vs-template/10187/1 "2023-06-06T07:43:04Z")

</div>

Hi,

When I configure a service with Ansible, I usually use the `ansible.builtin.template` module for configuration file templates, since they allow variables. Here’s an example stub of a `main.cf.j2` template file for Postfix:

```auto
# /etc/postfix/main.cf
#
# Minimal Postfix configuration for LAN servers

# Disable backwards compatibility
compatibility_level = 2

# Disable IPv6
inet_protocols = ipv4

# Outbound mail only
inet_interfaces = localhost
mailbox_size_limit = 0

# Host
myhostname = {{ansible_hostname}}.{{ansible_dns.search.0}}

# Domain
mydomain = {{ansible_dns.search.0}}

# Authorize local machine only
mynetworks = 127.0.0.0/8

```

On the other hand, some services have “static” configuration files, meaning I don’t use any variables to install them. Here’s an example `chrony.conf`:

```auto
# /etc/chrony.conf
server 0.fr.pool.ntp.org iburst
server 1.fr.pool.ntp.org iburst
server 2.fr.pool.ntp.org iburst
server 3.fr.pool.ntp.org iburst
driftfile /var/lib/chrony/drift
makestep 1.0 3
rtcsync
logdir /var/log/chrony

```

Since there are no variables in this file, I just put this file in the `roles/ntp_client/files` directory and use the `ansible.builtin.copy` module to install it.

Now I wonder if this is an orthodox way to do things, or if it’s considered good practice to still use the `template` module and put this configuration file in `templates` even if there are no variables in it.

Being picky here, I know.

---

<div class="post-metadata">

**Author:** ![iwalker](https://sea2.discourse-cdn.com/flex020/user_avatar/forums.rockylinux.org/iwalker/32/2599_2.png) [@iwalker](https://forums.rockylinux.org/u/iwalker)\
**Post date:** [June 6, 2023, 8:43am UTC](https://forums.rockylinux.org/t/ansible-best-practices-copy-vs-template/10187/2 "2023-06-06T08:43:26Z")

</div>

You can use this role: [Ansible Galaxy](https://galaxy.ansible.com/linux-system-roles/timesync)

That way no need to use a config file or template. The readme there gives some examples, eg:

```auto
- name: Manage timesync with 3 servers
  hosts: targets
  vars:
    timesync_ntp_servers:
      - hostname: foo.example.com
        iburst: true
      - hostname: bar.example.com
        iburst: true
      - hostname: baz.example.com
        iburst: true
  roles:
    - linux-system-roles.timesync

```

with custom bits:

```auto
    timesync_chrony_custom_settings:
      - "logdir /var/log/chrony"

```

This can also be installed using:

```auto
dnf install rhel-system-roles

```

without having to install from Ansible Galaxy.

```auto
[root@rocky8 ~]# dnf repoquery -l rhel-system-roles | grep -i timesync
Last metadata expiration check: 2:20:05 ago on Tue 06 Jun 2023 08:26:11 AM CEST.
/usr/share/ansible/collections/ansible_collections/redhat/rhel_system_roles/COPYING-timesync
/usr/share/ansible/collections/ansible_collections/redhat/rhel_system_roles/docs/CHANGELOG_timesync.md
/usr/share/ansible/collections/ansible_collections/redhat/rhel_system_roles/docs/README_timesync.md
/usr/share/ansible/collections/ansible_collections/redhat/rhel_system_roles/docs/timesync
/usr/share/ansible/collections/ansible_collections/redhat/rhel_system_roles/docs/timesync/multiple-ntp-servers.yml
/usr/share/ansible/collections/ansible_collections/redhat/rhel_system_roles/docs/timesync/single-pool.yml
/usr/share/ansible/collections/ansible_collections/redhat/rhel_system_roles/plugins/modules/timesync_provider.sh
/usr/share/ansible/collections/ansible_collections/redhat/rhel_system_roles/roles/timesync
/usr/share/ansible/collections/ansible_collections/redhat/rhel_system_roles/roles/timesync/.ansible-lint
/usr/share/ansible/collections/ansible_collections/redhat/rhel_system_roles/roles/timesync/CHANGELOG.md
/usr/share/ansible/collections/ansible_collections/redhat/rhel_system_roles/roles/timesync/README.md
/usr/share/ansible/collections/ansible_collections/redhat/rhel_system_roles/roles/timesync/defaults
/usr/share/ansible/collections/ansible_collections/redhat/rhel_system_roles/roles/timesync/defaults/main.yml
/usr/share/ansible/collections/ansible_collections/redhat/rhel_system_roles/roles/timesync/handlers
/usr/share/ansible/collections/ansible_collections/redhat/rhel_system_roles/roles/timesync/handlers/main.yml
/usr/share/ansible/collections/ansible_collections/redhat/rhel_system_roles/roles/timesync/meta
/usr/share/ansible/collections/ansible_collections/redhat/rhel_system_roles/roles/timesync/meta/main.yml
/usr/share/ansible/collections/ansible_collections/redhat/rhel_system_roles/roles/timesync/tasks
/usr/share/ansible/collections/ansible_collections/redhat/rhel_system_roles/roles/timesync/tasks/main.yml
/usr/share/ansible/collections/ansible_collections/redhat/rhel_system_roles/roles/timesync/tasks/set_vars.yml
/usr/share/ansible/collections/ansible_collections/redhat/rhel_system_roles/roles/timesync/templates
/usr/share/ansible/collections/ansible_collections/redhat/rhel_system_roles/roles/timesync/templates/chrony.conf.j2
/usr/share/ansible/collections/ansible_collections/redhat/rhel_system_roles/roles/timesync/templates/chronyd.sysconfig.j2
/usr/share/ansible/collections/ansible_collections/redhat/rhel_system_roles/roles/timesync/templates/ntp.conf.j2
/usr/share/ansible/collections/ansible_collections/redhat/rhel_system_roles/roles/timesync/templates/ntpd.sysconfig.j2
/usr/share/ansible/collections/ansible_collections/redhat/rhel_system_roles/roles/timesync/templates/phc2sys.sysconfig.j2
/usr/share/ansible/collections/ansible_collections/redhat/rhel_system_roles/roles/timesync/templates/ptp4l.conf.j2
/usr/share/ansible/collections/ansible_collections/redhat/rhel_system_roles/roles/timesync/templates/ptp4l.sysconfig.j2
/usr/share/ansible/collections/ansible_collections/redhat/rhel_system_roles/roles/timesync/templates/timemaster.conf.j2
/usr/share/ansible/collections/ansible_collections/redhat/rhel_system_roles/roles/timesync/vars
/usr/share/ansible/collections/ansible_collections/redhat/rhel_system_roles/roles/timesync/vars/CentOS_6.yml
/usr/share/ansible/collections/ansible_collections/redhat/rhel_system_roles/roles/timesync/vars/CentOS_9.yml
/usr/share/ansible/collections/ansible_collections/redhat/rhel_system_roles/roles/timesync/vars/Debian.yml
/usr/share/ansible/collections/ansible_collections/redhat/rhel_system_roles/roles/timesync/vars/OracleLinux_6.yml
/usr/share/ansible/collections/ansible_collections/redhat/rhel_system_roles/roles/timesync/vars/OracleLinux_7.yml
/usr/share/ansible/collections/ansible_collections/redhat/rhel_system_roles/roles/timesync/vars/OracleLinux_8.yml
/usr/share/ansible/collections/ansible_collections/redhat/rhel_system_roles/roles/timesync/vars/OracleLinux_9.yml
/usr/share/ansible/collections/ansible_collections/redhat/rhel_system_roles/roles/timesync/vars/RedHat_6.yml
/usr/share/ansible/collections/ansible_collections/redhat/rhel_system_roles/roles/timesync/vars/RedHat_9.yml
/usr/share/ansible/collections/ansible_collections/redhat/rhel_system_roles/roles/timesync/vars/default.yml
/usr/share/ansible/collections/ansible_collections/redhat/rhel_system_roles/roles/timesync/vars/main.yml
/usr/share/ansible/collections/ansible_collections/redhat/rhel_system_roles/tests/timesync
/usr/share/ansible/collections/ansible_collections/redhat/rhel_system_roles/tests/timesync/.fmf
/usr/share/ansible/collections/ansible_collections/redhat/rhel_system_roles/tests/timesync/.fmf/version
/usr/share/ansible/collections/ansible_collections/redhat/rhel_system_roles/tests/timesync/inventory.yaml.j2
/usr/share/ansible/collections/ansible_collections/redhat/rhel_system_roles/tests/timesync/provision.fmf
/usr/share/ansible/collections/ansible_collections/redhat/rhel_system_roles/tests/timesync/setup-snapshot.yml
/usr/share/ansible/collections/ansible_collections/redhat/rhel_system_roles/tests/timesync/tests_chrony.yml
/usr/share/ansible/collections/ansible_collections/redhat/rhel_system_roles/tests/timesync/tests_default.yml
/usr/share/ansible/collections/ansible_collections/redhat/rhel_system_roles/tests/timesync/tests_default_vars.yml
/usr/share/ansible/collections/ansible_collections/redhat/rhel_system_roles/tests/timesync/tests_default_wrapper.yml
/usr/share/ansible/collections/ansible_collections/redhat/rhel_system_roles/tests/timesync/tests_ntp.yml
/usr/share/ansible/collections/ansible_collections/redhat/rhel_system_roles/tests/timesync/tests_ntp_provider1.yml
/usr/share/ansible/collections/ansible_collections/redhat/rhel_system_roles/tests/timesync/tests_ntp_provider2.yml
/usr/share/ansible/collections/ansible_collections/redhat/rhel_system_roles/tests/timesync/tests_ntp_provider3.yml
/usr/share/ansible/collections/ansible_collections/redhat/rhel_system_roles/tests/timesync/tests_ntp_provider4.yml
/usr/share/ansible/collections/ansible_collections/redhat/rhel_system_roles/tests/timesync/tests_ntp_provider5.yml
/usr/share/ansible/collections/ansible_collections/redhat/rhel_system_roles/tests/timesync/tests_ntp_provider6.yml
/usr/share/ansible/collections/ansible_collections/redhat/rhel_system_roles/tests/timesync/tests_ntp_ptp.yml
/usr/share/ansible/collections/ansible_collections/redhat/rhel_system_roles/tests/timesync/tests_ptp_multi.yml
/usr/share/ansible/collections/ansible_collections/redhat/rhel_system_roles/tests/timesync/tests_ptp_single.yml
/usr/share/ansible/roles/linux-system-roles.timesync
/usr/share/ansible/roles/rhel-system-roles.timesync
/usr/share/ansible/roles/rhel-system-roles.timesync/CHANGELOG.md
/usr/share/ansible/roles/rhel-system-roles.timesync/COPYING
/usr/share/ansible/roles/rhel-system-roles.timesync/README.html
/usr/share/ansible/roles/rhel-system-roles.timesync/README.md
/usr/share/ansible/roles/rhel-system-roles.timesync/ansible_pytest_extra_requirements.txt
/usr/share/ansible/roles/rhel-system-roles.timesync/custom_requirements.txt
/usr/share/ansible/roles/rhel-system-roles.timesync/defaults
/usr/share/ansible/roles/rhel-system-roles.timesync/defaults/main.yml
/usr/share/ansible/roles/rhel-system-roles.timesync/handlers
/usr/share/ansible/roles/rhel-system-roles.timesync/handlers/main.yml
/usr/share/ansible/roles/rhel-system-roles.timesync/library
/usr/share/ansible/roles/rhel-system-roles.timesync/library/timesync_provider.sh
/usr/share/ansible/roles/rhel-system-roles.timesync/meta
/usr/share/ansible/roles/rhel-system-roles.timesync/meta/main.yml
/usr/share/ansible/roles/rhel-system-roles.timesync/molecule_extra_requirements.txt
/usr/share/ansible/roles/rhel-system-roles.timesync/pylint_extra_requirements.txt
/usr/share/ansible/roles/rhel-system-roles.timesync/pylintrc
/usr/share/ansible/roles/rhel-system-roles.timesync/pytest_extra_requirements.txt
/usr/share/ansible/roles/rhel-system-roles.timesync/tasks
/usr/share/ansible/roles/rhel-system-roles.timesync/tasks/main.yml
/usr/share/ansible/roles/rhel-system-roles.timesync/tasks/set_vars.yml
/usr/share/ansible/roles/rhel-system-roles.timesync/templates
/usr/share/ansible/roles/rhel-system-roles.timesync/templates/chrony.conf.j2
/usr/share/ansible/roles/rhel-system-roles.timesync/templates/chronyd.sysconfig.j2
/usr/share/ansible/roles/rhel-system-roles.timesync/templates/ntp.conf.j2
/usr/share/ansible/roles/rhel-system-roles.timesync/templates/ntpd.sysconfig.j2
/usr/share/ansible/roles/rhel-system-roles.timesync/templates/phc2sys.sysconfig.j2
/usr/share/ansible/roles/rhel-system-roles.timesync/templates/ptp4l.conf.j2
/usr/share/ansible/roles/rhel-system-roles.timesync/templates/ptp4l.sysconfig.j2
/usr/share/ansible/roles/rhel-system-roles.timesync/templates/timemaster.conf.j2
/usr/share/ansible/roles/rhel-system-roles.timesync/tests
/usr/share/ansible/roles/rhel-system-roles.timesync/tests/.fmf
/usr/share/ansible/roles/rhel-system-roles.timesync/tests/.fmf/version
/usr/share/ansible/roles/rhel-system-roles.timesync/tests/inventory.yaml.j2
/usr/share/ansible/roles/rhel-system-roles.timesync/tests/provision.fmf
/usr/share/ansible/roles/rhel-system-roles.timesync/tests/roles
/usr/share/ansible/roles/rhel-system-roles.timesync/tests/setup-snapshot.yml
/usr/share/ansible/roles/rhel-system-roles.timesync/tests/tests_chrony.yml
/usr/share/ansible/roles/rhel-system-roles.timesync/tests/tests_default.yml
/usr/share/ansible/roles/rhel-system-roles.timesync/tests/tests_default_vars.yml
/usr/share/ansible/roles/rhel-system-roles.timesync/tests/tests_default_wrapper.yml
/usr/share/ansible/roles/rhel-system-roles.timesync/tests/tests_ntp.yml
/usr/share/ansible/roles/rhel-system-roles.timesync/tests/tests_ntp_provider1.yml
/usr/share/ansible/roles/rhel-system-roles.timesync/tests/tests_ntp_provider2.yml
/usr/share/ansible/roles/rhel-system-roles.timesync/tests/tests_ntp_provider3.yml
/usr/share/ansible/roles/rhel-system-roles.timesync/tests/tests_ntp_provider4.yml
/usr/share/ansible/roles/rhel-system-roles.timesync/tests/tests_ntp_provider5.yml
/usr/share/ansible/roles/rhel-system-roles.timesync/tests/tests_ntp_provider6.yml
/usr/share/ansible/roles/rhel-system-roles.timesync/tests/tests_ntp_ptp.yml
/usr/share/ansible/roles/rhel-system-roles.timesync/tests/tests_ptp_multi.yml
/usr/share/ansible/roles/rhel-system-roles.timesync/tests/tests_ptp_single.yml
/usr/share/ansible/roles/rhel-system-roles.timesync/tox.ini
/usr/share/ansible/roles/rhel-system-roles.timesync/vars
/usr/share/ansible/roles/rhel-system-roles.timesync/vars/CentOS_6.yml
/usr/share/ansible/roles/rhel-system-roles.timesync/vars/CentOS_9.yml
/usr/share/ansible/roles/rhel-system-roles.timesync/vars/Debian.yml
/usr/share/ansible/roles/rhel-system-roles.timesync/vars/OracleLinux_6.yml
/usr/share/ansible/roles/rhel-system-roles.timesync/vars/OracleLinux_7.yml
/usr/share/ansible/roles/rhel-system-roles.timesync/vars/OracleLinux_8.yml
/usr/share/ansible/roles/rhel-system-roles.timesync/vars/OracleLinux_9.yml
/usr/share/ansible/roles/rhel-system-roles.timesync/vars/RedHat_6.yml
/usr/share/ansible/roles/rhel-system-roles.timesync/vars/RedHat_9.yml
/usr/share/ansible/roles/rhel-system-roles.timesync/vars/default.yml
/usr/share/ansible/roles/rhel-system-roles.timesync/vars/main.yml
/usr/share/doc/rhel-system-roles/collection/roles/timesync
/usr/share/doc/rhel-system-roles/collection/roles/timesync/CHANGELOG.md
/usr/share/doc/rhel-system-roles/collection/roles/timesync/README.html
/usr/share/doc/rhel-system-roles/collection/roles/timesync/README.md
/usr/share/doc/rhel-system-roles/timesync
/usr/share/doc/rhel-system-roles/timesync/CHANGELOG.md
/usr/share/doc/rhel-system-roles/timesync/README.html
/usr/share/doc/rhel-system-roles/timesync/README.md
/usr/share/doc/rhel-system-roles/timesync/example-multiple-ntp-servers-playbook.yml
/usr/share/doc/rhel-system-roles/timesync/example-single-pool-playbook.yml
/usr/share/licenses/rhel-system-roles/timesync.COPYING

```

and you can use the role from /usr/share/ansible/roles/rhel-system-roles.timesync - some examples also included there under /usr/share/doc/

---

<div class="post-metadata">

**Author:** ![jlehtone](https://avatars.discourse-cdn.com/v4/letter/j/e9a140/32.png) [@jlehtone](https://forums.rockylinux.org/u/jlehtone)\
**Post date:** [June 6, 2023, 10:10am UTC](https://forums.rockylinux.org/t/ansible-best-practices-copy-vs-template/10187/3 "2023-06-06T10:10:58Z")

</div>

> [@iwalker](#):
>
> This can also be installed using:
> 
> ```auto
> dnf install rhel-system-roles
> 
> ```
> 
> without having to install from Ansible Galaxy.

This.  
The package has both names: `rhel-system-roles.timesync` and `linux-system-roles.timesync`, although the latter is just a symlink to the former.

I prefer dynamic _include\_role_ tasks to the `roles:` list, but the timesync has to be _imported_. For example:

```yaml
  - ansible.builtin.import_role:
      name: rhel-system-roles.timesync
    when:
    - timesync_ntp_servers is defined
    - timesync_ntp_servers|length > 0
    tags: timesync

```

(Most rhel-system-roles can be included.)

* * *

As to the copy vs template I’d say that copy is ok when it is clear that parametrization will not be needed. (If you have to deploy binary data, then the template would not be an option.)

The pointed out role shows that neither copy nor template might be necessary, but that is semantic – the role does use something under its hood.

---

<div class="post-metadata">

**Author:** ![brian](https://sea2.discourse-cdn.com/flex020/user_avatar/forums.rockylinux.org/brian/32/5777_2.png) [@brian](https://forums.rockylinux.org/u/brian)\
**Post date:** [August 25, 2023, 3:11am UTC](https://forums.rockylinux.org/t/ansible-best-practices-copy-vs-template/10187/4 "2023-08-25T03:11:40Z")

</div>


