What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Use OpenSSH’s ForceCommand internal-sftp in a Match User or Match Group block. It forces the selected account into the in-process SFTP server for every SSH session, so the account can upload and download files but cannot obtain an interactive shell or run arbitrary commands. Add ChrootDirectory when the account must see only a restricted directory tree.
Need a server to try this on? Antihost offers Linux VPS plans with NVMe storage, full root access and a 14-day free trial.
The configuration that creates an SFTP-only account
The essential restriction is ForceCommand internal-sftp. It applies to shell requests, command requests and subsystem requests, preventing a matched user from selecting a shell command, legacy SCP operation or another SSH subsystem. A global SFTP subsystem definition makes the service available, while the Match block limits the restriction to the intended accounts.
As an Amazon Associate I earn from qualifying purchases.
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Scan for outdated or missing drivers - takes under a minuteDriver Scan →# /etc/ssh/sshd_config
Subsystem sftp internal-sftp
Match Group sftpusers
ChrootDirectory /srv/sftp/%u
ForceCommand internal-sftp
DisableForwarding yes
PermitTTY no
In this example, every member of sftpusers is confined to a per-user path such as /srv/sftp/alice. Remove the ChrootDirectory line if you want SFTP-only access without filesystem chrooting. Keep the Match block at the end of the file, or otherwise verify exactly which later directives are in its scope.
What each OpenSSH control does
ForceCommand internal-sftp
This is the control that removes shell and arbitrary command access. OpenSSH starts its in-process SFTP server instead of the command requested by the client. Because the server runs inside sshd, it does not need a shell binary, shared libraries or ordinary device nodes inside a chroot. An account may still have a normal home directory and Unix permissions outside a chroot, but it cannot use an SSH session to execute commands when the forced command is active.
#1 Best Overall
Subsystem sftp internal-sftp
The Subsystem line defines how ordinary SFTP subsystem requests are handled globally. On many installations an equivalent line already exists; edit that line rather than adding conflicting definitions. The forced command remains the important restriction because it also handles attempts to request a shell or a command.
ChrootDirectory
Chrooting changes the filesystem view after authentication. With ChrootDirectory /srv/sftp/%u, user alice sees that directory as / inside the SFTP session. The token %u expands to the authenticated username, allowing one root-owned tree per account. Chrooting is optional for shell restriction; without it, the user’s SFTP client sees whatever paths Unix permissions allow.
DisableForwarding yes and PermitTTY no
DisableForwarding yes prevents TCP, agent, X11 and stream-local forwarding facilities for the matched account. PermitTTY no rejects allocation of a terminal. These settings reduce ways an SFTP credential could be repurposed, but they do not replace ForceCommand.
Choose between SFTP-only and chrooted SFTP-only access
| Design | Shell and command access | Filesystem visibility | Setup effort | Isolation trade-off |
|---|---|---|---|---|
| SFTP-only, no chroot | ForceCommand internal-sftp blocks interactive shells and arbitrary commands. |
Normal filesystem view, filtered by Unix ownership and mode permissions. | Lower: no chroot ownership layout is required. | Less isolation if a file-transfer account can read more of the host filesystem than intended. |
| Chrooted SFTP-only | Same command restriction, normally combined with DisableForwarding yes and PermitTTY no. |
The account sees only its chroot tree; a writable child directory is used for uploads. | Higher: every chroot path component must pass ownership and mode checks. | A dedicated hierarchy, and where appropriate nodev, noexec and nosuid mount options, can reduce exposure and storage blast radius. |
Use the first design for trusted internal transfer accounts that already have carefully limited Unix permissions. Use the second for external parties, automation credentials or any account that should not discover the rest of the server’s directory tree. ANSSI guidance recommends a dedicated hierarchy or partition for users and groups dedicated to SFTP.
Plan the account before changing SSH
- Pick a dedicated group. A group makes the policy easy to audit and lets you add or remove accounts without editing the SSH configuration for each one.
- Decide authentication. Public-key authentication is usually preferable for unattended transfer. Install the key through the distribution’s normal
AuthorizedKeysFilelocation or another supported authentication method. - Decide the writable area. The chroot root itself must not be writable by the user. Create a child such as
uploadfor files. - Keep an administrative path open. Retain an existing root or administrator SSH session while validating the new configuration and reloading the daemon.
- Check the installed version. Directive defaults and service names differ between OpenSSH and Linux distribution releases. Read the local
sshd_config(5)manual before production rollout.
Step-by-step: create a chrooted SFTP-only user
1. Create a dedicated group and account
sudo groupadd sftpusers
sudo useradd -g sftpusers -s /usr/sbin/nologin alice
The /usr/sbin/nologin shell is defense in depth. It makes an ordinary login attempt fail, but it is not the mechanism that creates the SFTP-only policy and it does not chroot the account. ForceCommand internal-sftp is still required. If your distribution uses a different nologin path, use the path installed there. You may lock password authentication for a key-only account with the distribution’s supported account-management command, provided another approved authentication method is configured.
2. Build the root-owned chroot hierarchy
sudo mkdir -p /srv/sftp/alice/upload
sudo chown root:root /srv/sftp
sudo chmod 755 /srv/sftp
sudo chown root:root /srv/sftp/alice
sudo chmod 755 /srv/sftp/alice
sudo chown alice:sftpusers /srv/sftp/alice/upload
sudo chmod 750 /srv/sftp/alice/upload
Every component from the filesystem root through /srv/sftp/alice must be owned by root and must not be writable by the group or by others. The upload directory is outside the chroot root’s ownership requirement, so it can belong to alice or to a collaboration group. Adjust its group and mode to your sharing policy, while keeping the chroot boundary itself root-owned and non-writable.
Recommended Free Tools
Inspect the complete path rather than checking only the final directory:
namei -l /srv/sftp/alice
The output should show root ownership and suitable permissions for each path component. If a parent such as /srv is writable by an untrusted group, sshd can reject the chroot even when /srv/sftp/alice looks correct.
3. Install the public key or other approved credential
Place the user’s public key in the normal AuthorizedKeysFile location used by your distribution, then apply the ownership and mode requirements documented for that location. Do not put the key inside the chroot unless your local configuration explicitly uses a chroot-relative key file. Authentication occurs before the chroot is entered, so the conventional host-level key path is normally simpler.
Confirm the key belongs to the intended account and remove obsolete keys. A forced SFTP command limits what a stolen key can do through SSH, but it does not make the credential harmless: the attacker could still read or alter every file that the account can access through SFTP.
4. Add a narrowly scoped Match block
Edit /etc/ssh/sshd_config. Keep one global SFTP subsystem definition, then place the account policy in a group or user match. A group policy is convenient when all members need the same jail:
Subsystem sftp internal-sftp
Match Group sftpusers
ChrootDirectory /srv/sftp/%u
ForceCommand internal-sftp
DisableForwarding yes
PermitTTY no
For one account instead, use Match User alice. Be careful with scope: a Match block changes how subsequent directives are interpreted. Putting it at the end avoids accidentally applying SFTP restrictions to unrelated accounts. If your file already contains a conditional block, review where it ends and how OpenSSH parses the following lines.
5. Validate syntax before reloading
sudo sshd -t
No output normally means the syntax check passed. Treat any error as a deployment failure; correct it before touching the running daemon. A syntax check does not prove that the intended user matches the intended block, so inspect the effective configuration too:
sudo sshd -T -C user=alice,host=example,addr=192.0.2.10
Check that the result includes the expected forcecommand internal-sftp, chroot path, forwarding policy and TTY policy. Replace the example host and address with values representative of the connection you are testing, because conditional rules can depend on more than the username.
6. Reload the daemon without losing administrative access
Use the service manager for your distribution after sshd -t succeeds. Common systems use a reload operation rather than a full stop and start, but the exact service name can be ssh or sshd. Keep your existing administrator session open until a separate client has completed both positive and negative tests. If the reload fails, the old daemon may continue running; investigate the service manager’s error output instead of repeatedly retrying.
7. Test SFTP, shell, forwarding and file permissions
- From a separate client, connect with
sftp alice@server. - Run
pwdandls. In a chrooted setup, the visible root should be the restricted tree, and the writable location should be the child directory such asupload. - Upload a harmless test file into
upload, then download it and remove it. This confirms both read and write permissions. - Attempt
ssh alice@server. It must not provide an interactive shell. Depending on the client, it may close immediately or report that the forced SFTP service is not a terminal session. - Attempt a command such as
ssh alice@server id. It must not executeid; the forced internal SFTP server handles the request instead. - If legacy SCP is part of your compatibility test, verify that it cannot use the account to run a remote shell command. Use SFTP for supported transfers.
- Confirm that forwarding and terminal allocation are rejected when the client requests them.
Run these tests with the same username, source address and host pattern that production clients use. A user outside the matched group should retain the normal administrator policy; testing only the restricted account does not prove that other SSH users are unaffected.
Filesystem details that commonly decide whether chroot works
The chroot root cannot be the upload directory
OpenSSH checks ownership and writability of the chroot path. If alice owns /srv/sftp/alice and can write directly there, sshd normally rejects the connection with a bad-ownership error. Keep the root at root:root with a mode such as 0755, then grant write access only to /srv/sftp/alice/upload.
Internal SFTP does not need a copied operating system
Because internal-sftp runs inside the SSH daemon, a basic transfer chroot does not require a shell, dynamic libraries or ordinary device nodes within the jail. This is one reason it is simpler and less fragile than configuring an external SFTP server binary inside the chroot.
Rank #4
Logging can require a socket
If internal-SFTP logging is enabled, the platform may expect a syslog socket such as /dev/log to exist inside the chroot. Requirements vary by operating system and logging configuration. Investigate the system’s SSH and syslog documentation rather than creating device nodes by guesswork.
Mount options are an additional, not automatic, control
For a dedicated SFTP filesystem, administrators may consider nodev, noexec and nosuid mount options where they fit the application. They do not replace Unix ownership, SSH restrictions or backups, and they can break workloads that genuinely need the affected behavior. Evaluate them with the storage and operations teams.
Hardening beyond the basic forced command
- Use one group per policy. Separate external users, internal automation and administrators when their directory or forwarding requirements differ.
- Use per-user paths.
/srv/sftp/%uprevents one account’s files from being placed directly in another account’s root. Review group permissions if users must exchange files. - Keep forwarding disabled. Verify the effective value with
sshd -T -C; a later or more specific match can override assumptions. - Disable terminal allocation.
PermitTTY nomakes the account’s intended use explicit and removes an unnecessary interface. - Limit key distribution. Rotate keys, remove departed users promptly and record which automation job owns each credential.
- Monitor transfer activity. SFTP-only does not mean read-only. File names, contents and upload volume remain within the account’s granted permissions and should be covered by the normal audit and malware-scanning process.
- Protect the host administrator path. Never test a risky SSH edit by closing the only working administrative session.
Troubleshooting by symptom
“Bad ownership or modes for chroot directory”
Run namei -l /srv/sftp/alice and inspect every component. Change the chroot path and its parents to root ownership and remove group/other write permission. Keep the user-owned upload directory below the chroot, not at the chroot root itself. Re-run sshd -t, reload and test again.
SFTP connects, but the directory is empty or uploads fail
An empty listing can be correct when the chroot contains only an upload directory and no files. If uploads fail, check the child directory’s owner, group, mode and available space. The user needs write permission on the child, while the chroot root must remain non-writable. Test from inside SFTP with pwd, ls -la and a small file transfer.
The Tool Desk
Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →SFTP works, but SSH still opens a shell
First confirm that the account is actually in the selected group: check the group database and start a fresh connection. Then inspect the effective policy:
sudo sshd -T -C user=alice,host=example,addr=192.0.2.10 | grep -E 'forcecommand|chrootdirectory|disableforwarding|permittty'
If forcecommand is absent or points elsewhere, the Match block is not being applied, is misspelled, or is shadowed by conditional configuration. Ensure ForceCommand internal-sftp is present and that the block’s scope is correct. A nologin shell alone cannot provide this guarantee.
Best Value
Logging errors appear after chrooting
Review whether your operating system’s syslog service exposes /dev/log inside the jail when internal-SFTP logging is enabled. The required socket and ownership are platform-specific. If transfer works but logs do not, fix the logging path deliberately rather than weakening the chroot.
The configuration reload fails
Run sudo sshd -t and read the exact line number. Check for duplicate or malformed Subsystem lines, unsupported directives in the installed OpenSSH version, and a Match block that starts earlier than intended. Keep the existing administrative connection open while correcting the file. Only reload after the syntax check succeeds.
Do these 3 things before closing this tab:
1Clear out junk files and repair common Windows errors2Fix the driver behind crashes, sound loss and screen glitches3Repair Windows errors before they cause bigger problemsThe wrong users are restricted
Use sshd -T -C for both a restricted and an unrestricted test account. Review group membership, host and address conditions, and the location of the Match block. A broad group name or a misplaced block can silently change access for ordinary administrators, so test both sides of the boundary after every policy edit.
Operational limits and maintenance
An SFTP-only account is constrained at the SSH protocol layer, not magically transformed into a complete security boundary. Unix permissions still determine which files it can read or overwrite. A compromised account can perform every permitted transfer, consume storage and potentially upload malicious content for another process to consume. Apply quotas, monitoring, malware scanning and backup policy as appropriate for the server’s role.
When adding a user, repeat the same sequence: create the account, create a root-owned chroot, add a writable child, install and verify the credential, check the effective SSH configuration, then test from an independent client. When removing one, revoke its keys and group membership, decide whether its files must be retained, and remove or archive the chroot according to your retention policy.
Keep a record of the OpenSSH version and distribution release used to validate the policy. Defaults, service names, key-file locations and supported directives can differ between releases. Re-run the negative tests after upgrades, configuration-management changes and any modification to group membership.
Windows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallCrashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minuteResult you should expect
With the example policy applied correctly, sftp alice@server opens a transfer session rooted at /srv/sftp/alice, and upload is writable by Alice. ssh alice@server does not yield a shell, arbitrary commands are not executed, terminal allocation is denied and forwarding is disabled. Other accounts are unaffected unless they also match the same Match conditions. That combination—forced internal SFTP, a root-owned chroot when needed, and verified configuration scope—is the standard OpenSSH method for file transfer without shell access.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




