AnsiblePilot — Master Ansible Automation

AnsiblePilot is the leading resource for learning Ansible automation, DevOps, and infrastructure as code. Browse over 1,400 tutorials covering Ansible modules, playbooks, roles, collections, and real-world examples. Whether you are a beginner or an experienced engineer, our step-by-step guides help you automate Linux, Windows, cloud, containers, and network infrastructure.

Popular Topics

About Luca Berton

Luca Berton is an Ansible automation expert, author of 8 Ansible books published by Apress and Leanpub including "Ansible for VMware by Examples" and "Ansible for Kubernetes by Example", and creator of the Ansible Pilot YouTube channel. He shares practical automation knowledge through tutorials, books, and video courses to help IT professionals and DevOps engineers master infrastructure automation.

Ansible Create Hard Link & Symlink: file Module Guide

By Luca Berton · Published 2024-01-01 · Category: troubleshooting

How to create hard links and symbolic links with Ansible file module. Use state=hard and state=link with permissions, force, and practical examples.

Ansible Create Hard Link & Symlink: file Module Guide

I'm going to show you a live Playbook and some simple Ansible code. I'm Luca Berton and welcome to today's episode of Ansible Pilot.

See also: Ansible Create Symlink: file Module with state=link (Guide)

> ansible.builtin.file Manage files and file properties

Today we're talking about the Ansible module file. The full name is ansible.builtin.file, 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. It works in a different variety of operating systems. It manages files and file properties. For a symlink (or softlink) use see the following parameters of Ansible file module. For Windows targets, use the ansible.windows.win_file module instead.

Parameters

• src string - symlink path • dest string - destination file path • state string - file/absent/directory/link/hard/touch • mode/owner/group - permission • setype/seuser/selevel - SELinux

This module has some parameters to perform any tasks. The two required fields are "src" and "dest" which specify the filesystem paths of the har link and the target file. The state defines the type of object we are modifying, the default is "file" but for our use case, we need the "link" option. Let me highlight also the permission and SELinux parameters.

## Playbook

Let's jump into a real-life playbook on how to create a symbolic link with Ansible.

code

• create_hardlink.yml
---
- name: file module demo
  hosts: all
  vars:
    mylink: "~/link"
    myfile: "~/example.txt"
  tasks:
    - name: Creating hardlink
      ansible.builtin.file:
        src: "{{ myfile }}"
        dest: "{{ mylink }}"
        state: hard

execution

$ ansible-playbook -i virtualmachines/demo/inventory create\ link/hardlink.yml
PLAY [file module demo] ***************************************************************************
TASK [Gathering Facts] ****************************************************************************
ok: [demo.example.com]
TASK [Creating hardlink] **************************************************************************
changed: [demo.example.com]
PLAY RECAP ****************************************************************************************
demo.example.com           : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

before execution

$ ssh devops@demo.example.com
[devops@demo ~]$ ls -al
total 16
drwx------. 4 devops wheel 111 Dec  1 15:07 .
drwxr-xr-x. 4 root   root   35 Nov 28 16:46 ..
drwx------. 3 devops wheel  17 Nov 28 16:46 .ansible
-rw-------. 1 devops wheel 224 Dec  1 15:07 .bash_history
-rw-r--r--. 1 devops wheel  18 Dec  4  2020 .bash_logout
-rw-r--r--. 1 devops wheel 141 Dec  4  2020 .bash_profile
-rw-r--r--. 1 devops wheel 376 Dec  4  2020 .bashrc
drwx------. 2 devops wheel  29 Nov 28 16:46 .ssh
[devops@demo ~]$ echo test > example.txt
[devops@demo ~]$ cat example.txt
test
[devops@demo ~]$

after execution

$ ssh devops@demo.example.com
[devops@demo ~]$ ls -al
total 24
drwx------. 4 devops wheel 142 Dec  1 15:09 .
drwxr-xr-x. 4 root   root   35 Nov 28 16:46 ..
drwx------. 3 devops wheel  17 Nov 28 16:46 .ansible
-rw-------. 1 devops wheel 276 Dec  1 15:08 .bash_history
-rw-r--r--. 1 devops wheel  18 Dec  4  2020 .bash_logout
-rw-r--r--. 1 devops wheel 141 Dec  4  2020 .bash_profile
-rw-r--r--. 1 devops wheel 376 Dec  4  2020 .bashrc
drwx------. 2 devops wheel  29 Nov 28 16:46 .ssh
-rw-r--r--. 2 devops wheel   5 Dec  1 15:08 example.txt
-rw-r--r--. 2 devops wheel   5 Dec  1 15:08 link
[devops@demo ~]$ cat link 
test
[devops@demo ~]$ cat example.txt 
test
[devops@demo ~]$ ls -al 
total 24
drwx------. 4 devops wheel 142 Dec  1 15:09 .
drwxr-xr-x. 4 root   root   35 Nov 28 16:46 ..
drwx------. 3 devops wheel  17 Nov 28 16:46 .ansible
-rw-------. 1 devops wheel 276 Dec  1 15:08 .bash_history
-rw-r--r--. 1 devops wheel  18 Dec  4  2020 .bash_logout
-rw-r--r--. 1 devops wheel 141 Dec  4  2020 .bash_profile
-rw-r--r--. 1 devops wheel 376 Dec  4  2020 .bashrc
drwx------. 2 devops wheel  29 Nov 28 16:46 .ssh
-rw-r--r--. 2 devops wheel   5 Dec  1 15:08 example.txt
-rw-r--r--. 2 devops wheel   5 Dec  1 15:08 link
[devops@demo ~]$ chmod 777 link
[devops@demo ~]$ ls -al 
total 24
drwx------. 4 devops wheel 142 Dec  1 15:09 .
drwxr-xr-x. 4 root   root   35 Nov 28 16:46 ..
drwx------. 3 devops wheel  17 Nov 28 16:46 .ansible
-rw-------. 1 devops wheel 276 Dec  1 15:08 .bash_history
-rw-r--r--. 1 devops wheel  18 Dec  4  2020 .bash_logout
-rw-r--r--. 1 devops wheel 141 Dec  4  2020 .bash_profile
-rw-r--r--. 1 devops wheel 376 Dec  4  2020 .bashrc
drwx------. 2 devops wheel  29 Nov 28 16:46 .ssh
-rwxrwxrwx. 2 devops wheel   5 Dec  1 15:08 example.txt
-rwxrwxrwx. 2 devops wheel   5 Dec  1 15:08 link
[devops@demo ~]$ touch link
[devops@demo ~]$ ls -al
total 24
drwx------. 4 devops wheel 142 Dec  1 15:09 .
drwxr-xr-x. 4 root   root   35 Nov 28 16:46 ..
drwx------. 3 devops wheel  17 Nov 28 16:46 .ansible
-rw-------. 1 devops wheel 276 Dec  1 15:08 .bash_history
-rw-r--r--. 1 devops wheel  18 Dec  4  2020 .bash_logout
-rw-r--r--. 1 devops wheel 141 Dec  4  2020 .bash_profile
-rw-r--r--. 1 devops wheel 376 Dec  4  2020 .bashrc
drwx------. 2 devops wheel  29 Nov 28 16:46 .ssh
-rwxrwxrwx. 2 devops wheel   5 Dec  1 15:10 example.txt
-rwxrwxrwx. 2 devops wheel   5 Dec  1 15:10 link
[devops@demo ~]$ touch link
[devops@demo ~]$ ls -al 
total 24
drwx------. 4 devops wheel 142 Dec  1 15:09 .
drwxr-xr-x. 4 root   root   35 Nov 28 16:46 ..
drwx------. 3 devops wheel  17 Nov 28 16:46 .ansible
-rw-------. 1 devops wheel 359 Dec  1 15:11 .bash_history
-rw-r--r--. 1 devops wheel  18 Dec  4  2020 .bash_logout
-rw-r--r--. 1 devops wheel 141 Dec  4  2020 .bash_profile
-rw-r--r--. 1 devops wheel 376 Dec  4  2020 .bashrc
drwx------. 2 devops wheel  29 Nov 28 16:46 .ssh
-rwxrwxrwx. 2 devops wheel   5 Dec  1 15:19 example.txt
-rwxrwxrwx. 2 devops wheel   5 Dec  1 15:19 link
[devops@demo ~]$ ls -li *
134907033 -rwxrwxrwx. 2 devops wheel 5 Dec  1 15:19 example.txt
134907033 -rwxrwxrwx. 2 devops wheel 5 Dec  1 15:19 link
[devops@demo ~]$

code with ❤️ in GitHub

See also: Ansible Create Directory: file Module with state=directory (Guide)

Conclusion

Now you know how to create a hard link in the Linux filesystem with Ansible.

- ansible.builtin.file:
    src: /opt/myapp/current/bin/app
    dest: /usr/local/bin/app
    state: hard
  become: true

See also: Ansible Create File with Content: copy Module content Parameter

- file:
    src: /opt/releases/v2.5.0
    dest: /opt/myapp/current
    state: link
  become: true
# Deploy new version
- unarchive:
    src: "app-{{ version }}.tar.gz"
    dest: /opt/releases/
    remote_src: true
  become: true

# Update symlink to new version - file: src: "/opt/releases/{{ version }}" dest: /opt/myapp/current state: link force: true # Overwrite existing link become: true notify: restart app

| Feature | Hard Link | Symbolic Link | |---------|-----------|---------------| | Cross filesystem | ❌ | ✅ | | Link to directory | ❌ | ✅ | | Original deleted | File persists | Link breaks | | Inode | Same as source | Different | | state value | hard | link |

- file:
    src: "{{ item.src }}"
    dest: "{{ item.dest }}"
    state: link
  loop:
    - { src: /opt/myapp/current/bin/app, dest: /usr/local/bin/app }
    - { src: /opt/myapp/current/etc/app.conf, dest: /etc/app.conf }
    - { src: /opt/myapp/current/lib, dest: /usr/local/lib/myapp }
  become: true

Force Overwrite

# Replace existing file/link with new symlink
- file:
    src: /opt/releases/v3.0.0
    dest: /opt/myapp/current
    state: link
    force: true  # Required if dest already exists and isn't a link
  become: true
- file:
    src: /shared/data
    dest: /home/appuser/data
    state: link
    owner: appuser
    group: appuser
    follow: false  # Set ownership on the link itself
  become: true
# Remove symlink (not the target!)
- file:
    path: /opt/myapp/current
    state: absent
  become: true

Rollback Pattern

- name: Deploy new version
  block:
    - file:
        src: "/opt/releases/{{ new_version }}"
        dest: /opt/myapp/current
        state: link
        force: true
    - uri:
        url: http://localhost:8080/health
        status_code: 200
      retries: 5
      delay: 3
  rescue:
    - name: Rollback to previous version
      file:
        src: "/opt/releases/{{ old_version }}"
        dest: /opt/myapp/current
        state: link
        force: true
  become: true

FAQ

When to use hard links vs symlinks?

Symlinks for most cases (versioned deploys, config management). Hard links only when you need the file to survive source deletion.

Can I create a symlink to a non-existent target?

Yes — with force: true. The link will be "dangling" until the target exists.

follow parameter?

follow: true (default) — operations apply to the target. follow: false — operations apply to the link itself.

Related Articles

the Ansible inventory deep-divemanaging files with ansible.builtin.fileconfiguring Windows services via Ansible

Category: troubleshooting

Watch the video: Ansible Create Hard Link & Symlink: file Module Guide — Video Tutorial

Browse all Ansible tutorials · AnsiblePilot Home