Rajdip Khavad Logo
Rajdip Khavad
Back to all articles
DevOps & Windows Server

How to Set Up an SFTP Server on Windows with OpenSSH

Rajdip Khavad•2026-09-08•8 min read

Setting up an SFTP server on Windows can look straightforward until authentication works but the SFTP session fails, users land in the wrong directory, file permissions prevent uploads, or the OpenSSH service refuses to start after a configuration change.

I recently worked through this type of setup using Windows OpenSSH, including SFTP-only access, a restricted directory, NTFS permissions, sshd_config configuration, local connection testing, and troubleshooting an SFTP session that authenticated successfully but did not start correctly.

This guide focuses on the practical parts that matter when setting up a production-style SFTP server on Windows.

Note

The examples use placeholder values such as sftp.example.com, sftpuser, and D:\SFTP. Replace them with values appropriate for your environment.

What Is SFTP?

SFTP stands for SSH File Transfer Protocol.

It provides secure file transfer over an SSH connection and is different from FTP over TLS (FTPS).

A typical SFTP connection looks like:

šŸ“ Architecture Diagram
SFTP Client
    |
    | SSH / SFTP
    | TCP 22
    v
Windows Server
    |
    +-- OpenSSH Server (sshd)
    |
    +-- Authentication
    |
    +-- SFTP restrictions
    |
    +-- NTFS permissions
    |
    +-- SFTP directory

On Windows, OpenSSH provides the SSH server functionality and SFTP capabilities.

Why Use OpenSSH Instead of FTP or FTPS?

If the requirement is specifically SFTP, the server needs an SSH/SFTP implementation.

SFTP is not simply FTP with encryption added.

The protocols are different:

ProtocolTransportTypical Port
FTPFTP21
FTPSFTP + TLS21 / 990
SFTPSSH22

For a Windows server, Win32-OpenSSH is a natural option when SFTP is required and you want the service managed as part of Windows.

Environment Used for This Setup

The troubleshooting workflow behind this article used:

  • Windows Server
  • Win32-OpenSSH
  • TCP port 22
  • Windows local user authentication
  • sshd_config
  • SFTP-only access
  • a restricted/chroot-style directory
  • NTFS permissions
  • local SFTP testing before external testing
  • The exact Windows Server/OpenSSH versions can vary, so always verify that the OpenSSH version installed on your server is supported for the Windows version you're running.

    STEP 01Install OpenSSH Server

    On supported Windows versions, OpenSSH Server can be installed as a Windows capability.

    First check whether it is already installed.

    From an elevated PowerShell session:

    powershell
    Get-WindowsCapability -Online |
        Where-Object Name -like 'OpenSSH*'

    If OpenSSH Server is not installed, install it:

    powershell
    Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0

    Then verify the installation.

    A typical location is:

    text
    C:\Windows\System32\OpenSSH\

    STEP 02Start the OpenSSH Server

    Start the service:

    powershell
    Start-Service sshd

    Configure it to start automatically:

    powershell
    Set-Service -Name sshd -StartupType Automatic

    Check the service:

    powershell
    Get-Service sshd

    You should see the service in a running state.

    If it does not start, don't immediately change multiple configuration settings.

    First validate the configuration.

    STEP 03Validate sshd_config Before Restarting

    The OpenSSH server configuration is normally stored at:

    text
    C:\ProgramData\ssh\sshd_config

    Before restarting the service after making changes, validate the configuration:

    powershell
    sshd -t

    If the command returns an error, fix the configuration before restarting sshd.

    This is one of the most useful troubleshooting steps when working with Windows OpenSSH.

    STEP 04Create an SFTP User

    Create a dedicated Windows user for SFTP instead of using an administrator account.

    For example:

    powershell
    New-LocalUser `
        -Name "sftpuser" `
        -Password (Read-Host -AsSecureString "Password") `
        -Description "SFTP user"

    The exact account-management approach can vary depending on whether your server uses local users or Active Directory.

    The important principle is:

    Note

    Give the SFTP account only the access it needs.

    Avoid using a privileged Windows administrator account for routine file transfers.

    STEP 05Create the SFTP Directory Structure

    A simple structure can be:

    šŸ“ Architecture Diagram
    D:\SFTP\
        |
        +-- sftpuser\
             |
             +-- upload\
             |
             +-- download\

    The directory layout should make the security boundary clear.

    For example:

    šŸ“ Architecture Diagram
    D:\SFTP
    └── sftpuser
        ā”œā”€ā”€ upload
        └── download

    The user should have write access only where required.

    STEP 06Configure NTFS Permissions

    SFTP security is not controlled by sshd_config alone.

    Windows NTFS permissions are equally important.

    For example, the SFTP user may need write permission on:

    text
    D:\SFTP\sftpuser\upload

    but should not automatically receive unrestricted access to:

    text
    D:\

    or other server directories.

    Use icacls to inspect and configure permissions.

    For example:

    powershell
    icacls "D:\SFTP\sftpuser\upload"

    Be careful when modifying permissions recursively.

    A useful rule is:

    šŸ“ Architecture Diagram
    Chroot / SFTP root
            ↓
    Restricted
            ↓
    User-specific writable directory

    STEP 07Configure SFTP-Only Access

    If the user should only transfer files and should not receive an interactive SSH shell, configure an SFTP-only session.

    A typical sshd_config pattern is:

    text
    Subsystem sftp sftp-server.exe
    
    Match User sftpuser
        ChrootDirectory D:/SFTP/sftpuser
        ForceCommand internal-sftp

    The important directives are:

    `ChrootDirectory`

    This restricts the user's SFTP view to the specified directory tree.

    `ForceCommand internal-sftp`

    This forces the account into the SFTP subsystem instead of allowing an interactive shell.

    Important: Chroot Permissions

    One of the easiest mistakes is giving the SFTP user write permission directly to the chroot root.

    A safer structure is:

    šŸ“ Architecture Diagram
    D:\SFTP\sftpuser
            |
            +-- upload
            |
            +-- download

    The chroot root itself should be controlled appropriately, while the user receives write access to the specific child directory where uploads are expected.

    This distinction matters because the chroot directory is part of the security boundary.

    STEP 08Restart OpenSSH After Configuration Changes

    After modifying sshd_config:

    powershell
    sshd -t

    If validation succeeds:

    powershell
    Restart-Service sshd

    Then verify:

    powershell
    Get-Service sshd

    Do not restart the service repeatedly while configuration errors remain unresolved.

    Validate first.

    STEP 09Open TCP Port 22

    SFTP normally uses TCP port 22.

    Check whether the server is listening:

    powershell
    Get-NetTCPConnection -LocalPort 22

    You can also test locally:

    powershell
    Test-NetConnection localhost -Port 22

    If the service is running but port 22 is not reachable, investigate:

  • Windows Firewall
  • cloud/security-group rules
  • network ACLs
  • load balancers
  • NAT
  • external firewall rules
  • Do not troubleshoot external networking until local connectivity works.

    STEP 10Test SFTP Locally First

    Before testing the public hostname, test the SFTP service from the server or another machine on the same network.

    For example:

    powershell
    sftp sftpuser@localhost

    or:

    powershell
    sftp sftpuser@server-hostname

    If the server accepts the connection locally, you have already eliminated several possible causes:

    text
    Internet
    Cloud Firewall
    External Network
    DNS

    You can then focus on the server configuration and permissions.

    STEP 11Test From a Remote Windows PC

    Once local testing works, test from the client machine:

    powershell
    sftp sftpuser@sftp.example.com

    If the server uses a non-standard port:

    powershell
    sftp -P 2222 sftpuser@sftp.example.com

    For the standard SFTP configuration:

    text
    Host: sftp.example.com
    Port: 22
    Username: sftpuser
    Password: ********

    The same credentials can then be used from an SFTP client such as WinSCP or another compatible client.

    # Troubleshooting Common Problems

    Problem 1: Authentication Works but SFTP Session Fails

    If authentication succeeds but the SFTP session immediately disconnects or fails to initialize, investigate what happens after authentication:

  • ChrootDirectory
  • ForceCommand
  • NTFS permissions
  • OpenSSH service configuration
  • SFTP subsystem
  • Windows Event Viewer
  • OpenSSH logs
  • Problem 2: User Is Authenticated but Cannot Enter the SFTP Directory

    Check:

    text
    ChrootDirectory

    Make sure it points to a local directory rather than an unsuitable network/UNC path.

    Then check permissions:

    powershell
    icacls "D:\SFTP\sftpuser"

    and:

    powershell
    icacls "D:\SFTP\sftpuser\upload"

    Problem 3: User Can Connect but Cannot Upload

    Authentication and directory access are separate from write permission.

    Check the writable directory:

    powershell
    icacls "D:\SFTP\sftpuser\upload"

    The user needs appropriate NTFS write permissions.

    Do not solve an upload problem by giving the user full control over the entire drive.

    Problem 4: OpenSSH Service Will Not Start

    Run:

    powershell
    sshd -t

    This should be the first check.

    Then inspect Windows Event Viewer.

    Also verify that the configuration contains a valid SFTP subsystem entry:

    text
    Subsystem sftp sftp-server.exe

    Problem 5: SFTP Connection Hangs

    Check the problem from the bottom up:

    šŸ“ Architecture Diagram
    Is sshd running?
            ↓
    Does sshd -t pass?
            ↓
    Is TCP 22 listening?
            ↓
    Does localhost SFTP work?
            ↓
    Does LAN SFTP work?
            ↓
    Does external TCP 22 work?

    Problem 6: Need More Detailed SFTP Logs

    For difficult issues, temporarily increase OpenSSH logging.

    For example:

    text
    SyslogFacility LOCAL0
    LogLevel DEBUG3

    Use high verbosity for troubleshooting rather than leaving unnecessarily verbose logging enabled permanently.

    Problem 7: SSH Works but SFTP Is Not Restricted

    Remember that:

    text
    SSH access

    and:

    text
    SFTP-only access

    are different configurations.

    If the account should only transfer files, use an appropriate Match User / ForceCommand internal-sftp configuration and verify the actual behavior from a client.

    # A Practical Production Configuration

    A simplified configuration can look like:

    text
    Subsystem sftp sftp-server.exe
    
    Match User sftpuser
        ChrootDirectory D:/SFTP/sftpuser
        ForceCommand internal-sftp

    Directory:

    text
    D:\SFTP\sftpuser\
        upload\
        download\

    Conceptually:

    šŸ“ Architecture Diagram
    sftpuser
       |
       +-- SFTP authentication
       |
       +-- chroot
       |
       +-- internal-sftp
       |
       +-- upload/download directories
       |
       +-- NTFS permissions

    The exact permissions and configuration should be adapted to the server's security requirements.

    # Security Checklist

    Before exposing the SFTP server externally:

  • Use a dedicated SFTP account
  • Avoid administrator accounts
  • Restrict the account to the required directory
  • Use SFTP-only access where appropriate
  • Configure NTFS permissions carefully
  • Use strong authentication
  • Prefer SSH key authentication where appropriate
  • Restrict inbound TCP 22 to known sources where possible
  • Keep OpenSSH supported and updated
  • Monitor authentication and SFTP logs
  • Avoid exposing unnecessary services
  • Test the account's actual filesystem boundaries
  • Validate sshd_config before restarting the service
  • Password vs SSH Key Authentication

    Password authentication is convenient, but SSH public-key authentication can provide stronger operational control for automated integrations.

    A typical key-based flow is:

    šŸ“ Architecture Diagram
    Client
      |
      +-- Private Key
      |
      v
    SFTP Server
      |
      +-- Authorized Public Key
      |
      v
    Authentication

    Never copy a private key onto the server.

    The server only needs the corresponding public key.

    For Windows OpenSSH, authorized-key storage and permissions depend on whether the account is an administrator or standard user.

    # Why Local Testing Saved Time

    One of the most useful lessons from troubleshooting an SFTP server is to avoid changing multiple variables simultaneously.

    If:

    text
    sftp localhost

    fails, there is little value in troubleshooting DNS or an external firewall yet.

    If:

    text
    sftp localhost

    works but:

    text
    sftp sftp.example.com

    fails, the problem is more likely to be outside the local OpenSSH/SFTP configuration.

    This simple separation can save significant troubleshooting time.

    # Recommended Troubleshooting Checklist

    When an SFTP deployment fails, work through this list:

    text
    [ ] OpenSSH Server installed
    [ ] sshd service running
    [ ] sshd -t succeeds
    [ ] TCP 22 listening
    [ ] Windows Firewall allows TCP 22
    [ ] SFTP subsystem configured
    [ ] User authentication works
    [ ] Chroot directory exists
    [ ] Chroot permissions are correct
    [ ] Writable directory exists
    [ ] NTFS permissions are correct
    [ ] ForceCommand is correct
    [ ] Local SFTP works
    [ ] Remote SFTP works
    [ ] Event Viewer checked
    [ ] OpenSSH logs checked if required

    Conclusion

    A Windows SFTP server is not just an OpenSSH installation.

    A reliable setup requires several layers to work together:

    text
    OpenSSH
       +
    sshd_config
       +
    Authentication
       +
    Chroot / SFTP restrictions
       +
    NTFS permissions
       +
    Windows Firewall
       +
    Network connectivity

    The most important troubleshooting principle is to isolate these layers one at a time.

    Start locally, validate sshd_config before restarting the service, verify authentication separately from filesystem permissions, and only move to external networking once the local SFTP workflow works.

    That approach makes Windows SFTP deployments much easier to troubleshoot and maintain.

    Official References

  • Microsoft Learn — OpenSSH Server Configuration for Windows
  • Microsoft Learn — Troubleshoot Common SFTP Issues Using OpenSSH
  • OpenSSH documentation
  • Proven Engineering

    Need enterprise architecture consulting?

    Explore our real-world case studies detailing production migrations, performance scaling, and high-throughput gateways.

    View Case Studies