Ansible lineinfile Module: Edit Single Lines in Config Files
By Luca Berton · Published 2024-01-01 · Category: database-automation
How to edit single lines in files with Ansible lineinfile module. Add, modify, remove lines using regex, manage config files idempotently with examples.

Today we're going to talk about how to edit a single-line text in a file with Ansible. Ansible module lineinfile. I'm Luca Berton and welcome to today's episode of Ansible Pilot
Ansible module lineinfile
Today we're talking about the Ansible module lineinfile.
The full name is ansible.builtin.lineinfile, which means that is part of the collection of modules "builtin" with ansible and shipped with it.
It's a module pretty stable and out for years and it supports a large variety of operating systems.
You are able to insert, update and remove a single line of text in a file.
Main Parameters
• path _string_ - file path • line _string_ - text • insertafter/insertbefore _string_ - EOF/regular expression • validate _string_ - validation command • create _boolean_ - create if not exist • state _string_ - present/absent • owner/group/mode - permission • setype/seuser/selevel - SELinuxThis module has some parameters to perform any tasks. The only required is "path", where you specify the filesystem path of the file you're going to edit. "line" is the line of text we would like to insert in the file, easy! By default, the text is going to be inserted at the end of the file, but we could personalize it in a specific position with "insertafter" or "insertbefore". If there is any tool to validate the file we could specify it in the validate parameter, very useful for configuration files. If the file does not exist we could also "create" it! Usually, we would like to insert a text line but we could also remove using state in conjunction with parameter absent. Let me also highlight that we could also specify some permissions or SELinux property.
See also: Edit single-line text - Ansible Playbook for Changing IP Address of Remote Hosts
Links
• ansible.builtin.lineinfilePlaybook
Are you ready to make your hands dirty? Let's jump in a live Playbook of lineinfile module usage in the Ansible playbook. • lineinfile.yml---
- name: lineinfile module demo
hosts: all
become: true
tasks:
- name: allow password authentication
ansible.builtin.lineinfile:
state: present
dest: /etc/ssh/sshd_config
regexp: "^PasswordAuthentication"
line: "PasswordAuthentication yes"
validate: 'sshd -t -f %s'
See also: Ansible blockinfile Module: Insert & Manage Multi-Line Text Blocks (Guide)
Conclusion
Now you know better the Ansible module lineinfile and you could use it successfully in your playbook.Common lineinfile Patterns
Add or update a line
- name: Set timezone in config
ansible.builtin.lineinfile:
path: /etc/myapp/config.ini
regexp: '^timezone='
line: 'timezone=UTC'
become: true
Add line if not present
- name: Add DNS server
ansible.builtin.lineinfile:
path: /etc/resolv.conf
line: 'nameserver 8.8.8.8'
state: present
become: true
Remove a line
- name: Remove old DNS entry
ansible.builtin.lineinfile:
path: /etc/resolv.conf
regexp: '^nameserver 10\.0\.0\.1'
state: absent
become: true
Insert after a specific line
- name: Add config after section header
ansible.builtin.lineinfile:
path: /etc/ssh/sshd_config
insertafter: '^#Port 22'
line: 'Port 2222'
become: true
notify: restart sshd
Insert before a specific line
- name: Add comment before setting
ansible.builtin.lineinfile:
path: /etc/myapp/config.ini
insertbefore: '^max_connections='
line: '# Maximum database connections (default: 100)'
become: true
Uncomment a line
- name: Enable password authentication
ansible.builtin.lineinfile:
path: /etc/ssh/sshd_config
regexp: '^#?PasswordAuthentication'
line: 'PasswordAuthentication yes'
become: true
Modify with backreferences
- name: Double the max connections value
ansible.builtin.lineinfile:
path: /etc/myapp/config.ini
regexp: '^(max_connections=)(\d+)'
line: '\g<1>200'
backrefs: true
become: true
See also: Add Secondary Groups to Linux Users with Ansible Playbook
Validate Before Applying
- name: Update sshd_config safely
ansible.builtin.lineinfile:
path: /etc/ssh/sshd_config
regexp: '^PermitRootLogin'
line: 'PermitRootLogin no'
validate: '/usr/sbin/sshd -t -f %s'
become: true
lineinfile vs blockinfile vs replace
| Module | Use Case |
|--------|----------|
| lineinfile | Add/modify/remove a single line |
| blockinfile | Add/modify a block of multiple lines |
| replace | Regex find-and-replace (no line constraint) |
| template | Generate entire file from Jinja2 template |
| copy | Write entire file content |
Key Parameters
| Parameter | Description |
|-----------|-------------|
| path | Target file |
| line | Line content to add/set |
| regexp | Regex to find existing line |
| state | present (default) or absent |
| insertafter | Regex - insert after this line |
| insertbefore | Regex - insert before this line |
| backrefs | Use regex groups in replacement |
| create | Create file if missing |
| validate | Command to validate before saving |
| backup | Create backup before modifying |
FAQ
Why does lineinfile add duplicate lines?
If regexp doesn't match any existing line, lineinfile appends the line. Use a regex that matches the line you want to modify, including any previous value.
How do I edit multiple lines?
Use blockinfile for a block, or multiple lineinfile tasks. For complex multi-line edits, consider template.
Can I use variables in regexp?
Yes, but escape regex special characters:
regexp: "^{{ item.key | regex_escape }}="
line: "{{ item.key }}={{ item.value }}"
Add a Line
- ansible.builtin.lineinfile:
path: /etc/hosts
line: "10.0.1.10 web1.internal"
become: true
Replace a Line (Regex)
- lineinfile:
path: /etc/ssh/sshd_config
regexp: '^#?PermitRootLogin'
line: 'PermitRootLogin no'
become: true
notify: restart sshd
Remove a Line
- lineinfile:
path: /etc/hosts
regexp: 'old-server\.internal'
state: absent
become: true
Ensure Line After Pattern
- lineinfile:
path: /etc/myapp/config.conf
insertafter: '^\[database\]'
line: 'host = db.production.internal'
become: true
Ensure Line Before Pattern
- lineinfile:
path: /etc/nginx/nginx.conf
insertbefore: '^}'
line: ' include /etc/nginx/conf.d/*.conf;'
become: true
Multiple Lines (Loop)
- lineinfile:
path: /etc/sysctl.conf
regexp: "^{{ item.key }}"
line: "{{ item.key }} = {{ item.value }}"
loop:
- { key: net.ipv4.ip_forward, value: 1 }
- { key: vm.swappiness, value: 10 }
- { key: fs.file-max, value: 65536 }
become: true
notify: reload sysctl
Backup Before Change
- lineinfile:
path: /etc/fstab
regexp: '^/dev/sdb1'
line: '/dev/sdb1 /data ext4 defaults 0 2'
backup: true # Creates timestamped backup
become: true
Validate After Change
- lineinfile:
path: /etc/sudoers
regexp: '^deploy'
line: 'deploy ALL=(ALL) NOPASSWD: ALL'
validate: 'visudo -cf %s'
become: true
Create File If Missing
- lineinfile:
path: /etc/myapp/custom.conf
line: 'setting = value'
create: true
mode: '0644'
become: true
Common Use Cases
# Disable SELinux
- lineinfile:
path: /etc/selinux/config
regexp: '^SELINUX='
line: 'SELINUX=disabled'
# Set timezone
- lineinfile:
path: /etc/timezone
regexp: '.*'
line: 'America/New_York'
# Comment out a line
- lineinfile:
path: /etc/myapp/config
regexp: '^(dangerous_setting.*)'
line: '#\1'
backrefs: true
# Uncomment a line
- lineinfile:
path: /etc/myapp/config
regexp: '^#(wanted_setting.*)'
line: '\1'
backrefs: true
lineinfile vs blockinfile vs template
| Module | Use Case |
|--------|----------|
| lineinfile | Single line add/replace/remove |
| blockinfile | Multi-line block with markers |
| template | Full file management |
| replace | Regex replace (no line management) |
Key Parameters
| Parameter | Description |
|-----------|-------------|
| path | Target file |
| line | Line to ensure present |
| regexp | Pattern to match for replacement |
| state | present or absent |
| insertafter | Add after matching line |
| insertbefore | Add before matching line |
| backrefs | Use regex groups in line |
| create | Create file if missing |
| backup | Backup before change |
| validate | Validate command |
| firstmatch | Only affect first match |
FAQ
Why does lineinfile add duplicate lines?
If regexp doesn't match any existing line, lineinfile adds the line as new. Use regexp that matches what you're replacing.
How do I use regex groups (backrefs)?
- lineinfile:
path: /etc/config
regexp: '^(Port)\s+\d+'
line: '\1 8080'
backrefs: true
# Changes "Port 22" to "Port 8080"
Can I replace multiple occurrences?
lineinfile only replaces the last match by default. Use firstmatch: true for the first. For all occurrences, use the replace module.
Set a Config Value
- ansible.builtin.lineinfile:
path: /etc/ssh/sshd_config
regexp: '^#?PermitRootLogin'
line: 'PermitRootLogin no'
become: true
notify: restart sshd
Add a Line
- lineinfile:
path: /etc/hosts
line: '10.0.1.10 app.example.com'
become: true
Remove a Line
- lineinfile:
path: /etc/hosts
regexp: '^10\.0\.1\.10'
state: absent
become: true
Insert After/Before
# After a pattern
- lineinfile:
path: /etc/myapp/config.conf
insertafter: '^\[database\]'
line: 'host = db.example.com'
become: true
# Before a pattern
- lineinfile:
path: /etc/myapp/config.conf
insertbefore: '^\[logging\]'
line: 'cache_enabled = true'
become: true
Multiple Lines
- lineinfile:
path: /etc/sysctl.conf
regexp: "^{{ item.key }}"
line: "{{ item.key }} = {{ item.value }}"
loop:
- { key: 'net.ipv4.ip_forward', value: '1' }
- { key: 'net.ipv4.tcp_syncookies', value: '1' }
- { key: 'vm.swappiness', value: '10' }
become: true
notify: reload sysctl
Backup Before Edit
- lineinfile:
path: /etc/ssh/sshd_config
regexp: '^PasswordAuthentication'
line: 'PasswordAuthentication no'
backup: true
become: true
Create File If Missing
- lineinfile:
path: /etc/myapp/custom.conf
line: 'setting = value'
create: true
mode: '0644'
become: true
Validate After Edit
- lineinfile:
path: /etc/sudoers
regexp: '^deploy'
line: 'deploy ALL=(ALL) NOPASSWD: ALL'
validate: 'visudo -cf %s'
become: true
lineinfile vs replace vs blockinfile
| Module | Scope | Use Case |
|--------|-------|----------|
| lineinfile | Single line | Config key=value |
| replace | Regex match | Multi-line regex replace |
| blockinfile | Text block | Multi-line sections |
FAQ
regexp but line not found?
If regexp matches nothing, the line is appended to end of file. Use insertafter/insertbefore to control placement.
How to ensure a line is NOT present?
- lineinfile:
path: /etc/config
regexp: 'dangerous_setting'
state: absent
Why does lineinfile keep adding duplicate lines?
Your regexp doesn't match the line you're adding. Ensure regexp would match the exact line text.
Related Articles
• Ansible privilege escalation patterns • role-based playbook organization in AnsibleSee also
• Ansible Rolling Update Debian/Ubuntu: apt Module Guide (Examples)Category: database-automation
Watch the video: Ansible lineinfile Module: Edit Single Lines in Config Files — Video Tutorial