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>
Tip H2 is well suited for single-server deployments. For high-availability or multi-server environments, migrate to MySQL or PostgreSQL.

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.

Note Driver download requires internet access from the machine running the admin tool. In air-gapped environments, manually place the driver JAR in the 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
Tip Configure a separate appender for audit events to keep them in a dedicated log file. Use a 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).

Note If the service account does not have write access to the data directory, the server will fail to start. See Data Directory Separation below for permissions guidance.

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:

In configuration files, the macro ${STYLUS_SFTPSERVER_DATA} resolves to the data directory path at runtime.

Tip When upgrading, only the install directory is replaced. The data directory (configuration, database, homes, logs) is preserved automatically.

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:

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:

Tip The hot-reload mechanism uses a filesystem 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.
Note Components that read configuration at each decision point (such as authentication checks, audit dispatch, and IP filtering) pick up changes immediately via a lock-free 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:

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.