Configuration Reference

Overview

All Stylus SFTP Server configuration files are XML documents sharing the namespace http://www.xmlpipelineserver.com/sftp/. They are parsed with StAX (pull-parser) with external entity resolution and DTD processing disabled for security.

Path Macros

Several path macros are available throughout all configuration files. They are resolved at runtime before paths are used.

Macro Description
${STYLUS_SFTPSERVER_HOME} Install root directory (read-only binaries)
${STYLUS_SFTPSERVER_DATA} Data directory (writable: conf, db, homes, logs)
${username} Current session user's login name
${env.VAR} Operating system environment variable VAR
Note Relative paths in configuration files resolve against ${STYLUS_SFTPSERVER_HOME} (the install root).

Configuration Files

File Location Purpose
sftp-server.xml conf/ Master config: listeners, threading, host keys, security, access control, audit, user manager, password policy, notifications
filesystem-config.xml conf/ Home directory, upload rules, disk quota, volume guard
admin-console.xml conf/ Web admin console and file portal settings
users.xml conf/ Flat-file user directory (XML auth provider)
keys.xml conf/ Public key directory (key auth provider)
drivers-catalog.xml conf/ JDBC driver download definitions
log4j2.xml logs/ or conf/ Logging configuration (Log4j 2)

Each configuration file has a corresponding XSD schema in docs/xsd/. The XML files carry an xsi:schemaLocation hint pointing to the schema for editor validation.

sftp-server.xml — Full Reference

This is the master configuration file. It controls listeners, threading, host keys, security algorithms, access control, the user manager provider, password policy, audit sinks, and notifications.

Listeners

The <listeners> block defines one or more protocol listeners. Each <listener> element has a type attribute (sftp or ftp).

<listeners>
    <listener type="sftp">
        <port>22</port>
        <bind-address>0.0.0.0</bind-address>
        <idle-timeout-seconds>600</idle-timeout-seconds>
        <auth-timeout-seconds>30</auth-timeout-seconds>
    </listener>
    <listener type="ftp">
        <enabled>true</enabled>
        <port>21</port>
        <idle-timeout-seconds>600</idle-timeout-seconds>
        <passive-ports-start>50000</passive-ports-start>
        <passive-ports-end>50100</passive-ports-end>
        <implicit-ssl>false</implicit-ssl>
        <explicit-ssl>true</explicit-ssl>
        <keystore-path>/path/to/keystore.p12</keystore-path>
        <keystore-password>changeit</keystore-password>
        <ssl-protocols>TLSv1.2,TLSv1.3</ssl-protocols>
        <enabled-cipher-suites></enabled-cipher-suites>
        <key-alias></key-alias>
        <key-password></key-password>
        <ssl-pool-core>50</ssl-pool-core>
        <ssl-pool-max>150</ssl-pool-max>
    </listener>
</listeners>
Element Default Description
port 22 (SFTP) / 21 (FTP) TCP port number for the listener
bind-address 0.0.0.0 Network interface to bind to
idle-timeout-seconds 600 Close session after this many seconds of inactivity
auth-timeout-seconds 30 Maximum time allowed for authentication (SFTP only)
enabled true (SFTP) / false (FTP) Enable or disable the listener
passive-ports-start/end 0 / 0 (any available port) Port range for FTP passive mode data connections
implicit-ssl false Enable FTPS implicit TLS (dedicated TLS port)
explicit-ssl false Enable FTPS explicit TLS (STARTTLS upgrade)
keystore-path Path to Java keystore (PKCS12 or JKS) for TLS
keystore-password Keystore password
ssl-protocols TLSv1.2,TLSv1.3 Comma-separated list of allowed TLS protocol versions
enabled-cipher-suites (empty = JVM default) Comma-separated list of allowed TLS cipher suites
key-alias (empty = first key) Alias of the certificate entry in the keystore
key-password (same as keystore) Password for the private key entry, if different from keystore password
ssl-pool-core 50 Core SSL executor pool threads. Controls the minimum number of threads available for TLS handshake processing.
ssl-pool-max 150 Maximum SSL executor pool threads. Upper limit under heavy concurrent TLS load.
Note The default values for ssl-pool-core and ssl-pool-max are sufficient for most deployments. Increase these values only if the server handles hundreds of concurrent FTPS connections simultaneously.

Threading

<threading>
    <io-threads>0</io-threads>        <!-- 0 = 2x CPU cores -->
    <worker-threads>0</worker-threads>  <!-- 0 = automatic -->
</threading>
Element Default Description
io-threads 0 Number of NIO I/O threads. 0 means 2 × CPU core count.
worker-threads 0 Number of worker threads for file operations. 0 means automatic sizing.

Host Keys

<host-keys>
    <key type="RSA"     path="${STYLUS_SFTPSERVER_DATA}/conf/hostkey-rsa.ser"/>
    <key type="ECDSA"   path="${STYLUS_SFTPSERVER_DATA}/conf/hostkey-ecdsa.ser"/>
    <key type="Ed25519" path="${STYLUS_SFTPSERVER_DATA}/conf/hostkey-ed25519.ser"/>
</host-keys>

Each <key> element specifies a host key type and its file path. Host keys are automatically generated on first startup if the files do not exist. Supported types: RSA, ECDSA, Ed25519.

Host keys live under the data directory. The paths use ${STYLUS_SFTPSERVER_DATA} (typically C:\ProgramData\StylusSFTPServer\conf\), not the read-only install directory. The server generates these files on first startup and must be able to write them; the Windows service runs as LocalService, which has no write access to C:\Program Files. Keep the host-key files stable across upgrades — if they are lost or regenerated, connecting clients will report a changed host key (see Troubleshooting → Host key changed).

Security (Algorithm Allow-Lists)

The <security> block controls which SSH cryptographic algorithms the server will offer. Each sub-element (<ciphers>, <macs>, <key-exchanges>) contains a list of <algorithm> entries.

Warning An empty element (e.g., <ciphers/>) falls back to built-in defaults, which include legacy algorithms. A non-empty element restricts the server to exactly the listed algorithms. Unknown algorithm names are logged at WARN level and silently skipped.
<security>
    <ciphers>
        <algorithm>chacha20-poly1305@openssh.com</algorithm>
        <algorithm>aes256-gcm@openssh.com</algorithm>
        <algorithm>aes128-gcm@openssh.com</algorithm>
        <algorithm>aes256-ctr</algorithm>
        <algorithm>aes192-ctr</algorithm>
        <algorithm>aes128-ctr</algorithm>
    </ciphers>
    <macs>
        <algorithm>hmac-sha2-256-etm@openssh.com</algorithm>
        <algorithm>hmac-sha2-512-etm@openssh.com</algorithm>
        <algorithm>hmac-sha2-256</algorithm>
        <algorithm>hmac-sha2-512</algorithm>
    </macs>
    <key-exchanges>
        <algorithm>mlkem768x25519-sha256</algorithm>
        <algorithm>curve25519-sha256</algorithm>
        <algorithm>ecdh-sha2-nistp256</algorithm>
        <algorithm>diffie-hellman-group18-sha512</algorithm>
        <algorithm>diffie-hellman-group16-sha512</algorithm>
        <algorithm>diffie-hellman-group14-sha256</algorithm>
    </key-exchanges>
</security>
Sub-element Description
ciphers Symmetric encryption algorithms for the SSH transport layer
macs Message authentication codes for integrity protection
key-exchanges Key exchange algorithms, including post-quantum mlkem768x25519-sha256

Access Control

<access-control>
    <block-list>
        <entry>10.0.0.0/8</entry>
        <entry>203.0.113.0/24</entry>
    </block-list>
    <rate-limit>
        <max-connections>20</max-connections>
        <interval-seconds>60</interval-seconds>
        <blacklist-duration-minutes>30</blacklist-duration-minutes>
    </rate-limit>
    <geo-blocking>
        <mode>allow</mode>
        <countries>US, CA, GB</countries>
    </geo-blocking>
</access-control>
Element Description
block-list / entry IP addresses or CIDR ranges to permanently block. Checked before authentication.
rate-limit / max-connections Maximum connection attempts per IP within the interval window
rate-limit / interval-seconds Sliding window duration for rate counting
rate-limit / blacklist-duration-minutes How long an IP is blacklisted after exceeding the rate limit
geo-blocking / mode allow (whitelist) or deny (blacklist) mode
geo-blocking / countries Comma-separated ISO 3166-1 alpha-2 country codes

Password Policy

Enabled by default. Account lockout is on out of the box — 5 consecutive failures lock the account for 30 minutes, even when no <password-policy> block is present. Set lockout-threshold to 0 to disable it.
<password-policy>
    <lockout-threshold>5</lockout-threshold>
    <lockout-duration-minutes>30</lockout-duration-minutes>
</password-policy>
Element Default Description
lockout-threshold 5 Consecutive failed login attempts before the account is locked
lockout-duration-minutes 30 How long the account remains locked (minutes). The account can also be unlocked manually via admin tools.

User Manager

The <user-manager> block selects the authentication provider. Exactly one provider is active at a time, selected by the <provider> element.

<user-manager>
    <provider>xml</provider>  <!-- xml | ldap | jdbc -->

    <!-- XML flat-file provider -->
    <xml>
        <file>${STYLUS_SFTPSERVER_HOME}/conf/users.xml</file>
    </xml>

    <!-- LDAP / Active Directory provider -->
    <ldap>
        <url>ldap://ldap.example.com:389</url>
        <base-dn>ou=users,dc=example,dc=com</base-dn>
        <bind-dn>cn=sftpservice,dc=example,dc=com</bind-dn>
        <bind-password>secret</bind-password>
        <username-attribute>sAMAccountName</username-attribute>
        <user-filter>(objectClass=user)</user-filter>
        <public-key-attribute>sshPublicKey</public-key-attribute>
    </ldap>

    <!-- JDBC database provider -->
    <jdbc>
        <driver-class-name>org.h2.Driver</driver-class-name>
        <url>jdbc:h2:${STYLUS_SFTPSERVER_HOME}/db/sftpdb;AUTO_SERVER=TRUE</url>
        <username>sa</username>
        <password>secret</password>
        <max-pool-size>5</max-pool-size>
    </jdbc>
</user-manager>
Provider Description
xml Users defined in a flat XML file (users.xml). Simple setup for small deployments.
ldap Authenticates against LDAP or Active Directory. Configurable AD/LDAP groups (<access-groups>, <read-only-groups>) control access level. See Authentication for full details.
jdbc Users stored in a relational database (sftp_users table). H2 is the zero-config default; upgrade to MySQL, PostgreSQL, or SQL Server by changing the JDBC URL and driver class.

LDAP Elements

Element Description
url LDAP server URL (e.g., ldap://host:389 or ldaps://host:636)
base-dn Search base distinguished name
bind-dn Service account DN for directory searches
bind-password Service account password
username-attribute LDAP attribute containing the login username (typically sAMAccountName for AD)
user-filter LDAP search filter to locate user entries
public-key-attribute LDAP attribute storing SSH public keys (optional)
access-groups AD/LDAP group CNs that grant read-write access. Contains <group> child elements. (optional)
read-only-groups AD/LDAP group CNs that grant read-only access. Contains <group> child elements. Most restrictive wins. (optional)

JDBC Elements

Element Default Description
driver-class-name org.h2.Driver Fully qualified JDBC driver class name
url JDBC connection URL. Path macros are supported.
username sa Database username
password Database password
max-pool-size 5 Maximum number of connections in the HikariCP pool

Supported External Databases

To use an external database instead of the default H2, change the driver-class-name and url elements. The JDBC driver JAR must be placed in the server's libs/ directory.

Database Driver Class Example URL
H2 (default) org.h2.Driver jdbc:h2:${STYLUS_SFTPSERVER_DATA}/db/sftpdb;AUTO_SERVER=TRUE
SQL Server com.microsoft.sqlserver.jdbc.SQLServerDriver jdbc:sqlserver://dbhost:1433;databaseName=SftpAccounts
MySQL com.mysql.cj.jdbc.Driver jdbc:mysql://dbhost:3306/sftp_accounts
PostgreSQL org.postgresql.Driver jdbc:postgresql://dbhost:5432/sftp_accounts

Virtual Folder Mount Routing

Three independent switches control whether virtual folders (see the Organizations & Groups chapter) are surfaced to SFTP, FTP, and Web File Transfer Portal clients. All three live in conf/sftp-server.xml.

<!-- Enable virtual folders for SFTP sessions -->
<sftp-mount-routing enabled="false"/>

<!-- Enable virtual folders for FTP / FTPS sessions -->
<ftp-mount-routing enabled="false"/>

<!-- Enable virtual folders for the Web File Transfer Portal -->
<portal-mount-routing enabled="false"/>
Element Default Description
sftp-mount-routing false When true, an SFTP user's session shows every virtual folder granted to them as a top-level directory at the SFTP root, alongside the user's home files. When false, the session is anchored at the personal home directory as before.
ftp-mount-routing false Same effect for FTP / FTPS sessions.
portal-mount-routing false Same effect for Web File Transfer Portal sessions. Auto-flipped to true the first time any folder is granted to a group.

All three flags hot-reload — toggling them while the server is running takes effect on the next new session, no restart required.

Audit Sinks

The <audit> block configures one or more audit sinks. Events are dispatched asynchronously via a bounded LinkedBlockingQueue (capacity 10,000). Multiple sinks can be active simultaneously.

<audit>
    <!-- Log sink — writes to the SLF4J audit logger -->
    <log enabled="true"/>

    <!-- JDBC audit sink — writes to the sftp_audit table -->
    <jdbc enabled="true">
        <driver-class-name>org.h2.Driver</driver-class-name>
        <url>jdbc:h2:${STYLUS_SFTPSERVER_DATA}/db/sftpdb;AUTO_SERVER=TRUE</url>
        <username>sa</username>
        <password>secret</password>
        <max-pool-size>5</max-pool-size>
        <queue-capacity>10000</queue-capacity>
    </jdbc>

    <!-- Syslog / SIEM sink (RFC 5424 UDP) -->
    <syslog enabled="false">
        <host>siem.example.com</host>
        <port>514</port>
        <facility>LOCAL0</facility>
    </syslog>

    <!-- Webhook sink(s) — HTTP POST; wrap one or more <webhook> in <webhooks> -->
    <webhooks>
        <webhook enabled="false">
            <url>https://hooks.example.com/sftp-events</url>
            <events>UPLOAD_COMPLETE, AUTH_FAILURE</events>
            <format>json</format>            <!-- json | text -->
            <secret>your-hmac-signing-key</secret>
        </webhook>
    </webhooks>
</audit>
Sink Description
jdbc Writes events to the sftp_audit database table. Enabled by default when the JDBC provider is active.
syslog Sends RFC 5424 formatted messages via UDP. Fire-and-forget delivery.
webhook HTTP POST to a remote endpoint. Supports JSON and plain-text formats with optional HMAC-SHA256 request signing.

Notifications (SMTP)

The <notifications> block configures email alerts triggered by audit events. Requires SMTP server credentials and at least one notification rule.

<notifications>
    <smtp>
        <host>smtp.example.com</host>
        <port>587</port>
        <username>alerts@example.com</username>
        <password>secret</password>
        <from>alerts@example.com</from>
        <starttls>true</starttls>
    </smtp>
    <rules>
        <!-- Alert after 5 auth failures within 10 minutes (ISO-8601 window) -->
        <rule event="AUTH_FAILURE" to="admin@example.com" threshold="5" window="PT10M"/>
    </rules>
</notifications>

An optional <admin-alerts> block sends critical server alerts (disk space, certificate expiry, license expiry, etc.) to all admin users who have an email address configured:

    <admin-alerts>
        <enabled>true</enabled>
        <events>DISK_LOW,DISK_CRITICAL,CERT_EXPIRING,LICENSE_EXPIRING</events>
    </admin-alerts>

See Notifications for the full list of event types, rule modes (simple, threshold, batch), admin alerts, and user email configuration.

Update Notifications

The server periodically checks whether a newer version has been published and, when one exists, shows a dismissible "New version available" notice listing the changes since the version you are running, with a download link. The notice appears on the Web Admin Dashboard and the desktop console's Server tab; the CLI equivalents are admin update-status and admin check-update (run a check immediately). Dismissing the notice hides it for that version only — a newer release brings it back. The check is display-only: the server never downloads or installs anything by itself.

What is sent: the check is a plain HTTPS GET of the published release-notes feed (https://stylussftpserver.com/release-notes/release-notes.xml) that sends nothing identifying — no license key, no build number; the User-Agent is StylusSFTPServer-UpdateCheck without a version.

The check runs shortly after server start and every six hours thereafter. On a host without Internet access it logs a single line and stays silent; the Dashboard card simply never appears. Each newly discovered version is recorded once in the audit log (UPDATE_AVAILABLE), and a manual check from an admin surface is recorded as UPDATE_CHECK_RUN.

<update-check>
    <enabled>true</enabled>                 <!-- default: true -->
    <interval-hours>6</interval-hours>     <!-- default: 6 -->
</update-check>

To disable the check entirely, set <enabled>false</enabled> (hot-applied — no restart needed) or start the service with -Dstylus.sftpserver.update-check.disabled=true.

filesystem-config.xml — Full Reference

Controls home directory layout, upload behavior, disk quotas, and volume guard (server-level disk protection).

<filesystem-config xmlns="http://www.xmlpipelineserver.com/sftp/">

    <!-- Root directory under which per-user homes are created.
         ${username} is replaced with the authenticated user's login name. -->
    <home-root>${STYLUS_SFTPSERVER_DATA}/homes/${username}</home-root>

    <!-- Default access level for users without explicit override.
         Values: read-write | read-only -->
    <default-access>read-write</default-access>

    <!-- Upload lifecycle settings -->
    <upload>
        <!-- Pattern for the final name of a completed upload (basename only;
             the target directory is never changed). Macros:
               ${basename} = original name incl. extension (report.csv)
               ${filename} = name without extension        (report)
               ${ext}      = extension incl. leading dot    (.csv)
               ${username} = authenticated account name     (alice)
             Default ${basename} keeps the client's original name. -->
        <rename-pattern>${basename}</rename-pattern>

        <!-- Action when a file with the same name already exists.
             Values: timestamp-suffix (append timestamp suffix) | overwrite | reject -->
        <on-duplicate>timestamp-suffix</on-duplicate>

        <!-- Maximum age for orphaned .tmp staging files before cleanup.
             ISO 8601 duration (e.g., PT24H = 24 hours, P7D = 7 days). -->
        <orphan-max-age>PT24H</orphan-max-age>
    </upload>

    <!-- Disk quota settings -->
    <quota>
        <!-- Default quota limit for all users (bytes).
             Per-user overrides are stored in the sftp_quotas database table.
             0 = unlimited. -->
        <default-limit-bytes>1073741824</default-limit-bytes>  <!-- 1 GiB -->

        <!-- Enforcement mode:
             hard = reject writes that would exceed the quota
             soft = log a warning but allow the write -->
        <enforcement>hard</enforcement>
    </quota>

    <!-- Volume guard — server-level disk protection -->
    <volume-guard>
        <min-free-bytes>1073741824</min-free-bytes>       <!-- 1 GiB -->
        <check-interval-bytes>1073741824</check-interval-bytes> <!-- 1 GiB -->
    </volume-guard>

</filesystem-config>
Element Default Description
home-root ${STYLUS_SFTPSERVER_DATA}/homes/${username} Template path for per-user home directories. Supports path macros.
default-access read-write Default access level. read-only restricts users to downloads only.
rename-pattern ${basename} Final upload name (basename only; directory unchanged). Macros: ${basename}, ${filename}, ${ext}, ${username}. Default keeps the original name.
on-duplicate timestamp-suffix Duplicate file handling: timestamp-suffix, overwrite, or reject
orphan-max-age PT24H ISO 8601 duration. Orphaned .tmp files older than this are deleted at startup.
default-limit-bytes 1073741824 (1 GiB) Default per-user disk quota in bytes. 0 = unlimited.
enforcement hard hard rejects writes exceeding quota; soft logs a warning.
min-free-bytes 1073741824 (1 GiB) Volume guard: minimum free space to maintain on the storage volume. Uploads are rejected when free space falls below this threshold. 0 = disabled. See Volume Guard.
check-interval-bytes 1073741824 (1 GiB) Volume guard: how often to re-check free space during large uploads (bytes written). Minimum: 536870912 (512 MB).
Tip Per-user quota overrides can be configured in the sftp_quotas database table using the admin tools. The default quota applies to any user without an explicit override.
Warning The staging directory (.tmp files) and the final target directory must be on the same filesystem volume, because the server uses ATOMIC_MOVE to rename completed uploads.

admin-console.xml

Configures the embedded Tomcat instance that serves the Web Admin Console and the optional Web File Transfer Portal.

<admin-console xmlns="http://www.xmlpipelineserver.com/sftp/">
    <bind-address>127.0.0.1</bind-address>
    <port>9980</port>
    <jdbc>
        <driver-class-name>org.h2.Driver</driver-class-name>
        <url>jdbc:h2:${STYLUS_SFTPSERVER_DATA}/db/sftpdb;AUTO_SERVER=TRUE</url>
    </jdbc>
    <session-timeout-minutes>30</session-timeout-minutes>
    <file-portal>
        <enabled>false</enabled>
        <max-upload-bytes>1073741824</max-upload-bytes>
        <session-timeout-minutes>30</session-timeout-minutes>
        <max-zip-bytes>2147483648</max-zip-bytes>
        <max-search-results>500</max-search-results>
    </file-portal>
</admin-console>
Element Default Description
bind-address 127.0.0.1 Network interface for the web server. Use 127.0.0.1 (localhost only) in production.
port 9980 HTTP port for the admin console
jdbc / driver-class-name org.h2.Driver JDBC driver class for admin database access
jdbc / url JDBC URL. Should match the SFTP server's database for unified management.
session-timeout-minutes 30 Admin session inactivity timeout
file-portal / enabled false Enable browser-based file transfer for SFTP users
file-portal / max-upload-bytes 1073741824 (1 GiB) Maximum upload size per file through the portal
file-portal / session-timeout-minutes 30 Portal user session inactivity timeout
file-portal / max-zip-bytes 2147483648 (2 GiB) Maximum total uncompressed size for multi-file ZIP downloads. Requests exceeding this limit are rejected.
file-portal / max-search-results 500 Maximum number of results returned by the file search feature. The response includes a truncated flag when results are limited.
Note The admin console is a separate service (Tomcat) from the SFTP server. Both share the same database via H2 AUTO_SERVER=TRUE mode, which allows concurrent access from multiple JVM processes.

Supporting Configuration Files

users.xml

Flat-file user directory for the xml authentication provider. Each user entry contains a username, BCrypt-hashed password, and an enabled flag. See Authentication for the full schema and examples.

keys.xml

Public key directory for SSH public-key authentication. Each entry maps a username to one or more authorized public keys in OpenSSH format. See Authentication for details.

drivers-catalog.xml

Defines downloadable JDBC driver packages for MySQL and PostgreSQL. Drivers are not bundled with the server — they are downloaded at configuration time when the administrator selects an external database. The catalog includes driver coordinates (group, artifact, version), download URLs, and SHA-256 checksums.

log4j2.xml

Standard Log4j 2 configuration file. Controls log levels, appenders (file, console), rotation policies, and log format patterns. Generated automatically during installation.