Releases: TheHolyOneZ/Pylon
Release list
Pylon v0.2.0
Changelog
[0.2.0] — 15.05.2026
Fixed
SSH Handshake [Session(-1)] Unable to exchange encryption keys on Windows
Root cause: libssh2-sys on Windows MSVC has two separate feature flags:
vendored-openssl— compiles OpenSSL from source (was already set)openssl-on-win32— tells libssh2 to use OpenSSL as its crypto backend (was missing)
Without openssl-on-win32, libssh2 always compiles with WinCNG (Windows Cryptography
Next Generation) as its backend, regardless of whether OpenSSL is present. WinCNG's
Diffie-Hellman key exchange implementation has been broken since Windows 10 v1903 (May 2019),
causing the server to close the connection mid-handshake. libssh2 surfaces this as
LIBSSH2_ERROR_SOCKET_NONE = -1 with the message "Unable to exchange encryption keys".
macOS was unaffected because non-Windows targets unconditionally use OpenSSL.
Fix (src-tauri/Cargo.toml):
ssh2 = { version = "0.9", features = ["vendored-openssl", "openssl-on-win32"] }Adding openssl-on-win32 sets CARGO_FEATURE_OPENSSL_ON_WIN32 during the libssh2-sys build,
which switches the compile-time define from LIBSSH2_WINCNG to LIBSSH2_OPENSSL.
Additional hardening (all 4 handshake sites):
- Removed pre-handshake TCP
set_read_timeout/set_write_timeout— once libssh2 owns the
socket viaset_tcp_stream, Winsock-level timeouts conflict with libssh2's internal I/O loop. - Added
sess.set_blocking(true)+sess.set_timeout(30_000)— proper libssh2-level
30 s timeout that works correctly on both Windows and macOS.
Build requirement (Windows): Strawberry Perl must be in PATH for the vendored-openssl
build step that compiles OpenSSL from source. Install portable Perl to C:\strawberry-perl
and add C:\strawberry-perl\perl\bin and C:\strawberry-perl\c\bin to the system PATH.
Host Key Policy settings not respected in Vault and Quick Connect
Problems:
- ZVault quick-connect always showed "accept via Quick Connect first" regardless of the
host key policy setting in Settings → Security. - There was no way to accept an unknown host key from ZVault without switching to Quick Connect.
- The Advanced panel in Quick Connect hardcoded "Ask (known_hosts)" instead of showing
the live policy value.
Fix:
- Added
vault_accept_host_key_and_connect(credential_id, permanent)Rust command that
performs a fresh TCP connect + handshake + optionalknown_hostswrite + authentication
using vault-stored credentials (secrets never leave the backend). VaultModalnow readshostKeyPolicyfrom the settings store on every vault connect:auto-accept→ silently callsvaultAcceptHostKeyAndConnectwithpermanent: falsestrict→ rejects immediately with an error toastask(default) → shows the sameHostKeyModalused by Quick Connect, then calls
vaultAcceptHostKeyAndConnectwith the user's permanent/once choice
ConnectModaladvanced panel now reads and displays the live policy value.
App icon not rendering in titlebar and lock screen on Windows
Problem: The custom titlebar, app lock screen, and settings panel all load /pylon-icon.png
via a root-relative URL. No public/ directory existed in the project, so Vite had no file
to serve at that path — the <img> broke in both dev and production builds.
Fix: Created public/pylon-icon.png (copied from src-tauri/icons/icon.png). Vite serves
the public/ directory verbatim at the root URL, so the existing /pylon-icon.png references
in TitleBar.tsx, AppLock.tsx, and SettingsPanel.tsx now resolve correctly in both modes.
Installer and bundle still named Pylon_0.1.0_* after version bump
Problem: src-tauri/tauri.conf.json still contained "version": "0.1.0". This is the file
the Tauri bundler reads when naming build artifacts (Pylon_0.1.0_x64-setup.exe,
pylon_0.1.0_x64_en-US.msi). Updating only package.json and Cargo.toml had no effect
on the installer names.
Fix: Bumped tauri.conf.json version to 0.2.0. Also updated the hardcoded v0.1 badge
in TitleBar.tsx to v0.2.
Rust compiler warning: unused variable mirror_perms in fs_watcher.rs
Problem: push_file_via_sftp in src-tauri/src/fs_watcher.rs:572 accepted a
mirror_perms: bool parameter that was never read (permission mirroring not yet implemented
for that path).
Fix: Renamed to _mirror_perms to explicitly mark the parameter as intentionally unused,
silencing the #[warn(unused_variables)] warning.
Pylon v0.1.0
Pylon
Cross-platform SSH and SFTP desktop client built with Tauri v2, Rust, and React.
License: GPL-3.0 | Version: 0.1.0 (beta) | Platforms: Windows, macOS, Linux
Pylon is in beta. The vault format and configuration schema may change between pre-release versions. Back up your vault before upgrading.
Download
→ zsync.eu/pylon
Windows, macOS (Apple Silicon + Intel), and Linux — all builds available on the website. No account required. Free and open source under GPL-3.0.
macOS: Not yet notarized. Right-click the
.app→ Open → confirm in the security dialog on first launch.
Screenshots
| Files | Terminal |
|---|---|
![]() |
![]() |
| Sync | Transfers |
|---|---|
![]() |
![]() |
| Settings | ZVault |
|---|---|
![]() |
![]() |
Features
File Management
- Dual-pane browser: local filesystem on the left, remote SFTP on the right, resizable
- Multi-select with Shift+Click (range), Ctrl+Click (individual), Ctrl+A (all)
- Drag-and-drop upload and download between panes
- Context menu with full file operations
- Sortable columns (name, size, modified, permissions)
- Editable path bar (Ctrl+L), click-to-navigate breadcrumb, bookmarks
- File permission display (octal and rwx notation)
- Regex and fuzzy filter per pane
- Remote chmod editor
Transfer Engine
- Resume support: interrupted transfers restart from the last verified byte
- Atomic writes: files staged as
.pylon_tmp_*and renamed on completion - SHA-256 checksumming per transfer
- Real-time bytes/sec and ETA in the transfer drawer (Ctrl+T)
- Pause, resume, and retry controls per transfer
- Concurrent transfers (1–16, configurable)
- Optional per-transfer bandwidth limit (kbps)
- Recursive directory upload/download
- Overwrite policy: ask / overwrite all / skip all
SSH Terminal
- xterm.js with full VT100/ANSI, 256-color support
- Multiple terminal tabs per session, with tab rename
- Navigating the remote pane sends a
cdcommand to the active terminal - Command snippets toolbar (save frequently used commands as quick-launch buttons)
- Clickable URLs via xterm-addon-web-links
- Shell selection (bash, zsh, sh, fish) per connection
ZVault — Credential Manager
- AES-256-GCM encryption for all stored credentials
- Argon2id key derivation from master passphrase (m=64 MB, t=3, p=4)
- Unique random salt and nonce per vault; no pre-computation attacks apply
- Auto-lock after configurable idle timeout
- Decrypted credentials kept in memory only; never written to disk in plaintext
- SSH key path storage alongside passwords
- Full CRUD UI for managing stored profiles
Sync Watchers
- Watch a local directory and sync changes to a remote path over SFTP
- Powered by the
notifycrate (inotify / kqueue / ReadDirectoryChangesW) - Only changed files are uploaded; unchanged files are skipped
- 100 ms debounce window to coalesce rapid saves
- Delete propagation: remote files are deleted when local files are removed
- Optional timestamp preservation (mtime mirrored to remote)
- Optional permission mirroring (chmod applied to remote)
.syncignorefile support (gitignore syntax);.gitignoreis also respected- Keep-on-disconnect: watchers can be paused rather than stopped when a session ends
- Configurable overwrite rules: always overwrite / new files only / update existing / confirm on overwrite / confirm all
Metadata Stripping
Strip privacy-sensitive metadata in-flight on upload, or on-demand via context menu.
| Format | Stripped |
|---|---|
| JPEG / PNG / WebP / GIF | EXIF data (GPS, camera, serial, timestamps, thumbnails) |
| Author, creator, producer, keywords, XMP metadata |
Enable globally in Settings → Security, or trigger per-file from the context menu.
Security
- SSH host key verification against
~/.ssh/known_hostson every connection - Changed host keys show a blocking warning dialog (configurable policy: ask / auto-accept / strict)
- SSH keepalive prevents silent session drops
- No telemetry; no outbound connections beyond what you explicitly initiate
- Tauri CSP configured in
src-tauri/capabilities/default.json
Other
- Command palette (Ctrl+K)
- Activity log
- Keyboard shortcuts for all major actions
- Bookmarks for local and remote paths
Building
Prerequisites
| Tool | Required version |
|---|---|
| Rust | stable ≥ 1.77 |
| Node.js | ≥ 20 LTS |
| pnpm | ≥ 9 |
Linux — install WebKit2GTK and related system libraries:
# Debian / Ubuntu
sudo apt-get install -y libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf
# Fedora / RHEL
sudo dnf install webkit2gtk4.1-devel libappindicator-gtk3-devel librsvg2-develmacOS — Xcode Command Line Tools:
xcode-select --installDev
pnpm install
pnpm tauri devFrontend only (no Rust compilation, faster iteration):
pnpm devVerbose Rust logging:
RUST_LOG=debug pnpm tauri devRelease build
pnpm install
pnpm tauri buildArtifacts are placed in src-tauri/target/release/bundle/.
Keyboard Shortcuts
Global
| Shortcut | Action |
|---|---|
| Ctrl+K | Command palette |
| Ctrl+N | New connection |
| Ctrl+T | Toggle transfer drawer |
| Ctrl+D | Disconnect active session |
File browser
| Shortcut | Action |
|---|---|
| F5 | Refresh pane |
| Ctrl+A | Select all |
| Ctrl+L | Edit path bar |
| Enter | Open folder / download file |
| Backspace | Navigate up |
Terminal
| Shortcut | Action |
|---|---|
| Ctrl+Shift+T | New terminal tab |
| Ctrl+Shift+C | Copy selection |
| Ctrl+Shift+V | Paste |
Tech Stack
Frontend: React 18, TypeScript 5, Vite 5, Tailwind CSS 3, Zustand, Framer Motion, xterm.js 5, Lucide React, react-resizable-panels
Backend (Rust): tauri 2, ssh2, tokio, aes-gcm, argon2, notify, image, kamadak-exif, lopdf, sha2, ignore, rayon, flume, serde, anyhow, tracing
Vault file location
| Platform | Path |
|---|---|
| Linux | ~/.config/pylon/vault-default.json |
| macOS | ~/Library/Application Support/pylon/vault-default.json |
| Windows | %APPDATA%\pylon\vault-default.json |
If you forget your master password there is no recovery mechanism. The vault cannot be decrypted without the correct passphrase.
macOS note
Pylon is not yet notarized by Apple. On first launch, right-click the .app and choose Open, then confirm in the security dialog.
License
GNU General Public License v3.0. See LICENSE.





