Repository navigation
What's Changed
Added
- Dynamic Folder scripts can define the full connection, not just host/port/username (issue #410) — a dynamic-folder entry now accepts an optional
protocol_configobject in the native RustConn shape, so a generated connection can carry anything the connection editor sets: an SSHstartup_command(e.g.tmux new-session -A -s my-session), anauth_method, RDP display options, and so on. The object is the same tagged form the config file uses ({"type": "Ssh", "startup_command": "…", "auth_method": "agent"}); itstypetag decides the protocol and default port, and theprotocolstring is then only used to warn on a mismatch. Entries withoutprotocol_configbehave exactly as before, so existing scripts are unaffected. Because the connection stays read-only, the configuration is re-applied on every refresh instead of being lost when the folder regenerates, which removes the need to hand-edit a generated connection only to have the edit discarded on the next refresh. (rustconn-core/src/models/dynamic_folder.rs,rustconn-core/src/dynamic_folder.rs,docs/USER_GUIDE.md) - A KeePass database per connection or group (issue #411) — with the KeePass backend, a connection or a group can now name its own
.kdbxfile instead of the single global one, so personal and corporate vaults can live side by side. Groups get a KeePass Database row on the Identity page (independent of Default Credentials); connections get one beside the Vault password source. A connection reads from its own file, else from the nearest group above it that sets one, else from the global database; an empty field inherits. Only the file changes — the database password, key file and YubiKey slot still come from Settings → Secrets, so a database that needs a different passphrase is not covered yet. The path is device-local: it is stripped from the full sync export, never part of Group Sync, and a remote edit keeps this device's own value. Switching a connection's password source away from Vault drops its path. The unlock prompt for a locked database now names the override file. Every KeePass operation follows the same resolution, not just the connect: saving, loading and testing a password in the connection editor, a group's own password (saved, loaded and deleted in the group's database), copying a connection's password on paste, deleting it with the connection, renaming it on an edit or group move, and the VNC password prompt. A move that changes which database a connection resolves to leaves the entry in the old file and logs it, rather than copying between databases; the password is entered again. The KeePass Database rows are hidden when the KeePass backend is not active, and the file picker filters on*.kdbxwith a named filter.rustconn-clifollows the same resolution:secret get,secret set,secret deleteandadd --password-stdinopen the connection's database instead of always the global one and print which file they used, and the override is set with--kdbx-pathonadd,updateandgroup edit(an empty value onupdate/group editclears it) and shown byshowandgroup show. Backend-to-backend credential transfer still uses the global database only. (rustconn-core/src/models/connection.rs,rustconn-core/src/models/group.rs,rustconn-core/src/secret/resolver.rs,rustconn-core/src/sync/full_export.rs,rustconn/src/state/mod.rs,rustconn/src/state/sync.rs,rustconn/src/vault_ops.rs,rustconn/src/dialogs/connection/,rustconn/src/dialogs/widgets.rs,rustconn/src/window/edit_group.rs,rustconn/src/window/connection_dialogs.rs,rustconn/src/window/rdp_vnc.rs,rustconn-cli/src/,po/,docs/USER_GUIDE.md,docs/CLI_REFERENCE.md)
Fixed
-
Embedded RDP on macOS sent the wrong keys (issue #412) — on the macOS GTK Quartz backend the GDK hardware keycode is an Apple virtual keycode (
NSEvent.keyCode), not an evdev keycode, but the embedded (IronRDP) client ran it through the Linux evdev→AT scancode table. Every key landed on a neighbouring one: on a German layoutqwertzarrived as345687,123as90ß, and Backspace as#, because e.g. Apple keycode 12 (q) is evdev 12 (3). A newmacos_keycode_to_scancodetable maps the stable Apple virtual keycode straight to the IBM PC AT (Set 1) scancode the RDP server expects — letters, digits, punctuation, modifiers (Command → Super/Win), the function row (F1–F19), the navigation cluster (Help → Insert) and the numeric keypad (including Keypad=), with theE0prefix on extended keys.send_ironrdp_keynow selects the evdev table on Linux/BSD and the Apple table on macOS at compile time; the external FreeRDP client, which was never affected, is unchanged. (rustconn-core/src/rdp_client/input.rs,rustconn/src/embedded_rdp/input.rs) -
The tray icon now shows the real number of open sessions, and a failed connection no longer logs a false "Failed to terminate session" warning — both read the core
SessionManager, which the GUI never registers a terminal session in, so the tray always said 0 and every connection that failed with its tab still open loggedWARN Failed to terminate session: Session not found. The tray now uses the same count as the quit confirmation (tabs, detached windows and external viewers), the always-failing terminate calls are gone, and the Session Manager dialog shows one "active session(s)" count instead of a second "tracked" figure that was always 0. Opening the RDP editor without FreeRDP installed (normal on macOS, where the embedded client needs none) is now logged atinfoinstead ofwarn; a launch that needs FreeRDP still reports it. (rustconn/src/app.rs,rustconn/src/state/sessions.rs,rustconn/src/window/session_lifecycle.rs,rustconn/src/window/sessions.rs,rustconn/src/embedded_rdp/detect.rs) -
Closing one of two sessions of the same connection no longer clears its "connected" mark in the sidebar — the sidebar counted open sessions per connection, and one session ending is reported by several paths (the close-tab action, the notebook's page-closed hook, the terminal's child-exit handler, an embedded client's Disconnected state). Each report took one off the counter, so closing one tab of a connection with two open sessions dropped it to zero and cleared the check mark, and a failure on one session could mark a connection failed while another was still connected. The sidebar now keeps the set of open session ids per connection, so a session is removed once however many paths report it, and a reconnect in the same tab is not counted twice. External viewer sessions pass their session id to the sidebar for the same reason. (
rustconn/src/sidebar/mod.rs,rustconn/src/sidebar_types.rs,rustconn/src/external_session.rs,rustconn/src/window/) -
"System keyring" can be chosen for a saved master password on macOS — the Secrets tab gated the keyring choice on the Linux
secret-toolbinary, which macOS never has, so picking "System keyring" to store the KeePass, Bitwarden, 1Password, Passbolt or portable-file secret was reverted and every opening of Settings loggedWARN secret-tool not found. On macOS the choice is now gated on the Keychain probe the backend itself uses. (rustconn/src/dialogs/settings/secrets_tab/detection.rs) -
Logs name the KeePass database a lookup used — the debug line for a KeePass credential lookup now carries the
.kdbxpath, so a per-connection or per-group database (issue #411) can be told apart from the global one, andrustconn-cli secret get/set/deleteinclude the path in KeePass errors. The credential-resolve timing line is nowop="connect.resolve"instead ofssh.connect.resolve, because RDP, VNC and the other protocols resolve through the same code. (rustconn/src/state/mod.rs,rustconn-cli/src/commands/secret.rs,rustconn-core/src/tracing/perf.rs,docs/ARCHITECTURE.md)
Changed
- Code scanning moved to an in-repo CodeQL configuration — the repository's CodeQL scan is now defined by a committed workflow (
.github/workflows/codeql.yml) and config (.github/codeql/codeql-config.yml) instead of GitHub's UI-only default setup, so its scope is reviewable in a PR. The language set (actions, python, ruby, rust) and the default query suite are unchanged; the workflow usesgithub/codeql-action@v4(v3 is deprecated in December 2026) and a per-language job-level concurrency group, andpaths-ignorekeeps non-product trees (Rust integration tests and benchmarks, packaging and developer tooling, build output) out of the scan. Thirteen pre-existing high/critical alerts were reviewed and dismissed as false positives: each flagged a#[cfg(test)]fixture — a hard-coded test passphrase or a synthetic certificate-mismatch message — not a production secret or log. (.github/workflows/codeql.yml,.github/codeql/codeql-config.yml)
Dependencies
- Updated (semver-compatible): arc-swap 1.9.3→1.9.4, cc 1.11.0→1.11.1, flate2 1.1.10→1.1.11, inout 0.2.5→0.2.6, libz-sys 1.1.31→1.1.32, lzma-rust2 0.24.0→0.25.0, serde_spanned 1.1.2→1.1.3, smallvec 1.16.4→1.16.5, toml 1.2.0→1.2.1, toml_datetime 1.1.2→1.1.3, toml_edit 0.25.18→0.25.19, uuid 1.29.0→1.29.1, zip 9.4.0→9.4.2.
cargo deny check advisoriesis clean;cargo-sources.jsonregenerated for the Flatpak/Flathub manifests. Bundled Flatpak FreeRDP (3.33.0) and cJSON (1.7.19) are at their latest releases, every pinned CLI download (TigerVNC 1.16.2) is current, andironrdp-rdpdr0.9.0 is still the latest release, so the 0.24.7 known issue about embedded RDP shared-folder names still applies.
Installation
Flatpak (Recommended)
flatpak install flathub io.github.totoshko88.RustConnSnap
sudo snap install rustconnDebian/Ubuntu (.deb from this release)
sudo dpkg -i rustconn_0.24.8_amd64.deb
sudo apt-get install -f # Install dependencies if neededFedora (.rpm from this release)
sudo dnf install rustconn-0.24.8-1.fc44.x86_64.rpmAppImage
chmod +x RustConn-0.24.8-x86_64.AppImage
./RustConn-0.24.8-x86_64.AppImagemacOS (Homebrew)
brew tap totoshko88/rustconn
brew install rustconn
open $(brew --prefix)/opt/rustconn/RustConn.appAll dependencies (GTK4, libadwaita, VTE, Adwaita icons) are installed automatically.
Requires macOS 13 (Ventura) or later.
OBS Repositories
Packages available at: https://build.opensuse.org/package/show/home:totoshko88:rustconn/rustconn
# Debian 13 (Trixie)
echo 'deb http://download.opensuse.org/repositories/home:/totoshko88:/rustconn/Debian_13/ /' \
| sudo tee /etc/apt/sources.list.d/rustconn.list
curl -fsSL https://download.opensuse.org/repositories/home:/totoshko88:/rustconn/Debian_13/Release.key \
| gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/rustconn.gpg > /dev/null
sudo apt update && sudo apt install rustconn
# Ubuntu 24.04 LTS (Noble)
echo 'deb http://download.opensuse.org/repositories/home:/totoshko88:/rustconn/xUbuntu_24.04/ /' \
| sudo tee /etc/apt/sources.list.d/rustconn.list
curl -fsSL https://download.opensuse.org/repositories/home:/totoshko88:/rustconn/xUbuntu_24.04/Release.key \
| gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/rustconn.gpg > /dev/null
sudo apt update && sudo apt install rustconn
# Ubuntu 26.04 LTS (Resolute)
echo 'deb http://download.opensuse.org/repositories/home:/totoshko88:/rustconn/xUbuntu_26.04/ /' \
| sudo tee /etc/apt/sources.list.d/rustconn.list
curl -fsSL https://download.opensuse.org/repositories/home:/totoshko88:/rustconn/xUbuntu_26.04/Release.key \
| gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/rustconn.gpg > /dev/null
sudo apt update && sudo apt install rustconn
# Fedora 44
sudo dnf config-manager addrepo --from-repofile=https://download.opensuse.org/repositories/home:/totoshko88:/rustconn/Fedora_44/home:totoshko88:rustconn.repo
sudo dnf install rustconn
# Fedora 43
sudo dnf config-manager addrepo --from-repofile=https://download.opensuse.org/repositories/home:/totoshko88:/rustconn/Fedora_43/home:totoshko88:rustconn.repo
sudo dnf install rustconn
# openSUSE Tumbleweed
sudo zypper ar https://download.opensuse.org/repositories/home:/totoshko88:/rustconn/openSUSE_Tumbleweed/ rustconn
sudo zypper ref && sudo zypper in rustconn
# openSUSE Leap 16.0
sudo zypper ar https://download.opensuse.org/repositories/home:/totoshko88:/rustconn/openSUSE_Leap_16.0/ rustconn
sudo zypper ref && sudo zypper in rustconnArch Linux (AUR)
yay -S rustconnFreeBSD (Ports)
pkg install rustconnFull installation guide: https://github.com/totoshko88/RustConn/blob/main/docs/INSTALL.md
Verifying your download
Every binary on this release (deb, rpm, AppImage, Flatpak) is covered two ways.
Plain checksums — download SHA256SUMS alongside the asset, then:
sha256sum -c SHA256SUMSSigned build provenance (SLSA, via Sigstore) — proves the file was built by this
workflow from this commit:
gh attestation verify RustConn-0.24.8-x86_64.AppImage --repo totoshko88/RustConn(The snap is signed by the Snap Store; the macOS build is delivered via the Homebrew tap.)