mirror of
https://github.com/Termix-SSH/Termix.git
synced 2026-10-28 06:05:24 +00:00
Compare commits
115
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6940f4e9bb | ||
|
|
10bc491a9f | ||
|
|
9aa83c24ed | ||
|
|
54f03d73ce | ||
|
|
b0062343c7 | ||
|
|
09677caa26 | ||
|
|
7dc1bce272 | ||
|
|
58ba96654a | ||
|
|
0b00c26f8a | ||
|
|
9ff199ea96 | ||
|
|
0d464cdf56 | ||
|
|
963e54bf15 | ||
|
|
62262e5bf3 | ||
|
|
e800064f05 | ||
|
|
713d43fc52 | ||
|
|
a6295e5e7e | ||
|
|
2038a84c15 | ||
|
|
cf8fff572a | ||
|
|
cf5f0c41eb | ||
|
|
b43ca54fa0 | ||
|
|
08dbfdaf8f | ||
|
|
ba502de450 | ||
|
|
226cdcb7a0 | ||
|
|
a9d510aba4 | ||
|
|
5c5fe57dad | ||
|
|
1addd43039 | ||
|
|
946f5daaa9 | ||
|
|
e42c8c9788 | ||
|
|
a6b03aa792 | ||
|
|
175225dcd7 | ||
|
|
f2918e02f6 | ||
|
|
cb18a0cd87 | ||
|
|
98a45e9161 | ||
|
|
95c2994b3c | ||
|
|
0b302fc860 | ||
|
|
c5429ff2e8 | ||
|
|
9ab46cddd4 | ||
|
|
128ecbea04 | ||
|
|
9f7331d72a | ||
|
|
968e0cfeea | ||
|
|
c7e06f422d | ||
|
|
d799b8fe42 | ||
|
|
e058892118 | ||
|
|
33060eb1e4 | ||
|
|
3b0eddca27 | ||
|
|
8afadf6176 | ||
|
|
002683a2f0 | ||
|
|
24dcdc6751 | ||
|
|
bbaa9bf226 | ||
|
|
37e314edff | ||
|
|
b2f5459817 | ||
|
|
cd53d15a04 | ||
|
|
a17e72eec8 | ||
|
|
82b57a6af5 | ||
|
|
3c474d3b52 | ||
|
|
15e1fd215e | ||
|
|
4d8263a788 | ||
|
|
2061ac5e3b | ||
|
|
e1f9251186 | ||
|
|
b60924b9c7 | ||
|
|
bd844c7f11 | ||
|
|
ec64bb401b | ||
|
|
963ac01671 | ||
|
|
50c07c2f3a | ||
|
|
202de2123b | ||
|
|
f677a54551 | ||
|
|
0554f9c0fc | ||
|
|
1901c09a70 | ||
|
|
8229048e4c | ||
|
|
d7ca5eccf3 | ||
|
|
1adb64524c | ||
|
|
56ed93bb88 | ||
|
|
861194d8d1 | ||
|
|
74ce228fe1 | ||
|
|
17d2e65187 | ||
|
|
376fbb1b66 | ||
|
|
e68a508dec | ||
|
|
ad7532e88d | ||
|
|
c2405b0df2 | ||
|
|
d422a9ad25 | ||
|
|
ebf00630fd | ||
|
|
0bb4f2fb0b | ||
|
|
bc49d646b3 | ||
|
|
0f764dfb98 | ||
|
|
2fa968662e | ||
|
|
b5da3994b0 | ||
|
|
1820f36155 | ||
|
|
87107b8cc2 | ||
|
|
0cfde2410e | ||
|
|
25f8ce74ea | ||
|
|
02acc72bf6 | ||
|
|
a81b4834ce | ||
|
|
a2a441cdca | ||
|
|
4b927decce | ||
|
|
bda3fe9b31 | ||
|
|
fe09966196 | ||
|
|
bc14f803a2 | ||
|
|
b3e43a45af | ||
|
|
95573f7e37 | ||
|
|
0ed7d7a083 | ||
|
|
474965835f | ||
|
|
1f75dc0bd2 | ||
|
|
7b545367dc | ||
|
|
1a0d224ae0 | ||
|
|
848b388734 | ||
|
|
ea2343551d | ||
|
|
d46ddfe6ee | ||
|
|
a407bf15f7 | ||
|
|
3721edc128 | ||
|
|
0900017218 | ||
|
|
f14db79784 | ||
|
|
870cd9245e | ||
|
|
246bb8fb26 | ||
|
|
1139160e48 | ||
|
|
b6a3f881a8 |
No files matched your search
@@ -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]
|
||||
}
|
||||
}
|
||||
@@ -1,91 +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
|
||||
|
||||
|
||||
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
|
||||
@@ -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
|
||||
@@ -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,75 +0,0 @@
|
||||
name: Beta feedback
|
||||
description: A bug, rough edge or idea from a Termix beta
|
||||
labels: [beta]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for testing a beta. Short reports are fine. If you opened this from Termix, the version and setup are already filled in.
|
||||
- type: input
|
||||
id: termix-version
|
||||
attributes:
|
||||
label: Beta version
|
||||
description: Shown in Settings under Updates, or your image tag.
|
||||
placeholder: "e.g. 26.11.0-beta.2"
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: what-happened
|
||||
attributes:
|
||||
label: What happened?
|
||||
description: The bug, what felt off, or your idea. Screenshots help a lot.
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: regression
|
||||
attributes:
|
||||
label: Does this happen on the latest stable release?
|
||||
options:
|
||||
- "Not tested on stable"
|
||||
- "Yes, it happens on stable too"
|
||||
- "No, only on this beta"
|
||||
- "Not a bug, just feedback"
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
id: steps
|
||||
attributes:
|
||||
label: Steps to reproduce
|
||||
description: As few steps as you can.
|
||||
placeholder: |
|
||||
1.
|
||||
2.
|
||||
3.
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
id: beta-plugins
|
||||
attributes:
|
||||
label: Plugins on a beta
|
||||
description: Filled in by Termix. One plugin and version per line.
|
||||
render: text
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
id: environment
|
||||
attributes:
|
||||
label: Environment
|
||||
description: Browser or desktop app, OS, and how the server is installed.
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
id: logs
|
||||
attributes:
|
||||
label: Logs
|
||||
description: Errors from the browser console, `docker logs termix`, or the error Termix shows. This is shown as code, so no backticks needed.
|
||||
render: text
|
||||
validations:
|
||||
required: false
|
||||
- type: checkboxes
|
||||
id: checks
|
||||
attributes:
|
||||
label: Before you submit
|
||||
options:
|
||||
- label: I searched open issues and this is not a duplicate
|
||||
required: true
|
||||
@@ -1,107 +0,0 @@
|
||||
name: Bug report
|
||||
description: Something in Termix itself is broken
|
||||
labels: [bug]
|
||||
type: Bug
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for the report. A maintainer reads every issue, even when there is no reply right away. We usually reply once there is a fix or a workaround.
|
||||
|
||||
If you came from **Report an issue** in Termix, your versions and environment are already filled in below.
|
||||
|
||||
Is it about a plugin (terminal, file manager, Docker, remote desktop and so on)? Report it on that plugin's repo instead. **Report an issue** on the plugin's page in Termix takes you there with your versions filled in.
|
||||
- type: textarea
|
||||
id: what-happened
|
||||
attributes:
|
||||
label: What happened?
|
||||
description: Describe the bug. Screenshots help a lot.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: steps
|
||||
attributes:
|
||||
label: Steps to reproduce
|
||||
description: As few steps as you can.
|
||||
placeholder: |
|
||||
1.
|
||||
2.
|
||||
3.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: expected
|
||||
attributes:
|
||||
label: What did you expect?
|
||||
description: What should have happened instead?
|
||||
validations:
|
||||
required: false
|
||||
- type: input
|
||||
id: termix-version
|
||||
attributes:
|
||||
label: Termix version
|
||||
description: Shown in Settings under About, or in your User Profile.
|
||||
placeholder: "e.g. 26.10.0"
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: platform
|
||||
attributes:
|
||||
label: Platform
|
||||
description: Where do you see the problem?
|
||||
options:
|
||||
- "Web browser"
|
||||
- "Desktop app (Windows)"
|
||||
- "Desktop app (macOS)"
|
||||
- "Desktop app (Linux)"
|
||||
- "Mobile app (iOS)"
|
||||
- "Mobile app (Android)"
|
||||
- "Other"
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: install-method
|
||||
attributes:
|
||||
label: Server install
|
||||
description: How is the Termix server installed?
|
||||
options:
|
||||
- "Docker"
|
||||
- "Manual build"
|
||||
- "Proxmox community script"
|
||||
- "Desktop app (built-in server)"
|
||||
- "Not sure"
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: environment
|
||||
attributes:
|
||||
label: Environment
|
||||
description: Browser and OS, plus anything special about your setup (reverse proxy, database, SSO).
|
||||
placeholder: |
|
||||
Web, Chrome on Windows. Behind nginx, Postgres.
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
id: logs
|
||||
attributes:
|
||||
label: Logs
|
||||
description: Errors from the browser console, `docker logs termix`, or the error Termix shows. This is shown as code, so no backticks needed.
|
||||
render: text
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
id: context
|
||||
attributes:
|
||||
label: Anything else?
|
||||
description: Links, config, or anything that might help.
|
||||
validations:
|
||||
required: false
|
||||
- type: checkboxes
|
||||
id: checks
|
||||
attributes:
|
||||
label: Before you submit
|
||||
options:
|
||||
- label: I searched open and closed issues and this is not a duplicate
|
||||
required: true
|
||||
- label: I am on the latest version, or I said which version I am on
|
||||
required: true
|
||||
@@ -1,11 +0,0 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: Problem with a plugin?
|
||||
url: https://github.com/Termix-SSH/Termix#plugins
|
||||
about: Each plugin has its own repo. Find it in this list, or use Report an issue on the plugin's page in Termix.
|
||||
- name: Questions and chat
|
||||
url: https://discord.gg/jVQGdvHDrf
|
||||
about: Ask the community on Discord. Bugs and ideas belong in issues.
|
||||
- name: Business or priority support
|
||||
url: https://termix.site/contact
|
||||
about: For teams that need a faster response. Contact us to discuss terms.
|
||||
@@ -1,41 +0,0 @@
|
||||
name: Feature request
|
||||
description: Suggest an idea for Termix itself
|
||||
labels: [feature]
|
||||
type: Feature
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Is it about a plugin (terminal, file manager, Docker, remote desktop and so on)? Report it on that plugin's repo instead. **Report an issue** on the plugin's page in Termix takes you there with your versions filled in.
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for the idea. Explain the problem first, then how you would solve it.
|
||||
- type: textarea
|
||||
id: problem
|
||||
attributes:
|
||||
label: What problem would this solve?
|
||||
description: What are you trying to do, and what gets in the way today?
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: solution
|
||||
attributes:
|
||||
label: What would you like?
|
||||
description: Describe how it should work.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: alternatives
|
||||
attributes:
|
||||
label: Alternatives
|
||||
description: Anything you tried or considered instead.
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
id: context
|
||||
attributes:
|
||||
label: Anything else?
|
||||
description: Screenshots, mockups or links.
|
||||
validations:
|
||||
required: false
|
||||
@@ -1 +0,0 @@
|
||||
custom: https://donate.termix.site/
|
||||
@@ -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)
|
||||
@@ -0,0 +1,117 @@
|
||||
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: ubuntu-latest
|
||||
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.sha }}
|
||||
restore-keys: |
|
||||
${{ 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.ref_name }}-development-latest"
|
||||
else
|
||||
IMAGE_TAG="${{ github.event.inputs.tag_name }}"
|
||||
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: Notify via ntfy
|
||||
if: success()
|
||||
run: |
|
||||
curl -d "Docker image build and push completed successfully for tag: ${{ env.IMAGE_TAG }}" \
|
||||
https://ntfy.karmaa.site/termix-build
|
||||
|
||||
- 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
|
||||
@@ -1,150 +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
|
||||
- Beta
|
||||
- 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
|
||||
timeout-minutes: 20
|
||||
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@v2
|
||||
with:
|
||||
cache-key: termix-ssh/termix
|
||||
|
||||
- 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")
|
||||
elif [ "$BUILD_TYPE" = "Beta" ]; then
|
||||
TAGS+=("beta" "$VERSION")
|
||||
else
|
||||
TAGS+=("dev-$VERSION")
|
||||
fi
|
||||
|
||||
for tag in "${TAGS[@]}"; do
|
||||
ALL_TAGS+=("ghcr.io/lukegus/termix:$tag")
|
||||
ALL_TAGS+=("ghcr.io/termix-ssh/termix:$tag")
|
||||
if [ "$BUILD_TYPE" != "Development" ]; then
|
||||
ALL_TAGS+=("docker.io/bugattiguy527/termix:$tag")
|
||||
fi
|
||||
done
|
||||
|
||||
echo "ALL_TAGS=$(IFS=,; echo "${ALL_TAGS[*]}")" >> $GITHUB_ENV
|
||||
echo "TAGS=${TAGS[*]}" >> $GITHUB_ENV
|
||||
|
||||
- name: Login to GHCR
|
||||
if: ${{ !inputs.dry_run }}
|
||||
uses: docker/login-action@v4
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: lukegus
|
||||
password: ${{ secrets.TERMIX_PAT }}
|
||||
|
||||
- name: Login to Docker Hub (prod and beta only)
|
||||
if: ${{ (inputs.build_type == 'Production' || inputs.build_type == 'Beta') && !inputs.dry_run }}
|
||||
uses: docker/login-action@v4
|
||||
with:
|
||||
username: bugattiguy527
|
||||
password: ${{ secrets.DOCKERHUB_BUGATTIGUY527_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 }}
|
||||
outputs: ${{ inputs.dry_run && 'type=cacheonly' || 'type=registry,compression=zstd' }}
|
||||
|
||||
- name: Login to Docker Hub as termixssh
|
||||
id: termix_hub
|
||||
if: ${{ (inputs.build_type == 'Production' || inputs.build_type == 'Beta') && !inputs.dry_run }}
|
||||
env:
|
||||
TOKEN: ${{ secrets.DOCKERHUB_TERMIXSSH_TOKEN }}
|
||||
run: |
|
||||
if [ -z "$TOKEN" ]; then
|
||||
echo "DOCKERHUB_TERMIXSSH_TOKEN is not set, skipping docker.io/termixssh"
|
||||
exit 0
|
||||
fi
|
||||
echo "$TOKEN" | docker login docker.io --username termixssh --password-stdin
|
||||
echo "ready=true" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Copy image to docker.io/termixssh
|
||||
if: ${{ steps.termix_hub.outputs.ready == 'true' }}
|
||||
run: |
|
||||
for tag in $TAGS; do
|
||||
docker buildx imagetools create --tag "docker.io/termixssh/termix:$tag" "ghcr.io/termix-ssh/termix:$tag"
|
||||
done
|
||||
|
||||
- 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
@@ -1,111 +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@v7
|
||||
with:
|
||||
node-version-file: ".nvmrc"
|
||||
cache: "npm"
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Build plugin SDK
|
||||
run: npm run build:sdk
|
||||
|
||||
- name: Lint
|
||||
run: npm run lint
|
||||
|
||||
- name: Run Prettier check
|
||||
run: npx prettier --check .
|
||||
|
||||
- name: Type check
|
||||
run: npm run type-check
|
||||
|
||||
- name: Build
|
||||
run: npm run build
|
||||
|
||||
- name: Run unit tests
|
||||
run: npm run test
|
||||
|
||||
database-dialects:
|
||||
name: Postgres and MySQL
|
||||
runs-on: blacksmith-2vcpu-ubuntu-2404
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:16
|
||||
env:
|
||||
POSTGRES_USER: termix
|
||||
POSTGRES_PASSWORD: termix
|
||||
POSTGRES_DB: termix_test
|
||||
ports:
|
||||
- 5432:5432
|
||||
options: >-
|
||||
--health-cmd pg_isready
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries 5
|
||||
|
||||
mysql:
|
||||
image: mysql:8
|
||||
env:
|
||||
MYSQL_ROOT_PASSWORD: termix
|
||||
MYSQL_DATABASE: termix_test
|
||||
MYSQL_USER: termix
|
||||
MYSQL_PASSWORD: termix
|
||||
ports:
|
||||
- 3306:3306
|
||||
options: >-
|
||||
--health-cmd "mysqladmin ping -h 127.0.0.1 -ptermix"
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries 10
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v7
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v7
|
||||
with:
|
||||
node-version-file: ".nvmrc"
|
||||
cache: "npm"
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Build plugin SDK
|
||||
run: npm run build:sdk
|
||||
|
||||
- name: Verify Postgres
|
||||
run: npm run verify:dialect -- postgres://termix:termix@127.0.0.1:5432/termix_test
|
||||
|
||||
- name: Verify MySQL
|
||||
run: npm run verify:dialect -- mysql://termix:termix@127.0.0.1:3306/termix_test
|
||||
|
||||
- name: Repository tests on Postgres
|
||||
env:
|
||||
TEST_DIALECT: postgres
|
||||
TEST_DATABASE_URL: postgres://termix:termix@127.0.0.1:5432/termix_test
|
||||
run: npx vitest run src/backend/tests/database/repositories --no-file-parallelism
|
||||
|
||||
- name: Repository tests on MySQL
|
||||
env:
|
||||
TEST_DIALECT: mysql
|
||||
TEST_DATABASE_URL: mysql://termix:termix@127.0.0.1:3306/termix_test
|
||||
run: npx vitest run src/backend/tests/database/repositories --no-file-parallelism
|
||||
@@ -1,84 +0,0 @@
|
||||
name: Publish SDK
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
mode:
|
||||
description: "Publish mode"
|
||||
required: true
|
||||
default: Publish
|
||||
type: choice
|
||||
options:
|
||||
- Publish
|
||||
- Dry run
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
id-token: write
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
name: Publish @termix-ssh/plugin-sdk
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
env:
|
||||
NODE_OPTIONS: "--max-old-space-size=4096"
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
|
||||
- uses: actions/setup-node@v7
|
||||
with:
|
||||
node-version-file: ".nvmrc"
|
||||
cache: npm
|
||||
registry-url: https://registry.npmjs.org
|
||||
|
||||
- name: Update npm
|
||||
run: npm install -g npm@^11.19.0
|
||||
|
||||
- run: npm ci
|
||||
|
||||
- name: Check the version is new
|
||||
run: |
|
||||
VERSION=$(node -p "require('./packages/plugin-sdk/package.json').version")
|
||||
if npm view "@termix-ssh/plugin-sdk@$VERSION" version >/dev/null 2>&1; then
|
||||
echo "@termix-ssh/plugin-sdk@$VERSION is already on npm. Bump packages/plugin-sdk/package.json first."
|
||||
if [ "${{ inputs.mode }}" = "Publish" ]; then
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
echo "Publishing @termix-ssh/plugin-sdk@$VERSION"
|
||||
|
||||
- run: npm run build:sdk
|
||||
|
||||
- run: npm run lint
|
||||
|
||||
- run: npm run type-check
|
||||
|
||||
- run: npm run test
|
||||
|
||||
- name: Publish
|
||||
run: |
|
||||
if [ "${{ inputs.mode }}" = "Dry run" ]; then
|
||||
npm publish --workspace @termix-ssh/plugin-sdk --provenance --access public --dry-run
|
||||
else
|
||||
npm publish --workspace @termix-ssh/plugin-sdk --provenance --access public
|
||||
fi
|
||||
|
||||
- name: Tag and release
|
||||
if: ${{ inputs.mode == 'Publish' }}
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
VERSION=$(node -p "require('./packages/plugin-sdk/package.json').version")
|
||||
node -e "
|
||||
const fs = require('fs');
|
||||
const { changelogSection } = require('./packages/plugin-sdk/dist/changelog.js');
|
||||
const notes = changelogSection(fs.readFileSync('packages/plugin-sdk/CHANGELOG.md', 'utf8'), process.argv[1]);
|
||||
fs.writeFileSync('sdk-notes.md', notes);
|
||||
" "$VERSION"
|
||||
gh release create "sdk-v$VERSION" \
|
||||
--target "${{ github.sha }}" \
|
||||
--title "Plugin SDK $VERSION" \
|
||||
--notes-file sdk-notes.md \
|
||||
--latest=false
|
||||
@@ -1,610 +0,0 @@
|
||||
name: Release
|
||||
|
||||
# Stable: run by hand from a dev-X.Y.Z branch. Beta: run by hand from a dev
|
||||
# branch, or let the Tuesday and Friday schedule snapshot the newest dev
|
||||
# branch when it moved since the last beta.
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 15 * * 2,5"
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
channel:
|
||||
description: "Stable release or beta"
|
||||
required: true
|
||||
default: Stable
|
||||
type: choice
|
||||
options:
|
||||
- Stable
|
||||
- Beta
|
||||
mode:
|
||||
description: "Release mode (Overwrite release is stable only)"
|
||||
required: true
|
||||
default: Everything
|
||||
type: choice
|
||||
options:
|
||||
- Everything
|
||||
- Overwrite release
|
||||
- Dry run
|
||||
- Skip submit
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
concurrency:
|
||||
group: release
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
prep:
|
||||
runs-on: blacksmith-2vcpu-ubuntu-2404
|
||||
outputs:
|
||||
channel: ${{ steps.mode.outputs.channel }}
|
||||
mode: ${{ steps.mode.outputs.mode }}
|
||||
skip: ${{ steps.beta.outputs.skip || 'false' }}
|
||||
version: ${{ steps.info.outputs.version || steps.beta.outputs.version }}
|
||||
release_tag: ${{ steps.info.outputs.release_tag || steps.beta.outputs.release_tag }}
|
||||
mobile_version: ${{ steps.info.outputs.mobile_version }}
|
||||
mobile_tag: ${{ steps.info.outputs.mobile_tag }}
|
||||
dev_branch: ${{ steps.info.outputs.dev_branch || steps.beta.outputs.dev_branch }}
|
||||
sha: ${{ steps.beta.outputs.sha }}
|
||||
prev_ref: ${{ steps.beta.outputs.prev_ref }}
|
||||
steps:
|
||||
- name: Resolve channel and mode
|
||||
id: mode
|
||||
run: |
|
||||
CHANNEL="${{ inputs.channel || 'Beta' }}"
|
||||
MODE="${{ inputs.mode || 'Everything' }}"
|
||||
echo "channel=$CHANNEL" >> "$GITHUB_OUTPUT"
|
||||
echo "mode=$MODE" >> "$GITHUB_OUTPUT"
|
||||
if [ "$CHANNEL" = "Beta" ] && [ "$MODE" = "Overwrite release" ]; then
|
||||
echo "Overwrite release is for stable releases only."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Guard branch (release modes)
|
||||
if: ${{ github.event_name == 'workflow_dispatch' && steps.mode.outputs.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: ${{ steps.mode.outputs.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@v7
|
||||
with:
|
||||
node-version-file: ".nvmrc"
|
||||
|
||||
- name: Resolve versions
|
||||
id: info
|
||||
if: ${{ steps.mode.outputs.channel == 'Stable' }}
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
if [ "${{ steps.mode.outputs.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=v$VERSION" >> "$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$//; s/^v//')
|
||||
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"
|
||||
echo "mobile_tag=$MOBILE_RAW" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Check CHANGELOG.md has notes for this version
|
||||
if: ${{ steps.mode.outputs.channel == 'Stable' }}
|
||||
run: |
|
||||
node scripts/generate-release-body.cjs \
|
||||
--version "${{ steps.info.outputs.version }}" \
|
||||
--mobile-version "${{ steps.info.outputs.mobile_version }}" \
|
||||
--mobile-tag "${{ steps.info.outputs.mobile_tag }}" > /dev/null
|
||||
|
||||
- name: Resolve beta version
|
||||
id: beta
|
||||
if: ${{ steps.mode.outputs.channel == 'Beta' }}
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.TERMIX_PAT }}
|
||||
run: |
|
||||
if [ "${{ github.event_name }}" = "schedule" ]; then
|
||||
REFS=$(gh api "repos/${{ github.repository }}/branches" --paginate -q '.[].name')
|
||||
if ! DEV_BRANCH=$(printf '%s\n' "$REFS" | node scripts/latest-dev-branch.cjs 2>/dev/null); then
|
||||
echo "No dev-X.Y.Z branch is open, so no beta today."
|
||||
echo "skip=true" >> "$GITHUB_OUTPUT"
|
||||
exit 0
|
||||
fi
|
||||
else
|
||||
DEV_BRANCH="${GITHUB_REF#refs/heads/}"
|
||||
fi
|
||||
|
||||
BASE=$(node scripts/parse-dev-branch.cjs "$DEV_BRANCH")
|
||||
SHA=$(gh api "repos/${{ github.repository }}/branches/$DEV_BRANCH" -q .commit.sha)
|
||||
TAGS=$(gh api "repos/${{ github.repository }}/git/matching-refs/tags/v$BASE-beta." -q '.[].ref' | sed 's#^refs/tags/##')
|
||||
LATEST=$(printf '%s\n' "$TAGS" | node scripts/beta-version.cjs "$BASE" --latest)
|
||||
VERSION=$(printf '%s\n' "$TAGS" | node scripts/beta-version.cjs "$BASE")
|
||||
|
||||
if [ -n "$LATEST" ]; then
|
||||
LATEST_SHA=$(gh api "repos/${{ github.repository }}/commits/$LATEST" -q .sha)
|
||||
if [ "$LATEST_SHA" = "$SHA" ] && [ "${{ github.event_name }}" = "schedule" ]; then
|
||||
echo "$DEV_BRANCH has not moved since $LATEST, so no beta today."
|
||||
echo "skip=true" >> "$GITHUB_OUTPUT"
|
||||
exit 0
|
||||
fi
|
||||
PREV="$LATEST"
|
||||
else
|
||||
PREV=$(gh release view --repo ${{ github.repository }} --json tagName -q .tagName 2>/dev/null || true)
|
||||
fi
|
||||
|
||||
echo "Beta $VERSION from $DEV_BRANCH @ $SHA, changes since ${PREV:-nothing}"
|
||||
echo "skip=false" >> "$GITHUB_OUTPUT"
|
||||
echo "dev_branch=$DEV_BRANCH" >> "$GITHUB_OUTPUT"
|
||||
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
|
||||
echo "release_tag=v$VERSION" >> "$GITHUB_OUTPUT"
|
||||
echo "sha=$SHA" >> "$GITHUB_OUTPUT"
|
||||
echo "prev_ref=$PREV" >> "$GITHUB_OUTPUT"
|
||||
|
||||
verify-beta:
|
||||
needs: [prep]
|
||||
if: ${{ needs.prep.outputs.channel == 'Beta' && needs.prep.outputs.skip != 'true' }}
|
||||
runs-on: blacksmith-2vcpu-ubuntu-2404
|
||||
steps:
|
||||
- name: Checkout beta commit
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
ref: ${{ needs.prep.outputs.sha }}
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v7
|
||||
with:
|
||||
node-version-file: ".nvmrc"
|
||||
cache: "npm"
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Build plugin SDK
|
||||
run: npm run build:sdk
|
||||
|
||||
- name: Lint
|
||||
run: npm run lint
|
||||
|
||||
- name: Type check
|
||||
run: npm run type-check
|
||||
|
||||
- name: Build
|
||||
run: npm run build
|
||||
|
||||
- name: Run unit tests
|
||||
run: npm run test
|
||||
|
||||
normalize:
|
||||
needs: [prep]
|
||||
if: ${{ needs.prep.outputs.channel == 'Stable' && needs.prep.outputs.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.TERMIX_PAT }}
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v7
|
||||
with:
|
||||
node-version-file: ".nvmrc"
|
||||
cache: "npm"
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
# Manifest validation in lint loads the built SDK.
|
||||
- name: Build SDK
|
||||
run: npm run build:sdk
|
||||
|
||||
- name: Lint and format
|
||||
run: |
|
||||
npm run lint:fix
|
||||
npm run format
|
||||
npm run lint
|
||||
|
||||
- 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 [ "${{ needs.prep.outputs.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: ${{ needs.prep.outputs.channel == 'Stable' && needs.prep.outputs.mode != 'Dry run' && needs.prep.outputs.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.TERMIX_PAT }}
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v7
|
||||
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.TERMIX_PAT }}
|
||||
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@v3
|
||||
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 }}
|
||||
|
||||
# Off until the machine translation credits are topped up.
|
||||
- name: Pre-translate untranslated strings
|
||||
if: false
|
||||
env:
|
||||
CROWDIN_API_KEY: ${{ secrets.CROWDIN_API_KEY }}
|
||||
run: node scripts/crowdin-pretranslate.cjs
|
||||
|
||||
- name: Download translations from Crowdin
|
||||
uses: crowdin/github-action@v3
|
||||
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.prep.outputs.channel == 'Stable' && (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@v7
|
||||
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 }}" \
|
||||
--mobile-tag "${{ needs.prep.outputs.mobile_tag }}" > PR_BODY.md
|
||||
|
||||
- name: Open and squash-merge PR to main
|
||||
id: merge
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.TERMIX_PAT }}
|
||||
run: |
|
||||
DEV_BRANCH="${{ needs.prep.outputs.dev_branch }}"
|
||||
TITLE="v${{ needs.prep.outputs.version }}"
|
||||
|
||||
if [ "${{ needs.prep.outputs.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 [ "${{ needs.prep.outputs.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, verify-beta, merge-to-main]
|
||||
if: ${{ always() && needs.prep.result == 'success' && needs.prep.outputs.skip != 'true' && (needs.merge-to-main.result == 'success' || needs.verify-beta.result == 'success') }}
|
||||
uses: ./.github/workflows/docker.yml
|
||||
with:
|
||||
version: ${{ needs.prep.outputs.version }}
|
||||
build_type: ${{ needs.prep.outputs.channel == 'Beta' && 'Beta' || 'Production' }}
|
||||
dry_run: ${{ needs.prep.outputs.mode == 'Dry run' }}
|
||||
source_ref: ${{ needs.merge-to-main.outputs.build_ref || needs.prep.outputs.sha }}
|
||||
secrets: inherit
|
||||
|
||||
create-release:
|
||||
needs: [prep, merge-to-main, docker]
|
||||
if: ${{ always() && needs.prep.outputs.channel == 'Stable' && needs.docker.result == 'success' && needs.prep.outputs.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@v7
|
||||
with:
|
||||
node-version-file: ".nvmrc"
|
||||
|
||||
- name: Clear existing release artifacts (overwrite mode)
|
||||
if: ${{ needs.prep.outputs.mode == 'Overwrite release' }}
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.TERMIX_PAT }}
|
||||
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: ${{ needs.prep.outputs.mode != 'Overwrite release' }}
|
||||
run: |
|
||||
node scripts/generate-release-body.cjs \
|
||||
--version "${{ needs.prep.outputs.version }}" \
|
||||
--mobile-version "${{ needs.prep.outputs.mobile_version }}" \
|
||||
--mobile-tag "${{ needs.prep.outputs.mobile_tag }}" > RELEASE_BODY.md
|
||||
|
||||
- name: Create or update GitHub release
|
||||
if: ${{ needs.prep.outputs.mode != 'Overwrite release' }}
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.TERMIX_PAT }}
|
||||
run: |
|
||||
TAG="${{ needs.prep.outputs.release_tag }}"
|
||||
TITLE="v${{ 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
|
||||
|
||||
create-beta-release:
|
||||
needs: [prep, docker]
|
||||
if: ${{ always() && needs.prep.outputs.channel == 'Beta' && needs.docker.result == 'success' && needs.prep.outputs.mode != 'Dry run' }}
|
||||
runs-on: blacksmith-2vcpu-ubuntu-2404
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
- name: Checkout beta commit
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
ref: ${{ needs.prep.outputs.sha }}
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v7
|
||||
with:
|
||||
node-version-file: ".nvmrc"
|
||||
|
||||
- name: Generate beta release body
|
||||
run: |
|
||||
node scripts/generate-beta-body.cjs \
|
||||
--version "${{ needs.prep.outputs.version }}" \
|
||||
--branch "${{ needs.prep.outputs.dev_branch }}" \
|
||||
--sha "${{ needs.prep.outputs.sha }}" \
|
||||
--prev "${{ needs.prep.outputs.prev_ref }}" > BETA_BODY.md
|
||||
|
||||
- name: Create beta release
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.TERMIX_PAT }}
|
||||
run: |
|
||||
VERSION="${{ needs.prep.outputs.version }}"
|
||||
TITLE="Termix ${VERSION%-beta.*} Beta ${VERSION##*-beta.}"
|
||||
TAG="${{ needs.prep.outputs.release_tag }}"
|
||||
if gh release view "$TAG" --repo ${{ github.repository }} >/dev/null 2>&1; then
|
||||
gh release edit "$TAG" --repo ${{ github.repository }} \
|
||||
--title "$TITLE" --notes-file BETA_BODY.md --prerelease
|
||||
else
|
||||
gh release create "$TAG" --repo ${{ github.repository }} \
|
||||
--title "$TITLE" --notes-file BETA_BODY.md \
|
||||
--prerelease --target "${{ needs.prep.outputs.sha }}"
|
||||
fi
|
||||
|
||||
electron-release:
|
||||
needs: [prep, merge-to-main, docker, create-release, create-beta-release]
|
||||
if: ${{ always() && needs.prep.outputs.skip != 'true' && needs.docker.result == 'success' && needs.create-release.result != 'failure' && needs.create-beta-release.result != 'failure' }}
|
||||
uses: ./.github/workflows/electron.yml
|
||||
with:
|
||||
build_type: all
|
||||
artifact_destination: ${{ needs.prep.outputs.mode == 'Dry run' && 'file' || 'release' }}
|
||||
release_tag: ${{ needs.prep.outputs.release_tag }}
|
||||
version_override: ${{ needs.prep.outputs.channel == 'Beta' && needs.prep.outputs.version || '' }}
|
||||
source_ref: ${{ needs.merge-to-main.outputs.build_ref || needs.prep.outputs.sha }}
|
||||
secrets: inherit
|
||||
|
||||
electron-submit:
|
||||
needs: [prep, merge-to-main, electron-release]
|
||||
if: ${{ needs.prep.outputs.channel == 'Stable' && needs.prep.outputs.mode != 'Dry run' && needs.prep.outputs.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: ${{ needs.prep.outputs.channel == 'Stable' && needs.prep.outputs.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.TERMIX_PAT }}
|
||||
|
||||
- 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
|
||||
|
||||
git config user.name "LukeGus"
|
||||
git config user.email "bugattiguy527@gmail.com"
|
||||
|
||||
git fetch origin main
|
||||
git checkout -B main origin/main
|
||||
|
||||
sed -i "s|version \".*\"|version \"$VERSION\"|g" Casks/termix.rb
|
||||
sed -i "s|sha256 \".*\"|sha256 \"$DMG_SHA256\"|g" Casks/termix.rb
|
||||
|
||||
git add Casks/termix.rb
|
||||
if git diff --cached --quiet; then
|
||||
echo "Cask already up to date."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
git commit -m "chore: bump Homebrew cask to $VERSION"
|
||||
git push origin HEAD:main
|
||||
|
||||
prune-betas:
|
||||
needs: [prep, create-release]
|
||||
if: ${{ always() && needs.prep.outputs.channel == 'Stable' && needs.create-release.result == 'success' && needs.prep.outputs.mode != 'Overwrite release' }}
|
||||
runs-on: blacksmith-2vcpu-ubuntu-2404
|
||||
steps:
|
||||
- name: Delete this version's beta releases (tags stay)
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.TERMIX_PAT }}
|
||||
run: |
|
||||
PREFIX="v${{ needs.prep.outputs.version }}-beta."
|
||||
gh release list --repo ${{ github.repository }} --limit 200 --json tagName -q '.[].tagName' \
|
||||
| grep -F "$PREFIX" | while read -r TAG; do
|
||||
echo "Deleting release $TAG"
|
||||
gh release delete "$TAG" --repo ${{ github.repository }} --yes || true
|
||||
done
|
||||
|
||||
cleanup:
|
||||
needs: [prep, merge-to-main, electron-release, cask-commit-back]
|
||||
if: ${{ always() && needs.prep.outputs.channel == 'Stable' && (needs.prep.outputs.mode == 'Everything' || needs.prep.outputs.mode == 'Skip submit') && needs.merge-to-main.result == 'success' }}
|
||||
runs-on: blacksmith-2vcpu-ubuntu-2404
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
fetch-depth: 1
|
||||
persist-credentials: false
|
||||
|
||||
- name: Delete dev branch in Termix
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.TERMIX_PAT }}
|
||||
run: |
|
||||
git push https://x-access-token:${{ secrets.TERMIX_PAT }}@github.com/${{ github.repository }}.git \
|
||||
--delete "${{ needs.prep.outputs.dev_branch }}" || true
|
||||
+141
-24
@@ -1,3 +1,4 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
@@ -7,21 +8,13 @@ pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
src/mcp-server/node_modules
|
||||
dist
|
||||
dist-ssr
|
||||
coverage
|
||||
*.local
|
||||
|
||||
# Plugin build output. termix-plugin build writes it, the packaged server
|
||||
# gets its copy under dist/plugins.
|
||||
*.tmxplug
|
||||
*.tmxplug.sig
|
||||
termix-plugin-signing.key
|
||||
/src/**/*.js
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
.DS_Store
|
||||
*.suo
|
||||
@@ -30,18 +23,142 @@ termix-plugin-signing.key
|
||||
*.sln
|
||||
*.sw?
|
||||
|
||||
/db/
|
||||
/release/
|
||||
/.claude/
|
||||
/ssl/
|
||||
/uploads/
|
||||
/nul
|
||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
*.lcov
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# TypeScript v1 declaration files
|
||||
typings/
|
||||
|
||||
# TypeScript cache
|
||||
*.tsbuildinfo
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Microbundle cache
|
||||
.rpt2_cache/
|
||||
.rts2_cache_cjs/
|
||||
.rts2_cache_es/
|
||||
.rts2_cache_umd/
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variables file
|
||||
.env
|
||||
electron/build-info.cjs
|
||||
/.mcp.json
|
||||
/CLAUDE.md
|
||||
/old_db/
|
||||
/scripts/auto-fix.mjs
|
||||
/scripts/auto-fix-blocklist.json
|
||||
/scripts/auto-fix-state.json
|
||||
/scripts/auto-fix-report-*.json
|
||||
.env.test
|
||||
|
||||
# parcel-bundler cache (https://parceljs.org/)
|
||||
.cache
|
||||
|
||||
# Next.js build output
|
||||
.next
|
||||
|
||||
# Nuxt.js build / generate output
|
||||
.nuxt
|
||||
|
||||
# Gatsby files
|
||||
.cache/
|
||||
# Comment in the public line in if your project uses Gatsby and *not* Next.js
|
||||
# https://nextjs.org/blog/next-9-1#public-directory-support
|
||||
# public
|
||||
|
||||
# vuepress build output
|
||||
.vuepress/dist
|
||||
|
||||
# Serverless directories
|
||||
.serverless/
|
||||
|
||||
# FuseBox cache
|
||||
.fusebox/
|
||||
|
||||
# DynamoDB Local files
|
||||
.dynamodb/
|
||||
|
||||
# TernJS port file
|
||||
.tern-port
|
||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
/.pnp
|
||||
.pnp.js
|
||||
|
||||
# testing
|
||||
/coverage
|
||||
|
||||
# production
|
||||
/build
|
||||
|
||||
# misc
|
||||
.env.local
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
|
||||
.bash_history
|
||||
.bashrc
|
||||
.init_done
|
||||
.profile
|
||||
.sudo_as_admin_successful
|
||||
.wget-hsts
|
||||
.git-credentials
|
||||
.docker/
|
||||
.bash_logout
|
||||
|
||||
# VSCode Files
|
||||
.vscode-server/
|
||||
|
||||
# Configs
|
||||
.config/
|
||||
|
||||
# .dotnet
|
||||
.dotnet/
|
||||
|
||||
# .local
|
||||
.local/
|
||||
/docker/docker-compose.yml
|
||||
/src/data/
|
||||
/docker/mongodb/
|
||||
/docker/docker-compose.yml
|
||||
@@ -1 +0,0 @@
|
||||
npx --no -- commitlint --edit "$1"
|
||||
@@ -1,3 +0,0 @@
|
||||
# The .cmd shims on Windows add their own paths to each command, so keep
|
||||
# lint-staged's chunks well under cmd.exe's 8191 character limit.
|
||||
npx lint-staged --max-arg-length 4000
|
||||
@@ -1,24 +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
|
||||
|
||||
# Generated by drizzle-kit; formatting is the tool's own
|
||||
drizzle/
|
||||
|
||||
src/ui/settings/settings-search-index.ts
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"semi": true,
|
||||
"singleQuote": false,
|
||||
"tabWidth": 2,
|
||||
"trailingComma": "all",
|
||||
"printWidth": 80,
|
||||
"arrowParens": "always",
|
||||
"endOfLine": "lf"
|
||||
}
|
||||
Vendored
-22
@@ -1,22 +0,0 @@
|
||||
{
|
||||
"editor.formatOnSave": true,
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"prettier.prettierPath": "./node_modules/prettier",
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll.eslint": "explicit"
|
||||
},
|
||||
"eslint.validate": [
|
||||
"javascript",
|
||||
"javascriptreact",
|
||||
"typescript",
|
||||
"typescriptreact"
|
||||
],
|
||||
"files.eol": "\n",
|
||||
"files.insertFinalNewline": true,
|
||||
"files.trimTrailingWhitespace": true,
|
||||
"[markdown]": {
|
||||
"files.trimTrailingWhitespace": false
|
||||
},
|
||||
"typescript.tsdk": "node_modules/typescript/lib",
|
||||
"typescript.enablePromptUseWorkspaceTsdk": true
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
# Changelog
|
||||
|
||||
## 26.10.0
|
||||
|
||||
### Added
|
||||
|
||||
- Temp
|
||||
|
||||
### Changed
|
||||
|
||||
- Tem
|
||||
|
||||
### Removed
|
||||
|
||||
- Downgrading to 2.8 is no longer supported. A 2.8 install has to start 2.9 once before upgrading
|
||||
@@ -1,75 +0,0 @@
|
||||
# Contributing
|
||||
|
||||
Termix is a small core plus plugins. This repo is the core: hosts, credentials, users, sharing, sessions, the app shell and the plugin runtime. Every other feature lives in its own `Plugin-<Name>` repo. If your change is about the terminal, file manager, Docker or any other plugin feature, open it in that plugin's repo instead.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [Node.js](https://nodejs.org/en/download/) 22.12 or newer (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
|
||||
|
||||
```sh
|
||||
npm run dev
|
||||
```
|
||||
|
||||
This builds everything, starts the backend and then the Vite server at `http://localhost:5173/`. Backend changes restart the backend, and plugin changes in `../Termix-Plugins` rebuild and reload that plugin. `npm run dev:electron` does the same with the desktop app, and `npm run dev -- --help` lists the other options.
|
||||
|
||||
## Useful commands
|
||||
|
||||
```sh
|
||||
npm run test # run the test suite
|
||||
npm run type-check # type-check the core
|
||||
npm run lint # lint and the other repo checks
|
||||
npm run format # format the code with Prettier
|
||||
```
|
||||
|
||||
## Making a change
|
||||
|
||||
1. **Fork the repository**: Click "Fork" at the top right of the [repository page](https://github.com/Termix-SSH/Termix).
|
||||
2. **Create a branch**:
|
||||
```sh
|
||||
git checkout -b feature/my-new-feature
|
||||
```
|
||||
3. **Make your changes** and add or update tests for them.
|
||||
4. **Commit your changes**:
|
||||
```sh
|
||||
git commit -m "feat: add my new feature"
|
||||
```
|
||||
5. **Push to your fork**:
|
||||
```sh
|
||||
git push origin feature/my-new-feature
|
||||
```
|
||||
6. **Open a pull request** against the current `dev-*` branch with a clear description.
|
||||
|
||||
## Guidelines
|
||||
|
||||
- Follow the existing code style. The frontend uses React, Tailwind CSS and shadcn components in `src/ui/`.
|
||||
- Never hardcode text. Use `t()` and add the English string to `src/ui/locales/en.json`. Other languages are translated on [Crowdin](https://docs.termix.site/translations).
|
||||
- Keep the UI flat and square. Avoid rounded corners on panels, cards and dialogs.
|
||||
- Use the theme variables (like `var(--bg-base)` and `var(--text-primary)`) instead of fixed colors.
|
||||
- There is one component tree for desktop and mobile. Use `src/ui/hooks/use-mobile.ts` for layout changes.
|
||||
- Core never names a plugin. If core needs something from a plugin, add a slot, action or component id that the plugin fills.
|
||||
- Tests live in `src/backend/tests/` and `src/ui/tests/`, mirroring the source tree. `npm run test` must pass.
|
||||
- Every API route gets an OpenAPI JSDoc comment like the routes around it.
|
||||
- Use short commit messages that start with `feat:`, `fix:` or `chore:`, and link related issues.
|
||||
|
||||
## Building a plugin
|
||||
|
||||
Start from the [plugin template](https://github.com/Termix-SSH/Termix-Plugin-Template). It talks to Termix only through `@termix-ssh/plugin-sdk` and has its own build, test and release setup.
|
||||
|
||||
## Support
|
||||
|
||||
Bugs and ideas for Termix itself go in [this repo](https://github.com/Termix-SSH/Termix/issues/new/choose). Plugin problems go in that plugin's own `Plugin-<Name>` repo. Please be as detailed as possible, preferably in English. You can also ask in the [Discord](https://discord.gg/jVQGdvHDrf) server.
|
||||
@@ -1,24 +0,0 @@
|
||||
cask "termix" do
|
||||
version "2.9.1"
|
||||
sha256 "6d8847e18508314db8ed4380c63bf0dd31437102a288b8e861879c92ba25a254"
|
||||
|
||||
url "https://github.com/Termix-SSH/Termix/releases/download/v#{version}/termix_macos_universal_dmg.dmg"
|
||||
name "Termix"
|
||||
desc "Self-hosted, plugin-based server management"
|
||||
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
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"drips": {
|
||||
"ethereum": {
|
||||
"ownedBy": "0x67e0C779119D9BcC2187564A66B80a58767d05d1"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,21 @@
|
||||
Copyright 2025 Luke Gustafson
|
||||
MIT License
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
Copyright (c) 2025 Luke Gustafson
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -1,257 +1,62 @@
|
||||
<div align="center">
|
||||
# Repo Stats
|
||||

|
||||

|
||||

|
||||
<a href="https://discord.gg/jVQGdvHDrf"><img alt="Discord" src="https://img.shields.io/discord/1347374268253470720"></a>
|
||||
#### Top Technologies
|
||||
[](#)
|
||||
[](#)
|
||||
[](#)
|
||||
[](#)
|
||||
[](#)
|
||||
[](#)
|
||||
[](#)
|
||||
[](#)
|
||||
|
||||
<img src="./public/icon.svg" width="120" height="120" alt="Termix Logo" />
|
||||
|
||||
<h1>Termix</h1>
|
||||
|
||||
<p>Self-hosted, plugin-based server management</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>
|
||||
<br />
|
||||
<p align="center">
|
||||
<a href="https://github.com/LukeGus/Termix">
|
||||
<img alt="Termix Banner" src=./repo-images/TermixLogo.png style="width: 125px; height: auto;"> </a>
|
||||
</p>
|
||||
|
||||
<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>
|
||||
If you would like, you can support the project here!\
|
||||
[](https://paypal.me/LukeGustafson803)
|
||||
|
||||
</div>
|
||||
# Overview
|
||||
Termix is an open-source forever free self-hosted SSH (other protocols planned, see [Planned Features](#planned-features)) server management panel inspired by [Nexterm](https://github.com/gnmyt/Nexterm). Its purpose is to provide an all-in-one docker-hosted web solution to manage your servers in one easy place. I'm using this project to help me learn [React](https://github.com/facebook/react), [Vite](https://github.com/vitejs/vite-plugin-react), and [Docker](https://www.docker.com) but also because I could never settle on a server management software that I enjoyed to use.
|
||||
|
||||
<br />
|
||||
> [!WARNING]
|
||||
> This app is in the VERY early stages of development. Expect bugs, data loss, and unexplainable issues! For that reason, I recommend you securely tunnel your connection to Termix through a VPN.
|
||||
|
||||
## Overview
|
||||
# Features
|
||||
- SSH
|
||||
- Split Screen (Up to 4) & Tab System
|
||||
- User Authentication
|
||||
- Save Hosts (and easily view, connect, and manage them)
|
||||
|
||||
Termix is a free, open source, self-hosted platform for managing your servers, built on plugins. The core is small. It keeps your hosts, credentials, users, sharing and sessions. Everything else, like the SSH terminal, remote desktop, file manager, Docker and metrics, is a plugin you can turn on, turn off or remove.
|
||||
# Planned Features
|
||||
- VNC
|
||||
- RDP
|
||||
- SFTP (build in file transfer)
|
||||
- ChatGPT/Ollama Integration (for commands)
|
||||
- Apps (like notes, AI, etc)
|
||||
- Terminal Themes
|
||||
- User Management (roles, permissions, etc.)
|
||||
- SSH Tunneling
|
||||
- More Authentication Methods
|
||||
- More Security Features (like 2FA, etc.)
|
||||
|
||||
It runs on web, desktop and mobile, and it is a self-hosted alternative to Termius that stays free forever.
|
||||
# Installation
|
||||
Visit the Termix [Wiki](https://github.com/LukeGus/Termix/wiki) for information on how to install Termix. You can also use these links to go directly to guide. [Docker](https://github.com/LukeGus/Termix/wiki/Docker) or [Manual](https://github.com/LukeGus/Termix/wiki/Manual).
|
||||
|
||||
<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. If you would like to support me financially, you can on [Paypal](https://paypal.me/LukeGustafson803).
|
||||
|
||||
## Try the Demo
|
||||
# Show-off
|
||||
|
||||
Want to see it before you install it? Try the demo at [demo.termix.site](https://demo.termix.site/). Any username and password works.
|
||||

|
||||

|
||||
|
||||
<br />
|
||||
|
||||
## Core
|
||||
|
||||
What every Termix install has, with or without plugins:
|
||||
|
||||
- **Hosts:** Save hosts in nested folders with tags and parent hosts, bulk edit, import and export, and use Quick Connect for one-off connections
|
||||
- **Credentials:** Reuse saved passwords and keys across hosts, with host defaults you can set for the server, a user or a folder
|
||||
- **Sharing and Roles:** Share hosts, credentials and folders with users or roles at four levels: connect, view, edit and manage
|
||||
- **Accounts:** Local accounts, sessions you can see and revoke, trusted devices, API keys and an audit log
|
||||
- **Security:** Passwords, keys and other secrets are encrypted per user, and the database can be encrypted on disk
|
||||
- **Desktop Sync:** The desktop app runs on its own and can link to a Termix server to keep an offline copy of your account
|
||||
- **Interface:** Tabs and split screen, a command palette (double tap left shift), rebindable shortcuts, themes, branding and around 30 languages
|
||||
- **Databases:** SQLite by default, with PostgreSQL and MySQL supported too
|
||||
|
||||
<br />
|
||||
|
||||
## Plugins
|
||||
|
||||
Plugins add everything else. The official ones ship with Termix, and admins can install, update or remove plugins from the Plugins tab. Each plugin has its own repo.
|
||||
|
||||
| Plugin | What it does |
|
||||
| --------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- |
|
||||
| [ACME Certificates](https://github.com/Termix-SSH/Plugin-ACME-SSL) | Gets the Termix HTTPS certificate from Let's Encrypt or any ACME provider and renews it for you. |
|
||||
| [AI Assistant](https://github.com/Termix-SSH/Plugin-AI) | An AI assistant that reads your setup and proposes changes for you to approve. |
|
||||
| [Alerts](https://github.com/Termix-SSH/Plugin-Alerts) | One inbox for every alert in Termix, with delivery to webhooks, ntfy, Discord and email. |
|
||||
| [Automations](https://github.com/Termix-SSH/Plugin-Automations) | Run steps on your hosts on a schedule or when something happens. |
|
||||
| [Docker](https://github.com/Termix-SSH/Plugin-Docker) | Manage Docker and Podman containers on your hosts over SSH, with logs, stats and a console. |
|
||||
| [File Manager](https://github.com/Termix-SSH/Plugin-File-Manager) | Browse, edit and move files over SFTP, including straight from one server to another. |
|
||||
| [Fleets](https://github.com/Termix-SSH/Plugin-Fleets) | Group hosts into fleets and run commands, package actions and file transfers on all of them at once. |
|
||||
| [HashiCorp Vault](https://github.com/Termix-SSH/Plugin-Vault) | Connect to hosts with short-lived SSH certificates signed by HashiCorp Vault. |
|
||||
| [Homepage](https://github.com/Termix-SSH/Plugin-Homepage) | A drag and drop widget page for your servers and services, plus service links for the dashboard. |
|
||||
| [Host Metrics](https://github.com/Termix-SSH/Plugin-Host-Metrics) | Live CPU, memory, disk, network and GPU stats, plus tools to manage your hosts. |
|
||||
| [LDAP](https://github.com/Termix-SSH/Plugin-LDAP) | Sign in with your LDAP or Active Directory username and password. |
|
||||
| [Network Topology](https://github.com/Termix-SSH/Plugin-Network-Topology) | Draws your hosts and the links between them as a live, interactive graph. |
|
||||
| [OPKSSH](https://github.com/Termix-SSH/Plugin-OPKSSH) | Connect to hosts with short-lived OpenPubkey SSH certificates after signing in with your identity provider. |
|
||||
| [Passkeys](https://github.com/Termix-SSH/Plugin-WebAuthn) | Sign in with a passkey or security key instead of a password. |
|
||||
| [Proxmox](https://github.com/Termix-SSH/Plugin-Proxmox) | Import Proxmox VE guests as hosts, keep them in sync and watch node stats. |
|
||||
| [Remote Desktop](https://github.com/Termix-SSH/Plugin-Remote-Desktop) | RDP, VNC and Telnet sessions in your browser, with clipboard, file transfer, sharing and recording. |
|
||||
| [Secret Sources](https://github.com/Termix-SSH/Plugin-Secret-Sources) | Pull host passwords and keys from 1Password when you connect instead of storing them in Termix. |
|
||||
| [Serial](https://github.com/Termix-SSH/Plugin-Serial) | Open a serial console to a router, switch or other device plugged into your computer. |
|
||||
| [Session Recording](https://github.com/Termix-SSH/Plugin-Session-Recording) | Record terminal and remote desktop sessions and play them back or download them later. |
|
||||
| [Session Sharing](https://github.com/Termix-SSH/Plugin-Session-Sharing) | Share live sessions by link or with another user, and present sessions to a group in meeting rooms. |
|
||||
| [Single sign-on](https://github.com/Termix-SSH/Plugin-SSO) | Sign in with any OpenID Connect provider, GitHub or Google. |
|
||||
| [Snippets](https://github.com/Termix-SSH/Plugin-Snippets) | Save the commands you run often and run them in a terminal or on many hosts in one click. |
|
||||
| [SSH Terminal](https://github.com/Termix-SSH/Plugin-SSH-Terminal) | SSH terminal sessions with tabs, split screen, history, macros and a local terminal in the desktop app. |
|
||||
| [Step CA](https://github.com/Termix-SSH/Plugin-Step-CA) | Connect to hosts with short-lived SSH certificates from a smallstep step-ca server. |
|
||||
| [Tailscale](https://github.com/Termix-SSH/Plugin-Tailscale) | Add tailnet devices as hosts and connect with Tailscale SSH. |
|
||||
| [Termix Identity](https://github.com/Termix-SSH/Plugin-Termix-Identity) | Publish your SSH public keys under a public handle and run your own SSH certificate authority. |
|
||||
| [Tmux Monitor](https://github.com/Termix-SSH/Plugin-Tmux-Monitor) | Browse and control tmux sessions, windows and panes across your hosts. |
|
||||
| [TOTP](https://github.com/Termix-SSH/Plugin-TOTP) | Two-factor sign in with a code from an authenticator app, with backup codes. |
|
||||
| [Tunnels](https://github.com/Termix-SSH/Plugin-Tunnels) | SSH port forwarding that reconnects on its own, plus client tunnels from the desktop app. |
|
||||
| [Usage Statistics](https://github.com/Termix-SSH/Plugin-Telemetry) | Sends a small anonymous daily report so we can see how Termix is used. |
|
||||
| [Wake-on-LAN](https://github.com/Termix-SSH/Plugin-Wake-On-LAN) | Wake sleeping machines by sending a Wake-on-LAN packet to their MAC address. |
|
||||
| [Warpgate](https://github.com/Termix-SSH/Plugin-Warpgate) | Connect to hosts through a Warpgate SSH bastion. |
|
||||
| [Web Endpoint](https://github.com/Termix-SSH/Plugin-Web-Endpoint) | Open a host's web UI inside Termix, directly or over an SSH tunnel. |
|
||||
| [Workspaces](https://github.com/Termix-SSH/Plugin-Workspaces) | Save your open tabs and split layouts and reopen them in one click. |
|
||||
|
||||
Want to build your own? Start from the [plugin template](https://github.com/Termix-SSH/Termix-Plugin-Template). Plugins you can install are listed in the [registry](https://github.com/Termix-SSH/Termix-Registry).
|
||||
|
||||
<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 install steps on every platform.
|
||||
|
||||
Sample Docker Compose file (you can leave out `guacd` and the network if you don't plan to use the Remote Desktop plugin):
|
||||
|
||||
```yaml
|
||||
services:
|
||||
termix:
|
||||
image: ghcr.io/termix-ssh/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
|
||||
```
|
||||
|
||||
### Cloud Hosting
|
||||
|
||||
You can run Termix on a VPS instead of inside your own network. If Termix runs on the network it manages, an outage takes Termix down with it, right when you need it to fix things. Running it somewhere else keeps it reachable, gives you a static IP and lets you get in from anywhere without a VPN or port forward.
|
||||
|
||||
[GINERNET](https://docs.termix.site/install/ginernet) sponsors Termix, and the docs have a step by step guide for their VPS platform.
|
||||
|
||||
<br />
|
||||
|
||||
## Donate
|
||||
|
||||
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.
|
||||
|
||||
[Donate](https://donate.termix.site/)
|
||||
|
||||
<br />
|
||||
|
||||
## Sponsors
|
||||
|
||||
Interested in a paid placement to support development? Email [mail@termix.site](mailto:mail@termix.site).
|
||||
|
||||
<!-- SPONSORS:START -->
|
||||
|
||||
<div align="center">
|
||||
|
||||
<br />
|
||||
|
||||
<a href="https://www.digitalocean.com/">
|
||||
<img src="https://termix.site/img/sponsors/digitalocean.svg" height="40" alt="DigitalOcean" />
|
||||
</a>
|
||||
|
||||
<a href="https://crowdin.com/">
|
||||
<img src="https://termix.site/img/sponsors/crowdin.svg" height="40" alt="Crowdin" />
|
||||
</a>
|
||||
|
||||
<a href="https://www.blacksmith.sh/">
|
||||
<img src="https://termix.site/img/sponsors/blacksmith.svg" height="40" alt="Blacksmith" />
|
||||
</a>
|
||||
|
||||
<a href="https://www.cloudflare.com/">
|
||||
<img src="https://termix.site/img/sponsors/cloudflare.png" height="40" alt="Cloudflare" />
|
||||
</a>
|
||||
|
||||
<a href="https://akamai.com/">
|
||||
<img src="https://termix.site/img/sponsors/akamai.svg" height="40" alt="Akamai" />
|
||||
</a>
|
||||
|
||||
<a href="https://aws.amazon.com/">
|
||||
<img src="https://termix.site/img/sponsors/aws.png" height="40" alt="AWS" />
|
||||
</a>
|
||||
|
||||
<a href="https://rackgenius.com/">
|
||||
<img src="https://termix.site/img/sponsors/rackgenius.png" height="40" alt="Rack Genius" />
|
||||
</a>
|
||||
|
||||
<a href="https://ginernet.com/">
|
||||
<img src="https://termix.site/img/sponsors/ginernet.png" height="40" alt="Ginernet" />
|
||||
</a>
|
||||
|
||||
<a href="https://www.hetzner.com/?mtm_campaign=termix&mtm_medium=referral&mtm_content=sponsoring_link">
|
||||
<img src="https://termix.site/img/sponsors/hetzner.png" height="40" alt="Hetzner" />
|
||||
</a>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- SPONSORS:END -->
|
||||
|
||||
<br />
|
||||
|
||||
## Support
|
||||
|
||||
Bugs and ideas for Termix itself (login, hosts, credentials, sharing, sync, the app and desktop app) go in this repo: [report a bug](https://github.com/Termix-SSH/Termix/issues/new?template=bug_report.yml) or [request a feature](https://github.com/Termix-SSH/Termix/issues/new?template=feature_request.yml).
|
||||
|
||||
Every plugin has its own repo, so a problem with the terminal, file manager, Docker, remote desktop or any other plugin goes in that plugin's repo (see the table above, or use Report an issue on the plugin's page in the app, which fills in your versions for you). Not sure where it goes? Open it here and it will be moved.
|
||||
|
||||
You need to be logged in to GitHub. Please be as detailed as possible, preferably in English.
|
||||
|
||||
For discussions and questions, join the [Discord](https://discord.gg/jVQGdvHDrf) server. Update videos are on [YouTube](https://www.youtube.com/@TermixSSH/videos).
|
||||
|
||||
<br />
|
||||
|
||||
## License
|
||||
|
||||
Distributed under the Apache License Version 2.0. See [LICENSE](https://github.com/Termix-SSH/Termix/blob/main/LICENSE) for more information.
|
||||
# License
|
||||
Distributed under the MIT license. See LICENSE for more information.
|
||||
-23
@@ -1,23 +0,0 @@
|
||||
# Security Policy
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
Please report any vulnerabilities to [GitHub Security](https://github.com/Termix-SSH/Termix/security/advisories).
|
||||
|
||||
## External secret storage
|
||||
|
||||
By default, a single-container installation generates its keys in the Termix
|
||||
data directory for ease of recovery. Production deployments that keep backups
|
||||
or database files outside a trusted encrypted volume should set
|
||||
`TERMIX_REQUIRE_EXTERNAL_SECRETS=true` and provide all four keys through a
|
||||
secret manager:
|
||||
|
||||
- `JWT_SECRET` (at least 64 characters)
|
||||
- `DATABASE_KEY` (64 hexadecimal characters)
|
||||
- `ENCRYPTION_KEY` (64 hexadecimal characters)
|
||||
- `INTERNAL_AUTH_TOKEN` (at least 32 characters)
|
||||
|
||||
Each value can instead be mounted as a Docker or Kubernetes secret and supplied
|
||||
with its corresponding `_FILE` variable, such as `ENCRYPTION_KEY_FILE`.
|
||||
Hardened mode fails closed instead of writing a replacement key beside the
|
||||
encrypted database.
|
||||
@@ -1,25 +0,0 @@
|
||||
{
|
||||
"$schema": "https://ui.shadcn.com/schema.json",
|
||||
"style": "radix-lyra",
|
||||
"rsc": false,
|
||||
"tsx": true,
|
||||
"tailwind": {
|
||||
"config": "",
|
||||
"css": "src/index.css",
|
||||
"baseColor": "neutral",
|
||||
"cssVariables": true,
|
||||
"prefix": ""
|
||||
},
|
||||
"iconLibrary": "lucide",
|
||||
"rtl": false,
|
||||
"aliases": {
|
||||
"components": "@/components",
|
||||
"utils": "@/lib/utils",
|
||||
"ui": "@/components/ui",
|
||||
"lib": "@/lib",
|
||||
"hooks": "@/hooks"
|
||||
},
|
||||
"menuColor": "default",
|
||||
"menuAccent": "subtle",
|
||||
"registries": {}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
project_id: "858252"
|
||||
api_token: "env:CROWDIN_API_TOKEN"
|
||||
preserve_hierarchy: true
|
||||
|
||||
files:
|
||||
# Core has always lived at /en.json in Crowdin; moving it would orphan its translations.
|
||||
- source: /src/ui/locales/en.json
|
||||
dest: /en.json
|
||||
translation: /src/ui/locales/translated/%locale_with_underscore%.json
|
||||
+88
-120
@@ -1,139 +1,107 @@
|
||||
# Stage 1: Install dependencies
|
||||
# The builders only produce JS, so they run on the build machine's own arch
|
||||
# once instead of under QEMU per target. Rolldown hangs under arm64 emulation.
|
||||
FROM --platform=$BUILDPLATFORM node:26-slim AS deps
|
||||
# Stage 1: Build frontend
|
||||
FROM node:18-alpine AS frontend-builder
|
||||
WORKDIR /app
|
||||
|
||||
RUN apt-get update && apt-get install -y python3 make g++ && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
COPY package*.json ./
|
||||
COPY packages/plugin-sdk/package.json ./packages/plugin-sdk/package.json
|
||||
COPY .npmrc ./
|
||||
COPY vendor ./vendor
|
||||
|
||||
COPY scripts/patch-ssh2-agent.cjs ./scripts/
|
||||
|
||||
RUN npm ci --ignore-scripts && \
|
||||
node scripts/patch-ssh2-agent.cjs && \
|
||||
RUN npm ci --force && \
|
||||
npm cache clean --force
|
||||
|
||||
# Stage 2: Build frontend
|
||||
FROM deps AS frontend-builder
|
||||
WORKDIR /app
|
||||
|
||||
COPY . .
|
||||
RUN npm run build
|
||||
|
||||
RUN find public/fonts -name "*.ttf" ! -name "*Regular.ttf" ! -name "*Bold.ttf" ! -name "*Italic.ttf" -delete
|
||||
|
||||
RUN npm cache clean --force && \
|
||||
NODE_OPTIONS="--max-old-space-size=3072" npm run build
|
||||
|
||||
# Stage 3: Build backend
|
||||
FROM deps AS backend-builder
|
||||
# Stage 2: Build backend
|
||||
FROM node:18-alpine AS backend-builder
|
||||
WORKDIR /app
|
||||
|
||||
COPY . .
|
||||
|
||||
RUN npm run build:backend
|
||||
|
||||
# Stage 4: Download OPKSSH binary for the target platform so the image works offline
|
||||
FROM node:26-slim AS opkssh-downloader
|
||||
ARG TARGETARCH
|
||||
ARG OPKSSH_VERSION=v0.16.0
|
||||
ARG OPKSSH_SHA256_AMD64=c018c3e7baf98612b923e742dd87be38650bf61e3b755fb2bc90de177568b1bf
|
||||
ARG OPKSSH_SHA256_ARM64=9dd10c2b6ce99cde18e52c054877ca014134b291fd82afe71741c68db4f83d44
|
||||
WORKDIR /opkssh
|
||||
|
||||
RUN apt-get update && apt-get install -y curl ca-certificates && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
RUN case "$TARGETARCH" in \
|
||||
amd64) OPKSSH_ARCH=amd64; OPKSSH_SHA256="$OPKSSH_SHA256_AMD64" ;; \
|
||||
arm64) OPKSSH_ARCH=arm64; OPKSSH_SHA256="$OPKSSH_SHA256_ARM64" ;; \
|
||||
*) echo "Unsupported architecture: $TARGETARCH" && exit 1 ;; \
|
||||
esac && \
|
||||
curl -fSL -o "opkssh-linux-${OPKSSH_ARCH}" \
|
||||
"https://github.com/openpubkey/opkssh/releases/download/${OPKSSH_VERSION}/opkssh-linux-${OPKSSH_ARCH}" && \
|
||||
echo "$OPKSSH_SHA256 opkssh-linux-${OPKSSH_ARCH}" | sha256sum -c - && \
|
||||
chmod 755 "opkssh-linux-${OPKSSH_ARCH}" && \
|
||||
echo -n "$OPKSSH_VERSION" > version.txt
|
||||
|
||||
# Stage 5: Production dependencies only
|
||||
FROM node:26-slim 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 ./
|
||||
# The plugin SDK is a workspace package core imports at runtime, so npm ci
|
||||
# has to see it to link it and install its dependencies.
|
||||
COPY packages/plugin-sdk/package.json ./packages/plugin-sdk/package.json
|
||||
COPY .npmrc ./
|
||||
COPY vendor ./vendor
|
||||
|
||||
COPY scripts/patch-ssh2-agent.cjs ./scripts/
|
||||
|
||||
RUN npm ci --omit=dev --ignore-scripts && \
|
||||
node scripts/patch-ssh2-agent.cjs && \
|
||||
rm -rf node_modules/better-sqlite3/prebuilds && \
|
||||
npm run build-release --prefix node_modules/better-sqlite3 && \
|
||||
test -f node_modules/better-sqlite3/build/Release/better_sqlite3.node && \
|
||||
npm rebuild bcryptjs ssh2 && \
|
||||
RUN npm ci --only=production --force && \
|
||||
npm cache clean --force
|
||||
COPY src/backend/ ./src/backend/
|
||||
|
||||
# Stage 6: Final optimized image
|
||||
FROM node:26-slim
|
||||
# Stage 3: Build bcrypt for Ubuntu
|
||||
FROM ubuntu:focal AS bcrypt-builder
|
||||
ENV DEBIAN_FRONTEND=noninteractive \
|
||||
NODE_VERSION=18.x
|
||||
WORKDIR /app
|
||||
COPY package*.json ./
|
||||
RUN rm -f /var/lib/apt/lists/lock /var/cache/apt/archives/lock /var/lib/dpkg/lock* && \
|
||||
apt-get clean && \
|
||||
apt-get update && \
|
||||
apt-get install -y --no-install-recommends \
|
||||
python3 \
|
||||
make \
|
||||
g++ \
|
||||
wget \
|
||||
ca-certificates \
|
||||
gnupg && \
|
||||
wget -qO- https://deb.nodesource.com/setup_${NODE_VERSION} | bash - && \
|
||||
apt-get update && \
|
||||
apt-get install -y nodejs && \
|
||||
npm ci --only=production bcrypt --force && \
|
||||
npm cache clean --force && \
|
||||
apt-get clean && \
|
||||
rm -rf /var/lib/apt/lists/* /var/cache/apt/* /tmp/*
|
||||
|
||||
# The release the opkssh-downloader stage baked in, so the plugin trusts that
|
||||
# binary when the build picks a version other than its pinned one.
|
||||
ARG OPKSSH_VERSION=v0.16.0
|
||||
ARG OPKSSH_SHA256_AMD64=c018c3e7baf98612b923e742dd87be38650bf61e3b755fb2bc90de177568b1bf
|
||||
ARG OPKSSH_SHA256_ARM64=9dd10c2b6ce99cde18e52c054877ca014134b291fd82afe71741c68db4f83d44
|
||||
# Final stage
|
||||
FROM ubuntu:focal
|
||||
ENV DEBIAN_FRONTEND=noninteractive \
|
||||
NODE_VERSION=18.x \
|
||||
MONGO_VERSION=4.4.24 \
|
||||
MONGO_URL=mongodb://localhost:27017/termix \
|
||||
MONGODB_DATA_DIR=/data/db \
|
||||
MONGODB_LOG_DIR=/var/log/mongodb \
|
||||
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
|
||||
|
||||
ENV DATA_DIR=/app/data \
|
||||
OPKSSH_BUNDLED_DIR=/app/opkssh-bundled \
|
||||
OPKSSH_VERSION=$OPKSSH_VERSION \
|
||||
OPKSSH_SHA256_AMD64=$OPKSSH_SHA256_AMD64 \
|
||||
OPKSSH_SHA256_ARM64=$OPKSSH_SHA256_ARM64 \
|
||||
PORT=8080 \
|
||||
NODE_ENV=production
|
||||
# Create users first
|
||||
RUN groupadd -r mongodb && useradd -r -g mongodb mongodb \
|
||||
&& groupadd -r node && useradd -r -g node -m node
|
||||
|
||||
RUN apt-get update && apt-get install -y nginx gettext-base openssl ca-certificates gosu wget && \
|
||||
update-ca-certificates && \
|
||||
rm -rf /var/lib/apt/lists/* && \
|
||||
mkdir -p /app/data /app/uploads /app/nginx /tmp/nginx && \
|
||||
chown -R node:node /app /tmp/nginx && \
|
||||
chmod 755 /app/data /app/uploads /app/nginx /tmp/nginx
|
||||
# Install all dependencies in one layer
|
||||
RUN rm -f /var/lib/apt/lists/lock /var/cache/apt/archives/lock /var/lib/dpkg/lock* && \
|
||||
apt-get clean && \
|
||||
apt-get update && \
|
||||
apt-get install -y --no-install-recommends \
|
||||
ca-certificates \
|
||||
gnupg \
|
||||
gosu \
|
||||
nginx-light \
|
||||
wget && \
|
||||
# Add MongoDB 4.4 repository
|
||||
wget -qO - https://www.mongodb.org/static/pgp/server-4.4.asc | apt-key add - && \
|
||||
echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu focal/mongodb-org/4.4 multiverse" | tee /etc/apt/sources.list.d/mongodb-org-4.4.list && \
|
||||
# Add MongoDB 5.0 repository
|
||||
wget -qO - https://www.mongodb.org/static/pgp/server-5.0.asc | apt-key add - && \
|
||||
echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu focal/mongodb-org/5.0 multiverse" | tee /etc/apt/sources.list.d/mongodb-org-5.0.list && \
|
||||
# Add NodeJS repository
|
||||
wget -qO- https://deb.nodesource.com/setup_${NODE_VERSION} | bash - && \
|
||||
apt-get update && \
|
||||
# Install MongoDB 4.4 and 5.0 packages
|
||||
apt-get install -y --no-install-recommends \
|
||||
nodejs \
|
||||
mongodb-org-server=${MONGO_VERSION} \
|
||||
mongodb-org-shell=${MONGO_VERSION} \
|
||||
mongodb-org-server=5.0.21 && \
|
||||
apt-get clean && \
|
||||
rm -rf /var/lib/apt/lists/* /var/cache/apt/* /tmp/* && \
|
||||
mkdir -p /data/db /var/log/mongodb /var/run/mongodb && \
|
||||
chown -R mongodb:mongodb /data/db /var/log/mongodb /var/run/mongodb && \
|
||||
chmod 755 /data/db /var/log/mongodb /var/run/mongodb
|
||||
|
||||
COPY docker/nginx.conf /app/nginx/nginx.conf.template
|
||||
COPY docker/nginx-https.conf /app/nginx/nginx-https.conf.template
|
||||
# Setup nginx and frontend
|
||||
COPY docker/nginx.conf /etc/nginx/nginx.conf
|
||||
COPY --from=frontend-builder /app/dist /usr/share/nginx/html
|
||||
RUN chown -R www-data:www-data /usr/share/nginx/html
|
||||
|
||||
COPY --chown=node:node --from=frontend-builder /app/dist /app/html
|
||||
# Setup backend
|
||||
WORKDIR /app
|
||||
COPY package*.json ./
|
||||
RUN npm ci --only=production --ignore-scripts --force && \
|
||||
npm cache clean --force && \
|
||||
rm -rf /tmp/*
|
||||
COPY --from=bcrypt-builder /app/node_modules/bcrypt /app/node_modules/bcrypt
|
||||
COPY --from=backend-builder /app/src/backend ./src/backend
|
||||
RUN chown -R node:node /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
|
||||
# Plugins pinned in docker/bundled-plugins.json, resolved as dist/plugins by
|
||||
# getBundledPluginsDir().
|
||||
COPY --chown=node:node --from=backend-builder /app/dist/plugins ./dist/plugins
|
||||
# Target of node_modules/@termix-ssh/plugin-sdk, which core and the plugins import.
|
||||
COPY --chown=node:node --from=backend-builder /app/packages/plugin-sdk/package.json ./packages/plugin-sdk/package.json
|
||||
COPY --chown=node:node --from=backend-builder /app/packages/plugin-sdk/dist ./packages/plugin-sdk/dist
|
||||
# Pre-baked OPKSSH binary. The opkssh plugin uses it when its checksum
|
||||
# matches, so an offline install never downloads one.
|
||||
COPY --chown=node:node --from=opkssh-downloader /opkssh /app/opkssh-bundled
|
||||
COPY --chown=node:node package.json ./
|
||||
# Schema for Postgres and MySQL. Unused by the default SQLite deployment, which
|
||||
# builds its tables at startup instead.
|
||||
COPY --chown=node:node drizzle ./drizzle
|
||||
|
||||
VOLUME ["/app/data"]
|
||||
|
||||
EXPOSE ${PORT}
|
||||
|
||||
HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \
|
||||
CMD wget -q -O /dev/null http://localhost:30001/health || exit 1
|
||||
VOLUME ["/data/db"]
|
||||
EXPOSE 8080 8081 8082 27017
|
||||
|
||||
COPY docker/entrypoint.sh /entrypoint.sh
|
||||
RUN chmod +x /entrypoint.sh
|
||||
|
||||
CMD ["/entrypoint.sh"]
|
||||
CMD ["/entrypoint.sh"]
|
||||
@@ -1,251 +0,0 @@
|
||||
{
|
||||
"plugins": [
|
||||
{
|
||||
"id": "acme-ssl",
|
||||
"source": "tmxplug",
|
||||
"url": "https://github.com/Termix-SSH/Plugin-ACME-SSL/releases/download/v1.0.0/acme-ssl-1.0.0.tmxplug",
|
||||
"sha256": "1725735a058065b211436b166c0ef7d4ca6e74438102764664381160a2b305d3"
|
||||
},
|
||||
{
|
||||
"id": "ai",
|
||||
"source": "tmxplug",
|
||||
"url": "https://github.com/Termix-SSH/Plugin-AI/releases/download/v1.0.0/ai-1.0.0.tmxplug",
|
||||
"sha256": "ea121658305bed9d28e046e096fc458976258d7cb77387e1b8ac82ccb9a001cb"
|
||||
},
|
||||
{
|
||||
"id": "alerts",
|
||||
"source": "tmxplug",
|
||||
"url": "https://github.com/Termix-SSH/Plugin-Alerts/releases/download/v1.0.0/alerts-1.0.0.tmxplug",
|
||||
"sha256": "93274529eb3445db9e1dddc630b7608b15250eb179bb7919a43c3e6707fa20b5",
|
||||
"onboarding": {
|
||||
"recommended": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "automations",
|
||||
"source": "tmxplug",
|
||||
"url": "https://github.com/Termix-SSH/Plugin-Automations/releases/download/v1.0.0/automations-1.0.0.tmxplug",
|
||||
"sha256": "6cb00cf9464e42dbc46786a6ef74b07d62da39ece9905197584d2934265b9b10"
|
||||
},
|
||||
{
|
||||
"id": "docker",
|
||||
"source": "tmxplug",
|
||||
"url": "https://github.com/Termix-SSH/Plugin-Docker/releases/download/v1.0.0/docker-1.0.0.tmxplug",
|
||||
"sha256": "d1d1dd441b51a97231d5da94e38a12b2d2b25db6da5e2b13b4a4b9486881ed2d",
|
||||
"onboarding": {
|
||||
"recommended": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "file-manager",
|
||||
"source": "tmxplug",
|
||||
"url": "https://github.com/Termix-SSH/Plugin-File-Manager/releases/download/v1.0.0/file-manager-1.0.0.tmxplug",
|
||||
"sha256": "8d60f6299a38fcc69a17ca30abb0e2a168aa880c0cfb50d57f1dd37158d811a5",
|
||||
"onboarding": {
|
||||
"recommended": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "fleets",
|
||||
"source": "tmxplug",
|
||||
"url": "https://github.com/Termix-SSH/Plugin-Fleets/releases/download/v1.0.0/fleets-1.0.0.tmxplug",
|
||||
"sha256": "4a774d4a3685b0ee8da5b73d14c60d40f10b6a3f1c5b31a5dfefb94ba30fb7ad"
|
||||
},
|
||||
{
|
||||
"id": "homepage",
|
||||
"source": "tmxplug",
|
||||
"url": "https://github.com/Termix-SSH/Plugin-Homepage/releases/download/v1.0.0/homepage-1.0.0.tmxplug",
|
||||
"sha256": "403513bc1f96a7c21d39d55c8fd1d4e55fde7b8e6ec63228839bf3243d93e68a"
|
||||
},
|
||||
{
|
||||
"id": "host-metrics",
|
||||
"source": "tmxplug",
|
||||
"url": "https://github.com/Termix-SSH/Plugin-Host-Metrics/releases/download/v1.0.0/host-metrics-1.0.0.tmxplug",
|
||||
"sha256": "1cfc81f724418fd68306e3ac30daa529b03aa065740a866f6fbcaa67edb440ac",
|
||||
"onboarding": {
|
||||
"recommended": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "ldap",
|
||||
"source": "tmxplug",
|
||||
"url": "https://github.com/Termix-SSH/Plugin-LDAP/releases/download/v1.0.0/ldap-1.0.0.tmxplug",
|
||||
"sha256": "2d8cb269242c12522a5195fa44ec14e95ade3b00d7e7be12e9204631518a0f88"
|
||||
},
|
||||
{
|
||||
"id": "network-topology",
|
||||
"source": "tmxplug",
|
||||
"url": "https://github.com/Termix-SSH/Plugin-Network-Topology/releases/download/v1.0.0/network-topology-1.0.0.tmxplug",
|
||||
"sha256": "5c0a585dcffd1cd523e94d45f2eda32800c403a4c832854fec7331b651da7b7d"
|
||||
},
|
||||
{
|
||||
"id": "opkssh",
|
||||
"source": "tmxplug",
|
||||
"url": "https://github.com/Termix-SSH/Plugin-OPKSSH/releases/download/v1.0.0/opkssh-1.0.0.tmxplug",
|
||||
"sha256": "7e8a17aa9053954e937ac2274928e29b821dfd671759e356551b27c13e23c9ad"
|
||||
},
|
||||
{
|
||||
"id": "proxmox",
|
||||
"source": "tmxplug",
|
||||
"url": "https://github.com/Termix-SSH/Plugin-Proxmox/releases/download/v1.0.0/proxmox-1.0.0.tmxplug",
|
||||
"sha256": "cb6149ab69e348e5a0a1939b31943cb64aded3e1ee930b91dc77c46a715990d0"
|
||||
},
|
||||
{
|
||||
"id": "remote-desktop",
|
||||
"source": "tmxplug",
|
||||
"url": "https://github.com/Termix-SSH/Plugin-Remote-Desktop/releases/download/v1.0.0/remote-desktop-1.0.0.tmxplug",
|
||||
"sha256": "5201dc1ce4846ef9f509a4c609698e2b2970e31fbc152bb2fe5c39c72c5c6d39",
|
||||
"onboarding": {
|
||||
"recommended": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "secret-sources",
|
||||
"source": "tmxplug",
|
||||
"url": "https://github.com/Termix-SSH/Plugin-Secret-Sources/releases/download/v1.0.0/secret-sources-1.0.0.tmxplug",
|
||||
"sha256": "b6fbe38cd6d62d0b361c102f13f050ee8a281983dc806e32e8d8feeb416ceb20"
|
||||
},
|
||||
{
|
||||
"id": "serial",
|
||||
"source": "tmxplug",
|
||||
"url": "https://github.com/Termix-SSH/Plugin-Serial/releases/download/v1.0.0/serial-1.0.0.tmxplug",
|
||||
"sha256": "c8c3ac8c916253c928195005773e558ee87555fb47b7b56f3e43c0df0fb852c4",
|
||||
"onboarding": {
|
||||
"recommended": "desktop"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "session-recording",
|
||||
"source": "tmxplug",
|
||||
"url": "https://github.com/Termix-SSH/Plugin-Session-Recording/releases/download/v1.0.0/session-recording-1.0.0.tmxplug",
|
||||
"sha256": "ff0e6948806e0127399d41a6abd0f41fce404e65ba2c9d8044fb6dced401f4bb"
|
||||
},
|
||||
{
|
||||
"id": "session-sharing",
|
||||
"source": "tmxplug",
|
||||
"url": "https://github.com/Termix-SSH/Plugin-Session-Sharing/releases/download/v1.0.0/session-sharing-1.0.0.tmxplug",
|
||||
"sha256": "4d2e363086a8fe79815bf76b4ed359ac82d5926373ab24854028e4dbc5a57ac6"
|
||||
},
|
||||
{
|
||||
"id": "snippets",
|
||||
"source": "tmxplug",
|
||||
"url": "https://github.com/Termix-SSH/Plugin-Snippets/releases/download/v1.0.0/snippets-1.0.0.tmxplug",
|
||||
"sha256": "0239e63df6d33cb38a1212935dae972402b174a7eab8b351084dab45196f1fe5",
|
||||
"onboarding": {
|
||||
"recommended": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "ssh-terminal",
|
||||
"source": "tmxplug",
|
||||
"url": "https://github.com/Termix-SSH/Plugin-SSH-Terminal/releases/download/v1.0.0/ssh-terminal-1.0.0.tmxplug",
|
||||
"sha256": "66d2a4e87a2b5ac5551c74a4fad5808a6ee81d6e8f0a43c1f6456a12d6232714",
|
||||
"onboarding": {
|
||||
"recommended": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "sso",
|
||||
"source": "tmxplug",
|
||||
"url": "https://github.com/Termix-SSH/Plugin-SSO/releases/download/v1.0.0/sso-1.0.0.tmxplug",
|
||||
"sha256": "88d7fcf8eb3b0916d69bcc7349a58d98e37c493bfadc8b90f81b8aa5c845abc5",
|
||||
"onboarding": {
|
||||
"enabledByEnv": ["OIDC_CLIENT_ID"]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "step-ca",
|
||||
"source": "tmxplug",
|
||||
"url": "https://github.com/Termix-SSH/Plugin-Step-CA/releases/download/v1.0.0/step-ca-1.0.0.tmxplug",
|
||||
"sha256": "997af2068f88c017c76a057683ac5e367566b5b8bc0961fc1e29c32b702a9059"
|
||||
},
|
||||
{
|
||||
"id": "tailscale",
|
||||
"source": "tmxplug",
|
||||
"url": "https://github.com/Termix-SSH/Plugin-Tailscale/releases/download/v1.0.0/tailscale-1.0.0.tmxplug",
|
||||
"sha256": "963a84859f8411bcb27e2950d46a7a43b239ace1295ac2abc4a77ecec43806d9"
|
||||
},
|
||||
{
|
||||
"id": "telemetry",
|
||||
"source": "tmxplug",
|
||||
"url": "https://github.com/Termix-SSH/Plugin-Telemetry/releases/download/v1.0.0/telemetry-1.0.0.tmxplug",
|
||||
"sha256": "9f973902320a01eed5fead9b31288face503a790bf68a2826176e48fb663c30c",
|
||||
"onboarding": {
|
||||
"recommended": true,
|
||||
"consent": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "termix-identity",
|
||||
"source": "tmxplug",
|
||||
"url": "https://github.com/Termix-SSH/Plugin-Termix-Identity/releases/download/v1.0.0/termix-identity-1.0.0.tmxplug",
|
||||
"sha256": "00dfe3da65f78d7d085817c93a4e01bfef6931fb70ff5576c76e2f641e337555"
|
||||
},
|
||||
{
|
||||
"id": "tmux-monitor",
|
||||
"source": "tmxplug",
|
||||
"url": "https://github.com/Termix-SSH/Plugin-Tmux-Monitor/releases/download/v1.0.0/tmux-monitor-1.0.0.tmxplug",
|
||||
"sha256": "bbc508410296ca3434b5ba8c40fa5ef87646d104ec6f75da3bf0e22313bbbf18"
|
||||
},
|
||||
{
|
||||
"id": "totp",
|
||||
"source": "tmxplug",
|
||||
"url": "https://github.com/Termix-SSH/Plugin-TOTP/releases/download/v1.0.0/totp-1.0.0.tmxplug",
|
||||
"sha256": "c0b6b43d778dfd47af7bdbca099667bf46539de62936c3291947ac2425c02de9",
|
||||
"onboarding": {
|
||||
"recommended": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "tunnels",
|
||||
"source": "tmxplug",
|
||||
"url": "https://github.com/Termix-SSH/Plugin-Tunnels/releases/download/v1.0.0/tunnels-1.0.0.tmxplug",
|
||||
"sha256": "82df362cfc820437db8c56ebd1e3140d7fcef677d98a5439d7e868486cc21ad4",
|
||||
"onboarding": {
|
||||
"recommended": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "vault",
|
||||
"source": "tmxplug",
|
||||
"url": "https://github.com/Termix-SSH/Plugin-Vault/releases/download/v1.0.0/vault-1.0.0.tmxplug",
|
||||
"sha256": "d84b0ef1a309bb3a89288f488a242dd19df9e46b237df778c2f2a77e77867960"
|
||||
},
|
||||
{
|
||||
"id": "wake-on-lan",
|
||||
"source": "tmxplug",
|
||||
"url": "https://github.com/Termix-SSH/Plugin-Wake-On-LAN/releases/download/v1.0.0/wake-on-lan-1.0.0.tmxplug",
|
||||
"sha256": "e680c22279438a566d1033939e4a3063a0fbbeb7f57b6db3bd6712bed09a4388"
|
||||
},
|
||||
{
|
||||
"id": "warpgate",
|
||||
"source": "tmxplug",
|
||||
"url": "https://github.com/Termix-SSH/Plugin-Warpgate/releases/download/v1.0.0/warpgate-1.0.0.tmxplug",
|
||||
"sha256": "c974be686488905277a52440b248d14370f3f543a7bd53f3485d5b6db4fab40b"
|
||||
},
|
||||
{
|
||||
"id": "web-endpoint",
|
||||
"source": "tmxplug",
|
||||
"url": "https://github.com/Termix-SSH/Plugin-Web-Endpoint/releases/download/v1.0.0/web-endpoint-1.0.0.tmxplug",
|
||||
"sha256": "e93d8535617783bc538d415f25a5acc04e3805417002d68d4ebc4044c8fbed8c"
|
||||
},
|
||||
{
|
||||
"id": "webauthn",
|
||||
"source": "tmxplug",
|
||||
"url": "https://github.com/Termix-SSH/Plugin-WebAuthn/releases/download/v1.0.0/webauthn-1.0.0.tmxplug",
|
||||
"sha256": "fba89362c503813a12a7b73c9aed6994a10a1d010db8e1237a1f901131eb8713",
|
||||
"onboarding": {
|
||||
"recommended": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "workspaces",
|
||||
"source": "tmxplug",
|
||||
"url": "https://github.com/Termix-SSH/Plugin-Workspaces/releases/download/v1.0.0/workspaces-1.0.0.tmxplug",
|
||||
"sha256": "31d4d2ba02b59f2c2189c0400eb22d07aa8ba72728cd73a4512995581cf3afcd",
|
||||
"onboarding": {
|
||||
"recommended": true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,42 +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_TUNNEL_HOST: "termix-dev"
|
||||
GUACD_RECORDING_PATH: "/termix-data/session_recordings/guacamole"
|
||||
GUACD_DRIVE_PATH: "/termix-data/rdp-drive"
|
||||
# REDIS_URL: "redis://redis:6379"
|
||||
# TERMIX_REDIS_PREFIX: "termix:collab"
|
||||
# TERMIX_STEP_CA_REDIS_PREFIX: "termix:step-ca"
|
||||
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,55 +0,0 @@
|
||||
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"
|
||||
GUACD_HOST: "guacd"
|
||||
GUACD_TUNNEL_HOST: "termix"
|
||||
GUACD_RECORDING_PATH: "/termix-data/session_recordings/guacamole"
|
||||
# Where guacd stores files for RDP drive redirection (one folder per
|
||||
# user is created underneath). Must be writable by guacd's user.
|
||||
GUACD_DRIVE_PATH: "/termix-data/rdp-drive"
|
||||
# Multi-instance deployments should point every backend at the same
|
||||
# Redis. Without it, collaboration rooms keep their single-instance
|
||||
# in-memory fallback.
|
||||
# REDIS_URL: "redis://redis:6379"
|
||||
# TERMIX_REDIS_PREFIX: "termix:collab"
|
||||
# TERMIX_STEP_CA_REDIS_PREFIX: "termix:step-ca"
|
||||
# Hardened deployments can require keys from environment variables or
|
||||
# Docker secrets mounted through JWT_SECRET_FILE, DATABASE_KEY_FILE,
|
||||
# ENCRYPTION_KEY_FILE and INTERNAL_AUTH_TOKEN_FILE.
|
||||
# TERMIX_REQUIRE_EXTERNAL_SECRETS: "true"
|
||||
# Trusted reverse-proxy authentication is disabled by default. When
|
||||
# enabled, do not expose this container directly to untrusted clients.
|
||||
# TRUSTED_PROXY_AUTH_ENABLED: "true"
|
||||
# TRUSTED_PROXY_AUTH_TRUSTED_PROXIES: "172.16.0.0/12"
|
||||
# TRUSTED_PROXY_AUTH_ROLE_MAP: '{"operators":["user"]}'
|
||||
# TRUSTED_PROXY_AUTH_USERNAME_HEADER: "x-forwarded-username"
|
||||
# TRUSTED_PROXY_AUTH_ROLE_HEADER: "x-forwarded-role"
|
||||
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
|
||||
+108
-182
@@ -1,198 +1,124 @@
|
||||
#!/bin/sh
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
PUID=${PUID:-1000}
|
||||
PGID=${PGID:-1000}
|
||||
# Create required directories and set permissions
|
||||
mkdir -p /data/db /var/log/mongodb /var/run/mongodb
|
||||
chown -R mongodb:mongodb /data/db /var/log/mongodb /var/run/mongodb
|
||||
chmod 755 /data/db /var/log/mongodb /var/run/mongodb
|
||||
|
||||
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
|
||||
|
||||
DATA_DIR=${DATA_DIR:-/app/data}
|
||||
|
||||
RUNTIME_ENABLE_SSL_SET=${ENABLE_SSL+x}
|
||||
RUNTIME_ENABLE_SSL=${ENABLE_SSL-}
|
||||
RUNTIME_SSL_PORT_SET=${SSL_PORT+x}
|
||||
RUNTIME_SSL_PORT=${SSL_PORT-}
|
||||
RUNTIME_SSL_CERT_PATH_SET=${SSL_CERT_PATH+x}
|
||||
RUNTIME_SSL_CERT_PATH=${SSL_CERT_PATH-}
|
||||
RUNTIME_SSL_KEY_PATH_SET=${SSL_KEY_PATH+x}
|
||||
RUNTIME_SSL_KEY_PATH=${SSL_KEY_PATH-}
|
||||
RUNTIME_SSL_DOMAIN_SET=${SSL_DOMAIN+x}
|
||||
RUNTIME_SSL_DOMAIN=${SSL_DOMAIN-}
|
||||
|
||||
if [ -f "$DATA_DIR/.env" ]; then
|
||||
echo "Loading persisted SSL settings from $DATA_DIR/.env"
|
||||
set -a
|
||||
. "$DATA_DIR/.env"
|
||||
set +a
|
||||
fi
|
||||
|
||||
[ "$RUNTIME_ENABLE_SSL_SET" = "x" ] && ENABLE_SSL=$RUNTIME_ENABLE_SSL
|
||||
[ "$RUNTIME_SSL_PORT_SET" = "x" ] && SSL_PORT=$RUNTIME_SSL_PORT
|
||||
[ "$RUNTIME_SSL_CERT_PATH_SET" = "x" ] && SSL_CERT_PATH=$RUNTIME_SSL_CERT_PATH
|
||||
[ "$RUNTIME_SSL_KEY_PATH_SET" = "x" ] && SSL_KEY_PATH=$RUNTIME_SSL_KEY_PATH
|
||||
[ "$RUNTIME_SSL_DOMAIN_SET" = "x" ] && SSL_DOMAIN=$RUNTIME_SSL_DOMAIN
|
||||
|
||||
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}
|
||||
export TERMIX_SSL_TERMINATED_BY_NGINX=true
|
||||
|
||||
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
|
||||
|
||||
mkdir -p /tmp/nginx
|
||||
envsubst '${PORT} ${SSL_PORT} ${SSL_CERT_PATH} ${SSL_KEY_PATH}' < $NGINX_CONF_SOURCE > /tmp/nginx/nginx.conf
|
||||
|
||||
if [ "$ENABLE_SSL" = "true" ] && [ "$PORT" = "$SSL_PORT" ]; then
|
||||
echo "HTTP and HTTPS use port $SSL_PORT; disabling the HTTP redirect listener"
|
||||
sed -i '/# BEGIN HTTP_REDIRECT_SERVER/,/# END HTTP_REDIRECT_SERVER/d' /tmp/nginx/nginx.conf
|
||||
fi
|
||||
|
||||
mkdir -p /app/data /app/uploads
|
||||
chmod 755 /app/data /app/uploads 2>/dev/null || true
|
||||
|
||||
if [ -w /app/data ]; then
|
||||
echo "Data directory is writable"
|
||||
else
|
||||
echo "WARNING: Data directory is not writable. Plugins that keep files (OPKSSH, recordings) may fail."
|
||||
ls -ld /app/data
|
||||
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..."
|
||||
# Function to check MongoDB version
|
||||
check_mongo_version() {
|
||||
echo "Checking MongoDB version..."
|
||||
if [ -f "/data/db/diagnostic.data/metrics.2" ] || [ -f "/data/db/WiredTiger.wt" ]; then
|
||||
echo "Existing MongoDB data detected, attempting migration..."
|
||||
|
||||
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
|
||||
SUBJECT=$(openssl x509 -in /app/data/ssl/termix.crt -noout -subject 2>/dev/null | sed 's/^subject=//')
|
||||
ISSUER=$(openssl x509 -in /app/data/ssl/termix.crt -noout -issuer 2>/dev/null | sed 's/^issuer=//')
|
||||
# Only replace our own self-signed certificate. A CA-issued one is
|
||||
# kept until it expires, even when nothing renews it.
|
||||
if [ -n "$SUBJECT" ] && [ "$SUBJECT" = "$ISSUER" ]; then
|
||||
echo "Self-signed SSL certificate is expired or expiring soon, regenerating..."
|
||||
rm -f /app/data/ssl/termix.crt /app/data/ssl/termix.key
|
||||
else
|
||||
echo "WARNING: SSL certificate expires within 30 days and was not issued by Termix. Renew it."
|
||||
# Clear any existing mongod lock file
|
||||
rm -f /tmp/mongodb-27017.sock
|
||||
rm -f /data/db/mongod.lock
|
||||
|
||||
# First, start MongoDB 5.0 to set compatibility version
|
||||
echo "Starting MongoDB 5.0 to set compatibility version..."
|
||||
gosu mongodb /usr/bin/mongod --dbpath $MONGODB_DATA_DIR --port 27017 --bind_ip 127.0.0.1 --config /etc/mongod.conf &
|
||||
MONGO_PID=$!
|
||||
|
||||
# Wait for MongoDB 5.0 to start
|
||||
echo "Waiting for MongoDB 5.0 to start..."
|
||||
MAX_TRIES=30
|
||||
COUNT=0
|
||||
while ! gosu mongodb mongo --quiet --eval "db.version()" > /dev/null 2>&1; do
|
||||
sleep 2
|
||||
COUNT=$((COUNT + 1))
|
||||
if [ $COUNT -ge $MAX_TRIES ]; then
|
||||
echo "Failed to start MongoDB 5.0 after $MAX_TRIES attempts"
|
||||
kill -9 $MONGO_PID 2>/dev/null || true
|
||||
return 1
|
||||
fi
|
||||
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
|
||||
done
|
||||
|
||||
echo "SSL certificates generated successfully for domain: $DOMAIN"
|
||||
# Set compatibility version to 4.4
|
||||
echo "Setting feature compatibility version to 4.4..."
|
||||
if ! gosu mongodb mongo --quiet --eval 'db.adminCommand({setFeatureCompatibilityVersion: "4.4"})'; then
|
||||
echo "Failed to set feature compatibility version"
|
||||
kill -9 $MONGO_PID 2>/dev/null || true
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Shutdown MongoDB 5.0 cleanly
|
||||
echo "Shutting down MongoDB 5.0..."
|
||||
gosu mongodb mongo --quiet --eval "db.adminCommand({shutdown: 1})" || kill $MONGO_PID
|
||||
|
||||
# Wait for process to end
|
||||
while kill -0 $MONGO_PID 2>/dev/null; do
|
||||
sleep 1
|
||||
done
|
||||
|
||||
# Run repair with MongoDB 4.4
|
||||
echo "Running repair with MongoDB 4.4..."
|
||||
gosu mongodb /usr/bin/mongod --dbpath $MONGODB_DATA_DIR --repair
|
||||
|
||||
return 0
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
# Try migration up to 3 times
|
||||
MAX_MIGRATION_ATTEMPTS=3
|
||||
MIGRATION_ATTEMPT=1
|
||||
|
||||
while [ $MIGRATION_ATTEMPT -le $MAX_MIGRATION_ATTEMPTS ]; do
|
||||
echo "Migration attempt $MIGRATION_ATTEMPT of $MAX_MIGRATION_ATTEMPTS"
|
||||
if check_mongo_version; then
|
||||
break
|
||||
fi
|
||||
MIGRATION_ATTEMPT=$((MIGRATION_ATTEMPT + 1))
|
||||
if [ $MIGRATION_ATTEMPT -le $MAX_MIGRATION_ATTEMPTS ]; then
|
||||
echo "Migration failed, waiting before retry..."
|
||||
sleep 5
|
||||
fi
|
||||
done
|
||||
|
||||
if [ $MIGRATION_ATTEMPT -gt $MAX_MIGRATION_ATTEMPTS ]; then
|
||||
echo "Migration failed after $MAX_MIGRATION_ATTEMPTS attempts"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Start MongoDB 4.4 normally
|
||||
echo "Starting MongoDB 4.4..."
|
||||
gosu mongodb /usr/bin/mongod --dbpath $MONGODB_DATA_DIR --logpath $MONGODB_LOG_DIR/mongodb.log --bind_ip 0.0.0.0 &
|
||||
MONGO_PID=$!
|
||||
|
||||
# Wait for MongoDB to be ready
|
||||
echo "Waiting for MongoDB to start..."
|
||||
MAX_TRIES=30
|
||||
COUNT=0
|
||||
while ! gosu mongodb mongo --quiet --eval "db.version()" > /dev/null 2>&1; do
|
||||
sleep 2
|
||||
COUNT=$((COUNT + 1))
|
||||
if [ $COUNT -ge $MAX_TRIES ]; then
|
||||
echo "Failed to start MongoDB. Checking logs:"
|
||||
cat $MONGODB_LOG_DIR/mongodb.log
|
||||
exit 1
|
||||
fi
|
||||
echo "Waiting for MongoDB... (attempt $COUNT/$MAX_TRIES)"
|
||||
done
|
||||
echo "MongoDB started successfully"
|
||||
|
||||
# Start nginx
|
||||
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%/}"
|
||||
case "$CLEAN_BASE_PATH" in
|
||||
/*) ;;
|
||||
*) echo "BASE_PATH must start with /" >&2; exit 1 ;;
|
||||
esac
|
||||
case "$CLEAN_BASE_PATH" in
|
||||
*[!A-Za-z0-9_./~-]*) echo "BASE_PATH contains unsupported characters" >&2; exit 1 ;;
|
||||
esac
|
||||
find /app/html -name "index.html" -exec sed -i "s|name=\"termix-base-path\" content=\"\"|name=\"termix-base-path\" content=\"$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
|
||||
|
||||
# Start backend services
|
||||
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
|
||||
else
|
||||
echo "Warning: package.json not found"
|
||||
fi
|
||||
# Start SSH service
|
||||
su -s /bin/bash node -c "node src/backend/ssh.cjs" &
|
||||
|
||||
exec node dist/backend/backend/starter.js
|
||||
# Start database service
|
||||
su -s /bin/bash node -c "node src/backend/database.cjs" &
|
||||
|
||||
echo "All services started"
|
||||
|
||||
# Keep container running and show logs
|
||||
tail -f $MONGODB_LOG_DIR/mongodb.log
|
||||
@@ -1,469 +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;
|
||||
|
||||
server_tokens off;
|
||||
|
||||
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;
|
||||
|
||||
# Static assets only. API responses arrive already gzipped from the node
|
||||
# backend, and gzip_proxied would otherwise have nginx decompress and
|
||||
# recompress them for nothing.
|
||||
gzip on;
|
||||
gzip_vary on;
|
||||
gzip_min_length 2048;
|
||||
gzip_comp_level 5;
|
||||
gzip_types
|
||||
text/plain
|
||||
text/css
|
||||
text/javascript
|
||||
application/javascript
|
||||
application/json
|
||||
application/wasm
|
||||
image/svg+xml;
|
||||
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;
|
||||
|
||||
# BEGIN HTTP_REDIRECT_SERVER
|
||||
server {
|
||||
listen ${PORT};
|
||||
server_name _;
|
||||
|
||||
# ACME http-01 checks arrive on plain HTTP and must not be redirected.
|
||||
location ^~ /.well-known/acme-challenge/ {
|
||||
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;
|
||||
}
|
||||
|
||||
location / {
|
||||
return 301 https://$host:${SSL_PORT}$request_uri;
|
||||
}
|
||||
}
|
||||
# END HTTP_REDIRECT_SERVER
|
||||
|
||||
server {
|
||||
listen ${SSL_PORT} ssl;
|
||||
server_name _;
|
||||
client_max_body_size 50m;
|
||||
|
||||
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;
|
||||
|
||||
location ^~ /.well-known/acme-challenge/ {
|
||||
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;
|
||||
}
|
||||
|
||||
location = /sw.js {
|
||||
root /app/html;
|
||||
expires off;
|
||||
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
||||
add_header X-Content-Type-Options nosniff always;
|
||||
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 Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
||||
add_header X-Content-Type-Options nosniff always;
|
||||
add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0" always;
|
||||
try_files $uri =404;
|
||||
}
|
||||
|
||||
location ^~ /assets/ {
|
||||
root /app/html;
|
||||
expires 1y;
|
||||
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
||||
add_header X-Content-Type-Options nosniff always;
|
||||
add_header Cache-Control "public, max-age=31536000, immutable" always;
|
||||
try_files $uri =404;
|
||||
}
|
||||
|
||||
location ^~ /fonts/ {
|
||||
root /app/html;
|
||||
expires 1y;
|
||||
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
||||
add_header X-Content-Type-Options nosniff always;
|
||||
add_header Cache-Control "public, max-age=31536000, immutable" always;
|
||||
try_files $uri =404;
|
||||
}
|
||||
|
||||
location ^~ /icons/ {
|
||||
root /app/html;
|
||||
expires 30d;
|
||||
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
||||
add_header X-Content-Type-Options nosniff always;
|
||||
add_header Cache-Control "public, max-age=2592000" always;
|
||||
try_files $uri =404;
|
||||
}
|
||||
|
||||
location ~* ^/[^/]+\.(js|css|png|jpe?g|gif|ico|svg|webp|woff2?|ttf|eot)$ {
|
||||
root /app/html;
|
||||
expires 30d;
|
||||
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
||||
add_header X-Content-Type-Options nosniff always;
|
||||
add_header Cache-Control "public, max-age=2592000" always;
|
||||
try_files $uri =404;
|
||||
}
|
||||
|
||||
location ~* \.map$ {
|
||||
access_log off;
|
||||
log_not_found off;
|
||||
return 404;
|
||||
}
|
||||
|
||||
location / {
|
||||
root /app/html;
|
||||
index index.html index.htm;
|
||||
expires off;
|
||||
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'wasm-unsafe-eval' 'sha256-0FPou4vGHwupDie6Xais6VntpJ4yaK9E6TyhXLwZe8o='; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob: http: https:; font-src 'self' data:; connect-src 'self' http: https: ws: wss:; media-src 'self' data: blob: http: https:; worker-src 'self' blob:; frame-src http: https:; object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'none'" always;
|
||||
add_header X-Frame-Options "DENY" always;
|
||||
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
|
||||
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
|
||||
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
||||
add_header X-Content-Type-Options nosniff always;
|
||||
add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0" always;
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
|
||||
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 ~ ^/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 ~ ^/ssh-auth(/.*)?$ {
|
||||
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 ~ ^/sync(/.*)?$ {
|
||||
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 ~ ^/plugins(/.*)?$ {
|
||||
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;
|
||||
}
|
||||
|
||||
# Plugin frontend bundles, stylesheets and locales. Public like
|
||||
# /assets; the backend picks the cache policy from the ?v= query.
|
||||
location ^~ /plugin-assets/ {
|
||||
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;
|
||||
}
|
||||
|
||||
# Every plugin's HTTP routes. One block, no per-plugin entries: a
|
||||
# plugin serves at /plugin-api/<id>/ on the main backend and never
|
||||
# gets a port or a block of its own. Buffering is off so SSE streams
|
||||
# (AI, Proxmox discovery) reach the browser as they are produced, and
|
||||
# request buffering is off so large uploads stream through.
|
||||
location ^~ /plugin-api/ {
|
||||
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_read_timeout 86400s;
|
||||
proxy_send_timeout 86400s;
|
||||
proxy_connect_timeout 10s;
|
||||
|
||||
proxy_buffering off;
|
||||
proxy_request_buffering off;
|
||||
|
||||
client_max_body_size 0;
|
||||
}
|
||||
|
||||
# Every plugin's WebSockets: terminal, Guacamole display, Docker
|
||||
# console. Served at /plugin-ws/<id>/<path> from the same backend.
|
||||
location ^~ /plugin-ws/ {
|
||||
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_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-Host $proxy_x_forwarded_host;
|
||||
proxy_set_header X-Forwarded-Port $proxy_x_forwarded_port;
|
||||
proxy_cache_bypass $http_upgrade;
|
||||
|
||||
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 ~ ^/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 ~ ^/host-sidebar(/.*)?$ {
|
||||
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 ~ ^/credential-sidebar(/.*)?$ {
|
||||
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 ~ ^/ui-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 ~ ^/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/ {
|
||||
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;
|
||||
}
|
||||
|
||||
# File manager routes (recent/pinned/shortcuts, SFTP, transfers) moved
|
||||
# to the file-manager plugin, served under /plugin-api/file-manager/.
|
||||
# Session logs moved to the session-recording plugin, served under
|
||||
# /plugin-api/session-recording/.
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
# Service links and the homepage widget canvas moved to the homepage
|
||||
# plugin, served under /plugin-api/homepage/.
|
||||
|
||||
location /dashboard/ {
|
||||
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;
|
||||
}
|
||||
|
||||
error_page 500 502 503 504 /50x.html;
|
||||
location = /50x.html {
|
||||
root /app/html;
|
||||
internal;
|
||||
}
|
||||
}
|
||||
}
|
||||
+29
-411
@@ -1,438 +1,56 @@
|
||||
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;
|
||||
include mime.types;
|
||||
default_type application/octet-stream;
|
||||
|
||||
server_tokens off;
|
||||
|
||||
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;
|
||||
|
||||
# Static assets only. API responses arrive already gzipped from the node
|
||||
# backend, and gzip_proxied would otherwise have nginx decompress and
|
||||
# recompress them for nothing.
|
||||
gzip on;
|
||||
gzip_vary on;
|
||||
gzip_min_length 2048;
|
||||
gzip_comp_level 5;
|
||||
gzip_types
|
||||
text/plain
|
||||
text/css
|
||||
text/javascript
|
||||
application/javascript
|
||||
application/json
|
||||
application/wasm
|
||||
image/svg+xml;
|
||||
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;
|
||||
sendfile on;
|
||||
keepalive_timeout 65;
|
||||
|
||||
server {
|
||||
listen ${PORT};
|
||||
server_name _;
|
||||
client_max_body_size 50m;
|
||||
|
||||
absolute_redirect off;
|
||||
|
||||
add_header X-Content-Type-Options nosniff always;
|
||||
|
||||
location ^~ /.well-known/acme-challenge/ {
|
||||
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;
|
||||
}
|
||||
|
||||
location = /sw.js {
|
||||
root /app/html;
|
||||
expires off;
|
||||
add_header X-Content-Type-Options nosniff always;
|
||||
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 X-Content-Type-Options nosniff always;
|
||||
add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0" always;
|
||||
try_files $uri =404;
|
||||
}
|
||||
|
||||
location ^~ /assets/ {
|
||||
root /app/html;
|
||||
expires 1y;
|
||||
add_header X-Content-Type-Options nosniff always;
|
||||
add_header Cache-Control "public, max-age=31536000, immutable" always;
|
||||
try_files $uri =404;
|
||||
}
|
||||
|
||||
location ^~ /fonts/ {
|
||||
root /app/html;
|
||||
expires 1y;
|
||||
add_header X-Content-Type-Options nosniff always;
|
||||
add_header Cache-Control "public, max-age=31536000, immutable" always;
|
||||
try_files $uri =404;
|
||||
}
|
||||
|
||||
location ^~ /icons/ {
|
||||
root /app/html;
|
||||
expires 30d;
|
||||
add_header X-Content-Type-Options nosniff always;
|
||||
add_header Cache-Control "public, max-age=2592000" always;
|
||||
try_files $uri =404;
|
||||
}
|
||||
|
||||
location ~* ^/[^/]+\.(js|css|png|jpe?g|gif|ico|svg|webp|woff2?|ttf|eot)$ {
|
||||
root /app/html;
|
||||
expires 30d;
|
||||
add_header X-Content-Type-Options nosniff always;
|
||||
add_header Cache-Control "public, max-age=2592000" always;
|
||||
try_files $uri =404;
|
||||
}
|
||||
|
||||
location ~* \.map$ {
|
||||
access_log off;
|
||||
log_not_found off;
|
||||
return 404;
|
||||
}
|
||||
listen 8080;
|
||||
server_name localhost;
|
||||
|
||||
# Serve the React app
|
||||
location / {
|
||||
root /app/html;
|
||||
index index.html index.htm;
|
||||
expires off;
|
||||
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'wasm-unsafe-eval' 'sha256-0FPou4vGHwupDie6Xais6VntpJ4yaK9E6TyhXLwZe8o='; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob: http: https:; font-src 'self' data:; connect-src 'self' http: https: ws: wss:; media-src 'self' data: blob: http: https:; worker-src 'self' blob:; frame-src http: https:; object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'none'" always;
|
||||
add_header X-Frame-Options "DENY" always;
|
||||
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
|
||||
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
|
||||
add_header X-Content-Type-Options nosniff always;
|
||||
add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0" always;
|
||||
try_files $uri $uri/ /index.html;
|
||||
root /usr/share/nginx/html;
|
||||
index index.html index.htm;
|
||||
}
|
||||
|
||||
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 ~ ^/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 ~ ^/ssh-auth(/.*)?$ {
|
||||
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 ~ ^/sync(/.*)?$ {
|
||||
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 ~ ^/plugins(/.*)?$ {
|
||||
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;
|
||||
}
|
||||
|
||||
# Plugin frontend bundles, stylesheets and locales. Public like
|
||||
# /assets; the backend picks the cache policy from the ?v= query.
|
||||
location ^~ /plugin-assets/ {
|
||||
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;
|
||||
}
|
||||
|
||||
# Every plugin's HTTP routes. One block, no per-plugin entries: a
|
||||
# plugin serves at /plugin-api/<id>/ on the main backend and never
|
||||
# gets a port or a block of its own. Buffering is off so SSE streams
|
||||
# (AI, Proxmox discovery) reach the browser as they are produced, and
|
||||
# request buffering is off so large uploads stream through.
|
||||
location ^~ /plugin-api/ {
|
||||
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_read_timeout 86400s;
|
||||
proxy_send_timeout 86400s;
|
||||
proxy_connect_timeout 10s;
|
||||
|
||||
proxy_buffering off;
|
||||
proxy_request_buffering off;
|
||||
|
||||
client_max_body_size 0;
|
||||
}
|
||||
|
||||
# Every plugin's WebSockets: terminal, Guacamole display, Docker
|
||||
# console. Served at /plugin-ws/<id>/<path> from the same backend.
|
||||
location ^~ /plugin-ws/ {
|
||||
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_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-Host $proxy_x_forwarded_host;
|
||||
proxy_set_header X-Forwarded-Port $proxy_x_forwarded_port;
|
||||
proxy_cache_bypass $http_upgrade;
|
||||
|
||||
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 ~ ^/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 ~ ^/host-sidebar(/.*)?$ {
|
||||
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 ~ ^/credential-sidebar(/.*)?$ {
|
||||
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 ~ ^/ui-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 ~ ^/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 SSH socket requests
|
||||
location /ssh.io/ {
|
||||
proxy_pass http://127.0.0.1:8081;
|
||||
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 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 /host/ {
|
||||
proxy_pass http://127.0.0.1:30001;
|
||||
# Proxy MongoDB socket requests
|
||||
location /database.io/ {
|
||||
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;
|
||||
}
|
||||
|
||||
# File manager routes (recent/pinned/shortcuts, SFTP, transfers) moved
|
||||
# to the file-manager plugin, served under /plugin-api/file-manager/.
|
||||
# Session logs moved to the session-recording plugin, served under
|
||||
# /plugin-api/session-recording/.
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
# Service links and the homepage widget canvas moved to the homepage
|
||||
# plugin, served under /plugin-api/homepage/.
|
||||
|
||||
location /dashboard/ {
|
||||
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;
|
||||
}
|
||||
|
||||
error_page 500 502 503 504 /50x.html;
|
||||
# Error pages
|
||||
error_page 500 502 503 504 /50x.html;
|
||||
location = /50x.html {
|
||||
root /app/html;
|
||||
internal;
|
||||
root /usr/share/nginx/html;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
If you are an AI agent, do not place documentation files here. This is for maintainers only.
|
||||
@@ -1,7 +0,0 @@
|
||||
import { defineConfig } from "drizzle-kit";
|
||||
|
||||
export default defineConfig({
|
||||
dialect: "mysql",
|
||||
schema: "./src/backend/database/db/schema.mysql.ts",
|
||||
out: "./drizzle/mysql",
|
||||
});
|
||||
@@ -1,7 +0,0 @@
|
||||
import { defineConfig } from "drizzle-kit";
|
||||
|
||||
export default defineConfig({
|
||||
dialect: "postgresql",
|
||||
schema: "./src/backend/database/db/schema.pg.ts",
|
||||
out: "./drizzle/postgres",
|
||||
});
|
||||
@@ -1,7 +0,0 @@
|
||||
import { defineConfig } from "drizzle-kit";
|
||||
|
||||
export default defineConfig({
|
||||
dialect: "sqlite",
|
||||
schema: "./src/backend/database/db/schema.ts",
|
||||
out: "./drizzle/sqlite",
|
||||
});
|
||||
@@ -1,890 +0,0 @@
|
||||
CREATE TABLE `alert_firings` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`user_id` varchar(255) NOT NULL,
|
||||
`rule_id` int NOT NULL,
|
||||
`host_id` int NOT NULL,
|
||||
`host_name` text NOT NULL,
|
||||
`fired_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
`resolved_at` text,
|
||||
`value` double,
|
||||
`message` text NOT NULL,
|
||||
`severity` text NOT NULL DEFAULT ('warning'),
|
||||
`acknowledged` boolean NOT NULL DEFAULT false,
|
||||
CONSTRAINT `alert_firings_id` PRIMARY KEY(`id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `alert_rule_channels` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`rule_id` int NOT NULL,
|
||||
`channel_id` int NOT NULL,
|
||||
CONSTRAINT `alert_rule_channels_id` PRIMARY KEY(`id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `alert_rules` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`user_id` varchar(255) NOT NULL,
|
||||
`host_id` int,
|
||||
`name` varchar(255) NOT NULL,
|
||||
`enabled` boolean NOT NULL DEFAULT true,
|
||||
`trigger_type` text NOT NULL,
|
||||
`threshold_value` double,
|
||||
`threshold_duration_seconds` int,
|
||||
`cooldown_minutes` int NOT NULL DEFAULT 15,
|
||||
`created_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
`updated_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
CONSTRAINT `alert_rules_id` PRIMARY KEY(`id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `api_keys` (
|
||||
`id` varchar(255) NOT NULL,
|
||||
`user_id` varchar(255) NOT NULL,
|
||||
`name` varchar(255) NOT NULL,
|
||||
`token_hash` text NOT NULL,
|
||||
`token_prefix` text NOT NULL,
|
||||
`created_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
`expires_at` text,
|
||||
`last_used_at` text,
|
||||
`is_active` boolean NOT NULL DEFAULT true,
|
||||
CONSTRAINT `api_keys_id` PRIMARY KEY(`id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `audit_logs` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`user_id` varchar(255),
|
||||
`username` text NOT NULL,
|
||||
`action` text NOT NULL,
|
||||
`resource_type` text NOT NULL,
|
||||
`resource_id` text,
|
||||
`resource_name` text,
|
||||
`details` text,
|
||||
`ip_address` text,
|
||||
`user_agent` text,
|
||||
`success` boolean NOT NULL,
|
||||
`error_message` text,
|
||||
`timestamp` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
CONSTRAINT `audit_logs_id` PRIMARY KEY(`id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `c2s_tunnel_presets` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`user_id` varchar(255) NOT NULL,
|
||||
`name` varchar(255) NOT NULL,
|
||||
`config` text NOT NULL,
|
||||
`platform` text,
|
||||
`computer_name` text,
|
||||
`created_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
`updated_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
CONSTRAINT `c2s_tunnel_presets_id` PRIMARY KEY(`id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `command_history` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`user_id` varchar(255) NOT NULL,
|
||||
`host_id` int NOT NULL,
|
||||
`command` text NOT NULL,
|
||||
`executed_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
CONSTRAINT `command_history_id` PRIMARY KEY(`id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `dashboard_service_links` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`user_id` varchar(255) NOT NULL,
|
||||
`label` text NOT NULL,
|
||||
`url` text NOT NULL,
|
||||
`order` int NOT NULL DEFAULT 0,
|
||||
`sync_id` varchar(255),
|
||||
`created_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
`updated_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
CONSTRAINT `dashboard_service_links_id` PRIMARY KEY(`id`),
|
||||
CONSTRAINT `dashboard_service_links_sync_id_unique` UNIQUE(`sync_id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `dismissed_alerts` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`user_id` varchar(255) NOT NULL,
|
||||
`alert_id` text NOT NULL,
|
||||
`dismissed_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
CONSTRAINT `dismissed_alerts_id` PRIMARY KEY(`id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `file_manager_pinned` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`user_id` varchar(255) NOT NULL,
|
||||
`host_id` int NOT NULL,
|
||||
`name` varchar(255) NOT NULL,
|
||||
`path` text NOT NULL,
|
||||
`pinned_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
CONSTRAINT `file_manager_pinned_id` PRIMARY KEY(`id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `file_manager_recent` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`user_id` varchar(255) NOT NULL,
|
||||
`host_id` int NOT NULL,
|
||||
`name` varchar(255) NOT NULL,
|
||||
`path` text NOT NULL,
|
||||
`last_opened` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
CONSTRAINT `file_manager_recent_id` PRIMARY KEY(`id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `file_manager_shortcuts` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`user_id` varchar(255) NOT NULL,
|
||||
`host_id` int NOT NULL,
|
||||
`name` varchar(255) NOT NULL,
|
||||
`path` text NOT NULL,
|
||||
`created_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
CONSTRAINT `file_manager_shortcuts_id` PRIMARY KEY(`id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `homepage_items` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`user_id` varchar(255) NOT NULL,
|
||||
`type_id` text NOT NULL,
|
||||
`title` text,
|
||||
`config` text NOT NULL DEFAULT ('{}'),
|
||||
`folder_id` int,
|
||||
`sync_id` varchar(255),
|
||||
`created_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
`updated_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
CONSTRAINT `homepage_items_id` PRIMARY KEY(`id`),
|
||||
CONSTRAINT `homepage_items_sync_id_unique` UNIQUE(`sync_id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `homepage_layouts` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`user_id` varchar(255) NOT NULL,
|
||||
`layout` text NOT NULL DEFAULT ('{}'),
|
||||
`updated_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
CONSTRAINT `homepage_layouts_id` PRIMARY KEY(`id`),
|
||||
CONSTRAINT `homepage_layouts_user_id_unique` UNIQUE(`user_id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `host_access` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`host_id` int NOT NULL,
|
||||
`user_id` varchar(255),
|
||||
`role_id` int,
|
||||
`granted_by` varchar(255) NOT NULL,
|
||||
`permission_level` text NOT NULL DEFAULT ('connect'),
|
||||
`expires_at` text,
|
||||
`created_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
`last_accessed_at` text,
|
||||
`access_count` int NOT NULL DEFAULT 0,
|
||||
CONSTRAINT `host_access_id` PRIMARY KEY(`id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `host_health_checks` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`user_id` varchar(255) NOT NULL,
|
||||
`host_id` int NOT NULL,
|
||||
`checks` text NOT NULL,
|
||||
`interval_seconds` int NOT NULL DEFAULT 300,
|
||||
`created_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
`updated_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
CONSTRAINT `host_health_checks_id` PRIMARY KEY(`id`),
|
||||
CONSTRAINT `idx_host_health_checks_user_host` UNIQUE(`user_id`,`host_id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `host_health_history` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`user_id` varchar(255) NOT NULL,
|
||||
`host_id` int NOT NULL,
|
||||
`check_id` text NOT NULL,
|
||||
`ts` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
`ok` boolean NOT NULL,
|
||||
`latency_ms` int,
|
||||
`detail` text,
|
||||
CONSTRAINT `host_health_history_id` PRIMARY KEY(`id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `host_metrics_history` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`host_id` int NOT NULL,
|
||||
`ts` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
`cpu_percent` double,
|
||||
`mem_percent` double,
|
||||
`disk_percent` double,
|
||||
`net_rx_bytes` int,
|
||||
`net_tx_bytes` int,
|
||||
CONSTRAINT `host_metrics_history_id` PRIMARY KEY(`id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `host_metrics_preferences` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`user_id` varchar(255) NOT NULL,
|
||||
`host_id` int NOT NULL,
|
||||
`layout` text NOT NULL,
|
||||
`created_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
`updated_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
CONSTRAINT `host_metrics_preferences_id` PRIMARY KEY(`id`),
|
||||
CONSTRAINT `idx_host_metrics_prefs_user_host` UNIQUE(`user_id`,`host_id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `ssh_data` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`user_id` varchar(255) NOT NULL,
|
||||
`connection_type` text NOT NULL DEFAULT ('ssh'),
|
||||
`name` varchar(255),
|
||||
`ip` text NOT NULL,
|
||||
`port` int NOT NULL,
|
||||
`username` text NOT NULL,
|
||||
`folder` text,
|
||||
`tags` text,
|
||||
`pin` boolean NOT NULL DEFAULT false,
|
||||
`auth_type` text NOT NULL,
|
||||
`use_warpgate` boolean NOT NULL DEFAULT false,
|
||||
`share_ssh_auth` boolean NOT NULL DEFAULT false,
|
||||
`force_keyboard_interactive` text,
|
||||
`password` text,
|
||||
`key` text,
|
||||
`key_password` text,
|
||||
`key_type` text,
|
||||
`sudo_password` text,
|
||||
`autostart_password` text,
|
||||
`autostart_key` text,
|
||||
`autostart_key_password` text,
|
||||
`credential_id` int,
|
||||
`override_credential_username` boolean,
|
||||
`vault_profile_id` int,
|
||||
`enable_terminal` boolean NOT NULL DEFAULT true,
|
||||
`enable_session_logging` boolean NOT NULL DEFAULT true,
|
||||
`allow_session_sharing` boolean NOT NULL DEFAULT true,
|
||||
`enable_command_history` boolean NOT NULL DEFAULT true,
|
||||
`enable_tunnel` boolean NOT NULL DEFAULT true,
|
||||
`tunnel_connections` text,
|
||||
`jump_hosts` text,
|
||||
`enable_file_manager` boolean NOT NULL DEFAULT true,
|
||||
`scp_legacy` boolean NOT NULL DEFAULT false,
|
||||
`enable_docker` boolean NOT NULL DEFAULT false,
|
||||
`enable_tmux_monitor` boolean NOT NULL DEFAULT false,
|
||||
`show_terminal_in_sidebar` boolean NOT NULL DEFAULT true,
|
||||
`show_file_manager_in_sidebar` boolean NOT NULL DEFAULT false,
|
||||
`show_tunnel_in_sidebar` boolean NOT NULL DEFAULT false,
|
||||
`show_docker_in_sidebar` boolean NOT NULL DEFAULT false,
|
||||
`show_server_stats_in_sidebar` boolean NOT NULL DEFAULT false,
|
||||
`default_path` text,
|
||||
`stats_config` text,
|
||||
`docker_config` text,
|
||||
`enable_proxmox` boolean NOT NULL DEFAULT false,
|
||||
`proxmox_config` text,
|
||||
`terminal_config` text,
|
||||
`quick_actions` text,
|
||||
`notes` text,
|
||||
`enable_ssh` boolean NOT NULL DEFAULT true,
|
||||
`enable_rdp` boolean NOT NULL DEFAULT false,
|
||||
`enable_vnc` boolean NOT NULL DEFAULT false,
|
||||
`enable_telnet` boolean NOT NULL DEFAULT false,
|
||||
`ssh_port` int DEFAULT 22,
|
||||
`rdp_port` int DEFAULT 3389,
|
||||
`vnc_port` int DEFAULT 5900,
|
||||
`telnet_port` int DEFAULT 23,
|
||||
`rdp_credential_id` int,
|
||||
`rdp_user` text,
|
||||
`rdp_password` text,
|
||||
`rdp_domain` text,
|
||||
`rdp_security` text,
|
||||
`rdp_ignore_cert` boolean DEFAULT false,
|
||||
`vnc_credential_id` int,
|
||||
`vnc_password` text,
|
||||
`vnc_user` text,
|
||||
`telnet_user` text,
|
||||
`telnet_password` text,
|
||||
`telnet_credential_id` int,
|
||||
`rdp_auth_type` text,
|
||||
`vnc_auth_type` text,
|
||||
`telnet_auth_type` text,
|
||||
`domain` text,
|
||||
`security` text,
|
||||
`ignore_cert` boolean DEFAULT false,
|
||||
`guacamole_config` text,
|
||||
`use_socks5` boolean,
|
||||
`socks5_host` text,
|
||||
`socks5_port` int,
|
||||
`socks5_username` text,
|
||||
`socks5_password` text,
|
||||
`socks5_proxy_chain` text,
|
||||
`connection_origin` text,
|
||||
`mac_address` text,
|
||||
`wol_broadcast_address` text,
|
||||
`port_knock_sequence` text,
|
||||
`host_key_fingerprint` text,
|
||||
`host_key_type` text,
|
||||
`host_key_algorithm` text DEFAULT ('sha256'),
|
||||
`host_key_first_seen` text,
|
||||
`host_key_last_verified` text,
|
||||
`host_key_changed_count` int DEFAULT 0,
|
||||
`sync_id` varchar(255),
|
||||
`created_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
`updated_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
CONSTRAINT `ssh_data_id` PRIMARY KEY(`id`),
|
||||
CONSTRAINT `ssh_data_sync_id_unique` UNIQUE(`sync_id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `network_topology` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`user_id` varchar(255) NOT NULL,
|
||||
`topology` text,
|
||||
`created_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
`updated_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
CONSTRAINT `network_topology_id` PRIMARY KEY(`id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `notification_channels` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`user_id` varchar(255) NOT NULL,
|
||||
`name` varchar(255) NOT NULL,
|
||||
`type` text NOT NULL,
|
||||
`config` text NOT NULL,
|
||||
`enabled` boolean NOT NULL DEFAULT true,
|
||||
`created_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
CONSTRAINT `notification_channels_id` PRIMARY KEY(`id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `opkssh_tokens` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`user_id` varchar(255) NOT NULL,
|
||||
`host_id` int NOT NULL,
|
||||
`ssh_cert` text NOT NULL,
|
||||
`private_key` text NOT NULL,
|
||||
`email` text,
|
||||
`sub` text,
|
||||
`issuer` text,
|
||||
`audience` text,
|
||||
`created_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
`expires_at` text NOT NULL,
|
||||
`last_used` text,
|
||||
CONSTRAINT `opkssh_tokens_id` PRIMARY KEY(`id`),
|
||||
CONSTRAINT `idx_opkssh_tokens_user_host` UNIQUE(`user_id`,`host_id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `recent_activity` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`user_id` varchar(255) NOT NULL,
|
||||
`type` text NOT NULL,
|
||||
`host_id` int NOT NULL,
|
||||
`host_name` text,
|
||||
`timestamp` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
CONSTRAINT `recent_activity_id` PRIMARY KEY(`id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `roles` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`name` varchar(255) NOT NULL,
|
||||
`display_name` text NOT NULL,
|
||||
`description` text,
|
||||
`is_system` boolean NOT NULL DEFAULT false,
|
||||
`permissions` text,
|
||||
`created_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
`updated_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
CONSTRAINT `roles_id` PRIMARY KEY(`id`),
|
||||
CONSTRAINT `roles_name_unique` UNIQUE(`name`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `session_recordings` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`host_id` int NOT NULL,
|
||||
`user_id` varchar(255),
|
||||
`username` text,
|
||||
`access_id` int,
|
||||
`started_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
`ended_at` text,
|
||||
`duration` int,
|
||||
`commands` text,
|
||||
`dangerous_actions` text,
|
||||
`recording_path` text,
|
||||
`protocol` varchar(255) NOT NULL DEFAULT 'ssh',
|
||||
`format` text NOT NULL DEFAULT ('text'),
|
||||
`terminated_by_owner` boolean DEFAULT false,
|
||||
`termination_reason` text,
|
||||
CONSTRAINT `session_recordings_id` PRIMARY KEY(`id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `session_share_participants` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`share_id` varchar(255) NOT NULL,
|
||||
`user_id` varchar(255),
|
||||
`guest_label` text,
|
||||
`joined_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
`left_at` text,
|
||||
CONSTRAINT `session_share_participants_id` PRIMARY KEY(`id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `session_shares` (
|
||||
`id` varchar(255) NOT NULL,
|
||||
`host_id` int NOT NULL,
|
||||
`owner_user_id` varchar(255) NOT NULL,
|
||||
`protocol` varchar(255) NOT NULL,
|
||||
`session_id` text NOT NULL,
|
||||
`tab_instance_id` text,
|
||||
`share_type` text NOT NULL,
|
||||
`target_user_id` varchar(255),
|
||||
`link_token` varchar(255),
|
||||
`permission_level` text NOT NULL DEFAULT ('read-only'),
|
||||
`created_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
`expires_at` text NOT NULL,
|
||||
`revoked_at` text,
|
||||
`last_joined_at` text,
|
||||
`join_count` int NOT NULL DEFAULT 0,
|
||||
CONSTRAINT `session_shares_id` PRIMARY KEY(`id`),
|
||||
CONSTRAINT `session_shares_link_token_unique` UNIQUE(`link_token`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `sessions` (
|
||||
`id` varchar(255) NOT NULL,
|
||||
`user_id` varchar(255) NOT NULL,
|
||||
`jwt_token` text NOT NULL,
|
||||
`device_type` text NOT NULL,
|
||||
`device_info` text NOT NULL,
|
||||
`oidc_sub` text,
|
||||
`oidc_sid` text,
|
||||
`sso_provider_id` int,
|
||||
`created_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
`expires_at` text NOT NULL,
|
||||
`last_active_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
CONSTRAINT `sessions_id` PRIMARY KEY(`id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `settings` (
|
||||
`key` varchar(255) NOT NULL,
|
||||
`value` text NOT NULL,
|
||||
CONSTRAINT `settings_key` PRIMARY KEY(`key`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `shared_host_auth_overrides` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`host_id` int NOT NULL,
|
||||
`user_id` varchar(255) NOT NULL,
|
||||
`protocol` varchar(255) NOT NULL DEFAULT 'ssh',
|
||||
`credential_id` int NOT NULL,
|
||||
`created_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
`updated_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
CONSTRAINT `shared_host_auth_overrides_id` PRIMARY KEY(`id`),
|
||||
CONSTRAINT `shared_host_auth_overrides_host_user_protocol_unique` UNIQUE(`host_id`,`user_id`,`protocol`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `shared_host_secrets` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`host_access_id` int NOT NULL,
|
||||
`target_user_id` varchar(255) NOT NULL,
|
||||
`protocol` varchar(255) NOT NULL DEFAULT 'ssh',
|
||||
`source_type` text NOT NULL DEFAULT ('credential'),
|
||||
`original_credential_id` int,
|
||||
`encrypted_username` text,
|
||||
`encrypted_auth_type` text,
|
||||
`encrypted_password` text,
|
||||
`encrypted_key` text,
|
||||
`encrypted_key_password` text,
|
||||
`encrypted_key_type` text,
|
||||
`encrypted_domain` text,
|
||||
`created_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
`updated_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
CONSTRAINT `shared_host_secrets_id` PRIMARY KEY(`id`),
|
||||
CONSTRAINT `idx_shared_host_secrets_scope` UNIQUE(`host_access_id`,`target_user_id`,`protocol`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `snippet_access` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`snippet_id` int NOT NULL,
|
||||
`user_id` varchar(255),
|
||||
`role_id` int,
|
||||
`granted_by` varchar(255) NOT NULL,
|
||||
`permission_level` text NOT NULL DEFAULT ('view'),
|
||||
`expires_at` text,
|
||||
`created_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
CONSTRAINT `snippet_access_id` PRIMARY KEY(`id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `snippet_folders` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`user_id` varchar(255) NOT NULL,
|
||||
`name` varchar(255) NOT NULL,
|
||||
`color` text,
|
||||
`icon` text,
|
||||
`sync_id` varchar(255),
|
||||
`created_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
`updated_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
CONSTRAINT `snippet_folders_id` PRIMARY KEY(`id`),
|
||||
CONSTRAINT `snippet_folders_sync_id_unique` UNIQUE(`sync_id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `snippets` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`user_id` varchar(255) NOT NULL,
|
||||
`name` varchar(255) NOT NULL,
|
||||
`content` text NOT NULL,
|
||||
`description` text,
|
||||
`folder` text,
|
||||
`order` int NOT NULL DEFAULT 0,
|
||||
`sync_id` varchar(255),
|
||||
`created_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
`updated_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
`host_filter` text,
|
||||
CONSTRAINT `snippets_id` PRIMARY KEY(`id`),
|
||||
CONSTRAINT `snippets_sync_id_unique` UNIQUE(`sync_id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `ssh_credential_usage` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`credential_id` int NOT NULL,
|
||||
`host_id` int NOT NULL,
|
||||
`user_id` varchar(255) NOT NULL,
|
||||
`used_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
CONSTRAINT `ssh_credential_usage_id` PRIMARY KEY(`id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `ssh_credentials` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`user_id` varchar(255) NOT NULL,
|
||||
`name` varchar(255) NOT NULL,
|
||||
`description` text,
|
||||
`folder` text,
|
||||
`tags` text,
|
||||
`auth_type` text NOT NULL,
|
||||
`username` text,
|
||||
`password` text,
|
||||
`key` text,
|
||||
`private_key` text,
|
||||
`public_key` text,
|
||||
`key_password` text,
|
||||
`key_type` text,
|
||||
`detected_key_type` text,
|
||||
`cert_public_key` text,
|
||||
`usage_count` int NOT NULL DEFAULT 0,
|
||||
`last_used` text,
|
||||
`sync_id` varchar(255),
|
||||
`created_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
`updated_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
CONSTRAINT `ssh_credentials_id` PRIMARY KEY(`id`),
|
||||
CONSTRAINT `ssh_credentials_sync_id_unique` UNIQUE(`sync_id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `ssh_folders` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`user_id` varchar(255) NOT NULL,
|
||||
`name` varchar(255) NOT NULL,
|
||||
`color` text,
|
||||
`icon` text,
|
||||
`credential_id` int,
|
||||
`sync_id` varchar(255),
|
||||
`created_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
`updated_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
CONSTRAINT `ssh_folders_id` PRIMARY KEY(`id`),
|
||||
CONSTRAINT `ssh_folders_sync_id_unique` UNIQUE(`sync_id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `sso_providers` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`name` varchar(255) NOT NULL,
|
||||
`type` text NOT NULL,
|
||||
`enabled` boolean NOT NULL DEFAULT true,
|
||||
`display_order` int NOT NULL DEFAULT 0,
|
||||
`config` text NOT NULL,
|
||||
`created_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
`updated_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
CONSTRAINT `sso_providers_id` PRIMARY KEY(`id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `sync_tombstones` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`user_id` varchar(255) NOT NULL,
|
||||
`entity_type` text NOT NULL,
|
||||
`sync_id` varchar(255) NOT NULL,
|
||||
`deleted_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
CONSTRAINT `sync_tombstones_id` PRIMARY KEY(`id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `termix_identities` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`user_id` varchar(255) NOT NULL,
|
||||
`handle` varchar(255) NOT NULL,
|
||||
`description` text,
|
||||
`created_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
`updated_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
CONSTRAINT `termix_identities_id` PRIMARY KEY(`id`),
|
||||
CONSTRAINT `termix_identities_user_id_unique` UNIQUE(`user_id`),
|
||||
CONSTRAINT `termix_identities_handle_unique` UNIQUE(`handle`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `termix_identity_ca` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`identity_id` int NOT NULL,
|
||||
`user_id` varchar(255) NOT NULL,
|
||||
`public_key` text NOT NULL,
|
||||
`private_key` text NOT NULL,
|
||||
`validity_days` int NOT NULL DEFAULT 90,
|
||||
`created_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
`updated_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
CONSTRAINT `termix_identity_ca_id` PRIMARY KEY(`id`),
|
||||
CONSTRAINT `termix_identity_ca_identity_id_unique` UNIQUE(`identity_id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `termix_identity_keys` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`identity_id` int NOT NULL,
|
||||
`user_id` varchar(255) NOT NULL,
|
||||
`public_key` text NOT NULL,
|
||||
`key_type` text NOT NULL,
|
||||
`algorithm` text NOT NULL,
|
||||
`label` text,
|
||||
`comment` text,
|
||||
`source` text NOT NULL DEFAULT ('manual'),
|
||||
`credential_id` int,
|
||||
`enabled` boolean NOT NULL DEFAULT true,
|
||||
`created_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
CONSTRAINT `termix_identity_keys_id` PRIMARY KEY(`id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `tmux_session_tags` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`user_id` varchar(255) NOT NULL,
|
||||
`host_id` int NOT NULL,
|
||||
`session_name` text NOT NULL,
|
||||
`tag` text NOT NULL,
|
||||
`created_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
CONSTRAINT `tmux_session_tags_id` PRIMARY KEY(`id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `transfer_recent` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`user_id` varchar(255) NOT NULL,
|
||||
`source_host_id` int NOT NULL,
|
||||
`dest_host_id` int NOT NULL,
|
||||
`dest_path` text NOT NULL,
|
||||
`dest_path_label` text NOT NULL,
|
||||
`last_used` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
CONSTRAINT `transfer_recent_id` PRIMARY KEY(`id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `trusted_devices` (
|
||||
`id` varchar(255) NOT NULL,
|
||||
`user_id` varchar(255) NOT NULL,
|
||||
`device_fingerprint` text NOT NULL,
|
||||
`device_type` text NOT NULL,
|
||||
`device_info` text NOT NULL,
|
||||
`created_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
`expires_at` text NOT NULL,
|
||||
`last_used_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
CONSTRAINT `trusted_devices_id` PRIMARY KEY(`id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `user_open_tabs` (
|
||||
`id` varchar(255) NOT NULL,
|
||||
`user_id` varchar(255) NOT NULL,
|
||||
`tab_type` text NOT NULL,
|
||||
`host_id` int,
|
||||
`label` text NOT NULL,
|
||||
`tab_order` int NOT NULL DEFAULT 0,
|
||||
`backend_session_id` text,
|
||||
`created_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
`updated_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
CONSTRAINT `user_open_tabs_id` PRIMARY KEY(`id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `user_preferences` (
|
||||
`user_id` varchar(255) NOT NULL,
|
||||
`reopen_tabs_on_login` boolean NOT NULL DEFAULT false,
|
||||
`theme` text,
|
||||
`font_size` text,
|
||||
`accent_color` text,
|
||||
`language` text,
|
||||
`storage_mode` text,
|
||||
`command_autocomplete` boolean,
|
||||
`command_palette_enabled` boolean,
|
||||
`show_host_tags` boolean,
|
||||
`host_tray_on_click` boolean,
|
||||
`pin_app_rail` boolean,
|
||||
`expand_app_rail_on_hover` boolean,
|
||||
`folders_collapsed` boolean,
|
||||
`confirm_snippet_execution` boolean,
|
||||
`disable_update_check` boolean,
|
||||
`confirm_tab_close` boolean,
|
||||
`hidden_rail_tabs` text,
|
||||
`compact_host_view` boolean,
|
||||
`status_color_scheme` text,
|
||||
`custom_themes` text,
|
||||
`custom_keybindings` text,
|
||||
`updated_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
CONSTRAINT `user_preferences_user_id` PRIMARY KEY(`user_id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `user_roles` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`user_id` varchar(255) NOT NULL,
|
||||
`role_id` int NOT NULL,
|
||||
`granted_by` varchar(255),
|
||||
`granted_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
CONSTRAINT `user_roles_id` PRIMARY KEY(`id`),
|
||||
CONSTRAINT `idx_user_roles_user_role` UNIQUE(`user_id`,`role_id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `users` (
|
||||
`id` varchar(255) NOT NULL,
|
||||
`username` text NOT NULL,
|
||||
`password_hash` text NOT NULL,
|
||||
`is_admin` boolean NOT NULL DEFAULT false,
|
||||
`is_oidc` boolean NOT NULL DEFAULT false,
|
||||
`oidc_identifier` text,
|
||||
`sso_provider_id` int,
|
||||
`client_id` text,
|
||||
`client_secret` text,
|
||||
`issuer_url` text,
|
||||
`authorization_url` text,
|
||||
`token_url` text,
|
||||
`identifier_path` text,
|
||||
`name_path` text,
|
||||
`scopes` text DEFAULT ('openid email profile'),
|
||||
`totp_secret` text,
|
||||
`totp_enabled` boolean NOT NULL DEFAULT false,
|
||||
`totp_backup_codes` text,
|
||||
`registered_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
`donation_modal_dismissed` boolean NOT NULL DEFAULT false,
|
||||
CONSTRAINT `users_id` PRIMARY KEY(`id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `vault_profiles` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`user_id` varchar(255) NOT NULL,
|
||||
`name` varchar(255) NOT NULL,
|
||||
`description` text,
|
||||
`folder` text,
|
||||
`tags` text,
|
||||
`vault_addr` text NOT NULL,
|
||||
`vault_namespace` text,
|
||||
`oidc_mount` text,
|
||||
`oidc_role` text,
|
||||
`ssh_mount` text,
|
||||
`ssh_role` text NOT NULL,
|
||||
`valid_principals` text,
|
||||
`key_type` text,
|
||||
`shared` boolean NOT NULL DEFAULT false,
|
||||
`sync_id` varchar(255),
|
||||
`created_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
`updated_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
CONSTRAINT `vault_profiles_id` PRIMARY KEY(`id`),
|
||||
CONSTRAINT `vault_profiles_sync_id_unique` UNIQUE(`sync_id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `vault_tokens` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`user_id` varchar(255) NOT NULL,
|
||||
`profile_id` int NOT NULL,
|
||||
`ssh_cert` text NOT NULL,
|
||||
`private_key` text NOT NULL,
|
||||
`created_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
`expires_at` text NOT NULL,
|
||||
`last_used` text,
|
||||
CONSTRAINT `vault_tokens_id` PRIMARY KEY(`id`),
|
||||
CONSTRAINT `idx_vault_tokens_user_profile` UNIQUE(`user_id`,`profile_id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `webauthn_credentials` (
|
||||
`id` varchar(255) NOT NULL,
|
||||
`user_id` varchar(255) NOT NULL,
|
||||
`name` varchar(255) NOT NULL,
|
||||
`credential_id` text NOT NULL,
|
||||
`public_key` text NOT NULL,
|
||||
`counter` int NOT NULL DEFAULT 0,
|
||||
`device_type` text,
|
||||
`backed_up` boolean NOT NULL DEFAULT false,
|
||||
`transports` text,
|
||||
`user_verification` text NOT NULL DEFAULT ('preferred'),
|
||||
`created_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
`last_used_at` text,
|
||||
CONSTRAINT `webauthn_credentials_id` PRIMARY KEY(`id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE `alert_firings` ADD CONSTRAINT `alert_firings_user_id_users_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `alert_firings` ADD CONSTRAINT `alert_firings_rule_id_alert_rules_id_fk` FOREIGN KEY (`rule_id`) REFERENCES `alert_rules`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `alert_rule_channels` ADD CONSTRAINT `alert_rule_channels_rule_id_alert_rules_id_fk` FOREIGN KEY (`rule_id`) REFERENCES `alert_rules`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `alert_rule_channels` ADD CONSTRAINT `alert_rule_channels_channel_id_notification_channels_id_fk` FOREIGN KEY (`channel_id`) REFERENCES `notification_channels`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `alert_rules` ADD CONSTRAINT `alert_rules_user_id_users_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `alert_rules` ADD CONSTRAINT `alert_rules_host_id_ssh_data_id_fk` FOREIGN KEY (`host_id`) REFERENCES `ssh_data`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `api_keys` ADD CONSTRAINT `api_keys_user_id_users_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `audit_logs` ADD CONSTRAINT `audit_logs_user_id_users_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE set null ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `c2s_tunnel_presets` ADD CONSTRAINT `c2s_tunnel_presets_user_id_users_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `command_history` ADD CONSTRAINT `command_history_user_id_users_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `command_history` ADD CONSTRAINT `command_history_host_id_ssh_data_id_fk` FOREIGN KEY (`host_id`) REFERENCES `ssh_data`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `dashboard_service_links` ADD CONSTRAINT `dashboard_service_links_user_id_users_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `dismissed_alerts` ADD CONSTRAINT `dismissed_alerts_user_id_users_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `file_manager_pinned` ADD CONSTRAINT `file_manager_pinned_user_id_users_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `file_manager_pinned` ADD CONSTRAINT `file_manager_pinned_host_id_ssh_data_id_fk` FOREIGN KEY (`host_id`) REFERENCES `ssh_data`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `file_manager_recent` ADD CONSTRAINT `file_manager_recent_user_id_users_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `file_manager_recent` ADD CONSTRAINT `file_manager_recent_host_id_ssh_data_id_fk` FOREIGN KEY (`host_id`) REFERENCES `ssh_data`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `file_manager_shortcuts` ADD CONSTRAINT `file_manager_shortcuts_user_id_users_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `file_manager_shortcuts` ADD CONSTRAINT `file_manager_shortcuts_host_id_ssh_data_id_fk` FOREIGN KEY (`host_id`) REFERENCES `ssh_data`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `homepage_items` ADD CONSTRAINT `homepage_items_user_id_users_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `homepage_layouts` ADD CONSTRAINT `homepage_layouts_user_id_users_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `host_access` ADD CONSTRAINT `host_access_host_id_ssh_data_id_fk` FOREIGN KEY (`host_id`) REFERENCES `ssh_data`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `host_access` ADD CONSTRAINT `host_access_user_id_users_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `host_access` ADD CONSTRAINT `host_access_role_id_roles_id_fk` FOREIGN KEY (`role_id`) REFERENCES `roles`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `host_access` ADD CONSTRAINT `host_access_granted_by_users_id_fk` FOREIGN KEY (`granted_by`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `host_health_checks` ADD CONSTRAINT `host_health_checks_user_id_users_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `host_health_checks` ADD CONSTRAINT `host_health_checks_host_id_ssh_data_id_fk` FOREIGN KEY (`host_id`) REFERENCES `ssh_data`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `host_health_history` ADD CONSTRAINT `host_health_history_user_id_users_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `host_health_history` ADD CONSTRAINT `host_health_history_host_id_ssh_data_id_fk` FOREIGN KEY (`host_id`) REFERENCES `ssh_data`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `host_metrics_history` ADD CONSTRAINT `host_metrics_history_host_id_ssh_data_id_fk` FOREIGN KEY (`host_id`) REFERENCES `ssh_data`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `host_metrics_preferences` ADD CONSTRAINT `host_metrics_preferences_user_id_users_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `host_metrics_preferences` ADD CONSTRAINT `host_metrics_preferences_host_id_ssh_data_id_fk` FOREIGN KEY (`host_id`) REFERENCES `ssh_data`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `ssh_data` ADD CONSTRAINT `ssh_data_user_id_users_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `ssh_data` ADD CONSTRAINT `ssh_data_credential_id_ssh_credentials_id_fk` FOREIGN KEY (`credential_id`) REFERENCES `ssh_credentials`(`id`) ON DELETE set null ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `ssh_data` ADD CONSTRAINT `ssh_data_vault_profile_id_vault_profiles_id_fk` FOREIGN KEY (`vault_profile_id`) REFERENCES `vault_profiles`(`id`) ON DELETE set null ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `ssh_data` ADD CONSTRAINT `ssh_data_rdp_credential_id_ssh_credentials_id_fk` FOREIGN KEY (`rdp_credential_id`) REFERENCES `ssh_credentials`(`id`) ON DELETE set null ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `ssh_data` ADD CONSTRAINT `ssh_data_vnc_credential_id_ssh_credentials_id_fk` FOREIGN KEY (`vnc_credential_id`) REFERENCES `ssh_credentials`(`id`) ON DELETE set null ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `ssh_data` ADD CONSTRAINT `ssh_data_telnet_credential_id_ssh_credentials_id_fk` FOREIGN KEY (`telnet_credential_id`) REFERENCES `ssh_credentials`(`id`) ON DELETE set null ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `network_topology` ADD CONSTRAINT `network_topology_user_id_users_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `notification_channels` ADD CONSTRAINT `notification_channels_user_id_users_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `opkssh_tokens` ADD CONSTRAINT `opkssh_tokens_user_id_users_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `opkssh_tokens` ADD CONSTRAINT `opkssh_tokens_host_id_ssh_data_id_fk` FOREIGN KEY (`host_id`) REFERENCES `ssh_data`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `recent_activity` ADD CONSTRAINT `recent_activity_user_id_users_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `recent_activity` ADD CONSTRAINT `recent_activity_host_id_ssh_data_id_fk` FOREIGN KEY (`host_id`) REFERENCES `ssh_data`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `session_recordings` ADD CONSTRAINT `session_recordings_host_id_ssh_data_id_fk` FOREIGN KEY (`host_id`) REFERENCES `ssh_data`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `session_recordings` ADD CONSTRAINT `session_recordings_user_id_users_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE set null ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `session_recordings` ADD CONSTRAINT `session_recordings_access_id_host_access_id_fk` FOREIGN KEY (`access_id`) REFERENCES `host_access`(`id`) ON DELETE set null ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `session_share_participants` ADD CONSTRAINT `session_share_participants_share_id_session_shares_id_fk` FOREIGN KEY (`share_id`) REFERENCES `session_shares`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `session_share_participants` ADD CONSTRAINT `session_share_participants_user_id_users_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `session_shares` ADD CONSTRAINT `session_shares_host_id_ssh_data_id_fk` FOREIGN KEY (`host_id`) REFERENCES `ssh_data`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `session_shares` ADD CONSTRAINT `session_shares_owner_user_id_users_id_fk` FOREIGN KEY (`owner_user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `session_shares` ADD CONSTRAINT `session_shares_target_user_id_users_id_fk` FOREIGN KEY (`target_user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `sessions` ADD CONSTRAINT `sessions_user_id_users_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `shared_host_auth_overrides` ADD CONSTRAINT `shared_host_auth_overrides_host_id_ssh_data_id_fk` FOREIGN KEY (`host_id`) REFERENCES `ssh_data`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `shared_host_auth_overrides` ADD CONSTRAINT `shared_host_auth_overrides_user_id_users_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `shared_host_auth_overrides` ADD CONSTRAINT `shared_host_auth_overrides_credential_id_ssh_credentials_id_fk` FOREIGN KEY (`credential_id`) REFERENCES `ssh_credentials`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `shared_host_secrets` ADD CONSTRAINT `shared_host_secrets_host_access_id_host_access_id_fk` FOREIGN KEY (`host_access_id`) REFERENCES `host_access`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `shared_host_secrets` ADD CONSTRAINT `shared_host_secrets_target_user_id_users_id_fk` FOREIGN KEY (`target_user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `shared_host_secrets` ADD CONSTRAINT `shared_host_secrets_original_credential_id_ssh_credentials_id_fk` FOREIGN KEY (`original_credential_id`) REFERENCES `ssh_credentials`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `snippet_access` ADD CONSTRAINT `snippet_access_snippet_id_snippets_id_fk` FOREIGN KEY (`snippet_id`) REFERENCES `snippets`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `snippet_access` ADD CONSTRAINT `snippet_access_user_id_users_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `snippet_access` ADD CONSTRAINT `snippet_access_role_id_roles_id_fk` FOREIGN KEY (`role_id`) REFERENCES `roles`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `snippet_access` ADD CONSTRAINT `snippet_access_granted_by_users_id_fk` FOREIGN KEY (`granted_by`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `snippet_folders` ADD CONSTRAINT `snippet_folders_user_id_users_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `snippets` ADD CONSTRAINT `snippets_user_id_users_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `ssh_credential_usage` ADD CONSTRAINT `ssh_credential_usage_credential_id_ssh_credentials_id_fk` FOREIGN KEY (`credential_id`) REFERENCES `ssh_credentials`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `ssh_credential_usage` ADD CONSTRAINT `ssh_credential_usage_host_id_ssh_data_id_fk` FOREIGN KEY (`host_id`) REFERENCES `ssh_data`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `ssh_credential_usage` ADD CONSTRAINT `ssh_credential_usage_user_id_users_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `ssh_credentials` ADD CONSTRAINT `ssh_credentials_user_id_users_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `ssh_folders` ADD CONSTRAINT `ssh_folders_user_id_users_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `ssh_folders` ADD CONSTRAINT `ssh_folders_credential_id_ssh_credentials_id_fk` FOREIGN KEY (`credential_id`) REFERENCES `ssh_credentials`(`id`) ON DELETE set null ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `sync_tombstones` ADD CONSTRAINT `sync_tombstones_user_id_users_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `termix_identities` ADD CONSTRAINT `termix_identities_user_id_users_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `termix_identity_ca` ADD CONSTRAINT `termix_identity_ca_identity_id_termix_identities_id_fk` FOREIGN KEY (`identity_id`) REFERENCES `termix_identities`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `termix_identity_ca` ADD CONSTRAINT `termix_identity_ca_user_id_users_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `termix_identity_keys` ADD CONSTRAINT `termix_identity_keys_identity_id_termix_identities_id_fk` FOREIGN KEY (`identity_id`) REFERENCES `termix_identities`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `termix_identity_keys` ADD CONSTRAINT `termix_identity_keys_user_id_users_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `termix_identity_keys` ADD CONSTRAINT `termix_identity_keys_credential_id_ssh_credentials_id_fk` FOREIGN KEY (`credential_id`) REFERENCES `ssh_credentials`(`id`) ON DELETE set null ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `tmux_session_tags` ADD CONSTRAINT `tmux_session_tags_user_id_users_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `tmux_session_tags` ADD CONSTRAINT `tmux_session_tags_host_id_ssh_data_id_fk` FOREIGN KEY (`host_id`) REFERENCES `ssh_data`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `transfer_recent` ADD CONSTRAINT `transfer_recent_user_id_users_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `transfer_recent` ADD CONSTRAINT `transfer_recent_source_host_id_ssh_data_id_fk` FOREIGN KEY (`source_host_id`) REFERENCES `ssh_data`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `transfer_recent` ADD CONSTRAINT `transfer_recent_dest_host_id_ssh_data_id_fk` FOREIGN KEY (`dest_host_id`) REFERENCES `ssh_data`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `trusted_devices` ADD CONSTRAINT `trusted_devices_user_id_users_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `user_open_tabs` ADD CONSTRAINT `user_open_tabs_user_id_users_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `user_open_tabs` ADD CONSTRAINT `user_open_tabs_host_id_ssh_data_id_fk` FOREIGN KEY (`host_id`) REFERENCES `ssh_data`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `user_preferences` ADD CONSTRAINT `user_preferences_user_id_users_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `user_roles` ADD CONSTRAINT `user_roles_user_id_users_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `user_roles` ADD CONSTRAINT `user_roles_role_id_roles_id_fk` FOREIGN KEY (`role_id`) REFERENCES `roles`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `user_roles` ADD CONSTRAINT `user_roles_granted_by_users_id_fk` FOREIGN KEY (`granted_by`) REFERENCES `users`(`id`) ON DELETE set null ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `vault_profiles` ADD CONSTRAINT `vault_profiles_user_id_users_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `vault_tokens` ADD CONSTRAINT `vault_tokens_user_id_users_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `vault_tokens` ADD CONSTRAINT `vault_tokens_profile_id_vault_profiles_id_fk` FOREIGN KEY (`profile_id`) REFERENCES `vault_profiles`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `webauthn_credentials` ADD CONSTRAINT `webauthn_credentials_user_id_users_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;
|
||||
@@ -1,10 +0,0 @@
|
||||
CREATE TABLE `host_sidebar_preferences` (
|
||||
`user_id` varchar(255) NOT NULL,
|
||||
`data` text NOT NULL,
|
||||
`updated_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
CONSTRAINT `host_sidebar_preferences_user_id` PRIMARY KEY(`user_id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE `ssh_data` ADD `sort_order` int;--> statement-breakpoint
|
||||
ALTER TABLE `ssh_folders` ADD `sort_order` int;--> statement-breakpoint
|
||||
ALTER TABLE `host_sidebar_preferences` ADD CONSTRAINT `host_sidebar_preferences_user_id_users_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;
|
||||
@@ -1,10 +0,0 @@
|
||||
CREATE TABLE `credential_sidebar_preferences` (
|
||||
`user_id` varchar(255) NOT NULL,
|
||||
`data` text NOT NULL,
|
||||
`updated_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
CONSTRAINT `credential_sidebar_preferences_user_id` PRIMARY KEY(`user_id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE `ssh_credentials` ADD `pin` boolean DEFAULT false NOT NULL;--> statement-breakpoint
|
||||
ALTER TABLE `ssh_credentials` ADD `sort_order` int;--> statement-breakpoint
|
||||
ALTER TABLE `credential_sidebar_preferences` ADD CONSTRAINT `credential_sidebar_preferences_user_id_users_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;
|
||||
@@ -1 +0,0 @@
|
||||
ALTER TABLE `snippets` ADD `is_note` boolean DEFAULT false NOT NULL;
|
||||
@@ -1,28 +0,0 @@
|
||||
CREATE TABLE `proxmox_node_history` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`host_id` int NOT NULL,
|
||||
`ts` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
`cpu_percent` double,
|
||||
`mem_percent` double,
|
||||
`disk_percent` double,
|
||||
`net_rx_bytes` int,
|
||||
`net_tx_bytes` int,
|
||||
CONSTRAINT `proxmox_node_history_id` PRIMARY KEY(`id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `proxmox_stats_preferences` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`user_id` varchar(255) NOT NULL,
|
||||
`host_id` int NOT NULL,
|
||||
`layout` text NOT NULL,
|
||||
`created_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
`updated_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
CONSTRAINT `proxmox_stats_preferences_id` PRIMARY KEY(`id`),
|
||||
CONSTRAINT `idx_proxmox_stats_prefs_user_host` UNIQUE(`user_id`,`host_id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE `ssh_data` ADD `enable_proxmox_stats` boolean DEFAULT false NOT NULL;--> statement-breakpoint
|
||||
ALTER TABLE `ssh_data` ADD `proxmox_stats_config` text;--> statement-breakpoint
|
||||
ALTER TABLE `proxmox_node_history` ADD CONSTRAINT `proxmox_node_history_host_id_ssh_data_id_fk` FOREIGN KEY (`host_id`) REFERENCES `ssh_data`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `proxmox_stats_preferences` ADD CONSTRAINT `proxmox_stats_preferences_user_id_users_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `proxmox_stats_preferences` ADD CONSTRAINT `proxmox_stats_preferences_host_id_ssh_data_id_fk` FOREIGN KEY (`host_id`) REFERENCES `ssh_data`(`id`) ON DELETE cascade ON UPDATE no action;
|
||||
@@ -1 +0,0 @@
|
||||
ALTER TABLE `ssh_data` ADD `enable_terminal_toolbar` boolean DEFAULT true NOT NULL;
|
||||
@@ -1,45 +0,0 @@
|
||||
CREATE TABLE `fleet_inventory` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`host_id` int NOT NULL,
|
||||
`user_id` varchar(255) NOT NULL,
|
||||
`os_pretty_name` text,
|
||||
`kernel` text,
|
||||
`architecture` text,
|
||||
`hostname` text,
|
||||
`uptime_seconds` int,
|
||||
`ip` text,
|
||||
`package_manager` text,
|
||||
`collected_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
CONSTRAINT `fleet_inventory_id` PRIMARY KEY(`id`),
|
||||
CONSTRAINT `idx_fleet_inventory_host` UNIQUE(`host_id`,`user_id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `fleet_members` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`fleet_id` int NOT NULL,
|
||||
`host_id` int NOT NULL,
|
||||
`added_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
CONSTRAINT `fleet_members_id` PRIMARY KEY(`id`),
|
||||
CONSTRAINT `idx_fleet_members_fleet_host` UNIQUE(`fleet_id`,`host_id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `fleets` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`user_id` varchar(255) NOT NULL,
|
||||
`name` varchar(255) NOT NULL,
|
||||
`description` text,
|
||||
`color` text,
|
||||
`icon` text,
|
||||
`tag_rules` text,
|
||||
`sync_id` varchar(255),
|
||||
`created_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
`updated_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
CONSTRAINT `fleets_id` PRIMARY KEY(`id`),
|
||||
CONSTRAINT `fleets_sync_id_unique` UNIQUE(`sync_id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE `fleet_inventory` ADD CONSTRAINT `fleet_inventory_host_id_ssh_data_id_fk` FOREIGN KEY (`host_id`) REFERENCES `ssh_data`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `fleet_inventory` ADD CONSTRAINT `fleet_inventory_user_id_users_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `fleet_members` ADD CONSTRAINT `fleet_members_fleet_id_fleets_id_fk` FOREIGN KEY (`fleet_id`) REFERENCES `fleets`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `fleet_members` ADD CONSTRAINT `fleet_members_host_id_ssh_data_id_fk` FOREIGN KEY (`host_id`) REFERENCES `ssh_data`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `fleets` ADD CONSTRAINT `fleets_user_id_users_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;
|
||||
@@ -1,2 +0,0 @@
|
||||
ALTER TABLE `ssh_data` ADD `parent_host_id` int;--> statement-breakpoint
|
||||
ALTER TABLE `ssh_data` ADD CONSTRAINT `ssh_data_parent_host_id_ssh_data_id_fk` FOREIGN KEY (`parent_host_id`) REFERENCES `ssh_data`(`id`) ON DELETE set null ON UPDATE no action;
|
||||
@@ -1,18 +0,0 @@
|
||||
CREATE TABLE `user_workspaces` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`user_id` varchar(255) NOT NULL,
|
||||
`name` varchar(255) NOT NULL,
|
||||
`color` text,
|
||||
`icon` text,
|
||||
`kind` text NOT NULL DEFAULT ('manual'),
|
||||
`is_default` boolean NOT NULL DEFAULT false,
|
||||
`payload` text NOT NULL DEFAULT ('{}'),
|
||||
`sync_id` varchar(255),
|
||||
`created_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
`updated_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
`last_used_at` text,
|
||||
CONSTRAINT `user_workspaces_id` PRIMARY KEY(`id`),
|
||||
CONSTRAINT `user_workspaces_sync_id_unique` UNIQUE(`sync_id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE `user_workspaces` ADD CONSTRAINT `user_workspaces_user_id_users_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;
|
||||
@@ -1,26 +0,0 @@
|
||||
ALTER TABLE `api_keys` MODIFY COLUMN `expires_at` varchar(255);--> statement-breakpoint
|
||||
ALTER TABLE `audit_logs` MODIFY COLUMN `action` varchar(255) NOT NULL;--> statement-breakpoint
|
||||
ALTER TABLE `audit_logs` MODIFY COLUMN `resource_type` varchar(255) NOT NULL;--> statement-breakpoint
|
||||
ALTER TABLE `audit_logs` MODIFY COLUMN `timestamp` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP);--> statement-breakpoint
|
||||
ALTER TABLE `host_access` MODIFY COLUMN `expires_at` varchar(255);--> statement-breakpoint
|
||||
ALTER TABLE `opkssh_tokens` MODIFY COLUMN `expires_at` varchar(255) NOT NULL;--> statement-breakpoint
|
||||
ALTER TABLE `recent_activity` MODIFY COLUMN `timestamp` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP);--> statement-breakpoint
|
||||
ALTER TABLE `session_shares` MODIFY COLUMN `expires_at` varchar(255) NOT NULL;--> statement-breakpoint
|
||||
ALTER TABLE `sessions` MODIFY COLUMN `expires_at` varchar(255) NOT NULL;--> statement-breakpoint
|
||||
ALTER TABLE `snippet_access` MODIFY COLUMN `expires_at` varchar(255);--> statement-breakpoint
|
||||
ALTER TABLE `trusted_devices` MODIFY COLUMN `expires_at` varchar(255) NOT NULL;--> statement-breakpoint
|
||||
ALTER TABLE `vault_tokens` MODIFY COLUMN `expires_at` varchar(255) NOT NULL;--> statement-breakpoint
|
||||
ALTER TABLE `webauthn_credentials` MODIFY COLUMN `credential_id` varchar(255) NOT NULL;--> statement-breakpoint
|
||||
CREATE INDEX `idx_audit_logs_timestamp` ON `audit_logs` (`timestamp`);--> statement-breakpoint
|
||||
CREATE INDEX `idx_audit_logs_user_ts` ON `audit_logs` (`user_id`,`timestamp`);--> statement-breakpoint
|
||||
CREATE INDEX `idx_audit_logs_action_ts` ON `audit_logs` (`action`,`timestamp`);--> statement-breakpoint
|
||||
CREATE INDEX `idx_audit_logs_resource_ts` ON `audit_logs` (`resource_type`,`timestamp`);--> statement-breakpoint
|
||||
CREATE INDEX `idx_host_access_user_id` ON `host_access` (`user_id`);--> statement-breakpoint
|
||||
CREATE INDEX `idx_host_access_role_id` ON `host_access` (`role_id`);--> statement-breakpoint
|
||||
CREATE INDEX `idx_host_access_host_id` ON `host_access` (`host_id`);--> statement-breakpoint
|
||||
CREATE INDEX `idx_host_access_expires_at` ON `host_access` (`expires_at`);--> statement-breakpoint
|
||||
CREATE INDEX `idx_ssh_data_user_id` ON `ssh_data` (`user_id`);--> statement-breakpoint
|
||||
CREATE INDEX `idx_ssh_data_parent_host` ON `ssh_data` (`parent_host_id`);--> statement-breakpoint
|
||||
CREATE INDEX `idx_ssh_data_credential` ON `ssh_data` (`credential_id`);--> statement-breakpoint
|
||||
CREATE INDEX `idx_sessions_user_id` ON `sessions` (`user_id`);--> statement-breakpoint
|
||||
CREATE INDEX `idx_sessions_expires_at` ON `sessions` (`expires_at`);
|
||||
@@ -1,8 +0,0 @@
|
||||
CREATE TABLE `ui_preferences` (
|
||||
`user_id` varchar(255) NOT NULL,
|
||||
`data` text NOT NULL,
|
||||
`updated_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
CONSTRAINT `ui_preferences_user_id` PRIMARY KEY(`user_id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE `ui_preferences` ADD CONSTRAINT `ui_preferences_user_id_users_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;
|
||||
@@ -1,32 +0,0 @@
|
||||
ALTER TABLE `alert_firings` MODIFY COLUMN `fired_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP);--> statement-breakpoint
|
||||
ALTER TABLE `session_recordings` MODIFY COLUMN `started_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP);--> statement-breakpoint
|
||||
ALTER TABLE `session_shares` MODIFY COLUMN `session_id` varchar(255) NOT NULL;--> statement-breakpoint
|
||||
CREATE INDEX `idx_alert_firings_rule` ON `alert_firings` (`rule_id`,`fired_at`);--> statement-breakpoint
|
||||
CREATE INDEX `idx_alert_firings_host` ON `alert_firings` (`host_id`);--> statement-breakpoint
|
||||
CREATE INDEX `idx_api_keys_user_id` ON `api_keys` (`user_id`);--> statement-breakpoint
|
||||
CREATE INDEX `idx_command_history_user_host` ON `command_history` (`user_id`,`host_id`);--> statement-breakpoint
|
||||
CREATE INDEX `idx_dismissed_alerts_user_id` ON `dismissed_alerts` (`user_id`);--> statement-breakpoint
|
||||
CREATE INDEX `idx_file_manager_pinned_user` ON `file_manager_pinned` (`user_id`,`host_id`);--> statement-breakpoint
|
||||
CREATE INDEX `idx_file_manager_recent_user` ON `file_manager_recent` (`user_id`,`host_id`);--> statement-breakpoint
|
||||
CREATE INDEX `idx_file_manager_shortcuts_user` ON `file_manager_shortcuts` (`user_id`,`host_id`);--> statement-breakpoint
|
||||
CREATE INDEX `idx_fleet_inventory_user` ON `fleet_inventory` (`user_id`);--> statement-breakpoint
|
||||
CREATE INDEX `idx_fleet_members_host` ON `fleet_members` (`host_id`);--> statement-breakpoint
|
||||
CREATE INDEX `idx_homepage_items_user_id` ON `homepage_items` (`user_id`);--> statement-breakpoint
|
||||
CREATE INDEX `idx_recent_activity_user_ts` ON `recent_activity` (`user_id`,`timestamp`);--> statement-breakpoint
|
||||
CREATE INDEX `idx_session_recordings_user_started` ON `session_recordings` (`user_id`,`started_at`);--> statement-breakpoint
|
||||
CREATE INDEX `idx_session_recordings_host` ON `session_recordings` (`host_id`);--> statement-breakpoint
|
||||
CREATE INDEX `idx_session_shares_session_id` ON `session_shares` (`session_id`);--> statement-breakpoint
|
||||
CREATE INDEX `idx_session_shares_host_id` ON `session_shares` (`host_id`);--> statement-breakpoint
|
||||
CREATE INDEX `idx_snippet_access_user_id` ON `snippet_access` (`user_id`);--> statement-breakpoint
|
||||
CREATE INDEX `idx_snippet_access_snippet_id` ON `snippet_access` (`snippet_id`);--> statement-breakpoint
|
||||
CREATE INDEX `idx_snippet_access_role_id` ON `snippet_access` (`role_id`);--> statement-breakpoint
|
||||
CREATE INDEX `idx_snippets_user_id` ON `snippets` (`user_id`);--> statement-breakpoint
|
||||
CREATE INDEX `idx_ssh_credential_usage_credential` ON `ssh_credential_usage` (`credential_id`);--> statement-breakpoint
|
||||
CREATE INDEX `idx_ssh_credential_usage_user` ON `ssh_credential_usage` (`user_id`);--> statement-breakpoint
|
||||
CREATE INDEX `idx_ssh_credentials_user_id` ON `ssh_credentials` (`user_id`);--> statement-breakpoint
|
||||
CREATE INDEX `idx_ssh_folders_user_id` ON `ssh_folders` (`user_id`);--> statement-breakpoint
|
||||
CREATE INDEX `idx_transfer_recent_user` ON `transfer_recent` (`user_id`);--> statement-breakpoint
|
||||
CREATE INDEX `idx_trusted_devices_user_id` ON `trusted_devices` (`user_id`);--> statement-breakpoint
|
||||
CREATE INDEX `idx_user_open_tabs_user_id` ON `user_open_tabs` (`user_id`);--> statement-breakpoint
|
||||
CREATE INDEX `idx_user_roles_role_id` ON `user_roles` (`role_id`);--> statement-breakpoint
|
||||
CREATE INDEX `idx_user_workspaces_user_id` ON `user_workspaces` (`user_id`);
|
||||
@@ -1,224 +0,0 @@
|
||||
CREATE TABLE `ai_conversations` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`user_id` varchar(255) NOT NULL,
|
||||
`title` text,
|
||||
`provider_id` int,
|
||||
`model` text,
|
||||
`created_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
`updated_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
CONSTRAINT `ai_conversations_id` PRIMARY KEY(`id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `ai_messages` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`conversation_id` int NOT NULL,
|
||||
`role` text NOT NULL,
|
||||
`content` text NOT NULL DEFAULT (''),
|
||||
`tool_calls` text,
|
||||
`created_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
CONSTRAINT `ai_messages_id` PRIMARY KEY(`id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `ai_proposals` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`conversation_id` int NOT NULL,
|
||||
`user_id` varchar(255) NOT NULL,
|
||||
`kind` text NOT NULL,
|
||||
`summary` text,
|
||||
`payload` text NOT NULL DEFAULT ('{}'),
|
||||
`status` varchar(255) NOT NULL DEFAULT 'pending',
|
||||
`applied_at` text,
|
||||
`result_summary` text,
|
||||
`created_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
CONSTRAINT `ai_proposals_id` PRIMARY KEY(`id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `ai_providers` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`user_id` varchar(255) NOT NULL,
|
||||
`provider_type` text NOT NULL,
|
||||
`label` varchar(255) NOT NULL,
|
||||
`base_url` text,
|
||||
`api_key` text,
|
||||
`api_key_prefix` text,
|
||||
`default_model` text,
|
||||
`enabled` boolean NOT NULL DEFAULT true,
|
||||
`created_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
`updated_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
CONSTRAINT `ai_providers_id` PRIMARY KEY(`id`),
|
||||
CONSTRAINT `idx_ai_providers_user_label` UNIQUE(`user_id`,`label`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `automation_channels` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`automation_id` int NOT NULL,
|
||||
`channel_id` int NOT NULL,
|
||||
CONSTRAINT `automation_channels_id` PRIMARY KEY(`id`),
|
||||
CONSTRAINT `idx_automation_channels_pair` UNIQUE(`automation_id`,`channel_id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `automation_run_steps` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`run_id` int NOT NULL,
|
||||
`step_index` int NOT NULL,
|
||||
`step_id` text NOT NULL,
|
||||
`step_type` text NOT NULL,
|
||||
`status` varchar(255) NOT NULL,
|
||||
`started_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
`finished_at` text,
|
||||
`output` text,
|
||||
`error` text,
|
||||
`truncated` boolean NOT NULL DEFAULT false,
|
||||
CONSTRAINT `automation_run_steps_id` PRIMARY KEY(`id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `automation_runs` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`automation_id` int NOT NULL,
|
||||
`user_id` varchar(255) NOT NULL,
|
||||
`trigger_type` text NOT NULL,
|
||||
`trigger_context` text,
|
||||
`status` varchar(255) NOT NULL,
|
||||
`started_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
`finished_at` text,
|
||||
`duration_ms` int,
|
||||
`error` text,
|
||||
`dry_run` boolean NOT NULL DEFAULT false,
|
||||
`parent_run_id` int,
|
||||
CONSTRAINT `automation_runs_id` PRIMARY KEY(`id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `automation_schedules` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`automation_id` int NOT NULL,
|
||||
`cron` text,
|
||||
`interval_seconds` int,
|
||||
`timezone` text,
|
||||
`next_due_at` varchar(255),
|
||||
`last_tick_at` text,
|
||||
CONSTRAINT `automation_schedules_id` PRIMARY KEY(`id`),
|
||||
CONSTRAINT `idx_automation_schedules_automation` UNIQUE(`automation_id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `automation_trigger_state` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`automation_id` int NOT NULL,
|
||||
`state_key` varchar(255) NOT NULL,
|
||||
`breach_started_at` text,
|
||||
`last_fired_at` text,
|
||||
`last_value` double,
|
||||
`last_observed_state` text,
|
||||
`updated_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
CONSTRAINT `automation_trigger_state_id` PRIMARY KEY(`id`),
|
||||
CONSTRAINT `idx_automation_trigger_state_key` UNIQUE(`automation_id`,`state_key`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `automations` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`user_id` varchar(255) NOT NULL,
|
||||
`name` varchar(255) NOT NULL,
|
||||
`description` text,
|
||||
`enabled` boolean NOT NULL DEFAULT true,
|
||||
`definition` text NOT NULL,
|
||||
`definition_version` int NOT NULL DEFAULT 1,
|
||||
`concurrency_policy` text NOT NULL DEFAULT ('skip'),
|
||||
`max_run_seconds` int NOT NULL DEFAULT 300,
|
||||
`dry_run` boolean NOT NULL DEFAULT false,
|
||||
`last_run_at` text,
|
||||
`last_run_status` text,
|
||||
`created_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
`updated_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
CONSTRAINT `automations_id` PRIMARY KEY(`id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE `alert_rules` MODIFY COLUMN `created_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP);--> statement-breakpoint
|
||||
ALTER TABLE `alert_rules` MODIFY COLUMN `updated_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP);--> statement-breakpoint
|
||||
ALTER TABLE `api_keys` MODIFY COLUMN `created_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP);--> statement-breakpoint
|
||||
ALTER TABLE `c2s_tunnel_presets` MODIFY COLUMN `created_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP);--> statement-breakpoint
|
||||
ALTER TABLE `c2s_tunnel_presets` MODIFY COLUMN `updated_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP);--> statement-breakpoint
|
||||
ALTER TABLE `credential_sidebar_preferences` MODIFY COLUMN `updated_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP);--> statement-breakpoint
|
||||
ALTER TABLE `dashboard_service_links` MODIFY COLUMN `label` varchar(255) NOT NULL;--> statement-breakpoint
|
||||
ALTER TABLE `dashboard_service_links` MODIFY COLUMN `created_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP);--> statement-breakpoint
|
||||
ALTER TABLE `dashboard_service_links` MODIFY COLUMN `updated_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP);--> statement-breakpoint
|
||||
ALTER TABLE `file_manager_shortcuts` MODIFY COLUMN `created_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP);--> statement-breakpoint
|
||||
ALTER TABLE `fleets` MODIFY COLUMN `created_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP);--> statement-breakpoint
|
||||
ALTER TABLE `fleets` MODIFY COLUMN `updated_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP);--> statement-breakpoint
|
||||
ALTER TABLE `homepage_items` MODIFY COLUMN `created_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP);--> statement-breakpoint
|
||||
ALTER TABLE `homepage_items` MODIFY COLUMN `updated_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP);--> statement-breakpoint
|
||||
ALTER TABLE `homepage_layouts` MODIFY COLUMN `updated_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP);--> statement-breakpoint
|
||||
ALTER TABLE `host_access` MODIFY COLUMN `created_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP);--> statement-breakpoint
|
||||
ALTER TABLE `host_health_checks` MODIFY COLUMN `created_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP);--> statement-breakpoint
|
||||
ALTER TABLE `host_health_checks` MODIFY COLUMN `updated_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP);--> statement-breakpoint
|
||||
ALTER TABLE `host_metrics_preferences` MODIFY COLUMN `created_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP);--> statement-breakpoint
|
||||
ALTER TABLE `host_metrics_preferences` MODIFY COLUMN `updated_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP);--> statement-breakpoint
|
||||
ALTER TABLE `host_sidebar_preferences` MODIFY COLUMN `updated_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP);--> statement-breakpoint
|
||||
ALTER TABLE `ssh_data` MODIFY COLUMN `created_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP);--> statement-breakpoint
|
||||
ALTER TABLE `ssh_data` MODIFY COLUMN `updated_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP);--> statement-breakpoint
|
||||
ALTER TABLE `network_topology` MODIFY COLUMN `created_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP);--> statement-breakpoint
|
||||
ALTER TABLE `network_topology` MODIFY COLUMN `updated_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP);--> statement-breakpoint
|
||||
ALTER TABLE `notification_channels` MODIFY COLUMN `created_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP);--> statement-breakpoint
|
||||
ALTER TABLE `opkssh_tokens` MODIFY COLUMN `created_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP);--> statement-breakpoint
|
||||
ALTER TABLE `proxmox_stats_preferences` MODIFY COLUMN `created_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP);--> statement-breakpoint
|
||||
ALTER TABLE `proxmox_stats_preferences` MODIFY COLUMN `updated_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP);--> statement-breakpoint
|
||||
ALTER TABLE `roles` MODIFY COLUMN `created_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP);--> statement-breakpoint
|
||||
ALTER TABLE `roles` MODIFY COLUMN `updated_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP);--> statement-breakpoint
|
||||
ALTER TABLE `session_shares` MODIFY COLUMN `created_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP);--> statement-breakpoint
|
||||
ALTER TABLE `sessions` MODIFY COLUMN `created_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP);--> statement-breakpoint
|
||||
ALTER TABLE `shared_host_auth_overrides` MODIFY COLUMN `created_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP);--> statement-breakpoint
|
||||
ALTER TABLE `shared_host_auth_overrides` MODIFY COLUMN `updated_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP);--> statement-breakpoint
|
||||
ALTER TABLE `shared_host_secrets` MODIFY COLUMN `created_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP);--> statement-breakpoint
|
||||
ALTER TABLE `shared_host_secrets` MODIFY COLUMN `updated_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP);--> statement-breakpoint
|
||||
ALTER TABLE `snippet_access` MODIFY COLUMN `created_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP);--> statement-breakpoint
|
||||
ALTER TABLE `snippet_folders` MODIFY COLUMN `created_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP);--> statement-breakpoint
|
||||
ALTER TABLE `snippet_folders` MODIFY COLUMN `updated_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP);--> statement-breakpoint
|
||||
ALTER TABLE `snippets` MODIFY COLUMN `created_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP);--> statement-breakpoint
|
||||
ALTER TABLE `snippets` MODIFY COLUMN `updated_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP);--> statement-breakpoint
|
||||
ALTER TABLE `ssh_credentials` MODIFY COLUMN `created_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP);--> statement-breakpoint
|
||||
ALTER TABLE `ssh_credentials` MODIFY COLUMN `updated_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP);--> statement-breakpoint
|
||||
ALTER TABLE `ssh_folders` MODIFY COLUMN `created_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP);--> statement-breakpoint
|
||||
ALTER TABLE `ssh_folders` MODIFY COLUMN `updated_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP);--> statement-breakpoint
|
||||
ALTER TABLE `sso_providers` MODIFY COLUMN `created_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP);--> statement-breakpoint
|
||||
ALTER TABLE `sso_providers` MODIFY COLUMN `updated_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP);--> statement-breakpoint
|
||||
ALTER TABLE `termix_identities` MODIFY COLUMN `created_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP);--> statement-breakpoint
|
||||
ALTER TABLE `termix_identities` MODIFY COLUMN `updated_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP);--> statement-breakpoint
|
||||
ALTER TABLE `termix_identity_ca` MODIFY COLUMN `created_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP);--> statement-breakpoint
|
||||
ALTER TABLE `termix_identity_ca` MODIFY COLUMN `updated_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP);--> statement-breakpoint
|
||||
ALTER TABLE `termix_identity_keys` MODIFY COLUMN `label` varchar(255);--> statement-breakpoint
|
||||
ALTER TABLE `termix_identity_keys` MODIFY COLUMN `created_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP);--> statement-breakpoint
|
||||
ALTER TABLE `tmux_session_tags` MODIFY COLUMN `created_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP);--> statement-breakpoint
|
||||
ALTER TABLE `trusted_devices` MODIFY COLUMN `created_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP);--> statement-breakpoint
|
||||
ALTER TABLE `ui_preferences` MODIFY COLUMN `updated_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP);--> statement-breakpoint
|
||||
ALTER TABLE `user_open_tabs` MODIFY COLUMN `label` varchar(255) NOT NULL;--> statement-breakpoint
|
||||
ALTER TABLE `user_open_tabs` MODIFY COLUMN `created_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP);--> statement-breakpoint
|
||||
ALTER TABLE `user_open_tabs` MODIFY COLUMN `updated_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP);--> statement-breakpoint
|
||||
ALTER TABLE `user_preferences` MODIFY COLUMN `updated_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP);--> statement-breakpoint
|
||||
ALTER TABLE `user_workspaces` MODIFY COLUMN `created_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP);--> statement-breakpoint
|
||||
ALTER TABLE `user_workspaces` MODIFY COLUMN `updated_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP);--> statement-breakpoint
|
||||
ALTER TABLE `vault_profiles` MODIFY COLUMN `created_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP);--> statement-breakpoint
|
||||
ALTER TABLE `vault_profiles` MODIFY COLUMN `updated_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP);--> statement-breakpoint
|
||||
ALTER TABLE `vault_tokens` MODIFY COLUMN `created_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP);--> statement-breakpoint
|
||||
ALTER TABLE `webauthn_credentials` MODIFY COLUMN `created_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP);--> statement-breakpoint
|
||||
ALTER TABLE `user_preferences` ADD `ai_assistant_enabled` boolean;--> statement-breakpoint
|
||||
ALTER TABLE `user_preferences` ADD `ai_read_only_commands` boolean;--> statement-breakpoint
|
||||
ALTER TABLE `ai_conversations` ADD CONSTRAINT `ai_conversations_user_id_users_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `ai_messages` ADD CONSTRAINT `ai_messages_conversation_id_ai_conversations_id_fk` FOREIGN KEY (`conversation_id`) REFERENCES `ai_conversations`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `ai_proposals` ADD CONSTRAINT `ai_proposals_conversation_id_ai_conversations_id_fk` FOREIGN KEY (`conversation_id`) REFERENCES `ai_conversations`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `ai_proposals` ADD CONSTRAINT `ai_proposals_user_id_users_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `ai_providers` ADD CONSTRAINT `ai_providers_user_id_users_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `automation_channels` ADD CONSTRAINT `automation_channels_automation_id_automations_id_fk` FOREIGN KEY (`automation_id`) REFERENCES `automations`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `automation_channels` ADD CONSTRAINT `automation_channels_channel_id_notification_channels_id_fk` FOREIGN KEY (`channel_id`) REFERENCES `notification_channels`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `automation_run_steps` ADD CONSTRAINT `automation_run_steps_run_id_automation_runs_id_fk` FOREIGN KEY (`run_id`) REFERENCES `automation_runs`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `automation_runs` ADD CONSTRAINT `automation_runs_automation_id_automations_id_fk` FOREIGN KEY (`automation_id`) REFERENCES `automations`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `automation_runs` ADD CONSTRAINT `automation_runs_user_id_users_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `automation_schedules` ADD CONSTRAINT `automation_schedules_automation_id_automations_id_fk` FOREIGN KEY (`automation_id`) REFERENCES `automations`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `automation_trigger_state` ADD CONSTRAINT `automation_trigger_state_automation_id_automations_id_fk` FOREIGN KEY (`automation_id`) REFERENCES `automations`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `automations` ADD CONSTRAINT `automations_user_id_users_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
CREATE INDEX `idx_ai_conversations_user` ON `ai_conversations` (`user_id`,`updated_at`);--> statement-breakpoint
|
||||
CREATE INDEX `idx_ai_messages_conversation` ON `ai_messages` (`conversation_id`,`created_at`);--> statement-breakpoint
|
||||
CREATE INDEX `idx_ai_proposals_user` ON `ai_proposals` (`user_id`,`status`);--> statement-breakpoint
|
||||
CREATE INDEX `idx_ai_proposals_conversation` ON `ai_proposals` (`conversation_id`);--> statement-breakpoint
|
||||
CREATE INDEX `idx_automation_run_steps_run` ON `automation_run_steps` (`run_id`,`step_index`);--> statement-breakpoint
|
||||
CREATE INDEX `idx_automation_runs_automation` ON `automation_runs` (`automation_id`,`started_at`);--> statement-breakpoint
|
||||
CREATE INDEX `idx_automation_runs_user` ON `automation_runs` (`user_id`,`started_at`);--> statement-breakpoint
|
||||
CREATE INDEX `idx_automation_schedules_due` ON `automation_schedules` (`next_due_at`);--> statement-breakpoint
|
||||
CREATE INDEX `idx_automations_user` ON `automations` (`user_id`,`enabled`);
|
||||
@@ -1,2 +0,0 @@
|
||||
ALTER TABLE `user_preferences` ADD `terminal_defaults` text;--> statement-breakpoint
|
||||
ALTER TABLE `user_preferences` ADD `rdp_defaults` text;
|
||||
@@ -1 +0,0 @@
|
||||
ALTER TABLE `user_preferences` ADD `terminal_macros` text;
|
||||
@@ -1,34 +0,0 @@
|
||||
CREATE TABLE `collab_room_members` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`room_id` varchar(255) NOT NULL,
|
||||
`user_id` varchar(255) NOT NULL,
|
||||
`room_role` text NOT NULL DEFAULT ('member'),
|
||||
`added_by` varchar(255),
|
||||
`created_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
CONSTRAINT `collab_room_members_id` PRIMARY KEY(`id`),
|
||||
CONSTRAINT `idx_collab_room_members_room_user` UNIQUE(`room_id`,`user_id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `collab_rooms` (
|
||||
`id` varchar(255) NOT NULL,
|
||||
`name` varchar(255) NOT NULL,
|
||||
`owner_user_id` varchar(255) NOT NULL,
|
||||
`persistent` boolean NOT NULL DEFAULT false,
|
||||
`presenter_user_id` varchar(255),
|
||||
`stage_protocol` text,
|
||||
`stage_host_id` int,
|
||||
`stage_share_id` varchar(255),
|
||||
`created_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
`ended_at` text,
|
||||
CONSTRAINT `collab_rooms_id` PRIMARY KEY(`id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE `collab_room_members` ADD CONSTRAINT `collab_room_members_room_id_collab_rooms_id_fk` FOREIGN KEY (`room_id`) REFERENCES `collab_rooms`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `collab_room_members` ADD CONSTRAINT `collab_room_members_user_id_users_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `collab_room_members` ADD CONSTRAINT `collab_room_members_added_by_users_id_fk` FOREIGN KEY (`added_by`) REFERENCES `users`(`id`) ON DELETE set null ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `collab_rooms` ADD CONSTRAINT `collab_rooms_owner_user_id_users_id_fk` FOREIGN KEY (`owner_user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `collab_rooms` ADD CONSTRAINT `collab_rooms_presenter_user_id_users_id_fk` FOREIGN KEY (`presenter_user_id`) REFERENCES `users`(`id`) ON DELETE set null ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `collab_rooms` ADD CONSTRAINT `collab_rooms_stage_host_id_ssh_data_id_fk` FOREIGN KEY (`stage_host_id`) REFERENCES `ssh_data`(`id`) ON DELETE set null ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `collab_rooms` ADD CONSTRAINT `collab_rooms_stage_share_id_session_shares_id_fk` FOREIGN KEY (`stage_share_id`) REFERENCES `session_shares`(`id`) ON DELETE set null ON UPDATE no action;--> statement-breakpoint
|
||||
CREATE INDEX `idx_collab_room_members_user` ON `collab_room_members` (`user_id`);--> statement-breakpoint
|
||||
CREATE INDEX `idx_collab_rooms_owner` ON `collab_rooms` (`owner_user_id`);
|
||||
@@ -1,2 +0,0 @@
|
||||
ALTER TABLE `collab_rooms` ADD `guest_link_token` varchar(255);--> statement-breakpoint
|
||||
ALTER TABLE `collab_rooms` ADD CONSTRAINT `idx_collab_rooms_guest_token` UNIQUE(`guest_link_token`);
|
||||
@@ -1,15 +0,0 @@
|
||||
CREATE TABLE `secret_sources` (
|
||||
`id` varchar(255) NOT NULL,
|
||||
`user_id` varchar(255) NOT NULL,
|
||||
`name` varchar(255) NOT NULL,
|
||||
`kind` text NOT NULL DEFAULT ('onepassword-connect'),
|
||||
`base_url` text NOT NULL,
|
||||
`token` text NOT NULL,
|
||||
`shared` boolean NOT NULL DEFAULT false,
|
||||
`created_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
`updated_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
CONSTRAINT `secret_sources_id` PRIMARY KEY(`id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE `secret_sources` ADD CONSTRAINT `secret_sources_user_id_users_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
CREATE INDEX `idx_secret_sources_user` ON `secret_sources` (`user_id`);
|
||||
@@ -1,42 +0,0 @@
|
||||
CREATE TABLE `credential_access` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`credential_id` int NOT NULL,
|
||||
`user_id` varchar(255),
|
||||
`role_id` int,
|
||||
`granted_by` varchar(255) NOT NULL,
|
||||
`permission_level` text NOT NULL DEFAULT ('use'),
|
||||
`expires_at` varchar(255),
|
||||
`created_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
CONSTRAINT `credential_access_id` PRIMARY KEY(`id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `shared_credential_secrets` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`credential_access_id` int NOT NULL,
|
||||
`target_user_id` varchar(255) NOT NULL,
|
||||
`credential_id` int NOT NULL,
|
||||
`encrypted_username` text,
|
||||
`auth_type` text NOT NULL DEFAULT ('password'),
|
||||
`encrypted_password` text,
|
||||
`encrypted_key` text,
|
||||
`encrypted_key_password` text,
|
||||
`key_type` text,
|
||||
`public_key` text,
|
||||
`cert_public_key` text,
|
||||
`created_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
`updated_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
CONSTRAINT `shared_credential_secrets_id` PRIMARY KEY(`id`),
|
||||
CONSTRAINT `idx_shared_credential_secrets_scope` UNIQUE(`credential_access_id`,`target_user_id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE `credential_access` ADD CONSTRAINT `credential_access_credential_id_ssh_credentials_id_fk` FOREIGN KEY (`credential_id`) REFERENCES `ssh_credentials`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `credential_access` ADD CONSTRAINT `credential_access_user_id_users_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `credential_access` ADD CONSTRAINT `credential_access_role_id_roles_id_fk` FOREIGN KEY (`role_id`) REFERENCES `roles`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `credential_access` ADD CONSTRAINT `credential_access_granted_by_users_id_fk` FOREIGN KEY (`granted_by`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `shared_credential_secrets` ADD CONSTRAINT `shared_cred_secrets_access_id_fk` FOREIGN KEY (`credential_access_id`) REFERENCES `credential_access`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `shared_credential_secrets` ADD CONSTRAINT `shared_credential_secrets_target_user_id_users_id_fk` FOREIGN KEY (`target_user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `shared_credential_secrets` ADD CONSTRAINT `shared_credential_secrets_credential_id_ssh_credentials_id_fk` FOREIGN KEY (`credential_id`) REFERENCES `ssh_credentials`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
CREATE INDEX `idx_credential_access_user_id` ON `credential_access` (`user_id`);--> statement-breakpoint
|
||||
CREATE INDEX `idx_credential_access_role_id` ON `credential_access` (`role_id`);--> statement-breakpoint
|
||||
CREATE INDEX `idx_credential_access_credential_id` ON `credential_access` (`credential_id`);--> statement-breakpoint
|
||||
CREATE INDEX `idx_shared_credential_secrets_target` ON `shared_credential_secrets` (`target_user_id`,`credential_id`);
|
||||
@@ -1,22 +0,0 @@
|
||||
CREATE TABLE `folder_access` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`owner_user_id` varchar(255) NOT NULL,
|
||||
`folder` varchar(255) NOT NULL,
|
||||
`user_id` varchar(255),
|
||||
`role_id` int,
|
||||
`granted_by` varchar(255) NOT NULL,
|
||||
`permission_level` text NOT NULL DEFAULT ('connect'),
|
||||
`expires_at` varchar(255),
|
||||
`created_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
CONSTRAINT `folder_access_id` PRIMARY KEY(`id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE `ssh_data` MODIFY COLUMN `folder` varchar(255);--> statement-breakpoint
|
||||
ALTER TABLE `snippets` MODIFY COLUMN `folder` varchar(255);--> statement-breakpoint
|
||||
ALTER TABLE `ssh_credentials` MODIFY COLUMN `folder` varchar(255);--> statement-breakpoint
|
||||
ALTER TABLE `vault_profiles` MODIFY COLUMN `folder` varchar(255);--> statement-breakpoint
|
||||
ALTER TABLE `folder_access` ADD CONSTRAINT `folder_access_owner_user_id_users_id_fk` FOREIGN KEY (`owner_user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `folder_access` ADD CONSTRAINT `folder_access_user_id_users_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `folder_access` ADD CONSTRAINT `folder_access_role_id_roles_id_fk` FOREIGN KEY (`role_id`) REFERENCES `roles`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `folder_access` ADD CONSTRAINT `folder_access_granted_by_users_id_fk` FOREIGN KEY (`granted_by`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
CREATE INDEX `idx_folder_access_owner_folder` ON `folder_access` (`owner_user_id`,`folder`);
|
||||
@@ -1,2 +0,0 @@
|
||||
ALTER TABLE `ssh_data` ADD `enable_web_ui` boolean DEFAULT false NOT NULL;--> statement-breakpoint
|
||||
ALTER TABLE `ssh_data` ADD `web_ui_config` text;
|
||||
@@ -1 +0,0 @@
|
||||
ALTER TABLE `ssh_data` ADD `enable_ai_assistant` boolean DEFAULT false NOT NULL;
|
||||
@@ -1,51 +0,0 @@
|
||||
CREATE TABLE `plugin_install_counts` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`plugin_id` varchar(255) NOT NULL,
|
||||
`registry_id` varchar(255) NOT NULL,
|
||||
`count` int NOT NULL DEFAULT 0,
|
||||
`source` text NOT NULL DEFAULT ('aggregate-telemetry'),
|
||||
`updated_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
CONSTRAINT `plugin_install_counts_id` PRIMARY KEY(`id`),
|
||||
CONSTRAINT `idx_plugin_install_counts_plugin_registry` UNIQUE(`plugin_id`,`registry_id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `plugin_permission_grants` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`plugin_id` varchar(255) NOT NULL,
|
||||
`capability` varchar(255) NOT NULL,
|
||||
`granted_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
`granted_by` varchar(255) NOT NULL,
|
||||
CONSTRAINT `plugin_permission_grants_id` PRIMARY KEY(`id`),
|
||||
CONSTRAINT `idx_plugin_permission_grants_plugin_capability` UNIQUE(`plugin_id`,`capability`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `plugin_registries` (
|
||||
`id` varchar(255) NOT NULL,
|
||||
`name` varchar(255) NOT NULL,
|
||||
`url` text NOT NULL,
|
||||
`kind` text NOT NULL DEFAULT ('community'),
|
||||
`enabled` boolean NOT NULL DEFAULT true,
|
||||
`signing_key` text,
|
||||
`last_checked_at` text,
|
||||
`last_index_hash` text,
|
||||
CONSTRAINT `plugin_registries_id` PRIMARY KEY(`id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `plugins` (
|
||||
`id` varchar(255) NOT NULL,
|
||||
`name` varchar(255) NOT NULL,
|
||||
`version` text NOT NULL,
|
||||
`tier` text NOT NULL DEFAULT ('available'),
|
||||
`source` text NOT NULL DEFAULT ('community'),
|
||||
`registry_id` varchar(255),
|
||||
`state` text NOT NULL DEFAULT ('disabled'),
|
||||
`installed_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
`updated_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
`auto_update` boolean NOT NULL DEFAULT false,
|
||||
`manifest_json` text NOT NULL,
|
||||
CONSTRAINT `plugins_id` PRIMARY KEY(`id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE `plugin_permission_grants` ADD CONSTRAINT `plugin_permission_grants_plugin_id_plugins_id_fk` FOREIGN KEY (`plugin_id`) REFERENCES `plugins`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `plugin_permission_grants` ADD CONSTRAINT `plugin_permission_grants_granted_by_users_id_fk` FOREIGN KEY (`granted_by`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
CREATE INDEX `idx_plugins_registry_id` ON `plugins` (`registry_id`);
|
||||
@@ -1 +0,0 @@
|
||||
ALTER TABLE `user_preferences` ADD `show_pin_app_rail_button` boolean;
|
||||
@@ -1,11 +0,0 @@
|
||||
CREATE TABLE `plugin_storage` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`plugin_id` varchar(255) NOT NULL,
|
||||
`key` varchar(255) NOT NULL,
|
||||
`value` text NOT NULL,
|
||||
`updated_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
CONSTRAINT `plugin_storage_id` PRIMARY KEY(`id`),
|
||||
CONSTRAINT `idx_plugin_storage_plugin_key` UNIQUE(`plugin_id`,`key`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE `plugin_storage` ADD CONSTRAINT `plugin_storage_plugin_id_plugins_id_fk` FOREIGN KEY (`plugin_id`) REFERENCES `plugins`(`id`) ON DELETE cascade ON UPDATE no action;
|
||||
@@ -1,3 +0,0 @@
|
||||
DROP TABLE `alert_firings`;--> statement-breakpoint
|
||||
DROP TABLE `alert_rule_channels`;--> statement-breakpoint
|
||||
DROP TABLE `alert_rules`;
|
||||
@@ -1,3 +0,0 @@
|
||||
ALTER TABLE `plugin_permission_grants` MODIFY COLUMN `granted_by` varchar(255);--> statement-breakpoint
|
||||
ALTER TABLE `plugin_permission_grants` ADD `source` text DEFAULT ('admin') NOT NULL;--> statement-breakpoint
|
||||
ALTER TABLE `plugins` ADD `last_error` text;
|
||||
@@ -1,11 +0,0 @@
|
||||
CREATE TABLE `plugin_migrations` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`plugin_id` varchar(255) NOT NULL,
|
||||
`migration_id` varchar(255) NOT NULL,
|
||||
`checksum` text NOT NULL,
|
||||
`applied_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
CONSTRAINT `plugin_migrations_id` PRIMARY KEY(`id`),
|
||||
CONSTRAINT `idx_plugin_migrations_plugin_migration` UNIQUE(`plugin_id`,`migration_id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE `plugin_migrations` ADD CONSTRAINT `plugin_migrations_plugin_id_plugins_id_fk` FOREIGN KEY (`plugin_id`) REFERENCES `plugins`(`id`) ON DELETE cascade ON UPDATE no action;
|
||||
@@ -1,17 +0,0 @@
|
||||
CREATE TABLE `rbac_applied_defaults` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`role_name` varchar(255) NOT NULL,
|
||||
`permission` varchar(255) NOT NULL,
|
||||
`applied_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
CONSTRAINT `rbac_applied_defaults_id` PRIMARY KEY(`id`),
|
||||
CONSTRAINT `idx_rbac_applied_defaults_role_permission` UNIQUE(`role_name`,`permission`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `rbac_known_permissions` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`permission` varchar(255) NOT NULL,
|
||||
`plugin_id` varchar(255),
|
||||
`first_seen_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
CONSTRAINT `rbac_known_permissions_id` PRIMARY KEY(`id`),
|
||||
CONSTRAINT `idx_rbac_known_permissions_permission` UNIQUE(`permission`)
|
||||
);
|
||||
@@ -1,15 +0,0 @@
|
||||
CREATE TABLE `plugin_settings` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`plugin_id` varchar(255) NOT NULL,
|
||||
`scope` enum('admin','user','host','secret') NOT NULL,
|
||||
`scope_id` varchar(255),
|
||||
`key` varchar(255) NOT NULL,
|
||||
`value` text,
|
||||
`encrypted` boolean NOT NULL DEFAULT false,
|
||||
`updated_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
CONSTRAINT `plugin_settings_id` PRIMARY KEY(`id`),
|
||||
CONSTRAINT `idx_plugin_settings_scope_key` UNIQUE(`plugin_id`,`scope`,`scope_id`,`key`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE `plugin_settings` ADD CONSTRAINT `plugin_settings_plugin_id_plugins_id_fk` FOREIGN KEY (`plugin_id`) REFERENCES `plugins`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
CREATE INDEX `idx_plugin_settings_plugin_scope` ON `plugin_settings` (`plugin_id`,`scope`);
|
||||
@@ -1,24 +0,0 @@
|
||||
CREATE TABLE `user_external_identities` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`user_id` varchar(255) NOT NULL,
|
||||
`provider_id` varchar(255) NOT NULL,
|
||||
`subject` varchar(255) NOT NULL,
|
||||
`email` text,
|
||||
`created_at` varchar(255) NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
CONSTRAINT `user_external_identities_id` PRIMARY KEY(`id`),
|
||||
CONSTRAINT `idx_user_external_identities_provider_subject` UNIQUE(`provider_id`,`subject`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `user_second_factors` (
|
||||
`id` int AUTO_INCREMENT NOT NULL,
|
||||
`user_id` varchar(255) NOT NULL,
|
||||
`plugin_id` varchar(255) NOT NULL,
|
||||
`factor_id` varchar(255) NOT NULL,
|
||||
`enrolled_at` text NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
CONSTRAINT `user_second_factors_id` PRIMARY KEY(`id`),
|
||||
CONSTRAINT `idx_user_second_factors_user_factor` UNIQUE(`user_id`,`plugin_id`,`factor_id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE `user_external_identities` ADD CONSTRAINT `user_external_identities_user_id_users_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `user_second_factors` ADD CONSTRAINT `user_second_factors_user_id_users_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
CREATE INDEX `idx_user_external_identities_user` ON `user_external_identities` (`user_id`);
|
||||
@@ -1,5 +0,0 @@
|
||||
-- user_workspaces moved to the workspaces plugin, whose first migration renames it
|
||||
-- to p_workspaces_workspaces. Dropping it here would lose every saved workspace,
|
||||
-- so this only stops drizzle tracking it. SELECT 1 because MySQL rejects an
|
||||
-- empty query.
|
||||
SELECT 1;
|
||||
@@ -1,4 +0,0 @@
|
||||
-- network_topology moved to the network-topology plugin, which adopts (renames)
|
||||
-- this table in its own migration before this drizzle migration would run.
|
||||
-- No DROP here: it would delete every row before the plugin's rename applies.
|
||||
SELECT 1;
|
||||
@@ -1,4 +0,0 @@
|
||||
-- snippets, snippet_folders and snippet_access moved to the snippets plugin
|
||||
-- (p_snippets_*), adopted by rename rather than dropped. A real DROP TABLE
|
||||
-- here would run before the plugin's adoption migration and delete every row.
|
||||
SELECT 1;
|
||||
@@ -1,2 +0,0 @@
|
||||
-- dropped, see plugin adoption (fleets plugin, migrations/mysql/0001_adopt_fleets.sql)
|
||||
SELECT 1;
|
||||
@@ -1,6 +0,0 @@
|
||||
-- proxmox_node_history and proxmox_stats_preferences moved to the proxmox
|
||||
-- plugin (p_proxmox_*), adopted by rename rather than dropped. The four
|
||||
-- ssh_data proxmox columns are copied into the plugin's host settings after
|
||||
-- plugins load, which is after this migration, so a real DROP COLUMN here
|
||||
-- would delete the data first. The columns stay in place, unused, until 3.0.0.
|
||||
SELECT 1;
|
||||
@@ -1,5 +0,0 @@
|
||||
-- file_manager_pinned, file_manager_recent, file_manager_shortcuts and
|
||||
-- transfer_recent are adopted (renamed, not dropped) by the file-manager
|
||||
-- plugin's own migration, which runs at plugin activation, after core's
|
||||
-- drizzle migrations. A DROP TABLE here would run first and delete the data.
|
||||
SELECT 1;
|
||||
@@ -1,5 +0,0 @@
|
||||
-- c2s_tunnel_presets moved to the tunnels plugin, whose first migration renames
|
||||
-- it to p_tunnels_presets. Dropping it here would lose every saved preset, so
|
||||
-- this only stops drizzle tracking it. SELECT 1 because MySQL rejects an
|
||||
-- empty query.
|
||||
SELECT 1;
|
||||
@@ -1,5 +0,0 @@
|
||||
-- command_history moved to the ssh-terminal plugin, whose first migration
|
||||
-- renames it to p_ssh_terminal_command_history. Dropping it here would lose
|
||||
-- every saved command, so this only stops drizzle tracking it. SELECT 1
|
||||
-- because MySQL rejects an empty query.
|
||||
SELECT 1;
|
||||
@@ -1,5 +0,0 @@
|
||||
-- tmux_session_tags moved to the tmux-monitor plugin, whose first migration
|
||||
-- renames it to p_tmux_monitor_session_tags. Dropping it here would lose
|
||||
-- every saved tag, so this only stops drizzle tracking it. SELECT 1 because
|
||||
-- MySQL rejects an empty query.
|
||||
SELECT 1;
|
||||
@@ -1,6 +0,0 @@
|
||||
-- session_shares, session_share_participants, collab_rooms and
|
||||
-- collab_room_members moved to the session-sharing plugin, whose first
|
||||
-- migration renames them. Dropping them here would lose every share and
|
||||
-- room, so this only stops drizzle tracking them. SELECT 1 because MySQL
|
||||
-- rejects an empty query.
|
||||
SELECT 1;
|
||||
@@ -1,5 +0,0 @@
|
||||
-- session_recordings moved to the session-recording plugin, whose first
|
||||
-- migration renames it. Dropping it here would lose every recording, so
|
||||
-- this only stops drizzle tracking it. SELECT 1 because MySQL rejects an
|
||||
-- empty query.
|
||||
SELECT 1;
|
||||
@@ -1,7 +0,0 @@
|
||||
-- The remote desktop host options (enable_rdp, enable_vnc, enable_telnet,
|
||||
-- the three ports, rdp_security, rdp_ignore_cert, security, ignore_cert,
|
||||
-- guacamole_config) and user_preferences.rdp_defaults moved to the
|
||||
-- remote-desktop plugin's settings. The copy runs after plugins load, which
|
||||
-- is after this migration, so a real DROP COLUMN here would delete the data
|
||||
-- first. The columns stay in place, unused, until 3.0.0.
|
||||
SELECT 1;
|
||||
@@ -1,9 +0,0 @@
|
||||
-- host_metrics_preferences, host_health_checks, host_health_history and
|
||||
-- host_metrics_history moved to the host-metrics plugin, which adopts them by
|
||||
-- rename in its own first migration. That runs after this one, so a real
|
||||
-- DROP TABLE here would delete every row first.
|
||||
SELECT 1;--> statement-breakpoint
|
||||
-- Status checks are core: the per-host switch and interval, copied out of
|
||||
-- stats_config at boot by host-status-config-migration.ts.
|
||||
ALTER TABLE `ssh_data` ADD `status_check_enabled` boolean DEFAULT true NOT NULL;--> statement-breakpoint
|
||||
ALTER TABLE `ssh_data` ADD `status_check_interval` int;
|
||||
@@ -1,6 +0,0 @@
|
||||
-- ssh_data.stats_config split: its status half moved to status_check_enabled
|
||||
-- and status_check_interval, its metrics half to the host-metrics plugin's
|
||||
-- host settings. Both copies run at boot, after this migration, so a real
|
||||
-- DROP COLUMN here would delete the data first. The column stays in place,
|
||||
-- unused, until 3.0.0.
|
||||
SELECT 1;
|
||||
@@ -1,5 +0,0 @@
|
||||
-- ssh_data.enable_docker and docker_config moved to the docker plugin's host
|
||||
-- settings. The copy runs at boot, after this migration, so a real DROP
|
||||
-- COLUMN here would delete the data first. The columns stay in place,
|
||||
-- unused, until 3.0.0.
|
||||
SELECT 1;
|
||||
@@ -1,4 +0,0 @@
|
||||
-- The automation tables moved to the automations plugin, which renames them
|
||||
-- into its own namespace at activation. That runs after this migration, so a
|
||||
-- real DROP TABLE here would delete every automation first.
|
||||
SELECT 1;
|
||||
@@ -1,8 +0,0 @@
|
||||
-- The ai tables moved to the ai plugin, which renames them into its own
|
||||
-- namespace at activation, and ssh_data.enable_ai_assistant and the two
|
||||
-- user_preferences ai columns moved to its settings. Both run after this
|
||||
-- migration, so a real DROP here would delete the data first. The columns
|
||||
-- stay in place, unused, until 3.0.0. The timestamp and label type changes
|
||||
-- drizzle-kit also wrote are generator drift (see FINISH-LIST.md), not a
|
||||
-- change to the database, and are left out on purpose.
|
||||
SELECT 1;
|
||||
@@ -1,6 +0,0 @@
|
||||
-- dashboard_service_links, homepage_items and homepage_layouts moved to the
|
||||
-- homepage plugin, which adopts them by rename at activation (see
|
||||
-- plugins/homepage/migrations/mysql/0001_adopt_homepage_tables.sql).
|
||||
-- Dropping them here would delete every row before the plugin's migration
|
||||
-- ever runs, since this runs at boot before the plugins table exists.
|
||||
SELECT 1;
|
||||
@@ -1,4 +0,0 @@
|
||||
-- mac_address and wol_broadcast_address move to the wake-on-lan plugin's
|
||||
-- host settings at boot, after this migration runs. Dropping them here would
|
||||
-- delete the data before the copy has a chance to run.
|
||||
SELECT 1;
|
||||
@@ -1,4 +0,0 @@
|
||||
-- secret_sources moves to the secret-sources plugin's adopted table at
|
||||
-- activation, after this migration runs. Dropping it here would delete the
|
||||
-- data before the plugin has a chance to rename it.
|
||||
SELECT 1;
|
||||
@@ -1,4 +0,0 @@
|
||||
-- webauthn_credentials moves to the webauthn plugin's adopted table at
|
||||
-- activation, and the users TOTP columns are read by the TOTP boot migration
|
||||
-- after this runs. Dropping either here would lose the data first.
|
||||
SELECT 1;
|
||||
@@ -1,4 +0,0 @@
|
||||
-- sso_providers moves to the sso plugin's adopted table at activation, and
|
||||
-- its LDAP rows are copied into the ldap plugin by a boot migration after
|
||||
-- this runs. Dropping it here would lose the data first.
|
||||
SELECT 1;
|
||||
@@ -1,5 +0,0 @@
|
||||
-- opkssh_tokens moves to the opkssh plugin's adopted table at activation,
|
||||
-- and ssh_data.use_warpgate is copied into the warpgate plugin's host
|
||||
-- settings by a boot migration after this runs. Dropping either here would
|
||||
-- lose the data first.
|
||||
SELECT 1;
|
||||
@@ -1,5 +0,0 @@
|
||||
-- vault_profiles and vault_tokens move to the vault plugin's adopted tables
|
||||
-- at activation, and ssh_data.vault_profile_id is copied into the vault
|
||||
-- plugin's host settings by a boot migration after this runs. Dropping any
|
||||
-- of them here would lose the data first.
|
||||
SELECT 1;
|
||||
@@ -1,4 +0,0 @@
|
||||
-- termix_identities, termix_identity_keys and termix_identity_ca move to the
|
||||
-- termix-identity plugin's adopted tables at activation. Dropping them here
|
||||
-- would lose the data first.
|
||||
SELECT 1;
|
||||
Loaded 100 of 1803 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user