Web File Transfer Portal
The Web File Transfer Portal provides browser-based file transfer for SFTP end users. It exposes the same home directory, permissions, quotas, and audit trail as SFTP access. Users who cannot install an SFTP client — or who need occasional ad-hoc file exchange — can use the portal from any modern web browser.
Enabling the Portal
The portal is disabled by default. To enable it, add the
<file-portal> block to admin-console.xml:
<file-portal>
<enabled>true</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>
| Setting | Description | Default |
|---|---|---|
enabled |
Whether the portal is active. | false |
max-upload-bytes |
Maximum size of a single uploaded file, in bytes. | 1073741824 (1 GiB) |
session-timeout-minutes |
Idle session timeout before the user must re-authenticate. | 30 |
max-zip-bytes |
Maximum total uncompressed size for multi-file ZIP downloads. Requests exceeding this limit are rejected with an error. | 2147483648 (2 GiB) |
max-search-results |
Maximum number of results returned by the file search feature. Results beyond this limit are truncated. | 500 |
The portal runs on the same Tomcat instance as the admin console (same port, default 9980) but under a different URL prefix. No additional service or port configuration is required.
Accessing the Portal
Once enabled, the portal is available at:
http://localhost:9980/portal/
sftp_users table, BCrypt-hashed passwords). These are
not admin console credentials — the two user pools are
entirely separate. Do not confuse them.
Portal sessions are isolated from admin console sessions. Logging into the admin console does not grant portal access, and vice versa.
Features
File Grid
The main view displays the contents of the user's home directory as a sortable grid with the following columns:
- Icon — file or folder icon
- Name — file or directory name
- Expires — when the file will be deleted by a content-retention policy, if one applies
- Size — human-readable file size
- Last Modified — date and time of last modification
Double-click a folder to navigate into it, or double-click a file to download it.
When a folder is governed by a content-retention policy, the Expires column shows, for each file, the date it is scheduled to be deleted — the file's created or last-modified time (per the policy) plus the retention period. The date is shown in your local time zone with a relative hint such as (in 12 days), and a colour cue flags urgency: red within 24 hours or already due, amber within three days, grey otherwise. Hover the cell to see the exact policy. Files not subject to any policy — and all folders, which retention never deletes — show a dash (—). The date is always the rule that actually applies to the file, so it is correct even when you reach the file by browsing a shared folder above the one carrying the policy.
Toolbar
The toolbar at the top of the file grid provides quick access to all operations:
- ☰ (Toggle Tree) — show or hide the folder tree sidebar
- Up — navigate to the parent directory
- Refresh — reload the file grid and folder tree
- Download — download the selected file
- Download ZIP — download the selected folder as a ZIP archive
- Upload — open the upload dialog
- New Folder — create a new subdirectory
- Cut — mark selected items for moving (see Cut / Copy / Paste)
- Copy — mark selected items for copying
- Rename — rename the selected file or folder
- Delete — delete the selected file or folder
- Search — search for files by name across all subdirectories (see File Search)
All operations are also available via a right-click context menu on any item in the file grid or on the folder tree.
Folder Tree Sidebar
Click the ☰ button in the toolbar to show the folder tree on the left side of the file grid. The tree displays the full directory structure for the user's home directory:
- Click a folder in the tree to navigate the file grid to that directory.
- Right-click a folder for a context menu: Paste Here, New Subfolder, Delete Folder.
- Collapse/resize the tree by dragging its right edge or collapsing it via the toggle button.
The tree loads the complete folder structure in a single request and expands all folders automatically, giving you full visibility of the directory hierarchy at a glance. For directories with more than 50 subdirectories, a "load more" node is shown — click it to expand the remaining folders on demand.
The tree stays in sync with the file grid — creating, renaming, or deleting a folder in the grid immediately refreshes the tree. The tree's visibility (open or collapsed) is saved in the browser. If you open the tree, it stays open on your next visit. The tree also refreshes automatically when you switch back to the portal tab in your browser, catching any changes made by other users or protocols.
Navigation
A breadcrumb navigation bar is displayed above the file grid, showing the current path relative to the user's home directory. Click any segment in the breadcrumb to navigate directly to that directory. The folder tree (if open) highlights the current directory automatically.
Upload
Files can be uploaded using the Upload toolbar button or by dragging and dropping directly onto the file browser. Uploads support:
- Multiple files — select several files at once via the file picker or drag-and-drop a batch of files.
- Folder upload — drag-and-drop one or more folders from your desktop. The entire folder structure (including nested subdirectories) is recreated on the server. Supported in Chrome, Edge, and Firefox.
- Parallel upload — up to 4 files are transferred concurrently for faster throughput on large batches.
A progress bar is displayed during each upload. The maximum file size per
upload is controlled by the max-upload-bytes configuration
setting (default 1 GiB). Per-user disk quotas are enforced —
uploads that would exceed the quota are rejected.
File Search
The toolbar includes a search bar that searches by filename substring recursively through the user's entire home directory. Type a search term and press Enter (or click the search icon) to find matching files.
Search results are displayed in a modal window with:
- Full relative path for each matching file
- File size and last-modified date
- Checkbox multi-select for bulk operations
Selected files from the search results can be downloaded as a single ZIP archive using the Download Selected button.
max-search-results (default 500).
When results are truncated, a notice is displayed in the modal. Adjust this
limit in admin-console.xml if needed.
Multi-File ZIP Download
Multiple files can be downloaded together as a single ZIP archive. This is available from both the search results modal (select files and click Download Selected) and from the main file grid when a folder is selected (Download ZIP button).
The ZIP is generated server-side in a streaming fashion — no
temporary file is written to disk. The total uncompressed size of all
selected files is checked against the max-zip-bytes
limit (default 2 GiB) before streaming begins.
Folder Download as ZIP
Selecting a folder and clicking Download ZIP streams the entire folder contents as a ZIP archive. The ZIP is generated server-side in a streaming fashion — no temporary file is written to disk.
Cut / Copy / Paste
Files and folders can be moved or copied between directories using clipboard operations, just like a desktop file manager:
| Action | Trigger | Effect |
|---|---|---|
| Cut | Ctrl+X, toolbar button, or right-click → Cut | Marks selected items for moving. Cut items appear dimmed in the file grid. |
| Copy | Ctrl+C, toolbar button, or right-click → Copy | Marks selected items for copying. |
| Paste | Ctrl+V, clipboard bar button, or right-click empty area → Paste Here | Moves or copies the clipboard items into the current directory. |
| Cancel | Esc or the × button on the clipboard bar | Clears the clipboard. |
Clipboard Status Bar
After pressing Cut or Copy, a status bar appears below the toolbar showing:
- The operation type (Cut or Copied)
- The names of the selected items
- The source directory they came from
- The destination directory where they will be pasted
- A Move Here or Copy Here button (disabled when viewing the source directory)
Navigate to a different folder (via breadcrumb, double-click, or the folder tree), then click the paste button. The bar updates in real time to show where the paste will go.
Replacing Existing Files
If the destination already contains files with the same names, the portal prompts:
Replace existing files?
The following items already exist in the destination:
report.csv, data.xml
Do you want to replace them?
Clicking Yes atomically replaces the destination files. Clicking No cancels the operation — no files are modified.
Quota Usage Bar
A quota usage bar is displayed in the header area, showing the current disk usage relative to the user's quota. The bar changes color based on usage level:
- Green — below 70% usage
- Yellow — between 70% and 90% usage
- Red — above 90% usage
Read-Only Mode
If a user's account is configured for read-only access (via LDAP group membership
or the default-access setting in filesystem-config.xml),
the portal automatically hides all write-related toolbar buttons (Upload, New
Folder, Rename, Delete). Read-only access is also enforced server-side —
any attempt to write via the API is rejected regardless of the client-side UI
state.
The header also shows a read-only indicator badge next to the account chip, so the user can tell at a glance why the write buttons are hidden.
Checksum Sidecars
Users with the can_checksum group capability can generate a
SHA-512 checksum for any file in their view. The Portal computes the digest
on the server and writes a sidecar next to the original file, named
<file>.sha512. The sidecar contains a single line in the
standard sha512sum format:
b1f8e91c6c… release-2.4.zip
A recipient can verify the download by running sha512sum -c
(Linux), Get-FileHash -Algorithm SHA512 (Windows PowerShell), or
the bundled Verifier tool against the pair.
The Checksum button appears on the toolbar only when the
user's effective capabilities include can_checksum. Group flags
are edited from the Admin Console → Organizations tab → Group
Details.
PGP Signature Sidecars
Users with the can_sign group capability can generate a detached
PGP signature for any file. The Portal signs the file with the operator's
configured signing key (Admin Console → Signing panel) and writes an
armored sidecar named <file>.asc.
Signing is Enterprise-only. On Free / Standard /
Professional editions the Sign button is hidden and the endpoint returns
403. The signing key is generated or imported by the operator; the key's
passphrase is stored in the credential vault (credentials.p12).
The recipient verifies with gpg --verify release-2.4.zip.asc
release-2.4.zip after importing the operator's public key. The public
key is exposed at the public /KEYS
endpoint.
Public /KEYS Endpoint
The operator's PGP public key is served without authentication at two aliased URLs:
https://sftp.example.com/KEYS
https://sftp.example.com/portal/KEYS
This mirrors the convention used by Apache projects and other release-focused
services: customers who need to verify a signed download can grab the key
with a plain curl or browser hit, without needing a Portal
account. The response is a single ASCII-armored public key block. Content
type is application/pgp-keys.
If signing is not enabled on the server, the endpoint returns 404. The operator can regenerate or replace the key at any time from the Admin Console; the URL stays stable.
Verifier Tool Download
To make signature and checksum verification easy for recipients who don't
have gpg or PowerShell handy, the Portal serves a self-contained
verifier tool at two URLs:
/portal/tools/verify.jar— the shaded JAR (~2 MB). Runs on any machine with Java 21+./portal/tools/verify-portable.zip— a portable bundle containing a jlink JRE,verify.jar, and Windows / Linux launchers. No Java installation required.
Both endpoints are unauthenticated so recipients can
download the tool with the same anonymous access they use for
/KEYS. The tool checks any pair of file +
file.sha512 and, if a file.asc is also present,
verifies the PGP signature against the operator's public key (fetched from
/KEYS or supplied locally). A successful check prints
VERIFIED for each dimension; a failure prints the specific
reason.
Windows recipients who want a double-click GUI can use the
verify.exe native launcher shipped in the portable zip. The
same directory also contains verify-cli.exe for scripted use.
API Endpoints
The portal frontend communicates with the server through the following REST endpoints. All endpoints require an authenticated session (except Login).
| Operation | Method | Endpoint |
|---|---|---|
| Login | POST | /portal/api/login |
| Logout | POST | /portal/api/logout |
| Check session | GET | /portal/api/session/check |
| List files | GET | /portal/api/files?path=/ |
| Download file | GET | /portal/api/files/download?path= |
| Download folder as ZIP | GET | /portal/api/files/download?path=/folder |
| Upload | POST | /portal/api/files/upload?path= |
| Create folder | POST | /portal/api/files/mkdir |
| Delete | DELETE | /portal/api/files?path= |
| Rename | POST | /portal/api/files/rename |
| Quota info | GET | /portal/api/quota |
| Search files | GET | /portal/api/files/search?path=/&q=keyword |
| Download multiple files as ZIP | POST | /portal/api/files/download-zip |
| Copy files/folders | POST | /portal/api/files/copy |
| Move files/folders | POST | /portal/api/files/move |
| Folder tree | GET | /portal/api/files/tree |
| Generate SHA-512 checksum sidecar | POST | /portal/api/files/checksum |
| Generate PGP signature sidecar (Enterprise) | POST | /portal/api/files/sign |
| Public PGP key (unauthenticated) | GET | /KEYS or /portal/KEYS |
| Verifier JAR download (unauthenticated) | GET | /portal/tools/verify.jar |
| Verifier portable ZIP download (unauthenticated) | GET | /portal/tools/verify-portable.zip |
Security
The portal enforces the same security standards as the SFTP server itself:
-
CSRF protection — all mutating requests are validated
against
OriginandRefererheaders to prevent cross-site request forgery. - Login rate limiting — per-IP rate limiting on the login endpoint (5 attempts per 5 minutes) protects against brute-force attacks.
-
Path traversal prevention — every file operation
validates that the resolved path falls within the user's home directory. Any
attempt to escape via
../sequences or symbolic links is denied. -
Upload size limit — enforced server-side per the
max-upload-bytesconfiguration. - Shared account lockout — the portal shares the same account lockout mechanism as SFTP. Failed portal logins count toward the lockout threshold, and a locked account cannot authenticate via either protocol.
-
Staging file hiding — active upload staging files
(
.tmp) are hidden from directory listings, preventing users from seeing or downloading incomplete uploads. - Full audit trail — all portal operations (login, logout, upload, download, delete, rename, mkdir) are recorded in the same audit trail as SFTP operations.
localhost only. Use the reverse proxy to terminate TLS and forward
traffic to the portal.
Multi-Factor Authentication
When a user with MFA enrolled logs into the portal, the login flow adds an extra verification step:
- Password — the user enters their username and password as normal.
- MFA challenge — if the password is correct and the user has MFA enrolled, the portal displays a verification code form. The user enters the 6-digit code from their authenticator app (or a one-time recovery code).
- Session established — on successful verification, the portal session is fully authenticated.
If the user does not have MFA enrolled, the login completes immediately after the password step (subject to the server's MFA policy).
Self-Service MFA Enrollment
Authenticated portal users can manage their own MFA enrollment without administrator intervention:
| Operation | Method | Endpoint |
|---|---|---|
| Begin enrollment | POST | /portal/api/mfa/enroll |
| Confirm enrollment | POST | /portal/api/mfa/confirm |
| Disable MFA | POST | /portal/api/mfa/disable |
| Check status | GET | /portal/api/mfa/status |
| Verify code (login) | POST | /portal/api/mfa/verify |
The enrollment response includes an otpauth:// URI (suitable for
QR code display), the Base32-encoded secret (for manual entry), and the
one-time recovery codes.
White-label Branding (Enterprise edition)
Branding lets you ship the portal to your own end users as if it were your own product. The customer drops a small set of files into the data directory and restarts the admin service; the portal then renders with the configured product name, colors, and logo.
File layout
All branding files live in ${STYLUS_SFTPSERVER_DATA}/branding/
(created by the installer). A typical layout:
${STYLUS_SFTPSERVER_DATA}/branding/
branding.xml <-- product name, vendor name, colors, font, file overrides
logo.svg <-- displayed in login card and header bar
favicon.ico <-- browser tab icon
The installer also ships ready-to-copy starter themes under
${STYLUS_SFTPSERVER_HOME}/branding-examples/
(acme-corp, creative-studio,
healthcare, default-stylus). To apply a theme:
Windows (Administrator command prompt):
xcopy /E /I /Y "%STYLUS_SFTPSERVER_HOME%\branding-examples\acme-corp\*" ^
"%STYLUS_SFTPSERVER_DATA%\branding\"
net stop StylusSFTPAdmin && net start StylusSFTPAdmin
Linux:
sudo cp -r $STYLUS_SFTPSERVER_HOME/branding-examples/acme-corp/* \
$STYLUS_SFTPSERVER_DATA/branding/
sudo systemctl restart stylus-sftp-admin
To revert to the original look, copy the default-stylus
theme over branding/ and restart, or remove every file
inside branding/ and restart.
branding.xml fields
Every field is optional. Missing or invalid values fall back to the
sensible Stylus defaults. Colors are #RRGGBB hex (six
digits, no shorthand).
| Element | Controls | Default |
|---|---|---|
<product-name> |
Browser tab title, login card heading, header title | Stylus SFTP Server |
<vendor-name> |
Footer text; combined with product-name in browser title | IVI Technologies |
<primary-color> |
Login gradient start; fallback for banner | #1A3A5C |
<accent-color> |
Login gradient end, header bottom border, upload zone, progress fill | #2980B9 |
<banner-color> |
Top header bar background | falls back to <primary-color> |
<banner-text-color> |
Header title, user name, MFA / Sign Out, quota label/value | #ECF0F1 |
<footer-color> |
Bottom footer background | falls back to <banner-color> |
<footer-text-color> |
Bottom footer text | falls back to <banner-text-color> |
<toolbar-color> |
Toolbar above the file grid; grid column headers | #ECF0F1 |
<panel-title-color> |
Panel title bars (folder tree, etc.) | #ECF0F1 |
<breadcrumb-color> |
Navigation breadcrumb background | #ECF0F1 |
<breadcrumb-text-color> |
All breadcrumb text (links + current location + separators) | #7F8C8D |
<clipboard-bar-color> |
Paste-here / clipboard call-out bar background | #2A3A4D |
<text-color> |
Main body / file grid text | #2C3E50 |
<font-family> |
Body font stack (e.g.
"Inter", -apple-system, sans-serif) |
system font stack |
<logo-file> |
Filename to look for in branding/ for the logo |
probes logo.svg, logo.png,
logo.jpg |
<favicon-file> |
Filename to look for in branding/ for the favicon |
probes favicon.ico, favicon.png |
Empty product-name and vendor-name
When branding.xml is present, an explicitly empty
<product-name></product-name> or
<vendor-name></vendor-name> means
render nothing — the field is NOT replaced with the
Stylus defaults. This is intended for customers whose logo already
carries the brand name and who do not want any product-name or
vendor-name text in the UI. The default Stylus subtitles
(“File Transfer Portal” in the login card and
“File Portal” after the header title) are also
suppressed automatically whenever any custom branding is active.
Logo and favicon
The logo is rendered at 64 px tall in the login and MFA cards and
36 px tall in the header bar. Source images should be at least
twice those sizes for crisp HiDPI rendering. Recommended formats
in preference order: SVG (sharpest at every size), PNG (transparent
background), JPG. Favicons may be .ico or
.png (32×32 or multi-resolution
.ico).
The customer logo is served from
/portal/branding/logo and the favicon from
/portal/branding/favicon. Both are cached by the
browser; after replacing an image, run a hard refresh
(Ctrl+F5) to bypass the cache.
Example: minimal branding
<?xml version="1.0" encoding="UTF-8"?>
<branding xmlns="http://www.xmlpipelineserver.com/sftp/">
<product-name>Acme File Portal</product-name>
<vendor-name>Acme Corp</vendor-name>
<primary-color>#1ABC9C</primary-color>
<accent-color>#F39C12</accent-color>
<logo-file>acme-logo.svg</logo-file>
</branding>
More complete examples (including independent banner, footer,
toolbar, breadcrumb, and clipboard-bar colors) ship under
branding-examples/.
Frontend Technology
The portal frontend is a single-page application built with Sencha Ext JS 7.8.0
(Classic toolkit, Triton theme). The application code resides in
portal-app.js and communicates with the server exclusively through
the REST API endpoints listed above.