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 |
${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. |
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.
${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.
<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
<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). |
sftp_quotas
database table using the admin tools. The default quota applies to any user
without an explicit override.
.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. |
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.