Compare commits

..

39 Commits

Author SHA1 Message Date
Karmaa 4dc94c90b2 Merge pull request #57 from LukeGus/dev-1.01
Dev 1.01
2025-07-31 22:38:27 -05:00
LukeGus eb8b465c92 Merge remote-tracking branch 'origin/main' into dev-1.01
# Conflicts:
#	src/apps/SSH/Terminal/SSHTerminal.tsx
2025-07-31 22:30:51 -05:00
Karmaa 3559a6fd87 Update docker-image.yml 2025-07-31 19:13:02 -05:00
LukeGus b70fa4cd52 Fix terminal and tunnel timeout connection errors 2025-07-31 18:54:10 -05:00
Karmaa 43b833c4ae Update SSHTerminal.tsx 2025-07-31 16:19:18 -05:00
Karmaa 38560b8178 Update ssh.ts 2025-07-31 16:18:44 -05:00
Karmaa 4a33024b7f Update SSHTerminal.tsx 2025-07-31 15:24:42 -05:00
Karmaa 38f836b94f Update ssh.ts 2025-07-31 15:20:27 -05:00
Karmaa 4b53139c20 Update ssh.ts to fix 60 second disconnect 2025-07-31 14:55:40 -05:00
Karmaa e0a86b9e18 Update README.md 2025-07-29 01:09:08 -05:00
LukeGus b58b6e729c Update routes and homepage auth. 2025-07-28 22:47:52 -05:00
LukeGus 6eff103cae Migrate docs to new repo 2025-07-28 20:53:48 -05:00
LukeGus 137f8ef472 Update read me 2025-07-28 17:22:49 -05:00
LukeGus 0ca1392670 Update read me 2025-07-28 17:09:28 -05:00
LukeGus c2ed2729be Update read me, license, tools, and auth loading 2025-07-28 17:06:30 -05:00
LukeGus a92ed01129 Fix routing 2025-07-28 15:50:50 -05:00
LukeGus 1cab763bee Fix build error 2025-07-28 15:34:13 -05:00
LukeGus 30bcdd440e Clean up code 2025-07-28 14:56:43 -05:00
LukeGus bc4c2dc7e6 Finalized ssh config editor 2025-07-28 14:23:28 -05:00
LukeGus 962f0064fe Update backend connectivity for SSH 2025-07-27 20:36:54 -05:00
LukeGus eb3008d097 Update backend connectivity 2025-07-27 19:41:24 -05:00
LukeGus 64ac578d61 Fix build errors 2025-07-27 18:59:44 -05:00
LukeGus 50de22618a Fix build errors 2025-07-27 18:54:01 -05:00
LukeGus 493514d7fa Fix build errors 2025-07-27 18:48:26 -05:00
LukeGus 27495aa4ed Fix build errors 2025-07-27 18:41:41 -05:00
LukeGus babe105b2e Fix build errors 2025-07-27 18:12:55 -05:00
LukeGus ec2a1f4215 Fix build errors 2025-07-27 18:04:49 -05:00
LukeGus 6ed822c8b2 Updated building backend, improved oruitng, indivudal ssh tunnel control. 2025-07-27 18:01:44 -05:00
LukeGus 634e625eef Individual SSH Tunnel control 2025-07-27 16:04:32 -05:00
LukeGus 32945adcd9 Ssh tunnel backup before forwardIn rewrite 2025-07-27 14:21:15 -05:00
LukeGus 5e88f8496e Update ssh tunnel to new system 2025-07-26 23:01:45 -05:00
LukeGus abeba66432 Fixes 2025-07-26 21:33:39 -05:00
LukeGus 073e9a969b Update ssh sidebar to follow new scheme 2025-07-26 20:07:25 -05:00
LukeGus 2e62dee798 Started config editor, migrated to one ssh manager for adding hosts. 2025-07-26 15:42:15 -05:00
LukeGus 608111c37b Finalized ssh tunnels, updatetd database schemas, started on config editor. 2025-07-23 00:36:22 -05:00
LukeGus 547701378f Finalized ssh tunnels, updatetd database schemas, started on config editor. 2025-07-21 01:25:38 -05:00
LukeGus cfaa04e42c Added tools (run multi cmds), fixed UI scrolling, added SSH algo's and key types. 2025-07-19 02:27:20 -05:00
LukeGus 49a4d20740 Completed intial SSH section with user/ssh backend 2025-07-18 23:39:23 -05:00
LukeGus 00a827df09 Initial dev-1.0 commit for TS and Shadcn migration 2025-07-17 01:13:30 -05:00
1012 changed files with 14683 additions and 413127 deletions
-21
View File
@@ -1,21 +0,0 @@
{
"extends": ["@commitlint/config-conventional"],
"rules": {
"type-enum": [
2,
"always",
[
"feat",
"fix",
"docs",
"style",
"refactor",
"perf",
"test",
"chore",
"revert"
]
],
"subject-case": [0]
}
}
-92
View File
@@ -1,92 +0,0 @@
node_modules
npm-debug.log*
yarn-debug.log*
yarn-error.log*
dist
build
.next
.nuxt
.env.local
.env.development.local
.env.test.local
.env.production.local
.vscode
.idea
*.swp
*.swo
*~
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db
.git
.gitignore
README.md
CONTRIBUTING.md
LICENSE
repo-images/
uploads/
electron/
electron-builder.json
*.log
*.tmp
*.temp
logs
*.log
pids
*.pid
*.seed
*.pid.lock
coverage
.nyc_output
jspm_packages/
.npm
.eslintcache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/
.node_repl_history
*.tgz
.yarn-integrity
.cache
.parcel-cache
.next
.nuxt
.vuepress/dist
.serverless
.fusebox/
.dynamodb/
.tern-port
-14
View File
@@ -1,14 +0,0 @@
root = true
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
[*.{js,cjs,mjs,jsx,ts,tsx,json,css,scss,md,yml,yaml}]
indent_style = space
indent_size = 2
[*.md]
trim_trailing_whitespace = false
-34
View File
@@ -1,34 +0,0 @@
* text=auto eol=lf
*.js text eol=lf
*.cjs text eol=lf
*.mjs text eol=lf
*.jsx text eol=lf
*.ts text eol=lf
*.tsx text eol=lf
*.json text eol=lf
*.css text eol=lf
*.scss text eol=lf
*.html text eol=lf
*.md text eol=lf
*.yaml text eol=lf
*.yml text eol=lf
*.sh text eol=lf
*.bash text eol=lf
*.bat text eol=crlf
*.cmd text eol=crlf
*.ps1 text eol=crlf
*.png binary
*.jpg binary
*.jpeg binary
*.gif binary
*.ico binary
*.svg binary
*.woff binary
*.woff2 binary
*.ttf binary
*.eot binary
*.icns binary
+1
View File
@@ -0,0 +1 @@
github: [LukeGus]
-8
View File
@@ -1,8 +0,0 @@
blank_issues_enabled: false
contact_links:
- name: Support Center
url: https://github.com/Termix-SSH/Support/issues
about: Report any feature requests or bugs in the support center
- name: Discord
url: https://discord.gg/jVQGdvHDrf
about: Official Termix Discord server for general discussion (not recommended for support)
-83
View File
@@ -1,83 +0,0 @@
version: 2
updates:
# npm dependencies (single root package.json, no workspaces)
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "weekly"
day: "monday"
open-pull-requests-limit: 15
labels:
- "dependencies"
- "npm"
commit-message:
prefix: "chore"
prefix-development: "chore"
include: "scope"
groups:
dev-patch-updates:
dependency-type: "development"
update-types:
- "patch"
dev-minor-updates:
dependency-type: "development"
update-types:
- "minor"
prod-patch-updates:
dependency-type: "production"
update-types:
- "patch"
prod-minor-updates:
dependency-type: "production"
update-types:
- "minor"
# Major bumps grouped so they land as a single reviewable PR instead of
# one-per-package noise. These often need manual follow-up (Electron,
# React, Vite, Tailwind, Express 5, etc.).
major-updates:
update-types:
- "major"
# Docker base images (docker/Dockerfile + docker-compose / compose-dev)
- package-ecosystem: "docker"
directory: "/docker"
schedule:
interval: "weekly"
day: "monday"
open-pull-requests-limit: 10
labels:
- "dependencies"
- "docker"
commit-message:
prefix: "chore"
include: "scope"
groups:
docker-patch-updates:
update-types:
- "patch"
docker-minor-updates:
update-types:
- "minor"
docker-major-updates:
update-types:
- "major"
# GitHub Actions used across the workflows in .github/workflows
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
day: "monday"
open-pull-requests-limit: 10
labels:
- "dependencies"
- "github-actions"
commit-message:
prefix: "ci"
include: "scope"
groups:
github-actions:
update-types:
- "patch"
- "minor"
- "major"
-1
View File
@@ -1 +0,0 @@
custom: https://donate.termix.site/
-32
View File
@@ -1,32 +0,0 @@
# Overview
_Short summary of what this PR does_
- [ ] Added: ...
- [ ] Updated: ...
- [ ] Removed: ...
- [ ] Fixed: ...
# Changes Made
_Detailed explanation of changes (if needed)_
- ...
# Related Issues
_Link any issues this PR addresses_
- Closes #ISSUE_NUMBER
- Related to #ISSUE_NUMBER
# Screenshots / Demos
_(Optional: add before/after screenshots, GIFs, or console output)_
# Checklist
- [ ] Code follows project style guidelines
- [ ] Supports mobile and desktop UI/app (if applicable)
- [ ] I have read [Contributing.md](https://github.com/Termix-SSH/Termix/blob/main/CONTRIBUTING.md)
- [ ] This is not a translation request. See [docs](https://docs.termix.site/translations)
-157
View File
@@ -1,157 +0,0 @@
name: Retarget and Merge Dependabot PRs
on:
schedule:
- cron: "0 6 * * *"
workflow_dispatch:
permissions:
contents: write
pull-requests: write
jobs:
retarget-and-merge:
runs-on: blacksmith-2vcpu-ubuntu-2404
steps:
- name: Checkout repository
uses: actions/checkout@v7
with:
fetch-depth: 1
- name: Resolve newest dev branch
id: dev
env:
GH_TOKEN: ${{ secrets.GHCR_TOKEN }}
run: |
REFS=$(gh api "repos/${{ github.repository }}/branches" --paginate -q '.[].name')
# The helper exits non-zero when no dev-X.Y.Z branch exists; treat that
# as "nothing to do" rather than a workflow failure.
if DEV_BRANCH=$(printf '%s\n' "$REFS" | node scripts/latest-dev-branch.cjs 2>/dev/null); then
echo "Newest dev branch: $DEV_BRANCH"
echo "branch=$DEV_BRANCH" >> "$GITHUB_OUTPUT"
else
echo "No dev-X.Y.Z branch open; nothing to retarget."
echo "branch=" >> "$GITHUB_OUTPUT"
fi
- name: Retarget and merge Dependabot PRs
if: ${{ steps.dev.outputs.branch != '' }}
env:
GH_TOKEN: ${{ secrets.GHCR_TOKEN }}
DEV_BRANCH: ${{ steps.dev.outputs.branch }}
REPO: ${{ github.repository }}
run: |
set -uo pipefail
CONFLICT_LABEL="dependabot-rebase-requested"
# Ensure the bookkeeping label exists (no-op if it already does).
gh label create "$CONFLICT_LABEL" --repo "$REPO" \
--color "D93F0B" --description "Retarget workflow asked Dependabot to rebase a conflicting PR" \
2>/dev/null || true
# True if the PR already carries the conflict label.
has_conflict_label() {
gh pr view "$1" --repo "$REPO" --json labels \
-q '.labels[].name' | grep -qx "$CONFLICT_LABEL"
}
# Wait until GitHub has a definite mergeable verdict for a PR (it
# returns UNKNOWN while recomputing after a base change or a push).
# Echoes "<mergeable> <mergeStateStatus>".
wait_for_verdict() {
local pr="$1" mergeable state
for _ in $(seq 1 30); do
read -r mergeable state < <(gh pr view "$pr" --repo "$REPO" \
--json mergeable,mergeStateStatus \
-q '.mergeable + " " + .mergeStateStatus')
if [ "$mergeable" != "UNKNOWN" ] && [ "$state" != "UNKNOWN" ]; then
echo "$mergeable $state"
return 0
fi
sleep 20
done
echo "$mergeable $state"
}
# Phase 1: retarget every open Dependabot PR from main onto the dev
# branch. This kicks off a Dependabot rebase for each.
PR_NUMBERS=$(gh pr list --repo "$REPO" \
--author "app/dependabot" \
--base main \
--state open \
--json number -q '.[].number')
# Pick up PRs already sitting on the dev branch from a previous run too.
PR_NUMBERS="$PR_NUMBERS $(gh pr list --repo "$REPO" \
--author "app/dependabot" \
--base "$DEV_BRANCH" \
--state open \
--json number -q '.[].number')"
PR_NUMBERS=$(printf '%s\n' $PR_NUMBERS | sort -un)
if [ -z "$PR_NUMBERS" ]; then
echo "No open Dependabot PRs to process."
exit 0
fi
for PR in $PR_NUMBERS; do
BASE=$(gh pr view "$PR" --repo "$REPO" --json baseRefName -q .baseRefName)
if [ "$BASE" != "$DEV_BRANCH" ]; then
echo "Retargeting PR #$PR ($BASE -> $DEV_BRANCH)"
gh pr edit "$PR" --repo "$REPO" --base "$DEV_BRANCH"
fi
done
# Phase 2: merge one at a time. Each merge can make the remaining npm
# PRs stale, so re-check immediately before merging and rebase stragglers.
for PR in $PR_NUMBERS; do
echo "::group::PR #$PR"
read -r MERGEABLE STATE < <(wait_for_verdict "$PR")
echo " mergeable=$MERGEABLE mergeStateStatus=$STATE"
# BEHIND = clean but needs the latest base; ask Dependabot to rebase
# and skip for now (next run merges it once it is up to date).
if [ "$STATE" = "BEHIND" ]; then
echo " PR #$PR is behind $DEV_BRANCH; asking Dependabot to rebase."
gh pr comment "$PR" --repo "$REPO" --body "@dependabot rebase"
echo "::endgroup::"
continue
fi
# DIRTY / CONFLICTING = a real conflict. Try a rebase once (label it so
# we can tell next time); if it is STILL conflicting on a later run
# despite already being labelled, the rebase failed for good - close it
# so Dependabot reopens a fresh PR against the current dev branch.
if [ "$MERGEABLE" = "CONFLICTING" ] || [ "$STATE" = "DIRTY" ]; then
if has_conflict_label "$PR"; then
echo " PR #$PR still conflicts after a prior rebase request; closing so Dependabot reopens it fresh."
gh pr close "$PR" --repo "$REPO" --delete-branch \
--comment "Closing: this PR still conflicts with $DEV_BRANCH after a rebase attempt (its changes are likely already merged). Dependabot will reopen a fresh PR computed against the current $DEV_BRANCH."
else
echo " PR #$PR conflicts with $DEV_BRANCH; requesting a rebase and labelling it."
gh pr edit "$PR" --repo "$REPO" --add-label "$CONFLICT_LABEL"
gh pr comment "$PR" --repo "$REPO" --body "@dependabot rebase"
fi
echo "::endgroup::"
continue
fi
# A clean PR that was previously flagged has recovered - drop the label.
if has_conflict_label "$PR"; then
gh pr edit "$PR" --repo "$REPO" --remove-label "$CONFLICT_LABEL" || true
fi
echo " Squash-merging PR #$PR"
if gh pr merge "$PR" --repo "$REPO" --squash --admin; then
echo " Merged PR #$PR"
# Give GitHub a moment to mark the now-stale siblings BEHIND.
sleep 15
else
echo " Could not merge PR #$PR now; it will be retried next run."
fi
echo "::endgroup::"
done
+116
View File
@@ -0,0 +1,116 @@
name: Build and Push Docker Image
on:
push:
branches:
- development
paths-ignore:
- '**.md'
- '.gitignore'
workflow_dispatch:
inputs:
tag_name:
description: "Custom tag name for the Docker image"
required: false
default: ""
jobs:
build:
runs-on: [self-hosted, linux]
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
with:
platforms: arm64
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
with:
platforms: linux/amd64,linux/arm64
driver-opts: |
image=moby/buildkit:master
network=host
- name: Cache npm dependencies
uses: actions/cache@v3
with:
path: |
~/.npm
node_modules
*/*/node_modules
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
- name: Cache Docker layers
uses: actions/cache@v3
with:
path: /tmp/.buildx-cache
key: ${{ runner.os }}-buildx-${{ github.ref_name }}-${{ hashFiles('docker/Dockerfile') }}
restore-keys: |
${{ runner.os }}-buildx-${{ github.ref_name }}-
${{ runner.os }}-buildx-
- name: Login to Docker Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Determine Docker image tag
run: |
echo "REPO_OWNER=$(echo ${{ github.repository_owner }} | tr '[:upper:]' '[:lower:]')" >> $GITHUB_ENV
if [ "${{ github.event.inputs.tag_name }}" != "" ]; then
IMAGE_TAG="${{ github.event.inputs.tag_name }}"
elif [ "${{ github.ref }}" == "refs/heads/main" ]; then
IMAGE_TAG="latest"
elif [ "${{ github.ref }}" == "refs/heads/development" ]; then
IMAGE_TAG="development-latest"
else
IMAGE_TAG="${{ github.ref_name }}-development-latest"
fi
echo "IMAGE_TAG=$IMAGE_TAG" >> $GITHUB_ENV
- name: Build and Push Multi-Arch Docker Image
uses: docker/build-push-action@v5
with:
context: .
file: ./docker/Dockerfile
push: true
platforms: linux/amd64,linux/arm64
tags: ghcr.io/${{ env.REPO_OWNER }}/termix:${{ env.IMAGE_TAG }}
labels: |
org.opencontainers.image.source=https://github.com/${{ github.repository }}
org.opencontainers.image.revision=${{ github.sha }}
cache-from: type=local,src=/tmp/.buildx-cache
cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max
build-args: |
BUILDKIT_INLINE_CACHE=1
BUILDKIT_CONTEXT_KEEP_GIT_DIR=1
outputs: type=registry,compression=zstd,compression-level=19
- name: Move cache
run: |
rm -rf /tmp/.buildx-cache
mv /tmp/.buildx-cache-new /tmp/.buildx-cache
- name: Delete all untagged image versions
if: success()
uses: quartx-analytics/ghcr-cleaner@v1
with:
owner-type: user
token: ${{ secrets.GHCR_TOKEN }}
repository-owner: ${{ github.repository_owner }}
delete-untagged: true
- name: Cleanup Docker Images Locally
if: always()
run: |
docker image prune -af
docker system prune -af --volumes
-124
View File
@@ -1,124 +0,0 @@
name: Build and Push Docker Image
on:
workflow_dispatch:
inputs:
version:
description: "Version to build (e.g., 1.8.0)"
required: true
build_type:
description: "Build type"
required: true
default: "Development"
type: choice
options:
- Development
- Production
source_ref:
description: "Git ref/SHA to build (defaults to the workflow ref)"
required: false
default: ""
workflow_call:
inputs:
version:
description: "Version to build (e.g., 1.8.0)"
required: true
type: string
build_type:
description: "Build type (Development or Production)"
required: true
type: string
dry_run:
description: "Build the image but do not push to any registry"
required: false
type: boolean
default: false
source_ref:
description: "Git ref/SHA to build"
required: false
type: string
default: ""
jobs:
build:
runs-on: blacksmith-8vcpu-ubuntu-2404
steps:
- name: Checkout repository
uses: actions/checkout@v7
with:
ref: ${{ inputs.source_ref || github.ref }}
fetch-depth: 1
- name: Resolve source revision
run: echo "SOURCE_SHA=$(git rev-parse HEAD)" >> "$GITHUB_ENV"
- name: Set up QEMU
uses: docker/setup-qemu-action@v4
with:
platforms: linux/amd64,linux/arm64
- name: Setup Docker Buildx
uses: useblacksmith/setup-docker-builder@v1
- name: Determine tags
id: tags
run: |
VERSION=${{ inputs.version }}
BUILD_TYPE=${{ inputs.build_type }}
TAGS=()
ALL_TAGS=()
if [ "$BUILD_TYPE" = "Production" ]; then
TAGS+=("release-$VERSION" "$VERSION" "latest")
for tag in "${TAGS[@]}"; do
ALL_TAGS+=("ghcr.io/lukegus/termix:$tag")
ALL_TAGS+=("docker.io/bugattiguy527/termix:$tag")
done
else
TAGS+=("dev-$VERSION")
for tag in "${TAGS[@]}"; do
ALL_TAGS+=("ghcr.io/lukegus/termix:$tag")
done
fi
echo "ALL_TAGS=$(IFS=,; echo "${ALL_TAGS[*]}")" >> $GITHUB_ENV
- name: Login to GHCR
if: ${{ !inputs.dry_run }}
uses: docker/login-action@v4
with:
registry: ghcr.io
username: lukegus
password: ${{ secrets.GHCR_TOKEN }}
- name: Login to Docker Hub (prod only)
if: ${{ inputs.build_type == 'Production' && !inputs.dry_run }}
uses: docker/login-action@v4
with:
username: bugattiguy527
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and push multi-arch image
uses: useblacksmith/build-push-action@v2
with:
context: .
file: ./docker/Dockerfile
push: ${{ !inputs.dry_run }}
platforms: linux/amd64,linux/arm64
tags: ${{ env.ALL_TAGS }}
build-args: |
BUILDKIT_CONTEXT_KEEP_GIT_DIR=1
labels: |
org.opencontainers.image.source=https://github.com/${{ github.repository }}
org.opencontainers.image.revision=${{ env.SOURCE_SHA }}
org.opencontainers.image.created=${{ github.run_id }}
cache-from: type=gha
cache-to: type=gha,mode=max
outputs: ${{ inputs.dry_run && 'type=cacheonly' || 'type=registry,compression=zstd' }}
- name: Cleanup Docker
if: always()
run: |
docker image prune -af
docker system prune -af --volumes
File diff suppressed because it is too large Load Diff
-32
View File
@@ -1,32 +0,0 @@
name: Generate OpenAPI Specification
on:
workflow_dispatch:
jobs:
generate-openapi:
name: Generate OpenAPI JSON
runs-on: blacksmith-2vcpu-ubuntu-2404
steps:
- name: Checkout repository
uses: actions/checkout@v7
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version-file: ".nvmrc"
cache: "npm"
- name: Install dependencies
run: npm ci
- name: Generate OpenAPI specification
run: npm run generate:openapi
- name: Upload OpenAPI artifact
uses: actions/upload-artifact@v7
with:
name: openapi-spec
path: openapi.json
retention-days: 90
-37
View File
@@ -1,37 +0,0 @@
name: PR Check
on:
pull_request:
branches: [main, dev-*]
jobs:
lint-and-build:
runs-on: blacksmith-2vcpu-ubuntu-2404
env:
NODE_OPTIONS: "--max-old-space-size=4096"
steps:
- name: Checkout code
uses: actions/checkout@v7
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version-file: ".nvmrc"
cache: "npm"
- name: Install dependencies
run: npm ci
- name: Run ESLint
run: npx eslint .
- name: Run Prettier check
run: npx prettier --check .
- name: Type check
run: npx tsc --noEmit
- name: Build
run: npm run build
-551
View File
@@ -1,551 +0,0 @@
name: Release
on:
workflow_dispatch:
inputs:
mode:
description: "Release mode"
required: true
default: Everything
type: choice
options:
- Everything
- Overwrite release
- Dry run
- Skip submit
permissions:
contents: write
jobs:
prep:
runs-on: blacksmith-2vcpu-ubuntu-2404
outputs:
version: ${{ steps.info.outputs.version }}
release_tag: ${{ steps.info.outputs.release_tag }}
mobile_version: ${{ steps.info.outputs.mobile_version }}
dev_branch: ${{ steps.info.outputs.dev_branch }}
steps:
- name: Guard branch (release modes)
if: ${{ inputs.mode != 'Overwrite release' && !startsWith(github.ref, 'refs/heads/dev-') }}
run: |
echo "This mode must be run from a dev branch (got ${{ github.ref }})."
exit 1
- name: Guard branch (overwrite mode)
if: ${{ inputs.mode == 'Overwrite release' && github.ref != 'refs/heads/main' }}
run: |
echo "Overwrite release must be run from main (got ${{ github.ref }})."
exit 1
- name: Checkout repository
uses: actions/checkout@v7
with:
fetch-depth: 1
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version-file: ".nvmrc"
- name: Resolve versions
id: info
env:
GH_TOKEN: ${{ github.token }}
run: |
if [ "${{ inputs.mode }}" = "Overwrite release" ]; then
DEV_BRANCH=""
VERSION=$(node -p "require('./package.json').version")
else
DEV_BRANCH="${GITHUB_REF#refs/heads/}"
VERSION=$(node scripts/parse-dev-branch.cjs "$DEV_BRANCH")
fi
echo "dev_branch=$DEV_BRANCH" >> "$GITHUB_OUTPUT"
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
echo "release_tag=release-$VERSION-tag" >> "$GITHUB_OUTPUT"
MOBILE_RAW=$(gh release view -R Termix-SSH/Mobile --json tagName -q .tagName)
MOBILE_VERSION=$(echo "$MOBILE_RAW" | sed -E 's/^release-//; s/-tag$//')
if [ -z "$MOBILE_VERSION" ]; then
echo "Failed to resolve the latest Termix-SSH/Mobile release version."
exit 1
fi
echo "mobile_version=$MOBILE_VERSION" >> "$GITHUB_OUTPUT"
- name: Validate release notes
run: |
node scripts/generate-release-body.cjs \
--version "${{ steps.info.outputs.version }}" \
--mobile-version "${{ steps.info.outputs.mobile_version }}" \
--notes RELEASE_NOTES.md > /dev/null
normalize:
needs: [prep]
if: ${{ inputs.mode != 'Overwrite release' }}
runs-on: blacksmith-2vcpu-ubuntu-2404
steps:
- name: Checkout dev branch
uses: actions/checkout@v7
with:
ref: ${{ needs.prep.outputs.dev_branch }}
fetch-depth: 0
token: ${{ secrets.GHCR_TOKEN }}
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version-file: ".nvmrc"
cache: "npm"
- name: Install dependencies
run: npm ci
- name: Lint and format
run: |
npm run lint:fix || true
npm run format
- name: Run unit tests
run: npm run test
- name: Sync version
run: node scripts/sync-version.cjs --version "${{ needs.prep.outputs.version }}"
- name: Commit changes to dev branch
run: |
git config user.name "LukeGus"
git config user.email "bugattiguy527@gmail.com"
if git diff --quiet; then
echo "No lint/format/version changes to commit."
exit 0
fi
if [ "${{ inputs.mode }}" = "Dry run" ]; then
echo "DRY RUN: would commit and push the following changes to ${{ needs.prep.outputs.dev_branch }}:"
git --no-pager diff --stat
exit 0
fi
git add -A
git commit -m "chore: lint, format, and bump version to ${{ needs.prep.outputs.version }}"
git push origin HEAD:"${{ needs.prep.outputs.dev_branch }}"
crowdin:
needs: [prep, normalize]
if: ${{ inputs.mode != 'Dry run' && inputs.mode != 'Overwrite release' }}
runs-on: blacksmith-2vcpu-ubuntu-2404
steps:
- name: Checkout dev branch
uses: actions/checkout@v7
with:
ref: ${{ needs.prep.outputs.dev_branch }}
fetch-depth: 0
token: ${{ secrets.GHCR_TOKEN }}
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version-file: ".nvmrc"
- name: Merge main into dev branch
run: |
git config user.name "LukeGus"
git config user.email "bugattiguy527@gmail.com"
git fetch origin main
git merge origin/main -X ours --no-edit || true
git push origin HEAD:"${{ needs.prep.outputs.dev_branch }}"
- name: Clean up stale Crowdin git integration branch
continue-on-error: true
env:
GH_TOKEN: ${{ secrets.GHCR_TOKEN }}
run: |
PR_NUMBER=$(gh pr list --repo ${{ github.repository }} --head i18n_translate --state open --json number -q '.[0].number' || true)
if [ -n "$PR_NUMBER" ]; then
gh pr close "$PR_NUMBER" --repo ${{ github.repository }} --delete-branch || true
fi
git push origin --delete i18n_translate || true
- name: Upload sources to Crowdin
uses: crowdin/github-action@v2
with:
upload_sources: true
upload_translations: false
download_translations: false
create_pull_request: false
push_translations: false
token: ${{ secrets.CROWDIN_API_KEY }}
project_id: "858252"
env:
CROWDIN_API_TOKEN: ${{ secrets.CROWDIN_API_KEY }}
- name: Machine pre-translate untranslated strings
env:
CROWDIN_API_KEY: ${{ secrets.CROWDIN_API_KEY }}
run: node scripts/crowdin-pretranslate.cjs
- name: Download translations from Crowdin
uses: crowdin/github-action@v2
with:
upload_sources: false
upload_translations: false
download_translations: true
create_pull_request: false
push_translations: false
token: ${{ secrets.CROWDIN_API_KEY }}
project_id: "858252"
env:
CROWDIN_API_TOKEN: ${{ secrets.CROWDIN_API_KEY }}
- name: Commit translations to dev branch
run: |
git config user.name "LukeGus"
git config user.email "bugattiguy527@gmail.com"
git add src/ui/locales/translated
if git diff --cached --quiet; then
echo "No translation changes to commit."
exit 0
fi
git commit -m "chore: sync Crowdin translations for ${{ needs.prep.outputs.version }}"
git push origin HEAD:"${{ needs.prep.outputs.dev_branch }}"
merge-to-main:
needs: [prep, normalize, crowdin]
if: ${{ always() && needs.prep.result == 'success' && (needs.normalize.result == 'success' || needs.normalize.result == 'skipped') && (needs.crowdin.result == 'success' || needs.crowdin.result == 'skipped') }}
runs-on: blacksmith-2vcpu-ubuntu-2404
outputs:
main_sha: ${{ steps.merge.outputs.main_sha }}
build_ref: ${{ steps.merge.outputs.build_ref }}
steps:
- name: Checkout repository
uses: actions/checkout@v7
with:
fetch-depth: 1
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version-file: ".nvmrc"
- name: Generate PR body
id: body
run: |
node scripts/generate-release-body.cjs \
--version "${{ needs.prep.outputs.version }}" \
--mobile-version "${{ needs.prep.outputs.mobile_version }}" \
--notes RELEASE_NOTES.md > PR_BODY.md
- name: Open and squash-merge PR to main
id: merge
env:
GH_TOKEN: ${{ secrets.GHCR_TOKEN }}
run: |
DEV_BRANCH="${{ needs.prep.outputs.dev_branch }}"
TITLE="release-${{ needs.prep.outputs.version }}"
if [ "${{ inputs.mode }}" = "Overwrite release" ]; then
echo "OVERWRITE: no merge; building from main as-is."
echo "build_ref=main" >> "$GITHUB_OUTPUT"
echo "main_sha=$(gh api repos/${{ github.repository }}/commits/main -q .sha)" >> "$GITHUB_OUTPUT"
exit 0
fi
if [ "${{ inputs.mode }}" = "Dry run" ]; then
echo "DRY RUN: would open and squash-merge a PR from $DEV_BRANCH into main."
echo "DRY RUN: downstream jobs will build from $DEV_BRANCH instead of main."
echo "build_ref=$DEV_BRANCH" >> "$GITHUB_OUTPUT"
echo "main_sha=" >> "$GITHUB_OUTPUT"
exit 0
fi
PR_NUMBER=$(gh pr list --repo ${{ github.repository }} --head "$DEV_BRANCH" --base main --state open --json number -q '.[0].number' || true)
if [ -z "$PR_NUMBER" ]; then
PR_NUMBER=$(gh pr create --repo ${{ github.repository }} \
--base main --head "$DEV_BRANCH" \
--title "$TITLE" --body-file PR_BODY.md \
| grep -oE '[0-9]+$')
fi
gh pr merge "$PR_NUMBER" --repo ${{ github.repository }} --squash --admin
STATE=$(gh pr view "$PR_NUMBER" --repo ${{ github.repository }} --json state -q .state)
if [ "$STATE" != "MERGED" ]; then
echo "PR #$PR_NUMBER did not merge (state: $STATE)."
exit 1
fi
MAIN_SHA=$(gh api repos/${{ github.repository }}/commits/main -q .sha)
echo "main_sha=$MAIN_SHA" >> "$GITHUB_OUTPUT"
echo "build_ref=$MAIN_SHA" >> "$GITHUB_OUTPUT"
docker:
needs: [prep, merge-to-main]
uses: ./.github/workflows/docker.yml
with:
version: ${{ needs.prep.outputs.version }}
build_type: Production
dry_run: ${{ inputs.mode == 'Dry run' }}
source_ref: ${{ needs.merge-to-main.outputs.build_ref }}
secrets: inherit
create-release:
needs: [prep, merge-to-main, docker]
if: ${{ inputs.mode != 'Dry run' }}
runs-on: blacksmith-2vcpu-ubuntu-2404
permissions:
contents: write
steps:
- name: Checkout main
uses: actions/checkout@v7
with:
ref: main
fetch-depth: 1
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version-file: ".nvmrc"
- name: Clear existing release artifacts (overwrite mode)
if: ${{ inputs.mode == 'Overwrite release' }}
env:
GH_TOKEN: ${{ secrets.GHCR_TOKEN }}
run: |
TAG="${{ needs.prep.outputs.release_tag }}"
if ! gh release view "$TAG" --repo ${{ github.repository }} >/dev/null 2>&1; then
echo "Overwrite release: no existing release $TAG to overwrite."
exit 1
fi
echo "Clearing existing assets from $TAG..."
gh release view "$TAG" --repo ${{ github.repository }} --json assets -q '.assets[].name' | while read -r ASSET; do
[ -n "$ASSET" ] && gh release delete-asset "$TAG" "$ASSET" --repo ${{ github.repository }} --yes || true
done
- name: Generate release body
if: ${{ inputs.mode != 'Overwrite release' }}
run: |
node scripts/generate-release-body.cjs \
--version "${{ needs.prep.outputs.version }}" \
--mobile-version "${{ needs.prep.outputs.mobile_version }}" \
--notes RELEASE_NOTES.md > RELEASE_BODY.md
- name: Create or update GitHub release
if: ${{ inputs.mode != 'Overwrite release' }}
env:
GH_TOKEN: ${{ secrets.GHCR_TOKEN }}
run: |
TAG="${{ needs.prep.outputs.release_tag }}"
TITLE="release-${{ needs.prep.outputs.version }}"
if gh release view "$TAG" --repo ${{ github.repository }} >/dev/null 2>&1; then
gh release edit "$TAG" --repo ${{ github.repository }} --title "$TITLE" --notes-file RELEASE_BODY.md
else
gh release create "$TAG" --repo ${{ github.repository }} --title "$TITLE" --notes-file RELEASE_BODY.md --target "${{ needs.merge-to-main.outputs.main_sha }}"
fi
electron-release:
needs: [prep, merge-to-main, create-release]
if: ${{ always() && needs.merge-to-main.result == 'success' && (needs.create-release.result == 'success' || needs.create-release.result == 'skipped') }}
uses: ./.github/workflows/electron.yml
with:
build_type: all
artifact_destination: ${{ inputs.mode == 'Dry run' && 'file' || 'release' }}
release_tag: ${{ needs.prep.outputs.release_tag }}
source_ref: ${{ needs.merge-to-main.outputs.build_ref }}
secrets: inherit
electron-submit:
needs: [prep, merge-to-main, electron-release]
if: ${{ inputs.mode != 'Dry run' && inputs.mode != 'Skip submit' }}
uses: ./.github/workflows/electron.yml
with:
build_type: all
artifact_destination: submit
source_ref: ${{ needs.merge-to-main.outputs.build_ref }}
secrets: inherit
cask-commit-back:
needs: [prep, electron-release]
if: ${{ inputs.mode != 'Dry run' }}
runs-on: blacksmith-2vcpu-ubuntu-2404
permissions:
contents: write
steps:
- name: Checkout main
uses: actions/checkout@v7
with:
ref: main
fetch-depth: 1
token: ${{ secrets.GHCR_TOKEN }}
- name: Bump and commit Homebrew cask
env:
VERSION: ${{ needs.prep.outputs.version }}
DMG_SHA256: ${{ needs.electron-release.outputs.macos_universal_dmg_sha256 }}
run: |
if [ -z "$DMG_SHA256" ]; then
echo "No universal DMG checksum available (macOS build unsigned or skipped); leaving cask unchanged."
exit 0
fi
sed -i "s|version \".*\"|version \"$VERSION\"|g" Casks/termix.rb
sed -i "s|sha256 \".*\"|sha256 \"$DMG_SHA256\"|g" Casks/termix.rb
if git diff --quiet Casks/termix.rb; then
echo "Cask already up to date."
exit 0
fi
git config user.name "LukeGus"
git config user.email "bugattiguy527@gmail.com"
git add Casks/termix.rb
git stash
git pull --rebase origin main
git stash pop
git commit -m "chore: bump Homebrew cask to $VERSION"
git push origin HEAD:main
docs:
needs: [prep, merge-to-main]
if: ${{ always() && needs.merge-to-main.result == 'success' && inputs.mode != 'Overwrite release' }}
runs-on: blacksmith-2vcpu-ubuntu-2404
steps:
- name: Checkout Termix
uses: actions/checkout@v7
with:
ref: ${{ needs.merge-to-main.outputs.build_ref }}
fetch-depth: 1
path: termix
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version-file: "termix/.nvmrc"
cache: "npm"
cache-dependency-path: termix/package-lock.json
- name: Generate OpenAPI spec
working-directory: termix
run: |
npm ci
npm run generate:openapi
- name: Checkout Docs repository
uses: actions/checkout@v7
with:
repository: Termix-SSH/Docs
ref: main
fetch-depth: 0
token: ${{ secrets.GHCR_TOKEN }}
path: docs-repo
- name: Create docs release branch
working-directory: docs-repo
run: git checkout -B "dev-${{ needs.prep.outputs.version }}"
- name: Overwrite OpenAPI spec and regenerate API docs
working-directory: docs-repo
run: |
cp ../termix/openapi.json static/openapi.json
npm ci
npm run docusaurus gen-api-docs termix
- name: Commit and push docs branch
working-directory: docs-repo
run: |
git config user.name "LukeGus"
git config user.email "bugattiguy527@gmail.com"
if git diff --quiet; then
echo "No docs changes to commit."
exit 0
fi
if [ "${{ inputs.mode }}" = "Dry run" ]; then
echo "DRY RUN: would commit and push the following docs changes to dev-${{ needs.prep.outputs.version }}:"
git --no-pager diff --stat
exit 0
fi
git add -A
git commit -m "feat: update API docs for ${{ needs.prep.outputs.version }}"
git push --force origin "dev-${{ needs.prep.outputs.version }}"
- name: Open and squash-merge docs PR
if: ${{ inputs.mode != 'Dry run' }}
working-directory: docs-repo
env:
GH_TOKEN: ${{ secrets.GHCR_TOKEN }}
run: |
BRANCH="dev-${{ needs.prep.outputs.version }}"
if ! git ls-remote --exit-code origin "refs/heads/$BRANCH" >/dev/null 2>&1; then
echo "No docs branch pushed (nothing changed); skipping PR."
exit 0
fi
PR_NUMBER=$(gh pr list --repo Termix-SSH/Docs --head "$BRANCH" --base main --state open --json number -q '.[0].number' || true)
if [ -z "$PR_NUMBER" ]; then
PR_URL=$(gh pr create --repo Termix-SSH/Docs \
--base main --head "$BRANCH" \
--title "release-${{ needs.prep.outputs.version }}" \
--body "API docs for ${{ needs.prep.outputs.version }}")
PR_NUMBER=$(echo "$PR_URL" | grep -oE '[0-9]+$')
fi
if [ -z "$PR_NUMBER" ]; then
echo "Failed to find or create a PR for $BRANCH."
exit 1
fi
gh pr merge "$PR_NUMBER" --repo Termix-SSH/Docs --squash --admin
publish-youtube:
needs: [prep, electron-release]
if: ${{ always() && inputs.mode != 'Dry run' && inputs.mode != 'Overwrite release' && needs.electron-release.result == 'success' }}
runs-on: blacksmith-2vcpu-ubuntu-2404
steps:
- name: Checkout main
uses: actions/checkout@v7
with:
ref: main
fetch-depth: 1
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version-file: ".nvmrc"
- name: Set release video to public
env:
YOUTUBE_CLIENT_ID: ${{ secrets.YOUTUBE_CLIENT_ID }}
YOUTUBE_CLIENT_SECRET: ${{ secrets.YOUTUBE_CLIENT_SECRET }}
YOUTUBE_REFRESH_TOKEN: ${{ secrets.YOUTUBE_REFRESH_TOKEN }}
run: node scripts/publish-youtube.cjs
cleanup:
needs:
[
prep,
merge-to-main,
electron-release,
cask-commit-back,
docs,
publish-youtube,
]
if: ${{ always() && (inputs.mode == 'Everything' || inputs.mode == 'Skip submit') && needs.merge-to-main.result == 'success' && needs.electron-release.result == 'success' && needs.cask-commit-back.result == 'success' && needs.docs.result == 'success' && needs.publish-youtube.result == 'success' }}
runs-on: blacksmith-2vcpu-ubuntu-2404
steps:
- name: Delete dev branch in Termix
env:
GH_TOKEN: ${{ secrets.GHCR_TOKEN }}
run: |
git push https://x-access-token:${{ secrets.GHCR_TOKEN }}@github.com/${{ github.repository }}.git \
--delete "${{ needs.prep.outputs.dev_branch }}" || true
- name: Delete dev branch in Docs
env:
GH_TOKEN: ${{ secrets.GHCR_TOKEN }}
run: |
git push https://x-access-token:${{ secrets.GHCR_TOKEN }}@github.com/Termix-SSH/Docs.git \
--delete "dev-${{ needs.prep.outputs.version }}" || true
+4 -16
View File
@@ -1,3 +1,4 @@
# Logs
logs
*.log
npm-debug.log*
@@ -7,13 +8,13 @@ pnpm-debug.log*
lerna-debug.log*
node_modules
src/mcp-server/node_modules
dist
dist-ssr
coverage
*.local
.vscode/
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
@@ -21,17 +22,4 @@ coverage
*.njsproj
*.sln
*.sw?
/db/
/release/
/.claude/
/ssl/
/uploads/
/nul
.env
electron/build-info.cjs
/.mcp.json
/CLAUDE.md
/old_db/
/scripts/fix-bugs.mjs
/scripts/fix-features.mjs
-1
View File
@@ -1 +0,0 @@
npx --no -- commitlint --edit $1
-1
View File
@@ -1 +0,0 @@
npx lint-staged
-1
View File
@@ -1 +0,0 @@
legacy-peer-deps=true
-1
View File
@@ -1 +0,0 @@
24
-19
View File
@@ -1,19 +0,0 @@
build
coverage
dist
dist-ssr
release
node_modules
src/mcp-server/node_modules
package-lock.json
pnpm-lock.yaml
yarn.lock
db
.env
*.min.js
*.min.css
openapi.json
-9
View File
@@ -1,9 +0,0 @@
{
"semi": true,
"singleQuote": false,
"tabWidth": 2,
"trailingComma": "all",
"printWidth": 80,
"arrowParens": "always",
"endOfLine": "lf"
}
-128
View File
@@ -1,128 +0,0 @@
# Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity
and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
- Demonstrating empathy and kindness toward other people
- Being respectful of differing opinions, viewpoints, and experiences
- Giving and gracefully accepting constructive feedback
- Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
- Focusing on what is best not just for us as individuals, but for the
overall community
Examples of unacceptable behavior include:
- The use of sexualized language or imagery, and sexual attention or
advances of any kind
- Trolling, insulting or derogatory comments, and personal or political attacks
- Public or private harassment
- Publishing others' private information, such as a physical or email
address, without their explicit permission
- Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
mail@termix.site.
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series
of actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within
the community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
Community Impact Guidelines were inspired by [Mozilla's code of conduct
enforcement ladder](https://github.com/mozilla/diversity).
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at
https://www.contributor-covenant.org/translations.
-106
View File
@@ -1,106 +0,0 @@
# Contributing
## Prerequisites
- [Node.js](https://nodejs.org/en/download/) (built with v24)
- [NPM](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm)
- [Git](https://git-scm.com/downloads)
## Installation
1. Clone the repository:
```sh
git clone https://github.com/Termix-SSH/Termix
```
2. Install the dependencies:
```sh
npm install
```
## Running the development server
Run the following commands:
```sh
npm run dev
npm run dev:backend
```
This will start the backend and the frontend Vite server. You can access Termix by going to `http://localhost:5174/`.
## Contributing
1. **Fork the repository**: Click the "Fork" button at the top right of
the [repository page](https://github.com/Termix-SSH/Termix).
2. **Create a new branch**:
```sh
git checkout -b feature/my-new-feature
```
3. **Make your changes**: Implement your feature, fix, or improvement.
4. **Commit your changes**:
```sh
git commit -m "Feature request my new feature"
```
5. **Push to your fork**:
```sh
git push origin feature/my-feature-request
```
6. **Open a pull request**: Go to the original repository and create a PR with a clear description.
## Guidelines
- Follow the existing code style. Use Tailwind CSS with shadcn components.
- Use the below color scheme with the respective CSS variable placed in the `className` of a div/component.
- Place all API routes in the `main-axios.ts` file. Updating the `openapi.json` is unneeded.
- Include meaningful commit messages.
- Link related issues when applicable.
- `MobileApp.tsx` renders when the users screen width is less than 768px, otherwise it loads the usual `DesktopApp.tsx`.
## Color Scheme
### Background Colors
| CSS Variable | Color Value | Usage | Description |
| ----------------------------- | ----------- | --------------------------- | ---------------------------------------- |
| `--color-dark-bg` | `#18181b` | Main dark background | Primary dark background color |
| `--color-dark-bg-darker` | `#0e0e10` | Darker backgrounds | Darker variant for panels and containers |
| `--color-dark-bg-darkest` | `#09090b` | Darkest backgrounds | Darkest background (terminal) |
| `--color-dark-bg-light` | `#141416` | Light dark backgrounds | Lighter variant of dark background |
| `--color-dark-bg-very-light` | `#101014` | Very light dark backgrounds | Very light variant of dark background |
| `--color-dark-bg-panel` | `#1b1b1e` | Panel backgrounds | Background for panels and cards |
| `--color-dark-bg-panel-hover` | `#232327` | Panel hover states | Background for panels on hover |
### Element-Specific Backgrounds
| CSS Variable | Color Value | Usage | Description |
| ------------------------ | ----------- | ------------------ | --------------------------------------------- |
| `--color-dark-bg-input` | `#222225` | Input fields | Background for input fields and form elements |
| `--color-dark-bg-button` | `#23232a` | Button backgrounds | Background for buttons and clickable elements |
| `--color-dark-bg-active` | `#1d1d1f` | Active states | Background for active/selected elements |
| `--color-dark-bg-header` | `#131316` | Header backgrounds | Background for headers and navigation bars |
### Border Colors
| CSS Variable | Color Value | Usage | Description |
| ---------------------------- | ----------- | --------------- | ---------------------------------------- |
| `--color-dark-border` | `#303032` | Default borders | Standard border color |
| `--color-dark-border-active` | `#2d2d30` | Active borders | Border color for active elements |
| `--color-dark-border-hover` | `#434345` | Hover borders | Border color on hover states |
| `--color-dark-border-light` | `#5a5a5d` | Light borders | Lighter border color for subtle elements |
| `--color-dark-border-medium` | `#373739` | Medium borders | Medium weight border color |
| `--color-dark-border-panel` | `#222224` | Panel borders | Border color for panels and cards |
### Interactive States
| CSS Variable | Color Value | Usage | Description |
| ------------------------ | ----------- | ----------------- | --------------------------------------------- |
| `--color-dark-hover` | `#2d2d30` | Hover states | Background color for hover effects |
| `--color-dark-active` | `#2a2a2c` | Active states | Background color for active elements |
| `--color-dark-pressed` | `#1a1a1c` | Pressed states | Background color for pressed/clicked elements |
| `--color-dark-hover-alt` | `#2a2a2d` | Alternative hover | Alternative hover state color |
## Support
If you need help or want to request a feature with Termix, visit the [Issues](https://github.com/Termix-SSH/Support/issues) page, log in, and press `New Issue`.
Please be as detailed as possible in your issue, preferably written in English. You can also join the [Discord](https://discord.gg/jVQGdvHDrf) server and visit the support
channel, however, response times may be longer.
-24
View File
@@ -1,24 +0,0 @@
cask "termix" do
version "2.5.0"
sha256 "0662380b3cc986e5ddab263122e87b03a581bc18dbff1ad13e11dc973c84984b"
url "https://github.com/Termix-SSH/Termix/releases/download/release-#{version}-tag/termix_macos_universal_dmg.dmg"
name "Termix"
desc "Web-based server management platform with SSH terminal, tunneling, and file editing"
homepage "https://github.com/Termix-SSH/Termix"
livecheck do
url :url
strategy :github_latest
end
app "Termix.app"
zap trash: [
"~/Library/Application Support/termix",
"~/Library/Caches/com.karmaa.termix",
"~/Library/Caches/com.karmaa.termix.ShipIt",
"~/Library/Preferences/com.karmaa.termix.plist",
"~/Library/Saved Application State/com.karmaa.termix.savedState",
]
end
+57 -384
View File
@@ -1,261 +1,48 @@
<div align="center">
# Repo Stats
![GitHub Repo stars](https://img.shields.io/github/stars/LukeGus/Termix?style=flat&label=Stars)
![GitHub forks](https://img.shields.io/github/forks/LukeGus/Termix?style=flat&label=Forks)
![GitHub Release](https://img.shields.io/github/v/release/LukeGus/Termix?style=flat&label=Release)
<a href="https://discord.gg/jVQGdvHDrf"><img alt="Discord" src="https://img.shields.io/discord/1347374268253470720"></a>
#### Top Technologies
[![React Badge](https://img.shields.io/badge/-React-61DBFB?style=flat-square&labelColor=black&logo=react&logoColor=61DBFB)](#)
[![TypeScript Badge](https://img.shields.io/badge/-TypeScript-3178C6?style=flat-square&labelColor=black&logo=typescript&logoColor=3178C6)](#)
[![Node.js Badge](https://img.shields.io/badge/-Node.js-3C873A?style=flat-square&labelColor=black&logo=node.js&logoColor=3C873A)](#)
[![Vite Badge](https://img.shields.io/badge/-Vite-646CFF?style=flat-square&labelColor=black&logo=vite&logoColor=646CFF)](#)
[![Tailwind CSS Badge](https://img.shields.io/badge/-TailwindCSS-38B2AC?style=flat-square&labelColor=black&logo=tailwindcss&logoColor=38B2AC)](#)
[![Docker Badge](https://img.shields.io/badge/-Docker-2496ED?style=flat-square&labelColor=black&logo=docker&logoColor=2496ED)](#)
[![SQLite Badge](https://img.shields.io/badge/-SQLite-003B57?style=flat-square&labelColor=black&logo=sqlite&logoColor=003B57)](#)
[![Radix UI Badge](https://img.shields.io/badge/-Radix%20UI-161618?style=flat-square&labelColor=black&logo=radixui&logoColor=161618)](#)
<img src="./public/icon.svg" width="120" height="120" alt="Termix Logo" />
<h1>Termix</h1>
<p>Self-hosted SSH management and remote desktop access</p>
<p>
English ·
<a href="readme/README-CN.md">中文</a> ·
<a href="readme/README-JA.md">日本語</a> ·
<a href="readme/README-KO.md">한국어</a> ·
<a href="readme/README-FR.md">Français</a> ·
<a href="readme/README-DE.md">Deutsch</a> ·
<a href="readme/README-ES.md">Español</a> ·
<a href="readme/README-PT.md">Português</a> ·
<a href="readme/README-RU.md">Русский</a> ·
<a href="readme/README-AR.md">العربية</a> ·
<a href="readme/README-HI.md">हिन्दी</a> ·
<a href="readme/README-TR.md">Türkçe</a> ·
<a href="readme/README-VI.md">Tiếng Việt</a> ·
<a href="readme/README-IT.md">Italiano</a>
<br />
<p align="center">
<a href="https://github.com/LukeGus/Termix">
<img alt="Termix Banner" src=./public/icon.svg style="width: 250px; height: auto;"> </a>
</p>
<p>
<img src="https://img.shields.io/github/stars/Termix-SSH/Termix?style=flat&label=Stars&color=F39044&labelColor=1a1a1a" />
<img src="https://img.shields.io/github/forks/Termix-SSH/Termix?style=flat&label=Forks&color=F39044&labelColor=1a1a1a" />
<img src="https://img.shields.io/github/v/release/Termix-SSH/Termix?style=flat&label=Release&color=F39044&labelColor=1a1a1a&v=1" />
<a href="https://discord.gg/jVQGdvHDrf"><img alt="Discord" src="https://img.shields.io/discord/1347374268253470720?color=F39044&labelColor=1a1a1a" /></a>
<a href="https://donate.termix.site/"><img alt="Donate" src="https://img.shields.io/badge/Donate-Support%20Termix-F39044?style=flat&labelColor=1a1a1a" /></a>
</p>
If you would like, you can support the project here!\
[![GitHub Sponsor](https://img.shields.io/badge/Sponsor-LukeGus-181717?style=for-the-badge&logo=github&logoColor=white)](https://github.com/sponsors/LukeGus)
<p>
<a href="https://donate.termix.site/"><img alt="Donations this month" src="https://img.shields.io/badge/dynamic/json?style=for-the-badge&label=Donations%20this%20month&query=%24.fiatTotal&prefix=%24&url=https%3A%2F%2Ftermix.site%2Fdonation-snapshot.json&color=F39044&labelColor=1a1a1a" /></a>
</p>
# Overview
Termix is an open-source, forever-free, self-hosted all-in-one server management platform. It provides a web-based solution for managing your servers and infrastructure through a single, intuitive interface. Termix offers SSH terminal access, SSH tunneling capabilities, and remote file configuration editing, with many more tools to come.
<br />
# Features
- **SSH Terminal Access** - Full-featured terminal with split-screen support (up to 4 panels) and tab system
- **SSH Tunnel Management** - Create and manage SSH tunnels with automatic reconnection and health monitoring
- **Remote Config Editor** - Edit files directly on remote servers with syntax highlighting and file management
- **SSH Host Manager** - Save, organize, and manage your SSH connections with tags and folders
- **User Authentication** - Secure user management with admin controls
- **Modern UI** - Clean interface built with React, Tailwind CSS, and the amazing Shadcn
Termix is free and open source. If you find it useful, consider [donating](https://donate.termix.site/) to help cover server costs and development time.
<br />
<img src="./repo-images/Termix Header.png" alt="Termix Banner" width="900" />
<br />
<br />
<p>
<img src="repo-images/Repo of the Day.png" alt="Repo of the Day Achievement" width="280" />
<br />
<sub>Achieved on September 1st, 2025</sub>
</p>
</div>
<br />
## Overview
Termix is an open-source, forever-free, self-hosted all-in-one server management platform. It provides a multi-platform solution for managing your servers and infrastructure through a single, intuitive interface. Termix offers SSH terminal access, remote desktop control (RDP, VNC, Telnet), SSH tunneling capabilities, remote file management, and many other tools. Termix is the perfect free and self-hosted alternative to Termius available for all platforms.
<br />
## Features
<table>
<tr>
<td width="50%" valign="top">
**SSH Terminal Access:**
Full-featured terminal with split-screen support (up to 4 panels) with a browser-like tab system. Includes support for customizing the terminal including common terminal themes, fonts, and other components.
</td>
<td width="50%" valign="top">
**Remote Desktop Access:**
RDP, VNC, and Telnet support over the browser with complete customization and split screening.
</td>
</tr>
<tr>
<td width="50%" valign="top">
**SSH Tunnel Management:**
Create and manage server-to-server SSH tunnels with automatic reconnection, health monitoring, and local, remote, or dynamic SOCKS forwarding. Desktop client-to-server tunnel settings are stored locally per desktop install, optional C2S preset snapshots can be saved to the server, renamed, loaded, or deleted when you want to move a local tunnel configuration between clients.
</td>
<td width="50%" valign="top">
**Remote File Manager:**
Manage files directly on remote servers with support for viewing and editing code, images, audio, and video. Upload, download, rename, delete, and move files seamlessly with sudo support. Includes support for moving files from server to server.
</td>
</tr>
<tr>
<td width="50%" valign="top">
**Docker and Podman Management:**
Start, stop, pause, remove containers. View container stats. Control containers using a docker exec terminal. Supports both Docker and Podman as the container runtime. It was not made to replace Portainer or Dockge but rather to simply manage your containers compared to creating them.
</td>
<td width="50%" valign="top">
**SSH Host Manager:**
Save, organize, and manage your SSH connections with tags and folders (folder customization and nested folder support), and easily save reusable login info while being able to automate the deployment of SSH keys.
</td>
</tr>
<tr>
<td width="50%" valign="top">
**Host Metrics:**
View CPU, memory, disk usage, network, uptime, system information, firewall, port monitor, log viewer, users/permissions, certificates, and many more which work on most Linux based servers. Includes time-series history graphs and threshold-based alerts with ntfy and webhook support.
</td>
<td width="50%" valign="top">
**User Authentication:**
Secure user management with admin controls and OIDC/LDAP/SSO (with access control), 2FA (TOTP), and passkey (WebAuthn) support. View active user sessions across all platforms and revoke permissions. Link your OIDC/Local accounts together. View audit log of all users actions.
</td>
</tr>
<tr>
<td width="50%" valign="top">
**Tailscale Integration:**
List devices from your tailnet to quickly add them as hosts, and connect using Tailscale SSH as an authentication method, letting your tailnet ACLs handle authorization without storing credentials.
</td>
<td width="50%" valign="top">
**RBAC:**
Create roles and share hosts across users/roles.
</td>
</tr>
<tr>
<td width="50%" valign="top">
**Serial Connections:**
Connect to serial devices (routers, switches, microcontrollers, etc.) directly from the browser or desktop app. Configure baud rate, data bits, stop bits, and parity. Uses the Web Serial API in supported browsers or a native backend in the Electron app.
</td>
<td width="50%" valign="top">
**Alerts:**
Set threshold-based alert rules on host metrics (CPU, memory, disk, etc.) and get notified via ntfy or webhooks when they fire. View firing and resolved alerts in a history log.
</td>
</tr>
<tr>
<td width="50%" valign="top">
**Homepage:**
A fully customizable homepage with a drag-and-drop widget grid. Add widgets for host status, service links, clocks, notes, RSS feeds, weather, Docker containers, host metrics charts, embedded terminals, iframes, and more.
</td>
<td width="50%" valign="top">
**Database Encryption:**
Backend stored as encrypted SQLite database files. View [docs](https://docs.termix.site/security) for more.
</td>
</tr>
<tr>
<td width="50%" valign="top">
**Network Graph:**
Customize your Dashboard to visualize your homelab based off your SSH connections with status support.
</td>
<td width="50%" valign="top">
**SSH Tools:**
Create reusable command snippets that execute with a single click. Run one command simultaneously across multiple open terminals.
</td>
</tr>
<tr>
<td width="50%" valign="top">
**Persistent Tabs:**
SSH sessions and tabs stay open across devices/refreshes if enabled in user profile.
</td>
<td width="50%" valign="top">
**Languages:**
Built-in support ~30 languages (managed by [Crowdin](https://docs.termix.site/translations)).
</td>
</tr>
</table>
<br />
<details>
<summary><b>More features</b></summary>
<br />
- **Dashboard** - View server information at a glance on your dashboard
- **API Keys** - Create user-scoped API keys with expiration dates to be used for automation/CI
- **Data Export/Import** - Export and import SSH hosts, credentials, and file manager data
- **Automatic SSL Setup** - Built-in SSL certificate generation and management with HTTPS redirects
- **Modern UI** - Clean desktop/mobile-friendly interface built with React, Tailwind CSS, and Shadcn. Choose between many different UI themes including light, dark, Dracula, etc. Use URL routes to open any connection in full-screen.
- **Command History** - Auto-complete and view previously ran SSH commands
- **Quick Connect** - Connect to a server without having to save the connection data
- **Command Palette** - Double tap left shift to quickly access SSH connections with your keyboard
- **Proxmox Integration** - Auto-add hosts into Termix from your Proxmox instance
- **SSH Feature Rich** - Supports jump hosts, Warpgate, TOTP based connections, SOCKS5, host key verification, password autofill, [OPKSSH](https://github.com/openpubkey/opkssh), tmux, port knocking, terminal logging, SSH agent forwarding, Bitwarden SSH agent, HashiCorp Vault SSH signing, and more.
- **Termix ID** - A sshid.io equivalent built into Termix. Claim a handle, publish your public SSH keys at a resolver URL, and use a built-in CA to issue SSH certificates.
</details>
<br />
## Platform Support
<table align="center">
<tr>
<th align="center">Platform</th>
<th align="center">Distribution</th>
</tr>
<tr>
<td align="center"><b>Web</b></td>
<td>Any modern browser (Chrome, Safari, Firefox) · PWA support</td>
</tr>
<tr>
<td align="center"><b>Windows</b> <sub>x64/ia32</sub></td>
<td>Portable · MSI Installer · Chocolatey</td>
</tr>
<tr>
<td align="center"><b>Linux</b> <sub>x64/ia32</sub></td>
<td>Portable · AUR · AppImage · Deb · Flatpak</td>
</tr>
<tr>
<td align="center"><b>macOS</b> <sub>x64/ia32, v12.0+</sub></td>
<td>Apple App Store · DMG · Homebrew</td>
</tr>
<tr>
<td align="center"><b>iOS/iPadOS</b> <sub>v15.1+</sub></td>
<td>Apple App Store · IPA</td>
</tr>
<tr>
<td align="center"><b>Android</b> <sub>v7.0+</sub></td>
<td>Google Play Store · APK</td>
</tr>
</table>
<br />
## Installation
Visit the [Termix Docs](https://docs.termix.site/install) for full installation instructions across all platforms.
Sample Docker Compose file (you can omit `guacd` and the network if you don't plan on using remote desktop features):
# Planned Features
- **Improved Admin Control** - Ability to manage admins, and give more fine-grained control over their permissions, share hosts, reset passwords, delete accounts, etc
- **More auth types** - Add 2FA, OCID support, etc
- **Theming** - Modify themeing for all tools
- **Improved SFTP Support** - Ability to manage files easier with the config editor by uploading, creating, and removing files
- **Improved Terminal Support** - Add more terminal protocols such as VNC and RDP (anyone who has experience in integrating RDP into a web-application similar to Apache Guacamole, please contact me by creating an issue)
# Installation
Visit the Termix [Docs](https://docs.termix.site/docs) for more information on how to install Termix. Otherwise, view a sample docker-compose file here:
```yaml
services:
termix:
@@ -268,147 +55,33 @@ services:
- termix-data:/app/data
environment:
PORT: "8080"
depends_on:
- guacd
networks:
- termix-net
guacd:
image: guacamole/guacd:1.6.0
container_name: guacd
restart: unless-stopped
ports:
- "4822:4822"
networks:
- termix-net
volumes:
termix-data:
driver: local
networks:
termix-net:
driver: bridge
driver: local
```
<br />
# Support
If you need help with Termix, you can join the [Discord](https://discord.gg/jVQGdvHDrf) server and visit the support channel. You can also open an issue or open a pull request on the [GitHub](https://github.com/LukeGus/Termix/issues) repo.
## Donate
# Show-off
Termix is free and open source with no subscriptions or paid plans. If you find it useful, consider donating to help cover server costs, domains, and development time.
<p align="center">
<img src="./repo-images/Image 1.png" width="400" alt="Termix Demo 1"/>
<img src="./repo-images/Image 2.png" width="400" alt="Termix Demo 2"/>
</p>
[Donate](https://donate.termix.site/)
<p align="center">
<img src="./repo-images/Image 3.png" width="250" alt="Termix Demo 3"/>
<img src="./repo-images/Image 4.png" width="250" alt="Termix Demo 4"/>
<img src="./repo-images/Image 5.png" width="250" alt="Termix Demo 5"/>
</p>
<br />
<p align="center">
<video src="https://github.com/user-attachments/assets/0f95495d-c5db-48f5-b18b-9ab48bb10d31" width="800" controls>
Your browser does not support the video tag.
</video>
</p>
## Screenshots
<div align="center">
<br />
[![YouTube](./repo-images/YouTube.png)](https://www.youtube.com/@TermixSSH/videos)
<sub>Watch update overviews on YouTube</sub>
<br />
<br />
<table>
<tr>
<td><img src="./repo-images/Image 1.png" alt="Termix Screenshot 1" width="400" /></td>
<td><img src="./repo-images/Image 2.png" alt="Termix Screenshot 2" width="400" /></td>
</tr>
<tr>
<td><img src="./repo-images/Image 3.png" alt="Termix Screenshot 3" width="400" /></td>
<td><img src="./repo-images/Image 4.png" alt="Termix Screenshot 4" width="400" /></td>
</tr>
<tr>
<td><img src="./repo-images/Image 5.png" alt="Termix Screenshot 5" width="400" /></td>
<td><img src="./repo-images/Image 6.png" alt="Termix Screenshot 6" width="400" /></td>
</tr>
<tr>
<td><img src="./repo-images/Image 7.png" alt="Termix Screenshot 7" width="400" /></td>
<td><img src="./repo-images/Image 8.png" alt="Termix Screenshot 8" width="400" /></td>
</tr>
<tr>
<td><img src="./repo-images/Image 9.png" alt="Termix Screenshot 9" width="400" /></td>
<td><img src="./repo-images/Image 10.png" alt="Termix Screenshot 10" width="400" /></td>
</tr>
<tr>
<td><img src="./repo-images/Image 11.png" alt="Termix Screenshot 11" width="400" /></td>
<td><img src="./repo-images/Image 12.png" alt="Termix Screenshot 12" width="400" /></td>
</tr>
<tr>
<td><img src="./repo-images/Image 13.png" alt="Termix Screenshot 13" width="400" /></td>
<td><img src="./repo-images/Image 14.png" alt="Termix Screenshot 14" width="400" /></td>
</tr>
<tr>
<td><img src="./repo-images/Image 15.png" alt="Termix Screenshot 15" width="400" /></td>
<td><img src="./repo-images/Image 16.png" alt="Termix Screenshot 16" width="400" /></td>
</tr>
</table>
<sub>Some videos and images may be out of date or may not perfectly showcase features.</sub>
</div>
<br />
## Planned Features
See [Projects](https://github.com/orgs/Termix-SSH/projects/5) for all planned features. If you are looking to contribute, see [Contributing](https://github.com/Termix-SSH/Termix/blob/main/CONTRIBUTING.md).
<br />
## Sponsors
<div align="center">
<br />
<a href="https://www.digitalocean.com/">
<img src="https://opensource.nyc3.cdn.digitaloceanspaces.com/attribution/assets/SVG/DO_Logo_horizontal_blue.svg" height="40" alt="DigitalOcean" />
</a>
&nbsp;&nbsp;&nbsp;
<a href="https://crowdin.com/">
<img src="https://support.crowdin.com/assets/logos/core-logo/svg/crowdin-core-logo-cDark.svg" height="40" alt="Crowdin" />
</a>
&nbsp;&nbsp;&nbsp;
<a href="https://www.blacksmith.sh/">
<img src="https://cdn.prod.website-files.com/681bfb0c9a4601bc6e288ec4/683ca9e2c5186757092611b8_e8cb22127df4da0811c4120a523722d2_logo-backsmith-wordmark-light.svg" height="40" alt="Blacksmith" />
</a>
&nbsp;&nbsp;&nbsp;
<a href="https://www.cloudflare.com/">
<img src="https://sirv.sirv.com/website/screenshots/cloudflare/cloudflare-logo.png?w=300" height="40" alt="Cloudflare" />
</a>
&nbsp;&nbsp;&nbsp;
<a href="https://tailscale.com/">
<img src="https://drive.google.com/uc?export=view&id=1lIxkJuX6M23bW-2FElhT0rQieTrzaVSL" height="40" alt="Tailscale" />
</a>
&nbsp;&nbsp;&nbsp;
<a href="https://akamai.com/">
<img src="https://upload.wikimedia.org/wikipedia/commons/8/8b/Akamai_logo.svg" height="40" alt="Akamai" />
</a>
&nbsp;&nbsp;&nbsp;
<a href="https://aws.amazon.com/">
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/9/93/Amazon_Web_Services_Logo.svg/960px-Amazon_Web_Services_Logo.svg.png" height="40" alt="AWS" />
</a>
&nbsp;&nbsp;&nbsp;
<a href="https://rackgenius.com/">
<img src="https://rackgenius.com/rackgenius-logo.png" height="40" alt="AWS" />
</a>
</div>
<br />
## Support
If you need help or want to request a feature with Termix, visit the [Issues](https://github.com/Termix-SSH/Support/issues) page, log in, and press `New Issue`. Please be as detailed as possible in your issue, preferably written in English. You can also join the [Discord](https://discord.gg/jVQGdvHDrf) server and visit the support channel, however, response times may be longer.
<br />
## License
Distributed under the Apache License Version 2.0. See `LICENSE` for more information.
# License
Distributed under the Apache License Version 2.0. See LICENSE for more information.
-81
View File
@@ -1,81 +0,0 @@
<!-- SUMMARY -->
Major new features including serial connections, Tailscale/WireGuard support, HashiCorp Vault SSH auth, Bitwarden SSH agent, WebAuthn passkeys, Podman support, a new grid-based dashboard, host metrics history with alerting, and much more.
<!-- /SUMMARY -->
<!-- YOUTUBE -->
https://youtu.be/c3UD4q2jW_8
<!-- /YOUTUBE -->
<!-- UPDATE_LOG -->
- Termix ID with a public handle, hosted public key resolver, and built-in CA for issuing SSH certificates
- Serial connections support
- Tailscale and WireGuard VPN host integration with status detection
- HashiCorp Vault SSH signer authentication
- Bitwarden SSH agent integration
- WebAuthn passkey authentication
- Podman container runtime support alongside Docker
- SSH agent forwarding support across all SSH features
- New grid and widget-based dashboard homepage
- Grafana-style server stats history graphs
- Alert system with ntfy and webhook notification support
- Host temperature metrics card
- App fullscreen mode
- External editor support for file manager (desktop app)
- Safe host sharing export
- SSH credential password fallback for key-based auth
- Open all sessions in a folder at once
- Custom terminal theme color support
- Custom tunnel endpoints configuration
- GUACD_URL environment variable support
- App rail hover expansion setting
- Terminal font zoom with mouse wheel
- File manager terminals promoted to full tabs
- Donate button on dashboard
- PuTTY PPK SSH key support
- Confirmation dialog when closing active host connections
- Confirmation prompt before opening large files in the editor
- Cross-host file manager clipboard
- Prioritize host results in command palette search
- Retry autostart tunnel host fetches on failure
<!-- /UPDATE_LOG -->
<!-- BUG_FIXES -->
- SSH port connection bug
- VNC required argument handshake failure
- Jump host SOCKS5 proxy selection using wrong proxy
- Tunnel endpoint resolution failing in some configurations
- Direct tunnel skipping endpoint credential validation incorrectly
- Dashboard host routing ignoring protocol settings
- Dashboard service link creation broken
- File manager uploads failing with 400 error and missing schema migrations on upgrade
- Large file manager uploads not chunked (chunked for files >=1.5GB)
- File uploads over 100MB failing due to ArrayBuffer browser limit
- File path case not preserved in file manager UI
- File downloads unreliable in the desktop app
- Tmux detection path handling incorrect
- Host metrics startup polling incorrect
- TUI terminal output highlighting incorrect
- Runtime base path for auth callbacks incorrect
- Windows app icon unstable
- SSH heading syntax highlighting broken
- Terminal link dialog layering issue
- Electron OIDC browser authentication failures
- Proxmox import auth fallback not working
- OIDC role credential shares not synced for OIDC users
- RDP connections requiring credentials when none are needed
- VNC authentication settings not persisted
- Guacamole unicode token corruption
- Guacamole websocket base path incorrect
- Guacamole disconnect during startup crash
- Host metrics starting for non-SSH hosts
- Sidebar host hover causing layout shift
- Alert UI incorrectly applying Termix CSS and alert system failing to load
- Translation key incorrect for nav close action
- PUID HTML ownership in Docker entrypoint
<!-- /BUG_FIXES -->
-5
View File
@@ -1,5 +0,0 @@
# Security Policy
## Reporting a Vulnerability
Please report any vulnerabilities to [GitHub Security](https://github.com/Termix-SSH/Termix/security/advisories).
-58
View File
@@ -1,58 +0,0 @@
{
"$schema": "https://biomejs.dev/schemas/2.5.1/schema.json",
"vcs": {
"enabled": true,
"clientKind": "git",
"useIgnoreFile": true,
"defaultBranch": "dev-2.5.0"
},
"files": {
"ignoreUnknown": true,
"includes": [
"**",
"!!build",
"!!coverage",
"!!dist",
"!!dist-ssr",
"!!release",
"!!node_modules",
"!!src/mcp-server/node_modules",
"!!db",
"!!.env",
"!!**/*.min.js",
"!!**/*.min.css",
"!!openapi.json"
]
},
"formatter": {
"enabled": true,
"indentStyle": "space",
"indentWidth": 2,
"lineWidth": 80,
"lineEnding": "lf"
},
"linter": {
"enabled": false
},
"javascript": {
"formatter": {
"quoteStyle": "double",
"semicolons": "always",
"trailingCommas": "all",
"arrowParentheses": "always"
}
},
"json": {
"formatter": {
"trailingCommas": "none"
}
},
"css": {
"parser": {
"tailwindDirectives": true
}
},
"assist": {
"enabled": false
}
}
Binary file not shown.
-12
View File
@@ -1,12 +0,0 @@
const fs = require("fs");
const path = require("path");
exports.default = async function afterPack(context) {
const { targets, appOutDir } = context;
const isDir = targets.some((t) => t.name === "dir");
if (!isDir) return;
const markerPath = path.join(appOutDir, ".portable");
fs.writeFileSync(markerPath, "");
};
-14
View File
@@ -1,14 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
<key>com.apple.security.cs.allow-dyld-environment-variables</key>
<true/>
</dict>
</plist>
-14
View File
@@ -1,14 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
<key>com.apple.security.cs.allow-dyld-environment-variables</key>
<true/>
</dict>
</plist>
-16
View File
@@ -1,16 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.inherit</key>
<true/>
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
</dict>
</plist>
-20
View File
@@ -1,20 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.network.client</key>
<true/>
<key>com.apple.security.network.server</key>
<true/>
<key>com.apple.security.files.user-selected.read-write</key>
<true/>
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
</dict>
</plist>
-31
View File
@@ -1,31 +0,0 @@
const { notarize } = require('@electron/notarize');
exports.default = async function notarizing(context) {
const { electronPlatformName, appOutDir } = context;
if (electronPlatformName !== 'darwin') {
return;
}
const appleId = process.env.APPLE_ID;
const appleIdPassword = process.env.APPLE_ID_PASSWORD;
const teamId = process.env.APPLE_TEAM_ID;
if (!appleId || !appleIdPassword || !teamId) {
return;
}
const appName = context.packager.appInfo.productFilename;
try {
await notarize({
appBundleId: 'com.karmaa.termix',
appPath: `${appOutDir}/${appName}.app`,
appleId: appleId,
appleIdPassword: appleIdPassword,
teamId: teamId,
});
} catch (error) {
console.error('Notarization failed:', error);
}
};
-29
View File
@@ -1,29 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2015/06/nuspec.xsd">
<metadata>
<id>termix-ssh</id>
<version>VERSION_PLACEHOLDER</version>
<packageSourceUrl>https://github.com/Termix-SSH/Termix</packageSourceUrl>
<owners>bugattiguy527</owners>
<title>Termix SSH</title>
<authors>bugattiguy527</authors>
<projectUrl>https://github.com/Termix-SSH/Termix</projectUrl>
<iconUrl>https://raw.githubusercontent.com/Termix-SSH/Termix/main/public/icon.png</iconUrl>
<licenseUrl>https://raw.githubusercontent.com/Termix-SSH/Termix/refs/heads/main/LICENSE</licenseUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<projectSourceUrl>https://github.com/Termix-SSH/Termix</projectSourceUrl>
<docsUrl>https://docs.termix.site/install</docsUrl>
<bugTrackerUrl>https://github.com/Termix-SSH/Support/issues</bugTrackerUrl>
<tags>docker ssh terminal telnet self-hosted rdp file-management vnc ssh-tunnel server-stats termix</tags>
<summary>Self-hosted SSH and remote desktop management.</summary>
<description>
Termix is an open-source, forever-free, self-hosted all-in-one server management platform. It provides a multi-platform solution for managing your servers and infrastructure through a single, intuitive interface. Termix offers SSH terminal access, remote desktop control (RDP, VNC, Telnet), SSH tunneling capabilities, remote file management, and many other tools. Termix is the perfect free and self-hosted alternative to Termius available for all platforms.
This package installs the desktop application version of Termix.
</description>
<releaseNotes>https://github.com/Termix-SSH/Termix/releases</releaseNotes>
</metadata>
<files>
<file src="tools\**" target="tools" />
</files>
</package>
-20
View File
@@ -1,20 +0,0 @@
$ErrorActionPreference = 'Stop'
$packageName = 'termix-ssh'
$toolsDir = "$(Split-Path -parent $MyInvocation.MyCommand.Definition)"
$url64 = 'DOWNLOAD_URL_PLACEHOLDER'
$checksum64 = 'CHECKSUM_PLACEHOLDER'
$checksumType64 = 'sha256'
$packageArgs = @{
packageName = $packageName
fileType = 'msi'
url64bit = $url64
softwareName = 'Termix*'
checksum64 = $checksum64
checksumType64 = $checksumType64
silentArgs = "/qn /norestart /l*v `"$($env:TEMP)\$($packageName).$($env:chocolateyPackageVersion).MsiInstall.log`""
validExitCodes = @(0, 3010, 1641)
}
Install-ChocolateyPackage @packageArgs
-33
View File
@@ -1,33 +0,0 @@
$ErrorActionPreference = 'Stop'
$packageName = 'termix-ssh'
$softwareName = 'Termix*'
$installerType = 'msi'
$silentArgs = '/qn /norestart'
$validExitCodes = @(0, 3010, 1605, 1614, 1641)
[array]$key = Get-UninstallRegistryKey -SoftwareName $softwareName
if ($key.Count -eq 1) {
$key | % {
$file = "$($_.UninstallString)"
if ($installerType -eq 'msi') {
$silentArgs = "$($_.PSChildName) $silentArgs"
$file = ''
}
Uninstall-ChocolateyPackage -PackageName $packageName `
-FileType $installerType `
-SilentArgs "$silentArgs" `
-ValidExitCodes $validExitCodes `
-File "$file"
}
} elseif ($key.Count -eq 0) {
Write-Warning "$packageName has already been uninstalled by other means."
} elseif ($key.Count -gt 1) {
Write-Warning "$($key.Count) matches found!"
Write-Warning "To prevent accidental data loss, no programs will be uninstalled."
$key | % {Write-Warning "- $($_.DisplayName)"}
}
+4 -8
View File
@@ -1,17 +1,15 @@
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "radix-lyra",
"style": "new-york",
"rsc": false,
"tsx": true,
"tailwind": {
"config": "",
"css": "src/index.css",
"baseColor": "neutral",
"baseColor": "zinc",
"cssVariables": true,
"prefix": ""
},
"iconLibrary": "lucide",
"rtl": false,
"aliases": {
"components": "@/components",
"utils": "@/lib/utils",
@@ -19,7 +17,5 @@
"lib": "@/lib",
"hooks": "@/hooks"
},
"menuColor": "default",
"menuAccent": "subtle",
"registries": {}
}
"iconLibrary": "lucide"
}
-6
View File
@@ -1,6 +0,0 @@
project_id: "858252"
api_token: "env:CROWDIN_API_TOKEN"
files:
- source: /src/ui/locales/en.json
translation: /src/ui/locales/translated/%locale_with_underscore%.json
+36 -47
View File
@@ -1,17 +1,12 @@
# Stage 1: Install dependencies
FROM node:26-slim AS deps
# Stage 1: Install dependencies and build frontend
FROM node:18-alpine AS deps
WORKDIR /app
RUN apt-get update && apt-get install -y python3 make g++ && rm -rf /var/lib/apt/lists/*
RUN apk add --no-cache python3 make g++
COPY package*.json ./
COPY .npmrc ./
COPY vendor ./vendor
COPY scripts/patch-guacamole-lite.cjs ./scripts/
RUN npm ci --ignore-scripts && \
node scripts/patch-guacamole-lite.cjs && \
RUN npm ci --force && \
npm cache clean --force
# Stage 2: Build frontend
@@ -20,70 +15,64 @@ WORKDIR /app
COPY . .
RUN find public/fonts -name "*.ttf" ! -name "*Regular.ttf" ! -name "*Bold.ttf" ! -name "*Italic.ttf" -delete
RUN npm run build
RUN npm cache clean --force && \
NODE_OPTIONS="--max-old-space-size=3072" npm run build
# Stage 3: Build backend
# Stage 3: Build backend TypeScript
FROM deps AS backend-builder
WORKDIR /app
COPY . .
RUN npm rebuild better-sqlite3
RUN npm run build:backend
# Stage 4: Production dependencies only
FROM node:26-slim AS production-deps
# Stage 4: Production dependencies
FROM node:18-alpine AS production-deps
WORKDIR /app
RUN apt-get update && apt-get install -y python3 make g++ && rm -rf /var/lib/apt/lists/*
COPY package*.json ./
COPY .npmrc ./
COPY vendor ./vendor
COPY scripts/patch-guacamole-lite.cjs ./scripts/
RUN npm ci --omit=dev --ignore-scripts && \
node scripts/patch-guacamole-lite.cjs && \
npm rebuild better-sqlite3 bcryptjs ssh2 && \
RUN npm ci --only=production --ignore-scripts --force && \
npm cache clean --force
# Stage 5: Final optimized image
FROM node:26-slim
# Stage 5: Build native modules
FROM node:18-alpine AS native-builder
WORKDIR /app
RUN apk add --no-cache python3 make g++
COPY package*.json ./
RUN npm ci --only=production bcryptjs better-sqlite3 --force && \
npm cache clean --force
# Stage 6: Final image
FROM node:18-alpine
ENV DATA_DIR=/app/data \
PORT=8080 \
NODE_ENV=production
RUN apt-get update && apt-get install -y nginx gettext-base openssl ca-certificates gosu wget certbot python3-certbot-dns-cloudflare && \
update-ca-certificates && \
rm -rf /var/lib/apt/lists/* && \
mkdir -p /app/data /app/uploads /app/data/.opk /app/nginx /tmp/nginx && \
chown -R node:node /app /tmp/nginx && \
chmod 755 /app/data /app/uploads /app/data/.opk /app/nginx /tmp/nginx
RUN apk add --no-cache nginx gettext su-exec && \
mkdir -p /app/data && \
chown -R node:node /app/data
COPY docker/nginx.conf /app/nginx/nginx.conf.template
COPY docker/nginx-https.conf /app/nginx/nginx-https.conf.template
COPY docker/nginx.conf /etc/nginx/nginx.conf
COPY --from=frontend-builder /app/dist /usr/share/nginx/html
RUN chown -R nginx:nginx /usr/share/nginx/html
COPY --chown=node:node --from=frontend-builder /app/dist /app/html
WORKDIR /app
COPY --chown=node:node --from=production-deps /app/node_modules /app/node_modules
COPY --chown=node:node --from=backend-builder /app/dist/backend ./dist/backend
COPY --chown=node:node package.json ./
COPY --from=production-deps /app/node_modules /app/node_modules
COPY --from=native-builder /app/node_modules/bcryptjs /app/node_modules/bcryptjs
COPY --from=native-builder /app/node_modules/better-sqlite3 /app/node_modules/better-sqlite3
COPY --from=backend-builder /app/dist/backend ./dist/backend
COPY package.json ./
RUN chown -R node:node /app
VOLUME ["/app/data"]
EXPOSE ${PORT} 30001 30002 30003 30004 30005 30006 30007 30008 30009 30010 30011 30012
HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \
CMD wget -q -O /dev/null http://localhost:30001/health || exit 1
EXPOSE ${PORT} 8081 8082 8083 8084
COPY docker/entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
CMD ["/entrypoint.sh"]
CMD ["/entrypoint.sh"]
-37
View File
@@ -1,37 +0,0 @@
services:
termix-dev:
build:
context: ..
dockerfile: docker/Dockerfile
container_name: termix-dev
restart: unless-stopped
ports:
- "8081:8080"
volumes:
- termix-dev-data:/app/data
environment:
PORT: "8080"
NODE_ENV: development
GUACD_HOST: "guacd-dev"
GUACD_RECORDING_PATH: "/termix-data/session_recordings/guacamole"
depends_on:
- guacd-dev
networks:
- termix-dev-net
guacd-dev:
image: guacamole/guacd:1.6.0
container_name: guacd-dev
restart: unless-stopped
volumes:
- termix-dev-data:/termix-data
networks:
- termix-dev-net
volumes:
termix-dev-data:
driver: local
networks:
termix-dev-net:
driver: bridge
+1 -20
View File
@@ -9,26 +9,7 @@ services:
- termix-data:/app/data
environment:
PORT: "8080"
GUACD_HOST: "guacd"
GUACD_RECORDING_PATH: "/termix-data/session_recordings/guacamole"
depends_on:
- guacd
networks:
- termix-net
guacd:
image: guacamole/guacd:1.6.0
container_name: guacd
restart: unless-stopped
volumes:
- termix-data:/termix-data
networks:
- termix-net
volumes:
termix-data:
driver: local
networks:
termix-net:
driver: bridge
driver: local
+10 -151
View File
@@ -1,170 +1,29 @@
#!/bin/sh
set -e
PUID=${PUID:-1000}
PGID=${PGID:-1000}
if [ "$(id -u)" = "0" ]; then
if [ "$PUID" = "0" ]; then
echo "Running as root (PUID=0, PGID=$PGID)"
chown -R root:root /app/data /app/uploads /tmp/nginx 2>/dev/null || true
else
echo "Setting up user permissions (PUID: $PUID, PGID: $PGID)..."
groupmod -o -g "$PGID" node 2>/dev/null || true
usermod -o -u "$PUID" node 2>/dev/null || true
chown -R node:node /app/data /app/uploads /app/html /tmp/nginx 2>/dev/null || true
echo "User node is now UID: $PUID, GID: $PGID"
exec gosu node:node "$0" "$@"
fi
fi
export PORT=${PORT:-8080}
export ENABLE_SSL=${ENABLE_SSL:-false}
export SSL_PORT=${SSL_PORT:-8443}
export SSL_CERT_PATH=${SSL_CERT_PATH:-/app/data/ssl/termix.crt}
export SSL_KEY_PATH=${SSL_KEY_PATH:-/app/data/ssl/termix.key}
echo "Configuring web UI to run on port: $PORT"
if [ "$ENABLE_SSL" = "true" ]; then
echo "SSL enabled - using HTTPS configuration with redirect"
NGINX_CONF_SOURCE="/app/nginx/nginx-https.conf.template"
else
echo "SSL disabled - using HTTP-only configuration (default)"
NGINX_CONF_SOURCE="/app/nginx/nginx.conf.template"
fi
envsubst '${PORT}' < /etc/nginx/nginx.conf > /etc/nginx/nginx.conf.tmp
mv /etc/nginx/nginx.conf.tmp /etc/nginx/nginx.conf
mkdir -p /tmp/nginx
envsubst '${PORT} ${SSL_PORT} ${SSL_CERT_PATH} ${SSL_KEY_PATH}' < $NGINX_CONF_SOURCE > /tmp/nginx/nginx.conf
mkdir -p /app/data /app/uploads /app/data/.opk /app/data/acme-webroot/.well-known/acme-challenge
chmod 755 /app/data /app/uploads /app/data/.opk 2>/dev/null || true
if [ -w /app/data ]; then
echo "Data directory is writable"
else
echo "WARNING: Data directory is not writable. OPKSSH may fail."
ls -ld /app/data
fi
if [ -w /app/data/.opk ]; then
echo "OPKSSH directory is writable"
else
echo "WARNING: OPKSSH directory is not writable. OPKSSH authentication will fail."
ls -ld /app/data/.opk
fi
OPKSSH_DIR="${DATA_DIR:-/app/data}/opkssh"
if [ ! -d "$OPKSSH_DIR" ]; then
echo "WARNING: OPKSSH binary directory not found at $OPKSSH_DIR"
echo "OPKSSH will be downloaded automatically on first use."
else
echo "OPKSSH binary directory found at $OPKSSH_DIR"
fi
if [ "$ENABLE_SSL" = "true" ]; then
echo "Checking SSL certificate configuration..."
mkdir -p /app/data/ssl
chmod 755 /app/data/ssl 2>/dev/null || true
DOMAIN=${SSL_DOMAIN:-localhost}
if [ -f "/app/data/ssl/termix.crt" ] && [ -f "/app/data/ssl/termix.key" ]; then
echo "SSL certificates found, checking validity..."
if openssl x509 -in /app/data/ssl/termix.crt -checkend 2592000 -noout >/dev/null 2>&1; then
echo "SSL certificates are valid and will be reused for domain: $DOMAIN"
else
echo "SSL certificate is expired or expiring soon, regenerating..."
rm -f /app/data/ssl/termix.crt /app/data/ssl/termix.key
fi
else
echo "SSL certificates not found, will generate new ones..."
fi
if [ ! -f "/app/data/ssl/termix.crt" ] || [ ! -f "/app/data/ssl/termix.key" ]; then
echo "Generating SSL certificates for domain: $DOMAIN"
cat > /app/data/ssl/openssl.conf << EOF
[req]
default_bits = 2048
prompt = no
default_md = sha256
distinguished_name = dn
req_extensions = v3_req
[dn]
C=US
ST=State
L=City
O=Termix
OU=IT Department
CN=$DOMAIN
[v3_req]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = $DOMAIN
DNS.2 = localhost
DNS.3 = 127.0.0.1
IP.1 = 127.0.0.1
IP.2 = ::1
IP.3 = 0.0.0.0
EOF
openssl genrsa -out /app/data/ssl/termix.key 2048
openssl req -new -x509 -key /app/data/ssl/termix.key -out /app/data/ssl/termix.crt -days 365 -config /app/data/ssl/openssl.conf -extensions v3_req
chmod 600 /app/data/ssl/termix.key
chmod 644 /app/data/ssl/termix.crt
rm -f /app/data/ssl/openssl.conf
echo "SSL certificates generated successfully for domain: $DOMAIN"
fi
fi
mkdir -p /app/data
chown -R node:node /app/data
chmod 755 /app/data
echo "Starting nginx..."
nginx -c /tmp/nginx/nginx.conf
# Inject runtime BASE_PATH into frontend if configured
if [ -n "$BASE_PATH" ]; then
echo "Injecting BASE_PATH: $BASE_PATH"
# Strip trailing slash for use as a path prefix
CLEAN_BASE_PATH="${BASE_PATH%/}"
find /app/html -name "index.html" -exec sed -i "s|window.__TERMIX_BASE_PATH__ = \"\"|window.__TERMIX_BASE_PATH__ = \"$CLEAN_BASE_PATH\"|g" {} \;
# Patch sw.js static asset paths with the base path prefix
find /app/html -name "sw.js" -exec sed -i "s|__TERMIX_SW_BASE_PATH__|$CLEAN_BASE_PATH|g" {} \;
else
# No base path - replace placeholder with empty string so paths stay absolute from root
find /app/html -name "sw.js" -exec sed -i "s|__TERMIX_SW_BASE_PATH__||g" {} \;
fi
nginx
echo "Starting backend services..."
cd /app
export NODE_ENV=production
if [ -f "package.json" ]; then
VERSION=$(grep '"version"' package.json | sed 's/.*"version": *"\([^"]*\)".*/\1/')
if [ -n "$VERSION" ]; then
export VERSION
else
echo "Warning: Could not extract version from package.json"
fi
if command -v su-exec > /dev/null 2>&1; then
su-exec node node dist/backend/starter.js
else
echo "Warning: package.json not found"
su -s /bin/sh node -c "node dist/backend/starter.js"
fi
node dist/backend/backend/starter.js
echo "All services started"
tail -f /dev/null
tail -f /dev/null
-758
View File
@@ -1,758 +0,0 @@
worker_processes 1;
master_process off;
pid /tmp/nginx/nginx.pid;
error_log /tmp/nginx/error.log warn;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
access_log /tmp/nginx/access.log;
client_body_temp_path /tmp/nginx/client_body;
proxy_temp_path /tmp/nginx/proxy_temp;
fastcgi_temp_path /tmp/nginx/fastcgi_temp;
uwsgi_temp_path /tmp/nginx/uwsgi_temp;
scgi_temp_path /tmp/nginx/scgi_temp;
sendfile on;
keepalive_timeout 65;
client_header_timeout 300s;
set_real_ip_from 127.0.0.1;
set_real_ip_from 10.0.0.0/8;
set_real_ip_from 172.16.0.0/12;
set_real_ip_from 192.168.0.0/16;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
map $http_x_forwarded_proto $proxy_x_forwarded_proto {
default $http_x_forwarded_proto;
'' $scheme;
}
map $http_x_forwarded_host $proxy_x_forwarded_host {
default $http_x_forwarded_host;
'' $http_host;
}
map $http_x_forwarded_port $proxy_x_forwarded_port {
default $http_x_forwarded_port;
'' '';
}
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384;
ssl_prefer_server_ciphers off;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
server {
listen ${PORT};
server_name _;
return 301 https://$host:${SSL_PORT}$request_uri;
}
server {
listen ${SSL_PORT} ssl;
server_name _;
absolute_redirect off;
ssl_certificate ${SSL_CERT_PATH};
ssl_certificate_key ${SSL_KEY_PATH};
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Content-Type-Options nosniff always;
add_header X-XSS-Protection "1; mode=block" always;
location ^~ /.well-known/acme-challenge/ {
root /app/data/acme-webroot;
default_type "text/plain";
try_files $uri =404;
}
location = /sw.js {
root /app/html;
expires off;
add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0" always;
try_files $uri =404;
}
location = /manifest.json {
root /app/html;
expires off;
add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0" always;
try_files $uri =404;
}
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
root /app/html;
expires 1y;
add_header Cache-Control "public, max-age=31536000, immutable" always;
try_files $uri =404;
}
location / {
root /app/html;
index index.html index.htm;
expires off;
add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0" always;
try_files $uri $uri/ /index.html;
}
location ~* \.map$ {
return 404;
access_log off;
log_not_found off;
}
location ~ ^/users/sessions(/.*)?$ {
proxy_pass http://127.0.0.1:30001;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
}
location ~ ^/users(/.*)?$ {
proxy_pass http://127.0.0.1:30001;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
proxy_set_header X-Forwarded-Port $proxy_x_forwarded_port;
proxy_set_header X-Forwarded-Host $proxy_x_forwarded_host;
}
location ~ ^/version(/.*)?$ {
proxy_pass http://127.0.0.1:30001;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
}
location ~ ^/releases(/.*)?$ {
proxy_pass http://127.0.0.1:30001;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
}
location ~ ^/alerts(/.*)?$ {
proxy_pass http://127.0.0.1:30001;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
}
location ~ ^/alert-rules(/.*)?$ {
proxy_pass http://127.0.0.1:30001;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
}
location ~ ^/notification-channels(/.*)?$ {
proxy_pass http://127.0.0.1:30001;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
}
location ~ ^/alert-firings(/.*)?$ {
proxy_pass http://127.0.0.1:30001;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
}
location ~ ^/rbac(/.*)?$ {
proxy_pass http://127.0.0.1:30001;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
}
location ~ ^/credentials(/.*)?$ {
proxy_pass http://127.0.0.1:30001;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
proxy_connect_timeout 60s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
}
location ~ ^/snippets(/.*)?$ {
proxy_pass http://127.0.0.1:30001;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
}
location ~ ^/vault(/.*)?$ {
proxy_pass http://127.0.0.1:30001;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
}
location ~ ^/termix-id(/.*)?$ {
proxy_pass http://127.0.0.1:30001;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location ~ ^/proxmox(/.*)?$ {
proxy_pass http://127.0.0.1:30001;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
proxy_connect_timeout 60s;
proxy_send_timeout 120s;
proxy_read_timeout 120s;
}
location ~ ^/c2s-tunnel-presets(/.*)?$ {
proxy_pass http://127.0.0.1:30001;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
}
location ~ ^/audit-logs(/.*)?$ {
proxy_pass http://127.0.0.1:30001;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
}
location ~ ^/terminal(/.*)?$ {
proxy_pass http://127.0.0.1:30001;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
}
location ~ ^/open-tabs(/.*)?$ {
proxy_pass http://127.0.0.1:30001;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
}
location ~ ^/user-preferences(/.*)?$ {
proxy_pass http://127.0.0.1:30001;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
}
location ~ ^/database(/.*)?$ {
client_max_body_size 5G;
client_body_timeout 300s;
proxy_pass http://127.0.0.1:30001;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
proxy_connect_timeout 60s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
proxy_request_buffering off;
proxy_buffering off;
}
location ~ ^/db(/.*)?$ {
client_max_body_size 5G;
client_body_timeout 300s;
proxy_pass http://127.0.0.1:30001;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
proxy_connect_timeout 60s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
proxy_request_buffering off;
proxy_buffering off;
}
location ~ ^/encryption(/.*)?$ {
proxy_pass http://127.0.0.1:30001;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
}
location /host/quick-connect {
proxy_pass http://127.0.0.1:30001;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $http_host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
}
location ~ ^/host/opkssh-chooser(/.*)?$ {
proxy_pass http://127.0.0.1:30001/host/opkssh-chooser$1$is_args$args;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Host $proxy_x_forwarded_host;
proxy_set_header X-Forwarded-Port $proxy_x_forwarded_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
proxy_cache_bypass 1;
proxy_no_cache 1;
add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0";
}
location ~ ^/host/opkssh-callback(/.*)?$ {
proxy_pass http://127.0.0.1:30001/host/opkssh-callback$1$is_args$args;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Host $proxy_x_forwarded_host;
proxy_set_header X-Forwarded-Port $proxy_x_forwarded_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
proxy_cache_bypass 1;
proxy_no_cache 1;
add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0";
}
location /host/ {
proxy_pass http://127.0.0.1:30001;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
}
location /session_logs/ {
proxy_pass http://127.0.0.1:30001;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
}
location /tailscale/ {
proxy_pass http://127.0.0.1:30001;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
}
location /ssh/websocket/ {
proxy_pass http://127.0.0.1:30002/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Host $proxy_x_forwarded_host;
proxy_set_header X-Forwarded-Port $proxy_x_forwarded_port;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_read_timeout 86400s;
proxy_send_timeout 86400s;
proxy_connect_timeout 10s;
proxy_buffering off;
proxy_request_buffering off;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503;
}
location ^~ /guacamole/websocket/ {
proxy_pass http://127.0.0.1:30008/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $http_host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
proxy_set_header X-Forwarded-Port $proxy_x_forwarded_port;
proxy_set_header X-Forwarded-Host $proxy_x_forwarded_host;
proxy_read_timeout 86400s;
proxy_send_timeout 86400s;
proxy_connect_timeout 10s;
proxy_buffering off;
proxy_request_buffering off;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503;
}
location ~ ^/guacamole(/.*)?$ {
proxy_pass http://127.0.0.1:30001;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
}
location /host/tunnel/ {
proxy_pass http://127.0.0.1:30003;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
}
location /ssh/tunnel/ {
proxy_pass http://127.0.0.1:30003;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
proxy_read_timeout 86400s;
proxy_send_timeout 86400s;
proxy_buffering off;
proxy_cache off;
}
location /host/file_manager/recent {
proxy_pass http://127.0.0.1:30001;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
}
location /host/file_manager/pinned {
proxy_pass http://127.0.0.1:30001;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
}
location /host/file_manager/shortcuts {
proxy_pass http://127.0.0.1:30001;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
}
location /host/file_manager/sudo-password {
proxy_pass http://127.0.0.1:30004;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
}
location /ssh/file_manager/ {
client_max_body_size 5G;
client_body_timeout 300s;
add_header Cache-Control "no-store, no-cache, must-revalidate" always;
proxy_pass http://127.0.0.1:30004;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
proxy_connect_timeout 60s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
proxy_request_buffering off;
proxy_buffering off;
}
location /host/file_manager/ssh/ {
client_max_body_size 5G;
client_body_timeout 300s;
add_header Cache-Control "no-store, no-cache, must-revalidate" always;
proxy_pass http://127.0.0.1:30004;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
proxy_connect_timeout 60s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
proxy_request_buffering off;
proxy_buffering off;
}
location ~ ^/network-topology(/.*)?$ {
proxy_pass http://127.0.0.1:30001;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
}
location /health {
proxy_pass http://127.0.0.1:30001;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
}
location ~ ^/status(/.*)?$ {
proxy_pass http://127.0.0.1:30005;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
}
location ~ ^/metrics(/.*)?$ {
proxy_pass http://127.0.0.1:30005;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
location ~ ^/(refresh|host-updated)$ {
proxy_pass http://127.0.0.1:30005;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
}
location ~ ^/host-metrics(/.*)?$ {
proxy_pass http://127.0.0.1:30005;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
proxy_connect_timeout 600s;
proxy_send_timeout 600s;
proxy_read_timeout 600s;
}
location ~ ^/global-settings(/.*)?$ {
proxy_pass http://127.0.0.1:30005;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
}
location ~ ^/uptime(/.*)?$ {
proxy_pass http://127.0.0.1:30006;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
}
location ~ ^/activity(/.*)?$ {
proxy_pass http://127.0.0.1:30006;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
}
location ~ ^/service-links(/.*)?$ {
proxy_pass http://127.0.0.1:30006;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
}
location ~ ^/homepage(/.*)?$ {
proxy_pass http://127.0.0.1:30012;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
}
location ^~ /docker/console/ {
proxy_pass http://127.0.0.1:30009/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $http_host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
proxy_set_header X-Forwarded-Port $proxy_x_forwarded_port;
proxy_set_header X-Forwarded-Host $proxy_x_forwarded_host;
proxy_read_timeout 86400s;
proxy_send_timeout 86400s;
proxy_connect_timeout 10s;
proxy_buffering off;
proxy_request_buffering off;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503;
}
# --- tmux-monitor begin ---
location ~ ^/tmux_monitor(/.*)?$ {
proxy_pass http://127.0.0.1:30010;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
proxy_connect_timeout 60s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
}
# --- tmux-monitor end ---
location ~ ^/docker(/.*)?$ {
proxy_pass http://127.0.0.1:30007;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
proxy_connect_timeout 60s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
}
location ^~ /serial/websocket/ {
proxy_pass http://127.0.0.1:30011/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $http_host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
proxy_read_timeout 86400s;
proxy_send_timeout 86400s;
proxy_connect_timeout 10s;
proxy_buffering off;
proxy_request_buffering off;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /app/html;
}
}
}
+30 -693
View File
@@ -1,747 +1,84 @@
worker_processes 1;
master_process off;
pid /tmp/nginx/nginx.pid;
error_log /tmp/nginx/error.log warn;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
include mime.types;
default_type application/octet-stream;
access_log /tmp/nginx/access.log;
client_body_temp_path /tmp/nginx/client_body;
proxy_temp_path /tmp/nginx/proxy_temp;
fastcgi_temp_path /tmp/nginx/fastcgi_temp;
uwsgi_temp_path /tmp/nginx/uwsgi_temp;
scgi_temp_path /tmp/nginx/scgi_temp;
sendfile on;
keepalive_timeout 65;
client_header_timeout 300s;
set_real_ip_from 127.0.0.1;
set_real_ip_from 10.0.0.0/8;
set_real_ip_from 172.16.0.0/12;
set_real_ip_from 192.168.0.0/16;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
map $http_x_forwarded_proto $proxy_x_forwarded_proto {
default $http_x_forwarded_proto;
'' $scheme;
}
map $http_x_forwarded_host $proxy_x_forwarded_host {
default $http_x_forwarded_host;
'' $http_host;
}
map $http_x_forwarded_port $proxy_x_forwarded_port {
default $http_x_forwarded_port;
'' '';
}
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384;
ssl_prefer_server_ciphers off;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
server {
listen ${PORT};
server_name _;
absolute_redirect off;
add_header X-Content-Type-Options nosniff always;
add_header X-XSS-Protection "1; mode=block" always;
location ^~ /.well-known/acme-challenge/ {
root /app/data/acme-webroot;
default_type "text/plain";
try_files $uri =404;
}
location = /sw.js {
root /app/html;
expires off;
add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0" always;
try_files $uri =404;
}
location = /manifest.json {
root /app/html;
expires off;
add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0" always;
try_files $uri =404;
}
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
root /app/html;
expires 1y;
add_header Cache-Control "public, max-age=31536000, immutable" always;
try_files $uri =404;
}
server_name localhost;
location / {
root /app/html;
root /usr/share/nginx/html;
index index.html index.htm;
expires off;
add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0" always;
try_files $uri $uri/ /index.html;
}
location ~* \.map$ {
return 404;
access_log off;
log_not_found off;
}
location ~ ^/users/sessions(/.*)?$ {
proxy_pass http://127.0.0.1:30001;
location /users/ {
proxy_pass http://127.0.0.1:8081;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
}
location ~ ^/users(/.*)?$ {
proxy_pass http://127.0.0.1:30001;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
proxy_set_header X-Forwarded-Port $proxy_x_forwarded_port;
proxy_set_header X-Forwarded-Host $proxy_x_forwarded_host;
}
location ~ ^/version(/.*)?$ {
proxy_pass http://127.0.0.1:30001;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
}
location ~ ^/releases(/.*)?$ {
proxy_pass http://127.0.0.1:30001;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
}
location ~ ^/alerts(/.*)?$ {
proxy_pass http://127.0.0.1:30001;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
}
location ~ ^/alert-rules(/.*)?$ {
proxy_pass http://127.0.0.1:30001;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
}
location ~ ^/notification-channels(/.*)?$ {
proxy_pass http://127.0.0.1:30001;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
}
location ~ ^/alert-firings(/.*)?$ {
proxy_pass http://127.0.0.1:30001;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
}
location ~ ^/rbac(/.*)?$ {
proxy_pass http://127.0.0.1:30001;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
}
location ~ ^/credentials(/.*)?$ {
proxy_pass http://127.0.0.1:30001;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
proxy_connect_timeout 60s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
}
location ~ ^/snippets(/.*)?$ {
proxy_pass http://127.0.0.1:30001;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
}
location ~ ^/vault(/.*)?$ {
proxy_pass http://127.0.0.1:30001;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
}
location ~ ^/termix-id(/.*)?$ {
proxy_pass http://127.0.0.1:30001;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location ~ ^/proxmox(/.*)?$ {
proxy_pass http://127.0.0.1:30001;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
proxy_connect_timeout 60s;
proxy_send_timeout 120s;
proxy_read_timeout 120s;
}
location ~ ^/c2s-tunnel-presets(/.*)?$ {
proxy_pass http://127.0.0.1:30001;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
}
location ~ ^/audit-logs(/.*)?$ {
proxy_pass http://127.0.0.1:30001;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
}
location ~ ^/terminal(/.*)?$ {
proxy_pass http://127.0.0.1:30001;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
}
location ~ ^/open-tabs(/.*)?$ {
proxy_pass http://127.0.0.1:30001;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
}
location ~ ^/user-preferences(/.*)?$ {
proxy_pass http://127.0.0.1:30001;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
}
location ~ ^/database(/.*)?$ {
client_max_body_size 5G;
client_body_timeout 300s;
proxy_pass http://127.0.0.1:30001;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
proxy_connect_timeout 60s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
proxy_request_buffering off;
proxy_buffering off;
}
location ~ ^/db(/.*)?$ {
client_max_body_size 5G;
client_body_timeout 300s;
proxy_pass http://127.0.0.1:30001;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
proxy_connect_timeout 60s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
proxy_request_buffering off;
proxy_buffering off;
}
location ~ ^/encryption(/.*)?$ {
proxy_pass http://127.0.0.1:30001;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
}
location /host/quick-connect {
proxy_pass http://127.0.0.1:30001;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $http_host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
}
location ~ ^/host/opkssh-chooser(/.*)?$ {
proxy_pass http://127.0.0.1:30001/host/opkssh-chooser$1$is_args$args;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Host $proxy_x_forwarded_host;
proxy_set_header X-Forwarded-Port $proxy_x_forwarded_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
proxy_cache_bypass 1;
proxy_no_cache 1;
add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0";
}
location ~ ^/host/opkssh-callback(/.*)?$ {
proxy_pass http://127.0.0.1:30001/host/opkssh-callback$1$is_args$args;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Host $proxy_x_forwarded_host;
proxy_set_header X-Forwarded-Port $proxy_x_forwarded_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
proxy_cache_bypass 1;
proxy_no_cache 1;
add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0";
}
location /host/ {
proxy_pass http://127.0.0.1:30001;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
}
location /session_logs/ {
proxy_pass http://127.0.0.1:30001;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
}
location /tailscale/ {
proxy_pass http://127.0.0.1:30001;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
}
location /ssh/websocket/ {
proxy_pass http://127.0.0.1:30002/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Host $proxy_x_forwarded_host;
proxy_set_header X-Forwarded-Port $proxy_x_forwarded_port;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_read_timeout 86400s;
proxy_send_timeout 86400s;
proxy_connect_timeout 10s;
proxy_buffering off;
proxy_request_buffering off;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503;
}
location ^~ /guacamole/websocket/ {
proxy_pass http://127.0.0.1:30008/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $http_host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
proxy_set_header X-Forwarded-Port $proxy_x_forwarded_port;
proxy_set_header X-Forwarded-Host $proxy_x_forwarded_host;
proxy_read_timeout 86400s;
proxy_send_timeout 86400s;
proxy_connect_timeout 10s;
proxy_buffering off;
proxy_request_buffering off;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503;
}
location ~ ^/guacamole(/.*)?$ {
proxy_pass http://127.0.0.1:30001;
location /ssh/db/ {
proxy_pass http://127.0.0.1:8081;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
proxy_set_header X-Forwarded-Proto $scheme;
}
location /host/tunnel/ {
proxy_pass http://127.0.0.1:30003;
location /ssh/websocket/ {
proxy_pass http://127.0.0.1:8082/;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
proxy_set_header X-Forwarded-Proto $scheme;
}
location /ssh/tunnel/ {
proxy_pass http://127.0.0.1:30003;
proxy_pass http://127.0.0.1:8083;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $http_host;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
proxy_read_timeout 86400s;
proxy_send_timeout 86400s;
proxy_buffering off;
proxy_cache off;
proxy_set_header X-Forwarded-Proto $scheme;
}
location /host/file_manager/recent {
proxy_pass http://127.0.0.1:30001;
location /ssh/config_editor/ {
proxy_pass http://127.0.0.1:8084;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
proxy_set_header X-Forwarded-Proto $scheme;
}
location /host/file_manager/pinned {
proxy_pass http://127.0.0.1:30001;
location ~ ^/ssh/config_editor/(recent|pinned|shortcuts) {
proxy_pass http://127.0.0.1:8081;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
}
location /host/file_manager/shortcuts {
proxy_pass http://127.0.0.1:30001;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
}
location /host/file_manager/sudo-password {
proxy_pass http://127.0.0.1:30004;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
}
location /ssh/file_manager/ {
client_max_body_size 5G;
client_body_timeout 300s;
add_header Cache-Control "no-store, no-cache, must-revalidate" always;
proxy_pass http://127.0.0.1:30004;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
proxy_connect_timeout 60s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
proxy_request_buffering off;
proxy_buffering off;
}
location /host/file_manager/ssh/ {
client_max_body_size 5G;
client_body_timeout 300s;
add_header Cache-Control "no-store, no-cache, must-revalidate" always;
proxy_pass http://127.0.0.1:30004;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
proxy_connect_timeout 60s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
proxy_request_buffering off;
proxy_buffering off;
}
location ~ ^/network-topology(/.*)?$ {
proxy_pass http://127.0.0.1:30001;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
}
location /health {
proxy_pass http://127.0.0.1:30001;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
}
location ~ ^/status(/.*)?$ {
proxy_pass http://127.0.0.1:30005;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
}
location ~ ^/metrics(/.*)?$ {
proxy_pass http://127.0.0.1:30005;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
location ~ ^/(refresh|host-updated)$ {
proxy_pass http://127.0.0.1:30005;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
}
location ~ ^/host-metrics(/.*)?$ {
proxy_pass http://127.0.0.1:30005;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
proxy_connect_timeout 600s;
proxy_send_timeout 600s;
proxy_read_timeout 600s;
}
location ~ ^/global-settings(/.*)?$ {
proxy_pass http://127.0.0.1:30005;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
}
location ~ ^/uptime(/.*)?$ {
proxy_pass http://127.0.0.1:30006;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
}
location ~ ^/activity(/.*)?$ {
proxy_pass http://127.0.0.1:30006;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
}
location ~ ^/service-links(/.*)?$ {
proxy_pass http://127.0.0.1:30006;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
}
location ~ ^/homepage(/.*)?$ {
proxy_pass http://127.0.0.1:30012;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
}
location ^~ /docker/console/ {
proxy_pass http://127.0.0.1:30009/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $http_host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
proxy_set_header X-Forwarded-Port $proxy_x_forwarded_port;
proxy_set_header X-Forwarded-Host $proxy_x_forwarded_host;
proxy_read_timeout 86400s;
proxy_send_timeout 86400s;
proxy_connect_timeout 10s;
proxy_buffering off;
proxy_request_buffering off;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503;
}
# --- tmux-monitor begin ---
location ~ ^/tmux_monitor(/.*)?$ {
proxy_pass http://127.0.0.1:30010;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
proxy_connect_timeout 60s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
}
# --- tmux-monitor end ---
location ~ ^/docker(/.*)?$ {
proxy_pass http://127.0.0.1:30007;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
proxy_connect_timeout 60s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
}
location ^~ /serial/websocket/ {
proxy_pass http://127.0.0.1:30011/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $http_host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
proxy_read_timeout 86400s;
proxy_send_timeout 86400s;
proxy_connect_timeout 10s;
proxy_buffering off;
proxy_request_buffering off;
proxy_set_header X-Forwarded-Proto $scheme;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /app/html;
root /usr/share/nginx/html;
}
}
}
}
-149
View File
@@ -1,149 +0,0 @@
{
"appId": "com.karmaa.termix",
"productName": "Termix",
"publish": null,
"directories": {
"output": "release"
},
"asar": true,
"asarUnpack": [
"dist/backend/**/*",
"node_modules/**/*",
"public/icons/**/*",
"public/icon.*"
],
"files": [
"dist/**/*",
"electron/**/*",
"public/**/*",
"!src/**/*",
"!*.md",
"!tsconfig*.json",
"!vite.config.ts",
"!eslint.config.js",
"!node_modules/@napi-rs/canvas*/**/*",
"!node_modules/@rollup/rollup-darwin-*/**/*",
"!node_modules/@rollup/rollup-linux-*/**/*",
"!node_modules/@rollup/rollup-win32-*/**/*",
"!dist/icon-mac.png",
"!public/icon-mac.png",
"!dist/icon.ico",
"!dist/icon.icns",
"!public/icon.icns"
],
"extraMetadata": {
"main": "electron/main.cjs",
"type": "commonjs"
},
"buildDependenciesFromSource": false,
"nodeGypRebuild": false,
"npmRebuild": true,
"win": {
"target": [
{
"target": "nsis",
"arch": ["x64", "ia32"]
},
{
"target": "msi",
"arch": ["x64", "ia32"]
}
],
"icon": "public/icon.ico",
"executableName": "Termix"
},
"nsis": {
"oneClick": false,
"allowToChangeInstallationDirectory": true,
"artifactName": "termix_windows_${arch}_nsis.${ext}",
"createDesktopShortcut": true,
"createStartMenuShortcut": true,
"installerIcon": "public/icon.ico",
"uninstallerIcon": "public/icon.ico",
"shortcutName": "Termix",
"uninstallDisplayName": "Termix"
},
"msi": {
"artifactName": "termix_windows_${arch}_msi.${ext}"
},
"linux": {
"artifactName": "termix_linux_${arch}_portable.${ext}",
"target": [
{
"target": "AppImage",
"arch": ["x64", "arm64", "armv7l"]
},
{
"target": "deb",
"arch": ["x64", "arm64", "armv7l"]
},
{
"target": "tar.gz",
"arch": ["x64", "arm64", "armv7l"]
}
],
"icon": "public/icon.png",
"category": "Development",
"executableName": "termix",
"maintainer": "Termix <mail@termix.site>",
"desktop": {
"entry": {
"Name": "Termix",
"Comment": "Self-hosted SSH and remote desktop management. ",
"Keywords": "docker;ssh;terminal;telnet;self-hosted;rdp;file-management;vnc;ssh-tunnel;server-stats;termix",
"StartupWMClass": "termix"
}
}
},
"appImage": {
"artifactName": "termix_linux_${arch}_appimage.${ext}"
},
"deb": {
"artifactName": "termix_linux_${arch}_deb.${ext}"
},
"mac": {
"target": [
{
"target": "mas",
"arch": "universal"
},
{
"target": "dmg",
"arch": ["universal", "x64", "arm64"]
}
],
"icon": "public/icon.icns",
"category": "public.app-category.developer-tools",
"hardenedRuntime": true,
"gatekeeperAssess": false,
"entitlements": "build/entitlements.mac.plist",
"entitlementsInherit": "build/entitlements.mac.inherit.plist",
"type": "distribution",
"minimumSystemVersion": "10.15",
"mergeASARs": false,
"singleArchFiles": "**/*.{node,bare}",
"x64ArchFiles": "**/*.{node,bare}"
},
"dmg": {
"artifactName": "termix_macos_${arch}_dmg.${ext}",
"sign": true
},
"afterPack": "build/after-pack.cjs",
"afterSign": "build/notarize.cjs",
"mas": {
"provisioningProfile": "build/Termix_Mac_App_Store.provisionprofile",
"entitlements": "build/entitlements.mas.plist",
"entitlementsInherit": "build/entitlements.mas.inherit.plist",
"hardenedRuntime": false,
"gatekeeperAssess": false,
"type": "distribution",
"category": "public.app-category.developer-tools",
"artifactName": "termix_macos_${arch}_mas.${ext}",
"extendInfo": {
"ITSAppUsesNonExemptEncryption": false,
"NSAppleEventsUsageDescription": "Termix needs access to control other applications for terminal operations."
}
},
"generateUpdatesFilesForAllChannels": true
}
-3010
View File
File diff suppressed because it is too large Load Diff
-77
View File
@@ -1,77 +0,0 @@
const { contextBridge, ipcRenderer } = require("electron");
contextBridge.exposeInMainWorld("electronAPI", {
getAppVersion: () => ipcRenderer.invoke("get-app-version"),
removeAllListeners: (channel) => ipcRenderer.removeAllListeners(channel),
isElectron: true,
isDev: process.env.NODE_ENV === "development",
getSetting: (key) => ipcRenderer.invoke("get-setting", key),
setSetting: (key, value) => ipcRenderer.invoke("set-setting", key, value),
getC2STunnelConfig: () => ipcRenderer.invoke("get-c2s-tunnel-config"),
saveC2STunnelConfig: (config) =>
ipcRenderer.invoke("save-c2s-tunnel-config", config),
checkLocalPortAvailable: (host, port) =>
ipcRenderer.invoke("check-local-port-available", host, port),
getC2STunnelPresetDefaultName: () =>
ipcRenderer.invoke("get-c2s-tunnel-preset-default-name"),
startC2STunnel: (tunnel, index) =>
ipcRenderer.invoke("start-c2s-tunnel", tunnel, index),
testC2STunnel: (tunnel, index) =>
ipcRenderer.invoke("test-c2s-tunnel", tunnel, index),
stopC2STunnel: (tunnelName) =>
ipcRenderer.invoke("stop-c2s-tunnel", tunnelName),
getC2STunnelStatuses: () => ipcRenderer.invoke("get-c2s-tunnel-statuses"),
onC2STunnelStatuses: (callback) => {
const listener = (_event, statuses) => callback(statuses);
ipcRenderer.on("c2s-tunnel-statuses", listener);
return () => ipcRenderer.removeListener("c2s-tunnel-statuses", listener);
},
startC2SAutoStartTunnels: () =>
ipcRenderer.invoke("start-c2s-autostart-tunnels"),
clearSessionCookies: () => ipcRenderer.invoke("clear-session-cookies"),
getSessionCookie: (name, targetUrl) =>
ipcRenderer.invoke("get-session-cookie", name, targetUrl),
waitForSessionCookie: (name, targetUrl, previousValue, timeoutMs) =>
ipcRenderer.invoke(
"wait-session-cookie",
name,
targetUrl,
previousValue,
timeoutMs,
),
oidcSystemBrowserAuth: (authUrl, callbackPort) =>
ipcRenderer.invoke("oidc-system-browser-auth", authUrl, callbackPort),
openExternalEditor: (fileData) =>
ipcRenderer.invoke("open-external-editor", fileData),
closeExternalEditor: (editId) =>
ipcRenderer.invoke("close-external-editor", editId),
onExternalEditorSaved: (callback) => {
const listener = (_event, payload) => callback(payload);
ipcRenderer.on("external-editor-saved", listener);
return () => ipcRenderer.removeListener("external-editor-saved", listener);
},
showSaveDialog: (options) => ipcRenderer.invoke("show-save-dialog", options),
showOpenDialog: (options) => ipcRenderer.invoke("show-open-dialog", options),
createTempFile: (fileData) =>
ipcRenderer.invoke("create-temp-file", fileData),
createTempFolder: (folderData) =>
ipcRenderer.invoke("create-temp-folder", folderData),
startDragToDesktop: (dragData) =>
ipcRenderer.invoke("start-drag-to-desktop", dragData),
cleanupTempFile: (tempId) => ipcRenderer.invoke("cleanup-temp-file", tempId),
invoke: (channel, ...args) => ipcRenderer.invoke(channel, ...args),
});
contextBridge.exposeInMainWorld("electronClipboard", {
writeText: (text) => ipcRenderer.invoke("clipboard-write-text", text),
readText: () => ipcRenderer.invoke("clipboard-read-text"),
});
window.IS_ELECTRON = true;
+23
View File
@@ -0,0 +1,23 @@
import js from '@eslint/js'
import globals from 'globals'
import reactHooks from 'eslint-plugin-react-hooks'
import reactRefresh from 'eslint-plugin-react-refresh'
import tseslint from 'typescript-eslint'
import { globalIgnores } from 'eslint/config'
export default tseslint.config([
globalIgnores(['dist']),
{
files: ['**/*.{ts,tsx}'],
extends: [
js.configs.recommended,
tseslint.configs.recommended,
reactHooks.configs['recommended-latest'],
reactRefresh.configs.vite,
],
languageOptions: {
ecmaVersion: 2020,
globals: globals.browser,
},
},
])
-49
View File
@@ -1,49 +0,0 @@
import js from "@eslint/js";
import globals from "globals";
import reactHooks from "eslint-plugin-react-hooks";
import reactRefresh from "eslint-plugin-react-refresh";
import unusedImports from "eslint-plugin-unused-imports";
import tseslint from "typescript-eslint";
import { globalIgnores } from "eslint/config";
export default tseslint.config([
globalIgnores(["dist", "release", "Mobile", "src/mcp-server/node_modules"]),
{
files: ["**/*.{ts,tsx}"],
extends: [
js.configs.recommended,
tseslint.configs.recommended,
reactRefresh.configs.vite,
],
plugins: {
"react-hooks": reactHooks,
"unused-imports": unusedImports,
},
languageOptions: {
ecmaVersion: 2020,
globals: globals.browser,
},
rules: {
"unused-imports/no-unused-imports": "error",
"unused-imports/no-unused-vars": [
"warn",
{
vars: "all",
varsIgnorePattern: "^_",
args: "after-used",
argsIgnorePattern: "^_",
},
],
"@typescript-eslint/no-unused-vars": "off",
"@typescript-eslint/no-explicit-any": "warn",
"@typescript-eslint/no-unused-expressions": "warn",
"no-empty": "warn",
"no-control-regex": "off",
"no-useless-assignment": "off",
"preserve-caught-error": "off",
"react-hooks/exhaustive-deps": "warn",
"react-hooks/rules-of-hooks": "error",
"react-refresh/only-export-components": "warn",
},
},
]);
-11
View File
@@ -1,11 +0,0 @@
[Desktop Entry]
Name=Termix
Comment=Self-hosted SSH and remote desktop management.
Exec=run.sh %U
Icon=com.karmaa.termix
Terminal=false
Type=Application
Categories=Development;Network;System;
Keywords=ssh;terminal;server;management;tunnel;
StartupWMClass=termix
StartupNotify=true
-11
View File
@@ -1,11 +0,0 @@
[Flatpak Ref]
Name=Termix
Branch=stable
Title=Termix - SSH Server Management Platform
IsRuntime=false
Url=https://github.com/Termix-SSH/Termix/releases/download/VERSION_PLACEHOLDER/termix_linux_flatpak.flatpak
RuntimeRepo=https://flathub.org/repo/flathub.flatpakrepo
Comment=Self-hosted SSH and remote desktop management.
Description=Termix is an open-source, forever-free, self-hosted all-in-one server management platform. It provides a multi-platform solution for managing your servers and infrastructure through a single, intuitive interface. Termix offers SSH terminal access, remote desktop control (RDP, VNC, Telnet), SSH tunneling capabilities, remote file management, and many other tools. Termix is the perfect free and self-hosted alternative to Termius available for all platforms.
Icon=https://raw.githubusercontent.com/Termix-SSH/Termix/main/public/icon.png
Homepage=https://github.com/Termix-SSH/Termix
-77
View File
@@ -1,77 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<component type="desktop-application">
<id>com.karmaa.termix</id>
<name>Termix</name>
<summary>Self-hosted SSH and remote desktop management.</summary>
<metadata_license>CC0-1.0</metadata_license>
<project_license>Apache-2.0</project_license>
<developer_name>bugattiguy527</developer_name>
<description>
<p>
Termix is an open-source, forever-free, self-hosted all-in-one server management platform. It provides a
multi-platform solution for managing your servers and infrastructure through a single, intuitive interface.
Termix offers SSH terminal access, remote desktop control (RDP, VNC, Telnet), SSH tunneling capabilities,
remote file management, and many other tools. Termix is the perfect free and self-hosted alternative to
Termius available for all platforms.
</p>
</description>
<launchable type="desktop-id">com.karmaa.termix.desktop</launchable>
<screenshots>
<screenshot type="default">
<image>https://raw.githubusercontent.com/Termix-SSH/Termix/main/public/screenshots/terminal.png</image>
<caption>SSH Terminal Interface</caption>
</screenshot>
</screenshots>
<url type="homepage">https://github.com/Termix-SSH/Termix</url>
<url type="bugtracker">https://github.com/Termix-SSH/Support/issues</url>
<url type="help">https://docs.termix.site</url>
<url type="vcs-browser">https://github.com/Termix-SSH/Termix</url>
<content_rating type="oars-1.1">
<content_attribute id="social-info">moderate</content_attribute>
</content_rating>
<releases>
<release version="VERSION_PLACEHOLDER" date="DATE_PLACEHOLDER">
<description>
<p>Latest release of Termix</p>
</description>
<url>https://github.com/Termix-SSH/Termix/releases</url>
</release>
</releases>
<categories>
<category>Development</category>
<category>Network</category>
<category>System</category>
</categories>
<keywords>
<keyword>docker</keyword>
<keyword>ssh</keyword>
<keyword>terminal</keyword>
<keyword>telnet</keyword>
<keyword>self-hosted</keyword>
<keyword>rdp</keyword>
<keyword>file-management</keyword>
<keyword>vnc</keyword>
<keyword>ssh-tunnel</keyword>
<keyword>server-stats</keyword>
<keyword>termix</keyword>
</keywords>
<provides>
<binary>termix</binary>
</provides>
<requires>
<internet>always</internet>
</requires>
</component>
-88
View File
@@ -1,88 +0,0 @@
app-id: com.karmaa.termix
runtime: org.freedesktop.Platform
runtime-version: "24.08"
sdk: org.freedesktop.Sdk
base: org.electronjs.Electron2.BaseApp
base-version: "24.08"
command: run.sh
separate-locales: false
finish-args:
- --socket=x11
- --socket=wayland
- --socket=pulseaudio
- --share=network
- --share=ipc
- --device=dri
- --filesystem=home
- --socket=ssh-auth
- --socket=session-bus
- --talk-name=org.freedesktop.secrets
- --talk-name=org.freedesktop.portal.Desktop
- --env=ELECTRON_TRASH=gio
- --env=XCURSOR_PATH=/run/host/user-share/icons:/run/host/share/icons
- --env=ELECTRON_OZONE_PLATFORM_HINT=auto
modules:
- name: termix
buildsystem: simple
build-commands:
- chmod +x termix.AppImage
- ./termix.AppImage --appimage-extract
- install -Dm755 squashfs-root/termix /app/bin/termix
- cp -r squashfs-root/resources /app/bin/
- cp -r squashfs-root/locales /app/bin/ || true
- cp squashfs-root/*.so /app/bin/ || true
- cp squashfs-root/*.pak /app/bin/ || true
- cp squashfs-root/*.bin /app/bin/ || true
- cp squashfs-root/*.dat /app/bin/ || true
- cp squashfs-root/*.json /app/bin/ || true
- |
cat > run.sh << 'EOF'
#!/bin/bash
export TMPDIR="$XDG_RUNTIME_DIR/app/$FLATPAK_ID"
exec zypak-wrapper /app/bin/termix "$@"
EOF
- chmod +x run.sh
- install -Dm755 run.sh /app/bin/run.sh
- install -Dm644 com.karmaa.termix.desktop /app/share/applications/com.karmaa.termix.desktop
- install -Dm644 com.karmaa.termix.metainfo.xml /app/share/metainfo/com.karmaa.termix.metainfo.xml
- install -Dm644 com.karmaa.termix.svg /app/share/icons/hicolor/scalable/apps/com.karmaa.termix.svg
- install -Dm644 icon-256.png /app/share/icons/hicolor/256x256/apps/com.karmaa.termix.png || true
- install -Dm644 icon-128.png /app/share/icons/hicolor/128x128/apps/com.karmaa.termix.png || true
sources:
- type: file
url: https://github.com/Termix-SSH/Termix/releases/download/release-VERSION_PLACEHOLDER-tag/termix_linux_x64_appimage.AppImage
sha256: CHECKSUM_X64_PLACEHOLDER
dest-filename: termix.AppImage
only-arches:
- x86_64
- type: file
url: https://github.com/Termix-SSH/Termix/releases/download/release-VERSION_PLACEHOLDER-tag/termix_linux_arm64_appimage.AppImage
sha256: CHECKSUM_ARM64_PLACEHOLDER
dest-filename: termix.AppImage
only-arches:
- aarch64
- type: file
path: com.karmaa.termix.desktop
- type: file
path: com.karmaa.termix.metainfo.xml
- type: file
path: com.karmaa.termix.svg
- type: file
path: icon-256.png
- type: file
path: icon-128.png
-5
View File
@@ -1,5 +0,0 @@
{
"only-arches": ["x86_64", "aarch64"],
"skip-icons-check": false,
"skip-appstream-check": false
}
+1 -44
View File
@@ -2,54 +2,11 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="favicon.ico" />
<link rel="icon" type="image/svg+xml" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="theme-color" content="#09090b" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta
name="apple-mobile-web-app-status-bar-style"
content="black-translucent"
/>
<meta name="apple-mobile-web-app-title" content="Termix" />
<link rel="apple-touch-icon" href="icons/512x512.png" />
<link rel="manifest" href="manifest.json" />
<title>Termix</title>
<style>
.hide-scrollbar {
scrollbar-width: none;
-ms-overflow-style: none;
}
.hide-scrollbar::-webkit-scrollbar {
display: none;
}
.skinny-scrollbar {
scrollbar-width: thin;
scrollbar-color: #4a4a4a #1e1e21;
}
.skinny-scrollbar::-webkit-scrollbar {
width: 6px;
height: 6px;
}
.skinny-scrollbar::-webkit-scrollbar-track {
background: #1e1e21;
}
.skinny-scrollbar::-webkit-scrollbar-thumb {
background-color: #4a4a4a;
border-radius: 3px;
border: 1px solid #1e1e21;
}
</style>
</head>
<body>
<script>
window.__TERMIX_BASE_PATH__ = "";
</script>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
-98
View File
@@ -1,98 +0,0 @@
{
"$schema": "https://unpkg.com/knip@latest/schema.json",
"entry": [
"src/backend/starter.ts",
"src/backend/swagger.ts",
"scripts/**/*.cjs"
],
"project": ["src/**/*.{ts,tsx}", "electron/**/*.cjs", "scripts/**/*.cjs"],
"ignoreBinaries": ["powershell"],
"ignoreDependencies": [
"@codemirror/autocomplete",
"@codemirror/commands",
"@codemirror/search",
"@codemirror/theme-one-dark",
"@codemirror/view",
"@electron/notarize",
"@monaco-editor/react",
"@radix-ui/react-accordion",
"@radix-ui/react-alert-dialog",
"@radix-ui/react-checkbox",
"@radix-ui/react-dialog",
"@radix-ui/react-dropdown-menu",
"@radix-ui/react-label",
"@radix-ui/react-popover",
"@radix-ui/react-progress",
"@radix-ui/react-scroll-area",
"@radix-ui/react-select",
"@radix-ui/react-separator",
"@radix-ui/react-slider",
"@radix-ui/react-slot",
"@radix-ui/react-switch",
"@radix-ui/react-tabs",
"@radix-ui/react-tooltip",
"@types/better-sqlite3",
"@types/cookie-parser",
"@types/cors",
"@types/express",
"@types/guacamole-common-js",
"@types/js-yaml",
"@types/jsonwebtoken",
"@types/multer",
"@types/qrcode",
"@types/speakeasy",
"@types/ssh2",
"@uiw/codemirror-extensions-langs",
"@uiw/codemirror-theme-github",
"@uiw/react-codemirror",
"@xterm/addon-clipboard",
"@xterm/addon-fit",
"@xterm/addon-unicode11",
"@xterm/addon-web-links",
"@xterm/xterm",
"axios",
"bcryptjs",
"better-sqlite3",
"body-parser",
"chalk",
"class-variance-authority",
"clsx",
"cmdk",
"cookie-parser",
"cors",
"cytoscape",
"drizzle-orm",
"express",
"guacamole-lite",
"guacamole-common-js",
"jose",
"js-yaml",
"jsonwebtoken",
"jszip",
"multer",
"nanoid",
"qrcode",
"i18next-browser-languagedetector",
"lucide-react",
"motion",
"radix-ui",
"react-cytoscapejs",
"react-h5-audio-player",
"react-hook-form",
"react-icons",
"react-markdown",
"react-pdf",
"react-photo-view",
"react-syntax-highlighter",
"react-xtermjs",
"remark-gfm",
"socks",
"speakeasy",
"ssh2",
"undici",
"husky",
"sharp",
"sonner",
"tailwind-merge"
]
}
+2898 -12764
View File
File diff suppressed because it is too large Load Diff
+81 -194
View File
@@ -1,207 +1,94 @@
{
"name": "termix",
"private": true,
"version": "2.5.0",
"description": "Self-hosted SSH and remote desktop management.",
"author": "Karmaa",
"main": "electron/main.cjs",
"engines": {
"node": ">=22.12.0",
"npm": ">=11"
},
"version": "0.0.0",
"type": "module",
"scripts": {
"format": "prettier --write .",
"format:check": "prettier --check .",
"biome:check": "biome check biome.json package.json",
"biome:fix": "biome check --write biome.json package.json",
"postinstall": "node scripts/patch-app-builder-lib.cjs && node scripts/patch-guacamole-lite.cjs && node scripts/patch-better-sqlite3.cjs && node scripts/patch-nan.cjs && node scripts/patch-xterm-android-ime.cjs",
"prebuild": "node scripts/write-electron-build-info.cjs",
"lint": "eslint .",
"lint:fix": "eslint --fix .",
"type-check": "tsc --noEmit",
"test": "vitest run",
"test:watch": "vitest",
"test:ui": "vitest --ui",
"test:coverage": "vitest run --coverage",
"dev": "vite",
"build": "vite build && tsc -p tsconfig.node.json && node -e \"require('fs').copyFileSync('src/backend/package.json','dist/backend/package.json')\"",
"build:backend": "tsc -p tsconfig.node.json && node -e \"require('fs').copyFileSync('src/backend/package.json','dist/backend/package.json')\"",
"dev:backend": "tsc -p tsconfig.node.json && node -e \"require('fs').copyFileSync('src/backend/package.json','dist/backend/package.json')\" && node ./dist/backend/backend/starter.js",
"dev:docker": "docker stop termix-dev 2>nul & docker rm termix-dev 2>nul & docker build -f docker/Dockerfile -t termix:dev --no-cache . && docker run -d --name termix-dev -p 3000:3000 -p 8080:8080 -p 30001-30006:30001-30006 -v \"%cd%\\db\\data:/app/data\" termix:dev",
"dev:docker:restart": "docker stop termix-dev 2>nul & docker rm termix-dev 2>nul & docker run -d --name termix-dev -p 8080:8080 -p 30001-30006:30001-30006 -v \"%cd%\\db\\data:/app/data\" termix:dev",
"generate:openapi": "tsc -p tsconfig.node.json && node -e \"require('fs').copyFileSync('src/backend/package.json','dist/backend/package.json')\" && node ./dist/backend/backend/swagger.js",
"preview": "vite preview",
"electron:dev": "concurrently \"npm run dev\" \"powershell -c \\\"Start-Sleep -Seconds 5\\\" && electron .\"",
"electron:patch-builder": "node scripts/patch-app-builder-lib.cjs",
"electron:rebuild": "electron-rebuild -f -w better-sqlite3 -w serialport",
"build:win-portable": "npm run build && npm run electron:rebuild && npm run electron:patch-builder && electron-builder --win --dir",
"build:win-installer": "npm run build && npm run electron:rebuild && npm run electron:patch-builder && electron-builder --win --publish=never",
"build:linux-portable": "npm run build && npm run electron:rebuild && npm run electron:patch-builder && electron-builder --linux --dir",
"build:linux-appimage": "npm run build && npm run electron:rebuild && npm run electron:patch-builder && electron-builder --linux AppImage",
"build:linux-targz": "npm run build && npm run electron:rebuild && npm run electron:patch-builder && electron-builder --linux tar.gz",
"build:mac": "npm run build && npm run electron:rebuild && npm run electron:patch-builder && electron-builder --mac --universal",
"build:mac-dev": "npm run build && npm run electron:rebuild && npm run electron:patch-builder && electron-builder --mac dir --publish=never"
"build": "vite build",
"build:backend": "tsc -p tsconfig.node.json",
"dev:backend": "tsc -p tsconfig.node.json && node ./dist/backend/starter.js",
"lint": "eslint .",
"preview": "vite preview"
},
"dependencies": {
"@simplewebauthn/browser": "^13.3.0",
"@simplewebauthn/server": "^13.3.2",
"@tanstack/react-virtual": "^3.14.6",
"@types/ldapjs": "^3.0.6",
"axios": "^1.18.1",
"bcryptjs": "^3.0.3",
"better-sqlite3": "^12.11.1",
"body-parser": "^2.3.0",
"chalk": "^5.6.2",
"cookie-parser": "^1.4.7",
"cors": "^2.8.6",
"dotenv": "^17.4.2",
"drizzle-orm": "^0.45.2",
"express": "^5.2.1",
"guacamole-lite": "^1.2.0",
"jose": "^6.2.2",
"js-yaml": "^5.2.1",
"jsonwebtoken": "^9.0.3",
"jszip": "^3.10.1",
"ldapjs": "^3.0.7",
"motion": "^12.42.2",
"multer": "^2.2.0",
"nanoid": "^5.1.16",
"qrcode": "^1.5.4",
"serialport": "^13.0.0",
"socks": "^2.8.7",
"speakeasy": "^2.0.0",
"ssh2": "^1.17.0",
"undici": "^8.7.0",
"ws": "^8.20.0"
},
"devDependencies": {
"@biomejs/biome": "2.5.2",
"@codemirror/autocomplete": "^6.20.3",
"@codemirror/commands": "^6.10.4",
"@codemirror/search": "^6.7.1",
"@codemirror/theme-one-dark": "^6.1.3",
"@codemirror/view": "^6.43.5",
"@commitlint/cli": "^21.0.2",
"@commitlint/config-conventional": "^21.0.2",
"@deadendjs/swagger-jsdoc": "^8.1.2",
"@electron/notarize": "^3.1.1",
"@electron/rebuild": "^4.0.4",
"@eslint/js": "^10.0.1",
"@fontsource-variable/jetbrains-mono": "^5.2.8",
"@fontsource/fira-code": "^5.2.7",
"@fontsource/jetbrains-mono": "^5.2.8",
"@fontsource/source-code-pro": "^5.2.7",
"@monaco-editor/react": "^4.7.0",
"@radix-ui/react-accordion": "^1.2.15",
"@radix-ui/react-alert-dialog": "^1.1.18",
"@radix-ui/react-checkbox": "^1.3.6",
"@radix-ui/react-dialog": "^1.1.18",
"@radix-ui/react-dropdown-menu": "^2.1.19",
"@radix-ui/react-label": "^2.1.11",
"@radix-ui/react-popover": "^1.1.18",
"@radix-ui/react-progress": "^1.1.11",
"@radix-ui/react-scroll-area": "^1.2.13",
"@radix-ui/react-select": "^2.3.2",
"@radix-ui/react-separator": "^1.1.11",
"@radix-ui/react-slider": "^1.4.2",
"@radix-ui/react-slot": "^1.3.0",
"@radix-ui/react-switch": "^1.3.2",
"@radix-ui/react-tabs": "^1.1.16",
"@radix-ui/react-tooltip": "^1.2.11",
"@tailwindcss/vite": "^4.3.2",
"@testing-library/dom": "^10.4.1",
"@testing-library/jest-dom": "^6.9.1",
"@testing-library/react": "^16.3.2",
"@testing-library/user-event": "^14.6.1",
"@types/better-sqlite3": "^7.6.13",
"@types/cookie-parser": "^1.4.10",
"@types/cors": "^2.8.19",
"@types/express": "^5.0.6",
"@types/guacamole-common-js": "^1.5.5",
"@types/js-yaml": "^4.0.9",
"@types/jsonwebtoken": "^9.0.10",
"@types/multer": "^2.1.0",
"@types/node": "^26.0.0",
"@types/qrcode": "^1.5.6",
"@types/react": "^19.2.17",
"@types/react-dom": "^19.2.3",
"@types/speakeasy": "^2.0.10",
"@types/ssh2": "^1.15.5",
"@types/ws": "^8.18.1",
"@uiw/codemirror-extensions-langs": "^4.25.9",
"@uiw/codemirror-theme-github": "^4.25.9",
"@uiw/react-codemirror": "^4.25.9",
"@vitejs/plugin-react": "^6.0.3",
"@vitest/coverage-v8": "^4.1.9",
"@vitest/ui": "^4.1.9",
"@xterm/addon-clipboard": "^0.2.0",
"@xterm/addon-fit": "^0.11.0",
"@xterm/addon-unicode11": "^0.9.0",
"@xterm/addon-web-links": "^0.12.0",
"@xterm/xterm": "^6.0.0",
"@hookform/resolvers": "^5.1.1",
"@radix-ui/react-accordion": "^1.2.11",
"@radix-ui/react-avatar": "^1.1.10",
"@radix-ui/react-checkbox": "^1.3.2",
"@radix-ui/react-collapsible": "^1.1.11",
"@radix-ui/react-dialog": "^1.1.14",
"@radix-ui/react-dropdown-menu": "^2.1.15",
"@radix-ui/react-label": "^2.1.7",
"@radix-ui/react-popover": "^1.1.14",
"@radix-ui/react-scroll-area": "^1.2.9",
"@radix-ui/react-select": "^2.2.5",
"@radix-ui/react-separator": "^1.1.7",
"@radix-ui/react-slider": "^1.3.5",
"@radix-ui/react-slot": "^1.2.3",
"@radix-ui/react-switch": "^1.2.5",
"@radix-ui/react-tabs": "^1.1.12",
"@radix-ui/react-tooltip": "^1.2.7",
"@tailwindcss/vite": "^4.1.11",
"@types/bcryptjs": "^2.4.6",
"@types/multer": "^2.0.0",
"@uiw/codemirror-extensions-hyper-link": "^4.24.1",
"@uiw/codemirror-extensions-langs": "^4.24.1",
"@uiw/codemirror-themes": "^4.24.1",
"@uiw/react-codemirror": "^4.24.1",
"@xterm/addon-attach": "^0.11.0",
"@xterm/addon-clipboard": "^0.1.0",
"@xterm/addon-fit": "^0.10.0",
"@xterm/addon-unicode11": "^0.8.0",
"@xterm/xterm": "^5.5.0",
"axios": "^1.10.0",
"bcryptjs": "^3.0.2",
"better-sqlite3": "^12.2.0",
"chalk": "^4.1.2",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"cmdk": "^1.1.1",
"concurrently": "^10.0.3",
"cytoscape": "^3.34.0",
"electron": "^43.0.0",
"electron-builder": "^26.15.3",
"eslint": "^10.5.0",
"eslint-plugin-react-hooks": "^7.1.1",
"eslint-plugin-react-refresh": "^0.5.3",
"eslint-plugin-unused-imports": "^4.4.1",
"globals": "^17.5.0",
"guacamole-common-js": "^1.5.0",
"husky": "^9.1.7",
"i18next": "^26.3.4",
"i18next-browser-languagedetector": "^8.2.1",
"jsdom": "^29.1.1",
"lint-staged": "^17.0.8",
"lucide-react": "^1.20.0",
"prettier": "3.8.4",
"radix-ui": "^1.6.1",
"react": "^19.2.7",
"react-cytoscapejs": "^2.0.0",
"react-dom": "^19.2.7",
"react-h5-audio-player": "^3.10.2",
"react-hook-form": "^7.79.0",
"react-i18next": "^17.0.4",
"react-icons": "^5.6.0",
"react-markdown": "^10.1.0",
"react-pdf": "^10.4.1",
"react-photo-view": "^1.2.7",
"react-syntax-highlighter": "^16.1.1",
"cookie-parser": "^1.4.7",
"cors": "^2.8.5",
"dotenv": "^17.2.0",
"drizzle-orm": "^0.44.3",
"express": "^5.1.0",
"jsonwebtoken": "^9.0.2",
"lucide-react": "^0.525.0",
"multer": "^2.0.2",
"nanoid": "^5.1.5",
"react": "^19.1.0",
"react-dom": "^19.1.0",
"react-hook-form": "^7.60.0",
"react-resizable-panels": "^3.0.3",
"react-xtermjs": "^1.0.10",
"remark-gfm": "^4.0.1",
"sharp": "^0.35.3",
"sonner": "^2.0.7",
"tailwind-merge": "^3.5.0",
"tailwindcss": "^4.2.4",
"tw-animate-css": "^1.4.0",
"typescript": "~6.0.3",
"typescript-eslint": "^8.61.1",
"vite": "^8.0.16",
"vite-plugin-svgr": "^5.2.0",
"vitest": "^4.1.9"
"ssh2": "^1.16.0",
"tailwind-merge": "^3.3.1",
"tailwindcss": "^4.1.11",
"validator": "^13.15.15",
"ws": "^8.18.3",
"zod": "^4.0.5"
},
"lint-staged": {
"*.{ts,tsx}": [
"eslint --fix",
"prettier --write"
],
"*.{js,jsx}": [
"prettier --write"
],
"*.{json,css,md}": [
"prettier --write"
]
},
"overrides": {
"@electron/asar": "^4.2.0",
"@electron/get": "^5.0.0",
"dompurify": "^3.4.1",
"eslint-visitor-keys": "^4.2.1",
"prebuild-install": "npm:@mmomtchev/prebuild-install@1.0.2",
"rimraf": "file:vendor/rimraf-compat"
"devDependencies": {
"@eslint/js": "^9.30.1",
"@types/better-sqlite3": "^7.6.13",
"@types/cors": "^2.8.19",
"@types/express": "^5.0.3",
"@types/jsonwebtoken": "^9.0.10",
"@types/node": "^24.0.13",
"@types/react": "^19.1.8",
"@types/react-dom": "^19.1.6",
"@types/ssh2": "^1.15.5",
"@types/ws": "^8.18.1",
"@vitejs/plugin-react-swc": "^3.10.2",
"autoprefixer": "^10.4.21",
"eslint": "^9.30.1",
"eslint-plugin-react-hooks": "^5.2.0",
"eslint-plugin-react-refresh": "^0.4.20",
"globals": "^16.3.0",
"ts-node": "^10.9.2",
"tw-animate-css": "^1.3.5",
"typescript": "~5.8.3",
"typescript-eslint": "^8.35.1",
"vite": "^7.0.4"
}
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 221 KiB

Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

+79 -6
View File
File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 383 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 537 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 683 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 938 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.
Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

-40
View File
@@ -1,40 +0,0 @@
{
"name": "Termix",
"short_name": "Termix",
"description": "Self-hosted SSH and remote desktop management.",
"theme_color": "#09090b",
"background_color": "#09090b",
"display": "standalone",
"orientation": "any",
"scope": "./",
"start_url": "./",
"icons": [
{
"src": "./icons/48x48.png",
"sizes": "48x48",
"type": "image/png"
},
{
"src": "./icons/64x64.png",
"sizes": "64x64",
"type": "image/png"
},
{
"src": "./icons/128x128.png",
"sizes": "128x128",
"type": "image/png"
},
{
"src": "./icons/256x256.png",
"sizes": "256x256",
"type": "image/png"
},
{
"src": "./icons/512x512.png",
"sizes": "512x512",
"type": "image/png",
"purpose": "any maskable"
}
],
"categories": ["utilities", "developer", "productivity"]
}
-58128
View File
File diff suppressed because it is too large Load Diff
-97
View File
@@ -1,97 +0,0 @@
const CACHE_NAME = "termix-static-v2";
const BASE_PATH = "__TERMIX_SW_BASE_PATH__";
const STATIC_ASSETS = [
`${BASE_PATH}/favicon.ico`,
`${BASE_PATH}/icons/48x48.png`,
`${BASE_PATH}/icons/128x128.png`,
`${BASE_PATH}/icons/256x256.png`,
`${BASE_PATH}/icons/512x512.png`,
];
self.addEventListener("install", (event) => {
event.waitUntil(
caches
.open(CACHE_NAME)
.then((cache) => {
return cache.addAll(STATIC_ASSETS);
})
.then(() => {
return self.skipWaiting();
}),
);
});
self.addEventListener("activate", (event) => {
event.waitUntil(
caches
.keys()
.then((cacheNames) => {
return Promise.all(
cacheNames
.filter((name) => name !== CACHE_NAME)
.map((name) => {
return caches.delete(name);
}),
);
})
.then(() => {
return self.clients.claim();
}),
);
});
self.addEventListener("fetch", (event) => {
const { request } = event;
const url = new URL(request.url);
if (request.method !== "GET") {
return;
}
if (url.pathname.startsWith("/api/") || url.pathname.startsWith("/ws")) {
return;
}
if (
url.pathname.startsWith("/host/opkssh-chooser/") ||
url.pathname.startsWith("/host/opkssh-callback/")
) {
return;
}
if (url.origin !== self.location.origin) {
return;
}
if (request.mode === "navigate") {
event.respondWith(fetch(request));
return;
}
const isStaticAsset = STATIC_ASSETS.some((asset) => url.pathname === asset);
if (!isStaticAsset) {
return;
}
event.respondWith(
caches.match(request).then((cachedResponse) => {
if (cachedResponse) {
return cachedResponse;
}
return fetch(request).then((response) => {
if (!response || response.status !== 200 || response.type !== "basic") {
return response;
}
const responseClone = response.clone();
caches.open(CACHE_NAME).then((cache) => {
cache.put(request, responseClone);
});
return response;
});
}),
);
});
File diff suppressed because one or more lines are too long
-548
View File
@@ -1,548 +0,0 @@
# Database Layer Refactor Phase 0 Audit
Status: Draft
Branch: `feature/database-layer-refactor`
Purpose: Establish the current database access inventory, domain map, sensitive field map, and first implementation boundaries before changing runtime persistence.
## 1. Scope
Phase 0 does not change runtime behavior.
It produces the evidence needed for the next implementation phases:
- where database access currently happens
- which modules write directly to the database
- which tables belong to which product domains
- which fields are sensitive
- which direct writes are risky under the current in-memory snapshot model
- which domains should move first into repositories
## 2. Current Evidence
Commands used for the initial audit:
```bash
rg -n "getDb\\(|getSqlite\\(|DatabaseSaveTrigger|SimpleDBOps|db\\.\\$client|\\.prepare\\(" src/backend
rg -n "getDb\\(\\)\\.(insert|update|delete)|await db\\.(insert|update|delete)|db\\.(insert|update|delete)|\\.\\$client\\.prepare\\(\\\"(INSERT|UPDATE|DELETE)|\\.prepare\\(\\\"(INSERT|UPDATE|DELETE)|DatabaseSaveTrigger\\.triggerSave|DatabaseSaveTrigger\\.forceSave" src/backend
rg -n "export const .* = sqliteTable\\(" src/backend/database/db/schema.ts
```
High-level findings:
- Database infrastructure is concentrated in `src/backend/database/db/index.ts`.
- Business database access is spread across route modules, SSH modules, utilities, and auth helpers.
- `SimpleDBOps` is not the only write path.
- There are many direct Drizzle writes and raw SQLite writes.
- Some direct writes manually trigger `DatabaseSaveTrigger`; many write paths do not.
- Schema is SQLite-specific through `sqliteTable` and manual `CREATE TABLE IF NOT EXISTS` / `addColumnIfNotExists`.
## 3. Database Access Hotspots
The most database-heavy files by audit hits:
| File | Approx. hits | Notes |
| ----------------------------------------------------- | -----------: | --------------------------------------------------------------- |
| `src/backend/database/db/index.ts` | 75 | database init, schema creation, ad-hoc migration, snapshot save |
| `src/backend/database/routes/alert-rules-routes.ts` | 64 | alert rules, channels, firings, raw SQL deletes |
| `src/backend/database/routes/users.ts` | 54 | users, settings, OIDC/GitHub settings, admin flows |
| `src/backend/database/database.ts` | 27 | import/export, legacy SQLite handling |
| `src/backend/ssh/host-metrics.ts` | 26 | metrics connection and settings reads |
| `src/backend/database/routes/user-settings-routes.ts` | 16 | user settings |
| `src/backend/dashboard.ts` | 15 | dashboard aggregation reads |
| `src/backend/ssh/docker.ts` | 14 | host/credential reads for Docker SSH |
| `src/backend/ssh/managers/health.ts` | 13 | host health checks |
| `src/backend/ssh/alert-engine.ts` | 13 | alert evaluation and firing state |
| `src/backend/utils/user-crypto.ts` | 12 | settings writes for crypto metadata |
| `src/backend/ssh/host-metrics-settings-routes.ts` | 12 | metrics settings |
| `src/backend/ssh/tmux-monitor.ts` | 11 | tmux session tags |
| `src/backend/guacamole/routes.ts` | 11 | Guacamole config/routes |
| `src/backend/database/routes/host.ts` | 10 | host operations and related rows |
This confirms the refactor must be domain-by-domain. A mechanical replacement of `getDb()` would be noisy and unsafe.
## 4. Direct Write Risk Inventory
Under the current architecture, a direct write is risky when it bypasses `SimpleDBOps` and does not trigger `DatabaseSaveTrigger`.
### 4.1 Direct Writes That Need Repository Ownership
These areas perform direct writes and should move behind repositories/services:
| Area | Representative files | Examples |
| --------------------- | ------------------------------------------------------------------ | --------------------------------------------------------------- |
| users/settings/auth | `routes/users.ts`, `utils/auth-manager.ts`, `utils/user-crypto.ts` | sessions, trusted devices, OIDC settings, registration settings |
| RBAC/sharing | `routes/rbac.ts`, `utils/shared-credential-manager.ts` | roles, host access, snippet access, shared credentials |
| hosts/credentials | `routes/host.ts`, `routes/credentials.ts`, `host-resolver.ts` | host access cleanup, credential usage |
| file manager metadata | `host-file-manager-bookmark-routes.ts` | recent, pinned, shortcuts |
| alerts | `alert-rules-routes.ts`, `ssh/alert-engine.ts` | channels, rules, firings |
| metrics | `host-metrics-preferences-routes.ts`, `managers/health.ts` | preferences, health checks, history |
| terminal logs | `terminal-session-manager.ts` | session recording metadata |
| tmux | `tmux-monitor.ts` | tmux session tags |
| import/export | `database/database.ts` | SQLite import and forced save |
| open tabs | `routes/open-tabs.ts` | tab persistence and cleanup |
| API keys | `user-api-key-routes.ts`, `utils/auth-manager.ts` | API key create/delete/last-used |
| SSO and identity | `sso-provider-routes.ts`, `termix-id.ts` | providers, identity keys/CA |
### 4.2 Immediate Compatibility Rule
Until a domain is migrated to repositories:
- Every direct write must either be moved into a repository or explicitly trigger persistence in the old runtime.
- New code should not add direct `getDb()` writes outside infrastructure or repositories.
- The draft branch should add an enforcement check before Phase 8, not immediately, because the current codebase still violates the target rule widely.
## 5. Table Domain Map
### 5.1 Identity and Authentication
| Tables | Notes |
| ---------------------- | -------------------------------------------- |
| `users` | local/OIDC users, TOTP fields, password hash |
| `sessions` | JWT sessions |
| `trusted_devices` | remembered devices |
| `api_keys` | API token hashes/prefixes |
| `sso_providers` | configured SSO providers |
| `termix_identities` | Termix identity records |
| `termix_identity_keys` | public/private identity key metadata |
| `termix_identity_ca` | CA material, private key is sensitive |
Suggested repository:
- `userRepository`
- `sessionRepository`
- `trustedDeviceRepository`
- `apiKeyRepository`
- `ssoProviderRepository`
- `termixIdentityRepository`
### 5.2 Hosts and Credentials
| Tables | Notes |
| ---------------------- | ------------------------------------------------ |
| `ssh_data` | primary host table, many config JSON/text fields |
| `ssh_credentials` | reusable credentials |
| `ssh_credential_usage` | usage history |
| `ssh_folders` | folder metadata |
| `host_access` | sharing/RBAC access rows |
| `shared_credentials` | encrypted shared credential material |
| `network_topology` | topology graph/config |
Suggested repository:
- `hostRepository`
- `credentialRepository`
- `credentialUsageRepository`
- `hostAccessRepository`
- `sharedCredentialRepository`
- `hostFolderRepository`
- `networkTopologyRepository`
### 5.3 RBAC
| Tables | Notes |
| ---------------- | ------------------------ |
| `roles` | role definitions |
| `user_roles` | user to role assignments |
| `host_access` | host-level grants |
| `snippet_access` | snippet-level grants |
Suggested repository:
- `roleRepository`
- `accessRepository`
### 5.4 File Manager
| Tables | Notes |
| ------------------------ | ---------------------------------- |
| `file_manager_recent` | recently opened paths |
| `file_manager_pinned` | pinned paths |
| `file_manager_shortcuts` | saved shortcuts |
| `transfer_recent` | host-to-host transfer destinations |
Suggested repository:
- `fileManagerRepository`
- `transferRecentRepository`
### 5.5 Snippets
| Tables | Notes |
| ----------------- | ----------------------- |
| `snippets` | command snippets |
| `snippet_folders` | snippet folder metadata |
| `snippet_access` | snippet sharing |
Suggested repository:
- `snippetRepository`
### 5.6 Runtime Metadata and Audit
| Tables | Notes |
| -------------------- | ------------------------------------------------------ |
| `audit_logs` | append-only audit trail |
| `session_recordings` | terminal recording metadata, log content is file-based |
| `recent_activity` | host activity feed |
| `command_history` | terminal command history |
| `user_open_tabs` | UI restore state; currently cleared on startup |
| `user_preferences` | per-user UI/preferences |
| `settings` | global settings |
Suggested repository:
- `auditRepository`
- `sessionRecordingRepository`
- `activityRepository`
- `commandHistoryRepository`
- `openTabsRepository`
- `userPreferencesRepository`
- `settingsRepository`
### 5.7 Metrics and Alerts
| Tables | Notes |
| -------------------------- | -------------------------- |
| `host_metrics_preferences` | metrics layout/preferences |
| `host_health_checks` | health check definitions |
| `host_health_history` | health check results |
| `host_metrics_history` | metrics history |
| `alert_rules` | alert definitions |
| `notification_channels` | webhook/ntfy/etc config |
| `alert_rule_channels` | rule/channel joins |
| `alert_firings` | firing/ack state |
| `dismissed_alerts` | dismissed system alerts |
Suggested repository:
- `metricsRepository`
- `healthCheckRepository`
- `alertRepository`
- `notificationRepository`
### 5.8 Integrations and Feature Config
| Tables | Notes |
| ------------------------- | --------------------------------------- |
| `c2s_tunnel_presets` | tunnel preset config |
| `opkssh_tokens` | OPKSSH cert/private key cache |
| `vault_profiles` | Vault profile config, mostly non-secret |
| `vault_tokens` | Vault cert/private key cache |
| `dashboard_service_links` | dashboard links |
| `homepage_items` | homepage widgets/items |
| `homepage_layouts` | homepage layouts |
| `tmux_session_tags` | tmux tag metadata |
Suggested repository:
- `tunnelPresetRepository`
- `opksshTokenRepository`
- `vaultRepository`
- `dashboardRepository`
- `homepageRepository`
- `tmuxRepository`
## 6. Sensitive Field Map
The current explicit `FieldCrypto` map encrypts:
| Table | Fields |
| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `users` | `passwordHash`, `clientSecret`, `totpSecret`, `totpBackupCodes`, `oidcIdentifier` |
| `ssh_data` | `password`, `key`, `keyPassword`, `sudoPassword`, `autostartPassword`, `autostartKey`, `autostartKeyPassword`, `socks5Password`, `rdpPassword`, `vncPassword`, `telnetPassword` |
| `ssh_credentials` | `password`, `privateKey`, `keyPassword`, `key`, `publicKey` |
| `opkssh_tokens` | `sshCert`, `privateKey` |
| `termix_identity_ca` | `privateKey` |
| `vault_tokens` | `sshCert`, `privateKey` |
Additional sensitive fields by table semantics:
| Table | Fields / reason |
| ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `ssh_credentials` | `systemPassword`, `systemKey`, `systemKeyPassword` are system-key encrypted credential copies |
| `shared_credentials` | `encryptedUsername`, `encryptedAuthType`, `encryptedPassword`, `encryptedKey`, `encryptedKeyPassword`, `encryptedKeyType` are already encrypted payload fields |
| `api_keys` | `tokenHash` is not plaintext but is authentication material; `tokenPrefix` may remain plaintext for display |
| `settings` | some keys may hold provider secrets or reset codes; repository must classify by key |
| `notification_channels` | config may include webhook URLs/tokens; treat config as sensitive unless split |
| `alert_rules` | rule definitions are usually not secret but can include host/resource metadata |
| `homepage_items` | widget config can include URLs/API config; classify per widget type |
| `c2s_tunnel_presets` | config can include connection details; review before plaintext external DB storage |
| `termix_identity_keys` | inspect key material fields before migration; public keys are not secret but private material must never be plaintext |
| `vault_profiles` | current comments say profile fields are non-secret; keep that invariant explicit |
Open privacy decision:
- `ssh_data.ip`, domain fields, usernames, folders, and tags are queryable today.
- Encrypting them improves confidentiality but breaks search/filter/sort unless blind indexes are added.
- Recommended initial migration: keep them plaintext and document privacy implications; add optional privacy mode later.
## 7. Repository Migration Order
Use a vertical slice instead of broad replacement.
### 7.1 First Slice
1. `settingsRepository`
2. `userRepository`
3. `sessionRepository`
4. `hostRepository`
5. `credentialRepository`
Reasons:
- Covers the app's boot/login/core host management path.
- Exercises field encryption.
- Exercises per-user data unlock requirements.
- Exercises transaction and migration behavior.
- Builds reusable patterns for the rest of the backend.
### 7.2 Second Slice
1. `hostAccessRepository`
2. `roleRepository`
3. `sharedCredentialRepository`
4. `auditRepository`
5. `userPreferencesRepository`
Reasons:
- Completes permission and sharing boundaries.
- Removes high-risk direct writes in admin/RBAC flows.
- Moves audit to an append-only repository.
### 7.3 Third Slice
1. `snippetRepository`
2. `fileManagerRepository`
3. `metricsRepository`
4. `alertRepository`
5. `homepageRepository`
Reasons:
- These are broad feature domains with many routes.
- They should reuse patterns from the core slices.
### 7.4 Fourth Slice
1. `vaultRepository`
2. `opksshTokenRepository`
3. `termixIdentityRepository`
4. `tunnelPresetRepository`
5. `tmuxRepository`
Reasons:
- Sensitive token/key cache domains need careful encryption tests.
- Some data is transient and should have retention cleanup.
## 8. Adapter Design Notes
The adapter boundary should expose:
```ts
interface DatabaseAdapter {
dialect: "sqlite" | "postgres" | "mysql";
connect(): Promise<void>;
close(): Promise<void>;
migrate(): Promise<void>;
transaction<T>(fn: (tx: DatabaseTransaction) => Promise<T>): Promise<T>;
}
```
The repository layer should not depend on `better-sqlite3`.
For Drizzle, likely options:
- keep dialect-specific Drizzle clients internally
- expose repositories instead of exposing the raw Drizzle client
- keep schema definitions close to migrations, not route handlers
Important: do not make route modules import dialect-specific schema objects after migration.
## 9. Compatibility Shims
During the migration, avoid a flag day.
Add a compatibility database module that lets old code continue to run while new repositories are introduced:
```text
legacy getDb() path
new adapter/repository path
```
Rules:
- New modules use repositories only.
- Migrated modules must not fall back to `getDb()`.
- Legacy path is removed only after all domains move.
## 10. Phase 1 Entry Criteria
Before implementing the adapter skeleton:
- This audit document exists.
- The sensitive field map is reviewed.
- The first vertical slice is accepted.
- The draft PR remains draft.
- No runtime behavior has changed.
## 11. Phase 1 Deliverables
Recommended first implementation PR on this branch:
- `src/backend/database/runtime/config.ts`
- `src/backend/database/runtime/adapter.ts`
- `src/backend/database/runtime/sqlite-adapter.ts`
- `src/backend/database/repositories/settings-repository.ts`
- `src/backend/database/repositories/user-repository.ts`
- `src/backend/database/repositories/session-repository.ts`
- `src/backend/database/repositories/host-repository.ts`
- `src/backend/database/repositories/credential-repository.ts`
- `src/backend/database/repositories/field-encryption-boundary.ts`
- `src/backend/database/repositories/current-settings-repository.ts`
- tests for config parsing and SQLite adapter boot
Started:
- runtime config parser
- SQLite adapter skeleton
- migration metadata table bootstrap
- `SettingsRepository` skeleton and tests
- `UserRepository` and `SessionRepository` skeletons and tests
- `HostRepository` and `CredentialRepository` skeletons and tests
- `FieldEncryptionBoundary` skeleton and tests
- first settings route slice wired through `SettingsRepository`
- user settings route direct `settings` table access moved behind
`SettingsRepository`
- host metrics settings route direct `settings` table access moved behind
`SettingsRepository`
- ACME SSL settings route direct `settings` table access moved behind
`SettingsRepository`
- terminal route direct `settings` table access moved behind
`SettingsRepository`
- tailscale route direct `settings` table access moved behind
`SettingsRepository`
- Guacamole route and WebSocket server direct `settings` table access moved
behind the current settings repository boundary
- auth token expiry and terminal session timeout settings reads moved behind the
current settings repository boundary
- open tabs, TOTP, and LDAP auth route settings reads moved behind the current
settings repository boundary
- host metrics polling settings reads moved behind the current settings
repository boundary
- backend startup settings reads moved behind the current settings repository
boundary
- user deletion cleanup now removes per-user settings through
`SettingsRepository.deleteLike`
- password reset route reset code and temporary token settings access moved
behind `SettingsRepository`
- OIDC utility legacy config fallback reads `oidc_config` through
`SettingsRepository`
- user route registration/password flags and OIDC config administration moved
behind the current settings repository boundary
- OIDC authorize/callback temporary state and auto-provision reads moved behind
the current settings repository boundary
- user login settings reads moved behind the current settings repository
boundary, completing direct `settings` access cleanup in `routes/users.ts`
- user encryption metadata in `utils/user-crypto.ts` moved behind the current
settings repository boundary
- database startup and schema migration defaults in `database/db/index.ts`
moved to local raw settings helpers
- database import/export settings handling in `database/database.ts` moved to
local helper boundaries
- core `auth-manager.ts` session create/read/update/revoke/list paths started
using the current session repository boundary
- remaining `auth-manager.ts` session cleanup/middleware/logout paths and
`user-session-routes.ts` single-session lookup moved behind the current
session repository boundary
- current user repository factory/write-save hook added, and
`user-admin-routes.ts` list/admin promotion/admin removal/admin-create user
paths moved behind the current user repository boundary
- low-risk `routes/users.ts` current-user lookup and admin gate checks moved
behind the current user repository boundary
- user registration, self-delete, password change hash updates, and admin
delete-user lookup paths in `routes/users.ts` moved behind the current user
repository boundary, with first-user admin creation kept transactional inside
`UserRepository`
- traditional login username lookup and `auth-manager.ts` admin user checks
moved behind the current user repository boundary
- GitHub and standard OIDC callback user lookup/create/rollback/profile/admin
sync writes moved behind the current user repository boundary, removing direct
Drizzle `users` table access from `routes/users.ts`, `user-admin-routes.ts`,
and `auth-manager.ts`
- API key create/list/delete and API key authentication last-used updates moved
behind the current API key repository boundary
- trusted device check/add/remove and TOTP trusted-device cleanup moved behind
the current trusted device repository boundary
- user session routes moved user/admin lookups and admin session username
enrichment behind the current user repository boundary
- vault admin checks, Termix ID audit username lookup, permission manager admin
checks, and user data export user lookup moved behind the current user
repository boundary
- SSH credential OIDC username expansion and tmux monitor audit actor username
lookup moved behind the current user repository boundary
- user settings route admin checks and audit actor username lookups moved behind
the current user repository boundary
- ACME SSL route admin checks and audit actor username lookups moved behind the
current user repository boundary
- audit log route admin checks moved behind the current user repository boundary
- OIDC account link/unlink route user lookups and OIDC field updates moved
behind the current user repository boundary
- password reset route user lookups, password hash updates, and TOTP reset
fields moved behind the current user repository boundary
- user deletion helper now removes sessions through the current session
repository and the final user record through the current user repository
- snippet create/update/delete audit actor username lookups moved behind the
current user repository boundary
- LDAP login existing-user lookup, encryption rollback delete, admin sync, and
display-name sync moved behind the current user repository boundary
- TOTP setup/enable/disable/backup-code/login verification user updates and
session revocation moved behind the current user/session repository
boundaries
- RBAC host sharing, role assignment, and snippet sharing target-user existence
checks moved behind the current user repository boundary, with existing
RBAC/snippet owner username joins retained
- RBAC role list/create/update/delete, user-role assignment/removal/listing,
and shared host/snippet role-id lookups moved behind the current role
repository boundary, with existing RBAC/share credential joins retained
- permission manager role permission aggregation, role-id lookups for shared
host access, and admin role checks moved behind the current role repository
boundary
- RBAC host/snippet access-list read models moved behind the current RBAC access
repository boundary, and snippet route shared-access role-id lookups moved
behind the current role repository boundary
- RBAC shared host/shared snippet read models and the main snippet
shared-snippet read model moved behind the current RBAC access repository
boundary
- RBAC host/snippet access grant, revoke, and direct host-access credential
override writes moved behind the current RBAC access repository boundary,
with shared credential material creation retained in the existing manager
- permission manager host-access expiration cleanup, shared host-access lookup,
and last-access timestamp updates moved behind the current RBAC access
repository boundary
- repository rollout guard added through `DATABASE_LAYER_REPOSITORY_ROLLOUT`
for the migrated settings/users/sessions/API-key/trusted-device/role/RBAC-access
slice
Keep it small. Do not wire host or credential routes into the new repositories in
the same first implementation commit.
## 12. Current Unknowns
- Exact Drizzle multi-dialect strategy needs a spike.
- The project may need a migration generator or a custom migration runner.
- Some raw SQL in `routes/users.ts`, `alert-rules-routes.ts`, and `db/index.ts` must be rewritten or isolated.
- `settings` contains mixed public and sensitive values; key-level classification is required.
- `homepage_items.config`, `notification_channels.config`, and tunnel configs may contain embedded secrets.
- Legacy encrypted snapshot fixtures need to be created before migration implementation.
## 13. Decision Log
- Default upgrade target should be persistent SQLite, not PostgreSQL/MySQL.
- PostgreSQL/MySQL migration should be explicit and initially manual/experimental.
- Runtime SSH/WebSocket/tunnel state remains memory-only.
- Field-level encryption is mandatory for every database backend.
- Field-level encryption must use a stable record id; temporary encryption
contexts are forbidden for newly written repository data.
- Repository migration should start with settings/users/sessions/hosts/credentials.
File diff suppressed because it is too large Load Diff
-405
View File
@@ -1,405 +0,0 @@
<div align="center">
<img src="../public/icon.svg" width="120" height="120" alt="Termix Logo" />
<h1>Termix</h1>
<p>إدارة SSH ذاتية الاستضافة والوصول إلى سطح المكتب البعيد</p>
<p>
<a href="../README.md">English</a> ·
<a href="README-CN.md">中文</a> ·
<a href="README-JA.md">日本語</a> ·
<a href="README-KO.md">한국어</a> ·
<a href="README-FR.md">Français</a> ·
<a href="README-DE.md">Deutsch</a> ·
<a href="README-ES.md">Español</a> ·
<a href="README-PT.md">Português</a> ·
<a href="README-RU.md">Русский</a> ·
العربية ·
<a href="README-HI.md">हिन्दी</a> ·
<a href="README-TR.md">Türkçe</a> ·
<a href="README-VI.md">Tiếng Việt</a> ·
<a href="README-IT.md">Italiano</a>
</p>
<p>
<img src="https://img.shields.io/github/stars/Termix-SSH/Termix?style=flat&label=Stars&color=F39044&labelColor=1a1a1a" />
<img src="https://img.shields.io/github/forks/Termix-SSH/Termix?style=flat&label=Forks&color=F39044&labelColor=1a1a1a" />
<img src="https://img.shields.io/github/v/release/Termix-SSH/Termix?style=flat&label=Release&color=F39044&labelColor=1a1a1a&v=1" />
<a href="https://discord.gg/jVQGdvHDrf"><img alt="Discord" src="https://img.shields.io/discord/1347374268253470720?color=F39044&labelColor=1a1a1a" /></a>
<a href="https://donate.termix.site/"><img alt="Donate" src="https://img.shields.io/badge/Donate-Support%20Termix-F39044?style=flat&labelColor=1a1a1a" /></a>
</p>
<br />
Termix مجاني ومفتوح المصدر. إذا وجدته مفيدًا، فكّر في [التبرع](https://donate.termix.site/) للمساعدة في تغطية تكاليف الخادم ووقت التطوير.
<a href="https://donate.termix.site/"><img src="../repo-images/donation-goal.svg" alt="Monthly donation goal" /></a>
<br />
<img src="../repo-images/Termix Header.png" alt="Termix Banner" width="900" />
<br />
<br />
<p>
<img src="../repo-images/Repo of the Day.png" alt="Repo of the Day Achievement" width="280" />
<br />
<sub>تم تحقيقه في 1 سبتمبر 2025</sub>
</p>
</div>
<br />
## نظرة عامة
Termix هي منصة مفتوحة المصدر ومجانية للأبد وذاتية الاستضافة لإدارة الخوادم بشكل شامل. توفر حلاً متعدد المنصات لإدارة خوادمك وبنيتك التحتية من خلال واجهة واحدة وسهلة الاستخدام. يوفر Termix الوصول إلى طرفية SSH، والتحكم في سطح المكتب البعيد (RDP، VNC، Telnet)، وقدرات إنشاء أنفاق SSH، وإدارة ملفات SSH عن بُعد، والعديد من الأدوات الأخرى. يُعد Termix البديل المثالي المجاني وذاتي الاستضافة لـ Termius المتاح لجميع المنصات.
<br />
## الميزات
<table>
<tr>
<td width="50%" valign="top">
**الوصول إلى طرفية SSH:**
طرفية كاملة الميزات مع دعم تقسيم الشاشة (حتى 4 لوحات) مع نظام علامات تبويب شبيه بالمتصفح. يتضمن دعم تخصيص الطرفية بما في ذلك سمات الطرفية الشائعة والخطوط والمكونات الأخرى.
</td>
<td width="50%" valign="top">
**الوصول إلى سطح المكتب البعيد:**
دعم RDP و VNC و Telnet عبر المتصفح مع تخصيص كامل وتقسيم الشاشة.
</td>
</tr>
<tr>
<td width="50%" valign="top">
**إدارة أنفاق SSH:**
إنشاء وإدارة أنفاق SSH بين الخوادم مع إعادة الاتصال التلقائي ومراقبة الحالة وإعادة التوجيه المحلي أو البعيد أو SOCKS الديناميكي. يتم تخزين إعدادات نفق العميل-المكتبي إلى السيرفر محلياً لكل تثبيت مكتبي؛ يمكن حفظ لقطات C2S الاختيارية على الخادم وإعادة تسميتها وتحميلها أو حذفها لنقل تكوين النفق المحلي بين العملاء.
</td>
<td width="50%" valign="top">
**مدير الملفات عن بُعد:**
إدارة الملفات مباشرة على الخوادم البعيدة مع دعم عرض وتحرير الكود والصور والصوت والفيديو. رفع وتنزيل وإعادة تسمية وحذف ونقل الملفات بسلاسة مع دعم sudo.
</td>
</tr>
<tr>
<td width="50%" valign="top">
**إدارة Docker و Podman:**
تشغيل وإيقاف وتعليق وحذف الحاويات. عرض إحصائيات الحاويات. التحكم في الحاوية باستخدام طرفية docker exec. يدعم كلاً من Docker و Podman كبيئة تشغيل للحاويات. لم يُصمم ليحل محل Portainer أو Dockge بل لإدارة حاوياتك ببساطة مقارنة بإنشائها.
</td>
<td width="50%" valign="top">
**مدير مضيفات SSH:**
حفظ وتنظيم وإدارة اتصالات SSH الخاصة بك باستخدام العلامات والمجلدات (مع دعم تخصيص المجلدات والمجلدات المتداخلة)، وحفظ بيانات تسجيل الدخول القابلة لإعادة الاستخدام بسهولة مع إمكانية أتمتة نشر مفاتيح SSH.
</td>
</tr>
<tr>
<td width="50%" valign="top">
**مقاييس المضيف:**
عرض استخدام المعالج والذاكرة والقرص والشبكة ووقت التشغيل ومعلومات النظام وجدار الحماية ومراقب المنافذ وعارض السجلات والمستخدمين/الصلاحيات والشهادات وغيرها الكثير، تعمل على معظم الخوادم المبنية على Linux.
</td>
<td width="50%" valign="top">
**مصادقة المستخدمين:**
إدارة آمنة للمستخدمين مع ضوابط إدارية ودعم OIDC/LDAP/SSO (مع التحكم في الوصول) و 2FA (TOTP). عرض جلسات المستخدمين النشطة عبر جميع المنصات وإلغاء الصلاحيات. ربط حسابات OIDC/المحلية معاً. عرض سجل تدقيق لجميع إجراءات المستخدمين.
</td>
</tr>
<tr>
<td width="50%" valign="top">
**تكامل Tailscale:**
عرض أجهزة شبكتك من Tailscale لإضافتها بسرعة كمضيفات، والاتصال عبر Tailscale SSH كطريقة مصادقة، مما يتيح لقوائم تحكم الوصول في Tailscale التعامل مع التفويض دون الحاجة لتخزين بيانات اعتماد.
</td>
<td width="50%" valign="top">
**RBAC:**
إنشاء الأدوار ومشاركة المضيفات عبر المستخدمين/الأدوار.
</td>
</tr>
<tr>
<td width="50%" valign="top">
**الاتصالات التسلسلية:**
الاتصال بالأجهزة التسلسلية (أجهزة التوجيه والمفاتيح والمتحكمات الدقيقة وغيرها) مباشرة من المتصفح أو تطبيق سطح المكتب. ضبط معدل نقل البيانات وبتات البيانات وبتات التوقف والتكافؤ. يستخدم Web Serial API في المتصفحات المدعومة أو خلفية أصلية في تطبيق Electron.
</td>
<td width="50%" valign="top">
**التنبيهات:**
ضبط قواعد تنبيه قائمة على الحدود لمقاييس المضيف (المعالج والذاكرة والقرص وغيرها) والحصول على إشعارات عبر ntfy أو webhooks عند إطلاقها. عرض التنبيهات النشطة والمحلولة في سجل التاريخ.
</td>
</tr>
<tr>
<td width="50%" valign="top">
**الصفحة الرئيسية:**
صفحة رئيسية قابلة للتخصيص بالكامل مع شبكة أدوات قابلة للسحب والإفلات. أضف أدوات لحالة المضيف وروابط الخدمات والساعات والملاحظات وخلاصات RSS والطقس وحاويات Docker ومخططات مقاييس المضيف والطرفيات المضمنة والإطارات المضمنة وأكثر.
</td>
<td width="50%" valign="top">
**تشفير قاعدة البيانات:**
يُخزَّن الخادم الخلفي كملفات قاعدة بيانات SQLite مشفرة. اطلع على [الوثائق](https://docs.termix.site/security) لمزيد من المعلومات.
</td>
</tr>
<tr>
<td width="50%" valign="top">
**الرسم البياني للشبكة:**
تخصيص لوحة التحكم لتصور مختبرك المنزلي بناءً على اتصالات SSH مع دعم الحالة.
</td>
<td width="50%" valign="top">
**أدوات SSH:**
إنشاء مقتطفات أوامر قابلة لإعادة الاستخدام تُنفَّذ بنقرة واحدة. تشغيل أمر واحد في وقت واحد عبر عدة طرفيات مفتوحة.
</td>
</tr>
<tr>
<td width="50%" valign="top">
**علامات التبويب الدائمة:**
تبقى جلسات SSH وعلامات التبويب مفتوحة عبر الأجهزة/التحديثات إذا تم تفعيلها في ملف تعريف المستخدم.
</td>
<td width="50%" valign="top">
**اللغات:**
دعم مدمج لحوالي 30 لغة (تُدار بواسطة [Crowdin](https://docs.termix.site/translations)).
</td>
</tr>
</table>
<br />
<details>
<summary><b>المزيد من الميزات</b></summary>
<br />
- **لوحة التحكم** - عرض معلومات الخادم بنظرة واحدة على لوحة التحكم
- **مفاتيح API** - إنشاء مفاتيح API محددة النطاق للمستخدم مع تواريخ انتهاء صلاحية للاستخدام في الأتمتة/CI
- **تصدير/استيراد البيانات** - تصدير واستيراد مضيفات SSH وبيانات الاعتماد وبيانات مدير الملفات
- **إعداد SSL تلقائي** - إنشاء وإدارة شهادات SSL مدمجة مع إعادة التوجيه إلى HTTPS
- **واجهة مستخدم حديثة** - واجهة نظيفة متوافقة مع سطح المكتب والهاتف المحمول مبنية بـ React و Tailwind CSS و Shadcn. الاختيار بين العديد من سمات واجهة المستخدم بما في ذلك الفاتح والداكن و Dracula وغيرها. استخدام مسارات URL لفتح أي اتصال في وضع ملء الشاشة.
- **سجل الأوامر** - الإكمال التلقائي وعرض أوامر SSH التي تم تنفيذها سابقاً
- **الاتصال السريع** - الاتصال بخادم دون الحاجة إلى حفظ بيانات الاتصال
- **لوحة الأوامر** - اضغط مرتين على Shift الأيسر للوصول السريع إلى اتصالات SSH باستخدام لوحة المفاتيح
- **تكامل Proxmox** - إضافة المضيفات تلقائياً إلى Termix من نسخة Proxmox الخاصة بك
- **ميزات SSH الغنية** - دعم مضيفات القفز، Warpgate، الاتصالات المبنية على TOTP، SOCKS5، التحقق من مفتاح المضيف، الملء التلقائي لكلمة المرور، [OPKSSH](https://github.com/openpubkey/opkssh)، tmux، port knocking، تسجيل الطرفية، إلخ.
</details>
<br />
## دعم المنصات
<table align="center">
<tr>
<th align="center">المنصة</th>
<th align="center">التوزيع</th>
</tr>
<tr>
<td align="center"><b>Web</b></td>
<td>أي متصفح حديث (Chrome، Safari، Firefox) · دعم PWA</td>
</tr>
<tr>
<td align="center"><b>Windows</b> <sub>x64/ia32</sub></td>
<td>نسخة محمولة · مثبت MSI · Chocolatey</td>
</tr>
<tr>
<td align="center"><b>Linux</b> <sub>x64/ia32</sub></td>
<td>نسخة محمولة · AUR · AppImage · Deb · Flatpak</td>
</tr>
<tr>
<td align="center"><b>macOS</b> <sub>x64/ia32, v12.0+</sub></td>
<td>Apple App Store · DMG · Homebrew</td>
</tr>
<tr>
<td align="center"><b>iOS/iPadOS</b> <sub>v15.1+</sub></td>
<td>Apple App Store · IPA</td>
</tr>
<tr>
<td align="center"><b>Android</b> <sub>v7.0+</sub></td>
<td>Google Play Store · APK</td>
</tr>
</table>
<br />
## التثبيت
قم بزيارة [وثائق](https://docs.termix.site/install) Termix للحصول على مزيد من المعلومات حول كيفية تثبيت Termix على جميع المنصات. يمكنك الاطلاع على نموذج ملف Docker Compose هنا (يمكنك حذف guacd والشبكة إذا كنت لا تخطط لاستخدام ميزات سطح المكتب البعيد):
```yaml
services:
termix:
image: ghcr.io/lukegus/termix:latest
container_name: termix
restart: unless-stopped
ports:
- "8080:8080"
volumes:
- termix-data:/app/data
environment:
PORT: "8080"
depends_on:
- guacd
networks:
- termix-net
guacd:
image: guacamole/guacd:1.6.0
container_name: guacd
restart: unless-stopped
ports:
- "4822:4822"
networks:
- termix-net
volumes:
termix-data:
driver: local
networks:
termix-net:
driver: bridge
```
<br />
## التبرع
Termix مجاني ومفتوح المصدر. إذا وجدته مفيدًا، فكّر في [التبرع](https://donate.termix.site/) للمساعدة في تغطية تكاليف الخادم ووقت التطوير.
<a href="https://donate.termix.site/"><img src="../repo-images/donation-goal.svg" alt="Monthly donation goal" /></a>
<br />
## لقطات الشاشة
<div align="center">
<br />
[![YouTube](../repo-images/YouTube.png)](https://www.youtube.com/@TermixSSH/videos)
<sub>شاهد نظرة عامة على التحديثات على YouTube</sub>
<br />
<br />
<table>
<tr>
<td><img src="../repo-images/Image 1.png" alt="Termix Screenshot 1" width="400" /></td>
<td><img src="../repo-images/Image 2.png" alt="Termix Screenshot 2" width="400" /></td>
</tr>
<tr>
<td><img src="../repo-images/Image 3.png" alt="Termix Screenshot 3" width="400" /></td>
<td><img src="../repo-images/Image 4.png" alt="Termix Screenshot 4" width="400" /></td>
</tr>
<tr>
<td><img src="../repo-images/Image 5.png" alt="Termix Screenshot 5" width="400" /></td>
<td><img src="../repo-images/Image 6.png" alt="Termix Screenshot 6" width="400" /></td>
</tr>
<tr>
<td><img src="../repo-images/Image 7.png" alt="Termix Screenshot 7" width="400" /></td>
<td><img src="../repo-images/Image 8.png" alt="Termix Screenshot 8" width="400" /></td>
</tr>
<tr>
<td><img src="../repo-images/Image 9.png" alt="Termix Screenshot 9" width="400" /></td>
<td><img src="../repo-images/Image 10.png" alt="Termix Screenshot 10" width="400" /></td>
</tr>
<tr>
<td><img src="../repo-images/Image 11.png" alt="Termix Screenshot 11" width="400" /></td>
<td><img src="../repo-images/Image 12.png" alt="Termix Screenshot 12" width="400" /></td>
</tr>
<tr>
<td><img src="../repo-images/Image 13.png" alt="Termix Screenshot 13" width="400" /></td>
<td><img src="../repo-images/Image 14.png" alt="Termix Screenshot 14" width="400" /></td>
</tr>
<tr>
<td><img src="../repo-images/Image 15.png" alt="Termix Screenshot 15" width="400" /></td>
<td><img src="../repo-images/Image 16.png" alt="Termix Screenshot 16" width="400" /></td>
</tr>
</table>
<sub>قد تكون بعض مقاطع الفيديو والصور قديمة أو قد لا تعرض الميزات بشكل مثالي.</sub>
</div>
<br />
## الميزات المخططة
راجع [المشاريع](https://github.com/orgs/Termix-SSH/projects/5) لعرض جميع الميزات المخططة. إذا كنت تتطلع للمساهمة، راجع [المساهمة](https://github.com/Termix-SSH/Termix/blob/main/CONTRIBUTING.md).
<br />
## الرعاة
<div align="center">
<br />
<a href="https://www.digitalocean.com/">
<img src="https://opensource.nyc3.cdn.digitaloceanspaces.com/attribution/assets/SVG/DO_Logo_horizontal_blue.svg" height="40" alt="DigitalOcean" />
</a>
&nbsp;&nbsp;&nbsp;
<a href="https://crowdin.com/">
<img src="https://support.crowdin.com/assets/logos/core-logo/svg/crowdin-core-logo-cDark.svg" height="40" alt="Crowdin" />
</a>
&nbsp;&nbsp;&nbsp;
<a href="https://www.blacksmith.sh/">
<img src="https://cdn.prod.website-files.com/681bfb0c9a4601bc6e288ec4/683ca9e2c5186757092611b8_e8cb22127df4da0811c4120a523722d2_logo-backsmith-wordmark-light.svg" height="40" alt="Blacksmith" />
</a>
&nbsp;&nbsp;&nbsp;
<a href="https://www.cloudflare.com/">
<img src="https://sirv.sirv.com/website/screenshots/cloudflare/cloudflare-logo.png?w=300" height="40" alt="Cloudflare" />
</a>
&nbsp;&nbsp;&nbsp;
<a href="https://tailscale.com/">
<img src="https://drive.google.com/uc?export=view&id=1lIxkJuX6M23bW-2FElhT0rQieTrzaVSL" height="40" alt="Tailscale" />
</a>
&nbsp;&nbsp;&nbsp;
<a href="https://akamai.com/">
<img src="https://upload.wikimedia.org/wikipedia/commons/8/8b/Akamai_logo.svg" height="40" alt="Akamai" />
</a>
&nbsp;&nbsp;&nbsp;
<a href="https://aws.amazon.com/">
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/9/93/Amazon_Web_Services_Logo.svg/960px-Amazon_Web_Services_Logo.svg.png" height="40" alt="AWS" />
</a>
</div>
<br />
## الدعم
إذا كنت بحاجة إلى مساعدة أو ترغب في طلب ميزة لـ Termix، قم بزيارة صفحة [المشكلات](https://github.com/Termix-SSH/Support/issues)، وسجل الدخول، واضغط على `New Issue`. يرجى أن تكون مفصلاً قدر الإمكان في مشكلتك، ويُفضَّل كتابتها باللغة الإنجليزية. يمكنك أيضاً الانضمام إلى خادم [Discord](https://discord.gg/jVQGdvHDrf) وزيارة قناة الدعم، ومع ذلك قد تكون أوقات الاستجابة أطول.
<br />
## الترخيص
موزع بموجب رخصة Apache License الإصدار 2.0. راجع ملف `LICENSE` لمزيد من المعلومات.
-405
View File
@@ -1,405 +0,0 @@
<div align="center">
<img src="../public/icon.svg" width="120" height="120" alt="Termix Logo" />
<h1>Termix</h1>
<p>自托管 SSH 管理与远程桌面访问平台</p>
<p>
<a href="../README.md">English</a> ·
中文 ·
<a href="README-JA.md">日本語</a> ·
<a href="README-KO.md">한국어</a> ·
<a href="README-FR.md">Français</a> ·
<a href="README-DE.md">Deutsch</a> ·
<a href="README-ES.md">Español</a> ·
<a href="README-PT.md">Português</a> ·
<a href="README-RU.md">Русский</a> ·
<a href="README-AR.md">العربية</a> ·
<a href="README-HI.md">हिन्दी</a> ·
<a href="README-TR.md">Türkçe</a> ·
<a href="README-VI.md">Tiếng Việt</a> ·
<a href="README-IT.md">Italiano</a>
</p>
<p>
<img src="https://img.shields.io/github/stars/Termix-SSH/Termix?style=flat&label=Stars&color=F39044&labelColor=1a1a1a" />
<img src="https://img.shields.io/github/forks/Termix-SSH/Termix?style=flat&label=Forks&color=F39044&labelColor=1a1a1a" />
<img src="https://img.shields.io/github/v/release/Termix-SSH/Termix?style=flat&label=Release&color=F39044&labelColor=1a1a1a&v=1" />
<a href="https://discord.gg/jVQGdvHDrf"><img alt="Discord" src="https://img.shields.io/discord/1347374268253470720?color=F39044&labelColor=1a1a1a" /></a>
<a href="https://donate.termix.site/"><img alt="Donate" src="https://img.shields.io/badge/Donate-Support%20Termix-F39044?style=flat&labelColor=1a1a1a" /></a>
</p>
<br />
Termix 免费且开源。如果您觉得它有用,请考虑[捐赠](https://donate.termix.site/)以帮助支付服务器费用和开发时间。
<a href="https://donate.termix.site/"><img src="../repo-images/donation-goal.svg" alt="Monthly donation goal" /></a>
<br />
<img src="../repo-images/Termix Header.png" alt="Termix Banner" width="900" />
<br />
<br />
<p>
<img src="../repo-images/Repo of the Day.png" alt="Repo of the Day Achievement" width="280" />
<br />
<sub>获得于 2025年9月1日</sub>
</p>
</div>
<br />
## 概览
Termix 是一个开源、永久免费、自托管的一体化服务器管理平台。它提供了一个多平台解决方案,通过一个直观的界面管理你的服务器和基础设施。Termix 提供 SSH 终端访问、远程桌面控制(RDP、VNC、Telnet)、SSH 隧道功能、远程 SSH 文件管理以及许多其他工具。Termix 是适用于所有平台的完美免费自托管 Termius 替代品。
<br />
## 功能
<table>
<tr>
<td width="50%" valign="top">
**SSH 终端访问:**
功能齐全的终端,支持分屏(最多 4 个面板),并配有类似浏览器的标签系统。包括对自定义终端的支持,如常用的终端主题、字体和其他组件。
</td>
<td width="50%" valign="top">
**远程桌面访问:**
通过浏览器支持 RDP、VNC 和 Telnet,具有完整的自定义和分屏功能。
</td>
</tr>
<tr>
<td width="50%" valign="top">
**SSH 隧道管理:**
创建和管理具有自动重连和健康监测功能的服务器间 SSH 隧道,支持本地、远程或动态 SOCKS 转发。桌面客户端到服务器的隧道设置按桌面安装本地存储,可选的 C2S 预设快照可保存到服务器、重命名、加载或删除,以便在客户端之间迁移本地隧道配置。
</td>
<td width="50%" valign="top">
**远程文件管理器:**
直接在远程服务器上管理文件,支持查看和编辑代码、图像、音频和视频。支持通过 sudo 无缝上传、下载、重命名、删除和移动文件。
</td>
</tr>
<tr>
<td width="50%" valign="top">
**Docker 和 Podman 管理:**
启动、停止、暂停、移除容器。查看容器统计信息。通过 docker exec 终端控制容器。同时支持 Docker 和 Podman 作为容器运行时。它的初衷不是取代 Portainer 或 Dockge,而是为了比直接创建容器更简单地管理它们。
</td>
<td width="50%" valign="top">
**SSH 主机管理器:**
通过标签和文件夹(支持文件夹自定义和嵌套文件夹)保存、组织和管理您的 SSH 连接,轻松保存可重用的登录信息,并能自动化部署 SSH 密钥。
</td>
</tr>
<tr>
<td width="50%" valign="top">
**主机指标:**
在大多数基于 Linux 的服务器上查看 CPU、内存、磁盘使用情况、网络、运行时间、系统信息、防火墙、端口监控、日志查看器、用户/权限、证书等更多信息。
</td>
<td width="50%" valign="top">
**用户认证:**
安全的用户管理,具有管理员控制、OIDC/LDAP/SSO(带访问控制)和 2FA (TOTP) 支持。查看所有平台上的活动用户会话并撤销权限。将您的 OIDC/本地账户链接在一起。查看所有用户操作的审计日志。
</td>
</tr>
<tr>
<td width="50%" valign="top">
**Tailscale 集成:**
列出您 Tailscale 网络中的设备以快速添加为主机,并使用 Tailscale SSH 作为身份验证方式,让您的 Tailscale ACL 处理授权而无需存储凭据。
</td>
<td width="50%" valign="top">
**RBAC:**
创建角色并在用户/角色之间共享主机。
</td>
</tr>
<tr>
<td width="50%" valign="top">
**串口连接:**
直接从浏览器或桌面应用连接到串口设备(路由器、交换机、微控制器等)。配置波特率、数据位、停止位和奇偶校验。在支持的浏览器中使用 Web Serial API,或在 Electron 应用中使用原生后端。
</td>
<td width="50%" valign="top">
**告警:**
为主机指标(CPU、内存、磁盘等)设置基于阈值的告警规则,并通过 ntfy 或 webhook 接收触发通知。在历史日志中查看触发和已解决的告警。
</td>
</tr>
<tr>
<td width="50%" valign="top">
**主页:**
具有拖放小组件网格的完全可定制主页。添加主机状态、服务链接、时钟、笔记、RSS 订阅、天气、Docker 容器、主机指标图表、嵌入式终端、iframe 等小组件。
</td>
<td width="50%" valign="top">
**数据库加密:**
后端存储为加密的 SQLite 数据库文件。查看[文档](https://docs.termix.site/security)了解更多。
</td>
</tr>
<tr>
<td width="50%" valign="top">
**网络图:**
自定义您的仪表板,根据您的 SSH 连接可视化您的家庭实验室,并支持状态监测。
</td>
<td width="50%" valign="top">
**SSH 工具:**
创建可重用的命令片段,只需点击一下即可执行。在多个打开的终端中同时运行一个命令。
</td>
</tr>
<tr>
<td width="50%" valign="top">
**持久标签页:**
如果在用户个人资料中启用,SSH 会话和标签页将在设备/刷新后保持打开状态。
</td>
<td width="50%" valign="top">
**语言:**
内置支持约 30 种语言(由 [Crowdin](https://docs.termix.site/translations) 管理)。
</td>
</tr>
</table>
<br />
<details>
<summary><b>更多功能</b></summary>
<br />
- **仪表板** - 在仪表板上一目了然地查看服务器信息
- **API 密钥** - 创建带有到期日期的用户范围 API 密钥,用于自动化/CI
- **数据导出/导入** - 导出和导入 SSH 主机、凭据和文件管理器数据
- **自动 SSL 设置** - 内置 SSL 证书生成和管理,支持 HTTPS 重定向
- **现代 UI** - 使用 React、Tailwind CSS 和 Shadcn 构建的整洁的桌面/移动友好界面。有多种 UI 主题可选,包括浅色、深色、Dracula 等。使用 URL 路由全屏打开任何连接。
- **命令历史** - 自动完成并查看之前运行过的 SSH 命令
- **快速连接** - 无需保存连接数据即可连接到服务器
- **命令面板** - 双击左 Shift 键即可通过键盘快速访问 SSH 连接
- **Proxmox 集成** - 从您的 Proxmox 实例自动将主机添加到 Termix
- **丰富的 SSH 功能** - 支持跳转主机、Warpgate、基于 TOTP 的连接、SOCKS5、主机密钥验证、密码自动填充、[OPKSSH](https://github.com/openpubkey/opkssh)、tmux、端口敲击、终端日志记录等
</details>
<br />
## 平台支持
<table align="center">
<tr>
<th align="center">平台</th>
<th align="center">发行版</th>
</tr>
<tr>
<td align="center"><b>Web</b></td>
<td>任何现代浏览器(Chrome、Safari、Firefox)· PWA 支持</td>
</tr>
<tr>
<td align="center"><b>Windows</b> <sub>x64/ia32</sub></td>
<td>便携版 · MSI 安装程序 · Chocolatey</td>
</tr>
<tr>
<td align="center"><b>Linux</b> <sub>x64/ia32</sub></td>
<td>便携版 · AUR · AppImage · Deb · Flatpak</td>
</tr>
<tr>
<td align="center"><b>macOS</b> <sub>x64/ia32, v12.0+</sub></td>
<td>Apple App Store · DMG · Homebrew</td>
</tr>
<tr>
<td align="center"><b>iOS/iPadOS</b> <sub>v15.1+</sub></td>
<td>Apple App Store · IPA</td>
</tr>
<tr>
<td align="center"><b>Android</b> <sub>v7.0+</sub></td>
<td>Google Play Store · APK</td>
</tr>
</table>
<br />
## 安装
访问 [Termix 文档](https://docs.termix.site/install) 了解有关如何在所有平台上安装 Termix 的更多信息。此外,这里有一个示例 Docker Compose 文件(如果您不打算使用远程桌面功能,可以省略 guacd 和网络部分):
```yaml
services:
termix:
image: ghcr.io/lukegus/termix:latest
container_name: termix
restart: unless-stopped
ports:
- "8080:8080"
volumes:
- termix-data:/app/data
environment:
PORT: "8080"
depends_on:
- guacd
networks:
- termix-net
guacd:
image: guacamole/guacd:1.6.0
container_name: guacd
restart: unless-stopped
ports:
- "4822:4822"
networks:
- termix-net
volumes:
termix-data:
driver: local
networks:
termix-net:
driver: bridge
```
<br />
## 捐赠
Termix 免费且开源。如果您觉得它有用,请考虑[捐赠](https://donate.termix.site/)以帮助支付服务器费用和开发时间。
<a href="https://donate.termix.site/"><img src="../repo-images/donation-goal.svg" alt="Monthly donation goal" /></a>
<br />
## 展示
<div align="center">
<br />
[![YouTube](../repo-images/YouTube.png)](https://www.youtube.com/@TermixSSH/videos)
<sub>在 YouTube 上观看更新概览</sub>
<br />
<br />
<table>
<tr>
<td><img src="../repo-images/Image 1.png" alt="Termix Screenshot 1" width="400" /></td>
<td><img src="../repo-images/Image 2.png" alt="Termix Screenshot 2" width="400" /></td>
</tr>
<tr>
<td><img src="../repo-images/Image 3.png" alt="Termix Screenshot 3" width="400" /></td>
<td><img src="../repo-images/Image 4.png" alt="Termix Screenshot 4" width="400" /></td>
</tr>
<tr>
<td><img src="../repo-images/Image 5.png" alt="Termix Screenshot 5" width="400" /></td>
<td><img src="../repo-images/Image 6.png" alt="Termix Screenshot 6" width="400" /></td>
</tr>
<tr>
<td><img src="../repo-images/Image 7.png" alt="Termix Screenshot 7" width="400" /></td>
<td><img src="../repo-images/Image 8.png" alt="Termix Screenshot 8" width="400" /></td>
</tr>
<tr>
<td><img src="../repo-images/Image 9.png" alt="Termix Screenshot 9" width="400" /></td>
<td><img src="../repo-images/Image 10.png" alt="Termix Screenshot 10" width="400" /></td>
</tr>
<tr>
<td><img src="../repo-images/Image 11.png" alt="Termix Screenshot 11" width="400" /></td>
<td><img src="../repo-images/Image 12.png" alt="Termix Screenshot 12" width="400" /></td>
</tr>
<tr>
<td><img src="../repo-images/Image 13.png" alt="Termix Screenshot 13" width="400" /></td>
<td><img src="../repo-images/Image 14.png" alt="Termix Screenshot 14" width="400" /></td>
</tr>
<tr>
<td><img src="../repo-images/Image 15.png" alt="Termix Screenshot 15" width="400" /></td>
<td><img src="../repo-images/Image 16.png" alt="Termix Screenshot 16" width="400" /></td>
</tr>
</table>
<sub>某些视频和图像可能已过时,或者可能无法完美展示功能。</sub>
</div>
<br />
## 计划功能
查看 [Projects](https://github.com/orgs/Termix-SSH/projects/5) 了解所有计划功能。如果您想贡献代码,请参阅 [Contributing](https://github.com/Termix-SSH/Termix/blob/main/CONTRIBUTING.md)。
<br />
## 赞助商
<div align="center">
<br />
<a href="https://www.digitalocean.com/">
<img src="https://opensource.nyc3.cdn.digitaloceanspaces.com/attribution/assets/SVG/DO_Logo_horizontal_blue.svg" height="40" alt="DigitalOcean" />
</a>
&nbsp;&nbsp;&nbsp;
<a href="https://crowdin.com/">
<img src="https://support.crowdin.com/assets/logos/core-logo/svg/crowdin-core-logo-cDark.svg" height="40" alt="Crowdin" />
</a>
&nbsp;&nbsp;&nbsp;
<a href="https://www.blacksmith.sh/">
<img src="https://cdn.prod.website-files.com/681bfb0c9a4601bc6e288ec4/683ca9e2c5186757092611b8_e8cb22127df4da0811c4120a523722d2_logo-backsmith-wordmark-light.svg" height="40" alt="Blacksmith" />
</a>
&nbsp;&nbsp;&nbsp;
<a href="https://www.cloudflare.com/">
<img src="https://sirv.sirv.com/website/screenshots/cloudflare/cloudflare-logo.png?w=300" height="40" alt="Cloudflare" />
</a>
&nbsp;&nbsp;&nbsp;
<a href="https://tailscale.com/">
<img src="https://drive.google.com/uc?export=view&id=1lIxkJuX6M23bW-2FElhT0rQieTrzaVSL" height="40" alt="Tailscale" />
</a>
&nbsp;&nbsp;&nbsp;
<a href="https://akamai.com/">
<img src="https://upload.wikimedia.org/wikipedia/commons/8/8b/Akamai_logo.svg" height="40" alt="Akamai" />
</a>
&nbsp;&nbsp;&nbsp;
<a href="https://aws.amazon.com/">
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/9/93/Amazon_Web_Services_Logo.svg/960px-Amazon_Web_Services_Logo.svg.png" height="40" alt="AWS" />
</a>
</div>
<br />
## 支持
如果您需要 Termix 的帮助或想要请求功能,请访问 [Issues](https://github.com/Termix-SSH/Support/issues) 页面,登录并点击 `New Issue`。请尽可能详细地描述您的问题,建议使用英语。您也可以加入 [Discord](https://discord.gg/jVQGdvHDrf) 服务器并访问支持频道,但响应时间可能较长。
<br />
## 许可证
根据 Apache License Version 2.0 发布。更多信息请参见 `LICENSE`
-405
View File
@@ -1,405 +0,0 @@
<div align="center">
<img src="../public/icon.svg" width="120" height="120" alt="Termix Logo" />
<h1>Termix</h1>
<p>Selbst gehostete SSH-Verwaltung und Remote-Desktop-Zugriff</p>
<p>
<a href="../README.md">English</a> ·
<a href="README-CN.md">中文</a> ·
<a href="README-JA.md">日本語</a> ·
<a href="README-KO.md">한국어</a> ·
<a href="README-FR.md">Français</a> ·
Deutsch ·
<a href="README-ES.md">Español</a> ·
<a href="README-PT.md">Português</a> ·
<a href="README-RU.md">Русский</a> ·
<a href="README-AR.md">العربية</a> ·
<a href="README-HI.md">हिन्दी</a> ·
<a href="README-TR.md">Türkçe</a> ·
<a href="README-VI.md">Tiếng Việt</a> ·
<a href="README-IT.md">Italiano</a>
</p>
<p>
<img src="https://img.shields.io/github/stars/Termix-SSH/Termix?style=flat&label=Stars&color=F39044&labelColor=1a1a1a" />
<img src="https://img.shields.io/github/forks/Termix-SSH/Termix?style=flat&label=Forks&color=F39044&labelColor=1a1a1a" />
<img src="https://img.shields.io/github/v/release/Termix-SSH/Termix?style=flat&label=Release&color=F39044&labelColor=1a1a1a&v=1" />
<a href="https://discord.gg/jVQGdvHDrf"><img alt="Discord" src="https://img.shields.io/discord/1347374268253470720?color=F39044&labelColor=1a1a1a" /></a>
<a href="https://donate.termix.site/"><img alt="Donate" src="https://img.shields.io/badge/Donate-Support%20Termix-F39044?style=flat&labelColor=1a1a1a" /></a>
</p>
<br />
Termix ist kostenlos und Open Source. Wenn Sie es nützlich finden, erwägen Sie eine [Spende](https://donate.termix.site/), um Serverkosten und Entwicklungszeit zu decken.
<a href="https://donate.termix.site/"><img src="../repo-images/donation-goal.svg" alt="Monthly donation goal" /></a>
<br />
<img src="../repo-images/Termix Header.png" alt="Termix Banner" width="900" />
<br />
<br />
<p>
<img src="../repo-images/Repo of the Day.png" alt="Repo of the Day Achievement" width="280" />
<br />
<sub>Erreicht am 1. September 2025</sub>
</p>
</div>
<br />
## Uberblick
Termix ist eine quelloffene, dauerhaft kostenlose, selbst gehostete All-in-One-Serververwaltungsplattform. Sie bietet eine plattformubergreifende Losung zur Verwaltung Ihrer Server und Infrastruktur uber eine einzige, intuitive Oberflache. Termix bietet SSH-Terminalzugriff, Remote-Desktop-Steuerung (RDP, VNC, Telnet), SSH-Tunneling-Funktionen, Remote-SSH-Dateiverwaltung und viele weitere Werkzeuge. Termix ist die perfekte kostenlose und selbst gehostete Alternative zu Termius, verfugbar fur alle Plattformen.
<br />
## Funktionen
<table>
<tr>
<td width="50%" valign="top">
**SSH-Terminalzugriff:**
Voll ausgestattetes Terminal mit Split-Screen-Unterstutzung (bis zu 4 Panels) mit einem browserahnlichen Tab-System. Enthalt Unterstutzung fur die Anpassung des Terminals einschliesslich gangiger Terminal-Themes, Schriftarten und anderer Komponenten.
</td>
<td width="50%" valign="top">
**Remote-Desktop-Zugriff:**
RDP-, VNC- und Telnet-Unterstutzung uber den Browser mit vollstandiger Anpassung und Split-Screen.
</td>
</tr>
<tr>
<td width="50%" valign="top">
**SSH-Tunnelverwaltung:**
Erstellen und verwalten Sie Server-zu-Server-SSH-Tunnel mit automatischer Wiederverbindung und Gesundheitsuberwachung sowie lokaler, entfernter oder dynamischer SOCKS-Weiterleitung. Desktop-Client-zu-Server-Tunneleinstellungen werden lokal pro Desktop-Installation gespeichert, optionale C2S-Preset-Snapshots konnen auf dem Server gespeichert, umbenannt, geladen oder geloscht werden, um eine lokale Tunnelkonfiguration zwischen Clients zu ubertragen.
</td>
<td width="50%" valign="top">
**Remote-Dateimanager:**
Verwalten Sie Dateien direkt auf Remote-Servern mit Unterstutzung fur das Anzeigen und Bearbeiten von Code, Bildern, Audio und Video. Laden Sie Dateien hoch, herunter, benennen Sie sie um, loschen oder verschieben Sie sie nahtlos mit Sudo-Unterstutzung.
</td>
</tr>
<tr>
<td width="50%" valign="top">
**Docker- und Podman-Verwaltung:**
Container starten, stoppen, pausieren, entfernen. Container-Statistiken anzeigen. Container uber Docker-Exec-Terminal steuern. Unterstutzt sowohl Docker als auch Podman als Container-Laufzeitumgebung. Es wurde nicht entwickelt, um Portainer oder Dockge zu ersetzen, sondern um Ihre Container einfach zu verwalten, anstatt sie zu erstellen.
</td>
<td width="50%" valign="top">
**SSH-Host-Manager:**
Speichern, organisieren und verwalten Sie Ihre SSH-Verbindungen mit Tags und Ordnern (Ordneranpassung und verschachtelte Ordner werden unterstutzt) und speichern Sie einfach wiederverwendbare Anmeldeinformationen mit der Moglichkeit, die Bereitstellung von SSH-Schlusseln zu automatisieren.
</td>
</tr>
<tr>
<td width="50%" valign="top">
**Host-Metriken:**
CPU-, Arbeitsspeicher- und Festplattenauslastung, Netzwerk, Betriebszeit, Systeminformationen, Firewall, Port-Monitor, Log-Viewer, Benutzer/Berechtigungen, Zertifikate und vieles mehr auf den meisten Linux-basierten Servern anzeigen.
</td>
<td width="50%" valign="top">
**Benutzerauthentifizierung:**
Sichere Benutzerverwaltung mit Admin-Kontrollen und OIDC-/LDAP-/SSO-Unterstutzung (mit Zugriffskontrolle) sowie 2FA (TOTP)-Unterstutzung. Aktive Benutzersitzungen uber alle Plattformen anzeigen und Berechtigungen widerrufen. OIDC-/Lokale Konten miteinander verknupfen. Audit-Protokoll aller Benutzeraktionen anzeigen.
</td>
</tr>
<tr>
<td width="50%" valign="top">
**Tailscale-Integration:**
Gerate aus Ihrem Tailnet auflisten, um sie schnell als Hosts hinzuzufugen, und mit Tailscale SSH als Authentifizierungsmethode verbinden, sodass Ihre Tailnet-ACLs die Autorisierung ubernehmen, ohne Anmeldedaten speichern zu mussen.
</td>
<td width="50%" valign="top">
**RBAC:**
Rollen erstellen und Hosts uber Benutzer/Rollen teilen.
</td>
</tr>
<tr>
<td width="50%" valign="top">
**Serielle Verbindungen:**
Verbinden Sie sich direkt vom Browser oder der Desktop-App aus mit seriellen Geraten (Router, Switches, Mikrocontroller usw.). Konfigurieren Sie Baudrate, Datenbits, Stoppbits und Paritat. Verwendet die Web Serial API in unterstutzten Browsern oder ein natives Backend in der Electron-App.
</td>
<td width="50%" valign="top">
**Warnmeldungen:**
Legen Sie schwellenwertbasierte Warnregeln fur Host-Metriken (CPU, Arbeitsspeicher, Festplatte usw.) fest und erhalten Sie Benachrichtigungen uber ntfy oder Webhooks, wenn diese ausgelost werden. Zeigen Sie ausgeloste und aufgeloste Warnmeldungen in einem Verlaufsprotokoll an.
</td>
</tr>
<tr>
<td width="50%" valign="top">
**Startseite:**
Eine vollstandig anpassbare Startseite mit einem Drag-and-Drop-Widget-Raster. Fugen Sie Widgets fur Hoststatus, Service-Links, Uhren, Notizen, RSS-Feeds, Wetter, Docker-Container, Host-Metrik-Diagramme, eingebettete Terminals, iFrames und mehr hinzu.
</td>
<td width="50%" valign="top">
**Datenbankverschlusselung:**
Backend gespeichert als verschlusselte SQLite-Datenbankdateien. Weitere Informationen in der [Dokumentation](https://docs.termix.site/security).
</td>
</tr>
<tr>
<td width="50%" valign="top">
**Netzwerkgraph:**
Passen Sie Ihr Dashboard an, um Ihr Homelab basierend auf Ihren SSH-Verbindungen mit Statusunterstutzung zu visualisieren.
</td>
<td width="50%" valign="top">
**SSH-Werkzeuge:**
Erstellen Sie wiederverwendbare Befehlsvorlagen, die mit einem einzigen Klick ausgefuhrt werden. Fuhren Sie einen Befehl gleichzeitig in mehreren geoffneten Terminals aus.
</td>
</tr>
<tr>
<td width="50%" valign="top">
**Persistente Tabs:**
SSH-Sitzungen und Tabs bleiben uber Gerate/Aktualisierungen hinweg offen, wenn im Benutzerprofil aktiviert.
</td>
<td width="50%" valign="top">
**Sprachen:**
Integrierte Unterstutzung fur ca. 30 Sprachen (verwaltet uber [Crowdin](https://docs.termix.site/translations)).
</td>
</tr>
</table>
<br />
<details>
<summary><b>Weitere Funktionen</b></summary>
<br />
- **Dashboard** - Serverinformationen auf einen Blick auf Ihrem Dashboard anzeigen
- **API-Schlussel** - Erstellen Sie benutzerbezogene API-Schlussel mit Ablaufdaten zur Verwendung fur Automatisierung/CI
- **Datenexport/-import** - SSH-Hosts, Anmeldeinformationen und Dateimanager-Daten exportieren und importieren
- **Automatische SSL-Einrichtung** - Integrierte SSL-Zertifikatsgenerierung und -verwaltung mit HTTPS-Weiterleitungen
- **Moderne Benutzeroberflache** - Saubere desktop-/mobilfreundliche Oberflache, erstellt mit React, Tailwind CSS und Shadcn. Wahlen Sie zwischen vielen verschiedenen UI-Themes einschliesslich Hell, Dunkel, Dracula usw. Verwenden Sie URL-Routen, um jede Verbindung im Vollbildmodus zu offnen.
- **Befehlsverlauf** - Autovervollstandigung und Anzeige zuvor ausgefuhrter SSH-Befehle
- **Schnellverbindung** - Verbinden Sie sich mit einem Server, ohne die Verbindungsdaten speichern zu mussen
- **Befehlspalette** - Doppeltippen Sie die linke Umschalttaste, um schnell auf SSH-Verbindungen mit Ihrer Tastatur zuzugreifen
- **Proxmox-Integration** - Automatisches Hinzufugen von Hosts zu Termix aus Ihrer Proxmox-Instanz
- **SSH-Funktionsreich** - Unterstutzt Jump-Hosts, Warpgate, TOTP-basierte Verbindungen, SOCKS5, Host-Key-Verifizierung, automatisches Ausfullen von Passwortern, [OPKSSH](https://github.com/openpubkey/opkssh), tmux, Port Knocking, Terminal-Protokollierung usw.
</details>
<br />
## Plattformunterstutzung
<table align="center">
<tr>
<th align="center">Plattform</th>
<th align="center">Distribution</th>
</tr>
<tr>
<td align="center"><b>Web</b></td>
<td>Jeder moderne Browser (Chrome, Safari, Firefox) · PWA-Unterstutzung</td>
</tr>
<tr>
<td align="center"><b>Windows</b> <sub>x64/ia32</sub></td>
<td>Portabel · MSI-Installationsprogramm · Chocolatey</td>
</tr>
<tr>
<td align="center"><b>Linux</b> <sub>x64/ia32</sub></td>
<td>Portabel · AUR · AppImage · Deb · Flatpak</td>
</tr>
<tr>
<td align="center"><b>macOS</b> <sub>x64/ia32, v12.0+</sub></td>
<td>Apple App Store · DMG · Homebrew</td>
</tr>
<tr>
<td align="center"><b>iOS/iPadOS</b> <sub>v15.1+</sub></td>
<td>Apple App Store · IPA</td>
</tr>
<tr>
<td align="center"><b>Android</b> <sub>v7.0+</sub></td>
<td>Google Play Store · APK</td>
</tr>
</table>
<br />
## Installation
Besuchen Sie die Termix-[Dokumentation](https://docs.termix.site/install) fur weitere Informationen zur Installation von Termix auf allen Plattformen. Alternativ finden Sie hier eine Docker Compose-Beispieldatei (Sie konnen guacd und das Netzwerk weglassen, wenn Sie keine Remote-Desktop-Funktionen nutzen mochten):
```yaml
services:
termix:
image: ghcr.io/lukegus/termix:latest
container_name: termix
restart: unless-stopped
ports:
- "8080:8080"
volumes:
- termix-data:/app/data
environment:
PORT: "8080"
depends_on:
- guacd
networks:
- termix-net
guacd:
image: guacamole/guacd:1.6.0
container_name: guacd
restart: unless-stopped
ports:
- "4822:4822"
networks:
- termix-net
volumes:
termix-data:
driver: local
networks:
termix-net:
driver: bridge
```
<br />
## Spenden
Termix ist kostenlos und Open Source. Wenn Sie es nützlich finden, erwägen Sie eine [Spende](https://donate.termix.site/), um Serverkosten und Entwicklungszeit zu decken.
<a href="https://donate.termix.site/"><img src="../repo-images/donation-goal.svg" alt="Monthly donation goal" /></a>
<br />
## Screenshots
<div align="center">
<br />
[![YouTube](../repo-images/YouTube.png)](https://www.youtube.com/@TermixSSH/videos)
<sub>Update-Ubersichten auf YouTube ansehen</sub>
<br />
<br />
<table>
<tr>
<td><img src="../repo-images/Image 1.png" alt="Termix Screenshot 1" width="400" /></td>
<td><img src="../repo-images/Image 2.png" alt="Termix Screenshot 2" width="400" /></td>
</tr>
<tr>
<td><img src="../repo-images/Image 3.png" alt="Termix Screenshot 3" width="400" /></td>
<td><img src="../repo-images/Image 4.png" alt="Termix Screenshot 4" width="400" /></td>
</tr>
<tr>
<td><img src="../repo-images/Image 5.png" alt="Termix Screenshot 5" width="400" /></td>
<td><img src="../repo-images/Image 6.png" alt="Termix Screenshot 6" width="400" /></td>
</tr>
<tr>
<td><img src="../repo-images/Image 7.png" alt="Termix Screenshot 7" width="400" /></td>
<td><img src="../repo-images/Image 8.png" alt="Termix Screenshot 8" width="400" /></td>
</tr>
<tr>
<td><img src="../repo-images/Image 9.png" alt="Termix Screenshot 9" width="400" /></td>
<td><img src="../repo-images/Image 10.png" alt="Termix Screenshot 10" width="400" /></td>
</tr>
<tr>
<td><img src="../repo-images/Image 11.png" alt="Termix Screenshot 11" width="400" /></td>
<td><img src="../repo-images/Image 12.png" alt="Termix Screenshot 12" width="400" /></td>
</tr>
<tr>
<td><img src="../repo-images/Image 13.png" alt="Termix Screenshot 13" width="400" /></td>
<td><img src="../repo-images/Image 14.png" alt="Termix Screenshot 14" width="400" /></td>
</tr>
<tr>
<td><img src="../repo-images/Image 15.png" alt="Termix Screenshot 15" width="400" /></td>
<td><img src="../repo-images/Image 16.png" alt="Termix Screenshot 16" width="400" /></td>
</tr>
</table>
<sub>Einige Videos und Bilder konnen veraltet sein oder Funktionen moglicherweise nicht perfekt darstellen.</sub>
</div>
<br />
## Geplante Funktionen
Siehe [Projekte](https://github.com/orgs/Termix-SSH/projects/5) fur alle geplanten Funktionen. Wenn Sie beitragen mochten, siehe [Mitwirken](https://github.com/Termix-SSH/Termix/blob/main/CONTRIBUTING.md).
<br />
## Sponsoren
<div align="center">
<br />
<a href="https://www.digitalocean.com/">
<img src="https://opensource.nyc3.cdn.digitaloceanspaces.com/attribution/assets/SVG/DO_Logo_horizontal_blue.svg" height="40" alt="DigitalOcean" />
</a>
&nbsp;&nbsp;&nbsp;
<a href="https://crowdin.com/">
<img src="https://support.crowdin.com/assets/logos/core-logo/svg/crowdin-core-logo-cDark.svg" height="40" alt="Crowdin" />
</a>
&nbsp;&nbsp;&nbsp;
<a href="https://www.blacksmith.sh/">
<img src="https://cdn.prod.website-files.com/681bfb0c9a4601bc6e288ec4/683ca9e2c5186757092611b8_e8cb22127df4da0811c4120a523722d2_logo-backsmith-wordmark-light.svg" height="40" alt="Blacksmith" />
</a>
&nbsp;&nbsp;&nbsp;
<a href="https://www.cloudflare.com/">
<img src="https://sirv.sirv.com/website/screenshots/cloudflare/cloudflare-logo.png?w=300" height="40" alt="Cloudflare" />
</a>
&nbsp;&nbsp;&nbsp;
<a href="https://tailscale.com/">
<img src="https://drive.google.com/uc?export=view&id=1lIxkJuX6M23bW-2FElhT0rQieTrzaVSL" height="40" alt="Tailscale" />
</a>
&nbsp;&nbsp;&nbsp;
<a href="https://akamai.com/">
<img src="https://upload.wikimedia.org/wikipedia/commons/8/8b/Akamai_logo.svg" height="40" alt="Akamai" />
</a>
&nbsp;&nbsp;&nbsp;
<a href="https://aws.amazon.com/">
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/9/93/Amazon_Web_Services_Logo.svg/960px-Amazon_Web_Services_Logo.svg.png" height="40" alt="AWS" />
</a>
</div>
<br />
## Support
Wenn Sie Hilfe benotigen oder eine Funktion fur Termix anfragen mochten, besuchen Sie die [Issues](https://github.com/Termix-SSH/Support/issues)-Seite, melden Sie sich an und klicken Sie auf `New Issue`. Bitte beschreiben Sie Ihr Anliegen so detailliert wie moglich, vorzugsweise auf Englisch. Sie konnen auch dem [Discord](https://discord.gg/jVQGdvHDrf)-Server beitreten und den Support-Kanal besuchen, allerdings konnen die Antwortzeiten dort langer sein.
<br />
## Lizenz
Verteilt unter der Apache License Version 2.0. Siehe `LICENSE` fur weitere Informationen.
-405
View File
@@ -1,405 +0,0 @@
<div align="center">
<img src="../public/icon.svg" width="120" height="120" alt="Termix Logo" />
<h1>Termix</h1>
<p>Gestion SSH autoalojada y acceso a escritorio remoto</p>
<p>
<a href="../README.md">English</a> ·
<a href="README-CN.md">中文</a> ·
<a href="README-JA.md">日本語</a> ·
<a href="README-KO.md">한국어</a> ·
<a href="README-FR.md">Français</a> ·
<a href="README-DE.md">Deutsch</a> ·
Español ·
<a href="README-PT.md">Português</a> ·
<a href="README-RU.md">Русский</a> ·
<a href="README-AR.md">العربية</a> ·
<a href="README-HI.md">हिन्दी</a> ·
<a href="README-TR.md">Türkçe</a> ·
<a href="README-VI.md">Tiếng Việt</a> ·
<a href="README-IT.md">Italiano</a>
</p>
<p>
<img src="https://img.shields.io/github/stars/Termix-SSH/Termix?style=flat&label=Stars&color=F39044&labelColor=1a1a1a" />
<img src="https://img.shields.io/github/forks/Termix-SSH/Termix?style=flat&label=Forks&color=F39044&labelColor=1a1a1a" />
<img src="https://img.shields.io/github/v/release/Termix-SSH/Termix?style=flat&label=Release&color=F39044&labelColor=1a1a1a&v=1" />
<a href="https://discord.gg/jVQGdvHDrf"><img alt="Discord" src="https://img.shields.io/discord/1347374268253470720?color=F39044&labelColor=1a1a1a" /></a>
<a href="https://donate.termix.site/"><img alt="Donate" src="https://img.shields.io/badge/Donate-Support%20Termix-F39044?style=flat&labelColor=1a1a1a" /></a>
</p>
<br />
Termix es gratuito y de código abierto. Si lo encuentras útil, considera [donar](https://donate.termix.site/) para ayudar a cubrir los costos del servidor y el tiempo de desarrollo.
<a href="https://donate.termix.site/"><img src="../repo-images/donation-goal.svg" alt="Monthly donation goal" /></a>
<br />
<img src="../repo-images/Termix Header.png" alt="Termix Banner" width="900" />
<br />
<br />
<p>
<img src="../repo-images/Repo of the Day.png" alt="Repo of the Day Achievement" width="280" />
<br />
<sub>Logrado el 1 de septiembre de 2025</sub>
</p>
</div>
<br />
## Descripcion General
Termix es una plataforma de gestion de servidores todo en uno, de codigo abierto, siempre gratuita y autoalojada. Proporciona una solucion multiplataforma para gestionar sus servidores e infraestructura a traves de una interfaz unica e intuitiva. Termix ofrece acceso a terminal SSH, control de escritorio remoto (RDP, VNC, Telnet), capacidades de tuneles SSH, gestion remota de archivos SSH y muchas otras herramientas. Termix es la alternativa perfecta, gratuita y autoalojada a Termius, disponible para todas las plataformas.
<br />
## Caracteristicas
<table>
<tr>
<td width="50%" valign="top">
**Acceso a Terminal SSH:**
Terminal completo con soporte de pantalla dividida (hasta 4 paneles) con un sistema de pestanas similar al navegador. Incluye soporte para personalizar el terminal incluyendo temas comunes de terminal, fuentes y otros componentes.
</td>
<td width="50%" valign="top">
**Acceso a Escritorio Remoto:**
Soporte RDP, VNC y Telnet a traves del navegador con personalizacion completa y pantalla dividida.
</td>
</tr>
<tr>
<td width="50%" valign="top">
**Gestion de Tuneles SSH:**
Cree y gestione tuneles SSH de servidor a servidor con reconexion automatica, monitoreo de estado y reenvio local, remoto o dinamico SOCKS. La configuracion de tuneles de cliente de escritorio a servidor se almacena localmente por instalacion de escritorio; los snapshots de presets C2S opcionales pueden guardarse en el servidor, renombrarse, cargarse o eliminarse para mover una configuracion de tunel local entre clientes.
</td>
<td width="50%" valign="top">
**Gestor Remoto de Archivos:**
Gestione archivos directamente en servidores remotos con soporte para visualizar y editar codigo, imagenes, audio y video. Suba, descargue, renombre, elimine y mueva archivos sin problemas con soporte sudo.
</td>
</tr>
<tr>
<td width="50%" valign="top">
**Gestion de Docker y Podman:**
Inicie, detenga, pause, elimine contenedores. Vea estadisticas de contenedores. Controle contenedores usando el terminal docker exec. Compatible con Docker y Podman como entorno de ejecucion de contenedores. No fue creado para reemplazar Portainer o Dockge, sino para simplemente gestionar sus contenedores en lugar de crearlos.
</td>
<td width="50%" valign="top">
**Gestor de Hosts SSH:**
Guarde, organice y gestione sus conexiones SSH con etiquetas y carpetas (con personalizacion de carpetas y soporte de carpetas anidadas), y guarde facilmente informacion de inicio de sesion reutilizable con la capacidad de automatizar el despliegue de claves SSH.
</td>
</tr>
<tr>
<td width="50%" valign="top">
**Metricas del Host:**
Vea el uso de CPU, memoria y disco, red, tiempo de actividad, informacion del sistema, firewall, monitor de puertos, visor de registros, usuarios/permisos, certificados y muchos mas en la mayoria de los servidores basados en Linux.
</td>
<td width="50%" valign="top">
**Autenticacion de Usuarios:**
Gestion segura de usuarios con controles de administrador y soporte para OIDC/LDAP/SSO (con control de acceso) y 2FA (TOTP). Vea sesiones activas de usuarios en todas las plataformas y revoque permisos. Vincule sus cuentas OIDC/Locales entre si. Vea el registro de auditoria de las acciones de todos los usuarios.
</td>
</tr>
<tr>
<td width="50%" valign="top">
**Integracion con Tailscale:**
Liste dispositivos de su red Tailscale para agregarlos rapidamente como hosts y conectese usando Tailscale SSH como metodo de autenticacion, permitiendo que las ACL de Tailscale gestionen la autorizacion sin almacenar credenciales.
</td>
<td width="50%" valign="top">
**RBAC:**
Cree roles y comparta hosts entre usuarios/roles.
</td>
</tr>
<tr>
<td width="50%" valign="top">
**Conexiones Serie:**
Conectese a dispositivos serie (routers, switches, microcontroladores, etc.) directamente desde el navegador o la aplicacion de escritorio. Configure la tasa de baudios, bits de datos, bits de parada y paridad. Utiliza la Web Serial API en navegadores compatibles o un backend nativo en la aplicacion Electron.
</td>
<td width="50%" valign="top">
**Alertas:**
Configure reglas de alerta basadas en umbrales para metricas del host (CPU, memoria, disco, etc.) y reciba notificaciones a traves de ntfy o webhooks cuando se activen. Vea las alertas activas y resueltas en un historial de registros.
</td>
</tr>
<tr>
<td width="50%" valign="top">
**Pagina de Inicio:**
Una pagina de inicio completamente personalizable con una cuadricula de widgets de arrastrar y soltar. Agregue widgets para estado del host, enlaces de servicios, relojes, notas, feeds RSS, clima, contenedores Docker, graficos de metricas del host, terminales integrados, iframes y mas.
</td>
<td width="50%" valign="top">
**Cifrado de Base de Datos:**
Backend almacenado como archivos de base de datos SQLite cifrados. Consulte la [documentacion](https://docs.termix.site/security) para mas informacion.
</td>
</tr>
<tr>
<td width="50%" valign="top">
**Grafico de Red:**
Personalice su Dashboard para visualizar su homelab basado en sus conexiones SSH con soporte de estado.
</td>
<td width="50%" valign="top">
**Herramientas SSH:**
Cree fragmentos de comandos reutilizables que se ejecutan con un solo clic. Ejecute un comando simultaneamente en multiples terminales abiertos.
</td>
</tr>
<tr>
<td width="50%" valign="top">
**Pestanas Persistentes:**
Las sesiones SSH y pestanas permanecen abiertas entre dispositivos/actualizaciones si esta habilitado en el perfil de usuario.
</td>
<td width="50%" valign="top">
**Idiomas:**
Soporte integrado para aproximadamente 30 idiomas (gestionado por [Crowdin](https://docs.termix.site/translations)).
</td>
</tr>
</table>
<br />
<details>
<summary><b>Mas caracteristicas</b></summary>
<br />
- **Dashboard** - Vea la informacion del servidor de un vistazo en su dashboard
- **Claves API** - Cree claves API con ambito de usuario y fechas de vencimiento para usar en automatizacion/CI
- **Exportacion/Importacion de Datos** - Exporte e importe hosts SSH, credenciales y datos del gestor de archivos
- **Configuracion Automatica de SSL** - Generacion y gestion integrada de certificados SSL con redirecciones HTTPS
- **Interfaz Moderna** - Interfaz limpia compatible con escritorio/movil construida con React, Tailwind CSS y Shadcn. Elija entre muchos temas de UI diferentes, incluyendo claro, oscuro, Dracula, etc. Use rutas URL para abrir cualquier conexion en pantalla completa.
- **Historial de Comandos** - Autocompletado y visualizacion de comandos SSH ejecutados anteriormente
- **Conexion Rapida** - Conectese a un servidor sin necesidad de guardar los datos de conexion
- **Paleta de Comandos** - Pulse dos veces la tecla Shift izquierda para acceder rapidamente a las conexiones SSH con su teclado
- **Integracion con Proxmox** - Agregue automaticamente hosts a Termix desde su instancia de Proxmox
- **SSH Rico en Funciones** - Soporta jump hosts, Warpgate, conexiones basadas en TOTP, SOCKS5, verificacion de clave de host, autocompletado de contrasenas, [OPKSSH](https://github.com/openpubkey/opkssh), tmux, port knocking, registro de terminal, etc.
</details>
<br />
## Soporte de Plataformas
<table align="center">
<tr>
<th align="center">Plataforma</th>
<th align="center">Distribucion</th>
</tr>
<tr>
<td align="center"><b>Web</b></td>
<td>Cualquier navegador moderno (Chrome, Safari, Firefox) · Soporte PWA</td>
</tr>
<tr>
<td align="center"><b>Windows</b> <sub>x64/ia32</sub></td>
<td>Portable · Instalador MSI · Chocolatey</td>
</tr>
<tr>
<td align="center"><b>Linux</b> <sub>x64/ia32</sub></td>
<td>Portable · AUR · AppImage · Deb · Flatpak</td>
</tr>
<tr>
<td align="center"><b>macOS</b> <sub>x64/ia32, v12.0+</sub></td>
<td>Apple App Store · DMG · Homebrew</td>
</tr>
<tr>
<td align="center"><b>iOS/iPadOS</b> <sub>v15.1+</sub></td>
<td>Apple App Store · IPA</td>
</tr>
<tr>
<td align="center"><b>Android</b> <sub>v7.0+</sub></td>
<td>Google Play Store · APK</td>
</tr>
</table>
<br />
## Instalacion
Visite la [documentacion](https://docs.termix.site/install) de Termix para mas informacion sobre como instalar Termix en todas las plataformas. De lo contrario, vea un archivo Docker Compose de ejemplo aqui (puede omitir guacd y la red si no planea usar funciones de escritorio remoto):
```yaml
services:
termix:
image: ghcr.io/lukegus/termix:latest
container_name: termix
restart: unless-stopped
ports:
- "8080:8080"
volumes:
- termix-data:/app/data
environment:
PORT: "8080"
depends_on:
- guacd
networks:
- termix-net
guacd:
image: guacamole/guacd:1.6.0
container_name: guacd
restart: unless-stopped
ports:
- "4822:4822"
networks:
- termix-net
volumes:
termix-data:
driver: local
networks:
termix-net:
driver: bridge
```
<br />
## Donar
Termix es gratuito y de código abierto. Si lo encuentras útil, considera [donar](https://donate.termix.site/) para ayudar a cubrir los costos del servidor y el tiempo de desarrollo.
<a href="https://donate.termix.site/"><img src="../repo-images/donation-goal.svg" alt="Monthly donation goal" /></a>
<br />
## Capturas de Pantalla
<div align="center">
<br />
[![YouTube](../repo-images/YouTube.png)](https://www.youtube.com/@TermixSSH/videos)
<sub>Ver resúmenes de actualizaciones en YouTube</sub>
<br />
<br />
<table>
<tr>
<td><img src="../repo-images/Image 1.png" alt="Termix Screenshot 1" width="400" /></td>
<td><img src="../repo-images/Image 2.png" alt="Termix Screenshot 2" width="400" /></td>
</tr>
<tr>
<td><img src="../repo-images/Image 3.png" alt="Termix Screenshot 3" width="400" /></td>
<td><img src="../repo-images/Image 4.png" alt="Termix Screenshot 4" width="400" /></td>
</tr>
<tr>
<td><img src="../repo-images/Image 5.png" alt="Termix Screenshot 5" width="400" /></td>
<td><img src="../repo-images/Image 6.png" alt="Termix Screenshot 6" width="400" /></td>
</tr>
<tr>
<td><img src="../repo-images/Image 7.png" alt="Termix Screenshot 7" width="400" /></td>
<td><img src="../repo-images/Image 8.png" alt="Termix Screenshot 8" width="400" /></td>
</tr>
<tr>
<td><img src="../repo-images/Image 9.png" alt="Termix Screenshot 9" width="400" /></td>
<td><img src="../repo-images/Image 10.png" alt="Termix Screenshot 10" width="400" /></td>
</tr>
<tr>
<td><img src="../repo-images/Image 11.png" alt="Termix Screenshot 11" width="400" /></td>
<td><img src="../repo-images/Image 12.png" alt="Termix Screenshot 12" width="400" /></td>
</tr>
<tr>
<td><img src="../repo-images/Image 13.png" alt="Termix Screenshot 13" width="400" /></td>
<td><img src="../repo-images/Image 14.png" alt="Termix Screenshot 14" width="400" /></td>
</tr>
<tr>
<td><img src="../repo-images/Image 15.png" alt="Termix Screenshot 15" width="400" /></td>
<td><img src="../repo-images/Image 16.png" alt="Termix Screenshot 16" width="400" /></td>
</tr>
</table>
<sub>Algunos videos e imagenes pueden estar desactualizados o no mostrar perfectamente las caracteristicas.</sub>
</div>
<br />
## Caracteristicas Planeadas
Consulte [Proyectos](https://github.com/orgs/Termix-SSH/projects/5) para todas las caracteristicas planeadas. Si desea contribuir, consulte [Contribuir](https://github.com/Termix-SSH/Termix/blob/main/CONTRIBUTING.md).
<br />
## Patrocinadores
<div align="center">
<br />
<a href="https://www.digitalocean.com/">
<img src="https://opensource.nyc3.cdn.digitaloceanspaces.com/attribution/assets/SVG/DO_Logo_horizontal_blue.svg" height="40" alt="DigitalOcean" />
</a>
&nbsp;&nbsp;&nbsp;
<a href="https://crowdin.com/">
<img src="https://support.crowdin.com/assets/logos/core-logo/svg/crowdin-core-logo-cDark.svg" height="40" alt="Crowdin" />
</a>
&nbsp;&nbsp;&nbsp;
<a href="https://www.blacksmith.sh/">
<img src="https://cdn.prod.website-files.com/681bfb0c9a4601bc6e288ec4/683ca9e2c5186757092611b8_e8cb22127df4da0811c4120a523722d2_logo-backsmith-wordmark-light.svg" height="40" alt="Blacksmith" />
</a>
&nbsp;&nbsp;&nbsp;
<a href="https://www.cloudflare.com/">
<img src="https://sirv.sirv.com/website/screenshots/cloudflare/cloudflare-logo.png?w=300" height="40" alt="Cloudflare" />
</a>
&nbsp;&nbsp;&nbsp;
<a href="https://tailscale.com/">
<img src="https://drive.google.com/uc?export=view&id=1lIxkJuX6M23bW-2FElhT0rQieTrzaVSL" height="40" alt="Tailscale" />
</a>
&nbsp;&nbsp;&nbsp;
<a href="https://akamai.com/">
<img src="https://upload.wikimedia.org/wikipedia/commons/8/8b/Akamai_logo.svg" height="40" alt="Akamai" />
</a>
&nbsp;&nbsp;&nbsp;
<a href="https://aws.amazon.com/">
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/9/93/Amazon_Web_Services_Logo.svg/960px-Amazon_Web_Services_Logo.svg.png" height="40" alt="AWS" />
</a>
</div>
<br />
## Soporte
Si necesita ayuda o desea solicitar una funcion para Termix, visite la pagina de [Issues](https://github.com/Termix-SSH/Support/issues), inicie sesion y pulse `New Issue`. Por favor, sea lo mas detallado posible en su reporte, preferiblemente escrito en ingles. Tambien puede unirse al servidor de [Discord](https://discord.gg/jVQGdvHDrf) y visitar el canal de soporte, sin embargo, los tiempos de respuesta pueden ser mas largos.
<br />
## Licencia
Distribuido bajo la Licencia Apache Version 2.0. Consulte `LICENSE` para mas informacion.
-405
View File
@@ -1,405 +0,0 @@
<div align="center">
<img src="../public/icon.svg" width="120" height="120" alt="Termix Logo" />
<h1>Termix</h1>
<p>Gestion SSH auto-hebergee et acces bureau a distance</p>
<p>
<a href="../README.md">English</a> ·
<a href="README-CN.md">中文</a> ·
<a href="README-JA.md">日本語</a> ·
<a href="README-KO.md">한국어</a> ·
Français ·
<a href="README-DE.md">Deutsch</a> ·
<a href="README-ES.md">Español</a> ·
<a href="README-PT.md">Português</a> ·
<a href="README-RU.md">Русский</a> ·
<a href="README-AR.md">العربية</a> ·
<a href="README-HI.md">हिन्दी</a> ·
<a href="README-TR.md">Türkçe</a> ·
<a href="README-VI.md">Tiếng Việt</a> ·
<a href="README-IT.md">Italiano</a>
</p>
<p>
<img src="https://img.shields.io/github/stars/Termix-SSH/Termix?style=flat&label=Stars&color=F39044&labelColor=1a1a1a" />
<img src="https://img.shields.io/github/forks/Termix-SSH/Termix?style=flat&label=Forks&color=F39044&labelColor=1a1a1a" />
<img src="https://img.shields.io/github/v/release/Termix-SSH/Termix?style=flat&label=Release&color=F39044&labelColor=1a1a1a&v=1" />
<a href="https://discord.gg/jVQGdvHDrf"><img alt="Discord" src="https://img.shields.io/discord/1347374268253470720?color=F39044&labelColor=1a1a1a" /></a>
<a href="https://donate.termix.site/"><img alt="Donate" src="https://img.shields.io/badge/Donate-Support%20Termix-F39044?style=flat&labelColor=1a1a1a" /></a>
</p>
<br />
Termix est gratuit et open source. Si vous le trouvez utile, pensez à [faire un don](https://donate.termix.site/) pour aider à couvrir les coûts de serveur et le temps de développement.
<a href="https://donate.termix.site/"><img src="../repo-images/donation-goal.svg" alt="Monthly donation goal" /></a>
<br />
<img src="../repo-images/Termix Header.png" alt="Termix Banner" width="900" />
<br />
<br />
<p>
<img src="../repo-images/Repo of the Day.png" alt="Repo of the Day Achievement" width="280" />
<br />
<sub>Obtenu le 1er septembre 2025</sub>
</p>
</div>
<br />
## Presentation
Termix est une plateforme de gestion de serveurs tout-en-un, open source, a jamais gratuite et auto-hebergee. Elle fournit une solution multiplateforme pour gerer vos serveurs et votre infrastructure a travers une interface unique et intuitive. Termix offre un acces terminal SSH, le controle de bureau a distance (RDP, VNC, Telnet), des capacites de tunneling SSH, la gestion de fichiers SSH a distance et de nombreux autres outils. Termix est l'alternative parfaite, gratuite et auto-hebergee a Termius, disponible sur toutes les plateformes.
<br />
## Fonctionnalites
<table>
<tr>
<td width="50%" valign="top">
**Acces terminal SSH:**
Terminal complet avec support d'ecran partage (jusqu'a 4 panneaux) et un systeme d'onglets inspire des navigateurs. Inclut la personnalisation du terminal avec des themes courants, des polices et d'autres composants.
</td>
<td width="50%" valign="top">
**Acces Bureau a Distance:**
Support RDP, VNC et Telnet via navigateur avec personnalisation complete et ecran partage.
</td>
</tr>
<tr>
<td width="50%" valign="top">
**Gestion des tunnels SSH:**
Creez et gerez des tunnels SSH de serveur a serveur avec reconnexion automatique, surveillance de l'etat et transfert local, distant ou SOCKS dynamique. Les parametres de tunnel client-bureau-vers-serveur sont stockes localement par installation bureau ; des instantanes de prereglages C2S optionnels peuvent etre sauvegardes sur le serveur, renommes, charges ou supprimes pour deplacer une configuration de tunnel locale entre clients.
</td>
<td width="50%" valign="top">
**Gestionnaire de fichiers distant:**
Gerez les fichiers directement sur les serveurs distants avec support de la visualisation et de l'edition de code, images, audio et video. Televersez, telechargez, renommez, supprimez et deplacez des fichiers de maniere fluide avec support sudo.
</td>
</tr>
<tr>
<td width="50%" valign="top">
**Gestion Docker et Podman:**
Demarrez, arretez, mettez en pause, supprimez des conteneurs. Consultez les statistiques des conteneurs. Controlez les conteneurs via le terminal docker exec. Compatible avec Docker et Podman comme environnement d'execution de conteneurs. Non concu pour remplacer Portainer ou Dockge, mais plutot pour gerer simplement vos conteneurs plutot que de les creer.
</td>
<td width="50%" valign="top">
**Gestionnaire d'hotes SSH:**
Enregistrez, organisez et gerez vos connexions SSH avec des tags et des dossiers (personnalisation des dossiers et prise en charge des dossiers imbriques), et sauvegardez facilement les informations de connexion reutilisables tout en automatisant le deploiement des cles SSH.
</td>
</tr>
<tr>
<td width="50%" valign="top">
**Metriques d'hote:**
Visualisez l'utilisation du CPU, de la memoire, du disque, le reseau, le temps de fonctionnement, les informations systeme, le pare-feu, le moniteur de ports, le visualiseur de journaux, les utilisateurs/permissions, les certificats et bien plus encore sur la plupart des serveurs Linux.
</td>
<td width="50%" valign="top">
**Authentification des utilisateurs:**
Gestion securisee des utilisateurs avec controles administrateur et support OIDC/LDAP/SSO (avec controle d'acces) et 2FA (TOTP). Visualisez les sessions utilisateur actives sur toutes les plateformes et revoquez les permissions. Liez vos comptes OIDC/locaux ensemble. Consultez le journal d'audit des actions de tous les utilisateurs.
</td>
</tr>
<tr>
<td width="50%" valign="top">
**Integration Tailscale:**
Listez les appareils de votre reseau Tailscale pour les ajouter rapidement comme hotes, et connectez-vous en utilisant Tailscale SSH comme methode d'authentification, laissant les ACL de votre reseau gerer l'autorisation sans stocker de credentials.
</td>
<td width="50%" valign="top">
**RBAC:**
Creez des roles et partagez des hotes entre utilisateurs/roles.
</td>
</tr>
<tr>
<td width="50%" valign="top">
**Connexions Serie:**
Connectez-vous a des appareils serie (routeurs, commutateurs, microcontroleurs, etc.) directement depuis le navigateur ou l'application bureau. Configurez le debit en bauds, les bits de donnees, les bits d'arret et la parite. Utilise l'API Web Serial dans les navigateurs compatibles ou un backend natif dans l'application Electron.
</td>
<td width="50%" valign="top">
**Alertes:**
Definissez des regles d'alerte basees sur des seuils pour les metriques d'hote (CPU, memoire, disque, etc.) et recevez des notifications via ntfy ou webhooks lorsqu'elles se declenchent. Consultez les alertes actives et resolues dans un journal d'historique.
</td>
</tr>
<tr>
<td width="50%" valign="top">
**Page d'accueil:**
Une page d'accueil entierement personnalisable avec une grille de widgets glisser-deposer. Ajoutez des widgets pour l'etat des hotes, les liens de services, les horloges, les notes, les flux RSS, la meteo, les conteneurs Docker, les graphiques de metriques d'hote, les terminaux integres, les iframes et plus encore.
</td>
<td width="50%" valign="top">
**Chiffrement de la base de donnees:**
Le backend est stocke sous forme de fichiers de base de donnees SQLite chiffres. Consultez la [documentation](https://docs.termix.site/security) pour plus de details.
</td>
</tr>
<tr>
<td width="50%" valign="top">
**Graphe reseau:**
Personnalisez votre tableau de bord pour visualiser votre homelab base sur vos connexions SSH avec support des statuts.
</td>
<td width="50%" valign="top">
**Outils SSH:**
Creez des extraits de commandes reutilisables executables en un seul clic. Executez une commande simultanement sur plusieurs terminaux ouverts.
</td>
</tr>
<tr>
<td width="50%" valign="top">
**Onglets Persistants:**
Les sessions SSH et les onglets restent ouverts sur tous les appareils/actualisations si active dans le profil utilisateur.
</td>
<td width="50%" valign="top">
**Langues:**
Support integre d'environ 30 langues (gere par [Crowdin](https://docs.termix.site/translations)).
</td>
</tr>
</table>
<br />
<details>
<summary><b>Plus de fonctionnalites</b></summary>
<br />
- **Tableau de bord** - Consultez les informations de vos serveurs en un coup d'oeil depuis votre tableau de bord
- **Cles API** - Creez des cles API a portee utilisateur avec des dates d'expiration pour une utilisation en automatisation/CI
- **Export/Import de donnees** - Exportez et importez les hotes SSH, les identifiants et les donnees du gestionnaire de fichiers
- **Configuration SSL automatique** - Generation et gestion integrees de certificats SSL avec redirections HTTPS
- **Interface moderne** - Interface epuree compatible desktop/mobile construite avec React, Tailwind CSS et Shadcn. Choisissez parmi de nombreux themes d'interface utilisateur, notamment clair, sombre, Dracula, etc. Utilisez les routes URL pour ouvrir n'importe quelle connexion en plein ecran.
- **Historique des commandes** - Auto-completion et consultation des commandes SSH precedemment executees
- **Connexion rapide** - Connectez-vous a un serveur sans avoir a sauvegarder les donnees de connexion
- **Palette de commandes** - Appuyez deux fois sur Shift gauche pour acceder rapidement aux connexions SSH avec votre clavier
- **Integration Proxmox** - Ajoutez automatiquement des hotes dans Termix depuis votre instance Proxmox
- **SSH riche en fonctionnalites** - Support des hotes de rebond, Warpgate, connexions basees sur TOTP, SOCKS5, verification des cles d'hote, remplissage automatique des mots de passe, [OPKSSH](https://github.com/openpubkey/opkssh), tmux, port knocking, journalisation du terminal, etc.
</details>
<br />
## Support des plateformes
<table align="center">
<tr>
<th align="center">Plateforme</th>
<th align="center">Distribution</th>
</tr>
<tr>
<td align="center"><b>Web</b></td>
<td>Tout navigateur moderne (Chrome, Safari, Firefox) · Support PWA</td>
</tr>
<tr>
<td align="center"><b>Windows</b> <sub>x64/ia32</sub></td>
<td>Portable · MSI Installateur · Chocolatey</td>
</tr>
<tr>
<td align="center"><b>Linux</b> <sub>x64/ia32</sub></td>
<td>Portable · AUR · AppImage · Deb · Flatpak</td>
</tr>
<tr>
<td align="center"><b>macOS</b> <sub>x64/ia32, v12.0+</sub></td>
<td>Apple App Store · DMG · Homebrew</td>
</tr>
<tr>
<td align="center"><b>iOS/iPadOS</b> <sub>v15.1+</sub></td>
<td>Apple App Store · IPA</td>
</tr>
<tr>
<td align="center"><b>Android</b> <sub>v7.0+</sub></td>
<td>Google Play Store · APK</td>
</tr>
</table>
<br />
## Installation
Visitez la [documentation](https://docs.termix.site/install) de Termix pour plus d'informations sur l'installation de Termix sur toutes les plateformes. Voici un exemple de fichier Docker Compose (vous pouvez omettre guacd et le reseau si vous ne prevoyez pas d'utiliser les fonctionnalites de bureau a distance) :
```yaml
services:
termix:
image: ghcr.io/lukegus/termix:latest
container_name: termix
restart: unless-stopped
ports:
- "8080:8080"
volumes:
- termix-data:/app/data
environment:
PORT: "8080"
depends_on:
- guacd
networks:
- termix-net
guacd:
image: guacamole/guacd:1.6.0
container_name: guacd
restart: unless-stopped
ports:
- "4822:4822"
networks:
- termix-net
volumes:
termix-data:
driver: local
networks:
termix-net:
driver: bridge
```
<br />
## Faire un don
Termix est gratuit et open source. Si vous le trouvez utile, pensez à [faire un don](https://donate.termix.site/) pour aider à couvrir les coûts de serveur et le temps de développement.
<a href="https://donate.termix.site/"><img src="../repo-images/donation-goal.svg" alt="Monthly donation goal" /></a>
<br />
## Captures d'ecran
<div align="center">
<br />
[![YouTube](../repo-images/YouTube.png)](https://www.youtube.com/@TermixSSH/videos)
<sub>Regarder les aperçus des mises a jour sur YouTube</sub>
<br />
<br />
<table>
<tr>
<td><img src="../repo-images/Image 1.png" alt="Termix Screenshot 1" width="400" /></td>
<td><img src="../repo-images/Image 2.png" alt="Termix Screenshot 2" width="400" /></td>
</tr>
<tr>
<td><img src="../repo-images/Image 3.png" alt="Termix Screenshot 3" width="400" /></td>
<td><img src="../repo-images/Image 4.png" alt="Termix Screenshot 4" width="400" /></td>
</tr>
<tr>
<td><img src="../repo-images/Image 5.png" alt="Termix Screenshot 5" width="400" /></td>
<td><img src="../repo-images/Image 6.png" alt="Termix Screenshot 6" width="400" /></td>
</tr>
<tr>
<td><img src="../repo-images/Image 7.png" alt="Termix Screenshot 7" width="400" /></td>
<td><img src="../repo-images/Image 8.png" alt="Termix Screenshot 8" width="400" /></td>
</tr>
<tr>
<td><img src="../repo-images/Image 9.png" alt="Termix Screenshot 9" width="400" /></td>
<td><img src="../repo-images/Image 10.png" alt="Termix Screenshot 10" width="400" /></td>
</tr>
<tr>
<td><img src="../repo-images/Image 11.png" alt="Termix Screenshot 11" width="400" /></td>
<td><img src="../repo-images/Image 12.png" alt="Termix Screenshot 12" width="400" /></td>
</tr>
<tr>
<td><img src="../repo-images/Image 13.png" alt="Termix Screenshot 13" width="400" /></td>
<td><img src="../repo-images/Image 14.png" alt="Termix Screenshot 14" width="400" /></td>
</tr>
<tr>
<td><img src="../repo-images/Image 15.png" alt="Termix Screenshot 15" width="400" /></td>
<td><img src="../repo-images/Image 16.png" alt="Termix Screenshot 16" width="400" /></td>
</tr>
</table>
<sub>Certaines videos et images peuvent etre obsoletes ou ne pas presenter parfaitement les fonctionnalites.</sub>
</div>
<br />
## Fonctionnalites prevues
Consultez les [Projects](https://github.com/orgs/Termix-SSH/projects/5) pour toutes les fonctionnalites prevues. Si vous souhaitez contribuer, consultez [Contributing](https://github.com/Termix-SSH/Termix/blob/main/CONTRIBUTING.md).
<br />
## Sponsors
<div align="center">
<br />
<a href="https://www.digitalocean.com/">
<img src="https://opensource.nyc3.cdn.digitaloceanspaces.com/attribution/assets/SVG/DO_Logo_horizontal_blue.svg" height="40" alt="DigitalOcean" />
</a>
&nbsp;&nbsp;&nbsp;
<a href="https://crowdin.com/">
<img src="https://support.crowdin.com/assets/logos/core-logo/svg/crowdin-core-logo-cDark.svg" height="40" alt="Crowdin" />
</a>
&nbsp;&nbsp;&nbsp;
<a href="https://www.blacksmith.sh/">
<img src="https://cdn.prod.website-files.com/681bfb0c9a4601bc6e288ec4/683ca9e2c5186757092611b8_e8cb22127df4da0811c4120a523722d2_logo-backsmith-wordmark-light.svg" height="40" alt="Blacksmith" />
</a>
&nbsp;&nbsp;&nbsp;
<a href="https://www.cloudflare.com/">
<img src="https://sirv.sirv.com/website/screenshots/cloudflare/cloudflare-logo.png?w=300" height="40" alt="Cloudflare" />
</a>
&nbsp;&nbsp;&nbsp;
<a href="https://tailscale.com/">
<img src="https://drive.google.com/uc?export=view&id=1lIxkJuX6M23bW-2FElhT0rQieTrzaVSL" height="40" alt="Tailscale" />
</a>
&nbsp;&nbsp;&nbsp;
<a href="https://akamai.com/">
<img src="https://upload.wikimedia.org/wikipedia/commons/8/8b/Akamai_logo.svg" height="40" alt="Akamai" />
</a>
&nbsp;&nbsp;&nbsp;
<a href="https://aws.amazon.com/">
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/9/93/Amazon_Web_Services_Logo.svg/960px-Amazon_Web_Services_Logo.svg.png" height="40" alt="AWS" />
</a>
</div>
<br />
## Support
Si vous avez besoin d'aide ou souhaitez demander une fonctionnalite pour Termix, visitez la page [Issues](https://github.com/Termix-SSH/Support/issues), connectez-vous et appuyez sur `New Issue`. Veuillez etre aussi detaille que possible dans votre issue, de preference redigee en anglais. Vous pouvez egalement rejoindre le serveur [Discord](https://discord.gg/jVQGdvHDrf) et visiter le canal de support, cependant les temps de reponse peuvent etre plus longs.
<br />
## Licence
Distribue sous la licence Apache Version 2.0. Consultez `LICENSE` pour plus d'informations.
-405
View File
@@ -1,405 +0,0 @@
<div align="center">
<img src="../public/icon.svg" width="120" height="120" alt="Termix Logo" />
<h1>Termix</h1>
<p>स्व-होस्टेड SSH प्रबंधन और रिमोट डेस्कटॉप एक्सेस</p>
<p>
<a href="../README.md">English</a> ·
<a href="README-CN.md">中文</a> ·
<a href="README-JA.md">日本語</a> ·
<a href="README-KO.md">한국어</a> ·
<a href="README-FR.md">Français</a> ·
<a href="README-DE.md">Deutsch</a> ·
<a href="README-ES.md">Español</a> ·
<a href="README-PT.md">Português</a> ·
<a href="README-RU.md">Русский</a> ·
<a href="README-AR.md">العربية</a> ·
हिन्दी ·
<a href="README-TR.md">Türkçe</a> ·
<a href="README-VI.md">Tiếng Việt</a> ·
<a href="README-IT.md">Italiano</a>
</p>
<p>
<img src="https://img.shields.io/github/stars/Termix-SSH/Termix?style=flat&label=Stars&color=F39044&labelColor=1a1a1a" />
<img src="https://img.shields.io/github/forks/Termix-SSH/Termix?style=flat&label=Forks&color=F39044&labelColor=1a1a1a" />
<img src="https://img.shields.io/github/v/release/Termix-SSH/Termix?style=flat&label=Release&color=F39044&labelColor=1a1a1a&v=1" />
<a href="https://discord.gg/jVQGdvHDrf"><img alt="Discord" src="https://img.shields.io/discord/1347374268253470720?color=F39044&labelColor=1a1a1a" /></a>
<a href="https://donate.termix.site/"><img alt="Donate" src="https://img.shields.io/badge/Donate-Support%20Termix-F39044?style=flat&labelColor=1a1a1a" /></a>
</p>
<br />
Termix मुफ़्त और ओपन सोर्स है। यदि आपको यह उपयोगी लगता है, तो सर्वर लागत और विकास समय में मदद के लिए [दान करें](https://donate.termix.site/)।
<a href="https://donate.termix.site/"><img src="../repo-images/donation-goal.svg" alt="Monthly donation goal" /></a>
<br />
<img src="../repo-images/Termix Header.png" alt="Termix Banner" width="900" />
<br />
<br />
<p>
<img src="../repo-images/Repo of the Day.png" alt="Repo of the Day Achievement" width="280" />
<br />
<sub>1 सितंबर, 2025 को प्राप्त</sub>
</p>
</div>
<br />
## अवलोकन
Termix एक ओपन-सोर्स, हमेशा के लिए मुफ़्त, सेल्फ-होस्टेड ऑल-इन-वन सर्वर प्रबंधन प्लेटफ़ॉर्म है। यह एक एकल, सहज इंटरफ़ेस के माध्यम से आपके सर्वर और बुनियादी ढाँचे के प्रबंधन के लिए एक मल्टी-प्लेटफ़ॉर्म समाधान प्रदान करता है। Termix SSH टर्मिनल एक्सेस, रिमोट डेस्कटॉप कंट्रोल (RDP, VNC, Telnet), SSH टनलिंग क्षमताएँ, रिमोट SSH फ़ाइल प्रबंधन, और कई अन्य उपकरण प्रदान करता है। Termix सभी प्लेटफ़ॉर्म पर उपलब्ध Termius का सही मुफ़्त और सेल्फ-होस्टेड विकल्प है।
<br />
## विशेषताएँ
<table>
<tr>
<td width="50%" valign="top">
**SSH टर्मिनल एक्सेस:**
ब्राउज़र जैसी टैब प्रणाली के साथ स्प्लिट-स्क्रीन सपोर्ट (4 पैनल तक) वाला पूर्ण-विशेषता वाला टर्मिनल। इसमें लोकप्रिय टर्मिनल थीम, फ़ॉन्ट और अन्य कंपोनेंट सहित टर्मिनल को कस्टमाइज़ करने का सपोर्ट शामिल है।
</td>
<td width="50%" valign="top">
**रिमोट डेस्कटॉप एक्सेस:**
ब्राउज़र पर RDP, VNC और Telnet सपोर्ट, पूर्ण कस्टमाइज़ेशन और स्प्लिट स्क्रीन के साथ।
</td>
</tr>
<tr>
<td width="50%" valign="top">
**SSH टनल प्रबंधन:**
ऑटोमैटिक रीकनेक्शन, हेल्थ मॉनिटरिंग और लोकल, रिमोट या डायनेमिक SOCKS फॉरवर्डिंग के साथ सर्वर-टु-सर्वर SSH टनल बनाएँ और प्रबंधित करें। डेस्कटॉप क्लाइंट-टु-सर्वर टनल सेटिंग्स प्रत्येक डेस्कटॉप इंस्टॉल में स्थानीय रूप से संग्रहीत होती हैं; वैकल्पिक C2S प्रीसेट स्नैपशॉट सर्वर पर सेव, रीनेम, लोड या डिलीट किए जा सकते हैं।
</td>
<td width="50%" valign="top">
**रिमोट फ़ाइल मैनेजर:**
कोड, इमेज, ऑडियो और वीडियो देखने और संपादित करने के सपोर्ट के साथ रिमोट सर्वर पर सीधे फ़ाइलें प्रबंधित करें। sudo सपोर्ट के साथ फ़ाइलें अपलोड, डाउनलोड, रीनेम, डिलीट और मूव करें।
</td>
</tr>
<tr>
<td width="50%" valign="top">
**Docker और Podman प्रबंधन:**
कंटेनर शुरू, बंद, पॉज़, हटाएँ। कंटेनर स्टैट्स देखें। docker exec टर्मिनल का उपयोग करके कंटेनर को नियंत्रित करें। Docker और Podman दोनों को कंटेनर रनटाइम के रूप में सपोर्ट करता है। इसे Portainer या Dockge की जगह लेने के लिए नहीं बनाया गया बल्कि कंटेनर बनाने की तुलना में उन्हें सरलता से प्रबंधित करने के लिए बनाया गया है।
</td>
<td width="50%" valign="top">
**SSH होस्ट मैनेजर:**
टैग और फ़ोल्डर (फ़ोल्डर कस्टमाइज़ेशन और नेस्टेड फ़ोल्डर सपोर्ट के साथ) के साथ अपने SSH कनेक्शन सहेजें, व्यवस्थित करें और प्रबंधित करें, और SSH कुंजियों की तैनाती को स्वचालित करने की क्षमता के साथ पुन: उपयोग योग्य लॉगिन जानकारी आसानी से सहेजें।
</td>
</tr>
<tr>
<td width="50%" valign="top">
**होस्ट मेट्रिक्स:**
अधिकांश Linux आधारित सर्वर पर CPU, मेमोरी, डिस्क उपयोग, नेटवर्क, अपटाइम, सिस्टम जानकारी, फ़ायरवॉल, पोर्ट मॉनिटर, लॉग व्यूअर, उपयोगकर्ता/अनुमतियाँ, सर्टिफ़िकेट और भी बहुत कुछ देखें।
</td>
<td width="50%" valign="top">
**उपयोगकर्ता प्रमाणीकरण:**
व्यवस्थापक नियंत्रण और OIDC/LDAP/SSO (एक्सेस कंट्रोल के साथ) और 2FA (TOTP) सपोर्ट के साथ सुरक्षित उपयोगकर्ता प्रबंधन। सभी प्लेटफ़ॉर्म पर सक्रिय उपयोगकर्ता सत्र देखें और अनुमतियाँ रद्द करें। अपने OIDC/स्थानीय खातों को एक साथ जोड़ें। सभी उपयोगकर्ताओं की कार्रवाइयों का ऑडिट लॉग देखें।
</td>
</tr>
<tr>
<td width="50%" valign="top">
**Tailscale एकीकरण:**
अपने Tailscale नेटवर्क के डिवाइस सूचीबद्ध करें ताकि उन्हें जल्दी से होस्ट के रूप में जोड़ा जा सके, और Tailscale SSH को प्रमाणीकरण विधि के रूप में उपयोग करके कनेक्ट करें, जिससे आपके Tailscale ACL क्रेडेंशियल संग्रहीत किए बिना प्राधिकरण संभाल सकें।
</td>
<td width="50%" valign="top">
**RBAC:**
भूमिकाएँ बनाएँ और उपयोगकर्ताओं/भूमिकाओं में होस्ट साझा करें।
</td>
</tr>
<tr>
<td width="50%" valign="top">
**सीरियल कनेक्शन:**
सीरियल डिवाइस (राउटर, स्विच, माइक्रोकंट्रोलर आदि) से सीधे ब्राउज़र या डेस्कटॉप ऐप से कनेक्ट करें। बॉड रेट, डेटा बिट्स, स्टॉप बिट्स और पैरिटी कॉन्फ़िगर करें। समर्थित ब्राउज़र में Web Serial API या Electron ऐप में नेटिव बैकएंड का उपयोग करता है।
</td>
<td width="50%" valign="top">
**अलर्ट:**
होस्ट मेट्रिक्स (CPU, मेमोरी, डिस्क आदि) पर थ्रेशोल्ड-आधारित अलर्ट नियम सेट करें और जब वे ट्रिगर हों तो ntfy या webhooks के माध्यम से सूचना पाएँ। इतिहास लॉग में सक्रिय और हल किए गए अलर्ट देखें।
</td>
</tr>
<tr>
<td width="50%" valign="top">
**होमपेज:**
ड्रैग-एंड-ड्रॉप विजेट ग्रिड के साथ पूरी तरह से कस्टमाइज़ करने योग्य होमपेज। होस्ट स्टेटस, सर्विस लिंक, घड़ियाँ, नोट्स, RSS फ़ीड, मौसम, Docker कंटेनर, होस्ट मेट्रिक्स चार्ट, एम्बेडेड टर्मिनल, iframes और अन्य के लिए विजेट जोड़ें।
</td>
<td width="50%" valign="top">
**डेटाबेस एन्क्रिप्शन:**
बैकएंड एन्क्रिप्टेड SQLite डेटाबेस फ़ाइलों के रूप में संग्रहीत। अधिक जानकारी के लिए [डॉक्स](https://docs.termix.site/security) देखें।
</td>
</tr>
<tr>
<td width="50%" valign="top">
**नेटवर्क ग्राफ़:**
स्थिति सपोर्ट के साथ अपने SSH कनेक्शन के आधार पर अपने होमलैब को विज़ुअलाइज़ करने के लिए अपना डैशबोर्ड कस्टमाइज़ करें।
</td>
<td width="50%" valign="top">
**SSH टूल्स:**
एक क्लिक से निष्पादित होने वाले पुन: उपयोग योग्य कमांड स्निपेट बनाएँ। एक साथ कई खुले टर्मिनलों में एक कमांड चलाएँ।
</td>
</tr>
<tr>
<td width="50%" valign="top">
**परसिस्टेंट टैब:**
उपयोगकर्ता प्रोफ़ाइल में सक्षम होने पर SSH सेशन और टैब डिवाइस/रीफ्रेश के पार खुले रहते हैं।
</td>
<td width="50%" valign="top">
**भाषाएँ:**
लगभग 30 भाषाओं का बिल्ट-इन सपोर्ट ([Crowdin](https://docs.termix.site/translations) द्वारा प्रबंधित)।
</td>
</tr>
</table>
<br />
<details>
<summary><b>अधिक विशेषताएँ</b></summary>
<br />
- **डैशबोर्ड** - अपने डैशबोर्ड पर एक नज़र में सर्वर की जानकारी देखें
- **API कुंजियाँ** - ऑटोमेशन/CI के लिए उपयोग हेतु समाप्ति तिथियों के साथ उपयोगकर्ता-स्कोप्ड API कुंजियाँ बनाएँ
- **डेटा एक्सपोर्ट/इम्पोर्ट** - SSH होस्ट, क्रेडेंशियल और फ़ाइल मैनेजर डेटा एक्सपोर्ट और इम्पोर्ट करें
- **स्वचालित SSL सेटअप** - HTTPS रीडायरेक्ट के साथ बिल्ट-इन SSL सर्टिफ़िकेट जनरेशन और प्रबंधन
- **आधुनिक UI** - React, Tailwind CSS, और Shadcn से बना साफ़ डेस्कटॉप/मोबाइल-फ़्रेंडली इंटरफ़ेस। लाइट, डार्क, ड्रैकुला आदि सहित कई अलग-अलग UI थीम के बीच चुनें। किसी भी कनेक्शन को फ़ुल-स्क्रीन में खोलने के लिए URL रूट का उपयोग करें।
- **कमांड इतिहास** - पहले चलाए गए SSH कमांड का ऑटो-कम्प्लीट और दृश्य
- **क्विक कनेक्ट** - कनेक्शन डेटा सहेजे बिना सर्वर से कनेक्ट करें
- **कमांड पैलेट** - अपने कीबोर्ड से SSH कनेक्शन तक त्वरित पहुँच के लिए बाएँ Shift को दो बार टैप करें
- **Proxmox एकीकरण** - अपने Proxmox इंस्टेंस से Termix में होस्ट स्वचालित रूप से जोड़ें
- **SSH सुविधाओं से भरपूर** - जम्प होस्ट, Warpgate, TOTP आधारित कनेक्शन, SOCKS5, होस्ट की वेरिफ़िकेशन, पासवर्ड ऑटोफ़िल, [OPKSSH](https://github.com/openpubkey/opkssh), tmux, पोर्ट नॉकिंग, टर्मिनल लॉगिंग आदि का सपोर्ट
</details>
<br />
## प्लेटफ़ॉर्म सपोर्ट
<table align="center">
<tr>
<th align="center">प्लेटफ़ॉर्म</th>
<th align="center">वितरण</th>
</tr>
<tr>
<td align="center"><b>Web</b></td>
<td>कोई भी आधुनिक ब्राउज़र (Chrome, Safari, Firefox) · PWA सपोर्ट</td>
</tr>
<tr>
<td align="center"><b>Windows</b> <sub>x64/ia32</sub></td>
<td>पोर्टेबल · MSI इंस्टॉलर · Chocolatey</td>
</tr>
<tr>
<td align="center"><b>Linux</b> <sub>x64/ia32</sub></td>
<td>पोर्टेबल · AUR · AppImage · Deb · Flatpak</td>
</tr>
<tr>
<td align="center"><b>macOS</b> <sub>x64/ia32, v12.0+</sub></td>
<td>Apple App Store · DMG · Homebrew</td>
</tr>
<tr>
<td align="center"><b>iOS/iPadOS</b> <sub>v15.1+</sub></td>
<td>Apple App Store · IPA</td>
</tr>
<tr>
<td align="center"><b>Android</b> <sub>v7.0+</sub></td>
<td>Google Play Store · APK</td>
</tr>
</table>
<br />
## इंस्टॉलेशन
सभी प्लेटफ़ॉर्म पर Termix इंस्टॉल करने के बारे में अधिक जानकारी के लिए Termix [डॉक्स](https://docs.termix.site/install) पर जाएँ। यहाँ एक नमूना Docker Compose फ़ाइल देखें (यदि आप रिमोट डेस्कटॉप सुविधाओं का उपयोग करने की योजना नहीं बना रहे हैं तो आप guacd और नेटवर्क को हटा सकते हैं):
```yaml
services:
termix:
image: ghcr.io/lukegus/termix:latest
container_name: termix
restart: unless-stopped
ports:
- "8080:8080"
volumes:
- termix-data:/app/data
environment:
PORT: "8080"
depends_on:
- guacd
networks:
- termix-net
guacd:
image: guacamole/guacd:1.6.0
container_name: guacd
restart: unless-stopped
ports:
- "4822:4822"
networks:
- termix-net
volumes:
termix-data:
driver: local
networks:
termix-net:
driver: bridge
```
<br />
## दान करें
Termix मुफ़्त और ओपन सोर्स है। यदि आपको यह उपयोगी लगता है, तो सर्वर लागत और विकास समय में मदद के लिए [दान करें](https://donate.termix.site/)।
<a href="https://donate.termix.site/"><img src="../repo-images/donation-goal.svg" alt="Monthly donation goal" /></a>
<br />
## स्क्रीनशॉट
<div align="center">
<br />
[![YouTube](../repo-images/YouTube.png)](https://www.youtube.com/@TermixSSH/videos)
<sub>YouTube पर अपडेट की समीक्षाएँ देखें</sub>
<br />
<br />
<table>
<tr>
<td><img src="../repo-images/Image 1.png" alt="Termix Screenshot 1" width="400" /></td>
<td><img src="../repo-images/Image 2.png" alt="Termix Screenshot 2" width="400" /></td>
</tr>
<tr>
<td><img src="../repo-images/Image 3.png" alt="Termix Screenshot 3" width="400" /></td>
<td><img src="../repo-images/Image 4.png" alt="Termix Screenshot 4" width="400" /></td>
</tr>
<tr>
<td><img src="../repo-images/Image 5.png" alt="Termix Screenshot 5" width="400" /></td>
<td><img src="../repo-images/Image 6.png" alt="Termix Screenshot 6" width="400" /></td>
</tr>
<tr>
<td><img src="../repo-images/Image 7.png" alt="Termix Screenshot 7" width="400" /></td>
<td><img src="../repo-images/Image 8.png" alt="Termix Screenshot 8" width="400" /></td>
</tr>
<tr>
<td><img src="../repo-images/Image 9.png" alt="Termix Screenshot 9" width="400" /></td>
<td><img src="../repo-images/Image 10.png" alt="Termix Screenshot 10" width="400" /></td>
</tr>
<tr>
<td><img src="../repo-images/Image 11.png" alt="Termix Screenshot 11" width="400" /></td>
<td><img src="../repo-images/Image 12.png" alt="Termix Screenshot 12" width="400" /></td>
</tr>
<tr>
<td><img src="../repo-images/Image 13.png" alt="Termix Screenshot 13" width="400" /></td>
<td><img src="../repo-images/Image 14.png" alt="Termix Screenshot 14" width="400" /></td>
</tr>
<tr>
<td><img src="../repo-images/Image 15.png" alt="Termix Screenshot 15" width="400" /></td>
<td><img src="../repo-images/Image 16.png" alt="Termix Screenshot 16" width="400" /></td>
</tr>
</table>
<sub>कुछ वीडियो और छवियाँ पुरानी हो सकती हैं या विशेषताओं को पूरी तरह से प्रदर्शित नहीं कर सकती हैं।</sub>
</div>
<br />
## नियोजित विशेषताएँ
सभी नियोजित विशेषताओं के लिए [प्रोजेक्ट्स](https://github.com/orgs/Termix-SSH/projects/5) देखें। यदि आप योगदान देना चाहते हैं, तो [योगदान](https://github.com/Termix-SSH/Termix/blob/main/CONTRIBUTING.md) देखें।
<br />
## प्रायोजक
<div align="center">
<br />
<a href="https://www.digitalocean.com/">
<img src="https://opensource.nyc3.cdn.digitaloceanspaces.com/attribution/assets/SVG/DO_Logo_horizontal_blue.svg" height="40" alt="DigitalOcean" />
</a>
&nbsp;&nbsp;&nbsp;
<a href="https://crowdin.com/">
<img src="https://support.crowdin.com/assets/logos/core-logo/svg/crowdin-core-logo-cDark.svg" height="40" alt="Crowdin" />
</a>
&nbsp;&nbsp;&nbsp;
<a href="https://www.blacksmith.sh/">
<img src="https://cdn.prod.website-files.com/681bfb0c9a4601bc6e288ec4/683ca9e2c5186757092611b8_e8cb22127df4da0811c4120a523722d2_logo-backsmith-wordmark-light.svg" height="40" alt="Blacksmith" />
</a>
&nbsp;&nbsp;&nbsp;
<a href="https://www.cloudflare.com/">
<img src="https://sirv.sirv.com/website/screenshots/cloudflare/cloudflare-logo.png?w=300" height="40" alt="Cloudflare" />
</a>
&nbsp;&nbsp;&nbsp;
<a href="https://tailscale.com/">
<img src="https://drive.google.com/uc?export=view&id=1lIxkJuX6M23bW-2FElhT0rQieTrzaVSL" height="40" alt="Tailscale" />
</a>
&nbsp;&nbsp;&nbsp;
<a href="https://akamai.com/">
<img src="https://upload.wikimedia.org/wikipedia/commons/8/8b/Akamai_logo.svg" height="40" alt="Akamai" />
</a>
&nbsp;&nbsp;&nbsp;
<a href="https://aws.amazon.com/">
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/9/93/Amazon_Web_Services_Logo.svg/960px-Amazon_Web_Services_Logo.svg.png" height="40" alt="AWS" />
</a>
</div>
<br />
## सहायता
यदि आपको सहायता चाहिए या Termix के लिए किसी विशेषता का अनुरोध करना चाहते हैं, तो [इश्यूज़](https://github.com/Termix-SSH/Support/issues) पेज पर जाएँ, लॉग इन करें, और `New Issue` दबाएँ। कृपया अपने इश्यू में यथासंभव विस्तृत विवरण दें, अधिमानतः अंग्रेज़ी में लिखें। आप [Discord](https://discord.gg/jVQGdvHDrf) सर्वर में भी शामिल हो सकते हैं और सहायता चैनल पर जा सकते हैं, हालाँकि, प्रतिक्रिया समय अधिक हो सकता है।
<br />
## लाइसेंस
Apache License Version 2.0 के तहत वितरित। अधिक जानकारी के लिए `LICENSE` देखें।
-405
View File
@@ -1,405 +0,0 @@
<div align="center">
<img src="../public/icon.svg" width="120" height="120" alt="Termix Logo" />
<h1>Termix</h1>
<p>Gestione SSH self-hosted e accesso al desktop remoto</p>
<p>
<a href="../README.md">English</a> ·
<a href="README-CN.md">中文</a> ·
<a href="README-JA.md">日本語</a> ·
<a href="README-KO.md">한국어</a> ·
<a href="README-FR.md">Français</a> ·
<a href="README-DE.md">Deutsch</a> ·
<a href="README-ES.md">Español</a> ·
<a href="README-PT.md">Português</a> ·
<a href="README-RU.md">Русский</a> ·
<a href="README-AR.md">العربية</a> ·
<a href="README-HI.md">हिन्दी</a> ·
<a href="README-TR.md">Türkçe</a> ·
<a href="README-VI.md">Tiếng Việt</a> ·
Italiano
</p>
<p>
<img src="https://img.shields.io/github/stars/Termix-SSH/Termix?style=flat&label=Stars&color=F39044&labelColor=1a1a1a" />
<img src="https://img.shields.io/github/forks/Termix-SSH/Termix?style=flat&label=Forks&color=F39044&labelColor=1a1a1a" />
<img src="https://img.shields.io/github/v/release/Termix-SSH/Termix?style=flat&label=Release&color=F39044&labelColor=1a1a1a&v=1" />
<a href="https://discord.gg/jVQGdvHDrf"><img alt="Discord" src="https://img.shields.io/discord/1347374268253470720?color=F39044&labelColor=1a1a1a" /></a>
<a href="https://donate.termix.site/"><img alt="Donate" src="https://img.shields.io/badge/Donate-Support%20Termix-F39044?style=flat&labelColor=1a1a1a" /></a>
</p>
<br />
Termix è gratuito e open source. Se lo trovi utile, considera di [donare](https://donate.termix.site/) per aiutare a coprire i costi del server e il tempo di sviluppo.
<a href="https://donate.termix.site/"><img src="../repo-images/donation-goal.svg" alt="Monthly donation goal" /></a>
<br />
<img src="../repo-images/Termix Header.png" alt="Termix Banner" width="900" />
<br />
<br />
<p>
<img src="../repo-images/Repo of the Day.png" alt="Repo of the Day Achievement" width="280" />
<br />
<sub>Ottenuto il 1 settembre 2025</sub>
</p>
</div>
<br />
## Panoramica
Termix e una piattaforma di gestione server tutto-in-uno, open-source, per sempre gratuita e self-hosted. Fornisce una soluzione multipiattaforma per gestire i tuoi server e la tua infrastruttura attraverso un'unica interfaccia intuitiva. Termix offre accesso al terminale SSH, controllo remoto del desktop (RDP, VNC, Telnet), funzionalita di tunneling SSH, gestione remota dei file SSH e molti altri strumenti. Termix e la perfetta alternativa gratuita e self-hosted a Termius, disponibile per tutte le piattaforme.
<br />
## Funzionalita
<table>
<tr>
<td width="50%" valign="top">
**Accesso Terminale SSH:**
Terminale completo con supporto schermo diviso (fino a 4 pannelli) con un sistema di schede in stile browser. Include il supporto per la personalizzazione del terminale, inclusi temi, font e altri componenti comuni.
</td>
<td width="50%" valign="top">
**Accesso Desktop Remoto:**
Supporto RDP, VNC e Telnet tramite browser con personalizzazione completa e schermo diviso.
</td>
</tr>
<tr>
<td width="50%" valign="top">
**Gestione Tunnel SSH:**
Crea e gestisci tunnel SSH da server a server con riconnessione automatica, monitoraggio dello stato e inoltro locale, remoto o SOCKS dinamico. Le impostazioni del tunnel da client desktop a server sono archiviate localmente per ogni installazione desktop; gli snapshot di preset C2S opzionali possono essere salvati sul server, rinominati, caricati o eliminati per spostare una configurazione di tunnel locale tra i client.
</td>
<td width="50%" valign="top">
**Gestore File Remoto:**
Gestisci i file direttamente sui server remoti con supporto per la visualizzazione e la modifica di codice, immagini, audio e video. Carica, scarica, rinomina, elimina e sposta file senza problemi con supporto sudo.
</td>
</tr>
<tr>
<td width="50%" valign="top">
**Gestione Docker e Podman:**
Avvia, ferma, metti in pausa, rimuovi container. Visualizza le statistiche dei container. Controlla i container tramite terminale docker exec. Supporta sia Docker che Podman come runtime dei container. Non e stato creato per sostituire Portainer o Dockge, ma piuttosto per gestire semplicemente i tuoi container rispetto alla loro creazione.
</td>
<td width="50%" valign="top">
**Gestore Host SSH:**
Salva, organizza e gestisci le tue connessioni SSH con tag e cartelle (con personalizzazione delle cartelle e supporto per cartelle annidate), salva facilmente le informazioni di accesso riutilizzabili e automatizza il deployment delle chiavi SSH.
</td>
</tr>
<tr>
<td width="50%" valign="top">
**Metriche Host:**
Visualizza l'utilizzo di CPU, memoria, disco, rete, uptime, informazioni di sistema, firewall, monitoraggio porte, visualizzatore di log, utenti/permessi, certificati e molto altro sulla maggior parte dei server basati su Linux.
</td>
<td width="50%" valign="top">
**Autenticazione Utente:**
Gestione utenti sicura con controlli amministrativi e supporto OIDC/LDAP/SSO (con controllo degli accessi) e 2FA (TOTP). Visualizza le sessioni utente attive su tutte le piattaforme e revoca i permessi. Collega i tuoi account OIDC/Locali tra loro. Visualizza il log di controllo delle azioni di tutti gli utenti.
</td>
</tr>
<tr>
<td width="50%" valign="top">
**Integrazione Tailscale:**
Elenca i dispositivi della tua rete Tailscale per aggiungerli rapidamente come host, e connettiti utilizzando Tailscale SSH come metodo di autenticazione, lasciando che le ACL della tua rete gestiscano l'autorizzazione senza memorizzare credenziali.
</td>
<td width="50%" valign="top">
**RBAC:**
Crea ruoli e condividi host tra utenti/ruoli.
</td>
</tr>
<tr>
<td width="50%" valign="top">
**Connessioni Seriali:**
Connettiti a dispositivi seriali (router, switch, microcontrollori, ecc.) direttamente dal browser o dall'app desktop. Configura baud rate, bit di dati, bit di stop e parita. Utilizza la Web Serial API nei browser supportati o un backend nativo nell'app Electron.
</td>
<td width="50%" valign="top">
**Avvisi:**
Imposta regole di avviso basate su soglie per le metriche dell'host (CPU, memoria, disco, ecc.) e ricevi notifiche tramite ntfy o webhook quando si attivano. Visualizza gli avvisi attivi e risolti in un registro storico.
</td>
</tr>
<tr>
<td width="50%" valign="top">
**Homepage:**
Una homepage completamente personalizzabile con una griglia di widget drag-and-drop. Aggiungi widget per lo stato dell'host, link ai servizi, orologi, note, feed RSS, meteo, container Docker, grafici delle metriche dell'host, terminali incorporati, iframe e altro ancora.
</td>
<td width="50%" valign="top">
**Crittografia Database:**
Il backend e archiviato come file di database SQLite crittografati. Consulta la [documentazione](https://docs.termix.site/security) per maggiori informazioni.
</td>
</tr>
<tr>
<td width="50%" valign="top">
**Grafico di Rete:**
Personalizza la tua Dashboard per visualizzare il tuo homelab basato sulle connessioni SSH con supporto dello stato.
</td>
<td width="50%" valign="top">
**Strumenti SSH:**
Crea snippet di comandi riutilizzabili che si eseguono con un singolo clic. Esegui un comando simultaneamente su piu terminali aperti.
</td>
</tr>
<tr>
<td width="50%" valign="top">
**Schede Persistenti:**
Le sessioni SSH e le schede rimangono aperte tra dispositivi/aggiornamenti se abilitato nel profilo utente.
</td>
<td width="50%" valign="top">
**Lingue:**
Supporto integrato per circa 30 lingue (gestito da [Crowdin](https://docs.termix.site/translations)).
</td>
</tr>
</table>
<br />
<details>
<summary><b>Altre funzionalita</b></summary>
<br />
- **Dashboard** - Visualizza le informazioni del server a colpo d'occhio sulla tua dashboard
- **Chiavi API** - Crea chiavi API con ambito utente e date di scadenza da utilizzare per automazione/CI
- **Esportazione/Importazione Dati** - Esporta e importa host SSH, credenziali e dati del gestore file
- **Configurazione SSL Automatica** - Generazione e gestione integrata dei certificati SSL con reindirizzamenti HTTPS
- **Interfaccia Moderna** - Interfaccia pulita e responsive per desktop/mobile costruita con React, Tailwind CSS e Shadcn. Scegli tra molti temi UI diversi, inclusi chiaro, scuro, Dracula, ecc. Usa i percorsi URL per aprire qualsiasi connessione a schermo intero.
- **Cronologia Comandi** - Autocompletamento e visualizzazione dei comandi SSH eseguiti in precedenza
- **Connessione Rapida** - Connettiti a un server senza dover salvare i dati di connessione
- **Palette Comandi** - Premi due volte shift sinistro per accedere rapidamente alle connessioni SSH con la tastiera
- **Integrazione Proxmox** - Aggiungi automaticamente host a Termix dalla tua istanza Proxmox
- **SSH Ricco di Funzionalita** - Supporta jump host, Warpgate, connessioni basate su TOTP, SOCKS5, verifica chiave host, compilazione automatica password, [OPKSSH](https://github.com/openpubkey/opkssh), tmux, port knocking, registrazione terminale, ecc.
</details>
<br />
## Supporto Piattaforme
<table align="center">
<tr>
<th align="center">Piattaforma</th>
<th align="center">Distribuzione</th>
</tr>
<tr>
<td align="center"><b>Web</b></td>
<td>Qualsiasi browser moderno (Chrome, Safari, Firefox) · Supporto PWA</td>
</tr>
<tr>
<td align="center"><b>Windows</b> <sub>x64/ia32</sub></td>
<td>Portable · MSI Installer · Chocolatey</td>
</tr>
<tr>
<td align="center"><b>Linux</b> <sub>x64/ia32</sub></td>
<td>Portable · AUR · AppImage · Deb · Flatpak</td>
</tr>
<tr>
<td align="center"><b>macOS</b> <sub>x64/ia32, v12.0+</sub></td>
<td>Apple App Store · DMG · Homebrew</td>
</tr>
<tr>
<td align="center"><b>iOS/iPadOS</b> <sub>v15.1+</sub></td>
<td>Apple App Store · IPA</td>
</tr>
<tr>
<td align="center"><b>Android</b> <sub>v7.0+</sub></td>
<td>Google Play Store · APK</td>
</tr>
</table>
<br />
## Installazione
Visita la [Documentazione](https://docs.termix.site/install) di Termix per maggiori informazioni su come installare Termix su tutte le piattaforme. In alternativa, visualizza un file Docker Compose di esempio qui (puoi omettere guacd e la rete se non prevedi di utilizzare le funzioni di desktop remoto):
```yaml
services:
termix:
image: ghcr.io/lukegus/termix:latest
container_name: termix
restart: unless-stopped
ports:
- "8080:8080"
volumes:
- termix-data:/app/data
environment:
PORT: "8080"
depends_on:
- guacd
networks:
- termix-net
guacd:
image: guacamole/guacd:1.6.0
container_name: guacd
restart: unless-stopped
ports:
- "4822:4822"
networks:
- termix-net
volumes:
termix-data:
driver: local
networks:
termix-net:
driver: bridge
```
<br />
## Dona
Termix è gratuito e open source. Se lo trovi utile, considera di [donare](https://donate.termix.site/) per aiutare a coprire i costi del server e il tempo di sviluppo.
<a href="https://donate.termix.site/"><img src="../repo-images/donation-goal.svg" alt="Monthly donation goal" /></a>
<br />
## Screenshot
<div align="center">
<br />
[![YouTube](../repo-images/YouTube.png)](https://www.youtube.com/@TermixSSH/videos)
<sub>Guarda le panoramiche degli aggiornamenti su YouTube</sub>
<br />
<br />
<table>
<tr>
<td><img src="../repo-images/Image 1.png" alt="Termix Screenshot 1" width="400" /></td>
<td><img src="../repo-images/Image 2.png" alt="Termix Screenshot 2" width="400" /></td>
</tr>
<tr>
<td><img src="../repo-images/Image 3.png" alt="Termix Screenshot 3" width="400" /></td>
<td><img src="../repo-images/Image 4.png" alt="Termix Screenshot 4" width="400" /></td>
</tr>
<tr>
<td><img src="../repo-images/Image 5.png" alt="Termix Screenshot 5" width="400" /></td>
<td><img src="../repo-images/Image 6.png" alt="Termix Screenshot 6" width="400" /></td>
</tr>
<tr>
<td><img src="../repo-images/Image 7.png" alt="Termix Screenshot 7" width="400" /></td>
<td><img src="../repo-images/Image 8.png" alt="Termix Screenshot 8" width="400" /></td>
</tr>
<tr>
<td><img src="../repo-images/Image 9.png" alt="Termix Screenshot 9" width="400" /></td>
<td><img src="../repo-images/Image 10.png" alt="Termix Screenshot 10" width="400" /></td>
</tr>
<tr>
<td><img src="../repo-images/Image 11.png" alt="Termix Screenshot 11" width="400" /></td>
<td><img src="../repo-images/Image 12.png" alt="Termix Screenshot 12" width="400" /></td>
</tr>
<tr>
<td><img src="../repo-images/Image 13.png" alt="Termix Screenshot 13" width="400" /></td>
<td><img src="../repo-images/Image 14.png" alt="Termix Screenshot 14" width="400" /></td>
</tr>
<tr>
<td><img src="../repo-images/Image 15.png" alt="Termix Screenshot 15" width="400" /></td>
<td><img src="../repo-images/Image 16.png" alt="Termix Screenshot 16" width="400" /></td>
</tr>
</table>
<sub>Alcuni video e immagini potrebbero non essere aggiornati o potrebbero non mostrare perfettamente le funzionalita.</sub>
</div>
<br />
## Funzionalita Pianificate
Consulta [Progetti](https://github.com/orgs/Termix-SSH/projects/5) per tutte le funzionalita pianificate. Se desideri contribuire, consulta [Contribuire](https://github.com/Termix-SSH/Termix/blob/main/CONTRIBUTING.md).
<br />
## Sponsor
<div align="center">
<br />
<a href="https://www.digitalocean.com/">
<img src="https://opensource.nyc3.cdn.digitaloceanspaces.com/attribution/assets/SVG/DO_Logo_horizontal_blue.svg" height="40" alt="DigitalOcean" />
</a>
&nbsp;&nbsp;&nbsp;
<a href="https://crowdin.com/">
<img src="https://support.crowdin.com/assets/logos/core-logo/svg/crowdin-core-logo-cDark.svg" height="40" alt="Crowdin" />
</a>
&nbsp;&nbsp;&nbsp;
<a href="https://www.blacksmith.sh/">
<img src="https://cdn.prod.website-files.com/681bfb0c9a4601bc6e288ec4/683ca9e2c5186757092611b8_e8cb22127df4da0811c4120a523722d2_logo-backsmith-wordmark-light.svg" height="40" alt="Blacksmith" />
</a>
&nbsp;&nbsp;&nbsp;
<a href="https://www.cloudflare.com/">
<img src="https://sirv.sirv.com/website/screenshots/cloudflare/cloudflare-logo.png?w=300" height="40" alt="Cloudflare" />
</a>
&nbsp;&nbsp;&nbsp;
<a href="https://tailscale.com/">
<img src="https://drive.google.com/uc?export=view&id=1lIxkJuX6M23bW-2FElhT0rQieTrzaVSL" height="40" alt="Tailscale" />
</a>
&nbsp;&nbsp;&nbsp;
<a href="https://akamai.com/">
<img src="https://upload.wikimedia.org/wikipedia/commons/8/8b/Akamai_logo.svg" height="40" alt="Akamai" />
</a>
&nbsp;&nbsp;&nbsp;
<a href="https://aws.amazon.com/">
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/9/93/Amazon_Web_Services_Logo.svg/960px-Amazon_Web_Services_Logo.svg.png" height="40" alt="AWS" />
</a>
</div>
<br />
## Supporto
Se hai bisogno di aiuto o vuoi richiedere una funzionalita per Termix, visita la pagina [Segnalazioni](https://github.com/Termix-SSH/Support/issues), accedi e premi `New Issue`. Per favore, sii il piu dettagliato possibile nella tua segnalazione, preferibilmente scritta in inglese. Puoi anche unirti al server [Discord](https://discord.gg/jVQGdvHDrf) e visitare il canale di supporto, tuttavia i tempi di risposta potrebbero essere piu lunghi.
<br />
## Licenza
Distribuito sotto la Licenza Apache Versione 2.0. Consulta `LICENSE` per maggiori informazioni.
-405
View File
@@ -1,405 +0,0 @@
<div align="center">
<img src="../public/icon.svg" width="120" height="120" alt="Termix Logo" />
<h1>Termix</h1>
<p>セルフホスト型 SSH 管理とリモートデスクトップアクセス</p>
<p>
<a href="../README.md">English</a> ·
<a href="README-CN.md">中文</a> ·
日本語 ·
<a href="README-KO.md">한국어</a> ·
<a href="README-FR.md">Français</a> ·
<a href="README-DE.md">Deutsch</a> ·
<a href="README-ES.md">Español</a> ·
<a href="README-PT.md">Português</a> ·
<a href="README-RU.md">Русский</a> ·
<a href="README-AR.md">العربية</a> ·
<a href="README-HI.md">हिन्दी</a> ·
<a href="README-TR.md">Türkçe</a> ·
<a href="README-VI.md">Tiếng Việt</a> ·
<a href="README-IT.md">Italiano</a>
</p>
<p>
<img src="https://img.shields.io/github/stars/Termix-SSH/Termix?style=flat&label=Stars&color=F39044&labelColor=1a1a1a" />
<img src="https://img.shields.io/github/forks/Termix-SSH/Termix?style=flat&label=Forks&color=F39044&labelColor=1a1a1a" />
<img src="https://img.shields.io/github/v/release/Termix-SSH/Termix?style=flat&label=Release&color=F39044&labelColor=1a1a1a&v=1" />
<a href="https://discord.gg/jVQGdvHDrf"><img alt="Discord" src="https://img.shields.io/discord/1347374268253470720?color=F39044&labelColor=1a1a1a" /></a>
<a href="https://donate.termix.site/"><img alt="Donate" src="https://img.shields.io/badge/Donate-Support%20Termix-F39044?style=flat&labelColor=1a1a1a" /></a>
</p>
<br />
Termix は無料のオープンソースプロジェクトです。便利だと感じた場合は、サーバーコストと開発時間のために[寄付](https://donate.termix.site/)をご検討ください。
<a href="https://donate.termix.site/"><img src="../repo-images/donation-goal.svg" alt="Monthly donation goal" /></a>
<br />
<img src="../repo-images/Termix Header.png" alt="Termix Banner" width="900" />
<br />
<br />
<p>
<img src="../repo-images/Repo of the Day.png" alt="Repo of the Day Achievement" width="280" />
<br />
<sub>2025年9月1日に達成</sub>
</p>
</div>
<br />
## 概要
Termixは、オープンソースで永久無料のセルフホスト型オールインワンサーバー管理プラットフォームです。単一の直感的なインターフェースを通じて、サーバーとインフラストラクチャを管理するマルチプラットフォームソリューションを提供します。Termixは、SSHターミナルアクセス、リモートデスクトップ制御(RDP、VNC、Telnet)、SSHトンネリング機能、リモートSSHファイル管理、およびその他多くのツールを提供します。Termixは、すべてのプラットフォームで利用可能なTermiusの完全無料でセルフホスト可能な代替ソリューションです。
<br />
## 機能
<table>
<tr>
<td width="50%" valign="top">
**SSHターミナルアクセス:**
ブラウザ風タブシステムによる分割画面対応(最大4パネル)のフル機能ターミナル。一般的なターミナルテーマ、フォント、その他のコンポーネントを含むターミナルカスタマイズに対応しています。
</td>
<td width="50%" valign="top">
**リモートデスクトップアクセス:**
ブラウザ上でRDP、VNC、Telnetをサポート、完全なカスタマイズと分割画面に対応しています。
</td>
</tr>
<tr>
<td width="50%" valign="top">
**SSHトンネル管理:**
自動再接続とヘルスモニタリング、ローカル・リモート・ダイナミックSOCKSフォワーディングを備えたサーバー間SSHトンネルの作成・管理が可能です。デスクトップクライアント対サーバーのトンネル設定はデスクトップインストールごとにローカルに保存され、オプションのC2Sプリセットスナップショットをサーバーに保存・名前変更・読み込み・削除してクライアント間でローカルトンネル設定を移動できます。
</td>
<td width="50%" valign="top">
**リモートファイルマネージャー:**
コード、画像、音声、動画の表示・編集に対応し、リモートサーバー上のファイルを直接管理できます。sudo対応でファイルのアップロード、ダウンロード、名前変更、削除、移動をシームレスに実行できます。
</td>
</tr>
<tr>
<td width="50%" valign="top">
**DockerおよびPodman管理:**
コンテナの起動、停止、一時停止、削除。コンテナの統計情報を表示。docker execターミナルでコンテナを操作。DockerとPodmanの両方をコンテナランタイムとしてサポートしています。PortainerやDockgeの代替ではなく、コンテナの作成よりも簡易的な管理を目的としています。
</td>
<td width="50%" valign="top">
**SSHホストマネージャー:**
タグやフォルダ(フォルダのカスタマイズとネストフォルダ対応)でSSH接続を保存、整理、管理し、再利用可能なログイン情報を簡単に保存しながらSSHキーのデプロイを自動化できます。
</td>
</tr>
<tr>
<td width="50%" valign="top">
**ホストメトリクス:**
ほとんどのLinuxベースのサーバーで、CPU、メモリ、ディスク使用量、ネットワーク、アップタイム、システム情報、ファイアウォール、ポートモニター、ログビューア、ユーザー/権限、証明書など、さらに多くの情報を表示できます。
</td>
<td width="50%" valign="top">
**ユーザー認証:**
管理者コントロールとOIDC/LDAP/SSO(アクセス制御付き)および2FA(TOTP)対応による安全なユーザー管理。すべてのプラットフォームでアクティブなユーザーセッションを表示し、権限を取り消し可能。OIDC/ローカルアカウントの連携が可能です。すべてのユーザー操作の監査ログを表示できます。
</td>
</tr>
<tr>
<td width="50%" valign="top">
**Tailscaleインテグレーション:**
TailnetのデバイスをリストしてホストとしてすばやくH追加し、Tailscale SSHを認証方法として使用して接続します。これにより、TailnetのACLが認証情報を保存せずに認可を処理します。
</td>
<td width="50%" valign="top">
**RBAC:**
ロールを作成し、ユーザー/ロール間でホストを共有できます。
</td>
</tr>
<tr>
<td width="50%" valign="top">
**シリアル接続:**
ブラウザまたはデスクトップアプリからシリアルデバイス(ルーター、スイッチ、マイクロコントローラーなど)に直接接続できます。ボーレート、データビット、ストップビット、パリティを設定できます。対応ブラウザではWeb Serial APIを使用し、Electronアプリではネイティブバックエンドを使用します。
</td>
<td width="50%" valign="top">
**アラート:**
ホストメトリクス(CPU、メモリ、ディスクなど)に対してしきい値ベースのアラートルールを設定し、発動時にntfyまたはwebhookで通知を受け取れます。発動中および解決済みのアラートを履歴ログで確認できます。
</td>
</tr>
<tr>
<td width="50%" valign="top">
**ホームページ:**
ドラッグ&ドロップのウィジェットグリッドを備えた完全カスタマイズ可能なホームページ。ホストステータス、サービスリンク、時計、メモ、RSSフィード、天気、Dockerコンテナ、ホストメトリクスグラフ、埋め込みターミナル、iframeなどのウィジェットを追加できます。
</td>
<td width="50%" valign="top">
**データベース暗号化:**
バックエンドは暗号化されたSQLiteデータベースファイルとして保存されます。詳細は[ドキュメント](https://docs.termix.site/security)をご覧ください。
</td>
</tr>
<tr>
<td width="50%" valign="top">
**ネットワークグラフ:**
ダッシュボードをカスタマイズして、SSH接続に基づくホームラボのネットワークをステータス表示付きで可視化できます。
</td>
<td width="50%" valign="top">
**SSHツール:**
ワンクリックで実行できる再利用可能なコマンドスニペットの作成。複数の開いているターミナルに対して同時にコマンドを実行できます。
</td>
</tr>
<tr>
<td width="50%" valign="top">
**永続タブ:**
ユーザープロフィールで有効にすると、SSHセッションとタブがデバイス/更新をまたいで開いたまま保持されます。
</td>
<td width="50%" valign="top">
**多言語対応:**
約30言語の組み込みサポート([Crowdin](https://docs.termix.site/translations)で管理されています)。
</td>
</tr>
</table>
<br />
<details>
<summary><b>その他の機能</b></summary>
<br />
- **ダッシュボード** - ダッシュボードでサーバー情報を一目で確認できます
- **APIキー** - 自動化/CI用に有効期限付きのユーザースコープAPIキーを作成できます
- **データのエクスポート/インポート** - SSHホスト、認証情報、ファイルマネージャーデータのエクスポートとインポートが可能です
- **自動SSL設定** - HTTPSリダイレクト付きの組み込みSSL証明書生成・管理が可能です
- **モダンUI** - React、Tailwind CSS、Shadcnで構築された、デスクトップ/モバイル対応のクリーンなインターフェース。ライト、ダーク、Draculaなど、多くの異なるUIテーマから選択可能。URLルートで任意の接続をフルスクリーンで開くことができます。
- **コマンド履歴** - 過去に実行したSSHコマンドの自動補完と表示が可能です
- **クイック接続** - 接続データを保存せずにサーバーに接続できます
- **コマンドパレット** - 左Shiftキーを2回押すことで、キーボードからSSH接続に素早くアクセスできます
- **Proxmox統合** - Proxmoxインスタンスからホストを自動的にTermixに追加できます
- **SSH機能充実** - ジャンプホスト、Warpgate、TOTPベースの接続、SOCKS5、ホストキー検証、パスワード自動入力、[OPKSSH](https://github.com/openpubkey/opkssh)、tmux、ポート敲き(port knocking)、ターミナルログ記録などに対応しています
</details>
<br />
## プラットフォーム対応
<table align="center">
<tr>
<th align="center">プラットフォーム</th>
<th align="center">配布形式</th>
</tr>
<tr>
<td align="center"><b>Web</b></td>
<td>あらゆる最新ブラウザ(Chrome、Safari、Firefox)· PWA対応</td>
</tr>
<tr>
<td align="center"><b>Windows</b> <sub>x64/ia32</sub></td>
<td>ポータブル版 · MSIインストーラー · Chocolatey</td>
</tr>
<tr>
<td align="center"><b>Linux</b> <sub>x64/ia32</sub></td>
<td>ポータブル版 · AUR · AppImage · Deb · Flatpak</td>
</tr>
<tr>
<td align="center"><b>macOS</b> <sub>x64/ia32, v12.0+</sub></td>
<td>Apple App Store · DMG · Homebrew</td>
</tr>
<tr>
<td align="center"><b>iOS/iPadOS</b> <sub>v15.1+</sub></td>
<td>Apple App Store · IPA</td>
</tr>
<tr>
<td align="center"><b>Android</b> <sub>v7.0+</sub></td>
<td>Google Play Store · APK</td>
</tr>
</table>
<br />
## インストール
すべてのプラットフォームへのTermixのインストール方法については、Termixの[ドキュメント](https://docs.termix.site/install)をご覧ください。また、以下のサンプルDocker Composeファイルをご覧ください(リモートデスクトップ機能を使用する予定がない場合は、guacdとネットワークの設定を省略できます):
```yaml
services:
termix:
image: ghcr.io/lukegus/termix:latest
container_name: termix
restart: unless-stopped
ports:
- "8080:8080"
volumes:
- termix-data:/app/data
environment:
PORT: "8080"
depends_on:
- guacd
networks:
- termix-net
guacd:
image: guacamole/guacd:1.6.0
container_name: guacd
restart: unless-stopped
ports:
- "4822:4822"
networks:
- termix-net
volumes:
termix-data:
driver: local
networks:
termix-net:
driver: bridge
```
<br />
## 寄付
Termix は無料のオープンソースプロジェクトです。便利だと感じた場合は、サーバーコストと開発時間のために[寄付](https://donate.termix.site/)をご検討ください。
<a href="https://donate.termix.site/"><img src="../repo-images/donation-goal.svg" alt="Monthly donation goal" /></a>
<br />
## スクリーンショット
<div align="center">
<br />
[![YouTube](../repo-images/YouTube.png)](https://www.youtube.com/@TermixSSH/videos)
<sub>YouTubeでアップデートの概要を視聴する</sub>
<br />
<br />
<table>
<tr>
<td><img src="../repo-images/Image 1.png" alt="Termix Screenshot 1" width="400" /></td>
<td><img src="../repo-images/Image 2.png" alt="Termix Screenshot 2" width="400" /></td>
</tr>
<tr>
<td><img src="../repo-images/Image 3.png" alt="Termix Screenshot 3" width="400" /></td>
<td><img src="../repo-images/Image 4.png" alt="Termix Screenshot 4" width="400" /></td>
</tr>
<tr>
<td><img src="../repo-images/Image 5.png" alt="Termix Screenshot 5" width="400" /></td>
<td><img src="../repo-images/Image 6.png" alt="Termix Screenshot 6" width="400" /></td>
</tr>
<tr>
<td><img src="../repo-images/Image 7.png" alt="Termix Screenshot 7" width="400" /></td>
<td><img src="../repo-images/Image 8.png" alt="Termix Screenshot 8" width="400" /></td>
</tr>
<tr>
<td><img src="../repo-images/Image 9.png" alt="Termix Screenshot 9" width="400" /></td>
<td><img src="../repo-images/Image 10.png" alt="Termix Screenshot 10" width="400" /></td>
</tr>
<tr>
<td><img src="../repo-images/Image 11.png" alt="Termix Screenshot 11" width="400" /></td>
<td><img src="../repo-images/Image 12.png" alt="Termix Screenshot 12" width="400" /></td>
</tr>
<tr>
<td><img src="../repo-images/Image 13.png" alt="Termix Screenshot 13" width="400" /></td>
<td><img src="../repo-images/Image 14.png" alt="Termix Screenshot 14" width="400" /></td>
</tr>
<tr>
<td><img src="../repo-images/Image 15.png" alt="Termix Screenshot 15" width="400" /></td>
<td><img src="../repo-images/Image 16.png" alt="Termix Screenshot 16" width="400" /></td>
</tr>
</table>
<sub>動画や画像の一部は最新ではない場合や、機能を完全に紹介できていない場合があります。</sub>
</div>
<br />
## 予定されている機能
すべての予定機能については[Projects](https://github.com/orgs/Termix-SSH/projects/5)をご覧ください。コントリビュートをご希望の方は[Contributing](https://github.com/Termix-SSH/Termix/blob/main/CONTRIBUTING.md)をご覧ください。
<br />
## スポンサー
<div align="center">
<br />
<a href="https://www.digitalocean.com/">
<img src="https://opensource.nyc3.cdn.digitaloceanspaces.com/attribution/assets/SVG/DO_Logo_horizontal_blue.svg" height="40" alt="DigitalOcean" />
</a>
&nbsp;&nbsp;&nbsp;
<a href="https://crowdin.com/">
<img src="https://support.crowdin.com/assets/logos/core-logo/svg/crowdin-core-logo-cDark.svg" height="40" alt="Crowdin" />
</a>
&nbsp;&nbsp;&nbsp;
<a href="https://www.blacksmith.sh/">
<img src="https://cdn.prod.website-files.com/681bfb0c9a4601bc6e288ec4/683ca9e2c5186757092611b8_e8cb22127df4da0811c4120a523722d2_logo-backsmith-wordmark-light.svg" height="40" alt="Blacksmith" />
</a>
&nbsp;&nbsp;&nbsp;
<a href="https://www.cloudflare.com/">
<img src="https://sirv.sirv.com/website/screenshots/cloudflare/cloudflare-logo.png?w=300" height="40" alt="Cloudflare" />
</a>
&nbsp;&nbsp;&nbsp;
<a href="https://tailscale.com/">
<img src="https://drive.google.com/uc?export=view&id=1lIxkJuX6M23bW-2FElhT0rQieTrzaVSL" height="40" alt="Tailscale" />
</a>
&nbsp;&nbsp;&nbsp;
<a href="https://akamai.com/">
<img src="https://upload.wikimedia.org/wikipedia/commons/8/8b/Akamai_logo.svg" height="40" alt="Akamai" />
</a>
&nbsp;&nbsp;&nbsp;
<a href="https://aws.amazon.com/">
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/9/93/Amazon_Web_Services_Logo.svg/960px-Amazon_Web_Services_Logo.svg.png" height="40" alt="AWS" />
</a>
</div>
<br />
## サポート
Termixに関するヘルプや機能リクエストが必要な場合は、[Issues](https://github.com/Termix-SSH/Support/issues)ページにアクセスし、ログインして`New Issue`を押してください。Issueはできるだけ詳細に記述し、英語での記述が望ましいです。また、[Discord](https://discord.gg/jVQGdvHDrf)サーバーに参加してサポートチャンネルを利用することもできますが、応答時間が長くなる場合があります。
<br />
## ライセンス
Apache License Version 2.0のもとで配布されています。詳細は`LICENSE`をご覧ください。
-405
View File
@@ -1,405 +0,0 @@
<div align="center">
<img src="../public/icon.svg" width="120" height="120" alt="Termix Logo" />
<h1>Termix</h1>
<p>셀프 호스팅 SSH 관리 및 원격 데스크톱 액세스</p>
<p>
<a href="../README.md">English</a> ·
<a href="README-CN.md">中文</a> ·
<a href="README-JA.md">日本語</a> ·
한국어 ·
<a href="README-FR.md">Français</a> ·
<a href="README-DE.md">Deutsch</a> ·
<a href="README-ES.md">Español</a> ·
<a href="README-PT.md">Português</a> ·
<a href="README-RU.md">Русский</a> ·
<a href="README-AR.md">العربية</a> ·
<a href="README-HI.md">हिन्दी</a> ·
<a href="README-TR.md">Türkçe</a> ·
<a href="README-VI.md">Tiếng Việt</a> ·
<a href="README-IT.md">Italiano</a>
</p>
<p>
<img src="https://img.shields.io/github/stars/Termix-SSH/Termix?style=flat&label=Stars&color=F39044&labelColor=1a1a1a" />
<img src="https://img.shields.io/github/forks/Termix-SSH/Termix?style=flat&label=Forks&color=F39044&labelColor=1a1a1a" />
<img src="https://img.shields.io/github/v/release/Termix-SSH/Termix?style=flat&label=Release&color=F39044&labelColor=1a1a1a&v=1" />
<a href="https://discord.gg/jVQGdvHDrf"><img alt="Discord" src="https://img.shields.io/discord/1347374268253470720?color=F39044&labelColor=1a1a1a" /></a>
<a href="https://donate.termix.site/"><img alt="Donate" src="https://img.shields.io/badge/Donate-Support%20Termix-F39044?style=flat&labelColor=1a1a1a" /></a>
</p>
<br />
Termix는 무료 오픈소스 프로젝트입니다. 유용하게 사용하고 있다면 서버 비용과 개발 시간을 위해 [후원](https://donate.termix.site/)을 고려해 주세요.
<a href="https://donate.termix.site/"><img src="../repo-images/donation-goal.svg" alt="Monthly donation goal" /></a>
<br />
<img src="../repo-images/Termix Header.png" alt="Termix Banner" width="900" />
<br />
<br />
<p>
<img src="../repo-images/Repo of the Day.png" alt="Repo of the Day Achievement" width="280" />
<br />
<sub>2025년 9월 1일 달성</sub>
</p>
</div>
<br />
## 개요
Termix는 오픈 소스이며 영구 무료인 셀프 호스팅 올인원 서버 관리 플랫폼입니다. 단일 직관적인 인터페이스를 통해 서버와 인프라를 관리할 수 있는 멀티 플랫폼 솔루션을 제공합니다. Termix는 SSH 터미널 접속, 원격 데스크톱 제어(RDP, VNC, Telnet), SSH 터널링 기능, 원격 SSH 파일 관리 및 기타 다양한 도구를 제공합니다. Termix는 모든 플랫폼에서 사용 가능한 Termius의 완벽한 무료 셀프 호스팅 대안입니다.
<br />
## 기능
<table>
<tr>
<td width="50%" valign="top">
**SSH 터미널 접속:**
브라우저 스타일 탭 시스템과 분할 화면 지원(최대 4개 패널)을 갖춘 완전한 기능의 터미널. 일반 터미널 테마, 글꼴 및 기타 구성 요소를 포함한 터미널 사용자 정의 지원.
</td>
<td width="50%" valign="top">
**원격 데스크톱 접속:**
완전한 사용자 정의와 분할 화면을 지원하는 브라우저 기반 RDP, VNC, Telnet 지원.
</td>
</tr>
<tr>
<td width="50%" valign="top">
**SSH 터널 관리:**
자동 재연결, 상태 모니터링, 로컬·원격·동적 SOCKS 포워딩을 지원하는 서버 간 SSH 터널 생성 및 관리. 데스크톱 클라이언트-서버 터널 설정은 데스크톱 설치별로 로컬에 저장되며, 선택적 C2S 사전 설정 스냅샷을 서버에 저장·이름 변경·불러오기·삭제하여 클라이언트 간 로컬 터널 구성을 이동할 수 있습니다.
</td>
<td width="50%" valign="top">
**원격 파일 관리자:**
코드, 이미지, 오디오, 비디오의 보기 및 편집을 지원하여 원격 서버에서 파일을 직접 관리. sudo 지원으로 파일 업로드, 다운로드, 이름 변경, 삭제, 이동을 원활하게 수행.
</td>
</tr>
<tr>
<td width="50%" valign="top">
**Docker 및 Podman 관리:**
컨테이너 시작, 중지, 일시 정지, 제거. 컨테이너 통계 보기. docker exec 터미널로 컨테이너 제어. Docker와 Podman을 모두 컨테이너 런타임으로 지원. Portainer나 Dockge를 대체하기 위한 것이 아니라 컨테이너 생성보다는 간편한 관리를 목적으로 합니다.
</td>
<td width="50%" valign="top">
**SSH 호스트 관리자:**
태그와 폴더(폴더 사용자 지정 및 중첩 폴더 지원)로 SSH 연결을 저장, 정리, 관리하고, 재사용 가능한 로그인 정보를 쉽게 저장하면서 SSH 키 배포를 자동화.
</td>
</tr>
<tr>
<td width="50%" valign="top">
**호스트 메트릭:**
대부분의 Linux 기반 서버에서 CPU, 메모리, 디스크 사용량, 네트워크, 업타임, 시스템 정보, 방화벽, 포트 모니터, 로그 뷰어, 사용자/권한, 인증서 등 다양한 정보를 표시.
</td>
<td width="50%" valign="top">
**사용자 인증:**
관리자 제어와 OIDC/LDAP/SSO(액세스 제어 포함) 및 2FA(TOTP) 지원을 통한 안전한 사용자 관리. 모든 플랫폼에서 활성 사용자 세션을 보고 권한을 취소 가능. OIDC/로컬 계정 연동. 모든 사용자 작업의 감사 로그 조회.
</td>
</tr>
<tr>
<td width="50%" valign="top">
**Tailscale 통합:**
Tailscale 네트워크의 기기를 나열하여 호스트로 빠르게 추가하고, Tailscale SSH를 인증 방법으로 사용하여 연결함으로써 자격 증명을 저장하지 않고도 네트워크 ACL이 권한 부여를 처리하도록 합니다.
</td>
<td width="50%" valign="top">
**RBAC:**
역할을 생성하고 사용자/역할 간에 호스트 공유.
</td>
</tr>
<tr>
<td width="50%" valign="top">
**시리얼 연결:**
브라우저 또는 데스크톱 앱에서 직접 시리얼 장치(라우터, 스위치, 마이크로컨트롤러 등)에 연결. 보드레이트, 데이터 비트, 스톱 비트, 패리티 구성. 지원 브라우저에서는 Web Serial API를, Electron 앱에서는 네이티브 백엔드를 사용합니다.
</td>
<td width="50%" valign="top">
**알림:**
호스트 메트릭(CPU, 메모리, 디스크 등)에 대한 임계값 기반 알림 규칙을 설정하고 트리거될 때 ntfy 또는 웹훅을 통해 알림 수신. 기록 로그에서 발생 중인 알림과 해결된 알림 확인.
</td>
</tr>
<tr>
<td width="50%" valign="top">
**홈페이지:**
드래그 앤 드롭 위젯 그리드를 갖춘 완전 맞춤형 홈페이지. 호스트 상태, 서비스 링크, 시계, 메모, RSS 피드, 날씨, Docker 컨테이너, 호스트 메트릭 차트, 임베디드 터미널, iframe 등의 위젯 추가 가능.
</td>
<td width="50%" valign="top">
**데이터베이스 암호화:**
백엔드가 암호화된 SQLite 데이터베이스 파일로 저장됨. 자세한 내용은 [문서](https://docs.termix.site/security)를 참조하세요.
</td>
</tr>
<tr>
<td width="50%" valign="top">
**네트워크 그래프:**
대시보드를 사용자 정의하여 SSH 연결 기반의 홈랩 네트워크를 상태 표시와 함께 시각화.
</td>
<td width="50%" valign="top">
**SSH 도구:**
한 번의 클릭으로 실행 가능한 재사용 가능 명령어 스니펫 생성. 여러 열린 터미널에서 동시에 하나의 명령어 실행.
</td>
</tr>
<tr>
<td width="50%" valign="top">
**지속 탭:**
사용자 프로필에서 활성화된 경우 SSH 세션 및 탭이 기기/새로 고침 간에 열린 상태 유지.
</td>
<td width="50%" valign="top">
**다국어 지원:**
약 30개 언어 내장 지원([Crowdin](https://docs.termix.site/translations)으로 관리).
</td>
</tr>
</table>
<br />
<details>
<summary><b>더 많은 기능</b></summary>
<br />
- **대시보드** - 대시보드에서 서버 정보를 한눈에 확인
- **API 키** - 자동화/CI에 사용할 만료일이 있는 사용자 범위 API 키 생성
- **데이터 내보내기/가져오기** - SSH 호스트, 자격 증명, 파일 관리자 데이터의 내보내기 및 가져오기
- **자동 SSL 설정** - HTTPS 리디렉션을 포함한 내장 SSL 인증서 생성 및 관리
- **모던 UI** - React, Tailwind CSS, Shadcn으로 구축된 깔끔한 데스크톱/모바일 친화적 인터페이스. 라이트, 다크, 드라큘라 등 다양한 UI 테마 선택 가능. URL 라우트를 사용하여 모든 연결을 전체 화면으로 열기 가능.
- **명령어 기록** - 이전에 실행한 SSH 명령어의 자동 완성 및 조회
- **빠른 연결** - 연결 데이터를 저장하지 않고 서버에 접속
- **명령어 팔레트** - 왼쪽 Shift 키를 두 번 눌러 키보드로 SSH 연결에 빠르게 접근
- **Proxmox 통합** - Proxmox 인스턴스에서 Termix로 호스트를 자동 추가
- **풍부한 SSH 기능** - 점프 호스트, Warpgate, TOTP 기반 연결, SOCKS5, 호스트 키 검증, 비밀번호 자동 입력, [OPKSSH](https://github.com/openpubkey/opkssh), tmux, 포트 노킹, 터미널 로깅 등 지원
</details>
<br />
## 플랫폼 지원
<table align="center">
<tr>
<th align="center">플랫폼</th>
<th align="center">배포판</th>
</tr>
<tr>
<td align="center"><b>Web</b></td>
<td>모든 최신 브라우저(Chrome, Safari, Firefox) · PWA 지원</td>
</tr>
<tr>
<td align="center"><b>Windows</b> <sub>x64/ia32</sub></td>
<td>포터블 · MSI 설치 프로그램 · Chocolatey</td>
</tr>
<tr>
<td align="center"><b>Linux</b> <sub>x64/ia32</sub></td>
<td>포터블 · AUR · AppImage · Deb · Flatpak</td>
</tr>
<tr>
<td align="center"><b>macOS</b> <sub>x64/ia32, v12.0+</sub></td>
<td>Apple App Store · DMG · Homebrew</td>
</tr>
<tr>
<td align="center"><b>iOS/iPadOS</b> <sub>v15.1+</sub></td>
<td>Apple App Store · IPA</td>
</tr>
<tr>
<td align="center"><b>Android</b> <sub>v7.0+</sub></td>
<td>Google Play Store · APK</td>
</tr>
</table>
<br />
## 설치
모든 플랫폼에 Termix를 설치하는 방법에 대한 자세한 내용은 Termix [문서](https://docs.termix.site/install)를 방문하세요. 다음은 Docker Compose 파일 예시입니다(원격 데스크톱 기능을 사용할 계획이 없다면 guacd와 네트워크를 생략할 수 있습니다):
```yaml
services:
termix:
image: ghcr.io/lukegus/termix:latest
container_name: termix
restart: unless-stopped
ports:
- "8080:8080"
volumes:
- termix-data:/app/data
environment:
PORT: "8080"
depends_on:
- guacd
networks:
- termix-net
guacd:
image: guacamole/guacd:1.6.0
container_name: guacd
restart: unless-stopped
ports:
- "4822:4822"
networks:
- termix-net
volumes:
termix-data:
driver: local
networks:
termix-net:
driver: bridge
```
<br />
## 후원
Termix는 무료 오픈소스 프로젝트입니다. 유용하게 사용하고 있다면 서버 비용과 개발 시간을 위해 [후원](https://donate.termix.site/)을 고려해 주세요.
<a href="https://donate.termix.site/"><img src="../repo-images/donation-goal.svg" alt="Monthly donation goal" /></a>
<br />
## 스크린샷
<div align="center">
<br />
[![YouTube](../repo-images/YouTube.png)](https://www.youtube.com/@TermixSSH/videos)
<sub>YouTube에서 업데이트 개요 시청하기</sub>
<br />
<br />
<table>
<tr>
<td><img src="../repo-images/Image 1.png" alt="Termix Screenshot 1" width="400" /></td>
<td><img src="../repo-images/Image 2.png" alt="Termix Screenshot 2" width="400" /></td>
</tr>
<tr>
<td><img src="../repo-images/Image 3.png" alt="Termix Screenshot 3" width="400" /></td>
<td><img src="../repo-images/Image 4.png" alt="Termix Screenshot 4" width="400" /></td>
</tr>
<tr>
<td><img src="../repo-images/Image 5.png" alt="Termix Screenshot 5" width="400" /></td>
<td><img src="../repo-images/Image 6.png" alt="Termix Screenshot 6" width="400" /></td>
</tr>
<tr>
<td><img src="../repo-images/Image 7.png" alt="Termix Screenshot 7" width="400" /></td>
<td><img src="../repo-images/Image 8.png" alt="Termix Screenshot 8" width="400" /></td>
</tr>
<tr>
<td><img src="../repo-images/Image 9.png" alt="Termix Screenshot 9" width="400" /></td>
<td><img src="../repo-images/Image 10.png" alt="Termix Screenshot 10" width="400" /></td>
</tr>
<tr>
<td><img src="../repo-images/Image 11.png" alt="Termix Screenshot 11" width="400" /></td>
<td><img src="../repo-images/Image 12.png" alt="Termix Screenshot 12" width="400" /></td>
</tr>
<tr>
<td><img src="../repo-images/Image 13.png" alt="Termix Screenshot 13" width="400" /></td>
<td><img src="../repo-images/Image 14.png" alt="Termix Screenshot 14" width="400" /></td>
</tr>
<tr>
<td><img src="../repo-images/Image 15.png" alt="Termix Screenshot 15" width="400" /></td>
<td><img src="../repo-images/Image 16.png" alt="Termix Screenshot 16" width="400" /></td>
</tr>
</table>
<sub>일부 비디오 및 이미지는 최신이 아니거나 기능을 완벽하게 보여주지 않을 수 있습니다.</sub>
</div>
<br />
## 계획된 기능
모든 계획된 기능은 [Projects](https://github.com/orgs/Termix-SSH/projects/5)를 참조하세요. 기여를 원하시면 [Contributing](https://github.com/Termix-SSH/Termix/blob/main/CONTRIBUTING.md)을 참조하세요.
<br />
## 스폰서
<div align="center">
<br />
<a href="https://www.digitalocean.com/">
<img src="https://opensource.nyc3.cdn.digitaloceanspaces.com/attribution/assets/SVG/DO_Logo_horizontal_blue.svg" height="40" alt="DigitalOcean" />
</a>
&nbsp;&nbsp;&nbsp;
<a href="https://crowdin.com/">
<img src="https://support.crowdin.com/assets/logos/core-logo/svg/crowdin-core-logo-cDark.svg" height="40" alt="Crowdin" />
</a>
&nbsp;&nbsp;&nbsp;
<a href="https://www.blacksmith.sh/">
<img src="https://cdn.prod.website-files.com/681bfb0c9a4601bc6e288ec4/683ca9e2c5186757092611b8_e8cb22127df4da0811c4120a523722d2_logo-backsmith-wordmark-light.svg" height="40" alt="Blacksmith" />
</a>
&nbsp;&nbsp;&nbsp;
<a href="https://www.cloudflare.com/">
<img src="https://sirv.sirv.com/website/screenshots/cloudflare/cloudflare-logo.png?w=300" height="40" alt="Cloudflare" />
</a>
&nbsp;&nbsp;&nbsp;
<a href="https://tailscale.com/">
<img src="https://drive.google.com/uc?export=view&id=1lIxkJuX6M23bW-2FElhT0rQieTrzaVSL" height="40" alt="Tailscale" />
</a>
&nbsp;&nbsp;&nbsp;
<a href="https://akamai.com/">
<img src="https://upload.wikimedia.org/wikipedia/commons/8/8b/Akamai_logo.svg" height="40" alt="Akamai" />
</a>
&nbsp;&nbsp;&nbsp;
<a href="https://aws.amazon.com/">
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/9/93/Amazon_Web_Services_Logo.svg/960px-Amazon_Web_Services_Logo.svg.png" height="40" alt="AWS" />
</a>
</div>
<br />
## 지원
Termix에 대한 도움이 필요하거나 기능을 요청하려면 [Issues](https://github.com/Termix-SSH/Support/issues) 페이지를 방문하여 로그인하고 `New Issue`를 누르세요. 이슈는 가능한 한 상세하게 작성하고, 영어로 작성하는 것이 좋습니다. [Discord](https://discord.gg/jVQGdvHDrf) 서버에 참여하여 지원 채널을 이용할 수도 있지만, 응답 시간이 더 길 수 있습니다.
<br />
## 라이선스
Apache License Version 2.0에 따라 배포됩니다. 자세한 내용은 `LICENSE`를 참조하세요.
-405
View File
@@ -1,405 +0,0 @@
<div align="center">
<img src="../public/icon.svg" width="120" height="120" alt="Termix Logo" />
<h1>Termix</h1>
<p>Gerenciamento SSH auto-hospedado e acesso a area de trabalho remota</p>
<p>
<a href="../README.md">English</a> ·
<a href="README-CN.md">中文</a> ·
<a href="README-JA.md">日本語</a> ·
<a href="README-KO.md">한국어</a> ·
<a href="README-FR.md">Français</a> ·
<a href="README-DE.md">Deutsch</a> ·
<a href="README-ES.md">Español</a> ·
Português ·
<a href="README-RU.md">Русский</a> ·
<a href="README-AR.md">العربية</a> ·
<a href="README-HI.md">हिन्दी</a> ·
<a href="README-TR.md">Türkçe</a> ·
<a href="README-VI.md">Tiếng Việt</a> ·
<a href="README-IT.md">Italiano</a>
</p>
<p>
<img src="https://img.shields.io/github/stars/Termix-SSH/Termix?style=flat&label=Stars&color=F39044&labelColor=1a1a1a" />
<img src="https://img.shields.io/github/forks/Termix-SSH/Termix?style=flat&label=Forks&color=F39044&labelColor=1a1a1a" />
<img src="https://img.shields.io/github/v/release/Termix-SSH/Termix?style=flat&label=Release&color=F39044&labelColor=1a1a1a&v=1" />
<a href="https://discord.gg/jVQGdvHDrf"><img alt="Discord" src="https://img.shields.io/discord/1347374268253470720?color=F39044&labelColor=1a1a1a" /></a>
<a href="https://donate.termix.site/"><img alt="Donate" src="https://img.shields.io/badge/Donate-Support%20Termix-F39044?style=flat&labelColor=1a1a1a" /></a>
</p>
<br />
Termix é gratuito e de código aberto. Se o achar útil, considere [doar](https://donate.termix.site/) para ajudar a cobrir os custos de servidor e o tempo de desenvolvimento.
<a href="https://donate.termix.site/"><img src="../repo-images/donation-goal.svg" alt="Monthly donation goal" /></a>
<br />
<img src="../repo-images/Termix Header.png" alt="Termix Banner" width="900" />
<br />
<br />
<p>
<img src="../repo-images/Repo of the Day.png" alt="Repo of the Day Achievement" width="280" />
<br />
<sub>Conquistado em 1 de setembro de 2025</sub>
</p>
</div>
<br />
## Visao Geral
Termix e uma plataforma de gerenciamento de servidores tudo-em-um, de codigo aberto, sempre gratuita e auto-hospedada. Ela fornece uma solucao multiplataforma para gerenciar seus servidores e infraestrutura atraves de uma interface unica e intuitiva. Termix oferece acesso a terminal SSH, controle de desktop remoto (RDP, VNC, Telnet), capacidades de tunelamento SSH, gerenciamento remoto de arquivos SSH e muitas outras ferramentas. Termix e a alternativa perfeita, gratuita e auto-hospedada ao Termius, disponivel para todas as plataformas.
<br />
## Funcionalidades
<table>
<tr>
<td width="50%" valign="top">
**Acesso ao Terminal SSH:**
Terminal completo com suporte a tela dividida (ate 4 paineis) com um sistema de abas similar ao navegador. Inclui suporte para personalizacao do terminal incluindo temas comuns de terminal, fontes e outros componentes.
</td>
<td width="50%" valign="top">
**Acesso a Area de Trabalho Remota:**
Suporte a RDP, VNC e Telnet pelo navegador com personalizacao completa e tela dividida.
</td>
</tr>
<tr>
<td width="50%" valign="top">
**Gerenciamento de Tuneis SSH:**
Crie e gerencie tuneis SSH de servidor para servidor com reconexao automatica, monitoramento de saude e encaminhamento local, remoto ou SOCKS dinamico. As configuracoes de tunel de cliente desktop para servidor sao armazenadas localmente por instalacao de desktop; snapshots de predefinicoes C2S opcionais podem ser salvos no servidor, renomeados, carregados ou excluidos para mover uma configuracao de tunel local entre clientes.
</td>
<td width="50%" valign="top">
**Gerenciador Remoto de Arquivos:**
Gerencie arquivos diretamente em servidores remotos com suporte para visualizar e editar codigo, imagens, audio e video. Faca upload, download, renomeie, exclua e mova arquivos facilmente com suporte sudo.
</td>
</tr>
<tr>
<td width="50%" valign="top">
**Gerenciamento de Docker e Podman:**
Inicie, pare, pause, remova conteineres. Visualize estatisticas de conteineres. Controle conteineres usando o terminal Docker Exec. Suporta Docker e Podman como ambiente de execucao de conteineres. Nao foi feito para substituir Portainer ou Dockge, mas sim para simplesmente gerenciar seus conteineres em vez de cria-los.
</td>
<td width="50%" valign="top">
**Gerenciador de Hosts SSH:**
Salve, organize e gerencie suas conexoes SSH com tags e pastas (com personalizacao de pastas e suporte a pastas aninhadas), e salve facilmente informacoes de login reutilizaveis com a capacidade de automatizar a implantacao de chaves SSH.
</td>
</tr>
<tr>
<td width="50%" valign="top">
**Metricas do Host:**
Visualize o uso de CPU, memoria e disco, rede, tempo de atividade, informacoes do sistema, firewall, monitor de portas, visualizador de logs, usuarios/permissoes, certificados e muito mais na maioria dos servidores baseados em Linux.
</td>
<td width="50%" valign="top">
**Autenticacao de Usuarios:**
Gerenciamento seguro de usuarios com controles de administrador e suporte para OIDC/LDAP/SSO (com controle de acesso) e 2FA (TOTP). Visualize sessoes ativas de usuarios em todas as plataformas e revogue permissoes. Vincule suas contas OIDC/Locais entre si. Visualize o log de auditoria de todas as acoes dos usuarios.
</td>
</tr>
<tr>
<td width="50%" valign="top">
**Integracao com Tailscale:**
Liste dispositivos da sua rede Tailscale para adicioná-los rapidamente como hosts, e conecte-se usando Tailscale SSH como metodo de autenticacao, deixando as ACLs da sua rede gerenciar a autorizacao sem armazenar credenciais.
</td>
<td width="50%" valign="top">
**RBAC:**
Crie funcoes e compartilhe hosts entre usuarios/funcoes.
</td>
</tr>
<tr>
<td width="50%" valign="top">
**Conexoes Seriais:**
Conecte-se a dispositivos seriais (roteadores, switches, microcontroladores, etc.) diretamente do navegador ou do aplicativo desktop. Configure taxa de baud, bits de dados, bits de parada e paridade. Usa a Web Serial API em navegadores suportados ou um backend nativo no aplicativo Electron.
</td>
<td width="50%" valign="top">
**Alertas:**
Defina regras de alerta baseadas em limites para metricas do host (CPU, memoria, disco, etc.) e receba notificacoes via ntfy ou webhooks quando forem ativadas. Visualize alertas ativos e resolvidos em um historico de registros.
</td>
</tr>
<tr>
<td width="50%" valign="top">
**Pagina Inicial:**
Uma pagina inicial totalmente personalizavel com uma grade de widgets de arrastar e soltar. Adicione widgets para status do host, links de servicos, relogios, notas, feeds RSS, clima, conteineres Docker, graficos de metricas do host, terminais incorporados, iframes e mais.
</td>
<td width="50%" valign="top">
**Criptografia de Banco de Dados:**
Backend armazenado como arquivos de banco de dados SQLite criptografados. Consulte a [documentacao](https://docs.termix.site/security) para mais informacoes.
</td>
</tr>
<tr>
<td width="50%" valign="top">
**Grafico de Rede:**
Personalize seu Dashboard para visualizar seu homelab baseado nas suas conexoes SSH com suporte de status.
</td>
<td width="50%" valign="top">
**Ferramentas SSH:**
Crie trechos de comandos reutilizaveis que sao executados com um unico clique. Execute um comando simultaneamente em multiplos terminais abertos.
</td>
</tr>
<tr>
<td width="50%" valign="top">
**Abas Persistentes:**
Sessoes SSH e abas permanecem abertas entre dispositivos/atualizacoes se habilitado no perfil do usuario.
</td>
<td width="50%" valign="top">
**Idiomas:**
Suporte integrado para aproximadamente 30 idiomas (gerenciado pelo [Crowdin](https://docs.termix.site/translations)).
</td>
</tr>
</table>
<br />
<details>
<summary><b>Mais funcionalidades</b></summary>
<br />
- **Dashboard** - Visualize informacoes do servidor de relance no seu dashboard
- **Chaves de API** - Crie chaves de API com escopo de usuario e datas de expiracao para uso em automacao/CI
- **Exportacao/Importacao de Dados** - Exporte e importe hosts SSH, credenciais e dados do gerenciador de arquivos
- **Configuracao Automatica de SSL** - Geracao e gerenciamento integrado de certificados SSL com redirecionamentos HTTPS
- **Interface Moderna** - Interface limpa compativel com desktop/mobile construida com React, Tailwind CSS e Shadcn. Escolha entre muitos temas de interface diferentes, incluindo claro, escuro, Dracula, etc. Use rotas de URL para abrir qualquer conexao em tela cheia.
- **Historico de Comandos** - Autocompletar e visualizar comandos SSH executados anteriormente
- **Conexao Rapida** - Conecte-se a um servidor sem precisar salvar os dados de conexao
- **Paleta de Comandos** - Pressione duas vezes a tecla Shift esquerda para acessar rapidamente as conexoes SSH com seu teclado
- **Integracao com Proxmox** - Adicione automaticamente hosts ao Termix a partir da sua instancia Proxmox
- **SSH Rico em Funcionalidades** - Suporta jump hosts, Warpgate, conexoes baseadas em TOTP, SOCKS5, verificacao de chave do host, preenchimento automatico de senhas, [OPKSSH](https://github.com/openpubkey/opkssh), tmux, port knocking, registro de terminal, etc.
</details>
<br />
## Suporte a Plataformas
<table align="center">
<tr>
<th align="center">Plataforma</th>
<th align="center">Distribuicao</th>
</tr>
<tr>
<td align="center"><b>Web</b></td>
<td>Qualquer navegador moderno (Chrome, Safari, Firefox) · Suporte PWA</td>
</tr>
<tr>
<td align="center"><b>Windows</b> <sub>x64/ia32</sub></td>
<td>Portatil · Instalador MSI · Chocolatey</td>
</tr>
<tr>
<td align="center"><b>Linux</b> <sub>x64/ia32</sub></td>
<td>Portatil · AUR · AppImage · Deb · Flatpak</td>
</tr>
<tr>
<td align="center"><b>macOS</b> <sub>x64/ia32, v12.0+</sub></td>
<td>Apple App Store · DMG · Homebrew</td>
</tr>
<tr>
<td align="center"><b>iOS/iPadOS</b> <sub>v15.1+</sub></td>
<td>Apple App Store · IPA</td>
</tr>
<tr>
<td align="center"><b>Android</b> <sub>v7.0+</sub></td>
<td>Google Play Store · APK</td>
</tr>
</table>
<br />
## Instalacao
Visite a [documentacao](https://docs.termix.site/install) do Termix para mais informacoes sobre como instalar o Termix em todas as plataformas. Caso contrario, veja um arquivo Docker Compose de exemplo aqui (voce pode omitir o guacd e a rede se nao planeja usar recursos de area de trabalho remota):
```yaml
services:
termix:
image: ghcr.io/lukegus/termix:latest
container_name: termix
restart: unless-stopped
ports:
- "8080:8080"
volumes:
- termix-data:/app/data
environment:
PORT: "8080"
depends_on:
- guacd
networks:
- termix-net
guacd:
image: guacamole/guacd:1.6.0
container_name: guacd
restart: unless-stopped
ports:
- "4822:4822"
networks:
- termix-net
volumes:
termix-data:
driver: local
networks:
termix-net:
driver: bridge
```
<br />
## Doar
Termix é gratuito e de código aberto. Se o achar útil, considere [doar](https://donate.termix.site/) para ajudar a cobrir os custos de servidor e o tempo de desenvolvimento.
<a href="https://donate.termix.site/"><img src="../repo-images/donation-goal.svg" alt="Monthly donation goal" /></a>
<br />
## Capturas de Tela
<div align="center">
<br />
[![YouTube](../repo-images/YouTube.png)](https://www.youtube.com/@TermixSSH/videos)
<sub>Assista resumos de atualizacoes no YouTube</sub>
<br />
<br />
<table>
<tr>
<td><img src="../repo-images/Image 1.png" alt="Termix Screenshot 1" width="400" /></td>
<td><img src="../repo-images/Image 2.png" alt="Termix Screenshot 2" width="400" /></td>
</tr>
<tr>
<td><img src="../repo-images/Image 3.png" alt="Termix Screenshot 3" width="400" /></td>
<td><img src="../repo-images/Image 4.png" alt="Termix Screenshot 4" width="400" /></td>
</tr>
<tr>
<td><img src="../repo-images/Image 5.png" alt="Termix Screenshot 5" width="400" /></td>
<td><img src="../repo-images/Image 6.png" alt="Termix Screenshot 6" width="400" /></td>
</tr>
<tr>
<td><img src="../repo-images/Image 7.png" alt="Termix Screenshot 7" width="400" /></td>
<td><img src="../repo-images/Image 8.png" alt="Termix Screenshot 8" width="400" /></td>
</tr>
<tr>
<td><img src="../repo-images/Image 9.png" alt="Termix Screenshot 9" width="400" /></td>
<td><img src="../repo-images/Image 10.png" alt="Termix Screenshot 10" width="400" /></td>
</tr>
<tr>
<td><img src="../repo-images/Image 11.png" alt="Termix Screenshot 11" width="400" /></td>
<td><img src="../repo-images/Image 12.png" alt="Termix Screenshot 12" width="400" /></td>
</tr>
<tr>
<td><img src="../repo-images/Image 13.png" alt="Termix Screenshot 13" width="400" /></td>
<td><img src="../repo-images/Image 14.png" alt="Termix Screenshot 14" width="400" /></td>
</tr>
<tr>
<td><img src="../repo-images/Image 15.png" alt="Termix Screenshot 15" width="400" /></td>
<td><img src="../repo-images/Image 16.png" alt="Termix Screenshot 16" width="400" /></td>
</tr>
</table>
<sub>Alguns videos e imagens podem estar desatualizados ou podem nao mostrar perfeitamente as funcionalidades.</sub>
</div>
<br />
## Funcionalidades Planejadas
Consulte [Projetos](https://github.com/orgs/Termix-SSH/projects/5) para todas as funcionalidades planejadas. Se voce deseja contribuir, consulte [Contribuir](https://github.com/Termix-SSH/Termix/blob/main/CONTRIBUTING.md).
<br />
## Patrocinadores
<div align="center">
<br />
<a href="https://www.digitalocean.com/">
<img src="https://opensource.nyc3.cdn.digitaloceanspaces.com/attribution/assets/SVG/DO_Logo_horizontal_blue.svg" height="40" alt="DigitalOcean" />
</a>
&nbsp;&nbsp;&nbsp;
<a href="https://crowdin.com/">
<img src="https://support.crowdin.com/assets/logos/core-logo/svg/crowdin-core-logo-cDark.svg" height="40" alt="Crowdin" />
</a>
&nbsp;&nbsp;&nbsp;
<a href="https://www.blacksmith.sh/">
<img src="https://cdn.prod.website-files.com/681bfb0c9a4601bc6e288ec4/683ca9e2c5186757092611b8_e8cb22127df4da0811c4120a523722d2_logo-backsmith-wordmark-light.svg" height="40" alt="Blacksmith" />
</a>
&nbsp;&nbsp;&nbsp;
<a href="https://www.cloudflare.com/">
<img src="https://sirv.sirv.com/website/screenshots/cloudflare/cloudflare-logo.png?w=300" height="40" alt="Cloudflare" />
</a>
&nbsp;&nbsp;&nbsp;
<a href="https://tailscale.com/">
<img src="https://drive.google.com/uc?export=view&id=1lIxkJuX6M23bW-2FElhT0rQieTrzaVSL" height="40" alt="Tailscale" />
</a>
&nbsp;&nbsp;&nbsp;
<a href="https://akamai.com/">
<img src="https://upload.wikimedia.org/wikipedia/commons/8/8b/Akamai_logo.svg" height="40" alt="Akamai" />
</a>
&nbsp;&nbsp;&nbsp;
<a href="https://aws.amazon.com/">
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/9/93/Amazon_Web_Services_Logo.svg/960px-Amazon_Web_Services_Logo.svg.png" height="40" alt="AWS" />
</a>
</div>
<br />
## Suporte
Se voce precisa de ajuda ou deseja solicitar uma funcionalidade para o Termix, visite a pagina de [Issues](https://github.com/Termix-SSH/Support/issues), faca login e clique em `New Issue`. Por favor, seja o mais detalhado possivel no seu relato, preferencialmente escrito em ingles. Voce tambem pode entrar no servidor do [Discord](https://discord.gg/jVQGdvHDrf) e visitar o canal de suporte, porem, os tempos de resposta podem ser mais longos.
<br />
## Licenca
Distribuido sob a Licenca Apache Versao 2.0. Consulte `LICENSE` para mais informacoes.

Some files were not shown because too many files have changed in this diff Show More