Halloween DealsAmazon USHalloween week deals: useful picks before month-endAmazon US: current deals, useful picks and tech finds.Check DealsWindows FixRecommendedWindows errors stealing your time? Find the fix fastScan stability, cleanup and performance issues.Fix NowHalloween DealsAmazon USOctober picks are moving - compare before checkoutAmazon US: current deals, useful picks and tech finds.See Picks×
Skip to content
VGSources
Blog

How to Enable SFTP Without Shell Access on a Linux Server (OpenSSH Guide)

Configure OpenSSH so a Linux user can transfer files over SFTP without receiving a shell, running commands or using forwarding, with optional per-user chroot isolation.
Length11 min Posted Quest giverVGSources Team

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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.

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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
# /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.

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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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 AuthorizedKeysFile location 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 upload for 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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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

  1. From a separate client, connect with sftp alice@server.
  2. Run pwd and ls. In a chrooted setup, the visible root should be the restricted tree, and the writable location should be the child directory such as upload.
  3. Upload a harmless test file into upload, then download it and remove it. This confirms both read and write permissions.
  4. 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.
  5. Attempt a command such as ssh alice@server id. It must not execute id; the forced internal SFTP server handles the request instead.
  6. 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.
  7. 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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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/%u prevents 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 no makes 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.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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.

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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The 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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Result 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.

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.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

More quests from Patch Notes

  1. How to Set Up a RedM (RDR2) Server in 2026: License Key, txAdmin and server.cfg, Step by StepBlog11min
  2. Best RedM (RDR2) Server Hosting in 2026: Comparing Four Hosts on Slots, Memory and PriceBlog10min
  3. How to Host a Mindustry Server in 2026: server-release.jar, Port 6567 and the Commands That MatterBlog7min
Recommended PC Tool
Recommended PC Tool
Crashes, No Sound, or Screen Glitches?Free driver scan
PC Slower Than It Used to Be?Free scan - under a minute

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.