Add CT installers and metadata for six apps

Add container templates, install scripts and metadata for six applications: BirdNET-Go, ERPNext, Jitsi Meet, Storybook, Storyteller and Tube Archivist. New files include ct/* scripts (container templates and update handlers), install/* scripts (installation and systemd service setup, dependency installation and build steps) and json/* metadata entries (app catalog data, default resources, ports and notes). Each install script configures required dependencies, creates services, and prepares runtime configuration (e.g. DB, ElasticSearch, Node/Python environments, ffmpeg/Readium). This commit enables automated LXC provisioning and update flows for these apps.
This commit is contained in:
CanbiZ (MickLesk)
2026-03-25 10:21:42 +01:00
parent adcb155210
commit 9d21dfa112
18 changed files with 1135 additions and 0 deletions

60
ct/birdnet-go.sh Normal file
View File

@@ -0,0 +1,60 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
# Copyright (c) 2021-2026 community-scripts ORG
# Author: community-scripts
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://github.com/tphakala/birdnet-go
APP="BirdNET-Go"
var_tags="${var_tags:-monitoring;ai;nature}"
var_cpu="${var_cpu:-4}"
var_ram="${var_ram:-2048}"
var_disk="${var_disk:-12}"
var_os="${var_os:-debian}"
var_version="${var_version:-13}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -f /usr/local/bin/birdnet-go ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
if check_for_gh_release "birdnet-go" "tphakala/birdnet-go"; then
msg_info "Stopping Service"
systemctl stop birdnet-go
msg_ok "Stopped Service"
fetch_and_deploy_gh_release "birdnet-go" "tphakala/birdnet-go" "prebuild" "latest" "/opt/birdnet-go" "birdnet-go-linux-amd64.tar.gz"
msg_info "Deploying Binary"
cp /opt/birdnet-go/birdnet-go /usr/local/bin/birdnet-go
chmod +x /usr/local/bin/birdnet-go
msg_ok "Deployed Binary"
msg_info "Starting Service"
systemctl start birdnet-go
msg_ok "Started Service"
msg_ok "Updated successfully!"
fi
exit
}
start
build_container
description
msg_ok "Completed Successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:8080${CL}"

50
ct/erpnext.sh Normal file
View File

@@ -0,0 +1,50 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
# Copyright (c) 2021-2026 community-scripts ORG
# Author: community-scripts
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://github.com/frappe/erpnext
APP="ERPNext"
var_tags="${var_tags:-erp;business;accounting}"
var_cpu="${var_cpu:-4}"
var_ram="${var_ram:-4096}"
var_disk="${var_disk:-20}"
var_os="${var_os:-debian}"
var_version="${var_version:-13}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -d /opt/frappe-bench ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
msg_info "Updating ERPNext"
cd /opt/frappe-bench
$STD bench update --reset
msg_ok "Updated ERPNext"
exit
}
start
build_container
description
msg_ok "Completed Successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:8000${CL}"
echo -e "${INFO}${YW} Credentials:${CL}"
echo -e "${TAB}${BGN}Username: Administrator${CL}"
echo -e "${TAB}${BGN}Password: see /opt/frappe-bench/.env${CL}"

51
ct/jitsi.sh Normal file
View File

@@ -0,0 +1,51 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
# Copyright (c) 2021-2026 community-scripts ORG
# Author: community-scripts
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://jitsi.org/
APP="Jitsi Meet"
var_tags="${var_tags:-video;conference;communication}"
var_cpu="${var_cpu:-4}"
var_ram="${var_ram:-4096}"
var_disk="${var_disk:-12}"
var_os="${var_os:-debian}"
var_version="${var_version:-13}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -d /etc/jitsi ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
msg_info "Updating Jitsi Meet"
$STD apt update
$STD apt install -y --only-upgrade \
jitsi-meet \
jicofo \
jitsi-videobridge2 \
prosody
msg_ok "Updated Jitsi Meet"
exit
}
start
build_container
description
msg_ok "Completed Successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}https://${IP}${CL}"

54
ct/storybook.sh Normal file
View File

@@ -0,0 +1,54 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
# Copyright (c) 2021-2026 community-scripts ORG
# Author: community-scripts
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://github.com/storybookjs/storybook
APP="Storybook"
var_tags="${var_tags:-dev-tools;frontend;ui}"
var_cpu="${var_cpu:-2}"
var_ram="${var_ram:-2048}"
var_disk="${var_disk:-8}"
var_os="${var_os:-debian}"
var_version="${var_version:-13}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -f /opt/storybook/.projectpath ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
PROJECT_PATH=$(cat /opt/storybook/.projectpath)
if [[ ! -d "$PROJECT_PATH" ]]; then
msg_error "Project directory not found: $PROJECT_PATH"
exit
fi
msg_info "Updating Storybook"
cd "$PROJECT_PATH"
$STD npx storybook@latest upgrade --yes
msg_ok "Updated Storybook"
exit
}
start
build_container
description
msg_ok "Completed Successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:6006${CL}"

67
ct/storyteller.sh Normal file
View File

@@ -0,0 +1,67 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
# Copyright (c) 2021-2026 community-scripts ORG
# Author: community-scripts
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://gitlab.com/storyteller-platform/storyteller
APP="Storyteller"
var_tags="${var_tags:-media;ebook;audiobook}"
var_cpu="${var_cpu:-4}"
var_ram="${var_ram:-8192}"
var_disk="${var_disk:-16}"
var_os="${var_os:-debian}"
var_version="${var_version:-13}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -d /opt/storyteller ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
msg_info "Stopping Service"
systemctl stop storyteller
msg_ok "Stopped Service"
msg_info "Backing up Data"
cp /opt/storyteller/.env /opt/storyteller_env.bak
msg_ok "Backed up Data"
CLEAN_INSTALL=1 fetch_and_deploy_gl_release "storyteller" "storyteller-platform/storyteller" "tarball" "latest" "/opt/storyteller"
msg_info "Rebuilding Storyteller"
cd /opt/storyteller
$STD yarn install
$STD yarn workspaces foreach -Rpt --from @storyteller-platform/web --exclude @storyteller-platform/eslint run build
msg_ok "Rebuilt Storyteller"
msg_info "Restoring Configuration"
mv /opt/storyteller_env.bak /opt/storyteller/.env
msg_ok "Restored Configuration"
msg_info "Starting Service"
systemctl start storyteller
msg_ok "Started Service"
msg_ok "Updated successfully!"
exit
}
start
build_container
description
msg_ok "Completed Successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:8001${CL}"

77
ct/tubearchivist.sh Normal file
View File

@@ -0,0 +1,77 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
# Copyright (c) 2021-2026 community-scripts ORG
# Author: community-scripts
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://github.com/tubearchivist/tubearchivist
APP="Tube Archivist"
var_tags="${var_tags:-media;youtube;archiving}"
var_cpu="${var_cpu:-4}"
var_ram="${var_ram:-6144}"
var_disk="${var_disk:-30}"
var_os="${var_os:-debian}"
var_version="${var_version:-13}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -d /opt/tubearchivist ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
if check_for_gh_release "tubearchivist" "tubearchivist/tubearchivist"; then
msg_info "Stopping Service"
systemctl stop tubearchivist
msg_ok "Stopped Service"
msg_info "Backing up Data"
cp /opt/tubearchivist/.env /opt/tubearchivist_env.bak
msg_ok "Backed up Data"
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "tubearchivist" "tubearchivist/tubearchivist" "tarball" "latest" "/opt/tubearchivist"
msg_info "Rebuilding Tube Archivist"
cd /opt/tubearchivist/frontend
$STD npm install
$STD npm run build:deploy
mkdir -p /opt/tubearchivist/backend/static
cp -r /opt/tubearchivist/frontend/dist/* /opt/tubearchivist/backend/static/
cp /opt/tubearchivist/docker_assets/backend_start.py /opt/tubearchivist/backend/
$STD uv pip install --python /opt/tubearchivist/.venv/bin/python -r /opt/tubearchivist/backend/requirements.txt
if [[ -f /opt/tubearchivist/backend/requirements.plugins.txt ]]; then
mkdir -p /opt/yt_plugins/bgutil
$STD uv pip install --python /opt/tubearchivist/.venv/bin/python --target /opt/yt_plugins/bgutil -r /opt/tubearchivist/backend/requirements.plugins.txt
fi
msg_ok "Rebuilt Tube Archivist"
msg_info "Restoring Configuration"
mv /opt/tubearchivist_env.bak /opt/tubearchivist/.env
msg_ok "Restored Configuration"
msg_info "Starting Service"
systemctl start tubearchivist
msg_ok "Started Service"
msg_ok "Updated successfully!"
fi
exit
}
start
build_container
description
msg_ok "Completed Successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:8000${CL}"

View File

@@ -0,0 +1,55 @@
#!/usr/bin/env bash
# Copyright (c) 2021-2026 community-scripts ORG
# Author: community-scripts
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://github.com/tphakala/birdnet-go
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
color
verb_ip6
catch_errors
setting_up_container
network_check
update_os
msg_info "Installing Dependencies"
$STD apt install -y \
libasound2 \
sox \
alsa-utils
msg_ok "Installed Dependencies"
setup_ffmpeg
fetch_and_deploy_gh_release "birdnet-go" "tphakala/birdnet-go" "prebuild" "latest" "/opt/birdnet-go" "birdnet-go-linux-amd64.tar.gz"
msg_info "Setting up BirdNET-Go"
cp /opt/birdnet-go/birdnet-go /usr/local/bin/birdnet-go
chmod +x /usr/local/bin/birdnet-go
mkdir -p /opt/birdnet-go/data/clips
msg_ok "Set up BirdNET-Go"
msg_info "Creating Service"
cat <<EOF >/etc/systemd/system/birdnet-go.service
[Unit]
Description=BirdNET-Go
After=network.target
[Service]
Type=simple
User=root
WorkingDirectory=/opt/birdnet-go/data
ExecStart=/usr/local/bin/birdnet-go realtime
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
systemctl enable -q --now birdnet-go
msg_ok "Created Service"
motd_ssh
customize
cleanup_lxc

106
install/erpnext-install.sh Normal file
View File

@@ -0,0 +1,106 @@
#!/usr/bin/env bash
# Copyright (c) 2021-2026 community-scripts ORG
# Author: community-scripts
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://github.com/frappe/erpnext
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
color
verb_ip6
catch_errors
setting_up_container
network_check
update_os
msg_info "Installing Dependencies"
$STD apt install -y \
git \
build-essential \
libffi-dev \
libssl-dev \
redis-server \
xvfb \
libfontconfig1 \
libxrender1 \
fontconfig \
libjpeg-dev \
libmariadb-dev
msg_ok "Installed Dependencies"
NODE_VERSION="22" NODE_MODULE="yarn" setup_nodejs
UV_PYTHON="3.13" setup_uv
setup_mariadb
msg_info "Configuring MariaDB for ERPNext"
cat <<EOF >/etc/mysql/mariadb.conf.d/50-erpnext.cnf
[mysqld]
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci
[client]
default-character-set=utf8mb4
EOF
$STD systemctl restart mariadb
msg_ok "Configured MariaDB for ERPNext"
msg_info "Installing wkhtmltopdf"
WKHTMLTOPDF_URL="https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6.1-3/wkhtmltox_0.12.6.1-3.bookworm_amd64.deb"
$STD curl -fsSL -o /tmp/wkhtmltox.deb "$WKHTMLTOPDF_URL"
$STD apt install -y /tmp/wkhtmltox.deb
rm -f /tmp/wkhtmltox.deb
msg_ok "Installed wkhtmltopdf"
msg_info "Installing Frappe Bench"
$STD uv tool install frappe-bench
msg_ok "Installed Frappe Bench"
msg_info "Initializing Frappe Bench"
ADMIN_PASS=$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | head -c13)
cd /opt
$STD bench init --frappe-branch version-15 frappe-bench
cd /opt/frappe-bench
$STD bench get-app erpnext --branch version-15
$STD bench new-site site1.local \
--db-root-username root \
--admin-password "$ADMIN_PASS" \
--install-app erpnext \
--set-default
msg_ok "Initialized Frappe Bench"
msg_info "Configuring ERPNext"
cat <<EOF >/opt/frappe-bench/.env
ADMIN_PASSWORD=${ADMIN_PASS}
SITE_NAME=site1.local
EOF
$STD systemctl enable --now redis-server
msg_ok "Configured ERPNext"
msg_info "Setting up Production"
$STD bench setup production root --yes
msg_ok "Set up Production"
msg_info "Creating Service"
cat <<EOF >/etc/systemd/system/erpnext.service
[Unit]
Description=ERPNext (Frappe Bench)
After=network.target mariadb.service redis-server.service
[Service]
Type=simple
User=root
WorkingDirectory=/opt/frappe-bench
ExecStart=/opt/frappe-bench/env/bin/gunicorn --bind 0.0.0.0:8000 --workers 4 --timeout 120 frappe.app:application
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
systemctl enable -q --now erpnext
msg_ok "Created Service"
motd_ssh
customize
cleanup_lxc

40
install/jitsi-install.sh Normal file
View File

@@ -0,0 +1,40 @@
#!/usr/bin/env bash
# Copyright (c) 2021-2026 community-scripts ORG
# Author: community-scripts
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://jitsi.org/
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
color
verb_ip6
catch_errors
setting_up_container
network_check
update_os
msg_info "Installing Dependencies"
$STD apt install -y nginx
msg_ok "Installed Dependencies"
source /etc/os-release
setup_deb822_repo "prosody" "https://prosody.im/files/prosody-debian-packages.key" "http://packages.prosody.im/debian" "${VERSION_CODENAME}" "main"
setup_deb822_repo "jitsi" "https://download.jitsi.org/jitsi-key.gpg.key" "https://download.jitsi.org/stable" "./"
msg_info "Installing Jitsi Meet"
echo "jitsi-videobridge2 jitsi-videobridge/jvb-hostname string ${LOCAL_IP}" | debconf-set-selections
echo "jitsi-meet-web-config jitsi-meet/cert-choice select Generate a new self-signed certificate" | debconf-set-selections
DEBIAN_FRONTEND=noninteractive $STD apt install -y jitsi-meet
msg_ok "Installed Jitsi Meet"
msg_info "Configuring Network"
cat <<EOF >/etc/sysctl.d/99-jitsi.conf
net.core.rmem_max=10485760
net.core.netdev_max_backlog=100000
EOF
$STD sysctl -p /etc/sysctl.d/99-jitsi.conf
msg_ok "Configured Network"
motd_ssh
customize
cleanup_lxc

View File

@@ -0,0 +1,54 @@
#!/usr/bin/env bash
# Copyright (c) 2021-2026 community-scripts ORG
# Author: community-scripts
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://github.com/storybookjs/storybook
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
color
verb_ip6
catch_errors
setting_up_container
network_check
update_os
NODE_VERSION="22" NODE_MODULE="pnpm" setup_nodejs
msg_info "Preparing Storybook"
mkdir -p /opt/storybook
cd /opt/storybook
msg_ok "Important: Interactive configuration will start now."
npx storybook@latest init --yes
PROJECT_PATH=$(find /opt/storybook -maxdepth 2 -name ".storybook" -type d 2>/dev/null | head -n1 | xargs dirname)
if [[ -z "$PROJECT_PATH" ]]; then
PROJECT_PATH="/opt/storybook"
fi
echo "$PROJECT_PATH" >/opt/storybook/.projectpath
msg_info "Creating Service"
cat <<EOF >/etc/systemd/system/storybook.service
[Unit]
Description=Storybook Dev Server
After=network.target
[Service]
Type=simple
User=root
WorkingDirectory=${PROJECT_PATH}
ExecStart=/usr/bin/npx storybook dev --host 0.0.0.0 --port 6006 --no-open
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
systemctl enable -q --now storybook
msg_ok "Created Service"
motd_ssh
customize
cleanup_lxc

View File

@@ -0,0 +1,85 @@
#!/usr/bin/env bash
# Copyright (c) 2021-2026 community-scripts ORG
# Author: community-scripts
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://gitlab.com/storyteller-platform/storyteller
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
color
verb_ip6
catch_errors
setting_up_container
network_check
update_os
msg_info "Installing Dependencies"
$STD apt install -y \
build-essential \
git \
libsqlite3-dev \
python3
msg_ok "Installed Dependencies"
NODE_VERSION="22" NODE_MODULE="yarn" setup_nodejs
setup_ffmpeg
msg_info "Installing Readium"
READIUM_VERSION="0.6.5"
mkdir -p /opt/readium
$STD curl -fsSL "https://github.com/readium/go-toolkit/releases/download/${READIUM_VERSION}/readium-x86_64-linux" -o /opt/readium/readium
chmod +x /opt/readium/readium
ln -sf /opt/readium /usr/local/bin/readium
msg_ok "Installed Readium"
fetch_and_deploy_gl_release "storyteller" "storyteller-platform/storyteller" "tarball" "latest" "/opt/storyteller"
msg_info "Setting up Storyteller"
cd /opt/storyteller
$STD yarn install
$STD gcc -g -fPIC -rdynamic -shared web/sqlite/uuid.c -o web/sqlite/uuid.c.so
STORYTELLER_SECRET_KEY=$(openssl rand -base64 32)
cat <<EOF >/opt/storyteller/.env
STORYTELLER_SECRET_KEY=${STORYTELLER_SECRET_KEY}
STORYTELLER_DATA_DIR=/opt/storyteller/data
PORT=8001
HOSTNAME=0.0.0.0
READIUM_PORT=9000
NODE_ENV=production
NEXT_TELEMETRY_DISABLED=1
EOF
mkdir -p /opt/storyteller/data
msg_ok "Set up Storyteller"
msg_info "Building Storyteller"
cd /opt/storyteller
export NODE_ENV=production
export NEXT_TELEMETRY_DISABLED=1
export SQLITE_NATIVE_BINDING=/opt/storyteller/node_modules/better-sqlite3/build/Release/better_sqlite3.node
$STD yarn workspaces foreach -Rpt --from @storyteller-platform/web --exclude @storyteller-platform/eslint run build
msg_ok "Built Storyteller"
msg_info "Creating Service"
cat <<EOF >/etc/systemd/system/storyteller.service
[Unit]
Description=Storyteller
After=network.target
[Service]
Type=simple
User=root
WorkingDirectory=/opt/storyteller/.next/standalone/web
EnvironmentFile=/opt/storyteller/.env
ExecStart=/usr/bin/node --enable-source-maps server.js
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
systemctl enable -q --now storyteller
msg_ok "Created Service"
motd_ssh
customize
cleanup_lxc

View File

@@ -0,0 +1,148 @@
#!/usr/bin/env bash
# Copyright (c) 2021-2026 community-scripts ORG
# Author: community-scripts
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://github.com/tubearchivist/tubearchivist
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
color
verb_ip6
catch_errors
setting_up_container
network_check
update_os
msg_info "Installing Dependencies"
$STD apt install -y \
build-essential \
git \
nginx \
redis-server \
atomicparsley \
libldap2-dev \
libsasl2-dev \
libssl-dev
msg_ok "Installed Dependencies"
UV_PYTHON="3.13" setup_uv
NODE_VERSION="22" setup_nodejs
setup_ffmpeg
fetch_and_deploy_gh_release "deno" "denoland/deno" "prebuild" "latest" "/usr/local/bin" "deno-x86_64-unknown-linux-gnu.zip"
msg_info "Installing ElasticSearch"
setup_deb822_repo "elastic-8.x" "https://artifacts.elastic.co/GPG-KEY-elasticsearch" "https://artifacts.elastic.co/packages/8.x/apt" "stable" "main"
$STD apt install -y elasticsearch
msg_ok "Installed ElasticSearch"
msg_info "Configuring ElasticSearch"
cat <<EOF >/etc/elasticsearch/elasticsearch.yml
cluster.name: tubearchivist
path.data: /var/lib/elasticsearch
path.logs: /var/log/elasticsearch
path.repo: ["/var/lib/elasticsearch/snapshot"]
network.host: 127.0.0.1
xpack.security.enabled: false
EOF
mkdir -p /var/lib/elasticsearch/snapshot
chown -R elasticsearch:elasticsearch /var/lib/elasticsearch/snapshot
cat <<EOF >/etc/elasticsearch/jvm.options.d/heap.options
-Xms1g
-Xmx1g
EOF
sysctl -w vm.max_map_count=262144 2>/dev/null || true
cat <<EOF >/etc/sysctl.d/99-elasticsearch.conf
vm.max_map_count=262144
EOF
systemctl enable -q --now elasticsearch
msg_ok "Configured ElasticSearch"
fetch_and_deploy_gh_release "tubearchivist" "tubearchivist/tubearchivist" "tarball" "latest" "/opt/tubearchivist"
msg_info "Building Frontend"
cd /opt/tubearchivist/frontend
$STD npm install
$STD npm run build:deploy
mkdir -p /opt/tubearchivist/backend/static
cp -r /opt/tubearchivist/frontend/dist/* /opt/tubearchivist/backend/static/
msg_ok "Built Frontend"
msg_info "Setting up Tube Archivist"
cp /opt/tubearchivist/docker_assets/backend_start.py /opt/tubearchivist/backend/
$STD uv venv /opt/tubearchivist/.venv
$STD uv pip install --python /opt/tubearchivist/.venv/bin/python -r /opt/tubearchivist/backend/requirements.txt
if [[ -f /opt/tubearchivist/backend/requirements.plugins.txt ]]; then
mkdir -p /opt/yt_plugins/bgutil
$STD uv pip install --python /opt/tubearchivist/.venv/bin/python --target /opt/yt_plugins/bgutil -r /opt/tubearchivist/backend/requirements.plugins.txt
fi
TA_PASSWORD=$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | head -c13)
ES_PASSWORD=$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | head -c13)
cat <<EOF >/opt/tubearchivist/.env
TA_HOST=http://${LOCAL_IP}:8000
TA_USERNAME=admin
TA_PASSWORD=${TA_PASSWORD}
TA_PORT=8000
TA_BACKEND_PORT=8100
ELASTIC_PASSWORD=${ES_PASSWORD}
REDIS_CON=redis://localhost:6379
ES_URL=http://localhost:9200
TZ=UTC
PYTHONUNBUFFERED=1
YTDLP_PLUGIN_DIRS=/opt/yt_plugins
EOF
$STD systemctl enable --now redis-server
msg_ok "Set up Tube Archivist"
msg_info "Configuring Nginx"
cat <<'EOF' >/etc/nginx/sites-available/tubearchivist
server {
listen 8000;
server_name _;
client_max_body_size 5G;
location /static/ {
alias /opt/tubearchivist/backend/static/;
expires 1y;
}
location / {
proxy_pass http://127.0.0.1:8100;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_read_timeout 1800;
}
}
EOF
ln -sf /etc/nginx/sites-available/tubearchivist /etc/nginx/sites-enabled/tubearchivist
rm -f /etc/nginx/sites-enabled/default
$STD systemctl restart nginx
msg_ok "Configured Nginx"
msg_info "Creating Service"
cat <<EOF >/etc/systemd/system/tubearchivist.service
[Unit]
Description=Tube Archivist
After=network.target elasticsearch.service redis-server.service
[Service]
Type=simple
User=root
WorkingDirectory=/opt/tubearchivist/backend
EnvironmentFile=/opt/tubearchivist/.env
Environment=PATH=/opt/tubearchivist/.venv/bin:/usr/local/bin:/usr/bin:/bin
ExecStart=/opt/tubearchivist/.venv/bin/python backend_start.py
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
systemctl enable -q --now tubearchivist
msg_ok "Created Service"
motd_ssh
customize
cleanup_lxc

48
json/birdnet-go.json Normal file
View File

@@ -0,0 +1,48 @@
{
"name": "BirdNET-Go",
"slug": "birdnet-go",
"categories": [
9
],
"date_created": "2026-03-25",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 8080,
"documentation": "https://github.com/tphakala/birdnet-go/wiki",
"website": "https://github.com/tphakala/birdnet-go",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/birdnet-go.webp",
"config_path": "/opt/birdnet-go/data",
"description": "BirdNET-Go is an AI-powered solution for continuous avian monitoring and identification, providing 24/7 realtime bird song analysis.",
"install_methods": [
{
"type": "default",
"script": "ct/birdnet-go.sh",
"resources": {
"cpu": 4,
"ram": 2048,
"hdd": 12,
"os": "Debian",
"version": "13"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": [
{
"text": "Audio device passthrough is required for realtime monitoring. Add the audio device to the LXC configuration.",
"type": "warning"
},
{
"text": "Data and recordings are stored in `/opt/birdnet-go/data`.",
"type": "info"
},
{
"text": "GPU acceleration is not available in the LXC version. CPU-based transcription is used.",
"type": "info"
}
]
}

48
json/erpnext.json Normal file
View File

@@ -0,0 +1,48 @@
{
"name": "ERPNext",
"slug": "erpnext",
"categories": [
25
],
"date_created": "2026-03-25",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 8000,
"documentation": "https://docs.erpnext.com/",
"website": "https://erpnext.com/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/erpnext.webp",
"config_path": "/opt/frappe-bench/.env",
"description": "ERPNext is a powerful, intuitive and open-source ERP system for managing accounting, inventory, manufacturing, CRM, projects, HR and more.",
"install_methods": [
{
"type": "default",
"script": "ct/erpnext.sh",
"resources": {
"cpu": 4,
"ram": 4096,
"hdd": 20,
"os": "Debian",
"version": "13"
}
}
],
"default_credentials": {
"username": "Administrator",
"password": null
},
"notes": [
{
"text": "Admin password is stored in `/opt/frappe-bench/.env`.",
"type": "info"
},
{
"text": "The default site name is `site1.local`. Configure your domain in Frappe settings.",
"type": "info"
},
{
"text": "Run `bench update` from `/opt/frappe-bench` to update ERPNext manually.",
"type": "info"
}
]
}

48
json/jitsi.json Normal file
View File

@@ -0,0 +1,48 @@
{
"name": "Jitsi Meet",
"slug": "jitsi",
"categories": [
0
],
"date_created": "2026-03-25",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 443,
"documentation": "https://jitsi.github.io/handbook/",
"website": "https://jitsi.org/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/jitsi.webp",
"config_path": "/etc/jitsi",
"description": "Jitsi Meet is a set of open-source projects for secure, simple and scalable video conferences with state-of-the-art video quality and features.",
"install_methods": [
{
"type": "default",
"script": "ct/jitsi.sh",
"resources": {
"cpu": 4,
"ram": 4096,
"hdd": 12,
"os": "Debian",
"version": "13"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": [
{
"text": "Uses a self-signed certificate by default. Your browser will show a security warning.",
"type": "info"
},
{
"text": "Port 10000/UDP must be forwarded to the container for video/audio to work properly.",
"type": "warning"
},
{
"text": "Configuration files are located in `/etc/jitsi/`.",
"type": "info"
}
]
}

44
json/storybook.json Normal file
View File

@@ -0,0 +1,44 @@
{
"name": "Storybook",
"slug": "storybook",
"categories": [
20
],
"date_created": "2026-03-25",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 6006,
"documentation": "https://storybook.js.org/docs",
"website": "https://storybook.js.org/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/storybook.webp",
"config_path": "",
"description": "Storybook is a frontend workshop for building UI components and pages in isolation. It's used for UI development, testing, and documentation.",
"install_methods": [
{
"type": "default",
"script": "ct/storybook.sh",
"resources": {
"cpu": 2,
"ram": 2048,
"hdd": 8,
"os": "Debian",
"version": "13"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": [
{
"text": "The installer uses an interactive setup wizard (like fumadocs). Follow the prompts during installation.",
"type": "info"
},
{
"text": "Storybook runs in development mode on port 6006.",
"type": "info"
}
]
}

48
json/storyteller.json Normal file
View File

@@ -0,0 +1,48 @@
{
"name": "Storyteller",
"slug": "storyteller",
"categories": [
13
],
"date_created": "2026-03-25",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 8001,
"documentation": "https://storyteller-platform.dev/docs/welcome",
"website": "https://storyteller-platform.dev/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/storyteller.webp",
"config_path": "/opt/storyteller/.env",
"description": "Storyteller is a self-hosted platform for creating and reading ebooks with synced narration, combining audiobooks and ebooks with automatic synchronization.",
"install_methods": [
{
"type": "default",
"script": "ct/storyteller.sh",
"resources": {
"cpu": 4,
"ram": 8192,
"hdd": 16,
"os": "Debian",
"version": "13"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": [
{
"text": "Minimum 8GB RAM recommended. AI-based transcription is resource-intensive.",
"type": "warning"
},
{
"text": "Secret key is stored in `/opt/storyteller/.env`.",
"type": "info"
},
{
"text": "GPU acceleration is not available in the LXC version. Use CPU-based transcription.",
"type": "info"
}
]
}

52
json/tubearchivist.json Normal file
View File

@@ -0,0 +1,52 @@
{
"name": "Tube Archivist",
"slug": "tubearchivist",
"categories": [
13
],
"date_created": "2026-03-25",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 8000,
"documentation": "https://docs.tubearchivist.com/",
"website": "https://github.com/tubearchivist/tubearchivist",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/tube-archivist.webp",
"config_path": "/opt/tubearchivist/.env",
"description": "Tube Archivist is a self-hosted YouTube media collection manager that indexes your video collection with metadata for organizing, searching, and playing archived YouTube videos offline.",
"install_methods": [
{
"type": "default",
"script": "ct/tubearchivist.sh",
"resources": {
"cpu": 4,
"ram": 6144,
"hdd": 30,
"os": "Debian",
"version": "13"
}
}
],
"default_credentials": {
"username": "admin",
"password": null
},
"notes": [
{
"text": "Requires `vm.max_map_count=262144` on the Proxmox host. Run `sysctl -w vm.max_map_count=262144` on the host and add it to `/etc/sysctl.conf` for persistence.",
"type": "warning"
},
{
"text": "ElasticSearch is configured with 1GB heap. Adjust `/etc/elasticsearch/jvm.options.d/heap.options` for larger collections.",
"type": "info"
},
{
"text": "Admin password is stored in `/opt/tubearchivist/.env`.",
"type": "info"
},
{
"text": "Minimum 6GB RAM recommended. ElasticSearch alone requires 2GB+.",
"type": "warning"
}
]
}