Setting up an SFTP chroot directory directly on an NFS share is not supported by OpenSSH because the chroot mechanism requires strict ownership and permission checks that NFS clients often cannot guarantee atomically. To achieve a secure, isolated environment for file transfers, you must use a local filesystem for the chroot root while mounting the NFS share inside it as a writable subdirectory. This approach ensures the integrity of the jail while allowing data persistence across reboots via network storage.
Why NFS Fails for Chroot Roots
The
ChrootDirectory directive in
/etc/ssh/sshd_config imposes specific requirements on the target directory. The most critical constraint is that the chroot path must be owned by the root user (
root:root) and must not be writable by any other user or group. When you attempt to set the chroot root to an NFS mount point, several issues arise. First, NFS exports often map UIDs and GIDs differently than the local server expects, leading to permission mismatches where the SSH daemon cannot verify ownership correctly. Second, NFS does not always support the strict attribute caching required for immediate consistency checks, which can cause the SSH service to reject the connection with "Permission denied" errors even if the permissions appear correct locally. Therefore, the chroot root itself must reside on a local disk partition such as
/var/sftp.
Preparing the Local Chroot Environment
Begin by creating a dedicated directory on your local filesystem to serve as the chroot root. This directory will act as the base of the jail for the SFTP user. You must ensure that this directory is owned by root and has no write permissions for group or others. Execute the following commands to create the structure:
sudo mkdir -p /var/sftp/uploads
sudo chown root:root /var/sftp
sudo chmod 755 /var/sftp
Next, create the subdirectories where the user will actually interact. For example, create an
uploads directory inside the chroot. This inner directory should be owned by the specific SFTP user, not root, so they have write access within their jailed environment.
sudo chown sftpuser:sftpuser /var/sftp/uploads
sudo chmod 755 /var/sftp/uploads
This structure satisfies the SSH requirement that the chroot root (
/var/sftp) is locked down, while the functional area (
/var/sftp/uploads) is accessible to the user.
Configuring the SFTP Server
Edit the SSH daemon configuration file located at
/etc/ssh/sshd_config. Add a new block specifically for your SFTP user to enforce the chroot. Use the
Match User directive to apply settings only to the relevant account. Inside this block, specify the subsystem as
sftp, set the
ChrootDirectory to the local path created earlier, and disable unnecessary features like port forwarding or X11 forwarding to enhance security.
Match User sftpuser
ForceCommand internal-sftp
ChrootDirectory /var/sftp
AllowTcpForwarding no
X11Forwarding no
PermitTunnel no
After saving the configuration, restart the SSH service to apply the changes. On Debian-based systems, use
sudo systemctl restart ssh. If you encounter connection issues, check the system logs using
journalctl -u ssh for detailed error messages. For further troubleshooting on connection errors, refer to our guide on
How to allow Linux PAM Authentication for non-Local users if you are integrating with external authentication sources.
Mounting the NFS Share
With the chroot environment secured on local storage, you can now mount the NFS share inside the user's writable directory. Edit
/etc/fstab to add a persistent mount entry. Replace the placeholders with your actual NFS server IP, export path, and credentials.
nfs-server.example.com:/exports/data /var/sftp/uploads nfs defaults,_netdev,noatime,rw 0 0
The
_netdev flag ensures the system waits for network availability before attempting to mount during boot. The
noatime option improves performance by reducing metadata writes. After adding this line, run
sudo mount -a to test the mount immediately. Verify that the NFS share is mounted correctly and that the user can write files to it. Since the mount point is inside the chroot, the user will see the NFS contents as part of their local directory structure.
Security Considerations and Best Practices
Always audit the permissions of the chroot root directory. Any deviation from
root:root ownership or world-writable permissions will break the chroot functionality. Additionally, consider implementing key-based authentication to avoid password exposure over the network. Setting up SSH host RSA keys for passwordless login enhances security significantly. See
SSH Host RSA Key Configuration for Passwordless SFTP for details on generating and deploying these keys securely. Regularly monitor disk usage on both the local chroot partition and the NFS server to prevent storage exhaustion, which can halt file transfers unexpectedly.
Frequently Asked Questions
Can I use a symbolic link for the chroot directory?
No, OpenSSH does not follow symbolic links when resolving the
ChrootDirectory path. The path specified must be the absolute physical path to a directory on a local filesystem. Using a symlink will result in a "bad ownership or modes" error upon connection.
What happens if the NFS server goes offline?
If the NFS share becomes unavailable, the user may experience timeouts or inability to write files depending on the NFS client timeout settings. The
_netdev flag in fstab helps during boot, but runtime failures require monitoring. You might need to implement scripts to unmount or remount shares automatically if connectivity is lost.
How do I grant write access to the NFS mount?
Write access is controlled by two layers: the NFS export permissions on the server side and the local filesystem permissions on the client side. Ensure the NFS export allows read-write access for the UID/GID mapped to your SFTP user. Locally, ensure the mount point directory is owned by that user and has appropriate write permissions (e.g.,
chmod 755 or
775).
Can I chroot multiple users to the same directory?
Yes, you can configure multiple
Match User blocks pointing to the same
ChrootDirectory. However, each user must have distinct ownership over the subdirectories inside the chroot to maintain isolation. If all users share the same inner directories, they can overwrite each other's files unless additional ACLs are configured.
Is there a performance penalty for using a local chroot with NFS mounts?
There is minimal overhead for the chroot mechanism itself. The primary performance factor is the NFS protocol latency and bandwidth. Using options like
noatime and tuning NFS read/write buffers can mitigate slowdowns. For large file transfers, ensure your network infrastructure supports the required throughput without congestion.