Ansible for File Content
Five modules cover nearly every file task, and choosing the smallest one that does the job keeps playbooks idempotent.
- copy puts a whole file in place, from src on control or inline content. Owner, group, mode and validate go with it. - template is copy plus Jinja2: variables, facts, loops and conditionals in a .j2 file. - lineinfile manages one line: regexp finds the existing line to replace, line is what it becomes, insertafter/insertbefore place a new one. - blockinfile manages several lines between markers, so it can update or remove its own block later. - file manages the thing rather than the content: directories, links, permissions, ownership, state: absent.
yaml - ansible.builtin.template: src: templates/motd.j2 This is {{ inventoryhostname }} in the {{ groupnames | first }} environment dest: /etc/motd - ansible.builtin.lineinfile: path: /etc/ssh/sshdconfig regexp: '^?PermitRootLogin' line: PermitRootLogin no validate: /usr/sbin/sshd -t -f %s notify: restart sshd - ansible.builtin.blockinfile: path: /etc/security/limits.conf marker: " {mark} WEBASHA DEV" block: | @developers soft nproc 4096 - ansible.builtin.file: { path: /srv/webasha, state: directory, group: wheel, mode: "2775" }
Templates on the exam. A favourite is /etc/hosts or a report built from facts of all hosts: {% for h in groups['all'] %}{{ hostvars[h].ansiblefacts.defaultipv4.address }} {{ hostvars[h].ansiblefacts.fqdn }}{% endfor %}. Facts of other hosts exist only if they were gathered in this run, so target all in an earlier play.
Checking your work. ansible all -m command -a 'cat /etc/motd' shows every rendered template at once, so a missing variable or a wrong group name stands out. Use --diff with --check to preview what lineinfile or template would change without changing it. Add backup: true when editing important system files; it keeps a timestamped copy next to the original.
Pitfalls. Unquoted modes: mode: 0644 is octal in YAML 1.1 but 2775 without a leading zero is decimal; always quote modes ("0644", "2775"). A lineinfile without regexp adds a second line instead of replacing the old one. {mark} must appear in a custom marker. Templates live on control, relative to the playbook or the role's templates/ directory.