WRM PRO
Your self-hosted WRM PRO: logs, files, services and commands with approvals and audit.
Install
Add this to your client's MCP configuration (Claude Desktop: claude_desktop_config.json; Cursor: .cursor/mcp.json; VS Code and others use the same "mcpServers" shape).
claude mcp add --transport http wrm-pro 'https://{wrm_host}/mcp' --header 'Authorization: <Bearer followed by a token of an AI connection (wrm_pat_…) from WRM → Settings → AI connections>'
{
"mcpServers": {
"wrm-pro": {
"type": "http",
"url": "https://{wrm_host}/mcp",
"headers": {
"Authorization": "<Bearer followed by a token of an AI connection (wrm_pat_…) from WRM → Settings → AI connections>"
}
}
}
}
Documentation
From the project's README on GitHub, refreshed weekly. Links open on GitHub.
Contents
- Web Remote Manager PRO (WRM)
- What's new in v13.12.0
- What's new in v13.11.0
- What's new in v13.10.0
- What's new in v13.9.0
- What's new in v13.8.0
- What's new in v13.7.0
- What's new in v13.6.0
- What's new in v13.5.0
- What's new in v12.9.1
- What's new in v12.9.0
- What's new in v12.8.1
- What's new in v12.8.0
- What's new in v12.7.4
- What's new in v12.7.3
- What's new in v12.7.2
- What's new in v12.7.1
- What's new in v12.7.0
- What's new in v12.6.26
- What's new in v12.6.25
- What's new in v12.6.24
- What's new in v12.6.23
- What's new in v12.6.22
- What's new in v12.6.21
- What's new in v12.6.20
- What's new in v12.6.11
- What's new in v12.6.10
- What's new in v12.6.9
- What's new in v12.6.8
- What's new in v12.6.7
- What's new in v12.6.6
- What's new in v12.6.5
- What's new in v12.6.4
- What's new in v12.6.3
- What's new in v12.6.2
- What's new in v12.6.1
- What's new in v12.6.0
- What's new in v12.5.1
- What's new in v12.5.0
- What's new in v12.4.5
- What's new in v12.4.4
- 📜 License: free for personal use and as a work tool in companies
- ☕ Support the project
- Table of contents
- What WRM is
- Quick start
- Upgrading from v13.11.0
- Upgrading from v13.10.0
- Upgrading from v13.9.0
- Upgrading from v13.8.0
- Upgrading from v13.7.0
- Upgrading from v13.6.0
- Upgrading from v13.5.0
- Upgrading from v13.4.4
- Upgrading from v12.9.0
- Upgrading from v12.8.1
- Upgrading from v12.7.1
- Upgrading from v12.7.0
- Upgrading from v12.6.26
- Upgrading from v12.6.25
- Upgrading from v12.6.24
- Upgrading from v12.6.23
- Upgrading from v12.6.22
- Upgrading from v12.6.21
- Upgrading from v12.6.20
- Upgrading from v12.6.19
- Upgrading from v12.6.11
- Upgrading from v12.6.10
- Upgrading from v12.6.9
- Upgrading from v12.6.8
- Upgrading from v12.6.7
- Upgrading from v12.6.6
- Upgrading from v12.6.5
- Upgrading from v12.6.4
- Upgrading from v12.6.3
- Upgrading from v12.6.2
- Upgrading from v12.6.1
- Upgrading from v12.6.0
- Upgrading from v12.5.1
- Upgrading from v12.5.0
- Upgrading from v12.4.5
- Upgrading from v12.4.4
- Upgrading from v12.4.3b
- Upgrading from v12.4.3
- Upgrading from v12.4.0
- Upgrading from v12.3.6
- Upgrading from v12.2.8
- Upgrading from v12.2.7
- Upgrading from v12.2.6
- Upgrading from v12.2.5
- Upgrading from v12.2.4
- Upgrading from v12.2.3
- Upgrading from v12.2.2
- Upgrading from v12.2.1
- Upgrading from v12.2.0
- Upgrading from v12.1.0
- Upgrading from v12.0.0
- Upgrading from v11.7.0
- Upgrading from v11.6.1
- Upgrading from v11.6.0
- Upgrading from v11.5.0
- Upgrading from v11.4.1
- Upgrading from v11.4.0
- Upgrading from v11.3.0
- Upgrading from v11.2.0
- Upgrading from v11.1.0
- Upgrading from v11.0.0
- Upgrading from v10.10.0
- Upgrading from v10.9.1
- Upgrading from v10.9.0
- Upgrading from v10.8.1
- Upgrading from v10.8.0
- Upgrading from v10.7
- Upgrading from v10.6
- Upgrading from v10.5
- Upgrading from v10.4
- Upgrading from v10.3
- Upgrading from v10.2
- Upgrading from v10.1
- Upgrading from v10.0
- Upgrading from v9
- How it works
- Features in detail
Web Remote Manager PRO (WRM)
A remote server manager that runs in any web browser, with an AI assistant and guided setup for AI agents. Add your own AI provider or a local model: WRM offers model suggestions, an Ollama setup wizard and connection presets for MCP agents to help you start practical work on your servers quickly.
Optional automatic Ollama installation: from WRM, an administrator can install the Ollama server on the WRM host, start it as a background service and download the chosen model. Enable ai_ollama_manage in Admin → AI, then confirm each action in the provider wizard. Choose the suggested local model or another supported model; installation and setup actions are recorded and audited. Connect Codex CLI, Claude Code, Gemini CLI, OpenCode, Cursor / VS Code, Claude or ChatGPT through the MCP wizard, which supplies the connection commands or configuration and lets you choose the servers and permissions.
Manage SSH terminals, SFTP / FTP / FTPS files and RDP / VNC desktops, Git service comparison and deployment, jump hosts, proxies, tunnels, BMC and serial consoles, keys and credentials, inventory imports, server-to-server transfers, notifications and collaboration with voice. AI tools can inspect logs and services, diagnose problems, run permitted commands and propose file changes with read-only, approval or limited automatic modes. WRM also provides sharing roles, 2FA, audit logs and session recordings. Run WRM as one self-hosted binary, a Docker container or a Linux AppImage.
Current version: v13.12.0 · Download · Release notes · Changelog · Security · Architecture
What's new in v13.12.0
Tools for writing addons, also with an AI. wrm -addon-lint ./my-addon checks an addon before you install it: the manifest against its schema, every file, and the code for what the sandbox would refuse (remote scripts, inline handlers, eval, fetch, localStorage, tokens in the ZIP, sites missing from http.origins, a panel that never says ready). Every finding has a code, the file, the line and a hint, so an AI can fix its own addon; -addon-lint-json gives the same as JSON, and a failed install in Settings → Addons opens the report by itself. wrm -addon-new grafana-panel ./my-addon starts from one of four templates (blank, fetch-and-render, grafana-panel, wasm-hook) that come with wrm-bridge.js, a small helper for the bridge. wrm -addon-dev ./my-addon opens the panel on your computer with the real sandbox and CSP, a stand-in for WRM (settings, web requests, secrets from environment variables) and a reload whenever a file changes. WRM also serves the manifest schema and an llms.txt guide for AI assistants. See Addons and the addon developer guide.
What's new in v13.11.0
Addons can reach web sites, through WRM and only where an administrator said yes. An addon now lists the sites it needs in addon.json (for example https://grafana.example.com, with the methods and paths it uses). WRM makes the request on the panel's behalf, so the panel itself still has no network: anything not listed is refused, every name is resolved by WRM and private or local addresses are blocked unless the administrator ticked private network for that site, and redirects are checked again. API keys and passwords for those sites are secrets that you type into WRM (🔑 Secrets on the instance): per instance, with your own value in a shared instance if you need one. They are stored encrypted, added to the request by WRM and never shown to the panel. A personal addon's sites wait for an administrator's approval. Recent requests are listed in the window's diagnostics. See Addons and the addon developer guide.
What's new in v13.10.0
Saved logins on demand, hostname names and a calmer top bar. Edit connection has 👁 Show saved login: after you confirm with your WRM password (or your domain password), WRM shows what the connection logs in with. Right-click a connection for Copy username, Copy password (same confirmation) and Copy IP address. A new connection can take its name from the server's hostname. Tabs show just the connection's name, the version next to the logo stays visible, the user name no longer jumps every 5 seconds, and the Git workspace server filter has no blank entries any more. See Connections & folders.
What's new in v13.9.0
Addon platform v2: your own addons, several windows each, and settings that stay. Every user can now install personal addons that only they see (an administrator decides who may with addon_personal and can turn any of them off). An addon with a panel opens as instances, each with its own settings and window, for example two dashboards side by side; administrators can set up shared instances for everybody. Settings are kept on the WRM server with export and import, and windows come back where you left them after a reload or on another device. Addon themes appear in Settings → Appearance for whoever picks them. Before an addon is enabled WRM shows a permission sheet generated from addon.json; an update that asks for more waits for approval again. apiVersion 2 panels run without any network of their own, every file is pinned by SHA-256, and a watchdog offers Reload when a panel hangs. See Addons and the addon developer guide.
What's new in v13.8.0
AI sessions, your own AI settings and approvals that do what they say. The new 🧠 AI sessions panel lists every AI session you had, from the assistant, the log and file assistants, OpenCode agents and AI apps over MCP, with search (also in the conversation), filters, a transcript viewer, Continue (also an MCP session, whose steps become the earlier context), Save (kept beyond the transcript retention) and export to Markdown or JSON. Everybody sees only their own sessions. ⚙ My AI settings in the assistant keep your own default provider (your own key, e.g. your OpenAI or Anthropic account), model, mode, engine and whether you see the model's thinking. Over MCP an approval given in WRM after the AI app stopped waiting now runs the call at once (ai_mcp_later_approval), Deny in the AI app is final, an app's open question is closed when you decide in WRM, and deciding a request that is no longer waiting says who decided it and where. The work log keeps the whole thinking text instead of its last lines. See AI sessions and AI desktop apps (MCP).
What's new in v13.7.0
Themes, accessibility and a screen lock you can rely on. Settings → Appearance offers eleven themes (dark, OLED black, Fjord, Solar, Forest, Ember, light Daylight, Paper, Solar light and two high-contrast themes), follows the system's light/dark setting if you want, and lets you change every colour, the fonts, the interface size, corners and spacing, save your own themes, export and import them, and add your own CSS. Themes from addons are picked there per user instead of being forced on everyone. For colour vision deficiency (deuteranopia, protanopia, tritanopia, achromatopsia) WRM switches status colours, diffs and optionally the terminal palette to colours you can tell apart, can add ✓ ✕ ! signs and shapes so nothing relies on colour alone, and offers more contrast, a terminal minimum contrast, reduced motion and transparency and a strong focus outline. Settings → Security → Screen lock sets when WRM locks (inactivity with a warning, a hidden window, the computer locking or sleeping, on every start, a keyboard shortcut) and how the lock screen looks; Lock now locks at once while terminals, transfers, tunnels, AI and MCP keep running. The lock is now kept by the server: a reload or a new tab stays locked, directory (LDAP) accounts can unlock, and a personal PIN can unlock instead of the password. See Appearance, themes and accessibility and Screen lock.
What's new in v13.6.0
Log folders, a folder tree and smarter operators. Monitoring → Logs can show the logs as a folder tree under their main folders (/var/log, /home/scripts …) and has a Folder filter for one folder and everything below it; Log settings take your own main folders. Operators are recognised from words that repeat in folder and service names (nova, NOVA2, novatv → one operator group), and every log says whether it sits in a log folder or an app folder. A log folder and a script folder with the same name (different case) no longer hide each other's logs. See Logs: viewer, search and log settings.
What's new in v13.5.0
A professional log viewer, a smart editor and an AI that shows its work. Monitoring → Logs lists every log of a server in about a second (one read-only SSH command), sortable and filterable by operator and service, and never lists scripts such as .py. Logs open in tabs with level colours, smart highlighting, find, level filters and Follow; the Search tab greps all selected logs on the server for a From/To range in the EU date format and sorts the hits on a timeline. Log settings are now separate from Zabbix. The file manager's editor highlights syntax, finds and replaces, shows your changes before saving, warns when the file changed on the server and has an AI assistant that reviews and edits the open file with your approval. The log viewer has an AI log assistant (search_logs). The AI work log shows the assistant's thinking and each step, chats get a short title with date and time, and an ended chat can be continued. See Logs: viewer, search and log settings, Text editor and AI assistant.
v13.0.0 to v13.4.4 (log engine, addons, screen lock, OpenCode Go, Claude quick start, Claude Desktop and Claude Code setup) are described in the changelog.
What's new in v12.9.1
Medium runs without the original tool. The WRM engine is now the default for projects nobody chose an engine for, its card comes first on the Medium page, and the original deploy tool with its Docker runtime is folded away as optional. Upgraded installations that already use the original tool keep it as their default until an administrator switches Medium: default engine to native. The deploy-config editor can now pull the configuration from its Git repository, show your local changes and Commit and push them through the WRM Git source, after checking that the whole configuration loads. WRM-host builds can run as an unprivileged account (medium_build_user) with a clean environment.
What's new in v12.9.0
Medium shows what changes in each file and lets you edit deploy-config. In the WRM engine's plan, Details opens the server's version of a changed file against the branch, line by line. Files that differ only in CRLF/LF are marked line endings only and counted separately, as in the original tool. Edit deploy-config edits servers.yaml, environments.yaml and the project files in WRM: a file is saved only when the whole configuration still loads, and comments, layout and line endings stay as you wrote them.
What's new in v12.8.1
Security update without a database change. The build toolchain is now Go 1.27.3, which fixes GO-2026-6809 / CVE-2026-111943: crypto/x509 now rejects known compromised intermediate certificates that an older system trust store may still contain. The gosec G702 finding in the OpenCode Docker sandbox was reviewed and accepted as a false positive: the Docker path is operator-configured and the container name is generated by WRM, both passed as separate arguments without a shell. See the release notes for the provenance of both findings.
What's new in v12.8.0
Folders now behave like a proper remote manager. Deleting a folder removes its subfolders and every connection inside in one step, without moving anything to the root first. Folders and connections can be moved from the context menu or dragged, including several selected connections at once, and the new position is saved. Shared and collaboration trees keep their nested folder structure; connection names sort case-insensitively, while folders keep their manual order.
Every reported detail is covered. The Settings window opens at the size of the Admin window and wide tab rows have scroll arrows. Terminal windows have Edit and Tunnels buttons in the title bar. The file manager can change permissions (including recursively and with an optional sudo password), and the transfer destination can create a folder. Additional uploads can be queued while one is running. Tunnels can be filtered by port, description or host, with an active-only switch, and proxy settings are reachable from Tools and the Tunnels panel. Save buttons show progress and reject a second click, and + Connection on a folder is pre-filled with that folder and its defaults.
What's new in v12.7.4
RDP works on Windows without preparing guacd by hand. When guacd does not answer and its address is local (127.0.0.1:4822), WRM starts the official guacamole/guacd:1.5.5 container in Docker Desktop, publishes it on loopback only, and keeps it running with Docker (wrm-guacd, unless-stopped). The first RDP/VNC/Telnet connection can start it; later starts happen with WRM. Admin → Overview shows the state and has Start guacd, -setup-guacd does the same from the command line, and the desktop window explains when Docker Desktop is missing or stopped. A custom guacd on another machine is never touched. Linux keeps using its system guacd or the docker-compose.yml service.
Every text file previews with its formatting. Preview now detects text from the file content, so shell/Python scripts, XML/SMIL, JSON, YAML, configuration files and extensionless files open as text instead of being refused. A bundled offline PrismJS highlighter colors the formats it knows; binary files still get the clear answer to download them. The 256 KiB preview limit and escaped-text safety policy are unchanged.
What's new in v12.7.3
Medium builds where you choose. Projects with a build step can now deploy with the WRM native engine. For each project, choose where the build runs: on the WRM host, on a chosen Linux build server over SSH, or not at all. The plan shows the place and the build's platform and architecture before anything runs; a destination with a different platform or architecture is refused with the reason. A build server receives only the prepared source in a temporary directory (no Git metadata and no SSH keys), and the directory is removed afterwards.
Monitoring → Logs finds every service. Service logs are now discovered under /home/<operator>/<operator>/<service>/log and /logs, with the correct Service and Operator labels. Non-compressed service logs, including FTP .txt files, are listed; virtual environments, build/archive directories and old backups are skipped. Discovery and listing have larger time budgets, so large hosts no longer show incomplete results.
What's new in v12.7.2
The version is read from the code. The Git workspace no longer trusts VERSION.md to say what is deployed. It compares every tracked file on the server with the repository tree at the target and at the earlier tags: all files matching one version show that version, a consistent older version is named exactly from its commit tree, and a mix or a hand-edited file shows Mixed / modified with the per-file details. A new checkbox next to Check now (off by default) also checks VERSION.md and warns when it disagrees. See Git workspace: every file and partial checks.
What's new in v12.7.1
Medium: per-environment server lists. environments.yaml now accepts the original deploy tool's servers: [name, ...] key, so an environment can be limited to chosen servers. A project target in that environment cannot deploy to any other server; an unknown, duplicate or empty list is refused with the file and key named. Existing configs without the key keep every server. See Medium native engine.
What's new in v12.7.0
Medium deploys natively. Switch a Medium project to the WRM native engine and WRM deploys it itself, from your WRM Git source to every server of the environment through your saved WRM connections, without Docker and without the original tool. Each server gets a lock, a backup of everything that changes, a SHA-256 check of every uploaded file, post_deploy and a history entry, all in the original tool's format, so both engines can take turns on the same servers and roll back each other's deployments. A dry run compares again under the lock and changes nothing; changes can be left out of a deployment; History and rollback shows what runs where, rolls back the last deployment and releases a lock someone left behind. Projects with a build step gained native builds in v12.7.3. See Medium native engine.
What's new in v12.6.26
SIEM export, security alerts and lockdown. WRM sends every audit entry to your SIEM: syslog over TLS (RFC 5424), a JSON lines file, Splunk HEC, Elastic, Microsoft Sentinel or any HTTPS collector, with user, role, directory identity, source address and the audit hash chain, and catches up after an outage. The admin sees per destination whether it delivers and what is waiting. Security alerts tell administrators about repeated failed sign-ins, break-glass sign-ins, new administrators, revealed secrets, AI full-access approvals and the audit being turned off. Stop user ends everything an account has open in one click, and lockdown keeps everyone except break-glass administrators out, switches AI off and pauses shares, from the UI, wrm -lockdown or WRM_LOCKDOWN=1. See SIEM export, alerts and lockdown.
What's new in v12.6.25
Active Directory, LDAP and SCIM. People sign in with their Active Directory or LDAP name and password on the normal sign-in page; WRM checks the password with the directory over LDAPS or StartTLS and never stores it. Rules turn directory groups (nested AD groups included) into WRM roles and teams, and WRM checks every linked account regularly: someone deleted, disabled, locked or removed from the WRM groups loses access at once. SCIM 2.0 lets Microsoft Entra ID or Okta create, change and disable WRM accounts and groups immediately. Whichever way an account is stopped, WRM ends its sessions, terminals, tunnels, rooms, AI sessions and AI connections. See LDAP / Active Directory and SCIM.
What's new in v12.6.24
Sign in with your organisation's account. WRM now signs people in through Microsoft Entra ID, ADFS, Okta, Keycloak, Google Workspace or any OpenID Connect provider (authorization code with PKCE). In Admin panel → Directory sign-in you add the provider, test the connection step by step, and write rules: an Entra app role or a group ID gives a WRM role and teams. Accounts are created on the first sign-in only for people a rule matches; everyone else is refused with a message that says why. People are recognised by their immutable directory ID, never by their name, so a renamed or re-used name cannot take over an account. A provider can require MFA proven by the token. WRM checks regularly with the provider that each signed-in user may still sign in: someone disabled or removed from the WRM group loses their sessions and terminals. Password sign-in can be limited to the break-glass administrators (the Enterprise level requires it once a directory sign-in is on). Test sign-in shows what the provider sends and what WRM would do, without creating anything. See Directory sign-in (OIDC).
What's new in v12.6.23
Roles, teams and a second confirmation for risky actions. Every account now has a role: Administrator, Security auditor (reads the audit log, terminal sessions, recordings, file transfers and the security posture, and changes nothing), Operator or User. Administrators create teams in Admin panel → Teams; a share can include a whole team with one role, and policies that say who may use a feature accept operators and teams:<names> besides off / admins / all. With step-up on (required from the Business level), changing policies, roles, the security level, deleting or disabling users, resetting passwords or 2FA and revealing stored secrets ask for your password (and 2FA code) again. A break-glass administrator account must use 2FA, can be limited to chosen networks, and every sign-in is audited and sent to the other administrators. When you delete a user, their connections, folders, credentials, keys, shares and proxies can pass to their team lead or another account instead of being deleted. See Roles, teams, step-up and break-glass.
What's new in v12.6.22
Security levels: Home, Business, Enterprise. Pick how strict WRM is on the first-run screen, at install (-security-level, WRM_INITIAL_SECURITY_LEVEL, forced with WRM_SECURITY_LEVEL) or later in Admin panel → Security. A level sets minimums for HTTPS, two-factor authentication, passwords, sessions, registration, host keys, secret export, guest links, AI full access, audit and session recording. Before you switch, a preview shows every change, what blocks it and whom it affects; a setting you keep below the level is a deviation with a written reason, on record and audited. The security posture page grades the installation item by item with the exact fix, and exports a report for auditors (JSON or PDF). See Security levels and posture.
What's new in v12.6.21
Signed releases. Every release from now on carries an ed25519 signature of its SHA256SUMS.txt, a software bill of materials (CycloneDX) and GitHub build provenance. Once the project's public key is built in, the one-click update refuses a release whose signature is missing or wrong, so a changed file on the release page cannot be installed. wrm -release-verify SHA256SUMS.txt checks a download by hand. Every night, fuzz tests feed random input to the import parsers (mRemoteNG, SSH config, CSV/XLSX, PuTTY, WinSCP, configuration files, deploy-config YAML) and OWASP ZAP scans a running WRM, signed out and as an administrator. The fuzz tests already found and fixed a crash in the PuTTY import.
What's new in v12.6.20
Security checked on every change. WRM is now built with a supported Go release (1.27) and up-to-date libraries, and every push and pull request runs automatic security checks: known vulnerabilities in Go and the libraries WRM uses (govulncheck), GitHub CodeQL for the server and the web UI, gosec and staticcheck, secret scanning (gitleaks), checks of the build workflows themselves, a dependency review, a vulnerability scan of the Docker image and the OpenSSF Scorecard. Dependabot proposes library updates every week, and Claude can review pull requests for security problems. The Medium proxy uses Go's safer Rewrite hook. No change for users; see Continuous security checks and the security roadmap (signed releases, security levels for home, business and enterprise, roles and teams, sign-in with Microsoft Entra ID / AD, LDAP and SCIM, SIEM export).
What's new in v12.6.11
OpenCode inside WRM. Add the OpenCode Zen provider and use OpenCode's free models in the AI assistant without an account, or paste an OpenCode account's Zen key for all its models. A Go subscription has its own OpenCode Go provider, so a Go key is sent to Go's endpoints instead of Zen. Choose OpenCode agent as the assistant's engine (agents build and plan): WRM downloads OpenCode itself after one click by an administrator (sha512 checked) and runs it on the WRM host with its own shell, file and web tools switched off, so it works on your servers only through WRM and every command still waits for your approval. The assistant can also hand text jobs to helper models, picked automatically by the kind of job (free first), each labelled with how it treats your data; models that may train on prompts stay off until you switch them on. See OpenCode Zen, Go, agents and helper models.
What's new in v12.6.10
One canvas, arranged your way. The window area is one canvas: terminals, file managers, desktops, Workboard addons and panels share it. Addons are windows you move, resize, snap, pin or dock; panels can be placed anywhere on the canvas, not only at the edges. The ▤ Workboard menu adds addons and holds the canvas tools: grid, tile and cascade, lock, saved layouts (optionally with your terminals) and export / import. New addons: links, saved sessions and a timer. The top bar is tidier: Broadcast is in 🧰 Tools, Shares is an icon, and Settings · Panels · Workboard sit together. A closed terminal's banner has a ✕ Close window button. See Workboard: the shared canvas and addons.
What's new in v12.6.9
Workboard: what matters, at a glance. ▤ Workboard in the top bar opens a page of tiles you put together yourself from an addon catalog, so nothing appears until you add it: server status, CPU / RAM / disk bars of chosen servers (from Monitoring, or read over SSH), WRM's notifications inside WRM, clocks for your time zones, the last commits of a Git service, running tunnels, quick connect buttons and notes. Any tile can be pulled out into a panel and docked, stacked or floated like the other panels. See Workboard and addons.
What's new in v12.6.8
Your panels, where you want them. Connections, Sessions, Snippets, Clipboard and the AI live view are panels with a tab you can drag: onto another panel's tab bar to stack them as tabs, onto the top or bottom part of a panel to split the column, onto an edge strip to dock it left, right or under the windows, or anywhere else to let it float. Panels (▦) in the top bar shows and hides them, and Lock the layout keeps everything in place. The layout is stored for your account on the server, so it follows you to every browser. See Panel layout.
What's new in v12.6.7
A top bar that fits and an AI panel that docks. The top bar now fits at any width and browser zoom: labels go first, then less used buttons move into a ⋯ menu, so nothing overlaps. The AI live view (what an AI app runs on your servers, with approvals and output) no longer covers your windows: it is a 🤖 AI tab next to Sessions and Snippets, a dock under the windows, a floating window, or hidden, chosen with its title bar buttons or by dragging it to an edge, and remembered per user. Approval cards still always pop up. See AI desktop apps (MCP). Every text on the page can be selected and copied again, and Medium's Docker runtime trusts your computer's certificates, so it works behind proxies and antivirus that inspect HTTPS (see Docker for Medium).
What's new in v12.6.6
Docker everywhere, installed by WRM. The original deploy tool now runs in WRM's managed Docker runtime on Linux, macOS and Windows alike, and WRM installs Docker itself when it is missing: an administrator presses Install Docker in Medium step 2 once (accepting Docker Desktop's licence on Windows and macOS), and WRM installs Docker Engine from the Linux distribution's packages or Docker Desktop from docker.com (signature checked), starts it, waits for it and prepares the runtime, every step with its output in the activity log. Afterwards a tool ZIP import does all of it by itself. Where WRM has no administrator rights it shows the one command to run, sudo wrm -setup-docker. See Docker for Medium.
What's new in v12.6.5
Medium tells you what it is doing. The Medium view now has a numbered step-by-step guide for the original deploy tool (1 import the tool ZIP, 2 prepare its runtime, 3 your deploy-config, 4 your SSH profile, 5 start/stop), each with a light, what it waits for and what to do when it fails. While something runs you see what runs, who started it, since when and every step with its time, with the output of Docker, pip and the original tool (secrets redacted). A deploy-config ZIP is checked by WRM at once and kept for the next start while the runtime is still being prepared, so you no longer wait to upload it. A new activity log lists every Medium action with its result, duration, steps and output, and WRM's console logs each step. The read-only WRM preview is a separate, clearly labelled panel. See Medium step by step.
What's new in v12.6.4
Your blocked commands, your choice. With full access on, the administrator now decides whether their own list of blocked commands (ai_blocked_commands) asks for approval like everything else (default) or stays blocked even with full access (ai_full_access_blocked, Admin panel → AI connections). See AI desktop apps (MCP).
What's new in v12.6.3
Full access with one switch. The administrator now chooses how full access applies (ai_full_access_mode): by default the Full access for the AI switch alone opens it for every AI session; it can instead apply only to AI connections with the ⚠ Full access scope, or to users who turn it on for themselves in Settings → AI connections. Claude still asks before anything WRM would otherwise refuse. See AI desktop apps (MCP).
What's new in v12.6.2
Full access, but Claude still asks. When an administrator allows it (ai_full_access), an AI connection can get the ⚠ Full access scope. WRM then refuses nothing outright: destructive and blocked commands, deny lists, shutdown and secret files come to you as an approval marked FULL ACCESS, every time and never automatically. Read-only connections stay read-only. See AI desktop apps (MCP).
What's new in v12.6.1
"Allow everything" now means everything. In an AI connection's automatic mode, Allow everything fills in * for commands and /** for files, and No time or action limit keeps the connection automatic for as long as it is valid. Chains with &&, variables and redirections no longer stop at an approval when * is allowed; blocked commands, your deny lists and sensitive files still do. When WRM does ask and nobody answers in time (or the app declines the question), the request stays in WRM to approve later, and the AI repeats it once you have. Files that may hold secrets are read after your approval, with secrets redacted. See AI desktop apps (MCP).
What's new in v12.6.0
Medium's native engine, first step. The Medium view has a read-only Native engine panel: WRM reads your deploy-config as it is, matches its servers to your saved WRM connections, prepares the chosen branch or tag from your WRM Git source and shows what a deployment would change on each server, without Docker and without writing anything. Compare with the original tool runs the original comparison next to it and shows whether both give the same result. Deploying natively and rollback followed in v12.7.0. See Medium native engine.
What's new in v12.5.1
Claude Desktop and Claude Code in one step. Settings → AI connections → Claude Desktop now downloads a WRM PRO extension (wrm-pro.mcpb) with your WRM address and token already filled in: open it, press Install, done. It works with a WRM on your own network and over plain HTTP, because Claude Desktop talks to WRM from your computer (a claude.ai custom connector connects from Anthropic's cloud and needs a public HTTPS address). For Claude Code there is a WRM PRO plugin: claude plugin install wrm-pro --marketplace vedranius/web-browser-RDM-public --config wrm_url=… --config wrm_token=…. Token lifetimes are entered in hours or days and default to 7 days (at most 30), so you are not asked to approve again every day. While an AI app works on a server, a live panel in WRM shows each command, the approval buttons and the output; after a denial the AI asks you how to go on. See AI desktop apps (MCP).
What's new in v12.5.0
Stamp as it is: the Stamp dialog shows which files differ and why an installation cannot be stamped. Tick Also stamp installations that are not up to date to write VERSION.md with each file's actual version and a note that the installation is partial.
Back in dialogs: dialogs opened from another dialog (for example Details → Update → confirmation) have ← Back (Alt+←) and keep what you ticked or typed. A code review of the v12.4.x features fixed production confirmations, Medium start/stop/settings and imports, log search with non-UTF-8 bytes and special characters, and the client GitLab cache. The next versions run Medium without Docker on WRM's own engine (roadmap).
What's new in v12.4.5
Medium: select the trusted tool/config ZIPs and click Prepare and run. WRM retains the imports, starts Docker, prepares the original dependencies, validates config, synchronizes the private profile and opens the unchanged original tool. First Windows setup can invoke the signed official Docker installer; OS/vendor prompts and required restarts remain visible. Existing custom configuration Git settings are replaced by the explicitly uploaded local config ZIP.
Monitoring → Logs: discovery starts automatically and streams results by server. Service log folders and Supervisor paths supplement manual roots. Filter by server/operator/service and event time, then search a keyword across all matching files from their beginning. Results show file modification time, matching event range, highlighted excerpts and open/follow actions. Progress, permission errors and partial searches remain visible; continue a bounded scan when necessary. Host metrics, service checks and SSH logs have separate setup requirements.
Overview/Installations keep filters, check controls and actions together while scrolling. Environments adds combined search/service/environment/server filters.
Operation and limits · Validation.
What's new in v12.4.4
Monitoring with Zabbix metrics/history and service Functionality, multi-window logs, client GitLab token access with persistent snapshots, easier MCP setup and editable grants, structured configuration inventory, terminal selection-to-AI/Open terminal here, visual folder/connection labels, longer provider timeouts, sticky filters and replay/import fixes.
Operation and limits · Release validation · Original Medium tool parity. General configuration import now recognizes mRemoteNG XML and PuTTY registry files (#5).
📜 License: free for personal use and as a work tool in companies
WRM is source-available. You may use it under the PolyForm Noncommercial License 1.0.0 or the PolyForm Internal Use License 1.0.0, whichever fits.
| ✅ Free for personal & noncommercial use | Personal use, home labs, learning, hobby projects, non-profits, schools and universities, public research, government. You may use, fork, modify and share it, including modified versions. Keep the LICENSE and its Required Notice: lines. |
| ✅ Free for companies as a work tool | Companies of any size may run WRM on their own servers and use it for their work, including paid work for their customers (e.g. managing customers' servers), and may modify it for internal use. |
| 💼 Needs a commercial license | Offering WRM to others as a hosted service / SaaS, charging anyone for access to or use of WRM, reselling, renting or white-labelling it, bundling it in a product or appliance, or using its code in a product you offer to others. Contact the owner first. See COMMERCIAL-LICENSE.md. |
| 🤝 Contributions welcome | Ideas, bug reports, translations and pull requests. See CONTRIBUTING.md. |
Copyright © 2026 vedranius. Third-party libraries keep their own licenses.
☕ Support the project
WRM is built in my spare time. If it saves you time, you can buy me a coffee:
**https://ko-fi.com/vedranius**. Thank you! ❤️
Table of contents
- What WRM is
- Quick start
- Upgrading from v13.11.0 · from v13.10.0 · from v13.9.0 · from v13.8.0 · from v13.7.0 · from v13.6.0 · from v13.5.0 · from v13.4.4 · from v12.9.0 · from v12.8.1 · from v12.7.1 · from v12.7.0 · from v12.6.26 · from v12.6.25 · from v12.6.24 · from v12.6.23 · from v12.6.22 · from v12.6.21 · from v12.6.20 · from v12.6.19 · from v12.6.11 · from v12.6.10 · from v12.6.9 · from v12.6.8 · from v12.6.7 · from v12.6.6 · from v12.6.5 · from v12.6.4 · from v12.6.3 · from v12.6.2 · from v12.6.1 · from v12.6.0 · from v12.5.1 · from v12.5.0 · from v12.4.5 · from v12.4.4 · from v12.4.3b · from v12.4.3 · from v12.4.0 · from v12.3.6 · from v12.2.8 · from v12.2.7 · from v12.2.6 · from v12.2.5 · from v12.2.4 · from v12.2.3 · from v12.2.2 · from v12.2.1 · from v12.2.0 · from v12.1.0 · from v12.0.0 · from v11.7.0 · from v11.6.1 · from v11.6.0 · from v11.5.0 · from v11.4.1 · from v11.4.0 · from v11.3.0 · from v11.2.0 · from v11.1.0 · from v11.0.0 · from v10.10.0 · from v10.9.1 · from v10.9.0 · from v10.8.1 · from v10.8.0 · from v10.7 · from v10.6 · from v10.5 · from v10.4 · from v10.3 · from v10.2 · from v10.1 · from v10.0 · from v9
- How it works
- Features in detail
- Accounts, sign-in & two-factor authentication
- Connections & folders
- Quick connect & connection notes
- SSH keys & credentials vault
- Jump hosts (bastions)
- Proxies (SOCKS / HTTP)
- SSH tunnels (port forwarding)
- Web interfaces (HTTP / HTTPS connections)
- Tags & inventory import (CSV, Excel, NetBox)
- Import from mRemoteNG, PuTTY and OpenSSH
- Windows, tabs & snapping
- Panel layout: dock, stack, float and lock
- Appearance, themes and accessibility
- Screen lock
- Workboard: the shared canvas and addons
- Addons
- SSH terminal
- Remote desktop: RDP, VNC, Telnet
- Out-of-band management, consoles & serial ports
- Snippets & run on connect
- Folder bookmarks
- Broadcast input
- Live up/down status
- Logs: viewer, search and log settings
- Notifications (e-mail, chat, push, webhook)
- Git workspace: service functionality and configuration
- Git workspace: compare services
- Git workspace: update, upgrade, rollback & restarts
- Git workspace: tab explanations
- Git workspace: Simple mode
- Git workspace: environments, deploy plans & safe deploys
- Git workspace: activity, deploy history & what is where
- Git workspace: new servers (install & transfer)
- Git workspace: .gitignore helper
- Git workspace: CI integration (optional)
- Git workspace: every file and partial checks
- AI assistant
- AI desktop apps (MCP)
- Network tools
- File manager (SFTP / FTP / FTPS)
- Search in files
- Text editor
- Server-to-server transfer
- Workspace sessions
- Clipboard panel
- Sharing: members, roles & links
- Real-time collaboration
- Voice calls
- Settings
- Audit log, session recording & file transfers
- Admin panel
- Security levels and posture
- Roles, teams, step-up and break-glass
- Directory sign-in (OIDC)
- LDAP / Active Directory and SCIM
- SIEM export, alerts and lockdown
- Updates & self-update
- Mobile, responsive UI & installable app
- Keyboard shortcuts
- Configuration
- Docker, service, reverse proxy & firewall
- Security model
- Limitations
- API reference
- Building from source & releases
- Troubleshooting
- Contributing
What WRM is
WRM is a single executable with a built-in web server and a built-in web app. You start it on any machine: your PC, a Raspberry Pi, a VPS or a company server. Then you open it in a browser and manage your remote servers from there:
- SSH terminals in the browser (xterm.js, 256 colors, full-screen apps like
nano,vim,htop,mc), with snippets (saved commands with variables, one click or Ctrl+Shift+Space), run on connect (sudo -i,cd /srv/app…) and broadcast input (type into many terminals at once, with a safety check for dangerous commands). - Live up/down status of every saved connection in the sidebar, with latency, server banner and a notification when a server goes down.
- Quick connect — type
root@10.0.0.5:22(orrdp://…,vnc://…) and connect without saving; notes & runbooks per connection (procedures, contacts, links); network tools — port check, ping, traceroute, DNS and HTTP/TLS check from the WRM server or from any of your servers ("can app-01 reach the database on 5432?"). - Out-of-band management — power on/off/restart, health and inventory through the server's BMC (iDRAC, iLO, XClarity, Supermicro, OpenBMC via Redfish, or IPMI), and its serial console (BMC SSH or IPMI Serial-over-LAN) in a terminal window; serial ports of the WRM machine for switch and router consoles.
- Remote desktops — RDP (Windows), VNC and Telnet in a browser window, also behind jump hosts, with clipboard, Ctrl+Alt+Del, recording and replay (through guacd, the Apache Guacamole proxy).
- File manager for SFTP (over SSH), FTP and FTPS: browse, upload, download, rename, delete, edit, search.
- SSH keys & credentials vault: generate SSH keys, put them on many servers at once (like
ssh-copy-id), see who has access to a server; one shared login such asroot@dc1for many connections, shared with colleagues without revealing it, with password rotation on all its servers. - Jump hosts (like
ssh -J): reach servers behind a bastion, also in chains — for terminals, files, transfers and tunnels. Proxies (SOCKS5/4, HTTP CONNECT) as a connection setting, like in PuTTY, also combined with jump hosts; folder defaults for the jump host and proxy of everything in a folder. - Bookmarks for deep directories (like WinSCP): per server, per folder or tag, or global, with variables such as
{name}— one click opens the directory in the file manager orcds there in the terminal. - Notifications when a server goes down or comes back, a password is due for rotation or a new service version is out: in WRM, in the browser, by e-mail, Telegram, Slack / Mattermost, Microsoft Teams, Discord, ntfy, Gotify, Pushover or a signed webhook.
- SSH tunnels (like
ssh -L / -R / -D, PuTTY, mRemoteNG): reach the web interface of a switch, an iDRAC/iLO or a database behind a server; a SOCKS proxy into a whole management network. Web interface connections open such pages with one double-click. - Import your server inventory from CSV / Excel files and NetBox (with tags for environment, site and rack, and sync), and your connections from mRemoteNG (with passwords, folders and SSH tunnels), PuTTY (with proxies) and OpenSSH
~/.ssh/config. Tags filter the sidebar and mark production servers. - Git workspace: which version of which service runs where — compare installations on your servers file by file with GitLab / GitHub or an offline bundle, see what is old, missing or changed by hand, with diffs and notifications — and update, upgrade or roll back them over SSH (backups, atomic writes, checks, automatic rollback, opt-in restarts, maintenance windows), deploy to environments of ordered servers with a reviewed one-shot plan, a dry run, a server-side lock, history and rollback per deploy, or install them on a new server and transfer them between servers with their per-host configuration; a .gitignore helper, and optional CI integration (GitLab / GitHub / Jenkins webhooks, bundles from CI artifacts, deploy through a pipeline).
- AI desktop apps (MCP): connect Claude (desktop or claude.ai), ChatGPT or any other MCP client to WRM — with OAuth or a personal access token, or through the small stdio bridge in the WRM binary. The app gets time-limited access to the servers, mode and scopes you choose; every call goes through the same permission engine, changes wait for your approval (in WRM or in the app), an AI connected indicator shows the session and revokes it with one click.
- AI assistant next to the terminal and the file manager: ask about a server and the assistant reads logs, services, packages and files through WRM's own tools. Read-only, ask before every change (the exact command or a diff, approved, edited or denied by you) or automatic within limits (an allow list, a time and an action limit you opt into). Destructive commands are always refused; administrators decide which modes, providers and models are allowed per connection, folder or tag, and every request, tool call and approval is audited and recorded. Works with the Anthropic API, OpenAI, Azure OpenAI, AWS Bedrock, Google Vertex AI and OpenAI-compatible local models, with the organisation's key or your own.
- Server-to-server copy between two SSH servers, without downloading to your computer first.
- Workspaces: many terminal and file windows side by side, tabs, snapping, saved sessions. Installable as an app (PWA) on desktops, tablets and phones.
- Sharing with roles: give colleagues or guests access to some connections — as Observer, Viewer, Operator or Moderator — without ever revealing the passwords.
- Live collaboration: chat with history, file exchange, voice calls (like Discord/Jitsi), terminal sharing with snapshots, remote keyboard control on request, raised hands and moderation.
- Enterprise security: two-factor authentication, closed registration, admin-managed accounts, password & session policies, account lockout, audit log (with CSV export and SIEM-friendly log lines), SSH host-key verification, encrypted secrets, CSRF protection and strict security headers.
Everything is stored in one local SQLite file. There is no external database, no Docker requirement, no CDN and no cloud account: the binary also serves all scripts and fonts, so WRM works in closed networks.
Supported platforms (prebuilt binaries): Linux (x86-64, arm64, ARMv7/Raspberry Pi, ARMv6, 32-bit), Windows (x86-64, arm64), macOS (Intel, Apple Silicon, Universal), Android arm64 (Termux), FreeBSD (x86-64, arm64), OpenBSD (x86-64).
Quick start
- Download the binary for your system from Releases and optionally verify it: put
SHA256SUMS.txtandSHA256SUMS.txt.signext to it and runwrm-pro-… -release-verify SHA256SUMS.txt(signature and SHA-256), or compare the SHA-256 yourself.gh attestation verify <file> --repo vedranius/web-browser-RDM-publicshows which workflow and commit built it. Run it:
Linux / macOS / FreeBSD / OpenBSD
chmod +x wrm-pro-v13.12.0-linux-amd64 ./wrm-pro-v13.12.0-linux-amd64On macOS, if Gatekeeper blocks the file:
xattr -d com.apple.quarantine wrm-pro-*-darwin-*.Windows (PowerShell), or just double-click the
.exe:.\wrm-pro-v13.12.0-windows-amd64.exeLinux AppImage (x86_64 / ARM64)
chmod +x wrm-pro-v13.12.0-linux-amd64.AppImage ./wrm-pro-v13.12.0-linux-amd64.AppImage # On ARM64 use wrm-pro-v13.12.0-linux-arm64.AppImage instead.Open **http://localhost:8080**. The AppImage runs in a terminal and binds to localhost by default; use
PORTorLISTEN_ADDRto change that. Stop it with Ctrl+C. If FUSE is unavailable, run with--appimage-extract-and-run.Data is stored in
${XDG_DATA_HOME:-$HOME/.local/share}/wrm-pro/, or at your explicitDB_PATH. Replace the AppImage to upgrade; the data and encryption key stay in place. For a boot service use the standalone Linux binary with-install-service.Android (Termux)
pkg install wget wget https://github.com/vedranius/web-browser-RDM-public/releases/download/v13.12.0/wrm-pro-v13.12.0-android-arm64 chmod +x wrm-pro-v13.12.0-android-arm64 && ./wrm-pro-v13.12.0-android-arm64Docker
git clone https://github.com/vedranius/web-browser-RDM-public.git && cd web-browser-RDM-public docker compose up -d # https://<host>:8080 (self-signed certificate)See Docker for details.
- Open **http://localhost:8080** (or
http://<server-ip>:8080). For voice calls from other computers use HTTPS — the quickest way isHTTPS_SELF_SIGNED=1(see Configuration). - Create the administrator account (the first account). After that, self-registration is closed: the administrator creates accounts in Admin panel → Users (or opens registration in Security policies).
- Click + Connection, enter host, user and password or key, then double-click the connection to open it.
On the first start WRM creates, next to the database:
| File | What it is |
|---|---|
remote_manager.db | SQLite database (users, connections, shares, audit log). Mode 0600. |
remote_manager.db.key | Random 256-bit key that encrypts stored passwords, private keys and 2FA secrets. Mode 0600. Back it up separately — without it stored secrets cannot be decrypted. Or set your own key with ENCRYPTION_KEY / ENCRYPTION_KEY_FILE. |
recordings/ | Terminal session recordings (YYYY/MM/<id>.cast.gz, mode 0600), created when the first session is recorded. Location: WRM_RECORDINGS_DIR. |
Locked out? ./wrm-pro-… -reset-password admin prints a new temporary password (add -reset-2fa to also turn off two-factor authentication).
Upgrading from v13.11.0
Replace the executable/AppImage/container and keep the database and encryption key. No database change; a previous version still starts on the database. New command-line options -addon-lint, -addon-lint-json, -addon-new, -addon-id, -addon-dev, -addon-dev-port and -addon-dev-private, and new endpoints under /api/addons/dev/. The addon ids dev, install, drafts, community and users are now reserved; an installed addon with one of those ids keeps working but cannot be installed again under that id.
Upgrading from v13.10.0
Replace the executable/AppImage/container and keep the database and encryption key. Additive migration: new tables addon_http_grants, addon_secrets and addon_http_log; a previous version still starts on the database (it ignores them, and addons with an http block were not installable there). New policy addon_http (all): who may use addons that reach web sites (off, admins, all). Existing addons are unchanged; an addon gets network access only after an update that declares http and a new approval.
Upgrading from v13.9.0
Replace the executable/AppImage/container and keep the database and encryption key. No database change; a previous version still starts on the database. Git workspace installations whose connection was deleted are no longer listed, and deleting a connection now removes its installations. Show saved login and Copy password follow the existing Allow export of passwords & keys policy (allow_secret_export, on by default; administrators always can) and the step-up policy.
Upgrading from v13.8.0
Replace the executable/AppImage/container and keep the database and encryption key. Additive migration: new tables addons_personal, addon_instances, addon_store and addon_windows and new columns files, approved and pending in addons; a previous version still starts on the database (it ignores personal addons, instances and stored values). Installed addons keep working; their files are pinned by SHA-256 the next time they are installed. New policy addon_personal (all): set it to admins or off if users must not install their own addons.
Upgrading from v13.7.0
Replace the executable/AppImage/container and keep the database and encryption key. Additive migration: a new column saved in ai_sessions and an index; a previous version still starts on the database. New settings ai_mcp_later_approval (run: an approval given in WRM after the AI app stopped waiting runs the call at once; repeat keeps the earlier behaviour, where the AI must repeat the call) and ai_keep_saved_sessions (1). Deny in an AI app's approval question is now a final denial; closing the question without an answer still keeps the request in WRM. New endpoints: GET /api/ai/sessions?view=all, POST /api/ai/sessions/{id}/save, GET /api/ai/sessions/{id}/export, and the key ai of /api/me/ui/{key}. A decision on a request that is no longer waiting answers 409 with decided.
Upgrading from v13.6.0
Replace the executable/AppImage/container and keep the database and encryption key. Additive migration: new columns locked_at and lock_failures in auth_sessions and lock_pin_hash in users; a previous version still starts on the database. New settings screen_lock_mode (server), screen_lock_max_minutes (0), screen_lock_pin (1), screen_lock_max_failures (0), appearance_default_theme (graphite) and appearance_custom_css (1); the Business and Enterprise security levels require screen_lock_mode=server and an idle lock of at most 30 / 15 minutes, and Enterprise turns the PIN off. Two behaviour changes: a locked browser session can no longer reach the API until it is unlocked (set screen_lock_mode to remember or browser for the looser behaviour), and a colour theme from an addon is no longer applied to everyone: each user picks it in Settings → Appearance, or the administrator makes it the default (appearance_default_theme=addon:<addon>:theme). The accent colour chosen in Settings → General before v13.7 is carried over into the theme once.
Upgrading from v13.5.0
Replace the executable/AppImage/container and keep the database and encryption key. No migration: the log settings gain main_folders (empty) and guess_operators (on) inside the existing per-server JSON, and a previous version ignores them. Labels of logs under a configured main folder are taken from it before the default patterns.
Upgrading from v13.4.4
Replace the executable/AppImage/container and keep the database and encryption key. Additive migration: a new table log_settings (per connection, encrypted) and new columns title, purpose, resumed_from and file_path in ai_sessions; a previous version still starts on the database. Log folders and journal units configured in the Zabbix dialog are read into the new Log settings until you save them there. New settings ai_show_thinking and ai_auto_titles (both 1). Dates are shown in the EU format by default; pick another in Settings → Date and time format (per browser).
Upgrading from v12.9.0
Replace the executable/AppImage/container and keep the database and encryption key. No database change. New policies: medium_default_engine (native) and medium_build_user (empty). If the original deploy tool was already imported, WRM sets medium_default_engine=original once at the first start and logs it, so projects keep their engine; set it to native in Admin → Policies to deploy with WRM by default. A project with an engine chosen explicitly keeps it. Pulling deploy-config from Git needs DEPLOY_CONFIG_REPO in the Medium settings and a WRM Git source for that repository (with a write token for commit and push).
Upgrading from v12.8.1
Replace the executable/AppImage/container and keep the database and encryption key. No database change. Editing deploy-config in WRM uses the existing medium_native policy (default admins); users without it see the files read-only.
Upgrading from v12.7.1
Replace the executable/AppImage/container and keep the database and encryption key. No database change. The Git check reads the version from the code by default; VERSION.md is only compared when the new checkbox is on. Deployments and updates still write VERSION.md. The first check after the upgrade may need a target refresh to load the older version trees; until then the per-file history is used.
Upgrading from v12.7.0
Replace the executable/AppImage/container and keep the database and encryption key. No database change. Existing deploy-config files keep working; an environment may now add servers: [name, ...] to limit its projects to those servers. Importing a config ZIP still replaces the config directory and removes its Git history, so use Git for changes once the directory is a clone.
Upgrading from v12.6.26
Replace the executable/AppImage/container and keep the database and encryption key. The database gets the table medium_project_engine; a previous version still starts on it (projects switched to the native engine are then deployed by the original tool again, which reads the same server state). Every project stays on the Docker runtime until someone allowed by the new policy medium_native (default admins) switches it to WRM native. New settings medium_command_timeout (300) and medium_transfer_timeout (3600). With step-up on, native deployments, rollbacks and lock releases ask for a confirmation (medium.deploy, medium.rollback, medium.lock_release).
Upgrading from v12.6.25
Replace the executable/AppImage/container and keep the database and encryption key. The database gets the table siem_destinations; a previous version still starts on it (it does not enforce a lockdown, so end a lockdown before going back). Nothing is exported until an administrator adds a SIEM destination. New settings alert_failed_signins (10), alert_failed_signins_minutes (10), alert_break_glass, alert_new_admin, alert_secret_reveal, alert_ai_full_access and alert_audit_off (all on); new notification event security.alert; new command line flags -lockdown / -lockdown-reason and environment variable WRM_LOCKDOWN. Security events (security.*) are now recorded even with audit_enabled off.
Upgrading from v12.6.24
Replace the executable/AppImage/container and keep the database and encryption key. The database gets the tables ldap_directories, ldap_identities, scim_clients, scim_users, scim_groups and scim_group_members; a previous version still starts on it (accounts that sign in with a directory password then cannot sign in, since WRM keeps no password for them). Nothing changes until an administrator adds an LDAP directory or a SCIM client. New setting ldap_sync_minutes (15). Changing an OIDC provider's issuer now asks for its client secret again.
Upgrading from v12.6.23
Replace the executable/AppImage/container and keep the database and encryption key. The database gets the tables oidc_providers and user_identities and the columns users.sso_only, auth_sessions.identity_id and team_members.source; a previous version still starts on it (directory accounts then cannot sign in, since they have no password). Nothing changes until an administrator adds an identity provider. New settings local_login (all), oidc_revalidate_minutes (60) and oidc_unverified_hours (12). The Enterprise level now requires local_login = break_glass; it takes effect only while a directory sign-in is enabled, so nobody is locked out of an installation without one. Releases from this version on are signed and published automatically when a version is merged.
Upgrading from v12.6.22
Replace the executable/AppImage/container and keep the database and encryption key. The database gets the tables teams, team_members and share_teams and the columns users.role, users.break_glass and auth_sessions.step_up_at; a previous version still starts on it (it sees administrators as before, and auditors and operators as ordinary users). Existing accounts keep their rights: administrators stay administrators, everyone else is a User. New settings require_step_up (off; the Business and Enterprise levels require it, so an installation at one of those levels shows it in the security posture until it is turned on), step_up_minutes and break_glass_ips. Scripts that call PUT /api/admin/settings, change roles or delete users with step-up on get 403 {"step_up": true} unless the session confirmed with POST /api/auth/step-up (signing in counts as a confirmation for step_up_minutes). DELETE /api/admin/users/{id} still deletes everything the user owns unless ?transfer_to=<user id> is given.
Upgrading from v12.6.21
Replace the executable/AppImage/container and keep the database and encryption key. The database gets one new table, security_deviations; a previous version still starts on it. Existing installations stay at the Home level and no setting changes until an administrator picks another level in Admin panel → Security (or sets WRM_INITIAL_SECURITY_LEVEL / WRM_SECURITY_LEVEL). New settings security_level, require_https and link_share_max_days; new endpoints GET /api/admin/security and POST /api/admin/security/level. Loosening a policy below the chosen level now needs a reason (_deviation_notes in PUT /api/admin/settings); scripts that set settings at the Home level are not affected.
Upgrading from v12.6.20
Replace the executable/AppImage/container and keep the database and encryption key. No database change. New setting update_signing_keys (empty: only the built-in key). This version has no built-in release key yet, so its self-update still verifies the SHA-256 only and the update dialog says Signature: not checked; the version that adds the key turns the signature check on. New command-line options -release-keygen, -release-sign, -release-verify.
Upgrading from v12.6.19
Replace the executable/AppImage/container and keep the database and encryption key. No database or setting change. Building from source now needs Go 1.26 or newer (go.mod asks for the Go 1.27.2 toolchain, which go downloads by itself when GOTOOLCHAIN allows it).
Upgrading from v12.6.11
Replace the executable/AppImage/container and keep the database and encryption key. No database change. Nothing changes until an administrator sets ai_opencode_sandbox (admins or all) and presses Download and install again in Admin panel → AI assistant → OpenCode agents, which prepares the Docker sandbox. New settings ai_opencode_sandbox and ai_opencode_sandbox_image; POST /api/ai/sessions takes sandbox: true.
Upgrading from v12.6.10
Replace the executable/AppImage/container and keep the database and encryption key. The database gets one new column, users.ai_delegate_training (a user's own choice to allow helper models that may train on prompts); a previous version still starts on it. Nothing changes until an administrator adds an OpenCode Zen provider, turns on delegation (ai_delegate) or installs OpenCode in Admin panel → AI assistant → OpenCode agents. ai_provider_kinds now includes opencode; if you set it yourself, add opencode to allow the new provider. New settings ai_delegate* and ai_opencode*; new endpoints /api/ai/delegate and /api/admin/opencode. OpenCode itself is stored next to the database in <DB>.opencode/.
Upgrading from v12.6.9
Replace the executable/AppImage/container and keep the database and encryption key. No database change. The Workboard is now the canvas itself: your v12.6.9 tiles open as addon windows beside your terminals the first time (from the top right), and tiles you pulled out into panels stay where they are. Broadcast moved from the top bar into 🧰 Tools. /api/me/ui/{key} now accepts values up to 256 KiB.
Upgrading from v12.6.8
Replace the executable/AppImage/container and keep the database and encryption key. The database gets one new table, user_events (each user's in-app notifications, newest 200); a previous version still starts on it and ignores it. Nothing changes on the page until you open ▤ Workboard and add an addon. New policy workboard_ssh_metrics (on): turn it off if the Server load addon must not log in to servers over SSH; servers with Monitoring still show their values. New endpoints /api/me/events and /api/workboard/metrics.
Upgrading from v12.6.7
Replace the executable/AppImage/container and keep the database and encryption key. The database gets one new table, user_ui (your panel layout); a previous version still starts on it and ignores it. Nothing moves: your first layout is built from what the browser remembered in v12.6.7 (the right panel's tab and width, where the AI live view was docked, floating or hidden). New endpoint /api/me/ui/{key}.
Upgrading from v12.6.6
Replace the executable/AppImage/container and keep the database and encryption key. No database or API change. The AI live view now opens as a 🤖 AI tab in the right panel instead of a box at the bottom left; pick Floating in its title bar (or the 🤖 menu) for the old behaviour. Medium's Docker runtime now trusts the WRM host's root certificates (policy medium_host_ca, default on); if runtime preparation failed with certificate verify failed, press Prepare runtime again.
Upgrading from v12.6.5
Replace the executable/AppImage/container and keep the database and encryption key. No database change. Medium now uses the managed Docker runtime by default on Linux and macOS too. An installation whose host runtime (Python virtual environment) is already prepared keeps it; set WRM_MEDIUM_RUNTIME=docker to move it to Docker, or native to keep the host runtime for good. Nothing is installed until an administrator presses Install Docker in Medium step 2; the new policy medium_docker_install (default on) switches that button and the automatic installation off.
Upgrading from v12.6.4
Replace the executable/AppImage/container and keep the database and encryption key. One additive table (medium_activity); a previous binary still starts on the database. POST /api/git/medium/start now answers 202 and starts in the background (poll GET /api/git/medium), and a deploy-config or SSH ZIP uploaded while Medium is busy or not prepared yet is kept and applied at the next start (202, pending). Command output is shown in the Medium activity log to the user who ran it and, for the shared runtime, to every Medium user; set medium_log_output to admins or none to limit that.
Upgrading from v12.6.3
Replace the executable/AppImage/container and keep the database and encryption key. No database change. Blocked commands keep asking under full access until an administrator sets ai_full_access_blocked to deny (Admin panel → AI connections → Blocked commands with full access).
Upgrading from v12.6.2
Replace the executable/AppImage/container and keep the database and encryption key. One additive column (users.ai_full_access); a previous binary still starts on the database. If ai_full_access was already on, it now applies to every AI session (ai_full_access_mode = all, the default); set the mode to AI connections with the Full access scope (connection) in Admin panel → AI connections to keep the v12.6.2 behaviour, or to Users who turn it on themselves (user).
Upgrading from v12.6.1
Replace the executable/AppImage/container and keep the database and encryption key. No database change. Full access stays off until an administrator turns on ai_full_access (Admin panel → AI connections); then edit an AI connection and tick ⚠ Full access. Open sessions of that connection end and the app reopens them with the new rules.
Upgrading from v12.6.0
Replace the executable/AppImage/container and keep the database and encryption key. No database change. Existing AI connections keep their limits. To let an app work without limits, edit its AI connection in Settings → AI connections, press Allow everything (it also ticks No time or action limit), confirm and save; open sessions end and the app opens them again with the new rules. Administrators can forbid connections without limits with ai_auto_until_grant = off.
Upgrading from v12.5.1
Replace the executable/AppImage/container and keep the database, encryption key and Medium directories. One additive table (medium_server_links) is created at start; a previous binary still starts on the database. The native preview uses your existing WRM Git sources and SSH connections and writes nothing to servers. Medium deployments keep running through the original tool.
Upgrading from v12.5.0
Replace the executable/AppImage/container and keep the database and encryption key. No database change. AI connections (MCP) stay off by default; once an administrator turns them on (Admin panel → AI connections), Claude Desktop users pick Claude Desktop in Settings → AI connections, download the extension and install it. An old claude_desktop_config.json entry with the stdio bridge keeps working. Token lifetimes can now be chosen in hours or days. The defaults change from 8 hours (at most 24) to 7 days (at most 30 days): ai_mcp_token_hours 168, ai_mcp_max_token_hours 720. A value an administrator saved explicitly stays in force; lower them again in Admin panel → AI connections if your policy needs short lifetimes.
Upgrading from v12.4.5
Replace the executable/AppImage/container and keep the database, encryption key and private Medium directories/volumes. No database migration. Medium settings saved empty now mean "original default" and are no longer passed to the tool; earlier .previous copies of replaced SSH profiles are deleted at the next Medium start. Stamp no longer refuses silently: choose Also stamp installations that are not up to date to stamp an installation as it is.
Upgrading from v12.4.4
Replace the executable/AppImage/container, preserving your database, encryption key and private runtime directories/volumes. No database migration is needed. In Medium use the combined ZIP fields and Prepare and run; empty fields reuse existing imports. Setup failure retains approved archives for retry. Existing original-tool deployment history and behavior are retained.
In Monitoring select Logs and a server. Discovery uses the same SSH account without sudo; it finds known service log/logs directories, bounded configured service roots and Supervisor log directories. Manual roots remain editable from the log toolbar. Date/timezone filters and keyword search read historical segments across matching logs, rather than only their recent tail. Progress and bounds remain visible. Zabbix is needed for host metrics, not SSH logs.
Windows first setup can require Docker/WSL license, OS permissions, virtualization setup or a restart on the WRM host. A Windows service cannot display a desktop installer: install Docker once for its account, then resume. Docker in Windows-container mode is not switched automatically because other containers may be using it. See the guide.
Upgrading from v12.4.3b
Replace the executable/container with v12.4.4 and retain the DB, encryption key and private runtime directories/volumes. Migrations are additive. Existing explicit policy values remain in force; MCP is still off by default. Functionality moves to Monitoring → Functionality. Configure each server's agent transport/log roots; automatic metrics polling is opt-in.
Client GitLab cache requires a client token and browser CORS permission or the companion on the computer that can access GitLab. Native Medium's Git/build subprocesses still need their direct route. v12.4.4 setup, limits and troubleshooting.
Upgrading from v12.4.3
Download the v12.4.3b Windows executable, stop WRM and replace the previous executable while retaining its database and encryption key. The v12.4.3 updater cannot parse the b suffix, so this first hotfix needs a manual download. v12.4.3b adds letter-hotfix support for subsequent checks/updates.
For Windows 10/11, install/start Docker Desktop with Linux containers under the account running WRM. In Git → Medium, import the original tool ZIP or, if it is already imported, click Prepare runtime / retry. WRM pulls the pinned Linux image and installs the original lockfile in a Linux volume. Import your deploy-config and SSH profile and start Medium. Standard ~/.ssh/key references work inside its private Linux home. No Windows Python/rsync installation is needed. Browser clients need no deploy tools.
Docker Desktop is not supported on Windows Server: run WRM/Medium on a supported Linux host or Linux VM/container and access it from the Windows browser. A remote Docker daemon is not supported by this bind-mount/localhost bridge. Docker engine access must belong to the account running WRM; installing Docker for a different desktop account does not grant a Windows service access automatically.
Back up the database/key and private .medium source/config/preferences plus Docker volumes named wrm-medium-<instance>-runtime and wrm-medium-<instance>-u<user>. Stop Medium before backing up user volumes. Runtime source/venv are read-only; user volumes retain native edits/history across restarts. Re-importing config/SSH replaces that profile explicitly without deleting deploy history. Existing native Linux runtime data is copied into a new user volume on its first Docker start. Source and SSH keys remain private.
Linux keeps its native runtime when dependencies exist; use WRM_MEDIUM_RUNTIME=docker to select the managed runtime or native to select native explicitly. Windows always selects Docker. Custom Docker paths/images use WRM_MEDIUM_DOCKER and WRM_MEDIUM_CONTAINER_IMAGE. The Windows CLI is also discovered at standard Docker Desktop installation paths without requiring a PATH refresh. Additional build toolchains/users may require a trusted custom Linux image; the pinned image uses its unprivileged wrm account for builds. Unix host-agent forwarding remains a native-runtime option; managed Docker uses the private SSH profile.
Upgrading from v12.4.0
Replace the binary/AppImage or update the container. Additive migrations create git_config_profiles and add folders.sort_order. Existing folders retain alphabetical order until reordered. Back up the database, matching encryption key and adjacent .medium / .bitwarden directories; they contain private runtime/configuration data. Older binaries ignore the new fields, but cannot use the new features.
Medium is enabled for administrators by default. Import the original deploy-tool ZIP once as an administrator, then each operator imports their deploy-config and optional SSH profile. The Docker image includes Python 3.12+, git, OpenSSH, rsync and the official Bitwarden CLI. Standalone binaries keep these dependencies optional: install them on the WRM host before enabling the corresponding feature. Medium uses the original engine's own plans, locks, backups and history; it does not import those into Simple/Advanced runs.
The earlier client GitLab relay/replay and AI/navigation/color/icon requests are delivered in v12.4.4; see the operation guide.
Upgrading from v12.3.6
Replace the binary or use the in-app updater; update the AppImage/container as appropriate. Startup adds a nullable folder parent and the git_server_health cache table. Existing folders, catalogs and route defaults keep their settings; previous binaries ignore the new fields.
The new Functionality view is available from Git Simple and Advanced. Run a Git check to populate it, and enable periodic monitoring/notification subscriptions if desired. Runtime commands read service state with the SSH login's permissions; no services are started or restarted. For AI availability, open Settings → AI assistant; provider connectivity and effective account permission are shown separately.
Upgrading from v12.2.8
Replace the binary. One additive table (git_hostnames) is created automatically; v12.2.8 still starts on the same database. No configuration changes.
- Git Simple mode is automatic. Services and environments the checker found on your servers appear as ready cards without defining environments per service; Save detected environments stores them in the catalog (audited). Advanced is unchanged and your own definitions keep priority.
- Servers are shown by hostname (read once over the existing SSH login and cached, falling back to the connection host) instead of the connection name.
Upgrading from v12.2.7
Replace the binary. No database or configuration changes; v12.2.7 still starts on the same database.
- The version label in the top bar ("WRM v12.2.8") now opens the Updates dialog, so an administrator can always press Check now, even when no update is known and the green badge is hidden. Non-administrators see the versions only.
Upgrading from v12.2.6
Replace the binary. One additive table (ai_ollama_runs) is created automatically; v12.2.6 still starts on the same database. No configuration changes.
- The AI provider wizard has presets for xAI, DeepSeek, Together AI, Fireworks AI, Cerebras, Cohere and Perplexity, refreshed model suggestions and a Load the model list button (the provider's
/models). Models can always be typed freely. - Ollama, step by step: detection, status, installed models, per-OS install / background-service / download commands and, optionally, running them through WRM. The last is off by default: an administrator enables the policy
ai_ollama_manage(WRM_AI_OLLAMA_MANAGE=1). Each run needs a confirmation, is permission-checked on the server and written to the audit log (admin.ai_ollama_*). See the configuration table and the API reference below.
Upgrading from v12.2.5
Replace the binary. No database or configuration changes; v12.2.5 still starts on the same database.
- Settings → AI connections now has a step-by-step wizard for connecting Codex CLI, Claude Code, Gemini CLI, Cursor / VS Code, Claude and ChatGPT: it creates the token, shows (and lets you download) the ready command or config file and tests the connection. The AI assistant has a matching provider wizard. See Connect an AI app below.
- The MCP server explains what "wrm" is to its clients, and permission denials now say which scope is missing and how to fix it.
Upgrading from v12.2.4
Replace the binary. No database or configuration changes; v12.2.4 still starts on the same database.
- The AI assistant window inside a terminal window can now be docked left / right / top / bottom, floated, moved, resized and expanded over the whole terminal window. See AI assistant below.
Upgrading from v12.2.3
Replace the binary. No database or configuration changes; v12.2.3 still starts on the same database.
- The session recording replay window can now be resized (drag its bottom-right corner) and expanded to fullscreen (⛶ button, Esc leaves). The terminal is scaled to the window width, so there is no sideways scrolling. See Session recording below.
Upgrading from v12.2.2
Replace the binary. No database or configuration changes; v12.2.2 still starts on the same database.
- Every tab of the Advanced Git workspace, of Settings and of the Admin panel now has a short explanation of what it is for. See Git workspace: tab explanations.
Upgrading from v12.2.1
Replace the binary. No database or configuration changes; v12.2.1 still starts on the same database.
- The Git workspace has a Simple / Advanced switch in its header. Simple shows one guided card per service environment (what runs on the server vs. the latest version on the branch, a clear status) with Install / Update / Deploy again and Roll back to the previous version. Advanced is the unchanged Git workspace and stays the default. See Git workspace: Simple mode.
Upgrading from v12.2.0
Replace the binary. No database or configuration changes.
- New terminal windows open maximized with the cursor in the terminal; windows of a saved session keep their layout.
- Selecting more text than fits on the screen now copies the whole selection (it is copied when you release the mouse).
- A click or double-click on the title bar of a maximized window no longer shrinks it; only dragging restores it.
Upgrading from v12.1.0
Replace the binary. There are no database changes; v12.1.0 still starts on the same database.
- Gemini and other OpenAI-compatible providers work with tools: the provider's
extra_content(Gemini'sthought_signature) of each tool call is stored in the session and sent back unchanged, which fixes HTTP 400: Function call is missing a thought_signature. - Temporary provider errors no longer end the turn at once: HTTP 408 / 429 / 5xx (for example 503 high demand) are retried up to three times with a back-off, and a request that is too large for the provider (HTTP 413, or a token limit such as Groq's) shortens the long command output of the conversation and is retried. The assistant shows a short notice for both.
Upgrading from v12.0.0
Replace the binary. The database gets new tables (mcp_tokens, mcp_clients) and the column ai_sessions.mcp_token_id; v12.0.0 still starts on it and ignores them.
- AI desktop apps (MCP) are off by default. An administrator turns them on in Admin panel → AI connections (
ai_mcp_enabled); by default only administrators may create AI connections (ai_mcp=admins), with the modesread_only,ask,auto(ai_mcp_modes), a default lifetime of 8 hours (ai_mcp_token_hours) and at most 24 hours (ai_mcp_max_token_hours; since v12.5.1 the defaults are 7 and 30 days). Users then find Settings → AI connections. See AI desktop apps (MCP). - MCP clients reach WRM at
https://<your WRM>/mcp. Hosted connectors (claude.ai, ChatGPT) connect from the provider's cloud: WRM must be reachable from the internet over HTTPS for them. Behind a reverse proxy setai_mcp_public_url(the address the apps use) and pass/mcp,/oauth/and/.well-known/through. Desktop apps with the stdio bridge only need to reach WRM from your computer. - The kill switch of the AI assistant (
ai_kill_switch) also stops every AI connection. Turning off the built-in assistant (ai_assistant) does not turn off MCP, and the other way round. - The top bar shows 🤖 AI connected while an AI app is connected; at narrower widths the top-bar labels hide a little earlier than before so nothing overlaps.
Upgrading from v11.7.0
Replace the binary. The database gets new tables (ai_providers, ai_sessions, ai_messages) and the column users.ai_blocked; v11.7.0 still starts on it and ignores them.
- AI assistant (off by default). An administrator turns it on in Admin panel → AI assistant (
ai_assistant=adminsorall) and adds the organisation's provider (Anthropic, OpenAI, Azure OpenAI, AWS Bedrock, Google Vertex AI or an OpenAI-compatible endpoint). Users then get an AI button in the title bar of SSH terminals and file managers. See AI assistant. - New modes are restrictive by default:
ai_modes=read_only,ask(the automatic mode must be allowed explicitly), personal API keys are off (ai_personal_keys), output is redacted before it is sent to the provider (ai_redact_output). - Consumer chat subscriptions (Claude.ai, ChatGPT) cannot be used by WRM or any other third-party application: use an API key, an enterprise gateway, or the MCP integration of v12.1.0 (AI desktop apps).
- AI sessions appear in Sessions & recordings with an ✦ AI mark (the transcript is recorded like a terminal) and in the audit log as
ai.*events. - The top bar no longer overlaps the New window button at about 1100 px.
Upgrading from v11.6.1
Replace the binary (or use the new one-click update from the next release on); the database does not change.
- Run as a service: on an interactive start WRM asks once whether to install itself as a service that starts at boot (systemd, launchd, rc.d or a Windows service; Don't ask again is remembered in
<DB_PATH>.service.json). Scripts use-install-service,-uninstall-serviceand-service-status;-no-service-promptskips the question. See Service.sudo wrm -setup-docker [-service-user ACCOUNT](Linux) installs Docker Engine for Medium, lets the WRM account use it and restarts the WRM service. - Updates: WRM checks the project's GitHub releases once a day (no user data is sent). The version in the top bar shows ⬆ Update vX.Y.Z with the release notes; administrators update with one click (SHA-256 checked against
SHA256SUMS.txt, previous binary kept for a rollback). Air-gapped installations:WRM_UPDATE_CHECK=off. Docker never replaces itself. See Updates & self-update. - 📂 in an SSH terminal is now a menu: Open here, Open /, Open home. "Here" works without configuring OSC 7. See Windows, tabs & snapping.
- A systemd unit that runs WRM with
ProtectSystem=strictneeds the binary's folder inReadWritePathsfor the one-click update (units written by-install-servicehave it).
Upgrading from v11.6.0
Replace the binary; the database does not change.
- 📂 in the title bar of SSH terminals opens the file manager of the same server, in the terminal's current directory when the shell reports it (OSC 7) (#24). See Windows, tabs & snapping.
Upgrading from v11.5.0
Replace the binary; the database does not change.
- Activity tab in the Git workspace with three views — Git activity (pushes and commits per branch and author from the Git server), Deploy history (the
history.jsonlof every environment destination merged with the WRM runs of installations without environments) and What is where (branch, commit, version, who and when per environment and server, commits behind the branch head, drift). Each view has a CSV export of what its filters show. See Git workspace: activity, deploy history & what is where. - Gitea sources: a Git source can now be a Gitea server (API v1,
Authorization: token …). Targets, comparisons, deploys and the activity work as with GitHub; a .gitignore pull request is not available for Gitea yet (download the file). - The activity reads the provider API with the source's read-only token; for GitHub repository activity (pushes, force pushes) the token needs read access to the repository's metadata, otherwise only commits are shown. The deploy history and the matrix read the destinations over SSH like the Environments tab and need the
git_checkspolicy; without it only WRM's own records are shown. - No new settings or policies.
Upgrading from v11.4.1
Replace the binary. The database gets one new table (git_env_exclusions); the previous binary still starts on it and ignores it. Catalogs and installations without environments work exactly as before.
- Environments (optional): a service of the catalog can get named environments — ordered destinations
server:/path(the server is the name of an SSH connection) with rules: typed confirmation,allowed_refs, extra ignore patterns, an optionalpost_deploycommand and the number of backups to keep. Add them on the new Environments tab (✎) or in the catalog JSON (apps[].environments). See Git workspace: environments, deploy plans & safe deploys. - Server-side state: an environment deploy keeps its state next to the installation, by default in
<path>/.deploy-bak(the existing backup directory):state.json,history.jsonl,deploys/<id>.json,backups/rollback-<id>/and the lock.lock/. Backups keep the existing<id>-<YYYYMMDD-HHMMSS>layout, andVERSION.md/updates.jsonlare written as before, so file-based tools keep working. - Anchored patterns: an exclude or ignore pattern that starts with
/now matches the whole relative path only (/lib/a.pydoes not matchx/lib/a.py). Exclude permanently writes such patterns; existing patterns are unchanged. - The same policies apply:
git_update(deploy),git_upgrade(deploy of another ref),git_rollback,git_restart. Environment deploys run right away (no scheduling); use a dry run to preview.
Upgrading from v11.4.0
Replace the binary; the database does not change.
- Clipboard history per user: the Clipboard panel now keeps its history per signed-in user, and signing out removes it from the browser (#30). The browser-wide history of earlier versions is deleted on the first sign-in, so the panel starts empty once.
Upgrading from v11.3.0
Replace the binary. The database gets two new columns of git_installs (last_ok_at, last_ok_state); the previous binary still starts on it and ignores them.
- Git sources lost by the v11.3.0 upgrade come back: upgrading a database from v11.2.0 or earlier to v11.3.0 set the
git_sourcestable aside asgit_sources_old_<time>. On the first start, v11.4.0 restores those sources (with their encrypted tokens) when no source exists yet; the old table is renamed togit_sources_restored_<time>. - Every file of an installation: the details list every file of the server folder and of the repository, with the reason for each state, and diff any repository file (also the ones the catalog excludes). Refresh the targets once so the targets keep their full commit and the repository files outside the catalog are listed too. See Git workspace: every file and partial checks.
- Partial checks: select installations, servers or services and check only those (or only stale ones); results stream in and can be cancelled. Two new settings:
git_check_parallel(8) andgit_check_per_server(2).
Upgrading from v11.2.0
Replace the binary. The database gets two new tables (git_feeds, git_pipelines) and four new columns of git_sources (write_token, hook_id, hook_secret, hook_at); the previous binary still starts on it and ignores them.
- .gitignore helper: a new .gitignore tab in the Git workspace. The output is a download; a merge / pull request needs an optional write token on the Git source and the new policy
git_gitignore_mr(administrators only by default). See Git workspace: .gitignore helper. - Optional CI integration: a webhook per Git source, bundles fetched from CI artifacts, and the deploy method CI pipeline per service. All of it is off until you set it up; WRM works without any CI. See Git workspace: CI integration (optional).
- Webhooks arrive at
/api/hooks/git/<id>: if WRM is behind a reverse proxy that only forwards some paths, forward this one too. - Checks now also record the size of files found only on servers; installations show it after their next check.
Upgrading from v11.1.0
Replace the binary. The database is unchanged: installs and transfers are stored as runs in git_runs; the previous binary still starts on it.
- New servers from the Git workspace: Install… on the Installations tab (a wizard: server, services with their version, target directory, pre-checks, per-host files from templates / copies / typed, optional systemd or supervisor unit, optional start) and Transfer… for an installation (copy it to another server with its per-host configuration). See Git workspace: new servers (install & transfer).
- New policies
git_installandgit_transfer— administrators only by default; change them in Admin panel → Policies. - Installs and transfers send the existing run notifications (Git: … started / succeeded / failed) and are audited as
git.install/git.transfer.
Upgrading from v11.0.0
Replace the binary. The database gets two new tables (git_runs, git_pending_restarts); the previous binary still starts on it and ignores them.
- Deploying from the Git workspace: Update, Upgrade…, Rollback…, Restart… and Stamp on the Installations tab and in the details of an installation, a new Runs tab, and scheduled runs. See Git workspace: update, upgrade, rollback & restarts.
- New policies
git_update,git_upgrade,git_rollback,git_restart— administrators only by default; change them in Admin panel → Policies — andgit_schedule_grace_minutes(30). - New notification events for runs and restarts (Git: an update, upgrade or rollback started / succeeded / failed, a service restart is scheduled / done, a scheduled run starts soon) in Settings → Notifications.
- WRM writes on servers only when you start or schedule a run; checks stay read-only.
Upgrading from v10.10.0
Replace the binary. The database gets new tables (git_sources, git_trees, git_blobs, git_workspace, git_targets, git_installs); the previous binary still starts on it and ignores them.
- Git workspace: the new ⎇ Git button in the top bar compares the services installed on your servers with GitLab / GitHub or an offline bundle, file by file and read-only. See Git workspace.
- It is on for everyone. Administrators can hide it (
git_enabledoff, orWRM_GIT_ENABLED=0) or limit checks to administrators (git_checks). - New notification events Git: a new version is available, Git: files changed by hand on a server and Git: a server is unreachable for checks in Settings → Notifications.
Upgrading from v10.9.1
Replace the binary. The database gets a new table bookmarks; the previous binary still starts on it and ignores it.
- Folder bookmarks: ★ next to the path bar of the file manager and in a terminal's title bar. Bookmark this directory… saves the current folder for one connection, a folder, a tag or all connections; paths may use
~,$USER,{host}and{name}. A bookmark can be the start directory of a connection. See Folder bookmarks. - WinSCP bookmarks: ★ → Manage bookmarks… → Import WinSCP.ini adds the remote directory bookmarks of a WinSCP configuration as global bookmarks.
- Bookmarks are part of Export / Import.
Upgrading from v10.9.0
Replace the binary. The database gets a new table putty_sessions and a column connections.putty_session; the previous binary still starts on it and ignores them.
- Import from PuTTY: Settings → Data → Import from PuTTY reads a
.regexport of your saved PuTTY sessions, with their proxies. See Import from mRemoteNG, PuTTY and OpenSSH. - mRemoteNG connections imported before v10.9.1 do not remember their PuttySession, and importing the file again skips them as existing: give them the proxy by hand (or through their folder's default proxy).
Upgrading from v10.8.1
Replace the binary. The database gets new tables (proxies, proxy_grants, notify_channels, notify_subscriptions, notify_prefs, notify_pending, notify_state) and columns (connections.proxy_id, folders.jump_conn_id, folders.proxy_id); the previous binary still starts on it and ignores them (connections then go without their proxy and folder defaults).
- Proxies: define SOCKS5, SOCKS4/4a or HTTP CONNECT proxies (or a SOCKS tunnel of a connection) under 🔑 SSH keys & credentials → 🌐 Proxies and choose one in a connection (Proxy, next to Jump host). See Proxies.
- Folder defaults: right-click a folder → Folder settings… to give it a default jump host and proxy. Connections in the folder that have no jump host of their own then use the folder's (existing connections without a jump host included). Choose no jump host (not the folder's) where a connection must stay direct.
- Notifications: an administrator adds channels in Admin panel → Notifications (e-mail, Telegram, Slack / Mattermost / Rocket.Chat, Teams, Discord, ntfy, Gotify, Pushover, webhook); users subscribe in Settings → Notifications. Nothing is sent until both happened. See Notifications.
- Docker:
docker-compose.ymlnow mapshost.docker.internalto the Docker host (extra_hosts), for proxies that run on the host. - Deleting a jump host now makes the connections that used it fall back to their folder's default jump host (or go direct).
Upgrading from v10.8.0
Replace the binary. Nothing changes in the database.
- Larger imports work: mRemoteNG, OpenSSH config and inventory (CSV / Excel) files up to 20 MB import again (from about 1 MB on they failed with Bad JSON). A larger file gets a clear message with its size and the limit, already in the browser.
- Install as an app (Settings → General) now shows the steps for your browser, or the reason why installing is not possible here (plain
http://to an address other thanlocalhost, an untrusted certificate, Firefox on the desktop). The Install button appears only when the browser can install right away. To get HTTPS quickly, see HTTPS with Caddy. - A reverse proxy in front of WRM must allow request bodies of at least 32 MB for imports (
client_max_body_size 0;in the nginx example does).
Upgrading from v10.7
Replace the binary. The database gets two new columns (connections.notes, connections.temp_until); the previous binary still starts on it (it shows quick connections as normal ones).
- ⚡ Quick connect field at the top of the sidebar:
user@host:port+ Enter. - 📝 Notes in the connection dialog and in the right-click menu; a 📝 next to a connection opens them.
- 🧰 Tools in the top bar, and Network tools from this server… / Check ports of this host in the right-click menu (policy
network_tools, default: all users). - Install as an app: Settings → General, or the install icon of the browser's address bar (needs HTTPS with a trusted certificate, or
localhost).
Upgrading from v10.6
Replace the binary. The database gets one new column (connections.bmc); the previous binary still starts on it.
- Connections can have a BMC (Edit → Out-of-band management); right-click → Power & status (BMC)… and Serial console. For IPMI install
ipmitoolon the WRM server or on the jump host (apt install ipmitool). - New protocol Serial port for console cables on the WRM machine (administrators by default, policy
serial_ports). - Saved workspace sessions now really keep remote desktop windows (and console windows).
Upgrading from v10.5
Replace the binary. The database gets three new columns (connections.tags, ext_id, ext_tags) and a table inventory_sources; the previous binary still starts on it (it ignores the tags).
- Connections have tags; the sidebar shows a tag filter and an environment badge (
env:prod…). See Tags & inventory import. - Settings → Data → Import inventory: CSV / Excel files and NetBox.
Upgrading from v10.4
Replace the binary. The database gets new tables (ssh_keys, ssh_key_deployments, credentials, credential_grants) and two new columns (connections.key_id, connections.credential_id); the previous binary still starts on it (connections that use the new login types then cannot log in).
- New 🔑 Keys button: your SSH key store and the credentials vault. See SSH keys & credentials vault.
- Connections can log in with an SSH key from the key store or a credential from the vault; remote desktops and FTP can use vault credentials too.
- Deleting an account now also deletes its snippets, tunnels, keys and credentials.
Upgrading from v10.3
Replace the binary. The database gets one new column (connections.options); the previous binary still starts on it.
- Remote desktops need guacd next to WRM:
apt install guacd(Debian/Ubuntu),docker run -d --network host guacamole/guacd, or theguacdservice thatdocker-compose.ymlnow contains. Without guacd everything else keeps working; opening an RDP/VNC/Telnet connection then explains what is missing. See Remote desktop. - Importing from mRemoteNG now also brings RDP, VNC and Telnet connections (with domain, console, colors and RD Gateway).
- SQLite now waits up to 10 s for a busy database on every connection (fixes rare database is locked errors under load).
Upgrading from v10.2
Replace the binary. The database gets a new table (snippets) and one new column (connections.monitor); the previous binary still starts on it.
- File names no longer carry a suffix: releases are
v10.3.0, binarieswrm-pro-v10.3.0-linux-amd64etc. Update scripts and systemd units that use the file name. - Live status is on by default: WRM opens a TCP connection to every saved host:port once a minute (SSH and FTP: it reads the greeting and closes politely, like Nagios
check_ssh). Servers see it in their logs. Change the interval or turn it off in Admin panel → Security policies → Live status, or untick Monitor up/down status in a connection. See Live up/down status about fail2ban. - Broadcast input is available to everybody; turn it off with
broadcast_enabledif you do not want it. Every start and stop is in the audit log.
Upgrading from v10.1
Replace the binary. The database gets a new table (connection_tunnels) and two new columns on connections (jump_conn_id, web_path); nothing else changes. To go back, run the v10.1 binary on the same database; it does not know these features (connections behind a jump host then try to connect directly, web interface connections cannot be opened, tunnels do not run).
- New: jump hosts, SSH tunnels, web interface connections and import from mRemoteNG / OpenSSH.
- Tunnels are on by default for all users, listening on
127.0.0.1of the WRM machine only. Remote forwards (-R) and listening on network addresses are limited to administrators. Review Admin panel → Security policies → SSH tunnels — e.g. turn tunnels off (WRM_TUNNELS_ENABLED=0) or limit them to administrators if WRM runs on a shared server. - Jump hosts need
AllowTcpForwarding yeson the bastion (the OpenSSH default), exactly likessh -J.
Upgrading from v10.0
Replace the binary. The database is extended automatically (new tables, columns and triggers only — nothing is changed or removed; the previous binary still runs on the upgraded database).
- Terminal sessions are now recorded by default (
session_recording). Users see “This session is recorded” and a ● REC badge on the terminal. Inform your users (in many countries this is required), or turn it off in Admin panel → Security policies → Session recording. Keystrokes are not recorded unless you turn on Record keystrokes. - Recordings use disk space next to the database (
recordings/, typically a few KB to a few MB per session; limit per sessionrecording_max_mb, keptrecording_retention_days= 90 days). Back up or exclude that folder as you need. - The audit log is now append-only and hash-chained. Admin panel → Audit log → Verify integrity checks it. Entries written before the upgrade have no hash and are skipped by the check.
- Every upload, download (also files opened in the editor and files in ZIP downloads) and server-to-server copy is logged in Admin panel → File transfers with size and SHA-256.
- New:
/healthzfor load balancers and monitoring,wrm -healthcheckfor container health checks, aDockerfileanddocker-compose.yml.
Upgrading from v9
Replace the binary and start it with the same database and the same ENCRYPTION_KEY (if you set one). Everything is migrated automatically. Things to know:
- Stored secrets are re-encrypted. Without
ENCRYPTION_KEY, v9 used a public default key. v10 generates a random key file (remote_manager.db.key) and re-encrypts all secrets with it on the first start. Back that file up. (If you did setENCRYPTION_KEY, nothing changes.) - Self-registration is closed by default. Existing accounts keep working. Open it again in Admin panel → Security policies if you want it.
- Passwords and keys are no longer sent to the browser. The Edit connection dialog shows “saved and encrypted — leave empty to keep it”. Export is without secrets; Export with passwords & keys asks for your password.
- SSH host keys are verified (trust on first use). The first connection to each server remembers its key; a changed key is refused until you accept it.
- Key file / Auto (~/.ssh) authentication (keys stored on the WRM server) is limited to administrators unless the policy Allow server key files for all users is on.
- Existing shares keep their behaviour (anyone with the link, role Operator). Edit them to use the new access modes and roles.
- Behind a reverse proxy: state-changing API calls now require the
Originto match theHost(like WebSockets already did). Pass theHostheader, or setWRM_ALLOWED_ORIGINS. SetWRM_TRUST_PROXY=1so rate limits and the audit log see real client IPs. - The per-IP sign-in limit is now 20 failures / 10 minutes; accounts additionally lock for 15 minutes after 10 wrong passwords (policy).
- If the database comes from an earlier build that already had tables named like the new v10 tables (
audit_log,collab_messages, …) but with a different layout, WRM keeps them as<table>_old_<time>and creates new ones (logged as Upgraded table …). Nothing is deleted. - The app is served at
/. Old bookmarks to/static/are forwarded there.
How it works
Browser (any device) WRM server (one binary) Your servers
┌──────────────────────┐ HTTPS/HTTP ┌──────────────────────────────┐ SSH / SFTP ┌───────────┐
│ Web UI (embedded │ ─────────────▶ │ REST API (/api/...) │ ─────────────▶ │ Linux/BSD │
│ single-page app, │ │ WebSockets: │ FTP / FTPS │ servers, │
│ xterm.js terminal) │ ◀───────────── │ /ws/ssh terminal │ ─────────────▶ │ NAS, ... │
│ │ WebSockets │ /ws/share/ collaboration │ └───────────┘
└──────────┬───────────┘ │ /ws/events live updates │
│ voice (WebRTC, DTLS-SRTP) │ TURN relay UDP/TCP 3478 │
└────────────────────────────┤ SQLite: users, connections, │
peer-to-peer or via relay │ shares, audit log, settings │
└──────────────────────────────┘
- The WRM server makes the connections. Your browser talks only to WRM, and WRM talks to your servers with SSH (
golang.org/x/crypto/ssh), SFTP (pkg/sftp) and FTP (jlaffaye/ftp). Your servers only need to be reachable from the WRM machine. - Terminal: every terminal window is a WebSocket (
/ws/ssh) bound to one SSH session with a PTY. Keystrokes and output go as binary frames, so large outputs and multi-byte UTF-8 are never corrupted. The PTY size follows the window. - Flow control: when a command prints faster than the browser can draw, the browser asks the server to pause and resume. Nothing is lost.
- File operations use a small pool of SFTP connections per saved connection (reused for 5 minutes and health-checked). Uploads are streamed; downloads and ZIP archives are streamed to the browser.
- Secrets at rest (connection passwords, private keys, 2FA secrets) are AES-256-GCM encrypted. Session tokens are stored only as SHA-256 hashes.
- Collaboration:
/ws/share/{token}is the room of a share. The server decides identities and roles and relays chat, files, terminal streams (only to people watching them), remote-control keystrokes (only to the person who granted control) and voice signalling. - Jump hosts and tunnels: WRM logs in to the jump host, opens an SSH
direct-tcpipchannel through it and runs a second, separately encrypted SSH session inside it (likessh -J). Tunnels listen on the WRM machine (local / SOCKS) or on the SSH server (remote) and forward every connection through SSH. Tunnel ports are opened by WRM, not by the browser. - Voice: audio flows directly between browsers (WebRTC, end-to-end encrypted with DTLS-SRTP). When browsers cannot reach each other (NAT, firewalls), the built-in TURN relay carries the still-encrypted audio.
Features in detail
Accounts, sign-in & two-factor authentication
- The first account becomes administrator. Afterwards self-registration is closed (policy); administrators create accounts, optionally with a generated temporary password that must be changed at the first sign-in.
- Passwords are stored as bcrypt hashes (cost 12). Minimum length is a policy (default 8).
- Two-factor authentication (TOTP) with any authenticator app (Google/Microsoft Authenticator, 1Password, Bitwarden, FreeOTP…): Settings → Security → Two-factor authentication. A QR code is shown; 10 single-use recovery codes are generated. Codes cannot be replayed. Administrators can require 2FA for administrators or for everyone — users without it must set it up at their next sign-in.
- Brute-force protection: 20 failed sign-ins from one IP within 10 minutes lock that IP for 5 minutes; an account locks for 15 minutes after 10 wrong passwords (policy). Failed sign-ins take the same time whether the user exists or not.
- Sessions: HttpOnly, SameSite cookie (
Secureon HTTPS); the database only stores a hash of the token. Sessions end after inactivity (default 7 days) and after a maximum age (default 30 days) — both policies. Settings → Security lists your signed-in devices and signs out one or all others. Changing your password signs out every other device. - If your login expires while terminals or transfers are running, WRM shows a message instead of reloading the page.
Connections & folders
Folders can have a Parent folder (up to 32 levels); right-click a folder to create a subfolder or edit its parent. The sidebar renders the hierarchy and connection pickers show the complete folder path; tabs and window titles show only the connection's name, with the folder path in their tooltip. The row above connection tabs filters open tabs/windows by folder and focuses its most recently used window. Config export/import and new mRemoteNG imports preserve nesting. Deleting a folder moves its child folders to its former parent and keeps their connections. Sharing a folder includes descendants; jump/proxy defaults apply to the immediate folder only.
Left sidebar ("PRO MANAGER"):
- + Connection creates a connection:
- Protocol:
SSH(terminal, plus files over SFTP),SFTP(opens the file manager by default), 🖥 RDP, 🖥 VNC, Telnet (see Remote desktop), 🔌 Serial port of the WRM server (see Serial ports),FTP,FTPS(FTP with explicit TLS; file manager only), 🌐 Web interfaceHTTPS/HTTP(see Web interfaces). - Host : Port (default port 22 for SSH/SFTP, 21 for FTP/FTPS, 443/80 for web interfaces), Username, Folder, Tags (comma separated, e.g.
env:prod, site:dc1, rack:a12, web; the most used tags are offered below the field). - Jump host (connect via): another saved SSH connection to go through (see Jump hosts).
- Proxy: a saved SOCKS / HTTP proxy for everything the connection does over TCP (see Proxies). With a jump host the proxy is reached through it; the dialog shows the route, e.g.
⤳ Route: bastion → socks5://10.1.1.1:1080 → app-01. - Both show — as the folder: … — when the folder has a default (see below); no jump host / no proxy (not the folder's) overrides it.
- 🔀 SSH tunnels: port forwards of this connection (see SSH tunnels).
- ⚡ Out-of-band management: the BMC of the server (see Out-of-band management).
- 📝 Notes & runbook: procedures, contacts, links (see Notes).
- Authentication: Password, Private key (paste), Key file (path on the WRM server), Auto (tries
~/.ssh/id_rsa,id_ed25519,id_ecdsa,id_dsaof the WRM server user), 🔑 SSH key from the key store or 🗝 Credential from the vault (see SSH keys & credentials vault). Key file and Auto use keys of the WRM server itself and are therefore limited to administrators (policy). Password authentication also answers keyboard-interactive prompts. RDP, VNC, Telnet and FTP log in with a password or a vault credential. - Use the server's hostname as the name: leave the name empty; after saving, WRM logs in once and reads the hostname (SSH, SFTP), or looks the address up in DNS (other protocols, or the first label of a typed host name), and names the connection after it. Until then the address is the name. A host key that is not known yet is shown for approval first. Rename to the server's hostname in the connection menu does the same later.
- 🔌 Test connection logs in once and shows the result, latency and — for a new server — its host key fingerprint.
- Protocol:
- Secrets stay on the server unless the owner asks for them. Passwords and private keys are write-only in the form: the edit dialog shows “saved and encrypted — leave empty to keep it”, with an option to remove the saved secret. Duplicate copies the connection on the server.
- 👁 Show saved login (in Edit connection, or the 👁 in an empty password field) shows what the connection logs in with: its password or private key, the vault credential's user name and password (only for credentials you own), the key store key or the Bitwarden SSH key, or the path of a key file on the WRM server. You confirm with your WRM password; a domain (LDAP / Active Directory) account confirms with its directory password, and an account that only signs in through an identity provider confirms there (step-up). With Confirm dangerous actions (step-up) on, the 2FA code is asked as well. Every reveal is in the audit log (
connection.secret_revealed, failed attemptsconnection.secret_denied), raises the secret revealed alert when it is on, counts towards the sign-in rate limit, and follows the Allow export of passwords & keys policy (allow_secret_export; administrators always can). - Host key verification: the first connection to a server remembers its SSH host key (and, for FTPS, the certificate if it is not signed by a public CA). A changed key is refused with a clear warning and both fingerprints; the owner of the connection (or an administrator) can accept the new key after checking it. Policy: trust on first use (default), strict (new hosts must be approved) or off.
- Double-click a connection to open it: SSH opens a terminal; SFTP/FTP/FTPS open the file manager. On touch devices a single tap opens it.
- Right-click a connection: Open as Terminal / File Manager (in a new or an existing window), Tunnels, Start / Stop all tunnels, Add tunnel…, Network tools from this server…, Who has access (authorized_keys)…, Deploy SSH key…, Notes & runbook, Check ports of this host, Edit, Duplicate, Rename to the server's hostname, Share, Copy username, Copy password (after the same confirmation as Show saved login; the password is never shown in the notification), Copy IP address (or host name), Delete. Web interface connections: Open web interface.
- 📁 Folder creates folders. Drag connections onto a folder to move them, or onto "↓ Drop here" to move them back to the root. Right-click a folder to Share or Delete it (its connections move to the root), or Folder settings… to rename it and give it a default jump host and a default proxy: its connections — also new ones and the ones moved into it — use them unless they choose their own (⤳ after the folder name). Export and import keep the defaults.
- Search box filters by name, host, username, protocol or tag;
#tagsearches tags only, several words must all match (#env:prod web). The 🏷 tag bar above the list filters by one or more tags (click again to remove). Multi-select with Ctrl/Cmd + click, then use 🤝 Share, 🔑 Key (deploy an SSH key to all of them), 🏷 Tags (add tags, or remove them with-tag) or Delete. - The dot in front of a connection is its live status: 🟢 up, 🟡 up but slow (> 300 ms), 🔴 down, a ring = behind a jump host (colored by the jump host's state). A blue dot after the name means one of its terminals is connected. ⤳ means it goes through a jump host (hover shows the route), 🔀 that it has tunnels (colored while one runs; click opens them), WEB marks web interfaces.
- Shared with me lists shares you are a member of (and shares published for all users), with your role; ↗ opens the collaboration room.
Folders also support manual ordering: use the folder menu's Move up / Move down, or drag into the top/bottom third of another folder to place before/after it. Drop in the center to make it a child, or on the root area to move it to the root. Ownership, hierarchy depth and cycle checks apply. Export/import includes the saved order.
Quick connect & connection notes
⚡ Quick connect — the field at the top of the sidebar (⚡ Quick connect: user@host:port) — connects without filling in the connection dialog:
- Type an address and press Enter:
root@10.0.0.5,admin@sw1:2222,10.0.0.7, or with a scheme:ssh://,sftp://,rdp://admin@10.0.0.20,vnc://10.0.0.30:5901,telnet://sw1:23,https://10.0.0.11/ui. Without a scheme it is SSH. - A small dialog asks for the login — a password, a vault credential or a key from the key store — and optionally a jump host. Enter connects: a terminal, file manager, remote desktop or web interface opens like for a saved connection (host key check, recording and audit included; audit action
connection.quick). - The connection is listed under ⚡ Quick connections in the sidebar: 💾 (or right-click → Save as a connection) opens the connection dialog to give it a name, folder and tags and keep it; ✕ removes it. Quick connections are kept 24 hours after their last use (an open terminal keeps them), at most 20 per user, are not monitored and not exported.
📝 Notes & runbook — every connection has notes: what runs there, how to restart it, who to call, links to the wiki or the ticket:
- Edit → 📝 Notes & runbook, or right-click → Notes & runbook. A 📝 after the name in the sidebar and in the window bar of its terminals opens them.
- A small markdown:
# headings,- lists,**bold**,`code`,```code blocks and links (https://…). Everything else is shown as text (no HTML). - Notes belong to the owner of the connection: share members don't see them. They are exported and imported with the connection and copied by Duplicate. Up to 20 000 characters.
SSH keys & credentials vault
The 🔑 Keys button in the top bar opens two lists: SSH keys and Credentials.
SSH keys (key store)
- Generate key: ED25519 (recommended), RSA 2048/3072/4096 or ECDSA 256/384/521, with a name and a comment. The key is created on the WRM server and stored encrypted like all other secrets.
- Import key: paste (or choose the file of) an OpenSSH or PEM private key — keys with a passphrase are asked for it once and then stored encrypted with WRM's key. A public key alone (e.g. a colleague's
id_ed25519.pub) can be imported too: it can be deployed to servers, but WRM cannot log in with it. PuTTY.ppkkeys: export them with PuTTYgen → Conversions → Export OpenSSH key first. - Use it: in a connection choose Authentication → SSH key from the key store. The key list shows which connections log in with a key, where it is deployed and when it was last used.
- 🚀 Deploy: puts the public key on the selected SSH connections, like
ssh-copy-id: WRM logs in with each connection's current login (password, other key or vault credential — through jump hosts too), creates~/.sshif needed and appends the key to~/.ssh/authorized_keysonce (a key that is already there is not added again; other lines stay untouched; SELinux contexts are restored). With "Log in with this key from now on" WRM then logs in with the key to test it and switches the connections to it. Deploy from the key, from a connection (right-click → Deploy SSH key…) or for many selected connections (🔑 Key in the sidebar). - ✂ Revoke: removes the key from
authorized_keyson the selected servers. A connection that logs in with that key cannot be selected — WRM would lock itself out. - 📋 Copy public key, ⬇ .pub download, rename, delete (refused while connections or credentials log in with the key — servers keep a deleted key until you revoke it).
- 🔓 Export private key: after entering your WRM password again, optionally protected with a new passphrase; recorded in the audit log. Allowed when allow_secret_export is on (always for administrators).
Who has access (right-click an SSH connection → Who has access (authorized_keys)…): WRM reads ~/.ssh/authorized_keys of the user it logs in as and lists every key with type, size, comment, fingerprint and options (from=…, command=…). Keys of your key store are named, the key WRM itself logs in with is marked (and cannot be removed), and every other key can be removed with one click. Add a key… deploys one there. Keys allowed elsewhere (AuthorizedKeysFile, AuthorizedKeysCommand, other accounts) are not shown.
Credentials (vault)
A credential is a login that many connections share: a user name with a password, an SSH key of the key store, or both. Typical: root@dc1, Administrator of the Windows servers, the iDRAC/iLO admin.
- New credential: name, user name (optional — without one each connection uses its own user name), password (🎲 generates a strong one), SSH key, description, a rotation reminder in days and Only for hosts: host names with
*and?or CIDR ranges (*.dc1.example.com, 10.1.0.0/16). With a host list the credential works only for matching hosts. - Use it: in a connection choose Authentication → Credential from the vault. SSH, SFTP, RDP, VNC, Telnet and FTP connections can use it. Change the credential once — every connection logs in with the new secret.
- Share with users: add colleagues (or, administrators, all users). They see the credential in their list and can use it in their own connections, but they never see or change the secret. Removing a user stops their connections from logging in with it at once. Because a password is sent to the server when logging in, a shared credential should have a host list: then it only works for those hosts — and, for the people it is shared with, only through jump hosts that match the list too. WRM asks before saving a shared credential without a host list.
- 👁 Show reveals the stored password to its owner after entering the WRM password again (audited; policy allow_secret_export). 🔗 Used by lists the connections that use it (all users' for the owner).
Password rotation (🔄 Rotate… on a credential, owner only) changes the password on every SSH server that uses the credential:
- Check logins — WRM logs in to every server with the stored password (through jump hosts, in parallel) and changes nothing. Connections of other users that use the credential are included; the same user@host:port is changed only once.
- Rotate now — the same check first: if one server does not accept the stored password, nothing is changed. Then, one server after the other, WRM runs
passwdover SSH (answering its prompts in a terminal), logs in with the new password to verify it, and finally stores it in the vault. The new password is generated (24 characters: upper and lower case letters, digits and symbols) or entered by you. - All or nothing: when a server fails (password rules,
passwdnot allowed…), the servers already changed get the old password back and the vault keeps it. If even that fails (e.g. a password history rule refuses the old password), the vault keeps the old password and remembers the new one as pending: the credential is marked rotation incomplete, Show reveals both, and the result lists which servers have which password. Set the right password with Edit once fixed.
The progress of every server is shown live. Rotation needs SSH connections to servers where the login user may change its own password with passwd (Linux, BSD, macOS). Connections of other types (RDP, VNC, FTP…) block rotation — change those passwords yourself and save the new one with Edit (Edit with a new password counts as rotated). When the rotation reminder is due, the 🔑 button shows a badge and Admin panel → Overview warns.
Everything is in the audit log: ssh_key.created, ssh_key.deployed, ssh_key.revoked, ssh_key.exported, ssh_key.deleted, credential.created, credential.updated, credential.granted, credential.grant_revoked, credential.revealed, credential.checked, credential.rotated, credential.rotation_failed, credential.rotation_incomplete (never the secrets).
Bitwarden SSH keys
Open Keys & credentials → Bitwarden, choose the cloud/EU/self-hosted HTTPS server, and sign in with email, master password and supported two-step code. Personal API credentials plus a master password are also supported when email login requires a bot challenge or another MFA flow. Unlock the vault, sync if needed, then choose Bitwarden SSH key in an SSH/SFTP connection and select a native SSH key item. Secure-note attachments and arbitrary text fields are not SSH key items.
Install the official Bitwarden CLI on the WRM server (bw on PATH or WRM_BITWARDEN_CLI); Docker includes CLI 2026.9.1. Each WRM account has its own CLI profile. The connection stores its item ID; private keys are fetched server-side for authentication and are not returned to the browser or copied into the connection database. Master passwords and unlock session keys are not persisted. CLI data.json is sealed with the WRM encryption key between commands and recovered at startup after interrupted calls.
The default unlock inactivity is 15 minutes; a WRM restart, WRM logout, Lock or Sign out also ends unlock access. Lock prevents new key retrieval; existing SSH sessions continue. Refreshing keys and manual vault synchronization extend interactive inactivity; background SSH operations do not. Cloud login requires reachability from the WRM host. Errors distinguish missing CLI/locked vault from login failures without exposing CLI output.
Jump hosts (bastions)
Servers in data centers and customer networks are often reachable only through a bastion ("jump host"). WRM goes through it like ssh -J / ProxyJump and like the SSH tunnel setting of mRemoteNG:
- Create the bastion as a normal SSH connection, e.g.
bastion-dc1→203.0.113.10:22. - Create the internal server, e.g.
app-01→10.0.0.21:22, and choose Jump host (connect via) → bastion-dc1. - Double-click
app-01. The terminal showsConnecting to 10.0.0.21:22 via bastion-dc1….
WRM ──SSH──► bastion-dc1 ──SSH inside the first connection──► app-01 (10.0.0.21)
- Everything works through it: terminal, file manager (SFTP), FTP/FTPS (the FTP connection is made from the jump host), search, editor, server-to-server transfer, Test connection, tunnels and web interfaces.
- Chains: a jump host can have its own jump host — up to 5 hops, e.g.
vpn-gw → bastion-dc1 → app-01. Loops are refused when you save. - Every hop logs in with its own credentials (password, key, key file) and its host key is verified (trust on first use / strict), like a direct connection. WRM opens no port on the jump host; it uses a
direct-tcpipchannel, so the bastion only needsAllowTcpForwarding yes(the OpenSSH default). - The route is shown in the sidebar (⤳), in Test connection (
… via bastion-dc1), in the terminal, in Sessions & recordings and in the audit log. - Jump hosts are your own saved SSH connections. Shares of a connection behind a jump host work too — members never see the credentials of either.
- Deleting a jump host makes the connections that used it direct again (or use their folder's default jump host).
- A folder can give its connections a default jump host (Folder settings…); a jump host that is itself in the folder does not go through itself.
Proxies (SOCKS / HTTP)
Some servers are reached through a SOCKS or HTTP proxy instead of (or after) a bastion, like PuTTY's Connection → Proxy. A proxy is defined once and chosen per connection, like a vault credential:
- 🔑 SSH keys & credentials → 🌐 Proxies → New proxy (or + New proxy… in the connection dialog's Proxy field). Types:
- SOCKS5, with an optional user name and password (RFC 1929) — encrypted, or a vault credential;
- SOCKS4 / SOCKS4a (a user id, no password);
- HTTP CONNECT with Basic authentication;
- WRM SOCKS tunnel of a connection: a dynamic tunnel (
-D) of one of your SSH connections. WRM starts it when a connection needs it and stops it after 30 minutes without traffic.
- DNS at the proxy (PuTTY: Do DNS name lookup at proxy end, default on): the proxy resolves host names (SOCKS5 domain names, SOCKS4a). Off: WRM resolves them and sends the address.
- Everything a connection does over TCP goes through it: SSH terminal, SFTP, search, transfers, tunnels, key deploy and password rotation, FTP/FTPS (also the data connections), RDP / VNC / Telnet (guacd connects to a local relay on
desktop_tunnel_bind), web interfaces (opened through a local relay on127.0.0.1), Test connection, live status, network tools from the server, Redfish (when Through the jump host is ticked). IPMI and Serial-over-LAN use UDP and cannot go through a proxy: WRM refuses that combination. - Proxy and jump host together: the proxy is reached through the jump hosts, then the target:
WRM ──SSH──► bastion ──direct-tcpip──► proxy 10.1.1.1:1080 ──SOCKS CONNECT──► app-01:22
The route is shown in the sidebar, the dialog, the terminal, Sessions & recordings and the audit log: bastion → socks5://10.1.1.1:1080 → app-01. Jump hosts can have proxies of their own.
- Clear errors that tell the proxy and the target apart:
proxy socks5://10.1.1.1:1080: not reachable: connection refused— the proxy itself;proxy socks5://…: authentication required/authentication failed: wrong user name or password(HTTP:407);proxy socks5://… cannot reach 10.0.0.5:22: connection refused (SOCKS5 reply 5)— the proxy works, the target does not answer (HTTP:502/504).
- Live status checks through a WRM SOCKS tunnel proxy only while that tunnel runs (it is never started or kept alive by a check); otherwise the state is unknown.
- A proxy address on the WRM machine that is a running SSH tunnel of another user is refused (this address is an SSH tunnel of another user on the WRM server): tunnel listeners have no login of their own.
- Sharing: share a proxy with users (or, administrators, with everybody): they can use it but never see its login. A proxy shared with a password is not reached through the grantee's own jump hosts (they could read the plain-text proxy login there). WRM tunnel proxies are not shared.
- Folder default: Folder settings… → Default proxy.
- Policy
proxies(all/admins/off): who may define proxies. Everybody can use proxies shared with them. - Export and import keep proxies by name (the export lists your proxies, passwords only in an export with secrets; an import creates the missing ones); Duplicate keeps the proxy.
- Docker: inside a container
127.0.0.1is the container itself.docker-compose.ymlmapshost.docker.internalto the Docker host (extra_hosts: ["host.docker.internal:host-gateway"]): forssh -D 1080or a proxy on the host usehost.docker.internal:1080, and let it listen on an address the container reaches (not only127.0.0.1of the host). WRM warns when a proxy at127.0.0.1is saved while it runs in a container.
SSH tunnels (port forwarding)
Like ssh -L / -R / -D, the tunnels of PuTTY and the SSH tunnel feature of mRemoteNG. You configure tunnels in a connection (✏ Edit → 🔀 SSH tunnels, or right-click → Add tunnel…) and start and stop them in the 🔀 Tunnels panel in the top bar.
| Type | What it does | Example |
|---|---|---|
| Local (-L) | A port on the WRM machine leads, through the SSH connection, to a host:port as seen from that server. | Listen 127.0.0.1:2443 → target 10.0.0.5:443: open https://127.0.0.1:2443 to reach the web UI of a switch behind the server |
| SOCKS proxy (-D) | A SOCKS5 proxy on the WRM machine. Every destination is reached through the server. | 127.0.0.1:1080: set it in the browser (e.g. FoxyProxy, SOCKS v5, proxy DNS) and browse the whole management network, or curl --socks5-hostname 127.0.0.1:1080 http://10.0.0.5 |
| Remote (-R) | A port on the SSH server leads back to a host:port reachable from WRM. | 127.0.0.1:9000 on the server → 10.10.0.2:80: the server downloads from a mirror on your side |
Fields of a tunnel
- Listen: address and port.
127.0.0.1(default) means only programs on the WRM machine can use the tunnel. Leave the port empty for a free port chosen automatically (shown while running). Local and SOCKS ports must be 1024–65535. A network address (0.0.0.0, a LAN IP) makes the tunnel reachable by anyone who can reach that port, without signing in to WRM — administrators only, unless the policy allows it. - Target: host:port, as seen from the server (local) or from WRM (remote). Not used by SOCKS.
- Open as
http/https+ path: adds a 🌐 Open button that opens the tunnel in a new browser tab. - Start: Manual (▶ in the Tunnels panel); With terminal (starts with the first terminal of the connection and stops about 15 s after the last one closes); Always (starts with WRM and keeps running, also after a restart).
- Templates: web interface (HTTPS 443 / HTTP 80), SSH, RDP and VNC to an internal host, PostgreSQL, MySQL/MariaDB, iDRAC / iLO / IPMI web, SOCKS proxy.
The hint under each tunnel says in plain words what it will do, e.g. Connections to 127.0.0.1:2443 on the WRM machine go through Site1 to 10.0.0.5:443.
The 🔀 Tunnels panel lists your tunnels by connection: state (🟢 running, 🟡 reconnecting, 🔴 error), listen → target, open / total connections, traffic ↑↓, since when and who started it, with 🌐 Open, 📋 Copy address (for SOCKS as socks5h://…), ▶ Start and ■ Stop. The number on the button counts running tunnels. Administrators can show all users' tunnels and stop them (also in Admin panel → Overview).
Reliability: every running tunnel has its own SSH connection (through the jump hosts), checks it every 30 seconds and reconnects automatically (after 2, 5, 10, 30, 60 s…) while its port stays open. Changing a connection restarts its running tunnels; deleting it stops them. Each start, stop (with the bytes transferred) and error is in the audit log.
Where is the tunnel port? On the computer where WRM runs:
- WRM on your own PC (the usual case): open
http://127.0.0.1:<port>in your browser, or point any program (DBeaver, RDP client,psql, FileZilla…) at127.0.0.1:<port>. - WRM on a server you reach over the network: a
127.0.0.1tunnel is usable only on that server. An administrator can use listen address0.0.0.0(or the server's LAN address) and allow the port in the firewall — then everyone who can reach that port can use the tunnel, so prefer a restricted network. Or forward the port to your PC with plain SSH (ssh -L 2443:127.0.0.1:2443 wrm-server).
Example — the web interface of a server behind a site gateway (PC → WRM → Site1 → Site1-Webserver:443):
- Connection
Site1(SSH to the site gateway). - Edit
Site1→ 🔀 SSH tunnels → + Local (-L): listen127.0.0.1:2443, target10.1.0.20:443(the web server as seen fromSite1), open ashttps. - 🔀 Tunnels → ▶ Start → 🌐 Open →
https://127.0.0.1:2443.
Even simpler: save it as a web interface connection with jump host Site1.
Web interfaces (HTTP / HTTPS connections)
Save the web interfaces of your devices — iDRAC / iLO / IPMI, switches, firewalls, NAS, hypervisors, monitoring — as connections with protocol 🌐 Web interface (HTTPS) or (HTTP): host:port, an optional path (e.g. /login.html) and an optional jump host.
- Double-click (or right-click → Open web interface) opens it in a new browser tab.
- Without a jump host the browser opens the address directly (
https://10.0.0.200/login.html). - With a jump host WRM opens a temporary tunnel on the WRM machine (
127.0.0.1:<free port>→ host:port as seen from the last jump host) and opens that. The tunnel is reused while you work and stops after 30 minutes without traffic; the Tunnels panel shows it as temporary. - Test connection checks that the port answers (through the jump hosts).
- TLS goes end to end from your browser to the device; for self-signed device certificates the browser shows its usual warning.
- As with all tunnels, the temporary tunnel is on the WRM machine: when WRM runs on another computer, WRM shows the address instead of opening it (see Where is the tunnel port? above).
Tags & inventory import (CSV, Excel, NetBox)
Tags describe connections: free words (web, db) and tags with a key — env: (environment), site: (location), rack:, role:, tenant:, platform:, cluster:. Tags are lower case, without spaces (Rack A 12 becomes rack:a-12), at most 30 per connection.
- Set them in the connection dialog or for many connections at once (🏷 Tags after a multi-select;
-tagremoves one). - The 🏷 tag bar above the connections lists the most used tags with their counts; click tags to show only connections that have all of them (with +N for the rest). The search box finds tags too (
#rack:a12). - Environments stand out:
env:prod(alsoproduction,prd,live) gets a red PROD badge and a red edge, staging/UAT a yellow, test/QA a blue and dev/lab a green badge — so a production server is never mistaken for a test one. - Tags are kept by Export / Import and Duplicate.
Import inventory (Settings → Data → Import inventory):
CSV / Excel
- Choose a CSV file (comma, semicolon, tab or
|separated — detected automatically; UTF-8, UTF-16 or Windows-1250 as Excel saves it in Croatian, soč ć š ž đcome out right) or an Excel workbook (.xlsx) with a sheet selector. Old.xlsfiles: save them as.xlsxor CSV first. - WRM reads the first row as column names and guesses the mapping (English and Croatian names: Name/Naziv/Hostname, IP/IP adresa/Address/URL, Port, Protocol/Protokol, User/Korisnik, Password/Lozinka, Folder/Mapa/Grupa, Tags/Oznake, Environment/Okruženje, Site/Location/Lokacija, Rack, Role/Uloga, Platform/OS, Jump host/Bastion, Path). The preview shows the first rows under a field selector per column — change any column or set it to ignore.
- The host column understands
10.0.0.5,10.0.0.5:2222,root@10.0.0.5,10.0.0.5/24, IPv6 and URLs (https://idrac-01/becomes a web interface connection,ssh://admin@sw1:2222an SSH connection). A Platform containing Windows makes an RDP connection. Environment, Site, Rack, Role and Platform become tags; a Jump host column links connections to a jump host by name.
NetBox
- Enter the NetBox address and an API token (read-only is enough), optionally filters (sites, roles, tenants, a NetBox tag, status), whether to use the primary IP or the name (DNS) as address, and the name of a custom field that holds the environment. Load from NetBox reads devices and/or virtual machines (all pages) and shows them; objects without an address are marked.
- Sites, racks, roles, tenants, platforms, clusters, the environment and NetBox tags become tags; Windows platforms become RDP connections.
- Sync: imported objects remember their NetBox id. Loading again marks them as imported; with Update the ones imported before their address, NetBox tags and folder follow NetBox (your own tags, the name and the login stay). Objects that disappeared from NetBox are listed — WRM never deletes connections on its own.
- Remember address and token stores the address, filters and the token (encrypted) for your account; the token is never shown again.
For both: choose the login of the imported connections — none (set it later), a vault credential (e.g. root@dc1) or a stored SSH key — a default user name and protocol, folders (from a column, one per site / role / tenant, all in one, or none) and extra tags for all. Rows with their own password keep it. Existing connections (same name, host and protocol) are skipped, so importing again is safe. The result lists what was imported, updated and skipped (with reasons).
Import from mRemoteNG, PuTTY and OpenSSH
Settings → Data:
- Import from mRemoteNG — the
confCons.xmlfile (%APPDATA%\mRemoteNG\confCons.xml, or File → Export in mRemoteNG):- containers become folders (
DC1 / Rack A); SSH1/SSH2 connections become SSH connections, RDP, VNC and Telnet connections remote desktops (with their options), HTTP/HTTPS connections web interface connections (with the path of the URL); - passwords are decrypted (current AES-GCM format, older AES-CBC format, FullFileEncryption) and stored encrypted in WRM. If the file is protected with a master password, WRM asks for it;
- inherited settings (Inherit user name, password, port, domain, SSH tunnel) are resolved from the parent folders;
- the SSH tunnel setting (
SSHTunnelConnectionName) becomes the jump host; - ICA, rlogin and other protocols WRM does not open are listed as skipped; connections that already exist (same name, host and protocol) are skipped too, so importing again is safe.
- containers become folders (
- Import OpenSSH config —
~/.ssh/config(folder SSH config):Hostentries withHostName,User,Port; defaults fromHost *and from wildcard patterns;ProxyJump(alsouser@host:port; a jump host that is not its ownHostentry is created) andProxyCommand ssh -W …become the jump host;LocalForward,RemoteForward,DynamicForwardbecome tunnels that start with the terminal;IdentityFilebecomes Key file authentication (only if key files on the WRM server are allowed for you; otherwise a note asks you to add the key or a password);Matchblocks and wildcard-only hosts are skipped.
- Import from PuTTY — a registry export of the saved sessions (folder PuTTY). In
regeditright-clickHKEY_CURRENT_USER\Software\SimonTatham\PuTTY\Sessions→ Export, or runreg export HKCU\Software\SimonTatham\PuTTY\Sessions putty.reg. Both UTF-16 (regedit's default) and UTF-8 files are read:- session names are decoded (
My%20Server→ My Server);HostName(alsouser@host),PortNumber,UserNameandProtocolare imported. Default Settings is not imported as a connection, but its values are the defaults of the other sessions; - SSH and Telnet sessions become connections; raw, rlogin and serial sessions (a COM port of the Windows PC) are listed as skipped;
PublicKeyFilegives a note: convert the.ppkwith PuTTYgen (Conversions → Export OpenSSH key) and add it under 🔑 SSH keys;- proxies: SOCKS4, SOCKS5 and HTTP proxies (
ProxyMethod,ProxyHost,ProxyPort,ProxyUsername,ProxyPassword,ProxyDNS) become saved proxies named e.g. PuTTY socks5 proxy.example.com:1080, linked to the connections. Sessions with the same proxy share one; a proxy you already have (same type, address, login and DNS setting) is reused, so importing again creates nothing new. PuTTY's SSH proxy becomes the jump host (by name); Telnet and local-command proxies get a note. Needs the policyproxiesto allow you to define proxies; - with mRemoteNG: connections whose PuttySession names an imported PuTTY session get that session's proxy (unless they have a proxy already). The order does not matter: the second import links connections that the first one created.
- session names are decoded (
After the import a summary lists the imported connections, folders, jump host links and tunnels, what was skipped and what to check (e.g. connections without a user name or password).
Size limit: every import file (WRM export, mRemoteNG, PuTTY, OpenSSH config, CSV / Excel inventory) may be up to 20 MB. The browser checks the size before sending; a larger file gets The file is too large (… MB): the import limit is 20.0 MB (HTTP 413 from the API).
Windows, tabs & snapping
Every opened connection is a window inside the workspace. There is also a tab for it in the tab bar.
- + New Window (or Alt+N) opens an empty window with quick buttons for your connections and saved sessions.
- Title bar: drag to move, double-click to maximize or restore. Buttons: snap layouts, ↻ Reconnect (SSH windows), 📂 Files (SSH terminals), 📡 share terminal (in a collaboration room), minimize, maximize, close.
- 📂▾ Files in an SSH terminal's title bar is a menu that opens the file manager of the same server (#24); a file manager of that connection that is already open is brought to the front and moves to the chosen directory:
- Open here: the terminal's current directory. When the remote shell reports it with OSC 7, WRM uses it right away (bash:
PROMPT_COMMAND='printf "\033]7;file://%s%s\033\\" "$HOSTNAME" "$PWD"'in~/.bashrc). Otherwise WRM asks the server over a separate SSH channel of the same connection: it finds the terminal's shell among the server's processes (/procorps, Linux and BSD), prefers the terminal's foreground program, and reads its working directory (/proc/<pid>/cwd,pwdx,procstatorlsof). Nothing has to be configured. When the directory cannot be found (no/proc/ps, another user's process aftersudo -i, a non-OpenSSH server), WRM says why and offers home or/. - Open / and Open home.
- Open here: the terminal's current directory. When the remote shell reports it with OSC 7, WRM uses it right away (bash:
- Snapping: left, right, top and bottom halves, the four quarters, and maximize. Use the buttons in the title bar, the compact snap layouts menu in narrow windows, or the tab's right-click menu.
- Drag-to-edge snapping: drag a window with the pointer to an edge (half) or a corner (quarter) of the workspace. A blue preview shows where it will go.
- Windows can never leave the workspace: moving and resizing stop at all four edges. When the browser is resized or zoomed, or a panel changes size, windows are moved and shrunk to stay visible. Snapped and maximized windows keep their slot.
- Resize from any edge or corner. Dragging a snapped window restores its previous size.
- Tabs: click to focus or restore, drag to reorder, middle-click to close, right-click for Reconnect, Duplicate window, snap layouts and Close. SSH tabs show the connection state (🟡 connecting, 🟢 connected, 🔴 disconnected).
- Close confirmation can be Always, Never or Only when connected (Settings).
- The browser warns you before leaving the page while terminals are connected or a transfer is running.
Appearance, themes and accessibility
Settings → Appearance (static/appearance.js) changes how WRM looks for you; the choice is stored on the server (/api/me/ui/appearance) and follows you to every browser.
- Themes: Graphite (default), Midnight (OLED black), Fjord, Solar dark, Forest, Ember, Daylight, Paper, Solar light, High contrast dark and High contrast light. Follow the system light / dark setting switches between a dark and a light theme of your choice. Every theme also sets the terminal colours.
- Your own colours: every colour token (backgrounds, text, borders, accent, status colours and their text variants, terminal background, foreground and ANSI colours) has a colour picker and a CSS field; your changes apply on top of the theme and can be reset one by one or all at once. Save as my theme keeps the result (up to 30), Export / Import move a theme as JSON (
{"wrm_theme": 1, "name", "mode", "tokens", "term"}). - Fonts and size: interface font (including readable choices such as Atkinson Hyperlegible, Lexend and OpenDyslexic when installed), monospace font for terminals, editor and logs, interface size 70–160 %, spacing (compact, normal, roomy with larger click targets), rounded corners, line and letter spacing, heavier text.
- Colour vision: deuteranopia, protanopia, tritanopia and achromatopsia switch OK / warning / error / info colours and diffs to an Okabe–Ito based palette, optionally also in terminals. Do not rely on colour alone adds ✓ ✕ ! signs to status badges and toasts, shapes to connection status dots (● up, ◆ slow, ■ down) and underlines links.
- Other options: contrast (normal, more, maximum), minimum contrast in terminals (WCAG 4.5:1 or 7:1), animations (system, reduce, full), reduce transparency and blur, strong keyboard focus outline, underline links.
- Custom CSS for your own interface only (
appearance_custom_css, default on). - Themes from addons: an enabled addon offers its themes here (
ui.themesinaddon.jsonwithid,name,name_hr,mode,tokensand/orcss; the older singleui.themestylesheet appears as one theme). Nothing is applied to users who did not pick it. An administrator can make any theme the default with Default for everyone orappearance_default_theme.
Screen lock
The lock covers WRM and asks for the account password; terminals, file transfers, tunnels, AI and MCP sessions keep running. Settings → Security → Screen lock (per user, /api/me/ui/lock):
- Lock now (also 🔒 in the top bar and a keyboard shortcut, Ctrl+Alt+L by default).
- When: after inactivity (off, 1 minute to 4 hours or a custom time, with an optional 10/30/60 s warning; activity in any WRM tab counts, mouse movement optionally), when WRM is not visible (immediately or after 1/5/15 minutes, unless another WRM tab is visible), when the computer locks (browser idle detection, Chrome/Edge, asks for permission once), after the computer sleeps, and on every start or reload.
- Lock screen: blurred, dimmed or solid background, clock, your name, how many windows keep running, a message of your own, and a neutral tab title. Notifications are held while locked and shown after the unlock; desktop notifications do not show their text.
- Unlocking: the account password (local or directory/LDAP), or a personal 4–12 digit PIN (
screen_lock_pin). Accounts that only sign in through an identity provider can set a PIN right after signing in, or sign out from the lock screen. Every lock, unlock and failed attempt is audited; five attempts per minute at most, andscreen_lock_max_failuressigns the browser session out after that many wrong attempts. - How strict (
screen_lock_mode):server(default) remembers the lock per sign-in session and refuses that session's requests with423 Lockeduntil the unlock, so a reload, a new tab or the browser's developer tools do not get past it;rememberkeeps the lock over a reload but lets the page refresh underneath;browseris the page-only lock of earlier versions. All WRM tabs of the browser lock and unlock together. - Administrator limit:
screen_lock_max_minutesis the longest idle time a user may choose (0 = no limit); users cannot turn the idle lock off below it.
Panel layout: dock, stack, float and lock
The side panels are yours to arrange (v12.6.8). Connections, Sessions, Snippets, Clipboard and the AI live view (while an AI app works) are panels, each with a tab. Panels share a tab bar in a group; groups sit in a dock zone (left, right, or at the bottom under the windows) or on the canvas, anywhere between your windows (v12.6.10).
- Drag a panel by its tab (a blue frame shows where it lands):
- onto another tab bar: the panels share it as tabs (dropped between two tabs, it goes there);
- onto the top or bottom 30 % of a panel: that column is split, the dragged panel above or below (left or right part in the bottom zone);
- onto the Left, Right or Bottom strip at the edges of the workspace: it docks there as a new group;
- anywhere else on the canvas: it is placed right there, between your windows. It shares their stacking order (click it to bring it to the front), stays inside the canvas when the browser or the side panels change size, and lands on the grid when Snap to the grid is on.
- Resize: the line between two groups, the inner edge of the left and right zones and the top edge of the bottom zone. A panel on the canvas moves by the empty part of its tab bar and resizes by its bottom right corner.
- ⋯ on every group: Dock on the left, Dock on the right, Dock at the bottom (as a tab of the zone's first group), On the canvas (anywhere), Hide, Lock the layout, Panels…, Reset the layout.
- Panels (▦ in the top bar, or in its ⋯ menu when the bar is narrow) lists every panel and where it is (left, right, bottom, on the canvas, hidden). Tick a panel to show it again where it was, untick to hide it. The AI live view is listed but appears only while an AI app works on a server.
- Lock the layout (in Panels, the ▤ Workboard menu or any ⋯ menu): no panel or window can be dragged, split, resized or moved (the snap and maximize buttons still work), and the ▦ button shows 🔒. Switching tabs, collapsing the side panels and showing or hiding panels still work. Dragging a tab while locked says how to unlock.
- Reset the layout puts every panel back: Connections left; Sessions, Snippets and the AI live view as tabs on the right with Clipboard under them.
- Saved per user on the server (
/api/me/ui/layout), so the layout follows you to every browser, with a copy in the browser for an instant start. A zone without panels disappears. While the AI live view is shown in a side zone, that zone keeps its own width (up to half the window). - Phones (below 760 px) keep the fixed layout: the connection list and the Sessions/Snippets/Clipboard drawer; the AI live view is a sheet at the bottom.
- Workboard addons docked as a panel are panels too; Panels lists them under Workboard addons, and hiding one puts it back onto the canvas as a window (see the canvas).
Workboard: the shared canvas and addons
The window area is one canvas (v12.6.10): terminals, file managers, desktops, Workboard addons and the panels you place on it share it, and you arrange it as you like. ▤ Workboard (in the Settings · Panels · Workboard group of the top bar, or its ⋯ menu when the bar is narrow) opens the canvas menu. Addons start empty: you add only what you want from the catalog (+ Add addon, also on the empty canvas), up to 24, the same addon several times if you like (for example two Server load addons for two groups of servers).
- Addons are windows: move by the title bar, resize from any edge or corner, snap by dragging to an edge or with the snap buttons, double-click to maximize, minimize, switch with the tabs. Title bar buttons: ↻ refresh (addons that fetch data; hover the title to see how old the data is), ⚙ settings, ⇥ dock as a panel, and the usual minimize, maximize and ✕ remove (it asks first when settings or a note would be lost). Addons stay visible with any connection folder tab chosen. A new addon finds a free spot beside your windows.
- Window menu (right-click a title bar or a tab), for every window: snap layouts, 📌 Pin in place (no moving or resizing until unpinned; 📌 shows in the title bar) and Always on top; for addons also Settings, Refresh now and Dock on the right / left / at the bottom.
- Docked as a panel, an addon is a panel of the panel layout: stack it with Sessions, split a column, move it to another edge or anywhere on the canvas. Its bar keeps ↻, ⚙ and ⧉ Back onto the canvas as a window, which returns it to its last place.
- The ▤ Workboard menu:
- Add addon…
- Canvas: Snap to the grid (windows and panels land on grid lines when moved, and moved edges when resized), Grid size 10 / 20 / 40 px, Canvas background (only with the grid shows dots while snapping is on; or always dots, lines, plain).
- Tile the windows (a grid of all shown, unpinned windows), Cascade the windows, Minimize all windows, Show all minimized windows, Minimize / Show the addons, Lock the layout.
- Saved layouts: Save this layout… stores the addons with their places and settings, the panel layout and the canvas settings under a name (up to 10); tick Also the open terminals, file managers and desktops to keep those windows too (like a workspace session). Choosing a saved layout replaces your addons and panel layout; with windows in it, WRM asks whether to replace or add to your open windows. Manage saved layouts… applies or deletes them.
- Export the layout (JSON) downloads the addons, canvas settings, panel layout and saved layouts as
wrm-workboard-<date>.json; Import a layout… reads such a file (up to 512 KiB, everything checked as when loading), replaces your addons and panel layout and adds its saved layouts to yours. Exported files contain addon settings and notes, but no secrets. - Panels… and a short help text.
- Every addon's settings: your own title, Colour (a coloured edge on the title bar), Text size (small to extra large), the addon's own options, and Remove.
- Saved per user on the server (
/api/me/ui/workboard, with a copy in the browser), so the canvas follows you to every browser. Places are kept as fractions of the canvas, so they fit other screen sizes. - Addons load and refresh only while visible: not minimized and not completely covered by other windows (a countdown still ends on time).
- Phones (below 760 px): every window, addons included, is full screen and switched with the tabs; addons are not docked as panels there.
| Addon | Shows | Settings | |
|---|---|---|---|
| 🟢 Server status | Down, slow (over 300 ms), unknown and up connections from the live status, problems first, with latency or since when; a click opens the connection | connections (none chosen: all with a status), only problems | |
| 📈 Server load | Per server: CPU, RAM (with total), load per CPU, uptime and disks (fullest first; more in a tooltip). Bars turn yellow at 75 % and red at 90 %. Each server names its source, Monitoring (Zabbix agent) or read over SSH, and the age of the values; errors (SSH refused, not Linux …) are shown as they are | up to 8 SSH/SFTP connections | |
| 🔔 Notifications | Everything WRM notified you about, newest first, unread marked; Mark all read, Clear; the ▤ Workboard button counts unread ones | — | |
| 🕒 Clock | Local time and date, and other time zones | IANA time zones (UTC, Europe/London …), seconds | |
| ⎇ Recent commits | The last commits and pushes of a Git service (author, branch, short SHA, age, link to the commit on the Git server), refreshed every 5 minutes | service of the Git catalog, branch (empty: the branches the service tracks), 5 / 10 / 20 | |
| 🔀 Running tunnels | Running tunnels with their local address; Tunnels… opens the tunnel panel | — | |
| ⚡ Quick connect | Buttons with a status light that open the connection | up to 12 connections | |
| 📝 Notes | A note to yourself (up to 2000 characters), saved with the addon | — | |
| 🗂 Saved sessions | Your saved sessions with their number of windows; a click opens one | — | |
| 🔗 Links | Your links to web pages (dashboards, wikis, tickets), opened in a new tab | up to 30 lines `Name \ | https://address` (only http and https) |
| ⏱ Timer | A countdown with a progress bar that blinks and notifies (toast and, when allowed, a browser notification) when time is up, or a stopwatch; Start / Pause / Reset; keeps running across reloads | countdown or stopwatch, minutes (1–1440) |
Where the values of Server load come from: when the server has Monitoring (📊 in the top bar, Zabbix agent) on and its last sample is younger than 5 minutes, WRM uses that sample and does not log in. Otherwise WRM logs in over SSH with the connection's own credentials and runs one read-only command (uname -s, /proc/loadavg, /proc/stat twice one second apart, MemTotal/MemAvailable from /proc/meminfo, df -P -k without tmpfs/overlay mounts, /proc/uptime, nproc): at most once a minute per server while the addon is visible, one login per server at a time, results cached for 25 s. Reading over SSH works on Linux and can be turned off by an administrator (workboard_ssh_metrics); then only servers with Monitoring show values. Only your own SSH/SFTP connections can be chosen.
Notifications in WRM: every notification WRM sends you is also kept in your in-app list (newest 200), whatever channels or events you chose in Settings → Notifications, and even when an administrator turned sending off (notifications_enabled). Repeated reminders (expiring keys and credentials, a new version, upcoming Git jobs) are kept once a day.
Remote desktop: RDP, VNC, Telnet
Windows servers (RDP), Linux desktops and KVM/IPMI consoles (VNC) and old network gear (Telnet) open in a WRM window next to your SSH terminals — no RDP client, no plug-in.
browser ──WebSocket── WRM ──guacd protocol── guacd ──RDP / VNC / Telnet── server
Setup (once): WRM uses guacd, the proxy daemon of Apache Guacamole, which implements the protocols. Run it on the same machine as WRM:
| Where WRM runs | Install guacd |
|---|---|
| Debian / Ubuntu | sudo apt install guacd (listens on 127.0.0.1:4822) |
| Docker | docker compose up -d — docker-compose.yml contains a guacd service that shares WRM's network |
| Any Linux with Docker | docker run -d --name guacd --network host --restart unless-stopped guacamole/guacd |
| Windows / macOS | nothing by hand: WRM starts the official guacd container in Docker Desktop when guacd_address is local (127.0.0.1:4822). Docker Desktop must use Linux containers. Install/start it; otherwise run guacd on a Linux machine and set guacd_address. |
Admin panel → Overview shows whether guacd answers (and its version); Test connection on an RDP/VNC connection checks the server's port and guacd.
Connections: choose protocol RDP, VNC or Telnet, host (default ports 3389, 5900, 23), user, password and optionally a jump host. 🖥 Remote desktop options:
- RDP: domain, security (automatic, NLA, TLS, RDP, Hyper-V console), keyboard layout of the server, what happens when the window is resized (adapt the desktop size, reconnect, or keep and scale), colors, start program, accept the server certificate, console (admin) session, sound, clipboard, wallpaper, RD Gateway (host, port, user, domain).
- VNC: colors, local or remote mouse pointer, view only, clipboard.
- Telnet: font size, colors, login and password prompt patterns (for automatic login).
Working in a desktop window:
- Double-click the connection (or right-click → Open remote desktop). The window shows the remote screen, scaled to fit; ⤢ Fit switches to 1:1 with scroll bars, ⛶ to full screen. With RDP the remote desktop adapts its size to the window.
- Keyboard and mouse go to the remote computer while the window has the focus (click it). Ctrl+Alt+Del has its own button.
- Clipboard: text copied on the remote computer appears in WRM's clipboard panel and in your clipboard; 📋 Clipboard sends text to the remote clipboard. ⌨ Type types text as keystrokes — for login screens, BIOS/iDRAC consoles and other places without a clipboard.
- Sound from RDP plays in the browser.
- If the server asks for credentials that are not stored (e.g. an empty password), WRM asks for them.
- ↻ reconnects; the tab and the window show the connection state.
- Behind a jump host, WRM opens a temporary tunnel through the jump hosts for the session (listed as Remote desktop (temporary) in the Tunnels panel) and closes it with the session.
- Saved workspace sessions restore desktop windows too.
Audit and recording: every desktop session appears in Sessions & recordings and the audit log (desktop.open, desktop.close, desktop.error). With session recording on, WRM records the screen stream (no passwords: they are sent to guacd during the handshake and never appear on screen) and ▶ Replay plays it in the browser with play/pause and seek; ⬇ .guac downloads it (playable with Guacamole's tools).
Security: the browser never picks the target: WRM performs the handshake with the stored host, user, password and options, and afterwards forwards only display data and input instructions from an allow-list. Access follows the same rules as terminals (owner; share members with the Operator role or higher). Policies: desktop_enabled (REMOTE_DESKTOP_ENABLED), guacd_address (GUACD_ADDRESS, default 127.0.0.1:4822), guacd_auto (Windows/macOS: start the local guacd container in Docker Desktop; default on), desktop_tunnel_bind (address of jump-host tunnels for guacd, default 127.0.0.1).
Out-of-band management, consoles & serial ports
The BMC of a server (iDRAC, iLO, XClarity, Supermicro, OpenBMC, any IPMI controller) is set in the connection: Edit → ⚡ Out-of-band management:
- Type: Redfish (the HTTPS API of current BMCs) or IPMI (IPMI over LAN with
ipmitool). - BMC address (
10.0.100.11, orhost:port), login: a user name and password (stored encrypted), or a vault credential (e.g. oneidrac-rootfor all servers). - Through the jump host: when the management network is only reachable from the bastion, WRM reaches the BMC through the connection's jump hosts — Redfish over an SSH channel of the last hop,
ipmitoolruns on the last hop (IPMI uses UDP). - Serial console command for the BMC's SSH (
console com2for iDRAC,vspfor iLO,console 1for XClarity; suggested from the BMC's maker) and its SSH port.
⚡ Power & status (right-click → Power & status (BMC)…):
- Power state, health (with fault messages over IPMI), maker, model, serial number, BIOS, CPUs and memory, BMC model and firmware, power draw and inlet temperature (as far as the BMC tells).
- Power on, Shut down (graceful), Restart (graceful), Force off, Force restart, Power cycle, NMI — only what the BMC offers. Everything except Power on asks first and explains what happens; every action is in the audit log (
bmc.power,bmc.power_failed). - Redfish certificates are mostly self-signed: WRM pins the certificate on first use like an SSH host key and refuses a changed one (accept it after checking, like a host key).
📟 Serial console (right-click → Serial console, or the button in Power & status) opens a terminal window with the console of the machine — BIOS/UEFI setup, boot loader, kernel messages, a login prompt when the network is down:
- Redfish BMCs: WRM logs in to the BMC's SSH with the BMC login and types the console command (iDRAC
console com2, iLOvsp…). - IPMI: Serial-over-LAN (
ipmitool sol activate, an old session is deactivated first), on the jump host or on the WRM server (Linux).~.ends it. - Consoles are terminal sessions like any other: audited, recorded (
protocolconsole / sol), visible to administrators — and only the connection's owner opens them (not share members). Saved workspace sessions restore console windows.
🔌 Serial ports of the WRM machine (USB console cables, ttyS0): protocol Serial port, the device name (ttyUSB0, ttyACM0, ttyS0) as host and the line settings — speed (default 9600; 115200 is common too), data bits, parity, stop bits, flow control (none, RTS/CTS, XON/XOFF). Test connection opens the port; a double-click opens it in a terminal (raw, recorded). Serial ports belong to the WRM server like its key files: by default only administrators may add them (policy serial_ports: off / admins / all); WRM must run on Linux, as a user that may open the device (group dialout).
Policies: bmc_enabled (BMC_ENABLED), serial_ports.
Snippets & run on connect
Snippets are saved commands. Open them in the right panel (⚡ Snippets tab), or press Ctrl+Shift+Space in a terminal (or ⚡ in its title bar) for a quick picker.
- Click a snippet: it is typed into the focused terminal and run. Shift+click (or ⎘) types it without Enter, so you can edit it first. Right-click: run, insert, copy, edit, duplicate, delete.
- Quick picker: type to filter, ↑ ↓ to choose, Enter runs, Shift+Enter inserts, Esc closes, + New snippet saves the selected terminal text as a snippet.
- Groups (Diagnostics, Services, …), a description, and the scope: all connections, the connections of one folder, or one connection. The picker only offers snippets that apply to the terminal's connection.
- Multi-line snippets: every line is one command.
- Variables are filled in for each terminal:
{{host}},{{port}},{{user}},{{name}}(connection),{{folder}},{{wrm_user}},{{date}},{{time}}. Prompts are asked before the snippet runs, with a live preview:{{?Service}}or with a default{{?Service=nginx}}. Example:journalctl -u {{?Service=nginx}} --since "{{?Since=1 hour ago}}" --no-pager. - Run on connect: tick Run on connect and WRM types the snippet into the shell as soon as a terminal of a matching connection is connected (also after a reconnect) —
sudo -i,cd /srv/app,tmux attach || tmux new,export KUBECONFIG=…. Right-click a connection or a folder → ⚡ Run on connect… creates one. Order: all-connection snippets, then folder, then connection snippets. A message lists what ran; the audit log records it (terminal.auto_run). - Shared snippets: administrators can share a snippet with all users (read-only for them, all connections, never auto-run) — a team runbook in the terminal.
- ✨ Add example snippets creates a starter set (disk, memory, top processes, failed services, journal errors, listening ports, big files, service status/restart…).
- Snippets are included in Export / Import, copied with Duplicate, and removed with their connection or folder.
- Dangerous-looking commands (see below) ask for confirmation before they run.
Folder bookmarks
Bookmarks are named remote directories, like WinSCP's: the same deep folders (/opt/app/servers/<server>/downloads) are one click away on every server.
- ★ in the file manager (next to the path bar): ☆ Bookmark this directory…, the bookmarks of this connection, and ⚙ Manage bookmarks…. Picking a bookmark opens that directory. If it does not exist on this server, a message says so and the current folder stays open.
- ★ in a terminal's title bar and in the Ctrl+Shift+Space picker (after the snippets): picking a bookmark types
cd -- '<path>'into the terminal (shell-quoted; a leading~/stays outside the quotes so the shell expands it). In a broadcast, 📣 next to a bookmark sends thecdto every terminal of the group, each with its own connection's variables. - Scope: one connection, the connections of a folder, the connections with a tag, or all SSH / SFTP / FTP connections (global).
- Variables, filled in by the server for each connection:
~(home directory),$USER/${USER}/{user}(the connection's user name),{host}(without the port),{name}(connection name). Example:/opt/app/servers/{name}/downloads. - Start directory: tick Start directory and the file manager of a matching connection opens there; a terminal types the
cdwhen it connects (also after a reconnect), before the run-on-connect snippets. The most specific start directory wins: connection, then tag, then folder, then global. Right-click a connection or a folder → ★ Start directory… creates one. - Name, colour and note; Manage bookmarks renames, reorders (↑ ↓), moves bookmarks between scopes and deletes them.
- Sharing: a global bookmark marked Share with share members is offered (read-only) to the people who use your connections through a share.
- Import from WinSCP: Manage bookmarks → Import WinSCP.ini reads the remote directory bookmarks (
[Configuration\Bookmarks\Remote\…]) of a WinSCP configuration file and adds them as global bookmarks, with the WinSCP site in the note. Bookmarks that already exist (same name and path) are skipped. - Bookmarks are included in Export / Import, copied with Duplicate, and removed with their connection or folder.
Broadcast input
Type the same command into many servers at once — like MultiSSH, cssh or mRemoteNG's multi-SSH.
- Open the terminals (e.g. all web servers of a cluster).
- Top bar → 🧰 Tools → 📣 Broadcast… → select the terminals → Start broadcast (asks once).
- Everything you type in one of them now goes to all of them. An orange bar shows how many terminals receive it; included windows get an orange frame. 📣 in a window's title bar adds or removes that terminal; ■ Stop ends it.
Safety:
- Dangerous commands ask first: before Enter is sent for a line that looks dangerous —
rm -r/-f,shutdown/reboot/halt,init 0/6,systemctl stop/restart/disable…,mkfs,dd … of=,fdisk/parted,wipefs, writing to/dev/sd*or/etc/…,kill -9,pkill,chmod 777,chown -R,iptables -F,ufw disable,DROP/TRUNCATE TABLE,DELETE FROM,crontab -r, package removal,docker rm,kubectl delete,terraform destroy, a fork bomb … — WRM shows the command and the number of terminals; Cancel is the default button. - Pasting several lines into a broadcast asks for confirmation too.
- Snippets run on every terminal of the broadcast, each with its own
{{host}}/{{user}}, after one confirmation. - The check works on what you typed in this broadcast (not on commands recalled from the shell history with ↑).
- Each terminal records when it joined and left a broadcast (
terminal.broadcast, with the number of terminals) and, as always, the session recording shows what happened on each server. Administrators can turn the feature off (broadcast_enabled).
Live up/down status
WRM checks every saved connection in the background and shows the result in the sidebar:
- 🟢 up (hover: latency, since when, SSH server version), 🟡 slow (more than 300 ms), 🔴 down (pulsing; hover: since when and why — connection refused, timeout, host name not found …), a ring for connections behind a jump host.
- A folder shows how many of its connections are down (2↓). When something is down, a red bar above the tree shows only the connections that are down with one click.
- Notifications: a message when a server goes down or comes back, and a desktop notification while WRM is in the background (Settings → General → Notify when a server goes down). Outside the browser: e-mail, chat or push through Notifications.
- Through a proxy: connections with a proxy are checked through it (and through their jump hosts when Check through jump hosts is on).
- 🔄 Check status now (right-click a connection or a folder) checks immediately — also through the jump hosts — and shows the result per connection.
- How it checks: a TCP connection to the connection's port (SSH 22, FTP 21, web 80/443 or the port you set). SSH checks read the server banner and answer with
SSH-2.0-WRM_status_checkbefore closing, FTP checks read the 220 greeting and sendQUIT— the same as Nagioscheck_ssh/check_ftp. Nothing logs in. A failed check is repeated once before a server counts as down. Each distinct host:port is checked once per round, however many connections and users point to it. - Behind a jump host a connection shows the state of its jump host (a red ring when the jump host is down). With the policy Check through jump hosts, WRM logs in to the jump host once per round and checks the ports behind it through that SSH connection.
- Untick Monitor up/down status in a connection to leave it out (e.g. servers that are often off on purpose).
- Policies:
status_enabled(on),status_interval_seconds(60, 15–3600),status_jump_checks(off).
fail2ban / IDS: the check is an ordinary connection without a login. Default fail2ban
sshdfilters do not count it, but the aggressive / ddos modes may. Add the WRM server toignoreip, raise the interval, or untick monitoring for such hosts.
Logs: viewer, search and log settings
Monitoring → Logs, choose a server.
- Discovery runs over the connection's SSH account without sudo: one read-only command reads systemd units, Supervisor programs and Docker containers, a second one runs
findover the scan paths with a time budget. Accounts without a shell (SFTP only) fall back to an SFTP walk. Scripts and code (.py,.sh,.js…) are never listed as logs, even in a log folder. - File list: sort by newest, oldest, name, size, service, operator or path; filter by operator, service, folder and name; tick files to search only those. Each file shows its operator and service labels, whether it sits in a log folder (
/var/log,log,logs…) or an app folder (scripts, application), its folder, size and modification time. Services are compared without case, so a log folder/var/log/VideoX_NOVAand a script folder/home/scripts/Videox_NOVAare one service with both folders. - Folder tree (View: Folder tree): logs grouped under their main folder (the scan paths, the Git workspace server roots and the main folders from Log settings) and its subfolders. Open or close a folder with a click; its checkbox ticks every shown log in it. The Folder filter lists the same tree and keeps one folder and everything below it, in either view.
- Operators: labels from the path patterns and fixed folders come first. With Guess operators on (default), a word that repeats across service and folder names is an operator unless it is the product (the first word of several names) or an environment word (
qa,test,dev,prod,bkp…):VideoX_NOVA,VideoX_NOVA2,novatvandINGEST_SFTP_novatvgive operatorsnovaandnovatv. Operators where one name starts with another (at least four letters) form a group; the operator filter offers the group (nova (5) · nova, novatv) and each member. Guessed operators are marked≈. - Log tabs: line numbers, level colours (a stack trace keeps the level of its line), highlighting of times, IPs, URLs, HTTP status codes, UUIDs and key=value pairs, find in the log (regex, case, ↑ ↓, only matching lines), level chips (errors, warnings, info, debug, other), Follow (new lines every 2.5 s; for the journal by cursor), Load older lines, Go to line, wrap, line numbers, copy, download and open a terminal here. Keys:
/find,n/Nnext and previous hit,ggo to line,ffollow,wwrap. - Search tab: the search runs on the server (grep), so large and old logs are searched quickly: literal or regex, case, whole word, context lines, From / To in your date format with quick ranges (15 minutes to 30 days), the time zone of the logs, the selected or the shown files. Hits are sorted by time (either order) with level chips, a per-file filter and a timeline you can zoom. A click opens the file at that line.
- ⚙ Log settings (per server, only its owner can change them): scan paths, main folders for the folder tree, Guess operators, excluded names, path patterns that give operator and service labels (default
/home/*/{operator}/{service}/{logdir}/**,/srv/{operator}/{service}/{logdir}/**…), extra log name patterns, depth, maximum files and age, time budget, rotated and compressed files, empty files, the systemd journal, systemd/Supervisor/Docker metadata, explicit folders and journal units, and the method (auto,ssh,sftp). Zabbix settings stay in the Zabbix dialog. - 🤖 AI log assistant: a chat panel next to the logs that searches every discovered log with
search_logs, reads around the hits and explains what failed, since when, how often and which services are affected. It is always read-only. Its chats are listed separately from terminal chats, with title, date and time. - Date and time format: EU (
dd.mm.yyyy hh:mm) by default; ISO, US or the browser's locale in Settings → Date and time format (saved per browser).
Notifications (e-mail, chat, push, webhook)
WRM tells you about events outside the browser too. Administrators set up the channels (Admin panel → Notifications), users choose what they receive and where (Settings → Notifications). The in-app messages and browser notifications stay as they are.
- Channels:
| Type | What it needs |
|---|---|
| E-mail (SMTP) | server, port, security (STARTTLS / TLS / none), optional login, from, to. A login is only sent over TLS or to a server on the WRM machine |
| Telegram | bot token (@BotFather), chat ID; optionally the address of a local Bot API server |
| Slack / Mattermost / Rocket.Chat | incoming webhook URL (Slack format) |
| Microsoft Teams | a Workflows webhook URL (Post to a channel when a webhook request is received); sent as an Adaptive Card |
| Discord | webhook URL |
| ntfy | server (ntfy.sh or your own), topic, optional access token |
| Gotify | server, application token |
| Pushover | application token, user or group key |
| Webhook | URL; WRM POSTs JSON (title, text, events). With a signing secret the header X-WRM-Signature: sha256=<HMAC-SHA256 of the body> lets the receiver check it |
- Secrets (passwords, tokens, webhook URLs) are encrypted and never shown again; leave a field empty to keep it. 📨 Send test sends a test message at once and shows the service's answer (HTTP 400 chat not found, SMTP login: …). The last delivery and the last error are listed per channel.
- Users may enter their own recipient (e-mail, Telegram, ntfy, Pushover): each user can enter their own address, chat ID, topic or user key (e-mail: plain addresses only); otherwise the channel's is used. A channel without a default recipient needs the user's own. Slack-format and Discord messages cannot mention
@channel/@everyonethrough connection names. - Events: a server went down, a server is up again (only the owner's own monitored connections; connections with monitoring off are left out), credential rotation is due (again every 7 days while it stays due), credential rotation is incomplete (again every day).
- One message per round: what happens in one status round (or within a few seconds) goes out as one digest per user and channel, and a channel sends to the same recipient at most once per
notify_min_interval_seconds(60); what comes in meanwhile goes into the next message. - Quiet hours (per user, in the browser's time zone): messages wait and are sent together when the quiet hours end.
- Messages are in the user's language (English / Hrvatski). Waiting messages survive a restart; a failing channel is retried with a growing delay and gives up after 6 attempts.
- Policies
notifications_enabled(on) andnotify_min_interval_seconds. Channel changes and tests are audited (admin.notify_channel_*), subscriptions too (notify.settings_changed).
Git workspace: compare services
⎇ Git in the top bar opens a full-screen workspace (its code, static/git.js, loads only then). It answers which version of which service runs where, and what was changed by hand — for any GitLab or GitHub (cloud or self-hosted) that you connect. WRM ships no services or organisation-specific configuration. Servers need no git, Python or internet access: WRM reads the Git provider's API itself and works on servers over its existing SSH connections, so jump hosts, proxies and the vault apply. Checks only read; servers are changed only by the runs described in the next section.
- Sources (Settings): GitLab (API v4), GitHub (REST;
github.comor Enterprise<url>/api/v3) or Gitea (API v1,<url>/api/v1) with a read-only token (encrypted, never sent back to the browser). Test lists the projects of the catalog's groups / organisations (with subgroups). Self-signed Git servers are pinned on first use. - Few API calls: one recursive tree listing per version (cached forever, a commit never changes) gives the blob ID of every file; a file's content is downloaded only for a blob WRM has not seen yet and cached by blob ID — the same file in 20 versions is fetched once.
- Offline bundles (Settings → Offline bundles): when WRM cannot reach the Git server, import a
.tar.gzbuilt elsewhere — one top directory withbundle.json(per service the target ref and the hash and history of every file) andpayload/<service>/<path>;deploytool.pyandREADME.txtare ignored, protected files of the payload are never used. The list shows the bundle's age, author and source. Services → Export bundle writes the same format for servers that only a file-based deploy tool can reach. Targets from: automatic (the Git API, otherwise the newest bundle), the Git API or a bundle. - Service catalog (Services): name, project, ref (
tag:latest,tag:v2= the newestv2.x, or a branch), branch for tags, tag filter (regex), subdirectory of the repository that is the installation root, include / exclude globs, protected per-host files (config*,*.ini,.env; matched like Python'sfnmatchon the path and the file name) that are never overwritten and only shown, fingerprint files that recognise an installation, install hints (directory names) and kind (app, library, tool). Suggest from repository fills an entry from the repository tree. Import catalog (merge or replace) and Export catalog use catalog JSON (gitlab.url/groups,fallback_branches,server_roots,apps,ignore_dirs). Services of imported bundles work without a catalog entry. - Refs: only tags whose commit is on the chosen branch count (branch-aware); versions sort numerically (
v1.10afterv1.9);tag:latestwithout a matching tag uses the branch head, and a missing branch falls back tofallback_branchesor the default branch — both with a warning. Ref in the overview: as in the catalog, one branch for all, or each project's default branch. - Discovery (Installations → Discover, and with every check): one SSH call per server walks the server roots (
/opt,/srv, …) to depth 3 and finds installations by their fingerprint files. Paths that look like copies or backups are skipped (segments withbkp,backup,bak,old,orig,prev,copy,kopija,stari,recyclebin,trash,snapshot, policygit_backup_words, plus the catalog'signore_dirs). The environment comes from the path:/srv/scripts/test/App→ test,/opt/App_prod→ prod. Installations can also be added by hand. - Comparison: the server hashes its files with
tr -d '\r' < f | sha256sum(orshasum/openssl); WRM compares them with the target (SHA-256 with CRLF → LF) and with the earlier versions of every file (the earlier tags of the branch, History depth in Settings). Files are ok, old (n behind, with the tag it matches), modified, missing, extra (only on the server) or protected; an installation is review when a file is modified, needs update when a file is old or missing, otherwise up to date.VERSION.mdandupdates.jsonlof deploy tools,.deploy-bak,.git,__pycache__are left out. - Version from the code: the deployed version is concluded from the compared files, not from
VERSION.md. When every tracked file matches one known version, that version is shown exactly; an older consistent version is looked up in its Git commit tree; a mix or a hand-edited file shows Mixed / modified with the per-file states and is never guessed as one version. The checkbox next to Check now (off by default) also comparesVERSION.mdand warns when it disagrees; deployments and updates still write it for compatibility. - Details: the detected version, commit and date, the optional
VERSION.mdversion (when the checkbox is on), the systemd / supervisor units whose unit file mentions the directory, the file states and a coloured diff of a file (server → target). - Overview: the target of every service (version, latest tag, source, warnings) and a servers × services matrix with the state, environment, detected version and n behind of each installation, filtered by state, environment, folder, tag and text.
- Periodic checks (Settings → Periodic checks): while WRM runs, the chosen servers are checked every
git_check_interval_minutes(60). Checks never change anything. They notify (one digest per round) about a new version of a service, drift (an installation that turns to review) and unreachable servers — subscribe to the Git events in Settings → Notifications. - Everything is per user (sources, catalog, installations). Policies
git_enabled(hides the workspace),git_checks(who may run checks: everyone),git_check_interval_minutes,git_backup_words. Checks, bundle imports / exports, source and catalog changes and viewed diffs are audited (git.*).
Git workspace: service functionality and configuration
Open Monitoring → Functionality, or the Functionality button in Git Simple mode. It uses the existing service catalog and installations, including GitLab sources. Manual and periodic Git checks inspect all Supervisor workers on each selected server, failed systemd services, installation disk usage and Linux memory usage (90% warns). Each installation checks discovered/configured units and reports healthy, warning, failed or unverified state with timestamps and bounded error logs. A running Supervisor worker never hides a failed sibling. Missing installations remain visible. Read access failures, absent tools, no runtime check and incomplete scans cannot be reported as healthy.
Edit a service to set optional runtime units, an HTTP health URL or a TCP host:port. HTTP accepts 2xx, follows no redirects and verifies TLS; probes originate through SSH from the selected server. Unit commands use the SSH account, without automatic sudo or restart. Commands are bounded by a 30-second runtime step (individual commands use a six-second timeout where available); endpoints use six seconds. The server inventory caps workers at 256 and failed systemd units at 64, with an explicit warning if incomplete. Logs are capped at 16 KiB per check and redacted before storage.
Configuration reads configuration files on demand and displays section, variable/function, configured value and comment description. Explicit relative config_files paths take precedence; otherwise WRM discovers .ini, .conf, .cfg, .env* and config/settings files. JSON is flattened into setting paths; INI and assignment-style settings are parsed without executing source code. Unrecognized lines are counted. Secret-name values, credential URLs and known token formats are masked; configuration contents are not stored in the database. Up to 20 files of 256 KiB each and 2,000 entries per file are inspected. Symlink escapes, unreadable/missing files and limits are reported.
Optional c
Frequently asked questions
What is WRM PRO?
Your self-hosted WRM PRO: logs, files, services and commands with approvals and audit.
How do I install WRM PRO?
It runs as a remote server. In Claude Code: claude mcp add --transport http wrm-pro 'https://{wrm_host}/mcp' --header 'Authorization: <Bearer followed by a token of an AI connection (wrm_pat_…) from WRM → Settings → AI connections>'. For other clients, paste the JSON configuration from this page into their MCP settings.
Does WRM PRO need an API key?
Yes. It expects Authorization, which you set in its configuration.
Is WRM PRO open source?
Its code is public on GitHub, but the repository does not declare a standard license.
Who maintains WRM PRO?
It is published by vedranius. AI.tn lists it but does not maintain or endorse it.
From the official MCP Registry. Listing is not an endorsement: review a server's code and permissions before giving it access to your data.