* Feature request network graph

* Fixing PR442:

- Fixed:
    - UI design elemets
    - UI and button colors
    - JSON export
    - recent activity is default again
- Removed:
    - Online/Offline UI labels
    - left-click menu on hosts
- Added:
    - small pulsing dot inside the hosts to indicate online status like in the left bar

* fix: electron build errors and skip macos job

* fix: testflight submit failure

* fix: made submit job match build type

* fix: resolve Vite build warnings for mixed static/dynamic imports (#473)

* Update Crowdin configuration file

* Update Crowdin configuration file

* fix: resolve Vite build warnings for mixed static/dynamic imports

- Convert all dynamic imports of main-axios.ts to static imports (10 files)
- Convert all dynamic imports of sonner to static imports (4 files)
- Add manual chunking configuration to vite.config.ts for better bundle splitting
  - react-vendor: React and React DOM
  - ui-vendor: Radix UI, lucide-react, clsx, tailwind-merge
  - monaco: Monaco Editor
  - codemirror: CodeMirror and related packages
- Increase chunkSizeWarningLimit to 1000kB

This resolves Vite warnings about mixed import strategies preventing
proper code-splitting.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

---------

Co-authored-by: Luke Gustafson <88517757+LukeGus@users.noreply.github.com>
Co-authored-by: Termix CI <ci@termix.dev>
Co-authored-by: Claude <noreply@anthropic.com>

* fix: file manager incorrectly decoding/encoding when editing files (made base64/utf8 dependent)

* fix: build error on docker

* Handle enter button (#481)

* Update Crowdin configuration file

* Update Crowdin configuration file

* Update Linux Portable section with AUR link (#474)

* fix: file manager incorrectly decoding/encoding when editing files (#476)

* fix: electron build errors and skip macos job

* fix: testflight submit failure

* fix: made submit job match build type

* fix: resolve Vite build warnings for mixed static/dynamic imports (#473)

* Update Crowdin configuration file

* Update Crowdin configuration file

* fix: resolve Vite build warnings for mixed static/dynamic imports

- Convert all dynamic imports of main-axios.ts to static imports (10 files)
- Convert all dynamic imports of sonner to static imports (4 files)
- Add manual chunking configuration to vite.config.ts for better bundle splitting
  - react-vendor: React and React DOM
  - ui-vendor: Radix UI, lucide-react, clsx, tailwind-merge
  - monaco: Monaco Editor
  - codemirror: CodeMirror and related packages
- Increase chunkSizeWarningLimit to 1000kB

This resolves Vite warnings about mixed import strategies preventing
proper code-splitting.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

---------

Co-authored-by: Luke Gustafson <88517757+LukeGus@users.noreply.github.com>
Co-authored-by: Termix CI <ci@termix.dev>
Co-authored-by: Claude <noreply@anthropic.com>

* fix: file manager incorrectly decoding/encoding when editing files (made base64/utf8 dependent)

---------

Co-authored-by: Jefferson Nunn <89030989+jeffersonwarrior@users.noreply.github.com>
Co-authored-by: Termix CI <ci@termix.dev>
Co-authored-by: Claude <noreply@anthropic.com>

* fix: build error on docker (#477)

* fix: electron build errors and skip macos job

* fix: testflight submit failure

* fix: made submit job match build type

* fix: resolve Vite build warnings for mixed static/dynamic imports (#473)

* Update Crowdin configuration file

* Update Crowdin configuration file

* fix: resolve Vite build warnings for mixed static/dynamic imports

- Convert all dynamic imports of main-axios.ts to static imports (10 files)
- Convert all dynamic imports of sonner to static imports (4 files)
- Add manual chunking configuration to vite.config.ts for better bundle splitting
  - react-vendor: React and React DOM
  - ui-vendor: Radix UI, lucide-react, clsx, tailwind-merge
  - monaco: Monaco Editor
  - codemirror: CodeMirror and related packages
- Increase chunkSizeWarningLimit to 1000kB

This resolves Vite warnings about mixed import strategies preventing
proper code-splitting.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

---------

Co-authored-by: Luke Gustafson <88517757+LukeGus@users.noreply.github.com>
Co-authored-by: Termix CI <ci@termix.dev>
Co-authored-by: Claude <noreply@anthropic.com>

* fix: file manager incorrectly decoding/encoding when editing files (made base64/utf8 dependent)

* fix: build error on docker

---------

Co-authored-by: Jefferson Nunn <89030989+jeffersonwarrior@users.noreply.github.com>
Co-authored-by: Termix CI <ci@termix.dev>
Co-authored-by: Claude <noreply@anthropic.com>

* Increase max old space size for npm builds

* Increase Node.js memory limit in Dockerfile

* Remove NODE_OPTIONS from build commands in Dockerfile

* Change runner to blacksmith-4vcpu-ubuntu-2404

* fix: build error on docker

* Add handle on enter button;

---------

Co-authored-by: Luke Gustafson <88517757+LukeGus@users.noreply.github.com>
Co-authored-by: Gaylord Julien <g.j@mailbox.org>
Co-authored-by: Jefferson Nunn <89030989+jeffersonwarrior@users.noreply.github.com>
Co-authored-by: Termix CI <ci@termix.dev>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: LukeGus <bugattiguy527@gmail.com>

* fix: remove top tech

* fix: update readme

* fix: prevent long container names from overflowing card (#496)

Added min-w-0 to CardTitle to allow text truncation in flexbox.
Without this, flex items have min-width: auto which prevents
the truncate class from working properly.

Fixes #411

* fix: use SFTP readdir for file listing to support non-Linux systems (#495)

The file manager now uses SFTP readdir as the primary method for
listing files, with ls -la as a fallback. This enables compatibility
with MikroTik RouterOS and other non-Linux systems that don't have
standard shell commands.

Fixes #317

* fix: restore SSH connection timeout to 120s for 2FA authentication (#494)

The timeout was reduced from 120s to 30s in v1.10, causing 2FA login
failures. Users with keyboard-interactive authentication (TOTP/2FA)
need sufficient time to enter their verification codes before the
SSH connection times out.

Fixes #404

* feat: add Docker container healthcheck (#493)

* fix: owner should not be marked as shared when host is shared to their role (#492)

* fix: use correct MIME types for image preview (#491)

* fix: prevent session reset when updating host properties (#490)

* fix: add shell creation timeout and improve error handling (#489)

* fix: set default lineHeight to 1.0 for TUI apps compatibility (#488)

* fix: delete all related data when removing user (#487)

* fix: nginx permission denied on restricted kernels (#486)

* fix: skip existing hosts and credentials during JSON import (#485)

Added duplicate detection for SSH hosts (by ip+port+username) and
credentials (by name) during import. Existing items are now skipped
by default, or updated if replaceExisting option is enabled.

This matches the existing behavior of importDismissedAlerts.

Fixes #389

* feat: add firewall status widget for server stats (#484)

* Feature: PWA (#479)

* feat: add PWA support with offline capabilities

- Add web app manifest with icons and theme configuration
- Add service worker with cache-first strategy for static assets
- Add useServiceWorker hook for SW registration
- Add PWA meta tags and Apple-specific tags to index.html
- Update vite.config.ts for optimal asset caching

* Update package-lock.json

* New Crowdin updates (#472)

* New translations en.json (Romanian)

* New translations en.json (French)

* New translations en.json (Spanish)

* New translations en.json (Afrikaans)

* New translations en.json (Arabic)

* New translations en.json (Catalan)

* New translations en.json (Czech)

* New translations en.json (Danish)

* New translations en.json (German)

* New translations en.json (Greek)

* New translations en.json (Finnish)

* New translations en.json (Hebrew)

* New translations en.json (Hungarian)

* New translations en.json (Italian)

* New translations en.json (Japanese)

* New translations en.json (Korean)

* New translations en.json (Dutch)

* New translations en.json (Norwegian)

* New translations en.json (Polish)

* New translations en.json (Portuguese)

* New translations en.json (Russian)

* New translations en.json (Serbian (Cyrillic))

* New translations en.json (Swedish)

* New translations en.json (Turkish)

* New translations en.json (Ukrainian)

* New translations en.json (Chinese Simplified)

* New translations en.json (English)

* New translations en.json (Vietnamese)

* New translations en.json (German)

* feat: add listening ports widget for server stats (#483)

Co-authored-by: Luke Gustafson <88517757+LukeGus@users.noreply.github.com>

* feat: fix network stats merge and add openapi jsdocs comments

* feat: add workflow/config to auto generate openapi json

* feat: remove locales

* feat: support URL routes to open terminal directly (#156) (#503)

* fix: resolve merge conflict artifacts in dev-1.10.1

- Fix missing closing tags in AppView.tsx NetworkGraphView
- Fix incomplete catch blocks in server-stats.ts and db/index.ts
- Fix missing closing brace in en.json ports section
- Fix HostManagerApp.tsx import path
- Fix stats-widgets.ts type definition
- Fix schema.ts networkTopology table definition
- Add type annotations in user-data-import.ts

* feat: support URL routes to open terminal directly (#156)

- Add /terminal/{hostNameOrId} route for new format
- Keep /hosts/{id}/terminal for backward compatibility
- Smart detection: numeric IDs for ID lookup, otherwise name lookup
- Clean URL after opening to prevent duplicate on refresh
- Show toast error when host not found

---------

Co-authored-by: Luke Gustafson <88517757+LukeGus@users.noreply.github.com>

* feat: add Ctrl+Alt key remapping for browser-blocked shortcuts (#501)

Browsers intercept Ctrl+W/T/N/Q, making them unusable in terminal.
This adds Ctrl+Alt+<key> as an alternative that sends Ctrl+<key>.

- Ctrl+Alt+W → Ctrl+W (nano search, delete word)
- Ctrl+Alt+T → Ctrl+T (transpose chars)
- Ctrl+Alt+N → Ctrl+N (next line)
- Ctrl+Alt+Q → Ctrl+Q (XON flow control)

Fixes Termix-SSH/Support#407

* feat: remove locales

* New Crowdin updates (#504)

* New translations en.json (Romanian)

* New translations en.json (French)

* New translations en.json (Spanish)

* New translations en.json (Afrikaans)

* New translations en.json (Arabic)

* New translations en.json (Catalan)

* New translations en.json (Czech)

* New translations en.json (Danish)

* New translations en.json (German)

* New translations en.json (Greek)

* New translations en.json (Finnish)

* New translations en.json (Hebrew)

* New translations en.json (Hungarian)

* New translations en.json (Italian)

* New translations en.json (Japanese)

* New translations en.json (Korean)

* New translations en.json (Dutch)

* New translations en.json (Norwegian)

* New translations en.json (Polish)

* New translations en.json (Portuguese)

* New translations en.json (Russian)

* New translations en.json (Serbian (Cyrillic))

* New translations en.json (Swedish)

* New translations en.json (Turkish)

* New translations en.json (Ukrainian)

* New translations en.json (Chinese Simplified)

* New translations en.json (English)

* New translations en.json (Vietnamese)

* New translations en.json (German)

* New translations en.json (Norwegian)

* New translations en.json (Romanian)

* New translations en.json (French)

* New translations en.json (Spanish)

* New translations en.json (Arabic)

* New translations en.json (Czech)

* New translations en.json (Danish)

* New translations en.json (Greek)

* New translations en.json (Finnish)

* New translations en.json (Italian)

* New translations en.json (Japanese)

* New translations en.json (Dutch)

* New translations en.json (Norwegian)

* New translations en.json (Polish)

* New translations en.json (Portuguese)

* New translations en.json (Russian)

* New translations en.json (Swedish)

* New translations en.json (Ukrainian)

* New translations en.json (Chinese Simplified)

* New translations en.json (Chinese Traditional)

* New translations en.json (Finnish)

* New translations en.json (Chinese Simplified)

* New translations en.json (Chinese Traditional)

* feat: add option to disable update checker (#502)

* feat: add option to disable update checker

Add a new setting in User Profile > Settings to disable automatic
update checking on startup and dashboard.

- Adds 'Disable Update Check' toggle in profile settings
- Skips GitHub API calls when disabled (reduces network requests)
- Works for both web app and Electron client

Fixes Termix-SSH/Support#410

* feat: remove locales

---------

Co-authored-by: LukeGus <bugattiguy527@gmail.com>

* New Crowdin updates (#505)

* New translations en.json (Romanian)

* New translations en.json (French)

* New translations en.json (Spanish)

* New translations en.json (Afrikaans)

* New translations en.json (Arabic)

* New translations en.json (Catalan)

* New translations en.json (Czech)

* New translations en.json (Danish)

* New translations en.json (German)

* New translations en.json (Greek)

* New translations en.json (Finnish)

* New translations en.json (Hebrew)

* New translations en.json (Hungarian)

* New translations en.json (Italian)

* New translations en.json (Japanese)

* New translations en.json (Korean)

* New translations en.json (Dutch)

* New translations en.json (Norwegian)

* New translations en.json (Polish)

* New translations en.json (Portuguese)

* New translations en.json (Russian)

* New translations en.json (Serbian (Cyrillic))

* New translations en.json (Swedish)

* New translations en.json (Turkish)

* New translations en.json (Ukrainian)

* New translations en.json (Chinese Simplified)

* New translations en.json (English)

* New translations en.json (Vietnamese)

* New translations en.json (German)

* New translations en.json (Norwegian)

* New translations en.json (Romanian)

* New translations en.json (French)

* New translations en.json (Spanish)

* New translations en.json (Arabic)

* New translations en.json (Czech)

* New translations en.json (Danish)

* New translations en.json (Greek)

* New translations en.json (Finnish)

* New translations en.json (Italian)

* New translations en.json (Japanese)

* New translations en.json (Dutch)

* New translations en.json (Norwegian)

* New translations en.json (Polish)

* New translations en.json (Portuguese)

* New translations en.json (Russian)

* New translations en.json (Swedish)

* New translations en.json (Ukrainian)

* New translations en.json (Chinese Simplified)

* New translations en.json (Chinese Traditional)

* New translations en.json (Finnish)

* New translations en.json (Chinese Simplified)

* New translations en.json (Chinese Traditional)

* New translations en.json (Chinese Simplified)

* New translations en.json (Chinese Traditional)

* New translations en.json (Bulgarian)

* New translations en.json (Indonesian)

* New translations en.json (Hindi)

* feat: add crowdin i18n

* feat: remove locales

* New Crowdin updates (#506)

* New translations en.json (Romanian)

* New translations en.json (French)

* New translations en.json (Spanish)

* New translations en.json (Afrikaans)

* New translations en.json (Arabic)

* New translations en.json (Catalan)

* New translations en.json (Czech)

* New translations en.json (Danish)

* New translations en.json (German)

* New translations en.json (Greek)

* New translations en.json (Finnish)

* New translations en.json (Hebrew)

* New translations en.json (Hungarian)

* New translations en.json (Italian)

* New translations en.json (Japanese)

* New translations en.json (Korean)

* New translations en.json (Dutch)

* New translations en.json (Norwegian)

* New translations en.json (Polish)

* New translations en.json (Portuguese)

* New translations en.json (Russian)

* New translations en.json (Serbian (Cyrillic))

* New translations en.json (Swedish)

* New translations en.json (Turkish)

* New translations en.json (Ukrainian)

* New translations en.json (Chinese Simplified)

* New translations en.json (English)

* New translations en.json (Vietnamese)

* New translations en.json (German)

* New translations en.json (Norwegian)

* New translations en.json (Romanian)

* New translations en.json (French)

* New translations en.json (Spanish)

* New translations en.json (Arabic)

* New translations en.json (Czech)

* New translations en.json (Danish)

* New translations en.json (Greek)

* New translations en.json (Finnish)

* New translations en.json (Italian)

* New translations en.json (Japanese)

* New translations en.json (Dutch)

* New translations en.json (Norwegian)

* New translations en.json (Polish)

* New translations en.json (Portuguese)

* New translations en.json (Russian)

* New translations en.json (Swedish)

* New translations en.json (Ukrainian)

* New translations en.json (Chinese Simplified)

* New translations en.json (Chinese Traditional)

* New translations en.json (Finnish)

* New translations en.json (Chinese Simplified)

* New translations en.json (Chinese Traditional)

* New translations en.json (Chinese Simplified)

* New translations en.json (Chinese Traditional)

* New translations en.json (Bulgarian)

* New translations en.json (Indonesian)

* New translations en.json (Hindi)

* New translations en.json (Romanian)

* New translations en.json (French)

* New translations en.json (Spanish)

* New translations en.json (Afrikaans)

* New translations en.json (Arabic)

* New translations en.json (Catalan)

* New translations en.json (Czech)

* New translations en.json (German)

* New translations en.json (Greek)

* New translations en.json (Finnish)

* New translations en.json (Hebrew)

* New translations en.json (Hungarian)

* New translations en.json (Italian)

* New translations en.json (Japanese)

* New translations en.json (Korean)

* New translations en.json (Dutch)

* New translations en.json (Polish)

* New translations en.json (Portuguese)

* New translations en.json (Russian)

* New translations en.json (Serbian (Cyrillic))

* New translations en.json (Turkish)

* New translations en.json (Ukrainian)

* New translations en.json (Chinese Simplified)

* New translations en.json (Chinese Traditional)

* New translations en.json (Vietnamese)

* New translations en.json (Portuguese, Brazilian)

* New translations en.json (Bulgarian)

* New translations en.json (Indonesian)

* New translations en.json (Hindi)

* New translations en.json (Bengali)

* New translations en.json (Thai)

* feat: update readme

* feat: update readme

* feat: update credential editor to use submitting system and add health monitor

* feat: added toggle for command pallete

* feat: added close button on tab dropdown

* feat: added sidebar management and improved some host manager UI/UX

* feat: re-added missing users.ts route from merge

* feat: add toggle for password reset feature in admin settings (#508)

* feat: add sudo support for file manager operations (#509)

* fix: add sudo support for listFiles and improve permission error handling (#512)

* feat: add sudo support for file manager operations

* fix: add sudo support for listFiles and improve permission error handling

---------

Co-authored-by: Luke Gustafson <88517757+LukeGus@users.noreply.github.com>

* feat: fix sudo password dialog ui, add totp/pass reset limiting, and refreshed users screen when auth is outdated

* feat: add copy password button and fixed new line carriage issues and backend crash for auth key

* feat: added quick connection system (ad-hoc)

* Enter Key for Quick Login (#513)

* feat: added -r and -l support for tunnels

* feat: begin dashboard overhaul by splitting into cards and adding customization

* feat: improved full screen apps, overhauled dashboard, updated server stats ui, etc.

* feat: add auth.tsx suppot for fullscreen

* feat: greatly improve network graph ui/ux and migrated to use translations and theme system

* feat: update to use blacksmith

* feat: improve ui for customized tabs and hide add/edit host/credential when submiting

* feat: add warpgate support with a dialog (terminal only)

* feat: expand warpgate to docker/file manager

* fix: docker not working wtih warpgate and none auth failing for terminal

* fix: prevent owner permission loss when sharing host to own role (#514)

* Update Crowdin configuration file

* Update Crowdin configuration file

* Update Linux Portable section with AUR link (#474)

* fix: file manager incorrectly decoding/encoding when editing files (#476)

* fix: electron build errors and skip macos job

* fix: testflight submit failure

* fix: made submit job match build type

* fix: resolve Vite build warnings for mixed static/dynamic imports (#473)

* Update Crowdin configuration file

* Update Crowdin configuration file

* fix: resolve Vite build warnings for mixed static/dynamic imports

- Convert all dynamic imports of main-axios.ts to static imports (10 files)
- Convert all dynamic imports of sonner to static imports (4 files)
- Add manual chunking configuration to vite.config.ts for better bundle splitting
  - react-vendor: React and React DOM
  - ui-vendor: Radix UI, lucide-react, clsx, tailwind-merge
  - monaco: Monaco Editor
  - codemirror: CodeMirror and related packages
- Increase chunkSizeWarningLimit to 1000kB

This resolves Vite warnings about mixed import strategies preventing
proper code-splitting.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

---------

Co-authored-by: Luke Gustafson <88517757+LukeGus@users.noreply.github.com>
Co-authored-by: Termix CI <ci@termix.dev>
Co-authored-by: Claude <noreply@anthropic.com>

* fix: file manager incorrectly decoding/encoding when editing files (made base64/utf8 dependent)

---------

Co-authored-by: Jefferson Nunn <89030989+jeffersonwarrior@users.noreply.github.com>
Co-authored-by: Termix CI <ci@termix.dev>
Co-authored-by: Claude <noreply@anthropic.com>

* fix: build error on docker (#477)

* fix: electron build errors and skip macos job

* fix: testflight submit failure

* fix: made submit job match build type

* fix: resolve Vite build warnings for mixed static/dynamic imports (#473)

* Update Crowdin configuration file

* Update Crowdin configuration file

* fix: resolve Vite build warnings for mixed static/dynamic imports

- Convert all dynamic imports of main-axios.ts to static imports (10 files)
- Convert all dynamic imports of sonner to static imports (4 files)
- Add manual chunking configuration to vite.config.ts for better bundle splitting
  - react-vendor: React and React DOM
  - ui-vendor: Radix UI, lucide-react, clsx, tailwind-merge
  - monaco: Monaco Editor
  - codemirror: CodeMirror and related packages
- Increase chunkSizeWarningLimit to 1000kB

This resolves Vite warnings about mixed import strategies preventing
proper code-splitting.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

---------

Co-authored-by: Luke Gustafson <88517757+LukeGus@users.noreply.github.com>
Co-authored-by: Termix CI <ci@termix.dev>
Co-authored-by: Claude <noreply@anthropic.com>

* fix: file manager incorrectly decoding/encoding when editing files (made base64/utf8 dependent)

* fix: build error on docker

---------

Co-authored-by: Jefferson Nunn <89030989+jeffersonwarrior@users.noreply.github.com>
Co-authored-by: Termix CI <ci@termix.dev>
Co-authored-by: Claude <noreply@anthropic.com>

* Increase max old space size for npm builds

* Increase Node.js memory limit in Dockerfile

* Remove NODE_OPTIONS from build commands in Dockerfile

* Change runner to blacksmith-4vcpu-ubuntu-2404

* fix: build error on docker

* fix: prevent owner permission loss when sharing host to own role

Fixes #391

---------

Co-authored-by: Luke Gustafson <88517757+LukeGus@users.noreply.github.com>
Co-authored-by: Gaylord Julien <g.j@mailbox.org>
Co-authored-by: Jefferson Nunn <89030989+jeffersonwarrior@users.noreply.github.com>
Co-authored-by: Termix CI <ci@termix.dev>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: LukeGus <bugattiguy527@gmail.com>

* fix: SSH key passphrase not passed for Docker and Tunnel (#521)

* perf: optimize Host Manager for large host lists

- Add ServerStatusContext for shared status polling (reduces API calls from N to 1)
- Move TooltipProvider to component root (eliminates N context instances)
- Add pagination with "Show More" button (limits initial DOM nodes per folder)

Fixes performance issues when managing ~1000 hosts with status monitoring enabled.

* fix: SSH key passphrase not passed to ssh2 for Docker and Tunnel

Database field is `key_password` but code used `keyPassword`.
Added fallback to check both field names.

Affected:
- docker.ts: Docker SSH connections with encrypted keys
- tunnel.ts: Tunnel connections with encrypted keys

---------

Co-authored-by: Luke Gustafson <88517757+LukeGus@users.noreply.github.com>

* perf: optimize Host Manager for large host lists (#520)

- Add ServerStatusContext for shared status polling (reduces API calls from N to 1)
- Move TooltipProvider to component root (eliminates N context instances)
- Add pagination with "Show More" button (limits initial DOM nodes per folder)

Fixes performance issues when managing ~1000 hosts with status monitoring enabled.

Co-authored-by: Luke Gustafson <88517757+LukeGus@users.noreply.github.com>

* fix: add missing mimeTypes definition for image preview (#518)

Fixes Termix-SSH/Support#408

* fix: prevent session reset when updating host properties (#517)

Move WebSocket cleanup logic to a separate unmount-only effect to
prevent SSH sessions from being closed when host properties are updated.

Closes Termix-SSH/Support#401

* fix: backend type error

* feat: make terminal connections more resilient, added connection log, and fixed https/proxy reconnection loop (issue #385)

* feat: improved conneciton log ui/logic

* feat: improved conneciton log ui/logic

* feat: expanded connection log to work across all components (readying for release)

* feat: update readme

* feat: update readme

* fix: build error

* fix: build error

* fix: changed ver

* chore: clean up

* chore: continue clean up

* fix: remove attempts remaining and fix electron errors and some connection log ui inconsistencies

* fix: added missing nginx routes and fixed sudo password copy with sudo password autofil field

* fix: update readme and run cleaner

* fix: update readme

* fix: update readme

* fix: update readme

* feat: update chinese readme

---------

Co-authored-by: Steven Josefs <s.josefs@gmx.de>
Co-authored-by: Jefferson Nunn <89030989+jeffersonwarrior@users.noreply.github.com>
Co-authored-by: Termix CI <ci@termix.dev>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Nunzio Marfè <nunzio.marfe@protonmail.com>
Co-authored-by: Gaylord Julien <g.j@mailbox.org>
Co-authored-by: ZacharyZcR <zacharyzcr1984@gmail.com>
Co-authored-by: Aditya Tawade <36890395+aditya-tawade@users.noreply.github.com>
This commit is contained in:
Luke Gustafson
2026-01-24 19:49:42 -06:00
committed by GitHub
co-authored by Steven Josefs Jefferson Nunn Termix CI Claude Nunzio Marfè Gaylord Julien ZacharyZcR Aditya Tawade
parent 366667ca92
commit 536dc35258
169 changed files with 79905 additions and 47362 deletions
+283 -11
View File
@@ -44,6 +44,8 @@
"passwordRequired": "Password is required",
"sshKeyRequired": "SSH key is required",
"credentialAddedSuccessfully": "Credential \"{{name}}\" added successfully",
"savingCredential": "Saving credential...",
"updatingCredential": "Updating credential...",
"general": "General",
"description": "Description",
"folder": "Folder",
@@ -184,6 +186,32 @@
"renameFolder": "Rename folder",
"idLabel": "ID:"
},
"quickConnect": {
"title": "Quick Connect",
"description": "Connect directly to a terminal or file manager session without saving a host configuration",
"ipAddress": "IP Address or Hostname",
"port": "Port",
"username": "Username",
"password": "Password",
"key": "SSH Private Key",
"keyPassword": "Key Password (Optional)",
"keyType": "Key Type",
"uploadFile": "Upload File",
"pasteKey": "Paste Key",
"credential": "Credential",
"overrideUsername": "Override Credential Username",
"overrideUsernameDesc": "Use a different username than the one stored in the credential",
"connectTerminal": "Connect to Terminal",
"connectFileManager": "Connect to File Manager",
"cancel": "Cancel",
"passwordRequired": "Password is required",
"keyRequired": "SSH key is required",
"credentialRequired": "Credential selection is required",
"connectionEstablished": "Connection established successfully",
"connectionFailed": "Failed to establish connection",
"autoDetect": "Auto Detect",
"authentication": "Authentication"
},
"dragIndicator": {
"error": "Error: {{error}}",
"dragging": "Dragging {{fileName}}",
@@ -387,6 +415,7 @@
"sshPath": "SSH Path",
"localPath": "Local Path",
"appName": "Termix",
"openInNewTab": "Open in New Tab",
"resetSidebarWidth": "Reset sidebar width",
"dragToResizeSidebar": "Drag to resize sidebar",
"noAuthCredentials": "No authentication credentials available for this SSH host",
@@ -464,10 +493,12 @@
"retry": "Retry",
"checking": "Checking...",
"checkingDatabase": "Checking database connection...",
"checkingAuthentication": "Checking authentication...",
"actions": "Actions",
"remove": "Remove",
"revoke": "Revoke",
"create": "Create"
"create": "Create",
"update": "Update"
},
"nav": {
"home": "Home",
@@ -489,7 +520,12 @@
"hostManager": "Host Manager",
"cannotSplitTab": "Cannot split this tab",
"tabNavigation": "Tab Navigation",
"hostTabTitle": "{{username}}@{{ip}}:{{port}}"
"hostTabTitle": "{{username}}@{{ip}}:{{port}}",
"copyPassword": "Copy Password",
"copySudoPassword": "Copy Sudo Password",
"passwordCopied": "Password copied to clipboard",
"sudoPasswordCopied": "Sudo password copied to clipboard",
"noPasswordAvailable": "No password available"
},
"admin": {
"title": "Admin Settings",
@@ -537,6 +573,7 @@
"userRegistration": "User Registration",
"allowNewAccountRegistration": "Allow new account registration",
"allowPasswordLogin": "Allow username/password login",
"allowPasswordReset": "Allow password reset via reset code",
"missingRequiredFields": "Missing required fields: {{fields}}",
"oidcConfigurationUpdated": "OIDC configuration updated successfully!",
"failedToFetchOidcConfig": "Failed to fetch OIDC configuration",
@@ -856,6 +893,13 @@
"autoStartContainer": "Auto Start on Container Launch",
"autoStartDesc": "Automatically start this tunnel when the container launches",
"addConnection": "Add Tunnel Connection",
"tunnelType": "Tunnel Type",
"tunnelTypeLocal": "Local (-L)",
"tunnelTypeRemote": "Remote (-R)",
"tunnelTypeLocalDesc": "Forward local port to remote endpoint",
"tunnelTypeRemoteDesc": "Forward remote port to local machine",
"tunnelForwardDescriptionLocal": "This tunnel will forward traffic from local port {{sourcePort}} to port {{endpointPort}} on the endpoint machine.",
"tunnelForwardDescriptionRemote": "This tunnel will forward traffic from port {{sourcePort}} on the source machine (current connection details in general tab) to port {{endpointPort}} on the endpoint machine.",
"sshpassRequired": "Sshpass Required For Password Authentication",
"sshpassRequiredDesc": "For password authentication in tunnels, sshpass must be installed on the system.",
"otherInstallMethods": "Other installation methods:",
@@ -863,13 +907,16 @@
"or": "or",
"centosRhelFedora": "CentOS/RHEL/Fedora",
"macos": "macOS",
"windows": "Windows",
"windows": "Windows (WSL, no official binary)",
"sshServerConfigRequired": "SSH Server Configuration Required",
"sshServerConfigDesc": "For tunnel connections, the SSH server must be configured to allow port forwarding:",
"gatewayPortsYes": "to bind remote ports to all interfaces",
"allowTcpForwardingYes": "to enable port forwarding",
"permitRootLoginYes": "if using root user for tunneling",
"editSshConfig": "Edit /etc/ssh/sshd_config and restart SSH: sudo systemctl restart sshd",
"editSshConfig": "Edit the SSH configuration file:",
"sshConfigPath": "/etc/ssh/sshd_config",
"restartSshService": "Then restart the SSH service:",
"restartSshCommand": "sudo systemctl restart sshd",
"upload": "Upload",
"authentication": "Authentication",
"password": "Password",
@@ -1106,6 +1153,19 @@
"quickActionName": "Action name",
"noSnippetFound": "No snippet found",
"quickActionsOrder": "Quick action buttons will appear in the order listed above on the Server Stats page",
"sidebarCustomization": "Sidebar Button Customization",
"sidebarCustomizationDesc": "Choose which actions appear as quick buttons in the sidebar. Actions not shown as buttons will appear in the dropdown menu.",
"showTerminalInSidebar": "Show Terminal Button",
"showTerminalInSidebarDesc": "Display terminal as a quick button in the sidebar",
"showFileManagerInSidebar": "Show File Manager Button",
"showFileManagerInSidebarDesc": "Display file manager as a quick button in the sidebar",
"showTunnelInSidebar": "Show Tunnel Button",
"showTunnelInSidebarDesc": "Display tunnel management as a quick button in the sidebar",
"showDockerInSidebar": "Show Docker Button",
"showDockerInSidebarDesc": "Display docker management as a quick button in the sidebar",
"showServerStatsInSidebar": "Show Server Stats Button",
"showServerStatsInSidebarDesc": "Display server statistics as a quick button in the sidebar",
"atLeastOneActionRequired": "At least one enabled action must be shown in the sidebar",
"advancedAuthSettings": "Advanced Authentication Settings",
"sudoPasswordAutoFill": "Sudo Password Auto-Fill",
"sudoPasswordAutoFillDesc": "Automatically offer to insert SSH password when sudo prompts for password",
@@ -1125,6 +1185,15 @@
"addVariable": "Add Variable",
"docker": "Docker",
"openDocker": "Open Docker",
"copyFullScreenUrl": "Copy Full-Screen URL",
"fullScreenUrlCopied": "Full-screen URL copied to clipboard",
"failedToCopyUrl": "Failed to copy URL to clipboard",
"copyTerminalUrl": "Copy Terminal URL",
"copyFileManagerUrl": "Copy File Manager URL",
"copyTunnelUrl": "Copy Tunnel URL",
"copyServerStatsUrl": "Copy Server Stats URL",
"copyDockerUrl": "Copy Docker URL",
"fullScreenUrlTooltip": "Copy URL to open this app in full-screen mode",
"notEnabled": "Docker is not enabled for this host. Enable it in Host Settings to use Docker features.",
"validating": "Validating Docker...",
"error": "Error",
@@ -1274,10 +1343,34 @@
"totpCodeLabel": "Verification Code",
"totpPlaceholder": "000000",
"totpVerify": "Verify",
"warpgateAuthRequired": "Warpgate Authentication Required",
"warpgateSecurityKey": "Security Key",
"warpgateAuthUrl": "Authentication URL",
"warpgateOpenBrowser": "Open in Browser",
"warpgateContinue": "I've Completed Authentication",
"warpgateTimeout": "Warpgate authentication timeout. Please reconnect.",
"sudoPasswordPopupTitle": "Insert Password?",
"sudoPasswordPopupHint": "Press Enter to insert, Esc to dismiss",
"sudoPasswordPopupConfirm": "Insert",
"sudoPasswordPopupDismiss": "Dismiss"
"sudoPasswordPopupDismiss": "Dismiss",
"websocketAbnormalClose": "Connection closed unexpectedly. This may be due to a reverse proxy or SSL configuration issue. Please check server logs.",
"totpInvalid": "Invalid code. Please try again.",
"authMethodFallback": "{{method}} authentication failed. Trying alternative method...",
"authenticationRequired": "Authentication required",
"connectionLogTitle": "Connection Log",
"connectionLogCopy": "Copy logs to clipboard",
"connectionLogClear": "Clear logs",
"connectionLogEmpty": "No connection logs yet",
"connectionLogConnecting": "Connecting to host...",
"connectionLogCopied": "Connection logs copied to clipboard",
"connectionLogCopyFailed": "Failed to copy logs to clipboard",
"allAuthMethodsFailed": "All authentication methods failed. Please check your credentials.",
"methodNotSupported": "Server does not support {{method}} authentication. Available methods: {{available}}",
"retryWithMethod": "Retry with {{method}}",
"automaticFallback": "Automatically trying {{method}} authentication...",
"totpTimeout": "TOTP verification timeout. Please reconnect.",
"passwordTimeout": "Password verification timeout. Please reconnect.",
"connectionRejected": "Connection rejected by server. Please check your authentication and network configuration."
},
"fileManager": {
"title": "File Manager",
@@ -1360,6 +1453,12 @@
"itemDeletedSuccessfully": "{{type}} deleted successfully",
"itemsDeletedSuccessfully": "{{count}} items deleted successfully",
"failedToDeleteItems": "Failed to delete items",
"sudoPasswordRequired": "Administrator Password Required",
"enterSudoPassword": "Enter sudo password to continue this operation",
"sudoPassword": "Sudo password",
"sudoOperationFailed": "Sudo operation failed",
"sudoAuthFailed": "Sudo authentication failed",
"deleteOperation": "Delete files/folders",
"dragFilesToUpload": "Drop files here to upload",
"emptyFolder": "This folder is empty",
"itemCount": "{{count}} items",
@@ -1564,9 +1663,11 @@
"fileTooLarge": "File too large: {{error}}",
"sshConnectionFailed": "SSH connection failed. Please check your connection to {{name}} ({{ip}}:{{port}})",
"loadFileFailed": "Failed to load file: {{error}}",
"connecting": "Connecting...",
"connectedSuccessfully": "Connected successfully",
"totpVerificationFailed": "TOTP verification failed",
"sshConnectionFailed": "SSH connection failed. Please check your connection to {{name}} ({{ip}}:{{port}})",
"warpgateVerificationFailed": "Warpgate authentication failed",
"authenticationFailed": "Authentication failed",
"verificationCodePrompt": "Verification code:",
"newFolderDefault": "NewFolder",
"newFileDefault": "NewFile.txt",
@@ -1673,6 +1774,8 @@
"refreshStatus": "Refresh Status",
"fileManagerAlreadyOpen": "File Manager already open for this host",
"openFileManager": "Open File Manager",
"connecting": "Connecting...",
"connectionFailed": "Failed to connect to server",
"cpuCores_one": "{{count}} CPU",
"cpuCores_other": "{{count}} CPUs",
"naCpus": "N/A CPU(s)",
@@ -1731,7 +1834,34 @@
"executingQuickAction": "Executing {{name}}...",
"quickActionSuccess": "{{name}} completed successfully",
"quickActionFailed": "{{name}} failed",
"quickActionError": "Failed to execute {{name}}"
"quickActionError": "Failed to execute {{name}}",
"ports": {
"title": "Listening Ports",
"protocol": "Protocol",
"port": "Port",
"address": "Address",
"state": "State",
"process": "Process",
"noData": "No listening ports data"
},
"firewall": {
"title": "Firewall",
"active": "Active",
"inactive": "Inactive",
"notDetected": "Not Detected",
"policy": "Policy",
"rules": "rules",
"noRules": "No rules",
"noData": "No firewall data available",
"action": "Action",
"protocol": "Proto",
"port": "Port",
"source": "Source",
"accept": "ACCEPT",
"drop": "DROP",
"reject": "REJECT",
"anywhere": "Anywhere"
}
},
"auth": {
"tagline": "SSH SERVER MANAGER",
@@ -1873,7 +2003,11 @@
"emailExists": "Email already exists",
"loadFailed": "Failed to load data",
"saveError": "Failed to save",
"sessionExpired": "Session expired - please log in again"
"sessionExpired": "Session expired - please log in again",
"totpRateLimited": "Rate limited: Too many TOTP verification attempts. Please try again later.",
"totpRateLimitedWithTime": "Rate limited: Too many TOTP verification attempts. Please wait {{time}} seconds before trying again.",
"resetCodeRateLimited": "Rate limited: Too many verification attempts. Please try again later.",
"resetCodeRateLimitedWithTime": "Rate limited: Too many verification attempts. Please wait {{time}} seconds before trying again."
},
"messages": {
"saveSuccess": "Saved successfully",
@@ -1931,6 +2065,9 @@
"terminalSettings": "Terminal",
"hostSidebarSettings": "Host & Sidebar",
"snippetsSettings": "Snippets",
"updateSettings": "Updates",
"disableUpdateCheck": "Disable Update Check",
"disableUpdateCheckDesc": "Stop checking for new versions on startup and dashboard. Reduces network requests.",
"currentPassword": "Current Password",
"passwordChangedSuccess": "Password changed successfully! Please log in again.",
"failedToChangePassword": "Failed to change password. Please check your current password and try again.",
@@ -1939,7 +2076,9 @@
"themeDark": "Dark",
"themeSystem": "System",
"appearanceDesc": "Select the color theme for the application",
"terminalSyntaxHighlightingDesc": "Automatically highlight commands, paths, IPs, and log levels in terminal output"
"terminalSyntaxHighlightingDesc": "Automatically highlight commands, paths, IPs, and log levels in terminal output",
"enableCommandPaletteShortcut": "Enable Command Palette Shortcut",
"enableCommandPaletteShortcutDesc": "Double-tap left Shift to open the Command Palette for quick access to hosts"
},
"user": {
"failedToLoadVersionInfo": "Failed to load version information"
@@ -2134,6 +2273,7 @@
},
"dashboard": {
"title": "Dashboard",
"loading": "Loading dashboard...",
"github": "GitHub",
"support": "Support",
"discord": "Discord",
@@ -2163,7 +2303,88 @@
"noServerData": "No server data available",
"cpu": "CPU",
"ram": "RAM",
"notAvailable": "N/A"
"notAvailable": "N/A",
"customizeLayout": "Customize Dashboard",
"dashboardSettings": "Dashboard Settings",
"enableDisableCards": "Enable/Disable Cards",
"resetLayout": "Reset to Default",
"serverOverviewCard": "Server Overview",
"recentActivityCard": "Recent Activity",
"networkGraphCard": "Network Graph",
"networkGraph": "Network Graph",
"quickActionsCard": "Quick Actions",
"serverStatsCard": "Server Stats"
},
"networkGraph": {
"title": "Network Graph",
"addHost": "Add Host",
"addGroup": "Add Group",
"addLink": "Add Link",
"deleteSelected": "Delete Selected",
"zoomIn": "Zoom In",
"zoomOut": "Zoom Out",
"resetView": "Reset View",
"exportJson": "Export JSON",
"importJson": "Import JSON",
"selectHost": "Select Host",
"chooseHost": "Choose a host...",
"parentGroup": "Parent Group",
"noGroup": "No Group",
"groupName": "Group Name",
"color": "Color",
"source": "Source",
"target": "Target",
"moveToGroup": "Move to Group",
"selectGroup": "Select group...",
"addConnection": "Add Connection",
"hostDetails": "Host Details",
"connectToHost": "Connect to Host",
"openTerminal": "Open Terminal",
"openFileManager": "Open File Manager",
"openTunnel": "Open Tunnels",
"openDocker": "Open Docker",
"openServerStats": "Open Server Details",
"moveToGroupAction": "Move to Group",
"removeFromGroup": "Remove from Group",
"addHostHere": "Add Host Here",
"editGroup": "Edit Group",
"delete": "Delete",
"cancel": "Cancel",
"add": "Add",
"create": "Create",
"update": "Update",
"move": "Move",
"connect": "Connect",
"close": "Close",
"createGroup": "Create Group",
"noAvailableHosts": "No available hosts",
"selectSourcePlaceholder": "Select Source...",
"selectTargetPlaceholder": "Select Target...",
"invalidFile": "Invalid File",
"hostAlreadyExists": "Host is already in the topology",
"sourceTargetMustDiffer": "Source and target must be different",
"connectionExists": "Connection already exists",
"unknown": "Unknown",
"name": "Name",
"ip": "IP",
"status": "Status",
"id": "ID",
"failedToLoadData": "Failed to load network topology data",
"failedToAddNode": "Failed to add node",
"sourceDifferentFromTarget": "Source and target must be different",
"exportJSON": "Export JSON",
"importJSON": "Import JSON",
"searchHost": "Search hosts...",
"noHostFound": "No hosts found",
"searchGroup": "Search groups...",
"noGroupFound": "No groups found",
"searchNode": "Search nodes...",
"noNodeFound": "No nodes found",
"terminal": "Terminal",
"fileManager": "File Manager",
"tunnel": "Tunnel",
"docker": "Docker",
"serverStats": "Server Stats"
},
"rbac": {
"shareHost": "Share Host",
@@ -2356,9 +2577,15 @@
"notEnabled": "Docker is not enabled for this host",
"validating": "Validating Docker...",
"connectingToHost": "Connecting to host...",
"connecting": "Connecting...",
"error": "Error",
"errorCode": "Error code: {{code}}",
"version": "Docker {{version}}",
"connectionFailed": "Failed to connect to Docker",
"totpVerificationFailed": "TOTP verification failed",
"warpgateVerificationFailed": "Warpgate verification failed",
"verificationCodePrompt": "Enter verification code",
"loadingContainers": "Loading containers...",
"containerStarted": "Container {{name}} started",
"failedToStartContainer": "Failed to start container {{name}}",
"containerStopped": "Container {{name}} stopped",
@@ -2422,6 +2649,7 @@
"authenticationRequired": "Authentication required",
"verificationCodePrompt": "Enter verification code",
"totpVerificationFailed": "TOTP verification failed. Please try again.",
"warpgateVerificationFailed": "Warpgate authentication failed. Please try again.",
"connectedTo": "Connected to {{containerName}}",
"disconnected": "Disconnected",
"consoleError": "Console error",
@@ -2443,7 +2671,51 @@
"logs": "Logs",
"stats": "Stats",
"consoleTab": "Console",
"startContainerToAccess": "Start the container to access the console"
"startContainerToAccess": "Start the container to access the console",
"log": {
"connecting": "Connecting to Docker host...",
"authStarted": "Resolving authentication credentials...",
"totpRequired": "TOTP verification required",
"warpgateRequired": "Warpgate authentication required",
"sessionCreated": "Docker SSH session established",
"sessionReady": "Ready for Docker operations",
"error": "Docker connection failed: {{error}}"
}
},
"stats": {
"log": {
"connecting": "Starting metrics collection...",
"existingSession": "Using existing metrics session",
"totpVerifying": "TOTP verification required",
"sessionEstablished": "Metrics session established",
"collecting": "Collecting server metrics",
"heartbeat": "Keeping connection alive",
"stopped": "Metrics collection stopped",
"error": "Metrics collection failed: {{error}}"
}
},
"tunnel": {
"log": {
"connecting": "Establishing tunnel connection...",
"sourceConnecting": "Connecting to source host {{host}}...",
"sourceConnected": "Connected to source host",
"endpointResolving": "Resolving endpoint host {{host}}...",
"endpointResolved": "Endpoint host resolved",
"forwarding": "Setting up port forwarding {{localPort}} → {{remotePort}}...",
"connected": "Tunnel established successfully",
"retrying": "Connection failed, retrying in {{countdown}}s (attempt {{attempt}}/{{max}})...",
"retryExhausted": "Max retry attempts reached",
"error": "Tunnel connection failed: {{error}}"
}
},
"sftp": {
"log": {
"connecting": "Connecting to SFTP server...",
"jumpHost": "Connecting via jump host {{host}}...",
"connected": "SFTP connection established",
"authFailed": "Authentication failed",
"error": "SFTP operation failed: {{error}}"
}
},
"theme": {
"switchToLight": "Switch to Light",