Setting Up SFTP on a Linux Machine with Multiple Users

Abstract: Configure OpenSSH to chroot multiple users into isolated directories using internal-sftp and group-based matching.

Created: 2026-10-07 by

To configure SFTP for multiple users on a Linux machine, you must modify the SSH daemon configuration to use the internal-sftp subsystem and implement a chroot jail. This setup restricts each user to their home directory while allowing secure file transfers via the SFTP protocol without granting shell access or system-wide permissions.

Understanding the Security Model

When setting up SFTP for multiple users, the primary goal is often isolation. You want User A to see only their files, and User B to see only theirs, without the ability to traverse upward to the root filesystem or access other users' data. The standard OpenSSH server allows this through the ChrootDirectory directive combined with the Subsystem sftp internal-sftp command. This approach is superior to running separate SFTP servers because it leverages the existing, highly secure SSH infrastructure. It also simplifies management since user authentication is handled by the operating system's standard mechanisms. For environments requiring more complex authentication sources, such as LDAP or Active Directory, you might need to look into How to allow Linux PAM Authentication for non-Local users. However, for standard local Linux accounts, the built-in methods are robust and sufficient.

Preparing the Directory Structure

Before editing configuration files, you must create the necessary directory hierarchy. The ChrootDirectory requires specific ownership and permission settings to ensure security. If these are incorrect, SSH will refuse to start the service due to perceived security risks. First, create a base directory that will serve as the root for your chrooted users. For example, you might use /srv/sftp. This directory must be owned by root and not writable by any other user or group.
sudo mkdir -p /srv/sftp
sudo chown root:root /srv/sftp
sudo chmod 755 /srv/sftp
Next, create individual directories for each user inside this base directory. These subdirectories will be the actual homes where users can write files. Crucially, these subdirectories must be owned by the respective users.
sudo mkdir -p /srv/sftp/user1/data
sudo mkdir -p /srv/sftp/user2/data

sudo chown user1:user1 /srv/sftp/user1
sudo chown user2:user2 /srv/sftp/user2
Note that the parent directory of the chroot (/srv/sftp) must remain owned by root. Only the immediate child directories (like /srv/sftp/user1) should be owned by the specific user. This structure ensures that when the user logs in, they are effectively "chrooted" to their own directory, seeing it as the root of their file system.

Configuring the SSH Daemon

The core configuration happens in /etc/ssh/sshd_config. You need to locate the existing Subsystem sftp line and modify it, or add new configuration blocks at the end of the file. Replace or comment out the default subsystem line:
# Subsystem sftp /usr/lib/openssh/sftp-server
Then, add the following block. This configuration uses Match groups to apply specific settings only to users belonging to the sftponly group. This is a clean way to manage multiple users without creating duplicate global configurations.
Match Group sftponly
    ChrootDirectory /srv/sftp/%u
    ForceCommand internal-sftp
    AllowTcpForwarding no
    X11Forwarding no
Here, %u is a placeholder that gets replaced by the username at runtime. So, for user1, the chroot becomes /srv/sftp/user1. The ForceCommand internal-sftp ensures that even if a user tries to request a shell session, they are forced into the SFTP subsystem, preventing accidental or malicious shell access. Disabling TCP forwarding and X11 forwarding reduces the attack surface. After making these changes, restart the SSH service to apply the new configuration:
sudo systemctl restart sshd

Creating Users and Assigning Groups

Now that the server is configured, you need to create the users and assign them to the sftponly group. When creating the users, you can set their home directories to the paths defined earlier, but note that for chrooted users, the effective home directory from the OS perspective might differ from what they see.
sudo groupadd sftponly
sudo useradd -m -g sftponly -d /srv/sftp/user1 user1
sudo passwd user1
Repeat this process for each additional user. Ensure that the home directory specified in useradd matches the path structure you created in the previous step. If a user already exists, you can add them to the group using:
sudo usermod -aG sftponly existinguser
It is critical that these users do not have sudo privileges or membership in groups that grant broad system access, as this could potentially allow them to escape the chroot environment if there are vulnerabilities in the SSH implementation.

Testing the Configuration

Verification is the final step. Use an SFTP client to connect as one of the new users. From a terminal, you can test connectivity with:
sftp user1@your_server_ip
Once connected, try listing the root directory:
ls -la
You should see the contents of /srv/sftp/user1, which likely includes the data folder you created. Try changing directory to / or attempting to go up with cd ... In a properly configured chroot, these actions should either fail or simply keep you within your designated directory boundary. You cannot navigate outside the ChrootDirectory. For more information on managing specific SFTP commands like renaming files with wildcards, refer to SFTP Rename (mv) with Wildcard. Additionally, if you encounter connection issues during setup, such as the client hanging on connecting, check out SFTP Connection Stuck: Troubleshooting 'ls0[Connecting...]' Issues.

Frequently Asked Questions

Can users upload files directly to the root of their chroot?

No, because the chroot directory itself is owned by root and not writable by the user. Users can only write to subdirectories within their chroot that they own, such as the data folder created in the preparation step. This prevents privilege escalation attempts.

What happens if I forget to set the correct permissions on the chroot directory?

The SSH daemon will reject the connection with an error message indicating that the chroot directory is too open. OpenSSH requires that the chroot path and all its parent directories are owned by root and not writable by others. Fixing the ownership and permissions immediately resolves this.

Can I use this setup for FTP instead of SFTP?

No, this configuration specifically uses the SFTP subsystem integrated into SSH. Standard FTP does not support chroot jails in the same secure manner within the SSH daemon. You would need a dedicated FTP server like vsftpd for plain FTP connections.

How do I troubleshoot if a user cannot log in at all?

Check the SSH logs at /var/log/auth.log or /var/log/secure for detailed error messages. Common issues include incorrect group membership, wrong password, or SELinux/AppArmor blocking the access. Also verify that the user shell is not set to a restricted shell that conflicts with SFTP.

Is it possible to give some users shell access while keeping others on SFTP only?

Yes, by not adding those specific users to the sftponly group, they will fall back to the default SSH behavior. The Match Group directive only applies settings to members of that group, leaving other users unaffected.

Latest News

How to Display Output of xterm Command in Terminal Screen using Cron

Resolve the inability to display xterm output in a terminal screen from cron by redirecting logs or using wall instead of insecure X11 workarounds.

Read More
Expose Local Server on VPS Preserving Real Client IPs (OS Level)

Resolve VPS logging showing only gateway IPs by configuring reverse proxies to forward real client addresses via X-Forwarded-For headers.

Read More
How to Clear Recent Files History in Linux without Deleting Actual Files?

Clear recent files history in Linux by deleting ~/.local/share/recently-used.xbel without removing the actual files.

Read More
Best HDD Copy Strategy: Manually Syncing and Rewriting Scratch

Resolve data drift between two 4TB hard drives by using rsync with the --delete flag to manually sync and rewrite scratch data for an exact mirror.

Read More
Understanding Bash Prompt Abbreviations: An Overview

Resolve repetitive typing errors by creating and persisting Bash aliases in the .bashrc file for improved command-line efficiency.

Read More
Free Tools and Methods to Log Real-Time Performance Details in Task Manager

Log real-time CPU and memory metrics to CSV files using Windows Performance Monitor Data Collector Sets to troubleshoot system slowness.

Read More
Contact Qatar Airways Customer Service: Phone Number, Help Center, and More

Resolve urgent Qatar Airways reservation issues like flight changes and baggage claims using the US phone number +1801-855-5905 or online self-service tools.

Read More
Windows 11: Alt Codes Displaying Wrong Characters - Solutions

Resolve Windows 11 Alt codes showing wrong characters by verifying the US keyboard layout and enabling Num Lock.

Read More
Run Programs with Elevated Privileges: A Comprehensive Guide

Eliminates the need to type sudo for frequent administrative tasks by configuring .bashrc aliases or functions.

Read More
Dynamically Changing Dates in Excel Formulas Using Cells

Eliminate manual date updates in Excel by using cell references to create dynamic formulas that automatically adjust calculations when input dates change.

Read More
Granting Edit Access to a Specific Excel Sheet in an Office 365 User Email ID-Based Login

Excel Online lacks native sheet-level permissions, so users must split workbooks or use worksheet protection to isolate edit access for specific tabs.

Read More
Creating Network Load on Local Wi-Fi from One PC

Generate sustained Wi-Fi bandwidth load from a single PC using a VM SFTP server to test router stability and throughput.

Read More
Changing the Default Editor for Batch Files in Windows 11's File Explorer

Resolve the issue of batch files opening in Notepad by changing the default editor to a preferred application like VS Code.

Read More
Gain WiFi Connection Minutes Before Losing it by Changing MAC Address

Bypass MAC address filtering to restore WiFi connectivity temporarily when a device is blocked by network administrators.

Read More
Photos Folders Turned Black: Troubleshooting Picture Applications on Windows

Resolve black screens in Windows Photos by resetting the app, updating graphics drivers, and repairing system files.

Read More
Troubleshooting High CPU Temperature Values: A Step-by-Step Guide

Resolve high CPU temperatures and thermal throttling by monitoring with Speedfan, cleaning dust from cooling components, and replacing degraded thermal paste.

Read More
Make cURL establish TLS connection with CA unknown

Resolve cURL TLS connection failures with unknown or self-signed certificates by using the --insecure flag to bypass CA validation.

Read More
Troubleshooting Incorrect Network Metrics Values in Grafana, Prometheus, InfluxDB, and Telegraf

Fix incorrect network metrics in Grafana, Prometheus, InfluxDB, and Telegraf by verifying interface selection, resolving unit mismatches, and handling counter resets.

Read More
Start Another Terminal Window (cmd.exe) Windows Repair/Troubleshoot

Provides step-by-step instructions to access the Windows Command Prompt via bootable media for advanced system repair and troubleshooting.

Read More
Thinkpad P1 Gen 6: Sudden Thunderbolt 3 Dock USB-C Charging Stopped Working

Resolve sudden Thunderbolt 3 dock USB-C charging and internet failure on ThinkPad P1 Gen 6 by updating firmware, resetting the dock, and adjusting power settings.

Read More
ASUS Windows 11 Laptop: Internet Connection Issue with Hotspot

Resolve ASUS Windows 11 laptop spinning wheel issue when connecting to mobile hotspot by resetting network stack, disabling IPv6, and adjusting power settings.

Read More
Developing iOS Project with Firebase: Logging in and Sending Push Notifications

Integrates Firebase to enable secure user authentication and push notifications in iOS applications.

Read More
Troubleshooting Bash Script with Suspected Issues of Spaces, Dashes, Filenames and Quoting

Resolve Bash script failures caused by word splitting, globbing, and special characters in filenames by applying proper quoting techniques.

Read More
Populating OneDrive Folder for Local Backup without Affecting Remote Files

Prevent OneDrive from deleting remote files during Windows reinstallation by unlinking the account or using symbolic links to isolate local data.

Read More
Force First Frame as Keyframe Without Re-encoding: A Quick Solution

Resolve inaccurate seeking and playback glitches by re-encoding video to ensure the first frame is a valid keyframe.

Read More
Find Information in Database Using WSL (Ubuntu) on Windows-10

Resolve database connection issues from WSL Ubuntu on Windows 10 by configuring client tools and network access to query remote or local servers.

Read More
Configuring a New Router with Different Networks: One Family, One Guest

Resolve IP conflicts and isolate guest traffic by configuring a second router with a distinct subnet via its WAN port.

Read More
Quickly Open Multiple Stock Websites with a Single Command

Solve the problem of manually opening multiple stock research websites by creating a single command to launch them simultaneously on Windows, macOS, or Linux.

Read More
Improved Adobe Acrobat Search Experience: Access Advanced Search with Ease

Access advanced search filters like case sensitivity and regex in Adobe Acrobat by clicking More Options in the Find bar.

Read More
Port Forwarding VM via OpenVPN: A Comprehensive Guide

Configure OpenVPN server and iptables to forward specific ports from VPN clients to a virtual machine's internal IP address.

Read More
Understanding Partitions in the 1980s: A Look Back at MS-DOS and Master Boot Record

Explains how the Master Boot Record and partition table enabled MS-DOS to manage multiple disk volumes on a single physical drive.

Read More
Windows 10 Enterprise: Keyboard Not Detected in Managed Organization with Admin Privileges

Resolve Windows 10 Enterprise keyboard detection failures caused by Group Policy restrictions, driver corruption, or USB enumeration errors.

Read More
Can't Find x86_64 Versions of Applications on MacOS arm64 (M1)

Resolve missing x86_64 app issues on M1 Macs by installing Rosetta 2 and reinstalling apps as universal binaries.

Read More
How to Hide Installation Source for an Android App

Manage Android app installation source visibility by using USB transfers or file managers to reduce browser traces and isolate data via work profiles.

Read More
Connecting Momentus 4200.2 ST9808210A Hard Drive via USB Cable

Resolve inability to access Seagate Momentus 4200.2 ST9808210A hard drive by connecting it via USB using a compatible SATA-to-USB adapter and configuring the disk in Windows.

Read More