Using NFS over TLS
This procedure shows how to mount an NFS share over a Transport Layer Security (TLS) channel on systems that run either RHEL 9 / Rocky Linux 9 or Ubuntu 24.04 LTS.
1. Prerequisites
- A server that exports an NFS share and supports RFC 9289 - Towards Remote Procedure Call Encryption by Default.
- The kernel needs to be new enough to have been built with
CONFIG_NET_HANDSHAKE=y. Examples: RHEL 9.x or upstream kernel 6.7 and above. - Access to certificates that the client will trust (either a private CA certificate or the server certificate itself)
2. Install the required packages
RHEL 9 / Rocky Linux 9
sudo dnf install nfs-utils ktls-utils
The ktls-utils package delivers tlshd, the user‑space handshake daemon that enables kTLS.
Ubuntu 24.04 LTS
sudo apt update
sudo apt install nfs-common ktls-utils (>= 0.11)
If your mirror does not yet carry version 0.11 or later, download the package manually:
wget -4 https://archive.ubuntu.com/ubuntu/pool/universe/k/ktls-utils/ktls-utils_0.11-1_amd64.deb
sudo dpkg -i ktls-utils_0.11-1_amd64.deb
3. Enable the tlshd handshake daemon
sudo systemctl enable --now tlshd.service
Verify that the service is active:
systemctl --no-pager status tlshd
4. Provide certificates
The client must present a certificate chain that it trusts. Use one of the following options:
Option A — use an existing Enterprise CA
- Copy the CA certificate that signed the NFS server’s certificate to the client.
- Continue with Section 5.
Option B — generate a private CA and a server certificate (lab use)
WARNING: Self‑signed certificates are suitable only for testing. Use a trusted CA in production environments.
# Create a private CA (valid for 10 years)
openssl req \
-x509 -nodes -new -sha256 -days 3650 \
-newkey rsa:2048 \
-keyout RootCA.key \
-out RootCA.crt \
-subj "/CN=Demo‑Root‑CA"
# Create a server key and CSR (replace with real FQDN / IP)
openssl req \
-new -nodes -newkey rsa:2048 \
-keyout server.key \
-out server.csr \
-subj "/CN=nfs.example.com"
cat > domains.ext <<'EOF'
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage=digitalSignature,nonRepudiation,keyEncipherment,dataEncipherment
subjectAltName=DNS:nfs.example.com,IP:192.0.2.10
EOF
# Sign the CSR with the private CA (valid for ~3 years)
openssl x509 -req -in server.csr \
-CA RootCA.crt -CAkey RootCA.key -CAcreateserial \
-out server.crt -days 1024 -sha256 -extfile domains.ext
NOTE:
subjectAltNamefield must contain DNS names / IP addressees of server, used by client during connection establishing.
Copy RootCA.crt (or server.crt if you pinned only the server certificate) to the client.
5. Configure tlshd
Edit /etc/tlshd.conf and set the path to the certificate or trust store that you copied in the previous step. For example:
[authenticate.client]
x509.truststore=/etc/pki/ca-trust/source/anchors/RootCA.crt
NOTE: On Ubuntu, place the file in
/usr/local/share/ca-certificates/and runsudo update-ca-certificates.
Reload the daemon:
sudo systemctl restart tlshd.service
6. Mount the NFS share over TLS
-
Create a mount point:
sudo mkdir -p /mnt/nfs_tls -
Mount the share. Replace
nfs.example.com:/exportwith your export path:sudo mount -o xprtsec=tls nfs.example.com:/export /mnt/nfs_tlsThe
-o xprtsec=tlsoption tells the NFS client to negotiate a kTLS session with the server via tlshd.
To make the mount persistent, add an entry to /etc/fstab:
nfs.example.com:/export /mnt/nfs_tls nfs4 xprtsec=tls 0 0
7. Verify the TLS session
Run ss or nfsstat and check that the connection uses tls:
ss -tna | grep nfs
A line similar to the following confirms that the mount is encrypted:
ESTAB 0 0 192.0.2.100:915 192.0.2.10:2049 tls
8. Troubleshooting
| Symptom | Possible cause | Resolution |
|---|---|---|
mount returns permission denied | The client does not trust the server certificate | Verify that the correct CA / certificate is listed in tlshd.conf and restart tlshd |
mount hangs | tlshd is not running | Start the service with systemctl enable --now tlshd |
9. Additional resources
man nfsman tlshd
Document generated on 2025.11.10 10:07 for v4.5.2~prerelease-1-g37d710094, branch 4.5