This commit is contained in:
45
.github/workflows/renovate.yml
vendored
Executable file
45
.github/workflows/renovate.yml
vendored
Executable file
@@ -0,0 +1,45 @@
|
|||||||
|
name: Renovate
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
log_level:
|
||||||
|
type: choice
|
||||||
|
description: Log level
|
||||||
|
default: INFO
|
||||||
|
options:
|
||||||
|
- DEBUG
|
||||||
|
- INFO
|
||||||
|
- WARN
|
||||||
|
- ERROR
|
||||||
|
- FATAL
|
||||||
|
schedule:
|
||||||
|
- cron: 0 2 * * *
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
renovate:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install node
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: "22"
|
||||||
|
|
||||||
|
- name: Install bun
|
||||||
|
uses: oven-sh/setup-bun@v2
|
||||||
|
|
||||||
|
- name: Cache Bun global packages
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: ~/.bun/install/global
|
||||||
|
key: ${{ runner.os }}-bun-global-renovate-40
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-bun-global-
|
||||||
|
|
||||||
|
- name: Install Renovate
|
||||||
|
run: bun install -g renovate@40
|
||||||
|
|
||||||
|
- name: Run renovate
|
||||||
|
run: LOG_LEVEL=${{ github.event.inputs.log_level || 'INFO' }} renovate --token ${{ secrets.GITHUB_TOKEN }} ${{ github.repository }}
|
||||||
23
.github/workflows/test.yml
vendored
Executable file
23
.github/workflows/test.yml
vendored
Executable file
@@ -0,0 +1,23 @@
|
|||||||
|
name: Test
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main]
|
||||||
|
pull_request:
|
||||||
|
branches: [main]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Setup Bun
|
||||||
|
uses: oven-sh/setup-bun@v2
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: bun install
|
||||||
|
|
||||||
|
- name: Run tests
|
||||||
|
run: bun test
|
||||||
1
.gitignore
vendored
Executable file
1
.gitignore
vendored
Executable file
@@ -0,0 +1 @@
|
|||||||
|
node_modules/
|
||||||
13
LICENSE
Executable file
13
LICENSE
Executable file
@@ -0,0 +1,13 @@
|
|||||||
|
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||||
|
Version 2, December 2004
|
||||||
|
|
||||||
|
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
|
||||||
|
|
||||||
|
Everyone is permitted to copy and distribute verbatim or modified
|
||||||
|
copies of this license document, and changing it is allowed as long
|
||||||
|
as the name is changed.
|
||||||
|
|
||||||
|
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||||
|
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||||
|
|
||||||
|
0. You just DO WHAT THE FUCK YOU WANT TO.
|
||||||
31
README.md
Executable file
31
README.md
Executable file
@@ -0,0 +1,31 @@
|
|||||||
|
# Example App Store Template
|
||||||
|
|
||||||
|
This repository serves as a template for creating your own custom app store for the Runtipi platform. Use this as a starting point to create and share your own collection of applications.
|
||||||
|
|
||||||
|
## Repository Structure
|
||||||
|
|
||||||
|
- **apps/**: Contains individual app directories
|
||||||
|
|
||||||
|
- Each app has its own folder (e.g., `whoami/`) with the following structure:
|
||||||
|
- `config.json`: App configuration file
|
||||||
|
- `docker-compose.json`: Docker setup for the app
|
||||||
|
- `metadata/`: Contains app visuals and descriptions
|
||||||
|
- `description.md`: Markdown description of the app
|
||||||
|
- `logo.jpg`: App logo image
|
||||||
|
|
||||||
|
- **tests/**: Contains test files for the app store
|
||||||
|
|
||||||
|
- `apps.test.ts`: Test suite for validating apps
|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
This repository is intended to serve as a template for creating your own app store. Follow these steps to get started:
|
||||||
|
|
||||||
|
1. Click the "Use this template" button to create a new repository based on this template
|
||||||
|
2. Customize the apps or add your own app folders in the `apps/` directory
|
||||||
|
3. Test your app store by using it with Runtipi
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
For detailed instructions on creating your own app store, please refer to the official guide:
|
||||||
|
[Create Your Own App Store Guide](https://runtipi.io/docs/guides/create-your-own-app-store)
|
||||||
77
__tests__/apps.test.ts
Executable file
77
__tests__/apps.test.ts
Executable file
@@ -0,0 +1,77 @@
|
|||||||
|
import { expect, test, describe } from "bun:test";
|
||||||
|
import { appInfoSchema, dynamicComposeSchema } from '@runtipi/common/schemas'
|
||||||
|
import { fromError } from 'zod-validation-error';
|
||||||
|
import fs from 'node:fs'
|
||||||
|
import path from 'node:path'
|
||||||
|
|
||||||
|
const getApps = async () => {
|
||||||
|
const appsDir = await fs.promises.readdir(path.join(process.cwd(), 'apps'))
|
||||||
|
|
||||||
|
const appDirs = appsDir.filter((app) => {
|
||||||
|
const stat = fs.statSync(path.join(process.cwd(), 'apps', app))
|
||||||
|
return stat.isDirectory()
|
||||||
|
})
|
||||||
|
|
||||||
|
return appDirs
|
||||||
|
};
|
||||||
|
|
||||||
|
const getFile = async (app: string, file: string) => {
|
||||||
|
const filePath = path.join(process.cwd(), 'apps', app, file)
|
||||||
|
try {
|
||||||
|
const file = await fs.promises.readFile(filePath, 'utf-8')
|
||||||
|
return file
|
||||||
|
} catch (err) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
describe("each app should have the required files", async () => {
|
||||||
|
const apps = await getApps()
|
||||||
|
|
||||||
|
for (const app of apps) {
|
||||||
|
const files = ['config.json', 'docker-compose.json', 'metadata/logo.jpg', 'metadata/description.md']
|
||||||
|
|
||||||
|
for (const file of files) {
|
||||||
|
test(`app ${app} should have ${file}`, async () => {
|
||||||
|
const fileContent = await getFile(app, file)
|
||||||
|
expect(fileContent).not.toBeNull()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("each app should have a valid config.json", async () => {
|
||||||
|
const apps = await getApps()
|
||||||
|
|
||||||
|
for (const app of apps) {
|
||||||
|
test(`app ${app} should have a valid config.json`, async () => {
|
||||||
|
const fileContent = await getFile(app, 'config.json')
|
||||||
|
const parsed = appInfoSchema.omit({ urn: true }).safeParse(JSON.parse(fileContent || '{}'))
|
||||||
|
|
||||||
|
if (!parsed.success) {
|
||||||
|
const validationError = fromError(parsed.error);
|
||||||
|
console.error(`Error parsing config.json for app ${app}:`, validationError.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(parsed.success).toBe(true)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("each app should have a valid docker-compose.json", async () => {
|
||||||
|
const apps = await getApps()
|
||||||
|
|
||||||
|
for (const app of apps) {
|
||||||
|
test(`app ${app} should have a valid docker-compose.json`, async () => {
|
||||||
|
const fileContent = await getFile(app, 'docker-compose.json')
|
||||||
|
const parsed = dynamicComposeSchema.safeParse(JSON.parse(fileContent || '{}'))
|
||||||
|
|
||||||
|
if (!parsed.success) {
|
||||||
|
const validationError = fromError(parsed.error);
|
||||||
|
console.error(`Error parsing docker-compose.json for app ${app}:`, validationError.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(parsed.success).toBe(true)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
});
|
||||||
11
apps/cistech-tunnel/.env.example
Executable file
11
apps/cistech-tunnel/.env.example
Executable file
@@ -0,0 +1,11 @@
|
|||||||
|
# Required
|
||||||
|
OC_URL=https://vpn.cistech.net/Employees
|
||||||
|
OC_SERVERCERT=pin-sha256:HyHob3LiVmIp8ch9AzHJ9jMYqI43tO5N13oWeBLiZ/0=
|
||||||
|
|
||||||
|
# Optional
|
||||||
|
OC_AUTHGROUP=
|
||||||
|
OC_SSO_ARGS=--browser-display-mode shown
|
||||||
|
VNC_PASSWORD=vpnSSO12
|
||||||
|
NOVNC_PORT=6901
|
||||||
|
PUBLISH_ADDR=0.0.0.0
|
||||||
|
SSH_KEY_PATH=/home/alexz/.ssh/id_ed25519-lenovo
|
||||||
11
apps/cistech-tunnel/README.md
Executable file
11
apps/cistech-tunnel/README.md
Executable file
@@ -0,0 +1,11 @@
|
|||||||
|
# Cistech Tunnel (VPN + SSH)
|
||||||
|
|
||||||
|
- VPN: OpenConnect-SSO with noVNC for first-time SSO (port 6901)
|
||||||
|
- SSH tunnels: forwards to 10.3.1.201 inside the VPN namespace
|
||||||
|
|
||||||
|
Usage
|
||||||
|
- Copy `.env.example` to `.env` and adjust values.
|
||||||
|
- Build and start:
|
||||||
|
docker compose build
|
||||||
|
docker compose up -d vpn ssh_tunnel
|
||||||
|
- First-time SSO: open http://<host>:6901 and complete login; then set `OC_SSO_ARGS=--browser-display-mode hidden` and restart `vpn`.
|
||||||
25
apps/cistech-tunnel/config.json
Executable file
25
apps/cistech-tunnel/config.json
Executable file
@@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
"name": "Cistech Tunnel",
|
||||||
|
"id": "cistech-tunnel",
|
||||||
|
"available": true,
|
||||||
|
"short_desc": "OpenConnect-SSO VPN + SSH forwards (noVNC)",
|
||||||
|
"author": "alexz",
|
||||||
|
"port": 6901,
|
||||||
|
"categories": ["utilities","network"],
|
||||||
|
"description": "OpenConnect-SSO VPN running in an isolated namespace with noVNC for first-time SSO and an SSH tunnel service for local forwards.",
|
||||||
|
"tipi_version": 1,
|
||||||
|
"version": "1.0.0",
|
||||||
|
"source": "https://git.alexzaw.dev/alexz/cistech-tunnel",
|
||||||
|
"exposable": true,
|
||||||
|
"dynamic_config": false,
|
||||||
|
"no_gui": false,
|
||||||
|
"form_fields": [
|
||||||
|
{"label":"VPN URL","type":"text","env_variable":"OC_URL","required":true,"default":"https://vpn.cistech.net/Employees"},
|
||||||
|
{"label":"Server Cert Pin","type":"text","env_variable":"OC_SERVERCERT","required":true,"default":"pin-sha256:HyHob3LiVmIp8ch9AzHJ9jMYqI43tO5N13oWeBLiZ/0="},
|
||||||
|
{"label":"Auth Group","type":"text","env_variable":"OC_AUTHGROUP","required":false,"default":""},
|
||||||
|
{"label":"SSO Mode","type":"text","env_variable":"OC_SSO_ARGS","required":true,"default":"--browser-display-mode shown"},
|
||||||
|
{"label":"VNC Password","type":"password","env_variable":"VNC_PASSWORD","required":true,"default":"Az@83278327$$@@"},
|
||||||
|
{"label":"SSH Key Path","type":"text","env_variable":"SSH_KEY_PATH","required":true,"default":"/home/alexz/.ssh/id_ed25519-lenovo"}
|
||||||
|
],
|
||||||
|
"supported_architectures": ["arm64","amd64"]
|
||||||
|
}
|
||||||
25
apps/cistech-tunnel/config.json.bak.1765310779
Executable file
25
apps/cistech-tunnel/config.json.bak.1765310779
Executable file
@@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
"name": "Cistech Tunnel",
|
||||||
|
"id": "cistech-tunnel",
|
||||||
|
"available": true,
|
||||||
|
"short_desc": "OpenConnect-SSO VPN + SSH forwards (noVNC)",
|
||||||
|
"author": "alexz",
|
||||||
|
"port": 6901,
|
||||||
|
"categories": ["networking", "utilities"],
|
||||||
|
"description": "OpenConnect-SSO VPN running in an isolated namespace with noVNC for first-time SSO and an SSH tunnel service for local forwards.",
|
||||||
|
"tipi_version": 1,
|
||||||
|
"version": "1.0.0",
|
||||||
|
"source": "https://git.alexzaw.dev/alexz/cistech-tunnel",
|
||||||
|
"exposable": true,
|
||||||
|
"dynamic_config": true,
|
||||||
|
"no_gui": false,
|
||||||
|
"form_fields": [
|
||||||
|
{ "label": "VPN URL", "type": "text", "env_variable": "OC_URL_A", "required": true, "default": "https://vpn.cistech.net/Employees" },
|
||||||
|
{ "label": "Server Cert Pin", "type": "text", "env_variable": "OC_SERVERCERT_A", "required": true, "default": "pin-sha256:HyHob3LiVmIp8ch9AzHJ9jMYqI43tO5N13oWeBLiZ/0=" },
|
||||||
|
{ "label": "Auth Group", "type": "text", "env_variable": "OC_AUTHGROUP_A", "required": false, "default": "" },
|
||||||
|
{ "label": "SSO Mode", "type": "text", "env_variable": "OC_SSO_ARGS_A", "required": true, "default": "--browser-display-mode shown" },
|
||||||
|
{ "label": "VNC Password", "type": "password", "env_variable": "VNC_PASS_A", "required": true, "default": "vpnSSO12" },
|
||||||
|
{ "label": "SSH Key Path", "type": "text", "env_variable": "SSH_KEY_PATH", "required": true, "default": "/home/alexz/.ssh/id_ed25519-lenovo" }
|
||||||
|
],
|
||||||
|
"supported_architectures": ["arm64", "amd64"]
|
||||||
|
}
|
||||||
67
apps/cistech-tunnel/config.json.bak.1765311179
Executable file
67
apps/cistech-tunnel/config.json.bak.1765311179
Executable file
@@ -0,0 +1,67 @@
|
|||||||
|
{
|
||||||
|
"name": "Cistech Tunnel",
|
||||||
|
"id": "cistech-tunnel",
|
||||||
|
"available": true,
|
||||||
|
"short_desc": "OpenConnect-SSO VPN + SSH forwards (noVNC)",
|
||||||
|
"author": "alexz",
|
||||||
|
"port": 6901,
|
||||||
|
"categories": [
|
||||||
|
"utilities",
|
||||||
|
"network"
|
||||||
|
],
|
||||||
|
"description": "OpenConnect-SSO VPN running in an isolated namespace with noVNC for first-time SSO and an SSH tunnel service for local forwards.",
|
||||||
|
"tipi_version": 1,
|
||||||
|
"version": "1.0.0",
|
||||||
|
"source": "https://git.alexzaw.dev/alexz/cistech-tunnel",
|
||||||
|
"exposable": true,
|
||||||
|
"dynamic_config": true,
|
||||||
|
"no_gui": false,
|
||||||
|
"form_fields": [
|
||||||
|
{
|
||||||
|
"label": "VPN URL",
|
||||||
|
"type": "text",
|
||||||
|
"env_variable": "OC_URL",
|
||||||
|
"required": true,
|
||||||
|
"default": "https://vpn.cistech.net/Employees"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Server Cert Pin",
|
||||||
|
"type": "text",
|
||||||
|
"env_variable": "OC_SERVERCERT",
|
||||||
|
"required": true,
|
||||||
|
"default": "pin-sha256:HyHob3LiVmIp8ch9AzHJ9jMYqI43tO5N13oWeBLiZ/0="
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Auth Group",
|
||||||
|
"type": "text",
|
||||||
|
"env_variable": "OC_AUTHGROUP",
|
||||||
|
"required": false,
|
||||||
|
"default": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "SSO Mode",
|
||||||
|
"type": "text",
|
||||||
|
"env_variable": "OC_SSO_ARGS",
|
||||||
|
"required": true,
|
||||||
|
"default": "--browser-display-mode shown"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "VNC Password",
|
||||||
|
"type": "password",
|
||||||
|
"env_variable": "VNC_PASSWORD",
|
||||||
|
"required": true,
|
||||||
|
"default": "vpnSSO12"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "SSH Key Path",
|
||||||
|
"type": "text",
|
||||||
|
"env_variable": "SSH_KEY_PATH",
|
||||||
|
"required": true,
|
||||||
|
"default": "/home/alexz/.ssh/id_ed25519-lenovo"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"supported_architectures": [
|
||||||
|
"arm64",
|
||||||
|
"amd64"
|
||||||
|
]
|
||||||
|
}
|
||||||
39
apps/cistech-tunnel/docker-compose.json.bak.1765312176
Executable file
39
apps/cistech-tunnel/docker-compose.json.bak.1765312176
Executable file
@@ -0,0 +1,39 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://schemas.runtipi.io/v2/dynamic-compose.json",
|
||||||
|
"schemaVersion": 2,
|
||||||
|
"services": [
|
||||||
|
{
|
||||||
|
"name": "vpn_a",
|
||||||
|
"image": "vpn-openconnect-sso:latest",
|
||||||
|
"isMain": true,
|
||||||
|
"internalPort": 6901,
|
||||||
|
"capAdd": ["NET_ADMIN"],
|
||||||
|
"devices": [
|
||||||
|
{ "hostPath": "/dev/net/tun", "containerPath": "/dev/net/tun" }
|
||||||
|
],
|
||||||
|
"environment": [
|
||||||
|
{ "key": "OC_URL", "value": "${OC_URL_A}" },
|
||||||
|
{ "key": "OC_SERVERCERT", "value": "${OC_SERVERCERT_A}" },
|
||||||
|
{ "key": "OC_AUTHGROUP", "value": "${OC_AUTHGROUP_A}" },
|
||||||
|
{ "key": "OC_INTERFACE", "value": "tun0" },
|
||||||
|
{ "key": "OC_SSO_ARGS", "value": "${OC_SSO_ARGS_A}" },
|
||||||
|
{ "key": "VNC_PASSWORD", "value": "${VNC_PASS_A}" },
|
||||||
|
{ "key": "NOVNC_PORT", "value": "6901" }
|
||||||
|
],
|
||||||
|
"volumes": [
|
||||||
|
{ "hostPath": "${APP_DATA_DIR}/data/vpn_a_state", "containerPath": "/root" }
|
||||||
|
],
|
||||||
|
"restartPolicy": "unless-stopped"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "ssh_tunnel",
|
||||||
|
"image": "alpine:3.20",
|
||||||
|
"networkMode": "service:vpn_a",
|
||||||
|
"volumes": [
|
||||||
|
{ "hostPath": "${SSH_KEY_PATH}", "containerPath": "/root/.ssh/id_ed25519-lenovo", "readOnly": true }
|
||||||
|
],
|
||||||
|
"command": "sh -lc \"apk add --no-cache openssh-client && exec ssh -N -i /root/.ssh/id_ed25519-lenovo -o StrictHostKeyChecking=no -o ServerAliveInterval=60 -o ExitOnForwardFailure=yes -L 127.0.0.1:8090:localhost:8090 -L 127.0.0.1:2001:localhost:2001 -L 127.0.0.1:36001:localhost:36001 zawa@10.3.1.201\"",
|
||||||
|
"restartPolicy": "unless-stopped"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
43
apps/cistech-tunnel/docker-compose.yml
Executable file
43
apps/cistech-tunnel/docker-compose.yml
Executable file
@@ -0,0 +1,43 @@
|
|||||||
|
services:
|
||||||
|
vpn:
|
||||||
|
build: ./vpn-openconnect-sso
|
||||||
|
container_name: cistech-vpn
|
||||||
|
cap_add:
|
||||||
|
- NET_ADMIN
|
||||||
|
devices:
|
||||||
|
- /dev/net/tun:/dev/net/tun
|
||||||
|
environment:
|
||||||
|
OC_URL: ${OC_URL}
|
||||||
|
OC_SERVERCERT: ${OC_SERVERCERT}
|
||||||
|
OC_AUTHGROUP: ${OC_AUTHGROUP}
|
||||||
|
OC_INTERFACE: tun0
|
||||||
|
OC_SSO_ARGS: ${OC_SSO_ARGS:- --browser-display-mode shown}
|
||||||
|
VNC_PASSWORD: ${VNC_PASSWORD:-changeme}
|
||||||
|
NOVNC_PORT: ${NOVNC_PORT:-6901}
|
||||||
|
ports:
|
||||||
|
- "${PUBLISH_ADDR:-0.0.0.0}:${NOVNC_PORT:-6901}:${NOVNC_PORT:-6901}"
|
||||||
|
volumes:
|
||||||
|
- vpn_state:/root
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
ssh_tunnel:
|
||||||
|
image: alpine:3.20
|
||||||
|
container_name: cistech-ssh-tunnel
|
||||||
|
network_mode: "service:vpn"
|
||||||
|
depends_on:
|
||||||
|
- vpn
|
||||||
|
volumes:
|
||||||
|
- ${SSH_KEY_PATH:-/home/alexz/.ssh/id_ed25519-lenovo}:/root/.ssh/id_ed25519-lenovo:ro
|
||||||
|
command: >
|
||||||
|
sh -lc "apk add --no-cache openssh-client &&
|
||||||
|
exec ssh -N -i /root/.ssh/id_ed25519-lenovo \
|
||||||
|
-o StrictHostKeyChecking=no -o ServerAliveInterval=60 -o ExitOnForwardFailure=yes \
|
||||||
|
-L 0.0.0.0:8090:localhost:8090 \
|
||||||
|
-L 0.0.0.0:2001:localhost:2001 \
|
||||||
|
-L 0.0.0.0:36001:localhost:36001 \
|
||||||
|
-L 0.0.0.0:36000:localhost:36000 \
|
||||||
|
zawa@10.3.1.201"
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
vpn_state: {}
|
||||||
20
apps/cistech-tunnel/metadata/description.md
Executable file
20
apps/cistech-tunnel/metadata/description.md
Executable file
@@ -0,0 +1,20 @@
|
|||||||
|
# Dockerized OpenConnect-SSO with noVNC and Cloudflared
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
1) Copy `.env.example` to `.env` and fill values (URLs, servercert pins, VNC passwords, cloudflared tokens).
|
||||||
|
|
||||||
|
2) First-time SSO: leave `OC_SSO_ARGS_*=--browser-display-mode visible`.
|
||||||
|
|
||||||
|
3) Build and start:
|
||||||
|
docker compose build
|
||||||
|
docker compose up -d vpn_a
|
||||||
|
# Open http://localhost:6901, complete SSO.
|
||||||
|
# After success, attach app containers or start cloudflared_a.
|
||||||
|
|
||||||
|
4) Optional: switch to headless after first login:
|
||||||
|
Set `OC_SSO_ARGS_*=--browser-display-mode hidden` (or `headless`) and restart the vpn service.
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
- Each VPN runs in its own net namespace; routes from one cannot affect the other or the host.
|
||||||
|
- DNS from the VPN applies within its container namespace and attached services only.
|
||||||
|
- Persisted state lives in the named volumes mounted at `/root` (Playwright cache, configs).
|
||||||
BIN
apps/cistech-tunnel/metadata/logo.jpg
Executable file
BIN
apps/cistech-tunnel/metadata/logo.jpg
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 609 KiB |
33
apps/cistech-tunnel/vpn-openconnect-sso/Dockerfile
Executable file
33
apps/cistech-tunnel/vpn-openconnect-sso/Dockerfile
Executable file
@@ -0,0 +1,33 @@
|
|||||||
|
FROM ubuntu:24.04
|
||||||
|
ENV QTWEBENGINE_DISABLE_SANDBOX=1
|
||||||
|
ENV QTWEBENGINE_CHROMIUM_FLAGS="--no-sandbox --disable-gpu"
|
||||||
|
ENV DEBIAN_FRONTEND=noninteractive \
|
||||||
|
PLAYWRIGHT_BROWSERS_PATH=/ms-playwright \
|
||||||
|
VIRTUAL_ENV=/opt/venv \
|
||||||
|
PATH=/opt/venv/bin:$PATH
|
||||||
|
|
||||||
|
RUN apt-get update && apt-get install -y \
|
||||||
|
openconnect iproute2 iptables ca-certificates \
|
||||||
|
python3 python3-pip python3-venv \
|
||||||
|
vpnc-scripts curl \
|
||||||
|
x11vnc xvfb fluxbox novnc websockify \
|
||||||
|
xauth libnss3 libatk1.0-0 libatk-bridge2.0-0 \
|
||||||
|
libx11-6 libx11-xcb1 libxcomposite1 libxrandr2 libgbm1 libxdamage1 \
|
||||||
|
libpango-1.0-0 fonts-liberation \
|
||||||
|
libegl1 libgl1 libopengl0 libdbus-1-3 libglib2.0-0 \
|
||||||
|
libxkbcommon0 libxkbcommon-x11-0 \
|
||||||
|
libxcb1 libxcb-cursor0 libxcb-icccm4 libxcb-image0 libxcb-keysyms1 libxcb-render0 libxcb-render-util0 libxcb-shm0 libxcb-xfixes0 libxcb-xinerama0 libxcb-randr0 libxcb-glx0 \
|
||||||
|
sudo \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
RUN apt-get update && (apt-get install -y libasound2t64 || apt-get install -y libasound2) && rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
RUN python3 -m venv "$VIRTUAL_ENV"
|
||||||
|
RUN pip install --no-cache-dir openconnect-sso playwright \
|
||||||
|
&& python -m playwright install --with-deps chromium
|
||||||
|
|
||||||
|
COPY entrypoint.sh /entrypoint.sh
|
||||||
|
RUN chmod +x /entrypoint.sh
|
||||||
|
|
||||||
|
EXPOSE 6901
|
||||||
|
ENTRYPOINT ["/entrypoint.sh"]
|
||||||
36
apps/cistech-tunnel/vpn-openconnect-sso/entrypoint.sh
Executable file
36
apps/cistech-tunnel/vpn-openconnect-sso/entrypoint.sh
Executable file
@@ -0,0 +1,36 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
: "${OC_URL:?OC_URL is required}"
|
||||||
|
: "${OC_SERVERCERT:?OC_SERVERCERT is required}"
|
||||||
|
|
||||||
|
NOVNC_PORT="${NOVNC_PORT:-6901}"
|
||||||
|
VNC_PASSWORD="${VNC_PASSWORD:-changeme}"
|
||||||
|
DISPLAY_ADDR="${DISPLAY:-:1}"
|
||||||
|
OC_INTERFACE="${OC_INTERFACE:-tun0}"
|
||||||
|
OC_SSO_ARGS_DEFAULT="--browser-display-mode shown"
|
||||||
|
|
||||||
|
if [[ "${OC_SSO_ARGS:-$OC_SSO_ARGS_DEFAULT}" == *"shown"* ]]; then
|
||||||
|
mkdir -p /root/.vnc
|
||||||
|
x11vnc -storepasswd "$VNC_PASSWORD" /root/.vnc/pass >/dev/null 2>&1 || true
|
||||||
|
rm -f /tmp/.X1-lock /tmp/.X11-unix/X1 2>/dev/null || true
|
||||||
|
Xvfb "$DISPLAY_ADDR" -screen 0 ${XVFB_WxHxD:-1280x800x24} +extension RANDR &
|
||||||
|
sleep 0.5
|
||||||
|
export DISPLAY="$DISPLAY_ADDR"
|
||||||
|
fluxbox >/tmp/fluxbox.log 2>&1 &
|
||||||
|
x11vnc -display "$DISPLAY_ADDR" -rfbauth /root/.vnc/pass -forever -shared -rfbport 5900 -quiet &
|
||||||
|
websockify --web=/usr/share/novnc/ 0.0.0.0:"$NOVNC_PORT" localhost:5900 >/tmp/websockify.log 2>&1 &
|
||||||
|
fi
|
||||||
|
|
||||||
|
OPENCONNECT_CMD=(
|
||||||
|
/usr/sbin/openconnect
|
||||||
|
--protocol=anyconnect
|
||||||
|
--servercert "$OC_SERVERCERT"
|
||||||
|
--interface "$OC_INTERFACE"
|
||||||
|
--script /usr/share/vpnc-scripts/vpnc-script
|
||||||
|
)
|
||||||
|
[[ -n "${OC_AUTHGROUP:-}" ]] && OPENCONNECT_CMD+=(--authgroup "$OC_AUTHGROUP")
|
||||||
|
[[ -n "${OC_USERAGENT:-}" ]] && OPENCONNECT_CMD+=(--useragent "$OC_USERAGENT")
|
||||||
|
[[ -n "${OC_EXTRA_ARGS:-}" ]] && OPENCONNECT_CMD+=(${OC_EXTRA_ARGS})
|
||||||
|
|
||||||
|
exec openconnect-sso -s "$OC_URL" ${OC_SSO_ARGS:-$OC_SSO_ARGS_DEFAULT} -- "${OPENCONNECT_CMD[@]}"
|
||||||
27
apps/cloudbeaver/config.json
Executable file
27
apps/cloudbeaver/config.json
Executable file
@@ -0,0 +1,27 @@
|
|||||||
|
{
|
||||||
|
"name": "CloudBeaver",
|
||||||
|
"id": "cloudbeaver",
|
||||||
|
"available": true,
|
||||||
|
"short_desc": "Web-based database management platform",
|
||||||
|
"author": "DBeaver Corp",
|
||||||
|
"port": 8978,
|
||||||
|
"categories": [
|
||||||
|
"data",
|
||||||
|
"development"
|
||||||
|
],
|
||||||
|
"description": "CloudBeaver is a web-based database management platform. It provides a rich web interface for working with databases via web browser. Supports PostgreSQL, MySQL, MariaDB, SQL Server, Oracle, DB2, Firebird, SQLite, and many more databases.",
|
||||||
|
"tipi_version": 1,
|
||||||
|
"version": "25.2.5",
|
||||||
|
"source": "https://github.com/dbeaver/cloudbeaver",
|
||||||
|
"website": "https://cloudbeaver.io/",
|
||||||
|
"exposable": true,
|
||||||
|
"dynamic_config": true,
|
||||||
|
"no_gui": false,
|
||||||
|
"form_fields": [],
|
||||||
|
"supported_architectures": [
|
||||||
|
"arm64",
|
||||||
|
"amd64"
|
||||||
|
],
|
||||||
|
"created_at": 1732924800000,
|
||||||
|
"updated_at": 1732924800000
|
||||||
|
}
|
||||||
24
apps/cloudbeaver/docker-compose.json
Executable file
24
apps/cloudbeaver/docker-compose.json
Executable file
@@ -0,0 +1,24 @@
|
|||||||
|
{
|
||||||
|
"services": [
|
||||||
|
{
|
||||||
|
"name": "cloudbeaver",
|
||||||
|
"image": "dbeaver/cloudbeaver:25.2.5",
|
||||||
|
"isMain": true,
|
||||||
|
"internalPort": 8978,
|
||||||
|
"extraHosts": [
|
||||||
|
"host.docker.internal:host-gateway"
|
||||||
|
],
|
||||||
|
"environment": {
|
||||||
|
"CB_SERVER_NAME": "CloudBeaver",
|
||||||
|
"CB_ADMIN_NAME": "admin",
|
||||||
|
"CB_ADMIN_PASSWORD": "admin"
|
||||||
|
},
|
||||||
|
"volumes": [
|
||||||
|
{
|
||||||
|
"hostPath": "${APP_DATA_DIR}/data",
|
||||||
|
"containerPath": "/opt/cloudbeaver/workspace"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
46
apps/cloudbeaver/docker-compose.yml
Executable file
46
apps/cloudbeaver/docker-compose.yml
Executable file
@@ -0,0 +1,46 @@
|
|||||||
|
services:
|
||||||
|
cloudbeaver:
|
||||||
|
image: dbeaver/cloudbeaver:25.2.5
|
||||||
|
restart: unless-stopped
|
||||||
|
networks:
|
||||||
|
cloudbeaver_runtipi_network:
|
||||||
|
gw_priority: 0
|
||||||
|
tipi_main_network:
|
||||||
|
gw_priority: 1
|
||||||
|
extra_hosts:
|
||||||
|
- host.docker.internal:host-gateway
|
||||||
|
environment:
|
||||||
|
CB_SERVER_NAME: CloudBeaver
|
||||||
|
CB_ADMIN_NAME: admin
|
||||||
|
CB_ADMIN_PASSWORD: admin
|
||||||
|
ports:
|
||||||
|
- ${APP_PORT}:8978
|
||||||
|
volumes:
|
||||||
|
- ${APP_DATA_DIR}/data:/opt/cloudbeaver/workspace
|
||||||
|
labels:
|
||||||
|
generated: true
|
||||||
|
traefik.enable: true
|
||||||
|
traefik.docker.network: runtipi_tipi_main_network
|
||||||
|
traefik.http.middlewares.cloudbeaver-runtipi-web-redirect.redirectscheme.scheme: https
|
||||||
|
traefik.http.services.cloudbeaver-runtipi.loadbalancer.server.port: "8978"
|
||||||
|
traefik.http.routers.cloudbeaver-runtipi-insecure.rule: Host(`${APP_DOMAIN}`)
|
||||||
|
traefik.http.routers.cloudbeaver-runtipi-insecure.entrypoints: web
|
||||||
|
traefik.http.routers.cloudbeaver-runtipi-insecure.service: cloudbeaver-runtipi
|
||||||
|
traefik.http.routers.cloudbeaver-runtipi-insecure.middlewares: cloudbeaver-runtipi-web-redirect
|
||||||
|
traefik.http.routers.cloudbeaver-runtipi.rule: Host(`${APP_DOMAIN}`)
|
||||||
|
traefik.http.routers.cloudbeaver-runtipi.entrypoints: websecure
|
||||||
|
traefik.http.routers.cloudbeaver-runtipi.service: cloudbeaver-runtipi
|
||||||
|
traefik.http.routers.cloudbeaver-runtipi.tls.certresolver: myresolver
|
||||||
|
runtipi.managed: true
|
||||||
|
runtipi.appurn: cloudbeaver:runtipi
|
||||||
|
networks:
|
||||||
|
tipi_main_network:
|
||||||
|
name: runtipi_tipi_main_network
|
||||||
|
external: true
|
||||||
|
cloudbeaver_runtipi_network:
|
||||||
|
name: cloudbeaver_runtipi_network
|
||||||
|
external: false
|
||||||
|
ipam:
|
||||||
|
config:
|
||||||
|
- subnet: 10.128.18.0/24
|
||||||
|
|
||||||
27
apps/cloudbeaver/metadata/description.md
Executable file
27
apps/cloudbeaver/metadata/description.md
Executable file
@@ -0,0 +1,27 @@
|
|||||||
|
# CloudBeaver
|
||||||
|
|
||||||
|
CloudBeaver is a web-based database management platform that provides a rich web interface for working with databases directly from your browser.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- **Multi-Database Support**: Works with PostgreSQL, MySQL, MariaDB, SQL Server, Oracle, DB2, SQLite, Firebird, and many more
|
||||||
|
- **Web-Based Interface**: No desktop client needed - access from any modern web browser
|
||||||
|
- **Connection Management**: Easily manage multiple database connections
|
||||||
|
- **SQL Editor**: Full-featured SQL editor with syntax highlighting and autocomplete
|
||||||
|
- **Data Visualization**: View and edit data in intuitive table views
|
||||||
|
- **Query History**: Keep track of all your executed queries
|
||||||
|
- **User Management**: Multi-user support with role-based access control
|
||||||
|
- **Import/Export**: Import and export data in various formats
|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
After installation:
|
||||||
|
|
||||||
|
1. Access CloudBeaver at the configured port (default: **8978**)
|
||||||
|
2. Default credentials: **admin** / **admin**
|
||||||
|
3. Change the default password on first login
|
||||||
|
4. Create database connections to start managing your databases
|
||||||
|
|
||||||
|
## Connecting to Host Databases
|
||||||
|
|
||||||
|
To connect to databases running on your host machine, use **`host.docker.internal`** as the hostname in your connection settings.
|
||||||
BIN
apps/cloudbeaver/metadata/logo.jpg
Executable file
BIN
apps/cloudbeaver/metadata/logo.jpg
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
27
apps/nginx-proxy-manager/config.json
Executable file
27
apps/nginx-proxy-manager/config.json
Executable file
@@ -0,0 +1,27 @@
|
|||||||
|
{
|
||||||
|
"name": "Nginx Proxy Manager",
|
||||||
|
"id": "nginx-proxy-manager",
|
||||||
|
"available": true,
|
||||||
|
"short_desc": "Docker container for managing Nginx proxy hosts with a simple, powerful web interface",
|
||||||
|
"author": "jc21",
|
||||||
|
"port": 81,
|
||||||
|
"categories": [
|
||||||
|
"utilities",
|
||||||
|
"network"
|
||||||
|
],
|
||||||
|
"description": "Nginx Proxy Manager enables you to easily forward to your websites running at home or otherwise, including free SSL, without having to know too much about Nginx or Letsencrypt.",
|
||||||
|
"tipi_version": 1,
|
||||||
|
"version": "2.13.5",
|
||||||
|
"source": "https://github.com/NginxProxyManager/nginx-proxy-manager",
|
||||||
|
"website": "https://nginxproxymanager.com",
|
||||||
|
"exposable": true,
|
||||||
|
"dynamic_config": true,
|
||||||
|
"no_gui": false,
|
||||||
|
"form_fields": [],
|
||||||
|
"supported_architectures": [
|
||||||
|
"arm64",
|
||||||
|
"amd64"
|
||||||
|
],
|
||||||
|
"created_at": 1731607800000,
|
||||||
|
"updated_at": 1731607800000
|
||||||
|
}
|
||||||
37
apps/nginx-proxy-manager/docker-compose.json
Executable file
37
apps/nginx-proxy-manager/docker-compose.json
Executable file
@@ -0,0 +1,37 @@
|
|||||||
|
{
|
||||||
|
"schemaVersion": 2,
|
||||||
|
"services": [
|
||||||
|
{
|
||||||
|
"name": "nginx-proxy-manager",
|
||||||
|
"image": "jc21/nginx-proxy-manager:2.13.5",
|
||||||
|
"isMain": true,
|
||||||
|
"internalPort": 81,
|
||||||
|
"addPorts": [
|
||||||
|
{
|
||||||
|
"containerPort": 80,
|
||||||
|
"hostPort": 1080
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"containerPort": 443,
|
||||||
|
"hostPort": 10443
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"environment": [
|
||||||
|
{
|
||||||
|
"key": "DISABLE_IPV6",
|
||||||
|
"value": "true"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"volumes": [
|
||||||
|
{
|
||||||
|
"hostPath": "${APP_DATA_DIR}/data",
|
||||||
|
"containerPath": "/data"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"hostPath": "${APP_DATA_DIR}/letsencrypt",
|
||||||
|
"containerPath": "/etc/letsencrypt"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
45
apps/nginx-proxy-manager/docker-compose.yml
Executable file
45
apps/nginx-proxy-manager/docker-compose.yml
Executable file
@@ -0,0 +1,45 @@
|
|||||||
|
services:
|
||||||
|
nginx-proxy-manager:
|
||||||
|
image: jc21/nginx-proxy-manager:2.13.5
|
||||||
|
restart: unless-stopped
|
||||||
|
networks:
|
||||||
|
nginx-proxy-manager_runtipi_network:
|
||||||
|
gw_priority: 0
|
||||||
|
tipi_main_network:
|
||||||
|
gw_priority: 1
|
||||||
|
environment:
|
||||||
|
DISABLE_IPV6: "true"
|
||||||
|
ports:
|
||||||
|
- 1080:80
|
||||||
|
- 10443:443
|
||||||
|
- ${APP_PORT}:81
|
||||||
|
volumes:
|
||||||
|
- ${APP_DATA_DIR}/data:/data
|
||||||
|
- ${APP_DATA_DIR}/letsencrypt:/etc/letsencrypt
|
||||||
|
labels:
|
||||||
|
generated: true
|
||||||
|
traefik.enable: true
|
||||||
|
traefik.docker.network: runtipi_tipi_main_network
|
||||||
|
traefik.http.middlewares.nginx-proxy-manager-runtipi-web-redirect.redirectscheme.scheme: https
|
||||||
|
traefik.http.services.nginx-proxy-manager-runtipi.loadbalancer.server.port: "81"
|
||||||
|
traefik.http.routers.nginx-proxy-manager-runtipi-insecure.rule: Host(`${APP_DOMAIN}`)
|
||||||
|
traefik.http.routers.nginx-proxy-manager-runtipi-insecure.entrypoints: web
|
||||||
|
traefik.http.routers.nginx-proxy-manager-runtipi-insecure.service: nginx-proxy-manager-runtipi
|
||||||
|
traefik.http.routers.nginx-proxy-manager-runtipi-insecure.middlewares: nginx-proxy-manager-runtipi-web-redirect
|
||||||
|
traefik.http.routers.nginx-proxy-manager-runtipi.rule: Host(`${APP_DOMAIN}`)
|
||||||
|
traefik.http.routers.nginx-proxy-manager-runtipi.entrypoints: websecure
|
||||||
|
traefik.http.routers.nginx-proxy-manager-runtipi.service: nginx-proxy-manager-runtipi
|
||||||
|
traefik.http.routers.nginx-proxy-manager-runtipi.tls.certresolver: myresolver
|
||||||
|
runtipi.managed: true
|
||||||
|
runtipi.appurn: nginx-proxy-manager:runtipi
|
||||||
|
networks:
|
||||||
|
tipi_main_network:
|
||||||
|
name: runtipi_tipi_main_network
|
||||||
|
external: true
|
||||||
|
nginx-proxy-manager_runtipi_network:
|
||||||
|
name: nginx-proxy-manager_runtipi_network
|
||||||
|
external: false
|
||||||
|
ipam:
|
||||||
|
config:
|
||||||
|
- subnet: 10.128.11.0/24
|
||||||
|
|
||||||
108
apps/nginx-proxy-manager/metadata/description.md
Executable file
108
apps/nginx-proxy-manager/metadata/description.md
Executable file
@@ -0,0 +1,108 @@
|
|||||||
|
<p align="center">
|
||||||
|
<img src="https://nginxproxymanager.com/github.png">
|
||||||
|
<br><br>
|
||||||
|
<img src="https://img.shields.io/badge/version-2.13.5-green.svg?style=for-the-badge">
|
||||||
|
<a href="https://hub.docker.com/repository/docker/jc21/nginx-proxy-manager">
|
||||||
|
<img src="https://img.shields.io/docker/stars/jc21/nginx-proxy-manager.svg?style=for-the-badge">
|
||||||
|
</a>
|
||||||
|
<a href="https://hub.docker.com/repository/docker/jc21/nginx-proxy-manager">
|
||||||
|
<img src="https://img.shields.io/docker/pulls/jc21/nginx-proxy-manager.svg?style=for-the-badge">
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
This project comes as a pre-built docker image that enables you to easily forward to your websites
|
||||||
|
running at home or otherwise, including free SSL, without having to know too much about Nginx or Letsencrypt.
|
||||||
|
|
||||||
|
- [Quick Setup](#quick-setup)
|
||||||
|
- [Full Setup](https://nginxproxymanager.com/setup/)
|
||||||
|
- [Screenshots](https://nginxproxymanager.com/screenshots/)
|
||||||
|
|
||||||
|
## Project Goal
|
||||||
|
|
||||||
|
I created this project to fill a personal need to provide users with an easy way to accomplish reverse
|
||||||
|
proxying hosts with SSL termination and it had to be so easy that a monkey could do it. This goal hasn't changed.
|
||||||
|
While there might be advanced options they are optional and the project should be as simple as possible
|
||||||
|
so that the barrier for entry here is low.
|
||||||
|
|
||||||
|
<a href="https://www.buymeacoffee.com/jc21" target="_blank"><img src="http://public.jc21.com/github/by-me-a-coffee.png" alt="Buy Me A Coffee" style="height: 51px !important;width: 217px !important;" ></a>
|
||||||
|
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- Beautiful and Secure Admin Interface based on [Tabler](https://tabler.github.io/)
|
||||||
|
- Easily create forwarding domains, redirections, streams and 404 hosts without knowing anything about Nginx
|
||||||
|
- Free SSL using Let's Encrypt or provide your own custom SSL certificates
|
||||||
|
- Access Lists and basic HTTP Authentication for your hosts
|
||||||
|
- Advanced Nginx configuration available for super users
|
||||||
|
- User management, permissions and audit log
|
||||||
|
|
||||||
|
|
||||||
|
## Hosting your home network
|
||||||
|
|
||||||
|
I won't go in to too much detail here but here are the basics for someone new to this self-hosted world.
|
||||||
|
|
||||||
|
1. Your home router will have a Port Forwarding section somewhere. Log in and find it
|
||||||
|
2. Add port forwarding for port 80 and 443 to the server hosting this project
|
||||||
|
3. Configure your domain name details to point to your home, either with a static ip or a service like DuckDNS or [Amazon Route53](https://github.com/jc21/route53-ddns)
|
||||||
|
4. Use the Nginx Proxy Manager as your gateway to forward to your other web based services
|
||||||
|
|
||||||
|
## Quick Setup
|
||||||
|
|
||||||
|
1. Install Docker and Docker-Compose
|
||||||
|
|
||||||
|
- [Docker Install documentation](https://docs.docker.com/install/)
|
||||||
|
- [Docker-Compose Install documentation](https://docs.docker.com/compose/install/)
|
||||||
|
|
||||||
|
2. Create a docker-compose.yml file similar to this:
|
||||||
|
|
||||||
|
```yml
|
||||||
|
services:
|
||||||
|
app:
|
||||||
|
image: 'docker.io/jc21/nginx-proxy-manager:latest'
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- '80:80'
|
||||||
|
- '81:81'
|
||||||
|
- '443:443'
|
||||||
|
volumes:
|
||||||
|
- ./data:/data
|
||||||
|
- ./letsencrypt:/etc/letsencrypt
|
||||||
|
```
|
||||||
|
|
||||||
|
This is the bare minimum configuration required. See the [documentation](https://nginxproxymanager.com/setup/) for more.
|
||||||
|
|
||||||
|
3. Bring up your stack by running
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
4. Log in to the Admin UI
|
||||||
|
|
||||||
|
When your docker container is running, connect to it on port `81` for the admin interface.
|
||||||
|
Sometimes this can take a little bit because of the entropy of keys.
|
||||||
|
|
||||||
|
[http://127.0.0.1:81](http://127.0.0.1:81)
|
||||||
|
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
All are welcome to create pull requests for this project, against the `develop` branch. Official releases are created from the `master` branch.
|
||||||
|
|
||||||
|
CI is used in this project. All PR's must pass before being considered. After passing,
|
||||||
|
docker builds for PR's are available on dockerhub for manual verifications.
|
||||||
|
|
||||||
|
Documentation within the `develop` branch is available for preview at
|
||||||
|
[https://develop.nginxproxymanager.com](https://develop.nginxproxymanager.com)
|
||||||
|
|
||||||
|
|
||||||
|
### Contributors
|
||||||
|
|
||||||
|
Special thanks to [all of our contributors](https://github.com/NginxProxyManager/nginx-proxy-manager/graphs/contributors).
|
||||||
|
|
||||||
|
|
||||||
|
## Getting Support
|
||||||
|
|
||||||
|
1. [Found a bug?](https://github.com/NginxProxyManager/nginx-proxy-manager/issues)
|
||||||
|
2. [Discussions](https://github.com/NginxProxyManager/nginx-proxy-manager/discussions)
|
||||||
|
3. [Reddit](https://reddit.com/r/nginxproxymanager)
|
||||||
BIN
apps/nginx-proxy-manager/metadata/logo.jpg
Executable file
BIN
apps/nginx-proxy-manager/metadata/logo.jpg
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 56 KiB |
BIN
apps/nginx-proxy-manager/metadata/logo.png
Executable file
BIN
apps/nginx-proxy-manager/metadata/logo.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 56 KiB |
3
config.js
Executable file
3
config.js
Executable file
@@ -0,0 +1,3 @@
|
|||||||
|
export default {
|
||||||
|
allowedCommands: ["bun ./scripts/update-config.ts", "bun install && bun run test"],
|
||||||
|
};
|
||||||
293
package-lock.json
generated
Executable file
293
package-lock.json
generated
Executable file
@@ -0,0 +1,293 @@
|
|||||||
|
{
|
||||||
|
"name": "example-appstore",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"lockfileVersion": 3,
|
||||||
|
"requires": true,
|
||||||
|
"packages": {
|
||||||
|
"": {
|
||||||
|
"name": "example-appstore",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"@runtipi/common": "^0.8.0",
|
||||||
|
"bun": "^1.3.4",
|
||||||
|
"zod-validation-error": "^3.4.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/bun": "latest",
|
||||||
|
"@types/node": "^22.14.1"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"typescript": "^5.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@oven/bun-darwin-aarch64": {
|
||||||
|
"version": "1.3.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@oven/bun-darwin-aarch64/-/bun-darwin-aarch64-1.3.4.tgz",
|
||||||
|
"integrity": "sha512-2Ie4jDGvNGuPSD+pyyBKL8dJmX+bZfDNYEalwgROImVtwB1XYAatJK20dMaRlPA7jOhjvS9Io+4IZAJu7Js0AA==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"darwin"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"node_modules/@oven/bun-darwin-x64": {
|
||||||
|
"version": "1.3.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@oven/bun-darwin-x64/-/bun-darwin-x64-1.3.4.tgz",
|
||||||
|
"integrity": "sha512-4/BJojT8hk5g6Gecjn5yI7y96/+9Mtzsvdp9+2dcy9sTMdlV7jBvDzswqyJPZyQqw0F3HV3Vu9XuMubZwKd9lA==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"darwin"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"node_modules/@oven/bun-darwin-x64-baseline": {
|
||||||
|
"version": "1.3.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@oven/bun-darwin-x64-baseline/-/bun-darwin-x64-baseline-1.3.4.tgz",
|
||||||
|
"integrity": "sha512-ZYxzIOCDqylTMsnWYERjKMMuK2b4an4qbloBmUZTwLHmVzos00yrhtpitZhJBgH6yB/l4Q5eoJ2W98UKtFFeiQ==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"darwin"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"node_modules/@oven/bun-linux-aarch64": {
|
||||||
|
"version": "1.3.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@oven/bun-linux-aarch64/-/bun-linux-aarch64-1.3.4.tgz",
|
||||||
|
"integrity": "sha512-8DUIlanftMdFxLGq2FxwKwfrp8O4ZofF/8Oc6lxCyEFmg2hixbHhL04+fPfJIi5D4hZloynxZdwTeDbGv/Kc4A==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"node_modules/@oven/bun-linux-aarch64-musl": {
|
||||||
|
"version": "1.3.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@oven/bun-linux-aarch64-musl/-/bun-linux-aarch64-musl-1.3.4.tgz",
|
||||||
|
"integrity": "sha512-6UtmM4wXgRKz+gnLZEfddfsuBSVQpJr09K12e5pbdnLzeWgXYlBT5FG8S7SVn1t6cbgBMnigEsFjWwfTuMNoCw==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"node_modules/@oven/bun-linux-x64": {
|
||||||
|
"version": "1.3.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@oven/bun-linux-x64/-/bun-linux-x64-1.3.4.tgz",
|
||||||
|
"integrity": "sha512-03iSDMqdrmIFAsvsRptq+A7EGNjkg20dNzPnqxAlXHk5rc1PeIRWIP0eIn0i3nI6mmdj33mimf9AGr0+d0lKMg==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"node_modules/@oven/bun-linux-x64-baseline": {
|
||||||
|
"version": "1.3.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@oven/bun-linux-x64-baseline/-/bun-linux-x64-baseline-1.3.4.tgz",
|
||||||
|
"integrity": "sha512-ZMGPbFPqmG/VYJv61D+Y1V7T23jPK57vYl7yYLakmkTRjG6vcJ0Akhb2qR1iW94rHvfEBjeuVDAZBp8Qp9oyWA==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"node_modules/@oven/bun-linux-x64-musl": {
|
||||||
|
"version": "1.3.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@oven/bun-linux-x64-musl/-/bun-linux-x64-musl-1.3.4.tgz",
|
||||||
|
"integrity": "sha512-xUXPuJHndGhk4K3Cx1FgTyTgDZOn+ki3eWvdXYqKdfi0EaNA9KpUq+/vUtpJbZRjzpHs9L+OJcdDILq5H0LX4g==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"node_modules/@oven/bun-linux-x64-musl-baseline": {
|
||||||
|
"version": "1.3.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@oven/bun-linux-x64-musl-baseline/-/bun-linux-x64-musl-baseline-1.3.4.tgz",
|
||||||
|
"integrity": "sha512-qsGSSlNsxiX8lAayK2uYCfMLtqu776F0nn7qoyzg9Ti7mElM3woNh7RtGClTwQ6qsp5/UvgqT9g4pLaDHmqJFg==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"node_modules/@oven/bun-windows-x64": {
|
||||||
|
"version": "1.3.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@oven/bun-windows-x64/-/bun-windows-x64-1.3.4.tgz",
|
||||||
|
"integrity": "sha512-nswsuN6+HZPim6x4tFpDFpMa/qpTKfywbGvCkzxwrbJO9MtpuW/54NA1nFbHhpV14OLU0xuxyBj2PK4FHq4MlA==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"win32"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"node_modules/@oven/bun-windows-x64-baseline": {
|
||||||
|
"version": "1.3.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@oven/bun-windows-x64-baseline/-/bun-windows-x64-baseline-1.3.4.tgz",
|
||||||
|
"integrity": "sha512-ZQiSDFfSUdOrPTiL2GvkxlC/kMED4fsJwdZnwJK6S9ylXnk9xY/9ZXfe1615SFLQl2LsVRzJAtjQLeM0BifIKQ==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"win32"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"node_modules/@runtipi/common": {
|
||||||
|
"version": "0.8.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@runtipi/common/-/common-0.8.1.tgz",
|
||||||
|
"integrity": "sha512-x4K+Cn1LRsU1R0MyJBzAgjF457OyuJgi9RwcUhOpTSv6xPK+D8urM8qSQ9uLwK/2p/i2zGThxU6yUtsfkdnj/A==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"zod": "^3.25.30",
|
||||||
|
"zod-to-json-schema": "^3.24.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@types/bun": {
|
||||||
|
"version": "1.3.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/bun/-/bun-1.3.4.tgz",
|
||||||
|
"integrity": "sha512-EEPTKXHP+zKGPkhRLv+HI0UEX8/o+65hqARxLy8Ov5rIxMBPNTjeZww00CIihrIQGEQBYg+0roO5qOnS/7boGA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"bun-types": "1.3.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@types/node": {
|
||||||
|
"version": "22.19.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.2.tgz",
|
||||||
|
"integrity": "sha512-LPM2G3Syo1GLzXLGJAKdqoU35XvrWzGJ21/7sgZTUpbkBaOasTj8tjwn6w+hCkqaa1TfJ/w67rJSwYItlJ2mYw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"undici-types": "~6.21.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/bun": {
|
||||||
|
"version": "1.3.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/bun/-/bun-1.3.4.tgz",
|
||||||
|
"integrity": "sha512-xV6KgD5ImquuKsoghzbWmYzeCXmmSgN6yJGz444hri2W+NGKNRFUNrEhy9+/rRXbvNA2qF0K0jAwqFNy1/GhBg==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64",
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"os": [
|
||||||
|
"darwin",
|
||||||
|
"linux",
|
||||||
|
"win32"
|
||||||
|
],
|
||||||
|
"bin": {
|
||||||
|
"bun": "bin/bun.exe",
|
||||||
|
"bunx": "bin/bunx.exe"
|
||||||
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"@oven/bun-darwin-aarch64": "1.3.4",
|
||||||
|
"@oven/bun-darwin-x64": "1.3.4",
|
||||||
|
"@oven/bun-darwin-x64-baseline": "1.3.4",
|
||||||
|
"@oven/bun-linux-aarch64": "1.3.4",
|
||||||
|
"@oven/bun-linux-aarch64-musl": "1.3.4",
|
||||||
|
"@oven/bun-linux-x64": "1.3.4",
|
||||||
|
"@oven/bun-linux-x64-baseline": "1.3.4",
|
||||||
|
"@oven/bun-linux-x64-musl": "1.3.4",
|
||||||
|
"@oven/bun-linux-x64-musl-baseline": "1.3.4",
|
||||||
|
"@oven/bun-windows-x64": "1.3.4",
|
||||||
|
"@oven/bun-windows-x64-baseline": "1.3.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/bun-types": {
|
||||||
|
"version": "1.3.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/bun-types/-/bun-types-1.3.4.tgz",
|
||||||
|
"integrity": "sha512-5ua817+BZPZOlNaRgGBpZJOSAQ9RQ17pkwPD0yR7CfJg+r8DgIILByFifDTa+IPDDxzf5VNhtNlcKqFzDgJvlQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/typescript": {
|
||||||
|
"version": "5.9.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
|
||||||
|
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"peer": true,
|
||||||
|
"bin": {
|
||||||
|
"tsc": "bin/tsc",
|
||||||
|
"tsserver": "bin/tsserver"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.17"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/undici-types": {
|
||||||
|
"version": "6.21.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
|
||||||
|
"integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/zod": {
|
||||||
|
"version": "3.25.76",
|
||||||
|
"resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz",
|
||||||
|
"integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/colinhacks"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/zod-to-json-schema": {
|
||||||
|
"version": "3.25.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.25.0.tgz",
|
||||||
|
"integrity": "sha512-HvWtU2UG41LALjajJrML6uQejQhNJx+JBO9IflpSja4R03iNWfKXrj6W2h7ljuLyc1nKS+9yDyL/9tD1U/yBnQ==",
|
||||||
|
"license": "ISC",
|
||||||
|
"peerDependencies": {
|
||||||
|
"zod": "^3.25 || ^4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/zod-validation-error": {
|
||||||
|
"version": "3.5.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-3.5.4.tgz",
|
||||||
|
"integrity": "sha512-+hEiRIiPobgyuFlEojnqjJnhFvg4r/i3cqgcm67eehZf/WBaK3g6cD02YU9mtdVxZjv8CzCA9n/Rhrs3yAAvAw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"zod": "^3.24.4"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
25
package.json
Executable file
25
package.json
Executable file
@@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
"name": "example-appstore",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"main": "index.js",
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"test": "bun test"
|
||||||
|
},
|
||||||
|
"keywords": [],
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/bun": "latest",
|
||||||
|
"@types/node": "^22.14.1"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@runtipi/common": "^0.8.0",
|
||||||
|
"bun": "^1.2.10",
|
||||||
|
"zod-validation-error": "^3.4.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"typescript": "^5.0.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
62
renovate.json
Executable file
62
renovate.json
Executable file
@@ -0,0 +1,62 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||||
|
"automerge": false,
|
||||||
|
"extends": [
|
||||||
|
"config:recommended"
|
||||||
|
],
|
||||||
|
"addLabels": [
|
||||||
|
"renovate"
|
||||||
|
],
|
||||||
|
"enabledManagers": ["regex"],
|
||||||
|
"automergeStrategy": "rebase",
|
||||||
|
"customManagers": [
|
||||||
|
{
|
||||||
|
"customType": "regex",
|
||||||
|
"fileMatch": [
|
||||||
|
"^.*docker-compose\\.json$"
|
||||||
|
],
|
||||||
|
"matchStrings": [
|
||||||
|
"\"image\": \"(?<depName>.*?):(?<currentValue>.*?)\","
|
||||||
|
],
|
||||||
|
"datasourceTemplate": "docker"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"packageRules": [
|
||||||
|
{
|
||||||
|
"matchUpdateTypes": [
|
||||||
|
"minor",
|
||||||
|
"major",
|
||||||
|
"patch",
|
||||||
|
"pin",
|
||||||
|
"digest"
|
||||||
|
],
|
||||||
|
"automerge": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"matchDepTypes": [
|
||||||
|
"devDependencies"
|
||||||
|
],
|
||||||
|
"automerge": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"matchPackageNames": [
|
||||||
|
"mariadb",
|
||||||
|
"mysql",
|
||||||
|
"monogdb",
|
||||||
|
"postgres",
|
||||||
|
"redis"
|
||||||
|
],
|
||||||
|
"enabled": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"postUpgradeTasks": {
|
||||||
|
"commands": [
|
||||||
|
"bun ./scripts/update-config.ts {{packageFile}} {{newVersion}}",
|
||||||
|
"bun install && bun run test"
|
||||||
|
],
|
||||||
|
"fileFilters": [
|
||||||
|
"**/*"
|
||||||
|
],
|
||||||
|
"executionMode": "update"
|
||||||
|
}
|
||||||
|
}
|
||||||
35
scripts/update-config.ts
Executable file
35
scripts/update-config.ts
Executable file
@@ -0,0 +1,35 @@
|
|||||||
|
import path from "node:path";
|
||||||
|
import fs from "fs/promises";
|
||||||
|
|
||||||
|
const packageFile = process.argv[2];
|
||||||
|
const newVersion = process.argv[3];
|
||||||
|
|
||||||
|
type AppConfig = {
|
||||||
|
tipi_version: string;
|
||||||
|
version: string;
|
||||||
|
updated_at: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
const updateAppConfig = async (packageFile: string, newVersion: string) => {
|
||||||
|
try {
|
||||||
|
const packageRoot = path.dirname(packageFile);
|
||||||
|
const configPath = path.join(packageRoot, "config.json");
|
||||||
|
|
||||||
|
const config = await fs.readFile(configPath, "utf-8");
|
||||||
|
const configParsed = JSON.parse(config) as AppConfig;
|
||||||
|
|
||||||
|
configParsed.tipi_version = configParsed.tipi_version + 1;
|
||||||
|
configParsed.version = newVersion;
|
||||||
|
configParsed.updated_at = new Date().getTime();
|
||||||
|
|
||||||
|
await fs.writeFile(configPath, JSON.stringify(configParsed, null, 2));
|
||||||
|
} catch (e) {
|
||||||
|
console.error(`Failed to update app config, error: ${e}`);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!packageFile || !newVersion) {
|
||||||
|
console.error("Usage: node update-config.js <packageFile> <newVersion>");
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
updateAppConfig(packageFile, newVersion);
|
||||||
24
tsconfig.json
Executable file
24
tsconfig.json
Executable file
@@ -0,0 +1,24 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"target": "es2022",
|
||||||
|
"allowJs": true,
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"moduleDetection": "force",
|
||||||
|
"isolatedModules": true,
|
||||||
|
"verbatimModuleSyntax": true,
|
||||||
|
"strict": true,
|
||||||
|
"noUncheckedIndexedAccess": true,
|
||||||
|
"noImplicitOverride": true,
|
||||||
|
"module": "NodeNext",
|
||||||
|
"outDir": "dist",
|
||||||
|
"sourceMap": true,
|
||||||
|
"lib": [
|
||||||
|
"es2022"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"include": [
|
||||||
|
"**/*.ts",
|
||||||
|
],
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user