How to setup NFS server using Vagrant and Ansible
Here in this article we will see how we can setup a basic NFS server using Vagrant and Ansible. We will try to install and configure our NFS server and use a NFS client to mount the filesystems shared using the NFS server.
Test Environment
Fedora 37 workstation
What is NFS
The Network File System (NFS) was developed to allow machines to mount a disk partition on a remote machine as if it were a local disk. It allows for fast, seamless sharing of files across a network. NFS Versions 2, 3, and 4 are supported on 2.6 and later kernels.
What are NFS Daemons
NFS service relies on several different service daemons for normal operation. Here are some of them with brief details.
Daemon | Description |
nfsd | This daemon handles other client file-system requests |
mountd | This daemon handles file-system mount requests from remote systems and provides access control |
automountd | This daemon handles the mounting and unmounting requests from the autofs service |
lockd | This daemon supports record-locking operations on NFS files |
statd | This daemon records information about each monitored NFS peer on persistent storage |
quotad | This process provides user quota information for remote users |
If you are interested in watching the video. Here is the YouTube video on the same step by step procedure outline below.
Procedure
Step1: Install NFS Utils
The nfs-utils package provides a daemon for the kernel NFS server and related tools, which provides a much higher level of performance than the traditional Linux NFS server used by most users. NFS server consist of launching serveral daemons. The basic NFS service is called nfs-server. The nfs-server service automatically starts the rpcbind service, if it is not already running.
The following ports TCP and UDP ports 2049 (nfs), 111 (rpcbind) and TCP and UDP ports 20048 for the showmount command must be open for an NFS server to function properly.
$ cat ansible/roles/linux_nfs_install_server/tasks/main.yml
---
- name: install nfs server
dnf:
name: nfs-utils
state: present
- name: ensure nfs service is enabled and running
service:
name: nfs-server
state: started
enabled: yes
These are the list of installed packages.
Installed:
gssproxy-0.9.1-5.fc38.x86_64 keyutils-1.6.1-6.fc38.x86_64 libev-4.33-7.fc38.x86_64 libnfsidmap-1:2.6.3-1.rc3.fc38.x86_64 libverto-libev-0.3.2-5.fc38.x86_64
nfs-utils-1:2.6.3-1.rc3.fc38.x86_64 quota-1:4.09-2.fc38.x86_64 quota-nls-1:4.09-2.fc38.noarch rpcbind-1.2.6-4.rc2.fc38.x86_64 sssd-nfs-idmap-2.8.2-4.fc38.x86_64
These are the list of config files, utilities and services that are installed.
$ rpm -ql nfs-utils | grep -v "/usr/share" | grep -v "/usr/lib/.build-id"
Step2: Stop NFS Service
Let us now stop the default NFS service and try to configure it in our next steps after taking the backup of the NFS File share configruation.
$ cat ansible/roles/linux_nfs_stop_server/tasks/main.yml
- name: ensure nfs service is stopped
service:
name: nfs-server
state: stopped
Step3: Config Backup
Network filesystems are shared by exporting them from the NFS server. Exporting is done in Linux by adding entries into the /etc/exports file. Let’s try to take a backup of this configuration file before making any changes.
$ cat ansible/roles/linux_nfs_config_backup/vars/main.yml
---
nfs_config: "/etc/exports"
nfs_config_backup: "/mnt/backups"
$ cat ansible/roles/linux_nfs_config_backup/tasks/main.yml
- name: ensure backup directory present
file:
path: "{{ nfs_config_backup }}"
state: directory
mode: '0755'
- name: ensure nfs config backup
shell: cp -pr "{{ nfs_config }}" "{{ nfs_config_backup }}"/exports_$(date +%F_%H_%M_%Z)
Step4: Sharing NFS Filesystem
Here in this step we are going to create a new user and group. The ownership of the NFS share directory which we want to export is configured with the new user that we just created. We are also creating a dummy file on our NFS share directory and configuring the “/etc/exports” as shown below.
$ cat ansible/roles/linux_nfs_config_update/vars/main.yml
---
nfs_share_directory: "/share/stack"
nfs_other_directory: "/share/other"
$ cat ansible/roles/linux_nfs_config_update/templates/exports.j2
{{ nfs_share_directory }} 192.168.121.0/24(ro)
{{ nfs_other_directory }} 192.168.121.0/24(rw)
$ cat ansible/roles/linux_nfs_config_update/tasks/main.yml
- name: add group
group:
name: admin
gid: 1001
state: present
- name: add user
user:
name: admin
uid: 1001
comment: admin
group: admin
- name: ensure share directory present
file:
path: "{{ nfs_share_directory }}"
state: directory
mode: '0744'
owner: admin
group: admin
- name: ensure other directory present
file:
path: "{{ nfs_other_directory }}"
state: directory
mode: '0744'
owner: admin
group: admin
- name: ensure share directory present
shell: echo "Hello NFS Server Test!!" > "{{ nfs_share_directory }}"/hellonfs.txt; chown -R admin:admin "{{ nfs_share_directory }}"
- name: ensure other directory present
shell: echo "Hello NFS Server Test in other!!" > "{{ nfs_other_directory }}"/hellonfsother.txt; chown -R admin:admin "{{ nfs_other_directory }}"
- name: configure nfs server
template:
src: exports.j2
dest: /etc/exports
mode: '0644'
Step5: Start NFS Service
Now its time to start our NFS service. By rebooting the system or restarting the NFS service we essentially run exportfs commands which basically exports the NFS filesystem from the server that we want to share.
$ cat ansible/roles/linux_nfs_start_server/tasks/main.yml
- name: ensure nfs service is started
service:
name: nfs-server
state: started
Running the exportfs command after you change the exports file is a good idea. If any errors are in the file, exportfs identifies them for you.
# /usr/sbin/exportfs -a -r -v
Here is my complete project directory structure of the Vagrant and Ansible based NFS server that we will now launch using the vagrant utility as shown below.
$ tree .
.
├── ansible
│ ├── linux_nfs_provision_server.yml
│ └── roles
│ ├── linux_nfs_config_backup
│ │ ├── tasks
│ │ │ └── main.yml
│ │ └── vars
│ │ └── main.yml
│ ├── linux_nfs_config_update
│ │ ├── tasks
│ │ │ └── main.yml
│ │ ├── templates
│ │ │ └── exports.j2
│ │ └── vars
│ │ └── main.yml
│ ├── linux_nfs_install_server
│ │ └── tasks
│ │ └── main.yml
│ ├── linux_nfs_start_server
│ │ └── tasks
│ │ └── main.yml
│ └── linux_nfs_stop_server
│ └── tasks
│ └── main.yml
└── Vagrantfile
16 directories, 10 files
Here is my playbook which we are going to call from the Vagrantfile.
$ cat ansible/linux_nfs_provision_server.yml
---
- name: linuxn nfs server management
hosts: nfs
become: true
become_user: root
roles:
- { role: 'linux_nfs_install_server' }
- { role: 'linux_nfs_stop_server' }
- { role: 'linux_nfs_config_backup' }
- { role: 'linux_nfs_config_update' }
- { role: 'linux_nfs_start_server' }
$ vagrant up
Step6: Mount the NFS Share (Client Machine)
Here in this step we will first try to list the NFS shares that are available on the FNS server using the showmount command as shown below.
$ sudo showmount -e fednfs.stack.com
Export list for fednfs.stack.com:
/share/other 192.168.121.0/24
/share/stack 192.168.121.0/24
Now here we will try to mount the NFS share “/share/stack” onto /var/tmp/sud local filesystem directory as shown below.
$ mkdir -p /var/tmp/stack
$ mkdir -p /var/tmp/other
$ sudo mount -t nfs fednfs.stack.com:/share/stack /var/tmp/stack/
$ sudo mount -t nfs fednfs.stack.com:/share/other /var/tmp/other/
$ sudo mount -t nfs4
fednfs.stack.com:/share/stack on /var/tmp/stack type nfs4 (rw,relatime,vers=4.2,rsize=262144,wsize=262144,namlen=255,hard,proto=tcp,timeo=600,retrans=2,sec=sys,clientaddr=192.168.121.1,local_lock=none,addr=192.168.121.13)
fednfs.stack.com:/share/other on /var/tmp/other type nfs4 (rw,relatime,vers=4.2,rsize=262144,wsize=262144,namlen=255,hard,proto=tcp,timeo=600,retrans=2,sec=sys,clientaddr=192.168.121.1,local_lock=none,addr=192.168.121.13)
If the mount is successful, you should be able to see the NFS share dummy file that we create available for us to read as shown below.
$ cat /var/tmp/stack/hellonfs.txt
Hello NFS Server Test!!
$ cat /var/tmp/other/hellonfsother.txt
Hello NFS Server Test in other!!
Try editing files on the mount share.
$ echo "Try to write to me" > /var/tmp/stack/hellonfs.txt
bash: /var/tmp/stack/hellonfs.txt: Read-only file system
$ echo "Try to write to me" > /var/tmp/other/hellonfsother.txt
$ cat /var/tmp/other/hellonfsother.txt
Try to write to me
Once we are done with our task we can just unmount the fileshare from our local filesystem as shown below.
$ sudo umount /var/tmp/stack
$ sudo umount /var/tmp/other
Hope you enjoyed reading this article. Thank you..
Leave a Reply
You must be logged in to post a comment.