Picture this: You’ve set up Elasticsearch on your servers and want to update the configuration file to increase the heap size for better performance.
You have two options. The first is manual: SSH into each server, edit the Elasticsearch configuration file (elasticsearch.yml
) using a text editor, adjust the heap.size
value, save it, and restart the service. If you manage multiple nodes, you’ll repeat this process on each one, which can be tedious and error-prone.
The second option is to use Ansible’s lineinfile. With this approach, you define the change once in your playbook, and Ansible handles everything — connecting to all servers, updating the configuration, and managing restarts — in one command. This ensures consistency, saves time, and reduces human error.
In this article, we’ll explore the Ansible lineinfile module, explain how to use it, and discuss some common use cases. By the end of this article, you’ll no longer need to update your configurations manually.
The Ansible lineinfile module is designed to help you make specific changes to a line or multiple lines in your Ansible host’s configuration files. Instead of replacing an entire configuration file, it allows you to search for and modify a particular line or add a new one if it’s not there.
It works as a precise editor that runs on your server — automating what you would normally do by hand. Whether you need to update a value, correct a typo, or even insert a new setting, the lineinfile module ensures the file is updated exactly where it needs to be without touching the rest of its content.
The lineinfile module uses regular expressions to find the exact line you want to modify, enabling flexibility in how you search for and change values. This is useful for managing configuration files that are sensitive to formatting or contain many similar entries.
Plus, with an option to create backups of the original file before changes are made, the process has an extra layer of safety built in, reducing the risk of accidental misconfigurations.
Lineinfile module options
The lineinfile module comes with several parameters that allow you to control exactly how a line is added or modified in a file:
- path (required): This specifies the file path on the target host where you want to make changes.
- line (required): This is the new line or content you want to insert or update in the file.
- regexp (optional): This is a regular expression that identifies the line to search for within the file, ensuring the module knows exactly which line to modify.
- insertafter (optional): This specifies where the new line should be inserted if the regular expression doesn’t match any existing line. It can be added after a specific line or at the end of the file.
- insertbefore (optional): This is similar to insertafter, but it inserts the new line before a specific point in the file.
- state (optional): This controls whether the line should be present (inserted or replaced) or absent (deleted).
- create (optional): If set to true, the file will be created if it doesn’t already exist.
- backup (optional): This ensures that a file backup is made before any changes are applied, allowing you to restore the original version if needed.
For a complete list of the lineinfile parameters, you can view the Ansible lineinfile documentation section.
The difference between replace and lineinfile modules
The replace module in Ansible searches and replaces text in a file based on regular expressions. It operates on all occurrences within the file and is simpler, but it lacks control over specific lines.
The lineinfile module ensures a specific line exists (or doesn’t), replacing or adding it as needed. It targets a specific line by pattern matching, offering more control over individual lines.
replace should be used for bulk substitutions and lineinfile for precise line editing or enforcing file configurations.
Read about other Ansible modules: How To Use Ansible Modules Efficiently
The following sections will demonstrate how to use the Ansible lineinfile module to make basic configuration modifications:
We’ll continue with the Elasticsearch example for the demonstrations below. However, you can replicate it for various use cases you might have.
Demo environment
The examples in this article were created on an Ubuntu AWS EC2 instance. If you’re following along, you can easily set one up and install Ansible on your machine in just a few steps. Whether you’re using EC2 or another environment, the steps remain the same.
Note: In the playbooks below, you’ll notice the ansible.builtin.lineinfile reference — this is the Fully Qualified Collection Name (FQCN) of the lineinfile module. It’s a best practice to use the FQCN to avoid any conflicts with other module names.
Add a line to a file
To add a single line to a file if it doesn’t already exist, you use the line option of the Ansible lineinfile module to specify the text you want to add.
For example, if you want to add the line server.name: elasticsearch
to the /etc/elasticsearch/elasticsearch.yml
file, this is what your playbook will look like:
---
- hosts: all
become: yes
tasks:
- name: Add a line to the Elasticsearch configuration
ansible.builtin.lineinfile:
path: /etc/elasticsearch/elasticsearch.yml
line: 'server.name: elasticsearch'
create: true
In this case, if the file doesn’t exist, it will be created using the create: true option, and the line will be added.
Once you run this playbook, you should see the following output:
Remove a line in a file
To remove a specific line from a file with the Ansible lineinfile module, you can use the state: absent option, along with regexp, to match the line you want to remove.
For instance, to remove the line server.name: elasticsearch
from the /etc/elasticsearch/elasticsearch.yml
file, you will write your playbook like this:
---
- hosts: all
become: yes
tasks:
- name: Remove a line from the Elasticsearch configuration
ansible.builtin.lineinfile:
path: /etc/elasticsearch/elasticsearch.yml
regexp: '^server.name: elasticsearch'
state: absent
This will search for the line that matches the regular expression and remove it if found.
Once you run this playbook, you should see the following output:
Replace a line in a file
To replace an existing line, you use the regexp parameter to find the line and the line parameter to specify the new value. If the line exists, it will be replaced.
To replace the server.name: elasticsearch
line with server.name: my-elasticsearch
, your playbook will look like this:
---
- hosts: all
become: yes
tasks:
- name: Replace a line in the Elasticsearch configuration
ansible.builtin.lineinfile:
path: /etc/elasticsearch/elasticsearch.yml
regexp: '^server.name: elasticsearch'
line: 'server.name: my-elasticsearch'
This will search for the line starting with server.name: elasticsearch
and replace it with the new value.
Once you run this playbook, you should see the following output:
Change multiple lines in a file
To change multiple lines, you can add multiple lineinfile tasks to your playbook, or use the with_items loop for a more efficient configuration.
For instance, to change both the server.port
and cluster.name
values, your playbook will look like this:
---
- hosts: all
become: yes
tasks:
- name: Change multiple lines in Elasticsearch configuration
ansible.builtin.lineinfile:
path: /etc/elasticsearch/elasticsearch.yml
regexp: '{{ item.regexp }}'
line: '{{ item.line }}'
with_items:
- { regexp: '^server.port:', line: 'server.port: 9200'}
- { regexp: '^cluster.name:', line: 'cluster.name: my-cluster'}
This playbook updates both the server port and cluster name with just one task, using a loop.
Once you run this playbook, you should see the following output:
Insert a line after a match
You can use the insertafter option of the lineinfile module to insert a line after a specific match. This option determines where the new line should be added.
To insert discovery.zen.minimum_master_nodes: 1
after the cluster.name: my-cluster
line, you’ll run the following playbook:
---
- hosts: all
become: yes
tasks:
- name: Insert a line after a match
ansible.builtin.lineinfile:
path: /etc/elasticsearch/elasticsearch.yml
line: 'discovery.zen.minimum_master_nodes: 1'
insertafter: '^cluster.name: my-cluster'
This will add the new line right after the file’s cluster.name
configuration.
Once you run this playbook, you should see the following output:
Insert a line before a match
Similarly, you can insert a line before a specific match using the insertbefore option.
To insert http.port: 9200
before the network.host: 0.0.0.0 line
, run the following playbook:
---
- hosts: all
become: yes
tasks:
- name: Insert a line before a match
ansible.builtin.lineinfile:
path: /etc/elasticsearch/elasticsearch.yml
line: 'http.port: 9200'
insertbefore: '^network.host: 0.0.0.0'
This will insert the new configuration line before the network.host
setting in the file.
Once you run this playbook, you should see the following output:
The lineinfile module is extremely useful in specific scenarios where you need to manage files on remote hosts programmatically.
In this section, we’ll discuss common use cases and provide examples of when using the lineinfile module is the most logical and efficient approach.
Example 1: Writing to log files
Sometimes, you may need to append specific log entries to a file, such as adding a custom log entry after a certain action. Using Ansible lineinfile, you can ensure that the log entry is only added if it’s not already present.
With the example below, you can append a log entry to /var/log/custom.log
:
---
- hosts: all
become: yes
tasks:
- name: Append a log entry to a log file
ansible.builtin.lineinfile:
path: /var/log/custom.log
line: 'Log entry: Service started successfully'
insertafter: EOF
create: true
This task will add the line Log entry: Service started successfully
to the end of the log file if it doesn’t already exist.
Once you run this playbook, you should see the following output:
Example 2: Backing up changed files
When modifying configuration files, it’s good practice to create a backup in case the change causes issues. The lineinfile module allows you to back up the original file before any changes are made.
The following playbook allows you to modify a file and create a backup of the original:
---
- hosts: all
become: yes
tasks:
- name: Modify a configuration file with backup
ansible.builtin.lineinfile:
path: /etc/elasticsearch/elasticsearch.yml
line: 'server.port: 9300'
backup: yes
This will replace or add the line server.port: 9300
and automatically create a backup of the original file before any modifications.
Once you run this playbook, you should see the following output:
Example 3: Verifying changes
The lineinfile module provides a way to validate file content before making any modifications. The validate parameter allows you to specify a script or command to check the file’s content against specific rules.
The example below uses the validate parameter to ensure the /etc/elasticsearch/elasticsearch.yml
file meets the necessary conditions before modification:
---
- hosts: all
become: yes
tasks:
- name: Validate file before modification
ansible.builtin.lineinfile:
path: /etc/elasticsearch/elasticsearch.yml
line: 'cluster.name: my-cluster'
validate: "/home/ubuntu/validate.sh"
This task executes the specified validation script (validate.sh) before making any changes to /etc/elasticsearch/elasticsearch.yml
. If the validation fails, the lineinfile task will not proceed with any modifications.
Example 4: Checking if a line is present in a file
Before making changes, you may need to check whether a specific line or configuration already exists. This can help prevent duplicate entries or unnecessary edits.
The example below checks if server.name
is already present in the configuration file:
---
- hosts: all
become: yes
tasks:
- name: Check if server.name is present
ansible.builtin.lineinfile:
path: /etc/elasticsearch/elasticsearch.yml
line: 'server.name: elasticsearch'
state: present
This will ensure that the line is present in the file, and if it’s not, the module will add it.
Once you run this playbook, you should see the following output:
Example 5: Setting file permission
When adding or modifying a file, it’s often important to ensure that the file permissions are correct. The lineinfile module allows you to set file permissions explicitly using the mode parameter.
The mode parameter accepts the octal representation of file permissions, such as 0644 for read-write permissions for the owner and read-only permissions for others.
In the following example, you’ll see how you can set file permissions while creating or modifying a file:
Spacelift’s vibrant ecosystem and excellent GitOps flow can greatly assist you in managing and orchestrating Ansible. By introducing Spacelift on top of Ansible, you can then easily create custom workflows based on pull requests and apply any necessary compliance checks for your organization.
Another great advantage of using Spacelift is that you can manage different infrastructure tools like Ansible, Terraform, Pulumi, AWS CloudFormation, and even Kubernetes from the same place and combine their Stacks with building workflows across tools.
Our latest Ansible enhancements solve three of the biggest challenges engineers face when they are using Ansible:
- Having a centralized place in which you can run your playbooks
- Combining IaC with configuration management to create a single workflow
- Getting insights into what ran and where
Provisioning, configuring, governing, and even orchestrating your containers can be performed with a single workflow, separating the elements into smaller chunks to identify issues more easily.
If you want to learn more about using Spacelift with Ansible, check our documentation, read our Ansible guide, or book a demo with one of our engineers.
Would you like to see this in action – or just want a tl;dr? Check out this video I put together showing you Spacelift’s new Ansible functionality:
In this article, we covered the lineinfile module in Ansible, explaining its use cases and how it differs from the replace module. Although both modules modify files, we highlighted the distinction between them: lineinfile focuses on managing individual lines, whereas replace deals with much broader replacements.
We also walked through various code examples that demonstrate how to write your playbook for different scenarios, such as adding, removing, and replacing configuration lines in files. This included practical tasks like ensuring file permissions, backing up modified files, and validating file contents before making changes.
There are many non-manual ways to tweak your playbook to make modifications. All you need to do is combine a few lineinfile module parameters, and you’re good to go.
Manage Ansible Better with Spacelift
Managing large-scale playbook execution is hard. Spacelift enables you to automate Ansible playbook execution with visibility and control over resources, and seamlessly link provisioning and configuration workflows.