Advanced Topics
This chapter covers database options, JDBC driver management, schema details, path macros, logging, Windows service configuration, and data directory separation.
Database Options
Stylus SFTP Server supports three database backends. Only one is active at
a time, configured in the <jdbc> block of
sftp-server.xml. All tables are auto-created on first start
regardless of which backend you choose.
H2 (Default)
H2 is the zero-configuration default. It runs as an embedded database with
no external process to install or manage. The
AUTO_SERVER=TRUE option enables multi-JVM access: the first
JVM opens the database in embedded mode and starts a TCP listener on an
ephemeral port; subsequent JVMs detect the lock file and connect via TCP
transparently.
<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>
</jdbc>
MySQL
MySQL Connector/J is not bundled with the distribution due to its GPL2 license. The driver is downloaded at configuration time using the admin tool and the built-in driver catalog. Once downloaded, change the JDBC settings:
<jdbc enabled="true">
<driver-class-name>com.mysql.cj.jdbc.Driver</driver-class-name>
<url>jdbc:mysql://dbhost:3306/sftpdb?useSSL=true</url>
<username>sftpuser</username>
<password>secret</password>
</jdbc>
All tables are auto-created on first start. The DDL is compatible with MySQL 8.0 and later.
PostgreSQL
The PostgreSQL JDBC driver (pgjdbc) is also not bundled. Download it via the admin tool, then update the configuration:
<jdbc enabled="true">
<driver-class-name>org.postgresql.Driver</driver-class-name>
<url>jdbc:postgresql://dbhost:5432/sftpdb</url>
<username>sftpuser</username>
<password>secret</password>
</jdbc>
JDBC Driver Download
MySQL and PostgreSQL drivers are not bundled with the distribution to
avoid license redistribution issues. Instead, the admin tool downloads
them on demand from a catalog defined in
conf/drivers-catalog.xml:
<!-- drivers-catalog.xml -->
<driver name="mysql" class="com.mysql.cj.jdbc.Driver"
url="https://repo1.maven.org/.../mysql-connector-j-8.3.0.jar"
sha256="..." />
The catalog specifies the driver name, JDBC class, download URL, and a
SHA-256 checksum for integrity verification. Downloaded drivers are
tracked in the driver_registry database table.
libs/ directory and register it via the admin CLI.
Database Schema
All tables are auto-created on first boot via a
DatabaseMetaData check. If a table already exists, it is
left untouched. The following tables are managed by the server:
| Table | Purpose |
|---|---|
sftp_users |
User accounts — username, BCrypt password hash, enabled flag. |
sftp_account_keys |
SSH public keys per user account. |
sftp_quotas |
Per-user disk quota overrides. |
sftp_audit |
Audit trail events (see Audit Trail for column details). |
sftp_lockout |
Account lockout state — consecutive failure count, locked-until timestamp. |
sftp_notification_log |
Email notification tracking — links audit events to notification rules and sent status. |
sftp_commands |
Admin command queue — polled by the server for remote administration. |
sftp_server_status |
Server heartbeat and runtime state. |
sftp_geo_ip |
GeoIP lookup data for IP-based access control. |
sftp_geo_meta |
GeoIP database import metadata (source, timestamp, record count). |
sftp_admin_users |
Admin console user accounts — username, BCrypt password hash, enabled flag. |
driver_registry |
Downloaded JDBC driver tracking (name, version, path, checksum). |
Path Macros
Configuration files support path macros that are resolved at runtime. Macros can appear in any path-valued element (home directories, database URLs, log paths, etc.).
| Macro | Resolved To |
|---|---|
${STYLUS_SFTPSERVER_HOME} |
Server install root directory (read-only binaries). |
${STYLUS_SFTPSERVER_DATA} |
Data directory containing conf, db, homes, and logs. |
${username} |
Current SFTP session username (used in home directory templates). |
${env.VAR} |
Value of the environment variable VAR. |
${basename} |
Original upload filename with extension (e.g., report.csv). |
${filename} |
Upload filename without extension (e.g., report). |
${ext} |
File extension with leading dot (e.g., .csv). |
Relative paths in configuration files are resolved against
${STYLUS_SFTPSERVER_HOME}.
Logging Configuration
Stylus SFTP Server uses Log4j 2 (Apache 2.0) as the logging backend and SLF4J as the logging facade.
| Setting | Value |
|---|---|
| Config file | conf/log4j2.xml (or logs/log4j2.xml) |
| Audit logger | com.ivitechnologies.stylussftpserver.audit at INFO |
| Root package | com.ivitechnologies.stylussftpserver |
RollingFileAppender with
size- or time-based rotation to prevent log files from growing
indefinitely.
Example log4j2.xml snippet for a dedicated audit log:
<RollingFile name="AuditFile"
fileName="${sys:stylus.sftpserver.data}/logs/audit.log"
filePattern="${sys:stylus.sftpserver.data}/logs/audit-%d{yyyy-MM-dd}.log.gz">
<PatternLayout pattern="%d{ISO8601} %msg%n"/>
<Policies>
<TimeBasedTriggeringPolicy interval="1"/>
</Policies>
<DefaultRolloverStrategy max="90"/>
</RollingFile>
<Logger name="com.ivitechnologies.stylussftpserver.audit"
level="INFO" additivity="false">
<AppenderRef ref="AuditFile"/>
</Logger>
Windows Service
On Windows, Stylus SFTP Server runs as a Windows service managed by Apache Commons Daemon (procrun). The service is registered during installation and starts automatically on boot.
| Setting | Value |
|---|---|
| Service wrapper | Apache Commons Daemon (procrun) |
| Service binary | bin\prunsrv64.exe |
| Service name | StylusSFTPServer |
| Runs as | NT Authority\LocalService |
| Startup type | Automatic (configurable in services.msc) |
Service Commands
Common service management commands:
sc start StylusSFTPServer &REM; Start the service
sc stop StylusSFTPServer &REM; Stop the service
sc query StylusSFTPServer &REM; Check service status
The service can also be started and stopped from the admin tools (CLI, Swing, or Web console).
Data Directory Separation
Stylus SFTP Server separates read-only binaries from mutable runtime
data. This allows the install directory (e.g.,
C:\Program Files\StylusSFTPServer) to remain read-only
while all writable state lives in a dedicated data directory (e.g.,
C:\ProgramData\StylusSFTPServer).
| Directory | Location | Contents |
|---|---|---|
| Install directory | C:\Program Files\StylusSFTPServer |
Binaries, JARs, service wrapper (read-only) |
| Data directory | C:\ProgramData\StylusSFTPServer |
conf/, db/, homes/,
logs/, activation.key
(read-write) |
Configuration
The data directory location is established through two mechanisms:
-
dataFolder.txt— a plain-text file at the install root containing the absolute path to the data directory. -
System property —
stylus.sftpserver.data, which can be set on the Java command line or in the service wrapper configuration. This takes precedence overdataFolder.txt.
In configuration files, the macro
${STYLUS_SFTPSERVER_DATA} resolves to the data directory
path at runtime.
Hot-Reload Configuration
Stylus SFTP Server watches the conf/ directory for changes
to sftp-server.xml and filesystem-config.xml.
When a file is modified, the server automatically re-parses it and
applies the new configuration — typically within 2–3 seconds
of saving the file. No restart is required and no action is needed
beyond editing and saving the file.
Hot-Swappable Settings
The following settings take effect immediately after the configuration file is saved:
- MFA policy (
<mfa>) - Password policy and account lockout (
<password-policy>) - IP block list (
<block-list>) - Connection rate limiter (
<rate-limit>) - Syslog audit sink (
<syslog>) - Webhook audit sinks (
<webhooks>) - Email notifications (
<notifications>) - SSH idle and authentication timeouts
Restart-Required Settings
The following settings are applied only at server startup. If they change, the server logs a warning but continues running with the previous values until restarted:
- Listener ports and bind addresses
- User manager provider (
xml/ldap/jdbc) - Home root template (
<home-root>) - Host key paths
WatchService
on the conf/ directory. If the configuration file cannot
be parsed (e.g., malformed XML), the error is logged and the previous
valid configuration is retained. The server never enters an
inconsistent state due to a bad edit.
AtomicReference.
There is no window during which the old and new configurations are
mixed.
Build Number
Each installer build increments a build number that is embedded in the distribution. This number helps identify the exact build during support interactions and is visible in several places:
- Server startup log
- CLI
server-statuscommand - Swing admin title bar
- Web admin dashboard
- REST API
/api/server/statusendpoint
The build number is stored in build.properties inside the
distribution JAR and is read at runtime by the
BuildInfo class.
File Verifier Tool
The install image ships a small self-contained verifier that recipients of a signed release can use to check both the SHA-512 checksum and the PGP signature of a downloaded file. It is packaged in multiple forms so recipients can pick whatever they can execute:
| Artifact | Location | Requires |
|---|---|---|
verify.jar |
tools/verify.jar on the install image, and
/portal/tools/verify.jar for unauthenticated
download via the Portal. |
Any machine with Java 21+. |
verify-portable.zip |
tools/verify-portable.zip, also served at
/portal/tools/verify-portable.zip. |
Nothing — the ZIP contains a jlink JRE, the JAR, and Windows / Linux launcher scripts. |
verify.exe / verify-cli.exe |
Windows PE launchers built with jpackage. Bundled
inside verify-portable.zip. |
Windows only; no separate Java install. |
The tool accepts a file (or directory) plus an optional path to the
operator's KEYS file. It fetches KEYS from the
server's public /KEYS endpoint by default. For each pair of
file + file.sha512 the checksum is
recomputed, and if a file.asc is also present the PGP
signature is checked against the imported key. A successful check prints
the literal string VERIFIED for each
dimension (checksum and signature); failures print the specific reason
(MISMATCH, BAD, MISSING_SIDECAR, ERROR).
The Swing UI (verify.exe / java -jar verify.jar)
shows one big badge per file with the same VERIFIED / MISMATCH / BAD /
SKIPPED status. The CLI (verify-cli.exe or
java -jar verify.jar --cli) exits with 0 when every dimension
is VERIFIED, non-zero otherwise, so it plugs into CI pipelines.