diff --git a/.claude/HISTORY.md b/.claude/HISTORY.md index 6ade3dea..e8a58683 100644 --- a/.claude/HISTORY.md +++ b/.claude/HISTORY.md @@ -1,6 +1,6 @@ # SecuBox UI & Theme History -_Last updated: 2026-03-09 (HAProxy Routes Health Check, WAF Routing)_ +_Last updated: 2026-03-11 (RezApp Forge, Streamlit Forge)_ 1. **Unified Dashboard Refresh (2025-12-20)** - Dashboard received the "sh-page-header" layout, hero stats, and SecuNav top tabs. @@ -4531,3 +4531,78 @@ git checkout HEAD -- index.html - Modified haproxy_router.py to allow port 8081 routes (was blocked) - Domain now accessible via HTTPS through WAF with proper access control - Web Terminal (ttyd shell access) + +81. **RezApp Forge - Docker to SecuBox App Converter (2026-03-11)** + - Package: `secubox-app-rezapp` with `rezappctl` CLI + - UCI configuration: `/etc/config/rezapp` with catalog sources + - Supported catalogs: Docker Hub, LinuxServer.io, GitHub Container Registry + - CLI commands: + - `rezappctl catalog list/add/remove` - Manage catalog sources + - `rezappctl search ` - Search Docker images across catalogs + - `rezappctl info ` - Show image details (tags, arch, ENV) + - `rezappctl convert ` - Docker → LXC conversion + - `rezappctl package ` - Generate SecuBox package structure + - `rezappctl publish ` - Add to SecuBox addon catalog + - Conversion workflow: pull → export → extract → generate LXC config + - Templates: Makefile.tpl, init.d.tpl, ctl.tpl, config.tpl, start-lxc.tpl, lxc-config.tpl, manifest.tpl + - Auto-generates procd init scripts, management CLIs, and UCI configs + - Enables one-command Docker app deployment: convert → package → install + +82. **Streamlit Forge Plan (2026-03-11)** + - Comprehensive Streamlit app publishing platform specification + - Features planned: + - App upload and source management via Gitea + - Multiple running instances with isolated configs + - Auto-publishing to SecuBox dedicated spaces + - Miniature preview/thumbnail generation + - UCI configuration synchronization + - Mesh AppStore publishing + - Author workspace with blog integration + - Templates: basic, dashboard, data-viewer, research-paper, slides, portfolio + - Integration with: Gitea, HAProxy, Mitmproxy, MetaBlogizer, SecuBox P2P + - Plan: `/home/reepost/.claude/plans/streamlit-forge.md` + +83. **HAProxy Vhost Rename Feature (2026-03-11)** + - Added `haproxyctl vhost rename ` command + - Renames vhost UCI section and all related configurations + - Tested: MC360_Streamlit_BPM_v2.gk2.secubox.in → mc360.gk2.secubox.in + +84. **Streamlit Forge - App Publishing Platform (2026-03-11)** + - Package: `secubox-app-streamlit-forge` with `slforge` CLI + - UCI configuration at `/etc/config/streamlit-forge` + - 3 app templates: basic, dashboard, data-viewer + - CLI commands: + - `slforge create --from-template ` - Create from template + - `slforge start/stop/restart ` - Instance control + - `slforge status/info/list` - Status and information + - `slforge expose --domain ` - HAProxy vhost + SSL + - `slforge publish/unpublish ` - Mesh catalog management + - Runs apps in Streamlit LXC container (mount: /srv/apps/) + - Port-based status detection (works across LXC namespaces) + - Wrapper script approach for reliable container execution + - LuCI: `luci-app-streamlit-forge` with RPCD backend + - Status dashboard with running/total/LXC cards + - Create dialog with template selection + - App table with Start/Stop/Open/Expose/Publish/Delete actions + - Auto-refresh polling (10s interval) + +85. **RezApp Forge LuCI Dashboard (2026-03-11)** + - Package: `luci-app-rezapp` with RPCD backend + - Menu: Services > RezApp Forge + - Features: + - Status cards (converted apps, catalogs, Docker status) + - Docker Hub search with star ratings and descriptions + - Convert dialog (name, tag, memory options) + - Converted apps table with Package/Publish/Delete actions + - RPCD methods: status, catalogs, apps, search, info, convert, package, publish, delete + - ACL permissions for read/write operations + +86. **SecuBox KISS Apps Catalog Update (2026-03-11)** + - Added `luci-app-streamlit-forge` to catalog (productivity, lxc runtime) + - Streamlit app publishing with templates, SSL exposure, mesh publishing + - Featured as new release + - Added `luci-app-rezapp` to catalog (system, native runtime) + - Docker to LXC converter with catalog browsing, package generation + - Featured as new release + - Updated `new_releases` section with both apps + - Total plugins: 37 → 39 diff --git a/.claude/WIP.md b/.claude/WIP.md index fed1125f..d4a85eca 100644 --- a/.claude/WIP.md +++ b/.claude/WIP.md @@ -1,6 +1,6 @@ # Work In Progress (Claude) -_Last updated: 2026-03-10 (PeerTube Routing Fix)_ +_Last updated: 2026-03-11 (Forge LuCI Apps + Documentation)_ > **Architecture Reference**: SecuBox Fanzine v3 — Les 4 Couches @@ -8,6 +8,61 @@ _Last updated: 2026-03-10 (PeerTube Routing Fix)_ ## Recently Completed +### 2026-03-11 + +- **RezApp Forge - Docker to SecuBox App Converter** + - Package: `secubox-app-rezapp` with `rezappctl` CLI + - UCI config: `/etc/config/rezapp` with catalog sources (Docker Hub, LinuxServer.io, GHCR) + - Commands: catalog, search, info, convert, package, publish, list + - Docker to LXC workflow: pull → export → extract → generate LXC config + - Templates: Makefile.tpl, init.d.tpl, ctl.tpl, config.tpl, start-lxc.tpl, lxc-config.tpl, manifest.tpl + - Plan: `/home/reepost/.claude/plans/tingly-rolling-sky.md` + +- **Streamlit Forge Phase 1** (implemented) + - Package: `secubox-app-streamlit-forge` with `slforge` CLI + - UCI config for app management + - 3 templates: basic, dashboard, data-viewer + - Commands: create, start, stop, restart, status, list, info, delete, templates + - Runs apps in Streamlit LXC container with proper mount paths + - Port-based status detection (container PID namespaces) + - HAProxy expose integration + - Mesh catalog publish + - **LuCI dashboard**: `luci-app-streamlit-forge` with create/start/stop/expose/publish + +- **RezApp Forge LuCI** + - Package: `luci-app-rezapp` + - Dashboard with Docker search, conversion dialog + - Converted apps table with Package/Publish/Delete + - Status cards for apps count, catalogs, Docker status + +- **SecuBox KISS Apps Catalog Update** + - Added `luci-app-streamlit-forge` and `luci-app-rezapp` to catalog.json + - Category: productivity (Streamlit), system (RezApp) + - Featured in new_releases section + - Total plugins: 37 → 39 + +- **HAProxy Vhost Rename Feature** + - Added `haproxyctl vhost rename ` command + - Renamed MC360_Streamlit_BPM_v2.gk2.secubox.in → mc360.gk2.secubox.in + +- **Lyrion Music Server Upgrade (9.0.3 → 9.1.1)** + - Diagnosed library showing 0 tracks (Perl XS module version mismatches) + - Root cause: Alpine 3.19 Perl 5.038 incompatible with bundled modules + - **Solution**: Rebuilt LXC container from official Docker image + - Pulled `lmscommunity/lyrionmusicserver:stable` (Debian Bookworm based) + - Exported Docker to tarball, extracted to LXC rootfs + - Created `/start-lxc.sh` wrapper for LXC execution + - Updated LXC config: UID 499 (squeezeboxserver), new paths + - Fixed /srv/lyrion ownership for new UID + - Library scan working: 81,430 files discovered + - Preserved config in /srv/lyrion (prefs, logs, cache) + +- **Metablogizer Package Conflict** + - opkg install fails: `/etc/config/metablogizer` file conflict + - Both `secubox-app-metablogizer` and `luci-app-metablogizer` provide same file + - Workaround: Deploy scripts directly via SCP instead of package install + - TODO: Fix package to use conffiles properly + ### 2026-03-10 - **PeerTube Routing Fix** @@ -298,6 +353,9 @@ _Last updated: 2026-03-10 (PeerTube Routing Fix)_ ## In Progress +- **Streamlit Forge Phase 2** - Preview generation, Gitea push/pull +- **RezApp Forge Full Test** - Test Docker → LXC conversion workflow + - **RTTY Remote Control Module (Phase 4 - Session Replay)** - Avatar-tap integration for session capture - Replay captured sessions to target nodes diff --git a/package/secubox/luci-app-rezapp/Makefile b/package/secubox/luci-app-rezapp/Makefile new file mode 100644 index 00000000..7cdb02d2 --- /dev/null +++ b/package/secubox/luci-app-rezapp/Makefile @@ -0,0 +1,27 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=luci-app-rezapp +PKG_VERSION:=1.0.0 +PKG_RELEASE:=1 + +LUCI_TITLE:=LuCI RezApp Forge - Docker to LXC Converter +LUCI_DEPENDS:=+secubox-app-rezapp +LUCI_PKGARCH:=all + +include $(TOPDIR)/feeds/luci/luci.mk + +define Package/luci-app-rezapp/install + $(INSTALL_DIR) $(1)/usr/share/luci/menu.d + $(INSTALL_DATA) ./root/usr/share/luci/menu.d/luci-app-rezapp.json $(1)/usr/share/luci/menu.d/ + + $(INSTALL_DIR) $(1)/usr/share/rpcd/acl.d + $(INSTALL_DATA) ./root/usr/share/rpcd/acl.d/luci-app-rezapp.json $(1)/usr/share/rpcd/acl.d/ + + $(INSTALL_DIR) $(1)/usr/libexec/rpcd + $(INSTALL_BIN) ./root/usr/libexec/rpcd/luci.rezapp $(1)/usr/libexec/rpcd/ + + $(INSTALL_DIR) $(1)/www/luci-static/resources/view/rezapp + $(INSTALL_DATA) ./htdocs/luci-static/resources/view/rezapp/*.js $(1)/www/luci-static/resources/view/rezapp/ +endef + +$(eval $(call BuildPackage,luci-app-rezapp)) diff --git a/package/secubox/luci-app-rezapp/htdocs/luci-static/resources/view/rezapp/overview.js b/package/secubox/luci-app-rezapp/htdocs/luci-static/resources/view/rezapp/overview.js new file mode 100644 index 00000000..14ed593f --- /dev/null +++ b/package/secubox/luci-app-rezapp/htdocs/luci-static/resources/view/rezapp/overview.js @@ -0,0 +1,396 @@ +'use strict'; +'require view'; +'require rpc'; +'require ui'; +'require poll'; + +var callStatus = rpc.declare({ + object: 'luci.rezapp', + method: 'status', + expect: {} +}); + +var callCatalogs = rpc.declare({ + object: 'luci.rezapp', + method: 'catalogs', + expect: {} +}); + +var callApps = rpc.declare({ + object: 'luci.rezapp', + method: 'apps', + expect: {} +}); + +var callSearch = rpc.declare({ + object: 'luci.rezapp', + method: 'search', + params: ['query'], + expect: {} +}); + +var callInfo = rpc.declare({ + object: 'luci.rezapp', + method: 'info', + params: ['image'], + expect: {} +}); + +var callConvert = rpc.declare({ + object: 'luci.rezapp', + method: 'convert', + params: ['image', 'name', 'tag', 'memory'], + expect: {} +}); + +var callPackage = rpc.declare({ + object: 'luci.rezapp', + method: 'package', + params: ['name'], + expect: {} +}); + +var callPublish = rpc.declare({ + object: 'luci.rezapp', + method: 'publish', + params: ['name'], + expect: {} +}); + +var callDelete = rpc.declare({ + object: 'luci.rezapp', + method: 'delete', + params: ['name'], + expect: {} +}); + +return view.extend({ + status: {}, + catalogs: [], + apps: [], + searchResults: [], + + load: function() { + return Promise.all([ + callStatus(), + callCatalogs(), + callApps() + ]); + }, + + render: function(data) { + var self = this; + this.status = data[0] || {}; + this.catalogs = (data[1] && data[1].catalogs) || []; + this.apps = (data[2] && data[2].apps) || []; + + var view = E('div', { 'class': 'cbi-map' }, [ + E('h2', {}, 'RezApp Forge'), + E('div', { 'class': 'cbi-map-descr' }, + 'Convert Docker images to SecuBox LXC apps.'), + + // Status cards + E('div', { 'class': 'sh-stats', 'style': 'display:flex;gap:1rem;margin:1rem 0;flex-wrap:wrap;' }, [ + this.renderStatCard('Converted Apps', this.status.apps || 0, '#2196f3'), + this.renderStatCard('Catalogs', this.status.catalogs || 0, '#9c27b0'), + this.renderStatCard('Docker', this.status.docker_status || 'unknown', + this.status.docker_status === 'running' ? '#4caf50' : '#ff9800') + ]), + + // Search section + E('div', { 'class': 'cbi-section' }, [ + E('h3', {}, 'Search Docker Hub'), + E('div', { 'style': 'display:flex;gap:0.5rem;margin-bottom:1rem;' }, [ + E('input', { + 'type': 'text', + 'id': 'search-query', + 'class': 'cbi-input-text', + 'placeholder': 'Search images (e.g., nginx, heimdall)', + 'style': 'flex:1;' + }), + E('button', { + 'class': 'cbi-button cbi-button-action', + 'click': ui.createHandlerFn(this, 'handleSearch') + }, 'Search') + ]), + E('div', { 'id': 'search-results' }) + ]), + + // Converted apps section + E('div', { 'class': 'cbi-section' }, [ + E('h3', {}, 'Converted Apps'), + E('div', { 'id': 'apps-table' }, this.renderAppsTable()) + ]) + ]); + + poll.add(L.bind(this.pollApps, this), 15); + + return view; + }, + + renderStatCard: function(label, value, color) { + return E('div', { + 'style': 'background:#1a1a2e;border-left:4px solid ' + color + ';padding:1rem;min-width:120px;border-radius:4px;' + }, [ + E('div', { 'style': 'font-size:1.5rem;font-weight:bold;color:' + color }, String(value)), + E('div', { 'style': 'color:#888;font-size:0.85rem;' }, label) + ]); + }, + + renderAppsTable: function() { + if (!this.apps.length) { + return E('p', { 'class': 'cbi-value-description' }, + 'No converted apps yet. Search and convert a Docker image to get started.'); + } + + var rows = this.apps.map(L.bind(function(app) { + var statusBadge = E('span', { + 'class': 'badge', + 'style': 'background:' + (app.lxc_status === 'running' ? '#4caf50' : app.lxc_status === 'stopped' ? '#ff9800' : '#666') + ';color:#fff;padding:2px 8px;border-radius:10px;font-size:0.8rem;' + }, app.lxc_status || 'none'); + + var packageBadge = E('span', { + 'style': 'color:' + (app.packaged === 'yes' ? '#4caf50' : '#666') + }, app.packaged === 'yes' ? 'Yes' : 'No'); + + var actions = E('div', { 'style': 'display:flex;gap:4px;flex-wrap:wrap;' }, [ + app.packaged !== 'yes' ? + E('button', { + 'class': 'cbi-button', + 'style': 'padding:4px 8px;font-size:0.8rem;', + 'click': ui.createHandlerFn(this, 'handlePackage', app.name) + }, 'Package') : '', + E('button', { + 'class': 'cbi-button', + 'style': 'padding:4px 8px;font-size:0.8rem;', + 'click': ui.createHandlerFn(this, 'handlePublish', app.name) + }, 'Publish'), + E('button', { + 'class': 'cbi-button cbi-button-remove', + 'style': 'padding:4px 8px;font-size:0.8rem;', + 'click': ui.createHandlerFn(this, 'handleDelete', app.name) + }, 'Delete') + ]); + + return E('tr', {}, [ + E('td', {}, app.name), + E('td', { 'style': 'font-size:0.85rem;color:#888;' }, app.source_image || '-'), + E('td', {}, statusBadge), + E('td', {}, packageBadge), + E('td', { 'style': 'font-size:0.85rem;' }, app.converted_at || '-'), + E('td', {}, actions) + ]); + }, this)); + + return E('table', { 'class': 'table cbi-section-table' }, [ + E('tr', { 'class': 'tr table-titles' }, [ + E('th', { 'class': 'th' }, 'Name'), + E('th', { 'class': 'th' }, 'Source Image'), + E('th', { 'class': 'th' }, 'LXC Status'), + E('th', { 'class': 'th' }, 'Packaged'), + E('th', { 'class': 'th' }, 'Converted'), + E('th', { 'class': 'th' }, 'Actions') + ]) + ].concat(rows)); + }, + + renderSearchResults: function() { + var container = document.getElementById('search-results'); + if (!container) return; + + if (!this.searchResults.length) { + container.innerHTML = ''; + return; + } + + var rows = this.searchResults.map(L.bind(function(result) { + return E('tr', {}, [ + E('td', {}, [ + E('strong', {}, result.image), + E('span', { 'style': 'margin-left:0.5rem;color:#ffd700;' }, result.stars ? result.stars + '*' : '') + ]), + E('td', { 'style': 'font-size:0.85rem;color:#888;max-width:300px;overflow:hidden;text-overflow:ellipsis;' }, + result.description || ''), + E('td', {}, [ + E('button', { + 'class': 'cbi-button cbi-button-action', + 'style': 'padding:4px 8px;font-size:0.8rem;', + 'click': ui.createHandlerFn(this, 'handleConvert', result.image) + }, 'Convert') + ]) + ]); + }, this)); + + var table = E('table', { 'class': 'table cbi-section-table', 'style': 'margin-top:1rem;' }, [ + E('tr', { 'class': 'tr table-titles' }, [ + E('th', { 'class': 'th' }, 'Image'), + E('th', { 'class': 'th' }, 'Description'), + E('th', { 'class': 'th' }, 'Action') + ]) + ].concat(rows)); + + container.innerHTML = ''; + container.appendChild(table); + }, + + pollApps: function() { + var self = this; + return callApps().then(function(data) { + self.apps = (data && data.apps) || []; + var container = document.getElementById('apps-table'); + if (container) { + container.innerHTML = ''; + container.appendChild(self.renderAppsTable()); + } + }); + }, + + handleSearch: function() { + var self = this; + var query = document.getElementById('search-query').value.trim(); + + if (!query) { + ui.addNotification(null, E('p', 'Please enter a search query')); + return; + } + + var container = document.getElementById('search-results'); + container.innerHTML = '

Searching Docker Hub...

'; + + return callSearch(query).then(function(res) { + if (res.code !== 0) { + container.innerHTML = '

Search failed

'; + return; + } + + self.searchResults = res.results || []; + self.renderSearchResults(); + + if (!self.searchResults.length) { + container.innerHTML = '

No results found for "' + query + '"

'; + } + }).catch(function(err) { + container.innerHTML = '

Error: ' + err.message + '

'; + }); + }, + + handleConvert: function(image) { + var self = this; + + // Extract default name from image + var defaultName = image.split('/').pop().split(':')[0].replace(/[^a-zA-Z0-9_-]/g, '_'); + + ui.showModal('Convert Docker Image', [ + E('div', { 'class': 'cbi-section' }, [ + E('p', {}, ['Converting: ', E('strong', {}, image)]), + E('div', { 'class': 'cbi-value' }, [ + E('label', { 'class': 'cbi-value-title' }, 'App Name'), + E('div', { 'class': 'cbi-value-field' }, [ + E('input', { 'type': 'text', 'id': 'convert-name', 'class': 'cbi-input-text', 'value': defaultName }) + ]) + ]), + E('div', { 'class': 'cbi-value' }, [ + E('label', { 'class': 'cbi-value-title' }, 'Tag'), + E('div', { 'class': 'cbi-value-field' }, [ + E('input', { 'type': 'text', 'id': 'convert-tag', 'class': 'cbi-input-text', 'value': 'latest', 'placeholder': 'latest' }) + ]) + ]), + E('div', { 'class': 'cbi-value' }, [ + E('label', { 'class': 'cbi-value-title' }, 'Memory Limit'), + E('div', { 'class': 'cbi-value-field' }, [ + E('select', { 'id': 'convert-memory', 'class': 'cbi-input-select' }, [ + E('option', { 'value': '256M' }, '256 MB'), + E('option', { 'value': '512M', 'selected': true }, '512 MB'), + E('option', { 'value': '1G' }, '1 GB'), + E('option', { 'value': '2G' }, '2 GB') + ]) + ]) + ]) + ]), + E('div', { 'class': 'right' }, [ + E('button', { 'class': 'cbi-button', 'click': ui.hideModal }, 'Cancel'), + E('button', { + 'class': 'cbi-button cbi-button-positive', + 'click': function() { + var name = document.getElementById('convert-name').value.trim(); + var tag = document.getElementById('convert-tag').value.trim() || 'latest'; + var memory = document.getElementById('convert-memory').value; + + if (!name) { + ui.addNotification(null, E('p', 'Please enter an app name')); + return; + } + + ui.hideModal(); + ui.showModal('Converting...', [ + E('p', { 'class': 'spinning' }, 'Converting ' + image + ':' + tag + '...'), + E('p', { 'style': 'color:#888;font-size:0.85rem;' }, 'This may take several minutes. Please wait...') + ]); + + callConvert(image, name, tag, memory).then(function(res) { + ui.hideModal(); + if (res.code === 0) { + ui.addNotification(null, E('p', 'Conversion complete!')); + self.pollApps(); + } else { + ui.addNotification(null, E('p', 'Error: ' + (res.output || 'Conversion failed'))); + } + }).catch(function(err) { + ui.hideModal(); + ui.addNotification(null, E('p', 'Error: ' + err.message)); + }); + } + }, 'Convert') + ]) + ]); + }, + + handlePackage: function(name) { + var self = this; + ui.showModal('Generating Package...', [ + E('p', { 'class': 'spinning' }, 'Generating SecuBox package for ' + name + '...') + ]); + + return callPackage(name).then(function(res) { + ui.hideModal(); + if (res.code === 0) { + ui.addNotification(null, E('p', 'Package generated!')); + self.pollApps(); + } else { + ui.addNotification(null, E('p', 'Error: ' + (res.output || 'Package generation failed'))); + } + }); + }, + + handlePublish: function(name) { + var self = this; + ui.showModal('Publishing...', [ + E('p', { 'class': 'spinning' }, 'Publishing ' + name + ' to catalog...') + ]); + + return callPublish(name).then(function(res) { + ui.hideModal(); + if (res.code === 0) { + ui.addNotification(null, E('p', 'Published to catalog!')); + } else { + ui.addNotification(null, E('p', 'Error: ' + (res.output || 'Publish failed'))); + } + }); + }, + + handleDelete: function(name) { + var self = this; + if (!confirm('Delete converted app "' + name + '"? This cannot be undone.')) { + return; + } + + return callDelete(name).then(function(res) { + if (res.code === 0) { + ui.addNotification(null, E('p', 'Deleted ' + name)); + self.pollApps(); + } else { + ui.addNotification(null, E('p', 'Error deleting')); + } + }); + } +}); diff --git a/package/secubox/luci-app-rezapp/root/usr/libexec/rpcd/luci.rezapp b/package/secubox/luci-app-rezapp/root/usr/libexec/rpcd/luci.rezapp new file mode 100644 index 00000000..df887faf --- /dev/null +++ b/package/secubox/luci-app-rezapp/root/usr/libexec/rpcd/luci.rezapp @@ -0,0 +1,265 @@ +#!/bin/sh +# RPCD backend for RezApp Forge LuCI app + +. /lib/functions.sh +. /usr/share/libubox/jshn.sh + +APPS_DIR="/srv/rezapp/apps" +CACHE_DIR="/srv/rezapp/cache" +OUTPUT_DIR="/srv/rezapp/generated" + +# Get status overview +get_status() { + local apps=0 + local catalogs=0 + local docker_status="unknown" + + # Count converted apps + [ -d "$APPS_DIR" ] && apps=$(ls -1 "$APPS_DIR" 2>/dev/null | wc -l) + + # Count enabled catalogs + config_load rezapp + config_foreach count_catalog catalog + catalogs=$_catalog_count + + # Check Docker status + if pgrep dockerd >/dev/null 2>&1; then + docker_status="running" + else + docker_status="stopped" + fi + + json_init + json_add_int "apps" "$apps" + json_add_int "catalogs" "$catalogs" + json_add_string "docker_status" "$docker_status" + json_dump +} + +_catalog_count=0 +count_catalog() { + local enabled + config_get enabled "$1" enabled '0' + [ "$enabled" = "1" ] && _catalog_count=$((_catalog_count + 1)) +} + +# Get enabled catalogs +get_catalogs() { + json_init + json_add_array "catalogs" + + config_load rezapp + config_foreach add_catalog catalog + + json_close_array + json_dump +} + +add_catalog() { + local section="$1" + local name type url namespace enabled + + config_get name "$section" name "$section" + config_get type "$section" type 'dockerhub' + config_get url "$section" url '' + config_get namespace "$section" namespace '' + config_get enabled "$section" enabled '0' + + [ "$enabled" = "1" ] || return + + json_add_object "" + json_add_string "id" "$section" + json_add_string "name" "$name" + json_add_string "type" "$type" + json_add_string "url" "$url" + json_add_string "namespace" "$namespace" + json_close_object +} + +# Get converted apps +get_apps() { + json_init + json_add_array "apps" + + [ -d "$APPS_DIR" ] || { json_close_array; json_dump; return; } + + for app_dir in "$APPS_DIR"/*/; do + [ -d "$app_dir" ] || continue + local name=$(basename "$app_dir") + + local source_image="" + local converted_at="" + + if [ -f "$app_dir/metadata.json" ]; then + source_image=$(jsonfilter -i "$app_dir/metadata.json" -e '@.source_image' 2>/dev/null) + converted_at=$(jsonfilter -i "$app_dir/metadata.json" -e '@.converted_at' 2>/dev/null) + fi + + # Check if package exists + local packaged="no" + [ -d "$OUTPUT_DIR/secubox-app-$name" ] && packaged="yes" + + # Check if LXC container exists + local lxc_status="none" + if [ -d "/srv/lxc/$name" ]; then + if lxc-info -n "$name" 2>/dev/null | grep -q "RUNNING"; then + lxc_status="running" + else + lxc_status="stopped" + fi + fi + + json_add_object "" + json_add_string "name" "$name" + json_add_string "source_image" "$source_image" + json_add_string "converted_at" "$converted_at" + json_add_string "packaged" "$packaged" + json_add_string "lxc_status" "$lxc_status" + json_close_object + done + + json_close_array + json_dump +} + +# Search Docker Hub +do_search() { + local query="$1" + [ -z "$query" ] && { echo '{"error":"Query required"}'; return; } + + local output + output=$(rezappctl search "$query" 2>&1) + local rc=$? + + # Parse output into JSON + json_init + json_add_int "code" "$rc" + json_add_array "results" + + echo "$output" | grep -E "^\s+" | while read -r line; do + local image=$(echo "$line" | awk '{print $1}') + local stars=$(echo "$line" | awk '{print $2}' | tr -d '*') + local desc=$(echo "$line" | cut -d' ' -f3-) + + [ -n "$image" ] || continue + + json_add_object "" + json_add_string "image" "$image" + json_add_string "stars" "$stars" + json_add_string "description" "$desc" + json_close_object + done + + json_close_array + json_dump +} + +# Get image info +get_info() { + local image="$1" + [ -z "$image" ] && { echo '{"error":"Image required"}'; return; } + + local output + output=$(rezappctl info "$image" 2>&1) + local rc=$? + + # Extract tags + local tags="" + tags=$(echo "$output" | grep -A100 "Available Tags:" | grep "^\s*-" | sed 's/^\s*-\s*//' | head -10 | tr '\n' ',') + + json_init + json_add_int "code" "$rc" + json_add_string "image" "$image" + json_add_string "tags" "$tags" + json_add_string "raw_output" "$output" + json_dump +} + +# Convert Docker image +do_convert() { + local image="$1" + local name="$2" + local tag="$3" + local memory="$4" + + [ -z "$image" ] && { echo '{"error":"Image required"}'; return; } + + local cmd="rezappctl convert $image" + [ -n "$name" ] && cmd="$cmd --name $name" + [ -n "$tag" ] && cmd="$cmd --tag $tag" + [ -n "$memory" ] && cmd="$cmd --memory $memory" + + local output + output=$(eval "$cmd" 2>&1) + local rc=$? + + json_init + json_add_int "code" "$rc" + json_add_string "output" "$output" + json_dump +} + +# Generate package +do_package() { + local name="$1" + [ -z "$name" ] && { echo '{"error":"App name required"}'; return; } + + local output + output=$(rezappctl package "$name" 2>&1) + local rc=$? + + json_init + json_add_int "code" "$rc" + json_add_string "output" "$output" + json_dump +} + +# Publish to catalog +do_publish() { + local name="$1" + [ -z "$name" ] && { echo '{"error":"App name required"}'; return; } + + local output + output=$(rezappctl publish "$name" 2>&1) + local rc=$? + + json_init + json_add_int "code" "$rc" + json_add_string "output" "$output" + json_dump +} + +# Delete converted app +do_delete() { + local name="$1" + [ -z "$name" ] && { echo '{"error":"App name required"}'; return; } + + # Remove app directory + rm -rf "$APPS_DIR/$name" + rm -rf "$OUTPUT_DIR/secubox-app-$name" + rm -rf "$OUTPUT_DIR/luci-app-$name" + + json_init + json_add_int "code" 0 + json_add_string "message" "Deleted $name" + json_dump +} + +case "$1" in + list) + echo '{"status":{},"catalogs":{},"apps":{},"search":{"query":"String"},"info":{"image":"String"},"convert":{"image":"String","name":"String","tag":"String","memory":"String"},"package":{"name":"String"},"publish":{"name":"String"},"delete":{"name":"String"}}' + ;; + call) + case "$2" in + status) get_status ;; + catalogs) get_catalogs ;; + apps) get_apps ;; + search) read input; json_load "$input"; json_get_var query query; do_search "$query" ;; + info) read input; json_load "$input"; json_get_var image image; get_info "$image" ;; + convert) read input; json_load "$input"; json_get_var image image; json_get_var name name; json_get_var tag tag; json_get_var memory memory; do_convert "$image" "$name" "$tag" "$memory" ;; + package) read input; json_load "$input"; json_get_var name name; do_package "$name" ;; + publish) read input; json_load "$input"; json_get_var name name; do_publish "$name" ;; + delete) read input; json_load "$input"; json_get_var name name; do_delete "$name" ;; + esac + ;; +esac diff --git a/package/secubox/luci-app-rezapp/root/usr/share/luci/menu.d/luci-app-rezapp.json b/package/secubox/luci-app-rezapp/root/usr/share/luci/menu.d/luci-app-rezapp.json new file mode 100644 index 00000000..1b7c0d09 --- /dev/null +++ b/package/secubox/luci-app-rezapp/root/usr/share/luci/menu.d/luci-app-rezapp.json @@ -0,0 +1,14 @@ +{ + "admin/services/rezapp": { + "title": "RezApp Forge", + "order": 86, + "action": { + "type": "view", + "path": "rezapp/overview" + }, + "depends": { + "acl": ["luci-app-rezapp"], + "uci": { "rezapp": true } + } + } +} diff --git a/package/secubox/luci-app-rezapp/root/usr/share/rpcd/acl.d/luci-app-rezapp.json b/package/secubox/luci-app-rezapp/root/usr/share/rpcd/acl.d/luci-app-rezapp.json new file mode 100644 index 00000000..c13b3264 --- /dev/null +++ b/package/secubox/luci-app-rezapp/root/usr/share/rpcd/acl.d/luci-app-rezapp.json @@ -0,0 +1,17 @@ +{ + "luci-app-rezapp": { + "description": "Grant access to RezApp Forge", + "read": { + "ubus": { + "luci.rezapp": ["status", "catalogs", "apps", "search", "info"] + }, + "uci": ["rezapp"] + }, + "write": { + "ubus": { + "luci.rezapp": ["convert", "package", "publish", "delete"] + }, + "uci": ["rezapp"] + } + } +} diff --git a/package/secubox/luci-app-streamlit-forge/Makefile b/package/secubox/luci-app-streamlit-forge/Makefile new file mode 100644 index 00000000..066ca945 --- /dev/null +++ b/package/secubox/luci-app-streamlit-forge/Makefile @@ -0,0 +1,27 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=luci-app-streamlit-forge +PKG_VERSION:=1.0.0 +PKG_RELEASE:=1 + +LUCI_TITLE:=LuCI Streamlit Forge - App Publishing Platform +LUCI_DEPENDS:=+secubox-app-streamlit-forge +LUCI_PKGARCH:=all + +include $(TOPDIR)/feeds/luci/luci.mk + +define Package/luci-app-streamlit-forge/install + $(INSTALL_DIR) $(1)/usr/share/luci/menu.d + $(INSTALL_DATA) ./root/usr/share/luci/menu.d/luci-app-streamlit-forge.json $(1)/usr/share/luci/menu.d/ + + $(INSTALL_DIR) $(1)/usr/share/rpcd/acl.d + $(INSTALL_DATA) ./root/usr/share/rpcd/acl.d/luci-app-streamlit-forge.json $(1)/usr/share/rpcd/acl.d/ + + $(INSTALL_DIR) $(1)/usr/libexec/rpcd + $(INSTALL_BIN) ./root/usr/libexec/rpcd/luci.streamlit-forge $(1)/usr/libexec/rpcd/ + + $(INSTALL_DIR) $(1)/www/luci-static/resources/view/streamlit-forge + $(INSTALL_DATA) ./htdocs/luci-static/resources/view/streamlit-forge/*.js $(1)/www/luci-static/resources/view/streamlit-forge/ +endef + +$(eval $(call BuildPackage,luci-app-streamlit-forge)) diff --git a/package/secubox/luci-app-streamlit-forge/htdocs/luci-static/resources/view/streamlit-forge/overview.js b/package/secubox/luci-app-streamlit-forge/htdocs/luci-static/resources/view/streamlit-forge/overview.js new file mode 100644 index 00000000..694b7ad8 --- /dev/null +++ b/package/secubox/luci-app-streamlit-forge/htdocs/luci-static/resources/view/streamlit-forge/overview.js @@ -0,0 +1,383 @@ +'use strict'; +'require view'; +'require rpc'; +'require ui'; +'require form'; +'require poll'; + +var callList = rpc.declare({ + object: 'luci.streamlit-forge', + method: 'list', + expect: {} +}); + +var callStatus = rpc.declare({ + object: 'luci.streamlit-forge', + method: 'status', + expect: {} +}); + +var callTemplates = rpc.declare({ + object: 'luci.streamlit-forge', + method: 'templates', + expect: {} +}); + +var callCreate = rpc.declare({ + object: 'luci.streamlit-forge', + method: 'create', + params: ['name', 'template'], + expect: {} +}); + +var callStart = rpc.declare({ + object: 'luci.streamlit-forge', + method: 'start', + params: ['name'], + expect: {} +}); + +var callStop = rpc.declare({ + object: 'luci.streamlit-forge', + method: 'stop', + params: ['name'], + expect: {} +}); + +var callDelete = rpc.declare({ + object: 'luci.streamlit-forge', + method: 'delete', + params: ['name'], + expect: {} +}); + +var callExpose = rpc.declare({ + object: 'luci.streamlit-forge', + method: 'expose', + params: ['name', 'domain'], + expect: {} +}); + +var callPublish = rpc.declare({ + object: 'luci.streamlit-forge', + method: 'publish', + params: ['name'], + expect: {} +}); + +return view.extend({ + apps: [], + templates: [], + status: {}, + + load: function() { + return Promise.all([ + callList(), + callStatus(), + callTemplates() + ]); + }, + + render: function(data) { + var self = this; + this.apps = (data[0] && data[0].apps) || []; + this.status = data[1] || {}; + this.templates = (data[2] && data[2].templates) || []; + + var view = E('div', { 'class': 'cbi-map' }, [ + E('h2', {}, 'Streamlit Forge'), + E('div', { 'class': 'cbi-map-descr' }, + 'Create, manage, and publish Streamlit applications.'), + + // Status cards + E('div', { 'class': 'sh-stats', 'style': 'display:flex;gap:1rem;margin:1rem 0;flex-wrap:wrap;' }, [ + this.renderStatCard('Running', this.status.running || 0, '#4caf50'), + this.renderStatCard('Total Apps', this.status.total || 0, '#2196f3'), + this.renderStatCard('LXC Container', this.status.lxc_status || 'unknown', + this.status.lxc_status === 'running' ? '#4caf50' : '#ff9800') + ]), + + // Actions + E('div', { 'class': 'cbi-section' }, [ + E('h3', {}, 'Actions'), + E('div', { 'style': 'display:flex;gap:0.5rem;flex-wrap:wrap;' }, [ + E('button', { + 'class': 'cbi-button cbi-button-add', + 'click': ui.createHandlerFn(this, 'handleCreate') + }, '+ Create App'), + E('button', { + 'class': 'cbi-button', + 'click': ui.createHandlerFn(this, 'handleRefresh') + }, 'Refresh') + ]) + ]), + + // Apps table + E('div', { 'class': 'cbi-section' }, [ + E('h3', {}, 'Applications'), + this.renderAppsTable() + ]) + ]); + + poll.add(L.bind(this.pollStatus, this), 10); + + return view; + }, + + renderStatCard: function(label, value, color) { + return E('div', { + 'style': 'background:#1a1a2e;border-left:4px solid ' + color + ';padding:1rem;min-width:120px;border-radius:4px;' + }, [ + E('div', { 'style': 'font-size:1.5rem;font-weight:bold;color:' + color }, String(value)), + E('div', { 'style': 'color:#888;font-size:0.85rem;' }, label) + ]); + }, + + renderAppsTable: function() { + if (!this.apps.length) { + return E('p', { 'class': 'cbi-value-description' }, + 'No apps found. Click "Create App" to get started.'); + } + + var rows = this.apps.map(L.bind(function(app) { + var isRunning = app.status === 'running'; + var statusBadge = E('span', { + 'class': 'badge', + 'style': 'background:' + (isRunning ? '#4caf50' : '#666') + ';color:#fff;padding:2px 8px;border-radius:10px;font-size:0.8rem;' + }, isRunning ? 'Running' : 'Stopped'); + + var actions = E('div', { 'style': 'display:flex;gap:4px;flex-wrap:wrap;' }, [ + isRunning ? + E('button', { + 'class': 'cbi-button cbi-button-remove', + 'style': 'padding:4px 8px;font-size:0.8rem;', + 'click': ui.createHandlerFn(this, 'handleStop', app.name) + }, 'Stop') : + E('button', { + 'class': 'cbi-button cbi-button-apply', + 'style': 'padding:4px 8px;font-size:0.8rem;', + 'click': ui.createHandlerFn(this, 'handleStart', app.name) + }, 'Start'), + isRunning && app.port ? + E('a', { + 'class': 'cbi-button', + 'style': 'padding:4px 8px;font-size:0.8rem;text-decoration:none;', + 'href': 'http://' + window.location.hostname + ':' + app.port, + 'target': '_blank' + }, 'Open') : '', + !app.domain ? + E('button', { + 'class': 'cbi-button', + 'style': 'padding:4px 8px;font-size:0.8rem;', + 'click': ui.createHandlerFn(this, 'handleExpose', app.name) + }, 'Expose') : '', + E('button', { + 'class': 'cbi-button', + 'style': 'padding:4px 8px;font-size:0.8rem;', + 'click': ui.createHandlerFn(this, 'handlePublish', app.name) + }, 'Publish'), + E('button', { + 'class': 'cbi-button cbi-button-remove', + 'style': 'padding:4px 8px;font-size:0.8rem;', + 'click': ui.createHandlerFn(this, 'handleDelete', app.name) + }, 'Delete') + ]); + + return E('tr', {}, [ + E('td', {}, app.name), + E('td', {}, statusBadge), + E('td', {}, app.port || '-'), + E('td', {}, app.domain ? E('a', { 'href': 'https://' + app.domain, 'target': '_blank' }, app.domain) : '-'), + E('td', {}, app.created || '-'), + E('td', {}, actions) + ]); + }, this)); + + return E('table', { 'class': 'table cbi-section-table' }, [ + E('tr', { 'class': 'tr table-titles' }, [ + E('th', { 'class': 'th' }, 'Name'), + E('th', { 'class': 'th' }, 'Status'), + E('th', { 'class': 'th' }, 'Port'), + E('th', { 'class': 'th' }, 'Domain'), + E('th', { 'class': 'th' }, 'Created'), + E('th', { 'class': 'th' }, 'Actions') + ]) + ].concat(rows)); + }, + + pollStatus: function() { + var self = this; + return Promise.all([callList(), callStatus()]).then(function(data) { + self.apps = (data[0] && data[0].apps) || []; + self.status = data[1] || {}; + + var container = document.querySelector('.cbi-map'); + if (container) { + var statsDiv = container.querySelector('.sh-stats'); + if (statsDiv) { + statsDiv.innerHTML = ''; + statsDiv.appendChild(self.renderStatCard('Running', self.status.running || 0, '#4caf50')); + statsDiv.appendChild(self.renderStatCard('Total Apps', self.status.total || 0, '#2196f3')); + statsDiv.appendChild(self.renderStatCard('LXC Container', self.status.lxc_status || 'unknown', + self.status.lxc_status === 'running' ? '#4caf50' : '#ff9800')); + } + + var tableSection = container.querySelectorAll('.cbi-section')[1]; + if (tableSection) { + var oldTable = tableSection.querySelector('table, p'); + if (oldTable) { + oldTable.replaceWith(self.renderAppsTable()); + } + } + } + }); + }, + + handleRefresh: function() { + return this.pollStatus(); + }, + + handleCreate: function() { + var self = this; + var templates = this.templates; + + var templateOptions = templates.map(function(t) { + return E('option', { 'value': t.name }, t.name + ' - ' + (t.description || 'No description')); + }); + + ui.showModal('Create New App', [ + E('div', { 'class': 'cbi-section' }, [ + E('div', { 'class': 'cbi-value' }, [ + E('label', { 'class': 'cbi-value-title' }, 'App Name'), + E('div', { 'class': 'cbi-value-field' }, [ + E('input', { 'type': 'text', 'id': 'new-app-name', 'class': 'cbi-input-text', 'placeholder': 'myapp' }) + ]) + ]), + E('div', { 'class': 'cbi-value' }, [ + E('label', { 'class': 'cbi-value-title' }, 'Template'), + E('div', { 'class': 'cbi-value-field' }, [ + E('select', { 'id': 'new-app-template', 'class': 'cbi-input-select' }, templateOptions) + ]) + ]) + ]), + E('div', { 'class': 'right' }, [ + E('button', { + 'class': 'cbi-button', + 'click': ui.hideModal + }, 'Cancel'), + E('button', { + 'class': 'cbi-button cbi-button-positive', + 'click': function() { + var name = document.getElementById('new-app-name').value.trim(); + var template = document.getElementById('new-app-template').value; + + if (!name) { + ui.addNotification(null, E('p', 'Please enter an app name')); + return; + } + + if (!/^[a-zA-Z][a-zA-Z0-9_-]*$/.test(name)) { + ui.addNotification(null, E('p', 'Invalid app name. Use letters, numbers, underscore, hyphen.')); + return; + } + + ui.hideModal(); + ui.showModal('Creating App...', [ + E('p', { 'class': 'spinning' }, 'Creating ' + name + ' from ' + template + ' template...') + ]); + + callCreate(name, template).then(function(res) { + ui.hideModal(); + if (res.code === 0) { + ui.addNotification(null, E('p', 'App created successfully!')); + self.pollStatus(); + } else { + ui.addNotification(null, E('p', 'Error: ' + (res.output || 'Unknown error'))); + } + }); + } + }, 'Create') + ]) + ]); + }, + + handleStart: function(name) { + var self = this; + ui.showModal('Starting App...', [ + E('p', { 'class': 'spinning' }, 'Starting ' + name + '...') + ]); + + return callStart(name).then(function(res) { + ui.hideModal(); + if (res.code === 0) { + ui.addNotification(null, E('p', 'App started!')); + } else { + ui.addNotification(null, E('p', 'Error: ' + (res.output || 'Failed to start'))); + } + return self.pollStatus(); + }); + }, + + handleStop: function(name) { + var self = this; + return callStop(name).then(function(res) { + if (res.code === 0) { + ui.addNotification(null, E('p', 'App stopped')); + } + return self.pollStatus(); + }); + }, + + handleDelete: function(name) { + var self = this; + if (!confirm('Delete app "' + name + '"? This cannot be undone.')) { + return; + } + + return callDelete(name).then(function(res) { + if (res.code === 0) { + ui.addNotification(null, E('p', 'App deleted')); + } else { + ui.addNotification(null, E('p', 'Error: ' + (res.output || 'Failed to delete'))); + } + return self.pollStatus(); + }); + }, + + handleExpose: function(name) { + var self = this; + var domain = prompt('Enter domain for ' + name + ' (leave empty for auto):', name + '.apps.secubox.in'); + if (domain === null) return; + + ui.showModal('Exposing App...', [ + E('p', { 'class': 'spinning' }, 'Creating vhost and SSL certificate...') + ]); + + return callExpose(name, domain || '').then(function(res) { + ui.hideModal(); + if (res.code === 0) { + ui.addNotification(null, E('p', 'App exposed at ' + (domain || 'auto-domain'))); + } else { + ui.addNotification(null, E('p', 'Error: ' + (res.output || 'Failed to expose'))); + } + return self.pollStatus(); + }); + }, + + handlePublish: function(name) { + var self = this; + ui.showModal('Publishing...', [ + E('p', { 'class': 'spinning' }, 'Publishing to mesh catalog...') + ]); + + return callPublish(name).then(function(res) { + ui.hideModal(); + if (res.code === 0) { + ui.addNotification(null, E('p', 'App published to mesh catalog')); + } else { + ui.addNotification(null, E('p', 'Error: ' + (res.output || 'Failed to publish'))); + } + return self.pollStatus(); + }); + } +}); diff --git a/package/secubox/luci-app-streamlit-forge/root/usr/libexec/rpcd/luci.streamlit-forge b/package/secubox/luci-app-streamlit-forge/root/usr/libexec/rpcd/luci.streamlit-forge new file mode 100644 index 00000000..6e015778 --- /dev/null +++ b/package/secubox/luci-app-streamlit-forge/root/usr/libexec/rpcd/luci.streamlit-forge @@ -0,0 +1,365 @@ +#!/bin/sh +# RPCD backend for Streamlit Forge LuCI app + +. /lib/functions.sh +. /usr/share/libubox/jshn.sh + +APPS_DIR="/srv/streamlit/apps" + +# Get list of apps with status +get_apps() { + json_init + json_add_array "apps" + + config_load streamlit-forge + config_get apps_dir main apps_dir '/srv/streamlit/apps' + + for app_dir in "$apps_dir"/*/; do + [ -d "$app_dir" ] || continue + local name=$(basename "$app_dir") + [ "$name" = "." ] || [ "$name" = ".." ] && continue + [ -f "$app_dir/.slforge-start.sh" ] && continue + + local enabled port domain entrypoint memory created status + + config_get enabled "$name" enabled '0' + config_get port "$name" port '' + config_get domain "$name" domain '' + config_get entrypoint "$name" entrypoint 'app.py' + config_get memory "$name" memory '512M' + config_get created "$name" created '' + + # Check status by port + status="stopped" + if [ -n "$port" ] && netstat -tln 2>/dev/null | grep -q ":$port "; then + status="running" + fi + + json_add_object "" + json_add_string "name" "$name" + json_add_string "enabled" "$enabled" + json_add_string "port" "$port" + json_add_string "domain" "$domain" + json_add_string "entrypoint" "$entrypoint" + json_add_string "memory" "$memory" + json_add_string "created" "$created" + json_add_string "status" "$status" + json_close_object + done + + json_close_array + json_dump +} + +# Get app info +get_info() { + local name="$1" + [ -z "$name" ] && { echo '{"error":"App name required"}'; return; } + + config_load streamlit-forge + config_get apps_dir main apps_dir '/srv/streamlit/apps' + + local app_dir="$apps_dir/$name" + [ -d "$app_dir" ] || { echo '{"error":"App not found"}'; return; } + + local enabled port domain entrypoint memory created status + + config_get enabled "$name" enabled '0' + config_get port "$name" port '' + config_get domain "$name" domain '' + config_get entrypoint "$name" entrypoint 'app.py' + config_get memory "$name" memory '512M' + config_get created "$name" created '' + + status="stopped" + if [ -n "$port" ] && netstat -tln 2>/dev/null | grep -q ":$port "; then + status="running" + fi + + # Get files + local files="" + if [ -d "$app_dir/src" ]; then + files=$(ls -1 "$app_dir/src" 2>/dev/null | head -20 | tr '\n' ',') + fi + + json_init + json_add_string "name" "$name" + json_add_string "enabled" "$enabled" + json_add_string "port" "$port" + json_add_string "domain" "$domain" + json_add_string "entrypoint" "$entrypoint" + json_add_string "memory" "$memory" + json_add_string "created" "$created" + json_add_string "status" "$status" + json_add_string "files" "$files" + json_add_string "directory" "$app_dir" + json_dump +} + +# Get available templates +get_templates() { + json_init + json_add_array "templates" + + local tpl_dir="/usr/share/streamlit-forge/templates" + for tpl in "$tpl_dir"/*/; do + [ -d "$tpl" ] || continue + local name=$(basename "$tpl") + local desc="" + [ -f "$tpl/README.md" ] && desc=$(head -1 "$tpl/README.md" | sed 's/^#\s*//') + + json_add_object "" + json_add_string "name" "$name" + json_add_string "description" "$desc" + json_close_object + done + + json_close_array + json_dump +} + +# Get global status +get_status() { + local running=0 + local total=0 + + config_load streamlit-forge + config_get apps_dir main apps_dir '/srv/streamlit/apps' + + for app_dir in "$apps_dir"/*/; do + [ -d "$app_dir" ] || continue + local name=$(basename "$app_dir") + [ "$name" = "." ] || [ "$name" = ".." ] && continue + [ -f "$app_dir/.slforge-start.sh" ] && continue + + total=$((total + 1)) + + local port + config_get port "$name" port '' + if [ -n "$port" ] && netstat -tln 2>/dev/null | grep -q ":$port "; then + running=$((running + 1)) + fi + done + + # Check LXC container + local lxc_status="stopped" + if lxc-info -n streamlit 2>/dev/null | grep -q "RUNNING"; then + lxc_status="running" + fi + + json_init + json_add_int "total" "$total" + json_add_int "running" "$running" + json_add_string "lxc_status" "$lxc_status" + json_dump +} + +# Create app +do_create() { + local name="$1" + local template="$2" + + [ -z "$name" ] && { echo '{"error":"App name required"}'; return; } + [ -z "$template" ] && template="basic" + + local output + output=$(slforge create "$name" --from-template "$template" 2>&1) + local rc=$? + + json_init + json_add_int "code" "$rc" + json_add_string "output" "$output" + json_dump +} + +# Delete app +do_delete() { + local name="$1" + [ -z "$name" ] && { echo '{"error":"App name required"}'; return; } + + local output + output=$(slforge delete "$name" 2>&1) + local rc=$? + + json_init + json_add_int "code" "$rc" + json_add_string "output" "$output" + json_dump +} + +# Start app +do_start() { + local name="$1" + [ -z "$name" ] && { echo '{"error":"App name required"}'; return; } + + local output + output=$(slforge start "$name" 2>&1) + local rc=$? + + json_init + json_add_int "code" "$rc" + json_add_string "output" "$output" + json_dump +} + +# Stop app +do_stop() { + local name="$1" + [ -z "$name" ] && { echo '{"error":"App name required"}'; return; } + + local output + output=$(slforge stop "$name" 2>&1) + local rc=$? + + json_init + json_add_int "code" "$rc" + json_add_string "output" "$output" + json_dump +} + +# Restart app +do_restart() { + local name="$1" + [ -z "$name" ] && { echo '{"error":"App name required"}'; return; } + + local output + output=$(slforge restart "$name" 2>&1) + local rc=$? + + json_init + json_add_int "code" "$rc" + json_add_string "output" "$output" + json_dump +} + +# Expose app +do_expose() { + local name="$1" + local domain="$2" + + [ -z "$name" ] && { echo '{"error":"App name required"}'; return; } + + local output + if [ -n "$domain" ]; then + output=$(slforge expose "$name" --domain "$domain" 2>&1) + else + output=$(slforge expose "$name" 2>&1) + fi + local rc=$? + + json_init + json_add_int "code" "$rc" + json_add_string "output" "$output" + json_dump +} + +# Hide app +do_hide() { + local name="$1" + [ -z "$name" ] && { echo '{"error":"App name required"}'; return; } + + local output + output=$(slforge hide "$name" 2>&1) + local rc=$? + + json_init + json_add_int "code" "$rc" + json_add_string "output" "$output" + json_dump +} + +# Publish to mesh +do_publish() { + local name="$1" + [ -z "$name" ] && { echo '{"error":"App name required"}'; return; } + + local output + output=$(slforge publish "$name" 2>&1) + local rc=$? + + json_init + json_add_int "code" "$rc" + json_add_string "output" "$output" + json_dump +} + +# Unpublish from mesh +do_unpublish() { + local name="$1" + [ -z "$name" ] && { echo '{"error":"App name required"}'; return; } + + local output + output=$(slforge unpublish "$name" 2>&1) + local rc=$? + + json_init + json_add_int "code" "$rc" + json_add_string "output" "$output" + json_dump +} + +# Set config +do_set_config() { + local name="$1" + local key="$2" + local value="$3" + + [ -z "$name" ] && { echo '{"error":"App name required"}'; return; } + [ -z "$key" ] && { echo '{"error":"Key required"}'; return; } + + uci set streamlit-forge."$name"."$key"="$value" + uci commit streamlit-forge + + json_init + json_add_int "code" 0 + json_add_string "message" "Config updated" + json_dump +} + +# Get config +get_config() { + local name="$1" + [ -z "$name" ] && { echo '{"error":"App name required"}'; return; } + + json_init + config_load streamlit-forge + + local enabled port domain entrypoint memory + config_get enabled "$name" enabled '0' + config_get port "$name" port '' + config_get domain "$name" domain '' + config_get entrypoint "$name" entrypoint 'app.py' + config_get memory "$name" memory '512M' + + json_add_string "enabled" "$enabled" + json_add_string "port" "$port" + json_add_string "domain" "$domain" + json_add_string "entrypoint" "$entrypoint" + json_add_string "memory" "$memory" + json_dump +} + +case "$1" in + list) + echo '{"list":{},"status":{},"info":{"name":"String"},"templates":{},"config":{"name":"String"},"create":{"name":"String","template":"String"},"delete":{"name":"String"},"start":{"name":"String"},"stop":{"name":"String"},"restart":{"name":"String"},"expose":{"name":"String","domain":"String"},"hide":{"name":"String"},"publish":{"name":"String"},"unpublish":{"name":"String"},"set_config":{"name":"String","key":"String","value":"String"}}' + ;; + call) + case "$2" in + list) get_apps ;; + status) get_status ;; + info) read input; json_load "$input"; json_get_var name name; get_info "$name" ;; + templates) get_templates ;; + config) read input; json_load "$input"; json_get_var name name; get_config "$name" ;; + create) read input; json_load "$input"; json_get_var name name; json_get_var template template; do_create "$name" "$template" ;; + delete) read input; json_load "$input"; json_get_var name name; do_delete "$name" ;; + start) read input; json_load "$input"; json_get_var name name; do_start "$name" ;; + stop) read input; json_load "$input"; json_get_var name name; do_stop "$name" ;; + restart) read input; json_load "$input"; json_get_var name name; do_restart "$name" ;; + expose) read input; json_load "$input"; json_get_var name name; json_get_var domain domain; do_expose "$name" "$domain" ;; + hide) read input; json_load "$input"; json_get_var name name; do_hide "$name" ;; + publish) read input; json_load "$input"; json_get_var name name; do_publish "$name" ;; + unpublish) read input; json_load "$input"; json_get_var name name; do_unpublish "$name" ;; + set_config) read input; json_load "$input"; json_get_var name name; json_get_var key key; json_get_var value value; do_set_config "$name" "$key" "$value" ;; + esac + ;; +esac diff --git a/package/secubox/luci-app-streamlit-forge/root/usr/share/luci/menu.d/luci-app-streamlit-forge.json b/package/secubox/luci-app-streamlit-forge/root/usr/share/luci/menu.d/luci-app-streamlit-forge.json new file mode 100644 index 00000000..8ef88d36 --- /dev/null +++ b/package/secubox/luci-app-streamlit-forge/root/usr/share/luci/menu.d/luci-app-streamlit-forge.json @@ -0,0 +1,14 @@ +{ + "admin/services/streamlit-forge": { + "title": "Streamlit Forge", + "order": 85, + "action": { + "type": "view", + "path": "streamlit-forge/overview" + }, + "depends": { + "acl": ["luci-app-streamlit-forge"], + "uci": { "streamlit-forge": true } + } + } +} diff --git a/package/secubox/luci-app-streamlit-forge/root/usr/share/rpcd/acl.d/luci-app-streamlit-forge.json b/package/secubox/luci-app-streamlit-forge/root/usr/share/rpcd/acl.d/luci-app-streamlit-forge.json new file mode 100644 index 00000000..b65d29b1 --- /dev/null +++ b/package/secubox/luci-app-streamlit-forge/root/usr/share/rpcd/acl.d/luci-app-streamlit-forge.json @@ -0,0 +1,17 @@ +{ + "luci-app-streamlit-forge": { + "description": "Grant access to Streamlit Forge", + "read": { + "ubus": { + "luci.streamlit-forge": ["list", "status", "info", "templates", "config"] + }, + "uci": ["streamlit-forge"] + }, + "write": { + "ubus": { + "luci.streamlit-forge": ["create", "delete", "start", "stop", "restart", "expose", "hide", "publish", "unpublish", "set_config"] + }, + "uci": ["streamlit-forge"] + } + } +} diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/Packages b/package/secubox/secubox-app-bonus/root/www/secubox-feed/Packages index 6420732f..2943558c 100644 --- a/package/secubox/secubox-app-bonus/root/www/secubox-feed/Packages +++ b/package/secubox/secubox-app-bonus/root/www/secubox-feed/Packages @@ -7,7 +7,7 @@ Architecture: all Installed-Size: 61440 Description: Data Sovereignty Engine with multi-tier classification for ANSSI CSPN compliance Filename: luci-app-ai-gateway_1.0.0-r1_all.ipk -Size: 10787 +Size: 10789 Package: luci-app-ai-insights Version: 1.0.0-r1 @@ -22,7 +22,7 @@ Description: Unified AI security insights dashboard for SecuBox. DNS Guard, Network Anomaly, CVE Triage, and LocalRecall. Provides security posture scoring and AI-powered analysis. Filename: luci-app-ai-insights_1.0.0-r1_all.ipk -Size: 11635 +Size: 11638 Package: luci-app-auth-guardian Version: 0.4.0-r3 @@ -34,7 +34,7 @@ Architecture: all Installed-Size: 71680 Description: Comprehensive authentication and session management with captive portal, OAuth2/OIDC integration, voucher system, and time-based access control Filename: luci-app-auth-guardian_0.4.0-r3_all.ipk -Size: 12393 +Size: 12391 Package: luci-app-backup Version: 1.0.0-r1 @@ -46,7 +46,7 @@ Architecture: all Installed-Size: 30720 Description: LuCI Backup Manager Filename: luci-app-backup_1.0.0-r1_all.ipk -Size: 4535 +Size: 4532 Package: luci-app-bandwidth-manager Version: 0.5.0-r2 @@ -58,7 +58,7 @@ Architecture: all Installed-Size: 337920 Description: Advanced bandwidth management with QoS rules, client quotas, and SQM integration Filename: luci-app-bandwidth-manager_0.5.0-r2_all.ipk -Size: 61684 +Size: 61683 Package: luci-app-cdn-cache Version: 0.5.0-r3 @@ -70,7 +70,7 @@ Architecture: all Installed-Size: 122880 Description: Dashboard for managing local CDN caching proxy on OpenWrt Filename: luci-app-cdn-cache_0.5.0-r3_all.ipk -Size: 24252 +Size: 24256 Package: luci-app-client-guardian Version: 0.4.0-r7 @@ -82,7 +82,7 @@ Architecture: all Installed-Size: 276480 Description: Network Access Control with client monitoring, zone management, captive portal, parental controls, and SMS/email alerts Filename: luci-app-client-guardian_0.4.0-r7_all.ipk -Size: 52682 +Size: 52687 Package: luci-app-cloner Version: 1.0.0-r1 @@ -93,7 +93,7 @@ Architecture: all Installed-Size: 102400 Description: SecuBox cloning station for building and deploying clone images Filename: luci-app-cloner_1.0.0-r1_all.ipk -Size: 19431 +Size: 19434 Package: luci-app-config-advisor Version: 1.0.0-r1 @@ -105,7 +105,7 @@ Architecture: all Installed-Size: 51200 Description: ANSSI CSPN compliance checking and security configuration advisor Filename: luci-app-config-advisor_1.0.0-r1_all.ipk -Size: 8858 +Size: 8857 Package: luci-app-cookie-tracker Version: 1.0.0-r1 @@ -116,7 +116,7 @@ Architecture: all Installed-Size: 30720 Description: LuCI Cookie Tracker Dashboard Filename: luci-app-cookie-tracker_1.0.0-r1_all.ipk -Size: 5657 +Size: 5655 Package: luci-app-crowdsec-dashboard Version: 0.8.0-r1 @@ -140,7 +140,7 @@ Architecture: all Installed-Size: 30720 Description: LuCI CVE Triage Dashboard Filename: luci-app-cve-triage_1.0.0-r1_all.ipk -Size: 5942 +Size: 5941 Package: luci-app-cyberfeed Version: 0.1.1-r1 @@ -152,7 +152,7 @@ Architecture: all Installed-Size: 71680 Description: Cyberpunk-themed RSS feed aggregator dashboard with social media support Filename: luci-app-cyberfeed_0.1.1-r1_all.ipk -Size: 12884 +Size: 12882 Package: luci-app-device-intel Version: 1.0.0-r1 @@ -183,7 +183,7 @@ Description: SecuBox DNS Guard provides privacy-focused DNS management with AI- - Real-time alerts and blocklist management - Domain analysis with LocalAI integration Filename: luci-app-dnsguard_1.1.0-r1_all.ipk -Size: 12446 +Size: 12449 Package: luci-app-dns-provider Version: 1.0.0-r1 @@ -195,7 +195,7 @@ Architecture: all Installed-Size: 40960 Description: LuCI DNS Provider Manager Filename: luci-app-dns-provider_1.0.0-r1_all.ipk -Size: 7166 +Size: 7167 Package: luci-app-domoticz Version: 1.0.0-r1 @@ -207,7 +207,7 @@ Architecture: all Installed-Size: 40960 Description: LuCI Domoticz Home Automation Configuration Filename: luci-app-domoticz_1.0.0-r1_all.ipk -Size: 7122 +Size: 7123 Package: luci-app-exposure Version: 1.0.0-r3 @@ -219,7 +219,7 @@ Architecture: all Installed-Size: 71680 Description: LuCI SecuBox Service Exposure Manager Filename: luci-app-exposure_1.0.0-r3_all.ipk -Size: 11699 +Size: 11695 Package: luci-app-gitea Version: 1.0.0-r2 @@ -231,7 +231,7 @@ Architecture: all Installed-Size: 92160 Description: Modern dashboard for Gitea Platform management on OpenWrt Filename: luci-app-gitea_1.0.0-r2_all.ipk -Size: 16620 +Size: 16621 Package: luci-app-glances Version: 1.0.0-r2 @@ -243,7 +243,7 @@ Architecture: all Installed-Size: 51200 Description: Modern dashboard for Glances system monitoring with SecuBox theme Filename: luci-app-glances_1.0.0-r2_all.ipk -Size: 7017 +Size: 7015 Package: luci-app-gotosocial Version: 0.1.0-r1 @@ -255,7 +255,7 @@ Architecture: all Installed-Size: 51200 Description: LuCI app for GoToSocial Fediverse Server Filename: luci-app-gotosocial_0.1.0-r1_all.ipk -Size: 8208 +Size: 8206 Package: luci-app-haproxy Version: 1.0.0-r8 @@ -267,7 +267,7 @@ Architecture: all Installed-Size: 225280 Description: Web interface for managing HAProxy load balancer with vhosts, SSL certificates, and backend routing Filename: luci-app-haproxy_1.0.0-r8_all.ipk -Size: 35342 +Size: 35339 Package: luci-app-hexojs Version: 1.0.0-r3 @@ -279,7 +279,7 @@ Architecture: all Installed-Size: 194560 Description: Modern dashboard for Hexo static site generator on OpenWrt Filename: luci-app-hexojs_1.0.0-r3_all.ipk -Size: 30451 +Size: 30453 Package: luci-app-iot-guard Version: 1.0.0-r1 @@ -291,7 +291,7 @@ Architecture: all Installed-Size: 61440 Description: IoT device isolation and security monitoring interface Filename: luci-app-iot-guard_1.0.0-r1_all.ipk -Size: 10535 +Size: 10533 Package: luci-app-ipblocklist Version: 1.0.0-r1 @@ -303,7 +303,7 @@ Architecture: all Installed-Size: 40960 Description: SecuBox IP Blocklist - Static threat defense dashboard Filename: luci-app-ipblocklist_1.0.0-r1_all.ipk -Size: 6528 +Size: 6529 Package: luci-app-jabber Version: 0 @@ -315,7 +315,7 @@ Architecture: all Installed-Size: 61440 Description: LuCI Jabber/XMPP Server (Prosody) Filename: luci-app-jabber_0_all.ipk -Size: 9308 +Size: 9311 Package: luci-app-jellyfin Version: 1.0.0-r1 @@ -327,7 +327,7 @@ Architecture: all Installed-Size: 51200 Description: LuCI Jellyfin Media Server Configuration Filename: luci-app-jellyfin_1.0.0-r1_all.ipk -Size: 10486 +Size: 10483 Package: luci-app-jitsi Version: 1.0.0-r1 @@ -339,7 +339,7 @@ Architecture: all Installed-Size: 30720 Description: LuCI Jitsi Meet Configuration Filename: luci-app-jitsi_1.0.0-r1_all.ipk -Size: 5175 +Size: 5173 Package: luci-app-ksm-manager Version: 0.4.0-r2 @@ -351,7 +351,7 @@ Architecture: all Installed-Size: 112640 Description: Centralized cryptographic key management with hardware security module (HSM) support for Nitrokey and YubiKey devices. Provides secure key storage, certificate management, SSH key handling, and secret storage with audit logging. Filename: luci-app-ksm-manager_0.4.0-r2_all.ipk -Size: 18778 +Size: 18780 Package: luci-app-localai Version: 0.1.0-r15 @@ -375,7 +375,7 @@ Architecture: all Installed-Size: 40960 Description: LuCI LocalRecall AI Memory Dashboard Filename: luci-app-localrecall_1.0.0-r1_all.ipk -Size: 8415 +Size: 8413 Package: luci-app-lyrion Version: 1.0.0-r1 @@ -387,7 +387,7 @@ Architecture: all Installed-Size: 40960 Description: LuCI support for Lyrion Music Server Filename: luci-app-lyrion_1.0.0-r1_all.ipk -Size: 6841 +Size: 6837 Package: luci-app-mac-guardian Version: 0.5.0-r1 @@ -399,7 +399,7 @@ Architecture: all Installed-Size: 40960 Description: LuCI MAC Guardian - WiFi MAC Security Monitor Filename: luci-app-mac-guardian_0.5.0-r1_all.ipk -Size: 6660 +Size: 6667 Package: luci-app-magicmirror2 Version: 0.4.0-r6 @@ -411,7 +411,7 @@ Architecture: all Installed-Size: 71680 Description: Modern dashboard for MagicMirror2 smart display platform with module manager and SecuBox theme Filename: luci-app-magicmirror2_0.4.0-r6_all.ipk -Size: 12359 +Size: 12358 Package: luci-app-mailinabox Version: 1.0.0-r1 @@ -423,7 +423,7 @@ Architecture: all Installed-Size: 30720 Description: LuCI support for Mail-in-a-Box Filename: luci-app-mailinabox_1.0.0-r1_all.ipk -Size: 5484 +Size: 5482 Package: luci-app-mailserver Version: 1.0.0-r1 @@ -435,7 +435,7 @@ Architecture: all Installed-Size: 40960 Description: LuCI Mail Server Manager Filename: luci-app-mailserver_1.0.0-r1_all.ipk -Size: 6515 +Size: 6510 Package: luci-app-master-link Version: 1.0.0-r1 @@ -447,7 +447,7 @@ Architecture: all Installed-Size: 30720 Description: LuCI SecuBox Master-Link Mesh Management Filename: luci-app-master-link_1.0.0-r1_all.ipk -Size: 6305 +Size: 6309 Package: luci-app-matrix Version: 1.0.0-r1 @@ -459,7 +459,7 @@ Architecture: all Installed-Size: 40960 Description: LuCI Matrix Homeserver Dashboard Filename: luci-app-matrix_1.0.0-r1_all.ipk -Size: 7524 +Size: 7518 Package: luci-app-media-flow Version: 0.6.4-r1 @@ -471,7 +471,7 @@ Architecture: all Installed-Size: 133120 Description: Real-time detection and monitoring of streaming services (Netflix, YouTube, Spotify, etc.) with quality estimation, history tracking, and alerts. Supports nDPId local DPI and netifyd. Filename: luci-app-media-flow_0.6.4-r1_all.ipk -Size: 25380 +Size: 25379 Package: luci-app-metablogizer Version: 1.1.0-r1 @@ -483,7 +483,7 @@ Architecture: all Installed-Size: 133120 Description: LuCI support for MetaBlogizer Static Site Publisher Filename: luci-app-metablogizer_1.1.0-r1_all.ipk -Size: 26205 +Size: 26203 Package: luci-app-metabolizer Version: 1.0.0-r2 @@ -495,7 +495,7 @@ Architecture: all Installed-Size: 30720 Description: LuCI support for Metabolizer CMS Filename: luci-app-metabolizer_1.0.0-r2_all.ipk -Size: 4825 +Size: 4822 Package: luci-app-mitmproxy Version: 0.5.0-r2 @@ -519,7 +519,7 @@ Architecture: all Installed-Size: 51200 Description: Web interface for MMPM - MagicMirror Package Manager Filename: luci-app-mmpm_0.2.0-r3_all.ipk -Size: 7969 +Size: 7968 Package: luci-app-mqtt-bridge Version: 0.4.0-r4 @@ -531,7 +531,7 @@ Architecture: all Installed-Size: 122880 Description: USB-to-MQTT IoT hub with SecuBox theme Filename: luci-app-mqtt-bridge_0.4.0-r4_all.ipk -Size: 22691 +Size: 22688 Package: luci-app-ndpid Version: 1.1.2-r2 @@ -567,7 +567,7 @@ Architecture: all Installed-Size: 40960 Description: LuCI Network Anomaly Detection Dashboard Filename: luci-app-network-anomaly_1.0.0-r1_all.ipk -Size: 7646 +Size: 7641 Package: luci-app-network-modes Version: 0.5.0-r3 @@ -579,7 +579,7 @@ Architecture: all Installed-Size: 286720 Description: Configure OpenWrt for different network modes: Sniffer, Access Point, Relay, Router Filename: luci-app-network-modes_0.5.0-r3_all.ipk -Size: 54227 +Size: 54225 Package: luci-app-network-tweaks Version: 1.0.0-r7 @@ -591,7 +591,7 @@ Architecture: all Installed-Size: 81920 Description: Unified network services dashboard with DNS/hosts sync, CDN cache control, and WPAD auto-proxy configuration Filename: luci-app-network-tweaks_1.0.0-r7_all.ipk -Size: 15947 +Size: 15943 Package: luci-app-nextcloud Version: 1.0.0-r1 @@ -603,7 +603,7 @@ Architecture: all Installed-Size: 51200 Description: LuCI support for Nextcloud LXC Filename: luci-app-nextcloud_1.0.0-r1_all.ipk -Size: 10351 +Size: 10347 Package: luci-app-ollama Version: 0.1.0-r1 @@ -615,7 +615,7 @@ Architecture: all Installed-Size: 71680 Description: Modern dashboard for Ollama LLM management on OpenWrt Filename: luci-app-ollama_0.1.0-r1_all.ipk -Size: 14333 +Size: 14337 Package: luci-app-openclaw Version: 1.0.0-r1 @@ -627,7 +627,7 @@ Architecture: all Installed-Size: 40960 Description: Web interface for OpenClaw personal AI with Claude/OpenAI/Ollama support Filename: luci-app-openclaw_1.0.0-r1_all.ipk -Size: 8412 +Size: 8409 Package: luci-app-peertube Version: 0 @@ -639,7 +639,7 @@ Architecture: all Installed-Size: 30720 Description: LuCI PeerTube Video Platform Filename: luci-app-peertube_0_all.ipk -Size: 5757 +Size: 5755 Package: luci-app-picobrew Version: 1.0.0-r1 @@ -651,7 +651,7 @@ Architecture: all Installed-Size: 51200 Description: Modern dashboard for PicoBrew Server management on OpenWrt Filename: luci-app-picobrew_1.0.0-r1_all.ipk -Size: 9535 +Size: 9531 Package: luci-app-secubox Version: 0.7.1-r4 @@ -663,7 +663,7 @@ Architecture: all Installed-Size: 440320 Description: Central control hub for all SecuBox modules. Provides unified dashboard, module status, system health monitoring, and quick actions. Filename: luci-app-secubox_0.7.1-r4_all.ipk -Size: 82095 +Size: 82094 Package: luci-app-secubox-admin Version: 1.0.0-r19 @@ -686,7 +686,7 @@ Architecture: all Installed-Size: 81920 Description: LuCI SecuBox CrowdSec Dashboard Filename: luci-app-secubox-crowdsec_1.0.0-r3_all.ipk -Size: 13916 +Size: 13921 Package: luci-app-secubox-mirror Version: 0.1.0-r1 @@ -698,7 +698,7 @@ Architecture: all Installed-Size: 40960 Description: LuCI MirrorNet Dashboard Filename: luci-app-secubox-mirror_0.1.0-r1_all.ipk -Size: 5847 +Size: 5848 Package: luci-app-secubox-netdiag Version: 1.0.0-r1 @@ -710,7 +710,7 @@ Architecture: all Installed-Size: 81920 Description: Real-time DSA switch port statistics, error monitoring, and network health diagnostics Filename: luci-app-secubox-netdiag_1.0.0-r1_all.ipk -Size: 15344 +Size: 15342 Package: luci-app-secubox-netifyd Version: 1.2.1-r1 @@ -722,7 +722,7 @@ Architecture: all Installed-Size: 194560 Description: Complete LuCI interface for netifyd DPI engine with real-time flow monitoring, application detection, network analytics, and flow action plugins Filename: luci-app-secubox-netifyd_1.2.1-r1_all.ipk -Size: 36720 +Size: 36715 Package: luci-app-secubox-p2p Version: 0.1.0-r1 @@ -734,7 +734,7 @@ Architecture: all Installed-Size: 245760 Description: LuCI SecuBox P2P Hub Filename: luci-app-secubox-p2p_0.1.0-r1_all.ipk -Size: 46832 +Size: 46830 Package: luci-app-secubox-portal Version: 0.7.0-r3 @@ -758,7 +758,7 @@ Architecture: all Installed-Size: 61440 Description: Unified dashboard integrating netifyd DPI threats with CrowdSec intelligence for real-time threat monitoring and automated blocking Filename: luci-app-secubox-security-threats_1.0.0-r4_all.ipk -Size: 10656 +Size: 10657 Package: luci-app-secubox-users Version: 1.0.0-r1 @@ -769,7 +769,7 @@ Architecture: all Installed-Size: 30720 Description: LuCI SecuBox User Management Filename: luci-app-secubox-users_1.0.0-r1_all.ipk -Size: 5144 +Size: 5141 Package: luci-app-service-registry Version: 1.0.0-r1 @@ -781,7 +781,7 @@ Architecture: all Installed-Size: 194560 Description: Unified service aggregation with HAProxy vhosts, Tor hidden services, and QR-coded landing page Filename: luci-app-service-registry_1.0.0-r1_all.ipk -Size: 39952 +Size: 39953 Package: luci-app-simplex Version: 1.0.0-r1 @@ -793,7 +793,7 @@ Architecture: all Installed-Size: 40960 Description: LuCI SimpleX Chat Server Configuration Filename: luci-app-simplex_1.0.0-r1_all.ipk -Size: 7035 +Size: 7033 Package: luci-app-streamlit Version: 1.0.0-r11 @@ -805,7 +805,7 @@ Architecture: all Installed-Size: 112640 Description: Multi-instance Streamlit management with Gitea integration Filename: luci-app-streamlit_1.0.0-r11_all.ipk -Size: 20565 +Size: 20567 Package: luci-app-system-hub Version: 0.5.2-r2 @@ -817,7 +817,7 @@ Architecture: all Installed-Size: 327680 Description: Central system control with monitoring, services, logs, and backup Filename: luci-app-system-hub_0.5.2-r2_all.ipk -Size: 64292 +Size: 64290 Package: luci-app-threat-analyst Version: 1.0.0-r1 @@ -829,7 +829,7 @@ Architecture: all Installed-Size: 51200 Description: LuCI Threat Analyst Dashboard Filename: luci-app-threat-analyst_1.0.0-r1_all.ipk -Size: 10142 +Size: 10143 Package: luci-app-tor Version: 1.0.0-r1 @@ -865,7 +865,7 @@ Architecture: all Installed-Size: 81920 Description: Advanced traffic shaping with TC/CAKE for precise bandwidth control Filename: luci-app-traffic-shaper_0.4.0-r2_all.ipk -Size: 14587 +Size: 14589 Package: luci-app-vhost-manager Version: 0.5.0-r5 @@ -877,7 +877,7 @@ Architecture: all Installed-Size: 153600 Description: Nginx reverse proxy manager with Let's Encrypt SSL certificates, authentication, and WebSocket support Filename: luci-app-vhost-manager_0.5.0-r5_all.ipk -Size: 26278 +Size: 26282 Package: luci-app-voip Version: 1.0.0-r1 @@ -889,7 +889,7 @@ Architecture: all Installed-Size: 81920 Description: LuCI VoIP PBX Management Filename: luci-app-voip_1.0.0-r1_all.ipk -Size: 11040 +Size: 11048 Package: luci-app-vortex-dns Version: 1.0.0-r1 @@ -901,7 +901,7 @@ Architecture: all Installed-Size: 40960 Description: LuCI Vortex DNS Dashboard Filename: luci-app-vortex-dns_1.0.0-r1_all.ipk -Size: 6074 +Size: 6080 Package: luci-app-vortex-firewall Version: 1.0.0-r1 @@ -913,7 +913,7 @@ Architecture: all Installed-Size: 30720 Description: LuCI Vortex DNS Firewall Dashboard Filename: luci-app-vortex-firewall_1.0.0-r1_all.ipk -Size: 5452 +Size: 5453 Package: luci-app-wazuh Version: 1.0.0-r1 @@ -924,7 +924,7 @@ Architecture: all Installed-Size: 71680 Description: Unified security monitoring dashboard for Wazuh SIEM/XDR integration Filename: luci-app-wazuh_1.0.0-r1_all.ipk -Size: 11068 +Size: 11072 Package: luci-app-wireguard-dashboard Version: 0.7.0-r5 @@ -936,7 +936,7 @@ Architecture: all Installed-Size: 215040 Description: Modern dashboard for WireGuard VPN monitoring on OpenWrt Filename: luci-app-wireguard-dashboard_0.7.0-r5_all.ipk -Size: 42284 +Size: 42285 Package: luci-app-zigbee2mqtt Version: 1.0.0-r2 @@ -960,7 +960,7 @@ Architecture: all Installed-Size: 491520 Description: Global CyberMood design system (CSS/JS/i18n) shared by all SecuBox dashboards. Filename: luci-theme-secubox_0.4.8-r1_all.ipk -Size: 121588 +Size: 121590 Package: secubox-ai-gateway Version: 1.0.0-r1 @@ -985,7 +985,7 @@ Description: SecuBox AI Gateway implements the Data Classifier (Sovereignty Eng All cloud providers are opt-in. Local tier always active. Filename: secubox-ai-gateway_1.0.0-r1_all.ipk -Size: 13665 +Size: 13662 Package: secubox-app Version: 1.0.0-r2 @@ -996,7 +996,7 @@ Installed-Size: 92160 Description: Command line helper for SecuBox App Store manifests. Installs /usr/sbin/secubox-app and ships the default manifests under /usr/share/secubox/plugins/. Filename: secubox-app_1.0.0-r2_all.ipk -Size: 11185 +Size: 11186 Package: secubox-app-adguardhome Version: 1.0.0-r2 @@ -1010,7 +1010,7 @@ Description: Installer, configuration, and service manager for running AdGuard inside Docker on SecuBox-powered OpenWrt systems. Network-wide ad blocker with DNS-over-HTTPS/TLS support and detailed analytics. Filename: secubox-app-adguardhome_1.0.0-r2_all.ipk -Size: 2881 +Size: 2882 Package: secubox-app-auth-logger Version: 1.2.2-r1 @@ -1028,7 +1028,7 @@ Description: Logs authentication failures from LuCI/rpcd and Dropbear SSH - JavaScript hook to intercept login failures - CrowdSec parser and bruteforce scenario Filename: secubox-app-auth-logger_1.2.2-r1_all.ipk -Size: 9371 +Size: 9376 Package: secubox-app-crowdsec-custom Version: 1.1.0-r1 @@ -1053,7 +1053,7 @@ Description: Custom CrowdSec configurations for SecuBox web interface protectio - Insider WAF: LAN threat detection (C2, exfiltration, lateral movement) - Whitelist for trusted networks Filename: secubox-app-crowdsec-custom_1.1.0-r1_all.ipk -Size: 6946 +Size: 6942 Package: secubox-app-cs-firewall-bouncer Version: 0.0.31-r4 @@ -1080,7 +1080,7 @@ Description: SecuBox CrowdSec Firewall Bouncer for OpenWrt. - Automatic restart on firewall reload - procd service management Filename: secubox-app-cs-firewall-bouncer_0.0.31-r4_aarch64_cortex-a72.ipk -Size: 5049324 +Size: 5049323 Package: secubox-app-cyberfeed Version: 0.2.1-r1 @@ -1094,7 +1094,7 @@ Description: Cyberpunk-themed RSS feed aggregator for OpenWrt/SecuBox. Features emoji injection, neon styling, and RSS-Bridge support for social media feeds (Facebook, Twitter, Mastodon). Filename: secubox-app-cyberfeed_0.2.1-r1_all.ipk -Size: 12450 +Size: 12449 Package: secubox-app-device-intel Version: 1.0.0-r1 @@ -1108,7 +1108,7 @@ Description: Unified device inventory aggregating mac-guardian, client-guardian P2P mesh, and exposure scanner data. Includes heuristic classification and pluggable emulator modules for MQTT, Zigbee, and USB devices. Filename: secubox-app-device-intel_1.0.0-r1_all.ipk -Size: 13098 +Size: 13101 Package: secubox-app-dns-provider Version: 1.0.0-r1 @@ -1122,7 +1122,7 @@ Description: Programmatic DNS record management via provider APIs (OVH, Gandi Cloudflare). Provides the dnsctl CLI for record CRUD, zone sync DNS propagation verification, and ACME DNS-01 challenge support. Filename: secubox-app-dns-provider_1.0.0-r1_all.ipk -Size: 8258 +Size: 8259 Package: secubox-app-domoticz Version: 1.0.0-r4 @@ -1135,7 +1135,7 @@ Installed-Size: 30720 Description: Installer, configuration, and service manager for running Domoticz inside an LXC Alpine container on SecuBox-powered OpenWrt systems. Filename: secubox-app-domoticz_1.0.0-r4_all.ipk -Size: 7513 +Size: 7508 Package: secubox-app-exposure Version: 1.0.0-r1 @@ -1173,7 +1173,7 @@ Description: Gitea Git Platform - Self-hosted lightweight Git service Runs in LXC container with Alpine Linux. Configure in /etc/config/gitea. Filename: secubox-app-gitea_1.0.0-r5_all.ipk -Size: 9436 +Size: 9435 Package: secubox-app-gk2hub Version: 0.1.0-r1 @@ -1187,7 +1187,7 @@ Description: Dynamic landing page generator for GK2 SecuBox services. Aggregates Streamlit apps, MetaBlogizer sites, and infrastructure services into a single service directory page. Filename: secubox-app-gk2hub_0.1.0-r1_all.ipk -Size: 4060 +Size: 4061 Package: secubox-app-glances Version: 1.0.0-r1 @@ -1210,7 +1210,7 @@ Description: Glances - Cross-platform system monitoring tool for SecuBox. Runs in LXC container for isolation and security. Configure in /etc/config/glances. Filename: secubox-app-glances_1.0.0-r1_all.ipk -Size: 6142 +Size: 6137 Package: secubox-app-guacamole Version: 1.0.0-r1 @@ -1224,7 +1224,7 @@ Description: Apache Guacamole clientless remote desktop gateway. Runs in an LXC Debian container with guacd and Tomcat. Supports SSH, VNC, and RDP connections via web browser. Filename: secubox-app-guacamole_1.0.0-r1_all.ipk -Size: 6942 +Size: 6941 Package: secubox-app-haproxy Version: 1.0.0-r24 @@ -1268,7 +1268,7 @@ Description: Hexo CMS - Self-hosted static blog generator for OpenWrt Runs in LXC container with Alpine Linux. Configure in /etc/config/hexojs. Filename: secubox-app-hexojs_1.0.0-r8_all.ipk -Size: 100054 +Size: 100059 Package: secubox-app-ipblocklist Version: 1.0.0-r1 @@ -1283,7 +1283,7 @@ Description: Pre-emptive IP blocklist defense layer for SecuBox. Maintainer: Gandalf License: Apache-2.0 Filename: secubox-app-ipblocklist_1.0.0-r1_all.ipk -Size: 4701 +Size: 4699 Package: secubox-app-jabber Version: 1.0.0-r1 @@ -1297,7 +1297,7 @@ Description: Jabber/XMPP instant messaging server based on Prosody. Runs in an LXC Debian container with full XMPP support. Features multi-user chat (MUC), file uploads, and S2S federation. Filename: secubox-app-jabber_1.0.0-r1_all.ipk -Size: 13277 +Size: 13276 Package: secubox-app-jellyfin Version: 3.0.0-r1 @@ -1310,7 +1310,7 @@ Installed-Size: 20480 Description: Jellyfin media server running in LXC container. Free media server for streaming movies, TV shows, music, and photos. Filename: secubox-app-jellyfin_3.0.0-r1_all.ipk -Size: 4755 +Size: 4753 Package: secubox-app-jitsi Version: 1.0.0-r1 @@ -1335,7 +1335,7 @@ Description: Jitsi Meet - Secure, fully featured video conferencing for SecuBox Integrates with HAProxy for SSL termination. Configure in /etc/config/jitsi. Filename: secubox-app-jitsi_1.0.0-r1_all.ipk -Size: 8926 +Size: 8920 Package: secubox-app-localai Version: 3.9.0-r1 @@ -1401,7 +1401,7 @@ Description: Lyrion Media Server (formerly Logitech Media Server / Squeezebox S Auto-detects available runtime, preferring LXC for lower resource usage. Configure runtime in /etc/config/lyrion. Filename: secubox-app-lyrion_2.0.2-r1_all.ipk -Size: 8127 +Size: 8125 Package: secubox-app-mac-guardian Version: 0.5.0-r1 @@ -1416,7 +1416,7 @@ Description: WiFi MAC address security monitor for SecuBox. and spoofing. Integrates with CrowdSec and provides real-time hostapd hotplug detection. Filename: secubox-app-mac-guardian_0.5.0-r1_all.ipk -Size: 12097 +Size: 12093 Package: secubox-app-magicmirror2 Version: 0.4.0-r8 @@ -1463,7 +1463,7 @@ Description: Complete email server solution using docker-mailserver for SecuBox Commands: mailinaboxctl --help Filename: secubox-app-mailinabox_2.0.0-r1_all.ipk -Size: 7569 +Size: 7572 Package: secubox-app-mailserver Version: 2.0.0-r1 @@ -1476,7 +1476,7 @@ Installed-Size: 20480 Description: Postfix + Dovecot mail server running in LXC container. Supports IMAP/SMTP with SSL/TLS. Filename: secubox-app-mailserver_2.0.0-r1_all.ipk -Size: 5704 +Size: 5694 Package: secubox-app-matrix Version: 1.0.0-r1 @@ -1490,7 +1490,7 @@ Description: Matrix homeserver based on Conduit - a lightweight, high-performan Matrix server written in Rust. Runs in an LXC Debian container. Features E2EE messaging, federation, and mesh integration. Filename: secubox-app-matrix_1.0.0-r1_all.ipk -Size: 10448 +Size: 10451 Package: secubox-app-metabolizer Version: 1.0.0-r3 @@ -1511,7 +1511,7 @@ Description: Metabolizer Blog Pipeline - Integrated CMS with Git-based workflow Pipeline: Edit in Streamlit -> Push to Gitea -> Build with Hexo -> Publish Filename: secubox-app-metabolizer_1.0.0-r3_all.ipk -Size: 13979 +Size: 13976 Package: secubox-app-mitmproxy Version: 0.5.0-r19 @@ -1538,7 +1538,7 @@ Description: mitmproxy - Interactive HTTPS proxy for SecuBox-powered OpenWrt sy Runs in LXC container for isolation and security. Configure in /etc/config/mitmproxy. Filename: secubox-app-mitmproxy_0.5.0-r19_all.ipk -Size: 22956 +Size: 22957 Package: secubox-app-mmpm Version: 0.2.0-r5 @@ -1573,7 +1573,7 @@ Description: Nextcloud file sync and collaboration platform running in a Debian LXC container with MariaDB, Redis, and Nginx. Features HAProxy SSL integration, automated backups, and KISS LuCI dashboard. Filename: secubox-app-nextcloud_1.0.0-r2_all.ipk -Size: 9675 +Size: 9673 Package: secubox-app-ollama Version: 0.1.0-r1 @@ -1595,7 +1595,7 @@ Description: Ollama - Simple local LLM runtime for SecuBox-powered OpenWrt syst Runs in Docker/Podman container. Configure in /etc/config/ollama. Filename: secubox-app-ollama_0.1.0-r1_all.ipk -Size: 5735 +Size: 5731 Package: secubox-app-picobrew Version: 1.0.0-r7 @@ -1617,7 +1617,19 @@ Description: PicoBrew Server - Self-hosted brewing controller for PicoBrew devi Runs in LXC container with Python/Flask backend. Configure in /etc/config/picobrew. Filename: secubox-app-picobrew_1.0.0-r7_all.ipk -Size: 5539 +Size: 5537 + +Package: secubox-app-rezapp +Version: 1.0.0-r1 +Depends: docker, lxc, lxc-common, curl, wget-ssl, jsonfilter +Section: secubox +Architecture: all +Installed-Size: 40960 +Description: RezApp Forge converts Docker images to LXC containers and generates + SecuBox addon packages. Browse Docker Hub, GHCR, and LinuxServer.io + catalogs, convert images to LXC, and publish to the SecuBox app store. +Filename: secubox-app-rezapp_1.0.0-r1_all.ipk +Size: 8625 Package: secubox-app-rustdesk Version: 1.0.0-r1 @@ -1630,7 +1642,7 @@ Installed-Size: 20480 Description: Self-hosted RustDesk relay server for remote desktop access. Downloads and manages hbbs (ID server) and hbbr (relay server) binaries. Filename: secubox-app-rustdesk_1.0.0-r1_all.ipk -Size: 4463 +Size: 4461 Package: secubox-app-simplex Version: 1.0.0-r1 @@ -1695,7 +1707,20 @@ Description: Streamlit App Platform - Self-hosted Python data app platform Configure in /etc/config/streamlit. Filename: secubox-app-streamlit_1.0.0-r5_all.ipk -Size: 16514 +Size: 16512 + +Package: secubox-app-streamlit-forge +Version: 1.0.0-r1 +Depends: python3, python3-pip, lxc, lxc-common, curl, wget-ssl, jsonfilter +Section: secubox +Architecture: all +Installed-Size: 51200 +Description: Streamlit Forge is a comprehensive platform for creating, managing + and publishing Streamlit applications. Features include Gitea source + management, preview generation, UCI configuration sync, and mesh + appstore publishing. +Filename: secubox-app-streamlit-forge_1.0.0-r1_all.ipk +Size: 10814 Package: secubox-app-tor Version: 1.0.0-r1 @@ -1718,7 +1743,7 @@ Description: SecuBox Tor Shield - One-click Tor anonymization for OpenWrt Configure in /etc/config/tor-shield. Filename: secubox-app-tor_1.0.0-r1_all.ipk -Size: 7367 +Size: 7369 Package: secubox-app-voip Version: 1.0.0-r1 @@ -1732,7 +1757,7 @@ Description: VoIP PBX solution with Asterisk in LXC container. Features OVH SIP trunk integration, WebRTC support and Jabber/XMPP relay for SMS and voicemail notifications. Filename: secubox-app-voip_1.0.0-r1_all.ipk -Size: 11955 +Size: 11951 Package: secubox-app-webapp Version: 1.5.0-r7 @@ -1763,7 +1788,7 @@ Installed-Size: 20480 Description: Installer, configuration, and service manager for running Zigbee2MQTT inside an Alpine LXC container on SecuBox-powered OpenWrt systems. Filename: secubox-app-zigbee2mqtt_1.0.0-r3_all.ipk -Size: 5539 +Size: 5540 Package: secubox-config-advisor Version: 0.1.0-r1 @@ -1782,7 +1807,7 @@ Description: AI-powered configuration security advisor for SecuBox. - LocalAI integration for intelligent analysis - Automated remediation suggestions Filename: secubox-config-advisor_0.1.0-r1_all.ipk -Size: 14847 +Size: 14842 Package: secubox-content-pkg Version: 1.0.0-r1 @@ -1795,7 +1820,7 @@ Installed-Size: 20480 Description: Package Metablogizer sites and Streamlit apps as IPKs for P2P distribution. Auto-publishes content to the mesh feed for peer auto-sync. Filename: secubox-content-pkg_1.0.0-r1_all.ipk -Size: 3909 +Size: 3907 Package: secubox-cookie-tracker Version: 1.0.0-r1 @@ -1818,7 +1843,7 @@ Description: Cookie Tracker for SecuBox InterceptoR. Works with secubox-app-mitmproxy for transparent interception. Filename: secubox-cookie-tracker_1.0.0-r1_all.ipk -Size: 10643 +Size: 10639 Package: secubox-core Version: 0.10.0-r16 @@ -1838,7 +1863,7 @@ Description: SecuBox Core Framework provides the foundational infrastructure fo - Unified CLI interface - ubus RPC backend Filename: secubox-core_0.10.0-r16_all.ipk -Size: 127204 +Size: 127202 Package: secubox-cve-triage Version: 1.0.0-r1 @@ -1858,7 +1883,7 @@ Description: AI-powered CVE analysis and vulnerability management agent for Sec - Approval workflow for patch recommendations - LXC and Docker package monitoring Filename: secubox-cve-triage_1.0.0-r1_all.ipk -Size: 11829 +Size: 11826 Package: secubox-dns-guard Version: 1.0.0-r1 @@ -1877,7 +1902,7 @@ Description: SecuBox DNS Guard provides AI-powered DNS anomaly detection using - Unusual TLD pattern detection - Automatic blocklist generation with approval workflow Filename: secubox-dns-guard_1.0.0-r1_all.ipk -Size: 12482 +Size: 12480 Package: secubox-identity Version: 0.1.0-r1 @@ -1896,7 +1921,7 @@ Description: Decentralized identity management for SecuBox mesh nodes. - Peer identity verification - Trust scoring integration Filename: secubox-identity_0.1.0-r1_all.ipk -Size: 8090 +Size: 8089 Package: secubox-iot-guard Version: 1.0.0-r1 @@ -1912,7 +1937,7 @@ Description: IoT device isolation, classification, and security monitoring. risk scoring. Orchestrates Client Guardian, MAC Guardian Vortex Firewall, and Bandwidth Manager for IoT protection. Filename: secubox-iot-guard_1.0.0-r1_all.ipk -Size: 13363 +Size: 13370 Package: secubox-localrecall Version: 1.0.0-r1 @@ -1927,7 +1952,7 @@ Description: Persistent memory system for SecuBox AI agents. for context across sessions. LocalAI integration for semantic search and AI-powered summarization. Filename: secubox-localrecall_1.0.0-r1_all.ipk -Size: 7793 +Size: 7798 Package: secubox-master-link Version: 1.0.0-r1 @@ -1949,7 +1974,7 @@ Description: Secure mesh onboarding for SecuBox nodes via master/peer link. Configure in /etc/config/master-link. Filename: secubox-master-link_1.0.0-r1_all.ipk -Size: 15034 +Size: 15036 Package: secubox-mcp-server Version: 1.0.0-r1 @@ -1977,7 +2002,7 @@ Description: Model Context Protocol (MCP) server for SecuBox. - ai.explain_ban (Explain CrowdSec decisions) - ai.security_posture (Security assessment) Filename: secubox-mcp-server_1.0.0-r1_all.ipk -Size: 11428 +Size: 11427 Package: secubox-mirrornet Version: 0.1.0-r1 @@ -1995,7 +2020,7 @@ Description: MirrorNet core mesh orchestration for SecuBox. - Mesh health monitoring and anomaly detection - DID-based identity (did:plc compatible) Filename: secubox-mirrornet_0.1.0-r1_all.ipk -Size: 15305 +Size: 15303 Package: secubox-network-anomaly Version: 1.0.0-r1 @@ -2067,7 +2092,7 @@ Description: Autonomous threat analysis agent for SecuBox. Part of SecuBox AI Gateway (Couche 2). Filename: secubox-threat-analyst_1.0.0-r1_all.ipk -Size: 9866 +Size: 9865 Package: secubox-vortex-dns Version: 1.0.0-r1 @@ -2086,7 +2111,7 @@ Description: Meshed multi-dynamic subdomain delegation system for SecuBox. - Gossip-based exposure config sync - Submastering for nested hierarchies Filename: secubox-vortex-dns_1.0.0-r1_all.ipk -Size: 5439 +Size: 5441 Package: secubox-vortex-firewall Version: 1.0.0-r1 diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/Packages.gz b/package/secubox/secubox-app-bonus/root/www/secubox-feed/Packages.gz index 85bf6a6e..7bb00468 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/Packages.gz and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/Packages.gz differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/apps-local.json b/package/secubox/secubox-app-bonus/root/www/secubox-feed/apps-local.json index 1214a08e..58d11a33 100644 --- a/package/secubox/secubox-app-bonus/root/www/secubox-feed/apps-local.json +++ b/package/secubox/secubox-app-bonus/root/www/secubox-feed/apps-local.json @@ -1,12 +1,12 @@ { "feed_url": "/secubox-feed", - "generated": "2026-03-04T07:36:19+01:00", + "generated": "2026-03-11T08:34:40+01:00", "packages": [ { "name": "luci-app-ai-gateway", "version": "1.0.0-r1", "filename": "luci-app-ai-gateway_1.0.0-r1_all.ipk", - "size": 10787, + "size": 10789, "category": "utility", "icon": "package", "description": "SecuBox package", @@ -18,7 +18,7 @@ "name": "luci-app-ai-insights", "version": "1.0.0-r1", "filename": "luci-app-ai-insights_1.0.0-r1_all.ipk", - "size": 11635, + "size": 11638, "category": "utility", "icon": "package", "description": "SecuBox package", @@ -30,7 +30,7 @@ "name": "luci-app-auth-guardian", "version": "0.4.0-r3", "filename": "luci-app-auth-guardian_0.4.0-r3_all.ipk", - "size": 12393, + "size": 12391, "category": "security", "icon": "key", "description": "Authentication management", @@ -42,7 +42,7 @@ "name": "luci-app-backup", "version": "1.0.0-r1", "filename": "luci-app-backup_1.0.0-r1_all.ipk", - "size": 4535, + "size": 4532, "category": "utility", "icon": "package", "description": "SecuBox package", @@ -54,7 +54,7 @@ "name": "luci-app-bandwidth-manager", "version": "0.5.0-r2", "filename": "luci-app-bandwidth-manager_0.5.0-r2_all.ipk", - "size": 61684, + "size": 61683, "category": "network", "icon": "activity", "description": "Bandwidth monitoring and control", @@ -66,7 +66,7 @@ "name": "luci-app-cdn-cache", "version": "0.5.0-r3", "filename": "luci-app-cdn-cache_0.5.0-r3_all.ipk", - "size": 24252, + "size": 24256, "category": "network", "icon": "globe", "description": "CDN caching", @@ -78,7 +78,7 @@ "name": "luci-app-client-guardian", "version": "0.4.0-r7", "filename": "luci-app-client-guardian_0.4.0-r7_all.ipk", - "size": 52682, + "size": 52687, "category": "network", "icon": "users", "description": "Client management and monitoring", @@ -90,7 +90,7 @@ "name": "luci-app-cloner", "version": "1.0.0-r1", "filename": "luci-app-cloner_1.0.0-r1_all.ipk", - "size": 19431, + "size": 19434, "category": "utility", "icon": "package", "description": "SecuBox package", @@ -102,7 +102,7 @@ "name": "luci-app-config-advisor", "version": "1.0.0-r1", "filename": "luci-app-config-advisor_1.0.0-r1_all.ipk", - "size": 8858, + "size": 8857, "category": "utility", "icon": "package", "description": "SecuBox package", @@ -114,7 +114,7 @@ "name": "luci-app-cookie-tracker", "version": "1.0.0-r1", "filename": "luci-app-cookie-tracker_1.0.0-r1_all.ipk", - "size": 5657, + "size": 5655, "category": "utility", "icon": "package", "description": "SecuBox package", @@ -138,7 +138,7 @@ "name": "luci-app-cve-triage", "version": "1.0.0-r1", "filename": "luci-app-cve-triage_1.0.0-r1_all.ipk", - "size": 5942, + "size": 5941, "category": "utility", "icon": "package", "description": "SecuBox package", @@ -150,7 +150,7 @@ "name": "luci-app-cyberfeed", "version": "0.1.1-r1", "filename": "luci-app-cyberfeed_0.1.1-r1_all.ipk", - "size": 12884, + "size": 12882, "category": "utility", "icon": "package", "description": "SecuBox package", @@ -174,7 +174,7 @@ "name": "luci-app-dnsguard", "version": "1.1.0-r1", "filename": "luci-app-dnsguard_1.1.0-r1_all.ipk", - "size": 12446, + "size": 12449, "category": "utility", "icon": "package", "description": "SecuBox package", @@ -186,7 +186,7 @@ "name": "luci-app-dns-provider", "version": "1.0.0-r1", "filename": "luci-app-dns-provider_1.0.0-r1_all.ipk", - "size": 7166, + "size": 7167, "category": "utility", "icon": "package", "description": "SecuBox package", @@ -198,7 +198,7 @@ "name": "luci-app-domoticz", "version": "1.0.0-r1", "filename": "luci-app-domoticz_1.0.0-r1_all.ipk", - "size": 7122, + "size": 7123, "category": "utility", "icon": "package", "description": "SecuBox package", @@ -210,7 +210,7 @@ "name": "luci-app-exposure", "version": "1.0.0-r3", "filename": "luci-app-exposure_1.0.0-r3_all.ipk", - "size": 11699, + "size": 11695, "category": "utility", "icon": "package", "description": "SecuBox package", @@ -222,7 +222,7 @@ "name": "luci-app-gitea", "version": "1.0.0-r2", "filename": "luci-app-gitea_1.0.0-r2_all.ipk", - "size": 16620, + "size": 16621, "category": "utility", "icon": "package", "description": "SecuBox package", @@ -234,7 +234,7 @@ "name": "luci-app-glances", "version": "1.0.0-r2", "filename": "luci-app-glances_1.0.0-r2_all.ipk", - "size": 7017, + "size": 7015, "category": "utility", "icon": "package", "description": "SecuBox package", @@ -246,7 +246,7 @@ "name": "luci-app-gotosocial", "version": "0.1.0-r1", "filename": "luci-app-gotosocial_0.1.0-r1_all.ipk", - "size": 8208, + "size": 8206, "category": "utility", "icon": "package", "description": "SecuBox package", @@ -258,7 +258,7 @@ "name": "luci-app-haproxy", "version": "1.0.0-r8", "filename": "luci-app-haproxy_1.0.0-r8_all.ipk", - "size": 35342, + "size": 35339, "category": "utility", "icon": "package", "description": "SecuBox package", @@ -270,7 +270,7 @@ "name": "luci-app-hexojs", "version": "1.0.0-r3", "filename": "luci-app-hexojs_1.0.0-r3_all.ipk", - "size": 30451, + "size": 30453, "category": "utility", "icon": "package", "description": "SecuBox package", @@ -282,7 +282,7 @@ "name": "luci-app-iot-guard", "version": "1.0.0-r1", "filename": "luci-app-iot-guard_1.0.0-r1_all.ipk", - "size": 10535, + "size": 10533, "category": "utility", "icon": "package", "description": "SecuBox package", @@ -294,7 +294,7 @@ "name": "luci-app-ipblocklist", "version": "1.0.0-r1", "filename": "luci-app-ipblocklist_1.0.0-r1_all.ipk", - "size": 6528, + "size": 6529, "category": "utility", "icon": "package", "description": "SecuBox package", @@ -306,7 +306,7 @@ "name": "luci-app-jabber", "version": "0", "filename": "luci-app-jabber_0_all.ipk", - "size": 9308, + "size": 9311, "category": "utility", "icon": "package", "description": "SecuBox package", @@ -318,7 +318,7 @@ "name": "luci-app-jellyfin", "version": "1.0.0-r1", "filename": "luci-app-jellyfin_1.0.0-r1_all.ipk", - "size": 10486, + "size": 10483, "category": "utility", "icon": "package", "description": "SecuBox package", @@ -330,7 +330,7 @@ "name": "luci-app-jitsi", "version": "1.0.0-r1", "filename": "luci-app-jitsi_1.0.0-r1_all.ipk", - "size": 5175, + "size": 5173, "category": "utility", "icon": "package", "description": "SecuBox package", @@ -342,7 +342,7 @@ "name": "luci-app-ksm-manager", "version": "0.4.0-r2", "filename": "luci-app-ksm-manager_0.4.0-r2_all.ipk", - "size": 18778, + "size": 18780, "category": "system", "icon": "cpu", "description": "Kernel memory management", @@ -366,7 +366,7 @@ "name": "luci-app-localrecall", "version": "1.0.0-r1", "filename": "luci-app-localrecall_1.0.0-r1_all.ipk", - "size": 8415, + "size": 8413, "category": "utility", "icon": "package", "description": "SecuBox package", @@ -378,7 +378,7 @@ "name": "luci-app-lyrion", "version": "1.0.0-r1", "filename": "luci-app-lyrion_1.0.0-r1_all.ipk", - "size": 6841, + "size": 6837, "category": "utility", "icon": "package", "description": "SecuBox package", @@ -390,7 +390,7 @@ "name": "luci-app-mac-guardian", "version": "0.5.0-r1", "filename": "luci-app-mac-guardian_0.5.0-r1_all.ipk", - "size": 6660, + "size": 6667, "category": "utility", "icon": "package", "description": "SecuBox package", @@ -402,7 +402,7 @@ "name": "luci-app-magicmirror2", "version": "0.4.0-r6", "filename": "luci-app-magicmirror2_0.4.0-r6_all.ipk", - "size": 12359, + "size": 12358, "category": "iot", "icon": "monitor", "description": "Smart mirror display", @@ -414,7 +414,7 @@ "name": "luci-app-mailinabox", "version": "1.0.0-r1", "filename": "luci-app-mailinabox_1.0.0-r1_all.ipk", - "size": 5484, + "size": 5482, "category": "utility", "icon": "package", "description": "SecuBox package", @@ -426,7 +426,7 @@ "name": "luci-app-mailserver", "version": "1.0.0-r1", "filename": "luci-app-mailserver_1.0.0-r1_all.ipk", - "size": 6515, + "size": 6510, "category": "utility", "icon": "package", "description": "SecuBox package", @@ -438,7 +438,7 @@ "name": "luci-app-master-link", "version": "1.0.0-r1", "filename": "luci-app-master-link_1.0.0-r1_all.ipk", - "size": 6305, + "size": 6309, "category": "utility", "icon": "package", "description": "SecuBox package", @@ -450,7 +450,7 @@ "name": "luci-app-matrix", "version": "1.0.0-r1", "filename": "luci-app-matrix_1.0.0-r1_all.ipk", - "size": 7524, + "size": 7518, "category": "utility", "icon": "package", "description": "SecuBox package", @@ -462,7 +462,7 @@ "name": "luci-app-media-flow", "version": "0.6.4-r1", "filename": "luci-app-media-flow_0.6.4-r1_all.ipk", - "size": 25380, + "size": 25379, "category": "media", "icon": "film", "description": "Media streaming", @@ -474,7 +474,7 @@ "name": "luci-app-metablogizer", "version": "1.1.0-r1", "filename": "luci-app-metablogizer_1.1.0-r1_all.ipk", - "size": 26205, + "size": 26203, "category": "utility", "icon": "package", "description": "SecuBox package", @@ -486,7 +486,7 @@ "name": "luci-app-metabolizer", "version": "1.0.0-r2", "filename": "luci-app-metabolizer_1.0.0-r2_all.ipk", - "size": 4825, + "size": 4822, "category": "utility", "icon": "package", "description": "SecuBox package", @@ -510,7 +510,7 @@ "name": "luci-app-mmpm", "version": "0.2.0-r3", "filename": "luci-app-mmpm_0.2.0-r3_all.ipk", - "size": 7969, + "size": 7968, "category": "utility", "icon": "package", "description": "SecuBox package", @@ -522,7 +522,7 @@ "name": "luci-app-mqtt-bridge", "version": "0.4.0-r4", "filename": "luci-app-mqtt-bridge_0.4.0-r4_all.ipk", - "size": 22691, + "size": 22688, "category": "iot", "icon": "message-square", "description": "MQTT bridge", @@ -558,7 +558,7 @@ "name": "luci-app-network-anomaly", "version": "1.0.0-r1", "filename": "luci-app-network-anomaly_1.0.0-r1_all.ipk", - "size": 7646, + "size": 7641, "category": "network", "icon": "wifi", "description": "Network configuration", @@ -570,7 +570,7 @@ "name": "luci-app-network-modes", "version": "0.5.0-r3", "filename": "luci-app-network-modes_0.5.0-r3_all.ipk", - "size": 54227, + "size": 54225, "category": "network", "icon": "wifi", "description": "Network configuration", @@ -582,7 +582,7 @@ "name": "luci-app-network-tweaks", "version": "1.0.0-r7", "filename": "luci-app-network-tweaks_1.0.0-r7_all.ipk", - "size": 15947, + "size": 15943, "category": "network", "icon": "wifi", "description": "Network configuration", @@ -594,7 +594,7 @@ "name": "luci-app-nextcloud", "version": "1.0.0-r1", "filename": "luci-app-nextcloud_1.0.0-r1_all.ipk", - "size": 10351, + "size": 10347, "category": "utility", "icon": "package", "description": "SecuBox package", @@ -606,7 +606,7 @@ "name": "luci-app-ollama", "version": "0.1.0-r1", "filename": "luci-app-ollama_0.1.0-r1_all.ipk", - "size": 14333, + "size": 14337, "category": "utility", "icon": "package", "description": "SecuBox package", @@ -618,7 +618,7 @@ "name": "luci-app-openclaw", "version": "1.0.0-r1", "filename": "luci-app-openclaw_1.0.0-r1_all.ipk", - "size": 8412, + "size": 8409, "category": "utility", "icon": "package", "description": "SecuBox package", @@ -630,7 +630,7 @@ "name": "luci-app-peertube", "version": "0", "filename": "luci-app-peertube_0_all.ipk", - "size": 5757, + "size": 5755, "category": "utility", "icon": "package", "description": "SecuBox package", @@ -642,7 +642,7 @@ "name": "luci-app-picobrew", "version": "1.0.0-r1", "filename": "luci-app-picobrew_1.0.0-r1_all.ipk", - "size": 9535, + "size": 9531, "category": "utility", "icon": "package", "description": "SecuBox package", @@ -654,7 +654,7 @@ "name": "luci-app-secubox", "version": "0.7.1-r4", "filename": "luci-app-secubox_0.7.1-r4_all.ipk", - "size": 82095, + "size": 82094, "category": "system", "icon": "box", "description": "SecuBox system component", @@ -678,7 +678,7 @@ "name": "luci-app-secubox-crowdsec", "version": "1.0.0-r3", "filename": "luci-app-secubox-crowdsec_1.0.0-r3_all.ipk", - "size": 13916, + "size": 13921, "category": "system", "icon": "box", "description": "SecuBox system component", @@ -690,7 +690,7 @@ "name": "luci-app-secubox-mirror", "version": "0.1.0-r1", "filename": "luci-app-secubox-mirror_0.1.0-r1_all.ipk", - "size": 5847, + "size": 5848, "category": "system", "icon": "box", "description": "SecuBox system component", @@ -702,7 +702,7 @@ "name": "luci-app-secubox-netdiag", "version": "1.0.0-r1", "filename": "luci-app-secubox-netdiag_1.0.0-r1_all.ipk", - "size": 15344, + "size": 15342, "category": "system", "icon": "box", "description": "SecuBox system component", @@ -714,7 +714,7 @@ "name": "luci-app-secubox-netifyd", "version": "1.2.1-r1", "filename": "luci-app-secubox-netifyd_1.2.1-r1_all.ipk", - "size": 36720, + "size": 36715, "category": "system", "icon": "box", "description": "SecuBox system component", @@ -726,7 +726,7 @@ "name": "luci-app-secubox-p2p", "version": "0.1.0-r1", "filename": "luci-app-secubox-p2p_0.1.0-r1_all.ipk", - "size": 46832, + "size": 46830, "category": "system", "icon": "box", "description": "SecuBox system component", @@ -750,7 +750,7 @@ "name": "luci-app-secubox-security-threats", "version": "1.0.0-r4", "filename": "luci-app-secubox-security-threats_1.0.0-r4_all.ipk", - "size": 10656, + "size": 10657, "category": "system", "icon": "box", "description": "SecuBox system component", @@ -762,7 +762,7 @@ "name": "luci-app-secubox-users", "version": "1.0.0-r1", "filename": "luci-app-secubox-users_1.0.0-r1_all.ipk", - "size": 5144, + "size": 5141, "category": "system", "icon": "box", "description": "SecuBox system component", @@ -774,7 +774,7 @@ "name": "luci-app-service-registry", "version": "1.0.0-r1", "filename": "luci-app-service-registry_1.0.0-r1_all.ipk", - "size": 39952, + "size": 39953, "category": "utility", "icon": "package", "description": "SecuBox package", @@ -786,7 +786,7 @@ "name": "luci-app-simplex", "version": "1.0.0-r1", "filename": "luci-app-simplex_1.0.0-r1_all.ipk", - "size": 7035, + "size": 7033, "category": "utility", "icon": "package", "description": "SecuBox package", @@ -798,7 +798,7 @@ "name": "luci-app-streamlit", "version": "1.0.0-r11", "filename": "luci-app-streamlit_1.0.0-r11_all.ipk", - "size": 20565, + "size": 20567, "category": "utility", "icon": "package", "description": "SecuBox package", @@ -810,7 +810,7 @@ "name": "luci-app-system-hub", "version": "0.5.2-r2", "filename": "luci-app-system-hub_0.5.2-r2_all.ipk", - "size": 64292, + "size": 64290, "category": "system", "icon": "settings", "description": "System management", @@ -822,7 +822,7 @@ "name": "luci-app-threat-analyst", "version": "1.0.0-r1", "filename": "luci-app-threat-analyst_1.0.0-r1_all.ipk", - "size": 10142, + "size": 10143, "category": "utility", "icon": "package", "description": "SecuBox package", @@ -858,7 +858,7 @@ "name": "luci-app-traffic-shaper", "version": "0.4.0-r2", "filename": "luci-app-traffic-shaper_0.4.0-r2_all.ipk", - "size": 14587, + "size": 14589, "category": "network", "icon": "filter", "description": "Traffic shaping and QoS", @@ -870,7 +870,7 @@ "name": "luci-app-vhost-manager", "version": "0.5.0-r5", "filename": "luci-app-vhost-manager_0.5.0-r5_all.ipk", - "size": 26278, + "size": 26282, "category": "network", "icon": "server", "description": "Virtual host management", @@ -882,7 +882,7 @@ "name": "luci-app-voip", "version": "1.0.0-r1", "filename": "luci-app-voip_1.0.0-r1_all.ipk", - "size": 11040, + "size": 11048, "category": "utility", "icon": "package", "description": "SecuBox package", @@ -894,7 +894,7 @@ "name": "luci-app-vortex-dns", "version": "1.0.0-r1", "filename": "luci-app-vortex-dns_1.0.0-r1_all.ipk", - "size": 6074, + "size": 6080, "category": "utility", "icon": "package", "description": "SecuBox package", @@ -906,7 +906,7 @@ "name": "luci-app-vortex-firewall", "version": "1.0.0-r1", "filename": "luci-app-vortex-firewall_1.0.0-r1_all.ipk", - "size": 5452, + "size": 5453, "category": "utility", "icon": "package", "description": "SecuBox package", @@ -918,7 +918,7 @@ "name": "luci-app-wazuh", "version": "1.0.0-r1", "filename": "luci-app-wazuh_1.0.0-r1_all.ipk", - "size": 11068, + "size": 11072, "category": "utility", "icon": "package", "description": "SecuBox package", @@ -930,7 +930,7 @@ "name": "luci-app-wireguard-dashboard", "version": "0.7.0-r5", "filename": "luci-app-wireguard-dashboard_0.7.0-r5_all.ipk", - "size": 42284, + "size": 42285, "category": "vpn", "icon": "shield", "description": "WireGuard VPN dashboard", @@ -954,7 +954,7 @@ "name": "luci-theme-secubox", "version": "0.4.8-r1", "filename": "luci-theme-secubox_0.4.8-r1_all.ipk", - "size": 121588, + "size": 121590, "category": "theme", "icon": "palette", "description": "LuCI theme", @@ -966,7 +966,7 @@ "name": "secubox-ai-gateway", "version": "1.0.0-r1", "filename": "secubox-ai-gateway_1.0.0-r1_all.ipk", - "size": 13665, + "size": 13662, "category": "utility", "icon": "package", "description": "SecuBox package", @@ -978,7 +978,7 @@ "name": "secubox-app", "version": "1.0.0-r2", "filename": "secubox-app_1.0.0-r2_all.ipk", - "size": 11185, + "size": 11186, "category": "utility", "icon": "package", "description": "SecuBox package", @@ -990,7 +990,7 @@ "name": "secubox-app-adguardhome", "version": "1.0.0-r2", "filename": "secubox-app-adguardhome_1.0.0-r2_all.ipk", - "size": 2881, + "size": 2882, "category": "secubox", "icon": "package", "description": "SecuBox backend service", @@ -1002,7 +1002,7 @@ "name": "secubox-app-auth-logger", "version": "1.2.2-r1", "filename": "secubox-app-auth-logger_1.2.2-r1_all.ipk", - "size": 9371, + "size": 9376, "category": "secubox", "icon": "package", "description": "SecuBox backend service", @@ -1014,7 +1014,7 @@ "name": "secubox-app-crowdsec-custom", "version": "1.1.0-r1", "filename": "secubox-app-crowdsec-custom_1.1.0-r1_all.ipk", - "size": 6946, + "size": 6942, "category": "secubox", "icon": "package", "description": "SecuBox backend service", @@ -1026,7 +1026,7 @@ "name": "secubox-app-cs-firewall-bouncer", "version": "0.0.31-r4_aarch64", "filename": "secubox-app-cs-firewall-bouncer_0.0.31-r4_aarch64_cortex-a72.ipk", - "size": 5049324, + "size": 5049323, "category": "secubox", "icon": "package", "description": "SecuBox backend service", @@ -1038,7 +1038,7 @@ "name": "secubox-app-cyberfeed", "version": "0.2.1-r1", "filename": "secubox-app-cyberfeed_0.2.1-r1_all.ipk", - "size": 12450, + "size": 12449, "category": "secubox", "icon": "package", "description": "SecuBox backend service", @@ -1050,7 +1050,7 @@ "name": "secubox-app-device-intel", "version": "1.0.0-r1", "filename": "secubox-app-device-intel_1.0.0-r1_all.ipk", - "size": 13098, + "size": 13101, "category": "secubox", "icon": "package", "description": "SecuBox backend service", @@ -1062,7 +1062,7 @@ "name": "secubox-app-dns-provider", "version": "1.0.0-r1", "filename": "secubox-app-dns-provider_1.0.0-r1_all.ipk", - "size": 8258, + "size": 8259, "category": "secubox", "icon": "package", "description": "SecuBox backend service", @@ -1074,7 +1074,7 @@ "name": "secubox-app-domoticz", "version": "1.0.0-r4", "filename": "secubox-app-domoticz_1.0.0-r4_all.ipk", - "size": 7513, + "size": 7508, "category": "secubox", "icon": "package", "description": "SecuBox backend service", @@ -1098,7 +1098,7 @@ "name": "secubox-app-gitea", "version": "1.0.0-r5", "filename": "secubox-app-gitea_1.0.0-r5_all.ipk", - "size": 9436, + "size": 9435, "category": "secubox", "icon": "package", "description": "SecuBox backend service", @@ -1110,7 +1110,7 @@ "name": "secubox-app-gk2hub", "version": "0.1.0-r1", "filename": "secubox-app-gk2hub_0.1.0-r1_all.ipk", - "size": 4060, + "size": 4061, "category": "secubox", "icon": "package", "description": "SecuBox backend service", @@ -1122,7 +1122,7 @@ "name": "secubox-app-glances", "version": "1.0.0-r1", "filename": "secubox-app-glances_1.0.0-r1_all.ipk", - "size": 6142, + "size": 6137, "category": "secubox", "icon": "package", "description": "SecuBox backend service", @@ -1134,7 +1134,7 @@ "name": "secubox-app-guacamole", "version": "1.0.0-r1", "filename": "secubox-app-guacamole_1.0.0-r1_all.ipk", - "size": 6942, + "size": 6941, "category": "secubox", "icon": "package", "description": "SecuBox backend service", @@ -1158,7 +1158,7 @@ "name": "secubox-app-hexojs", "version": "1.0.0-r8", "filename": "secubox-app-hexojs_1.0.0-r8_all.ipk", - "size": 100054, + "size": 100059, "category": "secubox", "icon": "package", "description": "SecuBox backend service", @@ -1170,7 +1170,7 @@ "name": "secubox-app-ipblocklist", "version": "1.0.0-r1", "filename": "secubox-app-ipblocklist_1.0.0-r1_all.ipk", - "size": 4701, + "size": 4699, "category": "secubox", "icon": "package", "description": "SecuBox backend service", @@ -1182,7 +1182,7 @@ "name": "secubox-app-jabber", "version": "1.0.0-r1", "filename": "secubox-app-jabber_1.0.0-r1_all.ipk", - "size": 13277, + "size": 13276, "category": "secubox", "icon": "package", "description": "SecuBox backend service", @@ -1194,7 +1194,7 @@ "name": "secubox-app-jellyfin", "version": "3.0.0-r1", "filename": "secubox-app-jellyfin_3.0.0-r1_all.ipk", - "size": 4755, + "size": 4753, "category": "secubox", "icon": "package", "description": "SecuBox backend service", @@ -1206,7 +1206,7 @@ "name": "secubox-app-jitsi", "version": "1.0.0-r1", "filename": "secubox-app-jitsi_1.0.0-r1_all.ipk", - "size": 8926, + "size": 8920, "category": "secubox", "icon": "package", "description": "SecuBox backend service", @@ -1242,7 +1242,7 @@ "name": "secubox-app-lyrion", "version": "2.0.2-r1", "filename": "secubox-app-lyrion_2.0.2-r1_all.ipk", - "size": 8127, + "size": 8125, "category": "secubox", "icon": "package", "description": "SecuBox backend service", @@ -1254,7 +1254,7 @@ "name": "secubox-app-mac-guardian", "version": "0.5.0-r1", "filename": "secubox-app-mac-guardian_0.5.0-r1_all.ipk", - "size": 12097, + "size": 12093, "category": "secubox", "icon": "package", "description": "SecuBox backend service", @@ -1278,7 +1278,7 @@ "name": "secubox-app-mailinabox", "version": "2.0.0-r1", "filename": "secubox-app-mailinabox_2.0.0-r1_all.ipk", - "size": 7569, + "size": 7572, "category": "secubox", "icon": "package", "description": "SecuBox backend service", @@ -1290,7 +1290,7 @@ "name": "secubox-app-mailserver", "version": "2.0.0-r1", "filename": "secubox-app-mailserver_2.0.0-r1_all.ipk", - "size": 5704, + "size": 5694, "category": "secubox", "icon": "package", "description": "SecuBox backend service", @@ -1302,7 +1302,7 @@ "name": "secubox-app-matrix", "version": "1.0.0-r1", "filename": "secubox-app-matrix_1.0.0-r1_all.ipk", - "size": 10448, + "size": 10451, "category": "secubox", "icon": "package", "description": "SecuBox backend service", @@ -1314,7 +1314,7 @@ "name": "secubox-app-metabolizer", "version": "1.0.0-r3", "filename": "secubox-app-metabolizer_1.0.0-r3_all.ipk", - "size": 13979, + "size": 13976, "category": "secubox", "icon": "package", "description": "SecuBox backend service", @@ -1326,7 +1326,7 @@ "name": "secubox-app-mitmproxy", "version": "0.5.0-r19", "filename": "secubox-app-mitmproxy_0.5.0-r19_all.ipk", - "size": 22956, + "size": 22957, "category": "secubox", "icon": "package", "description": "SecuBox backend service", @@ -1350,7 +1350,7 @@ "name": "secubox-app-nextcloud", "version": "1.0.0-r2", "filename": "secubox-app-nextcloud_1.0.0-r2_all.ipk", - "size": 9675, + "size": 9673, "category": "secubox", "icon": "package", "description": "SecuBox backend service", @@ -1362,7 +1362,7 @@ "name": "secubox-app-ollama", "version": "0.1.0-r1", "filename": "secubox-app-ollama_0.1.0-r1_all.ipk", - "size": 5735, + "size": 5731, "category": "secubox", "icon": "package", "description": "SecuBox backend service", @@ -1374,19 +1374,31 @@ "name": "secubox-app-picobrew", "version": "1.0.0-r7", "filename": "secubox-app-picobrew_1.0.0-r7_all.ipk", - "size": 5539, + "size": 5537, "category": "secubox", "icon": "package", "description": "SecuBox backend service", "installed": false, "luci_app": "luci-app-picobrew" } +, + { + "name": "secubox-app-rezapp", + "version": "1.0.0-r1", + "filename": "secubox-app-rezapp_1.0.0-r1_all.ipk", + "size": 8625, + "category": "secubox", + "icon": "package", + "description": "SecuBox backend service", + "installed": false, + "luci_app": "luci-app-rezapp" + } , { "name": "secubox-app-rustdesk", "version": "1.0.0-r1", "filename": "secubox-app-rustdesk_1.0.0-r1_all.ipk", - "size": 4463, + "size": 4461, "category": "secubox", "icon": "package", "description": "SecuBox backend service", @@ -1422,19 +1434,31 @@ "name": "secubox-app-streamlit", "version": "1.0.0-r5", "filename": "secubox-app-streamlit_1.0.0-r5_all.ipk", - "size": 16514, + "size": 16512, "category": "secubox", "icon": "package", "description": "SecuBox backend service", "installed": false, "luci_app": "luci-app-streamlit" } +, + { + "name": "secubox-app-streamlit-forge", + "version": "1.0.0-r1", + "filename": "secubox-app-streamlit-forge_1.0.0-r1_all.ipk", + "size": 10814, + "category": "secubox", + "icon": "package", + "description": "SecuBox backend service", + "installed": false, + "luci_app": "luci-app-streamlit-forge" + } , { "name": "secubox-app-tor", "version": "1.0.0-r1", "filename": "secubox-app-tor_1.0.0-r1_all.ipk", - "size": 7367, + "size": 7369, "category": "secubox", "icon": "package", "description": "SecuBox backend service", @@ -1446,7 +1470,7 @@ "name": "secubox-app-voip", "version": "1.0.0-r1", "filename": "secubox-app-voip_1.0.0-r1_all.ipk", - "size": 11955, + "size": 11951, "category": "secubox", "icon": "package", "description": "SecuBox backend service", @@ -1470,7 +1494,7 @@ "name": "secubox-app-zigbee2mqtt", "version": "1.0.0-r3", "filename": "secubox-app-zigbee2mqtt_1.0.0-r3_all.ipk", - "size": 5539, + "size": 5540, "category": "secubox", "icon": "package", "description": "SecuBox backend service", @@ -1482,7 +1506,7 @@ "name": "secubox-config-advisor", "version": "0.1.0-r1", "filename": "secubox-config-advisor_0.1.0-r1_all.ipk", - "size": 14847, + "size": 14842, "category": "utility", "icon": "package", "description": "SecuBox package", @@ -1494,7 +1518,7 @@ "name": "secubox-content-pkg", "version": "1.0.0-r1", "filename": "secubox-content-pkg_1.0.0-r1_all.ipk", - "size": 3909, + "size": 3907, "category": "utility", "icon": "package", "description": "SecuBox package", @@ -1506,7 +1530,7 @@ "name": "secubox-cookie-tracker", "version": "1.0.0-r1", "filename": "secubox-cookie-tracker_1.0.0-r1_all.ipk", - "size": 10643, + "size": 10639, "category": "utility", "icon": "package", "description": "SecuBox package", @@ -1518,7 +1542,7 @@ "name": "secubox-core", "version": "0.10.0-r16", "filename": "secubox-core_0.10.0-r16_all.ipk", - "size": 127204, + "size": 127202, "category": "system", "icon": "box", "description": "SecuBox core components", @@ -1530,7 +1554,7 @@ "name": "secubox-cve-triage", "version": "1.0.0-r1", "filename": "secubox-cve-triage_1.0.0-r1_all.ipk", - "size": 11829, + "size": 11826, "category": "utility", "icon": "package", "description": "SecuBox package", @@ -1542,7 +1566,7 @@ "name": "secubox-dns-guard", "version": "1.0.0-r1", "filename": "secubox-dns-guard_1.0.0-r1_all.ipk", - "size": 12482, + "size": 12480, "category": "utility", "icon": "package", "description": "SecuBox package", @@ -1554,7 +1578,7 @@ "name": "secubox-identity", "version": "0.1.0-r1", "filename": "secubox-identity_0.1.0-r1_all.ipk", - "size": 8090, + "size": 8089, "category": "utility", "icon": "package", "description": "SecuBox package", @@ -1566,7 +1590,7 @@ "name": "secubox-iot-guard", "version": "1.0.0-r1", "filename": "secubox-iot-guard_1.0.0-r1_all.ipk", - "size": 13363, + "size": 13370, "category": "utility", "icon": "package", "description": "SecuBox package", @@ -1578,7 +1602,7 @@ "name": "secubox-localrecall", "version": "1.0.0-r1", "filename": "secubox-localrecall_1.0.0-r1_all.ipk", - "size": 7793, + "size": 7798, "category": "utility", "icon": "package", "description": "SecuBox package", @@ -1590,7 +1614,7 @@ "name": "secubox-master-link", "version": "1.0.0-r1", "filename": "secubox-master-link_1.0.0-r1_all.ipk", - "size": 15034, + "size": 15036, "category": "utility", "icon": "package", "description": "SecuBox package", @@ -1602,7 +1626,7 @@ "name": "secubox-mcp-server", "version": "1.0.0-r1", "filename": "secubox-mcp-server_1.0.0-r1_all.ipk", - "size": 11428, + "size": 11427, "category": "utility", "icon": "package", "description": "SecuBox package", @@ -1614,7 +1638,7 @@ "name": "secubox-mirrornet", "version": "0.1.0-r1", "filename": "secubox-mirrornet_0.1.0-r1_all.ipk", - "size": 15305, + "size": 15303, "category": "utility", "icon": "package", "description": "SecuBox package", @@ -1662,7 +1686,7 @@ "name": "secubox-threat-analyst", "version": "1.0.0-r1", "filename": "secubox-threat-analyst_1.0.0-r1_all.ipk", - "size": 9866, + "size": 9865, "category": "utility", "icon": "package", "description": "SecuBox package", @@ -1674,7 +1698,7 @@ "name": "secubox-vortex-dns", "version": "1.0.0-r1", "filename": "secubox-vortex-dns_1.0.0-r1_all.ipk", - "size": 5439, + "size": 5441, "category": "utility", "icon": "package", "description": "SecuBox package", diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-ai-gateway_1.0.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-ai-gateway_1.0.0-r1_all.ipk index 171f7611..7617a30d 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-ai-gateway_1.0.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-ai-gateway_1.0.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-ai-insights_1.0.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-ai-insights_1.0.0-r1_all.ipk index a8fbbf6b..04bb7baa 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-ai-insights_1.0.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-ai-insights_1.0.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-auth-guardian_0.4.0-r3_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-auth-guardian_0.4.0-r3_all.ipk index 186a7574..419dd204 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-auth-guardian_0.4.0-r3_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-auth-guardian_0.4.0-r3_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-backup_1.0.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-backup_1.0.0-r1_all.ipk index 13a653ca..6df12e41 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-backup_1.0.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-backup_1.0.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-bandwidth-manager_0.5.0-r2_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-bandwidth-manager_0.5.0-r2_all.ipk index 024a9008..81eab1d0 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-bandwidth-manager_0.5.0-r2_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-bandwidth-manager_0.5.0-r2_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-cdn-cache_0.5.0-r3_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-cdn-cache_0.5.0-r3_all.ipk index 633c8ccb..3085d003 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-cdn-cache_0.5.0-r3_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-cdn-cache_0.5.0-r3_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-client-guardian_0.4.0-r7_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-client-guardian_0.4.0-r7_all.ipk index 1faf00bd..ee4bc934 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-client-guardian_0.4.0-r7_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-client-guardian_0.4.0-r7_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-cloner_1.0.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-cloner_1.0.0-r1_all.ipk index fb1090d0..1881ae27 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-cloner_1.0.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-cloner_1.0.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-config-advisor_1.0.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-config-advisor_1.0.0-r1_all.ipk index aca69498..aca42cc9 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-config-advisor_1.0.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-config-advisor_1.0.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-cookie-tracker_1.0.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-cookie-tracker_1.0.0-r1_all.ipk index e8040d01..741a31ef 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-cookie-tracker_1.0.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-cookie-tracker_1.0.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-crowdsec-dashboard_0.8.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-crowdsec-dashboard_0.8.0-r1_all.ipk index db7ef36f..d7a99a31 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-crowdsec-dashboard_0.8.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-crowdsec-dashboard_0.8.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-cve-triage_1.0.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-cve-triage_1.0.0-r1_all.ipk index 226d642e..55a86a00 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-cve-triage_1.0.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-cve-triage_1.0.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-cyberfeed_0.1.1-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-cyberfeed_0.1.1-r1_all.ipk index 84580a4e..829fa67c 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-cyberfeed_0.1.1-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-cyberfeed_0.1.1-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-device-intel_1.0.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-device-intel_1.0.0-r1_all.ipk index 6bb6f094..23b7d658 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-device-intel_1.0.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-device-intel_1.0.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-dns-provider_1.0.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-dns-provider_1.0.0-r1_all.ipk index b1b0cc58..b02d46d9 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-dns-provider_1.0.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-dns-provider_1.0.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-dnsguard_1.1.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-dnsguard_1.1.0-r1_all.ipk index 9fabfcbc..f64ba2db 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-dnsguard_1.1.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-dnsguard_1.1.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-domoticz_1.0.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-domoticz_1.0.0-r1_all.ipk index 7c06dc2b..5af08292 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-domoticz_1.0.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-domoticz_1.0.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-exposure_1.0.0-r3_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-exposure_1.0.0-r3_all.ipk index d3f1905e..93194071 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-exposure_1.0.0-r3_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-exposure_1.0.0-r3_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-gitea_1.0.0-r2_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-gitea_1.0.0-r2_all.ipk index bbbb77d1..518e280d 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-gitea_1.0.0-r2_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-gitea_1.0.0-r2_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-glances_1.0.0-r2_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-glances_1.0.0-r2_all.ipk index 6f4e7dc5..fe5fc9fa 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-glances_1.0.0-r2_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-glances_1.0.0-r2_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-gotosocial_0.1.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-gotosocial_0.1.0-r1_all.ipk index 3f69c107..4ccccd4f 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-gotosocial_0.1.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-gotosocial_0.1.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-haproxy_1.0.0-r8_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-haproxy_1.0.0-r8_all.ipk index 36c06bd6..10ac6c86 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-haproxy_1.0.0-r8_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-haproxy_1.0.0-r8_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-hexojs_1.0.0-r3_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-hexojs_1.0.0-r3_all.ipk index 13417efe..105e057b 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-hexojs_1.0.0-r3_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-hexojs_1.0.0-r3_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-iot-guard_1.0.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-iot-guard_1.0.0-r1_all.ipk index 6d326ade..25eea6c4 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-iot-guard_1.0.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-iot-guard_1.0.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-ipblocklist_1.0.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-ipblocklist_1.0.0-r1_all.ipk index f02b981e..3e1897e6 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-ipblocklist_1.0.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-ipblocklist_1.0.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-jabber_0_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-jabber_0_all.ipk index f144613d..92b26913 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-jabber_0_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-jabber_0_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-jellyfin_1.0.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-jellyfin_1.0.0-r1_all.ipk index 349a7028..dbac1483 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-jellyfin_1.0.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-jellyfin_1.0.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-jitsi_1.0.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-jitsi_1.0.0-r1_all.ipk index a5efbfe3..ecd7014c 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-jitsi_1.0.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-jitsi_1.0.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-ksm-manager_0.4.0-r2_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-ksm-manager_0.4.0-r2_all.ipk index f97095aa..479ccc9f 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-ksm-manager_0.4.0-r2_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-ksm-manager_0.4.0-r2_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-localai_0.1.0-r15_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-localai_0.1.0-r15_all.ipk index 8fe0cf11..46cba6f7 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-localai_0.1.0-r15_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-localai_0.1.0-r15_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-localrecall_1.0.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-localrecall_1.0.0-r1_all.ipk index 5d42f321..58fc0d4f 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-localrecall_1.0.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-localrecall_1.0.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-lyrion_1.0.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-lyrion_1.0.0-r1_all.ipk index 620fbb1d..7fdabce2 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-lyrion_1.0.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-lyrion_1.0.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-mac-guardian_0.5.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-mac-guardian_0.5.0-r1_all.ipk index 57997ff9..47aa7fdb 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-mac-guardian_0.5.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-mac-guardian_0.5.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-magicmirror2_0.4.0-r6_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-magicmirror2_0.4.0-r6_all.ipk index a7ee7739..7e039cdb 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-magicmirror2_0.4.0-r6_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-magicmirror2_0.4.0-r6_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-mailinabox_1.0.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-mailinabox_1.0.0-r1_all.ipk index a2668582..6fd0a66f 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-mailinabox_1.0.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-mailinabox_1.0.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-mailserver_1.0.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-mailserver_1.0.0-r1_all.ipk index 12885ce7..2006fd5a 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-mailserver_1.0.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-mailserver_1.0.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-master-link_1.0.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-master-link_1.0.0-r1_all.ipk index 43cb4db7..d4369344 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-master-link_1.0.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-master-link_1.0.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-matrix_1.0.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-matrix_1.0.0-r1_all.ipk index 86223492..46829cb2 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-matrix_1.0.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-matrix_1.0.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-media-flow_0.6.4-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-media-flow_0.6.4-r1_all.ipk index 727f2d5e..184d833a 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-media-flow_0.6.4-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-media-flow_0.6.4-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-metablogizer_1.1.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-metablogizer_1.1.0-r1_all.ipk index a8f7de46..99cbdff1 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-metablogizer_1.1.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-metablogizer_1.1.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-metabolizer_1.0.0-r2_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-metabolizer_1.0.0-r2_all.ipk index 2ae20c2b..08e8f5f0 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-metabolizer_1.0.0-r2_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-metabolizer_1.0.0-r2_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-mitmproxy_0.5.0-r2_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-mitmproxy_0.5.0-r2_all.ipk index 5c67f3bd..6f46c3cb 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-mitmproxy_0.5.0-r2_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-mitmproxy_0.5.0-r2_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-mmpm_0.2.0-r3_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-mmpm_0.2.0-r3_all.ipk index 06c5ba9d..ca88c4f9 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-mmpm_0.2.0-r3_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-mmpm_0.2.0-r3_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-mqtt-bridge_0.4.0-r4_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-mqtt-bridge_0.4.0-r4_all.ipk index 2b0d10de..30ae85c4 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-mqtt-bridge_0.4.0-r4_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-mqtt-bridge_0.4.0-r4_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-ndpid_1.1.2-r2_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-ndpid_1.1.2-r2_all.ipk index fe8373a7..dfcc164e 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-ndpid_1.1.2-r2_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-ndpid_1.1.2-r2_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-netdata-dashboard_0.5.0-r2_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-netdata-dashboard_0.5.0-r2_all.ipk index 6ce3d2e9..e80de2ff 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-netdata-dashboard_0.5.0-r2_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-netdata-dashboard_0.5.0-r2_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-network-anomaly_1.0.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-network-anomaly_1.0.0-r1_all.ipk index d908bef7..d45a1ae6 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-network-anomaly_1.0.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-network-anomaly_1.0.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-network-modes_0.5.0-r3_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-network-modes_0.5.0-r3_all.ipk index f0254af5..9ee1337f 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-network-modes_0.5.0-r3_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-network-modes_0.5.0-r3_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-network-tweaks_1.0.0-r7_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-network-tweaks_1.0.0-r7_all.ipk index ff870b2e..e3fca5ea 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-network-tweaks_1.0.0-r7_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-network-tweaks_1.0.0-r7_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-nextcloud_1.0.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-nextcloud_1.0.0-r1_all.ipk index 30a70758..fb22ff28 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-nextcloud_1.0.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-nextcloud_1.0.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-ollama_0.1.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-ollama_0.1.0-r1_all.ipk index acef4976..40459afd 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-ollama_0.1.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-ollama_0.1.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-openclaw_1.0.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-openclaw_1.0.0-r1_all.ipk index f16222be..a953519a 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-openclaw_1.0.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-openclaw_1.0.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-peertube_0_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-peertube_0_all.ipk index bcec0c89..d8b6f8d1 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-peertube_0_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-peertube_0_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-picobrew_1.0.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-picobrew_1.0.0-r1_all.ipk index 6b2c1ac4..9bfa2cd3 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-picobrew_1.0.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-picobrew_1.0.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-secubox-admin_1.0.0-r19_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-secubox-admin_1.0.0-r19_all.ipk index 4f24c315..41735fd4 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-secubox-admin_1.0.0-r19_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-secubox-admin_1.0.0-r19_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-secubox-crowdsec_1.0.0-r3_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-secubox-crowdsec_1.0.0-r3_all.ipk index e8cfcc0d..09ab9c92 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-secubox-crowdsec_1.0.0-r3_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-secubox-crowdsec_1.0.0-r3_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-secubox-mirror_0.1.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-secubox-mirror_0.1.0-r1_all.ipk index 0facd626..d4fe04ea 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-secubox-mirror_0.1.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-secubox-mirror_0.1.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-secubox-netdiag_1.0.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-secubox-netdiag_1.0.0-r1_all.ipk index 93ca315a..06696c6c 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-secubox-netdiag_1.0.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-secubox-netdiag_1.0.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-secubox-netifyd_1.2.1-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-secubox-netifyd_1.2.1-r1_all.ipk index 09354474..0502b7db 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-secubox-netifyd_1.2.1-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-secubox-netifyd_1.2.1-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-secubox-p2p_0.1.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-secubox-p2p_0.1.0-r1_all.ipk index a89a6195..1104a0a0 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-secubox-p2p_0.1.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-secubox-p2p_0.1.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-secubox-portal_0.7.0-r3_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-secubox-portal_0.7.0-r3_all.ipk index bad3473b..1b543e31 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-secubox-portal_0.7.0-r3_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-secubox-portal_0.7.0-r3_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-secubox-security-threats_1.0.0-r4_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-secubox-security-threats_1.0.0-r4_all.ipk index 0966afd4..1f04df4c 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-secubox-security-threats_1.0.0-r4_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-secubox-security-threats_1.0.0-r4_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-secubox-users_1.0.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-secubox-users_1.0.0-r1_all.ipk index 08681b73..2245365f 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-secubox-users_1.0.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-secubox-users_1.0.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-secubox_0.7.1-r4_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-secubox_0.7.1-r4_all.ipk index f63bc23a..bfa045ae 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-secubox_0.7.1-r4_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-secubox_0.7.1-r4_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-service-registry_1.0.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-service-registry_1.0.0-r1_all.ipk index 8dbabd06..275af20d 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-service-registry_1.0.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-service-registry_1.0.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-simplex_1.0.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-simplex_1.0.0-r1_all.ipk index 4d63f079..7fdfcb46 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-simplex_1.0.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-simplex_1.0.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-streamlit_1.0.0-r11_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-streamlit_1.0.0-r11_all.ipk index cf4bb6d7..59e1daa7 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-streamlit_1.0.0-r11_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-streamlit_1.0.0-r11_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-system-hub_0.5.2-r2_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-system-hub_0.5.2-r2_all.ipk index e9cc1f02..d775fa1c 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-system-hub_0.5.2-r2_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-system-hub_0.5.2-r2_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-threat-analyst_1.0.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-threat-analyst_1.0.0-r1_all.ipk index 1d0edcb2..6376e08d 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-threat-analyst_1.0.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-threat-analyst_1.0.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-tor-shield_1.0.0-r10_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-tor-shield_1.0.0-r10_all.ipk index a5fb2cba..fb15faac 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-tor-shield_1.0.0-r10_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-tor-shield_1.0.0-r10_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-tor_1.0.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-tor_1.0.0-r1_all.ipk index a0e4b40c..9e5027e2 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-tor_1.0.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-tor_1.0.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-traffic-shaper_0.4.0-r2_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-traffic-shaper_0.4.0-r2_all.ipk index 477771eb..ec32d3a9 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-traffic-shaper_0.4.0-r2_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-traffic-shaper_0.4.0-r2_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-vhost-manager_0.5.0-r5_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-vhost-manager_0.5.0-r5_all.ipk index e610753b..ce2f79a5 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-vhost-manager_0.5.0-r5_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-vhost-manager_0.5.0-r5_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-voip_1.0.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-voip_1.0.0-r1_all.ipk index 056ed273..36b32a5c 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-voip_1.0.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-voip_1.0.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-vortex-dns_1.0.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-vortex-dns_1.0.0-r1_all.ipk index cf5092d2..bddfb99b 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-vortex-dns_1.0.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-vortex-dns_1.0.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-vortex-firewall_1.0.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-vortex-firewall_1.0.0-r1_all.ipk index d1dd6f3f..b401d0f6 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-vortex-firewall_1.0.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-vortex-firewall_1.0.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-wazuh_1.0.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-wazuh_1.0.0-r1_all.ipk index 0155cbcc..995573d7 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-wazuh_1.0.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-wazuh_1.0.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-wireguard-dashboard_0.7.0-r5_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-wireguard-dashboard_0.7.0-r5_all.ipk index 567ed6b7..52d4bbd8 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-wireguard-dashboard_0.7.0-r5_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-wireguard-dashboard_0.7.0-r5_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-zigbee2mqtt_1.0.0-r2_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-zigbee2mqtt_1.0.0-r2_all.ipk index 6520103d..983d3723 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-zigbee2mqtt_1.0.0-r2_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-app-zigbee2mqtt_1.0.0-r2_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-theme-secubox_0.4.8-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-theme-secubox_0.4.8-r1_all.ipk index 335756ac..1beda8c4 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-theme-secubox_0.4.8-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/luci-theme-secubox_0.4.8-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-ai-gateway_1.0.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-ai-gateway_1.0.0-r1_all.ipk index 87de1554..bf6e126d 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-ai-gateway_1.0.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-ai-gateway_1.0.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-adguardhome_1.0.0-r2_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-adguardhome_1.0.0-r2_all.ipk index 94dfdbcf..4adcb46a 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-adguardhome_1.0.0-r2_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-adguardhome_1.0.0-r2_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-auth-logger_1.2.2-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-auth-logger_1.2.2-r1_all.ipk index d07ddd60..9102844f 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-auth-logger_1.2.2-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-auth-logger_1.2.2-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-crowdsec-custom_1.1.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-crowdsec-custom_1.1.0-r1_all.ipk index bfb40faf..859b06ce 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-crowdsec-custom_1.1.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-crowdsec-custom_1.1.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-cs-firewall-bouncer_0.0.31-r4_aarch64_cortex-a72.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-cs-firewall-bouncer_0.0.31-r4_aarch64_cortex-a72.ipk index e8113e5e..ef57a79a 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-cs-firewall-bouncer_0.0.31-r4_aarch64_cortex-a72.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-cs-firewall-bouncer_0.0.31-r4_aarch64_cortex-a72.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-cyberfeed_0.2.1-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-cyberfeed_0.2.1-r1_all.ipk index fa3abb0b..ad27eb70 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-cyberfeed_0.2.1-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-cyberfeed_0.2.1-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-device-intel_1.0.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-device-intel_1.0.0-r1_all.ipk index 34fe77ee..d612c93f 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-device-intel_1.0.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-device-intel_1.0.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-dns-provider_1.0.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-dns-provider_1.0.0-r1_all.ipk index 28007a77..be3286a2 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-dns-provider_1.0.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-dns-provider_1.0.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-domoticz_1.0.0-r4_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-domoticz_1.0.0-r4_all.ipk index c38416a0..4a3d4f26 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-domoticz_1.0.0-r4_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-domoticz_1.0.0-r4_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-exposure_1.0.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-exposure_1.0.0-r1_all.ipk index 018a60b8..ffa1fec6 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-exposure_1.0.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-exposure_1.0.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-gitea_1.0.0-r5_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-gitea_1.0.0-r5_all.ipk index 4d159854..a6850538 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-gitea_1.0.0-r5_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-gitea_1.0.0-r5_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-gk2hub_0.1.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-gk2hub_0.1.0-r1_all.ipk index 14861897..81da4da0 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-gk2hub_0.1.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-gk2hub_0.1.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-glances_1.0.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-glances_1.0.0-r1_all.ipk index a6e57f58..779fef87 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-glances_1.0.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-glances_1.0.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-guacamole_1.0.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-guacamole_1.0.0-r1_all.ipk index 679b229b..69c91534 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-guacamole_1.0.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-guacamole_1.0.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-haproxy_1.0.0-r24_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-haproxy_1.0.0-r24_all.ipk index fa7108ae..6bda92da 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-haproxy_1.0.0-r24_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-haproxy_1.0.0-r24_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-hexojs_1.0.0-r8_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-hexojs_1.0.0-r8_all.ipk index 12ebee95..367d0d60 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-hexojs_1.0.0-r8_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-hexojs_1.0.0-r8_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-ipblocklist_1.0.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-ipblocklist_1.0.0-r1_all.ipk index 748947ca..dfc8bd79 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-ipblocklist_1.0.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-ipblocklist_1.0.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-jabber_1.0.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-jabber_1.0.0-r1_all.ipk index 14d3476c..6fca3da1 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-jabber_1.0.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-jabber_1.0.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-jellyfin_3.0.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-jellyfin_3.0.0-r1_all.ipk index 848aa9ab..b0b7ad07 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-jellyfin_3.0.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-jellyfin_3.0.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-jitsi_1.0.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-jitsi_1.0.0-r1_all.ipk index 13bdc4c3..1c21d8fb 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-jitsi_1.0.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-jitsi_1.0.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-localai-wb_2.25.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-localai-wb_2.25.0-r1_all.ipk index 63177bc5..d36a4f42 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-localai-wb_2.25.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-localai-wb_2.25.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-localai_3.9.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-localai_3.9.0-r1_all.ipk index ecc487ab..c3a17103 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-localai_3.9.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-localai_3.9.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-lyrion_2.0.2-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-lyrion_2.0.2-r1_all.ipk index 4169fbfd..db7c62d9 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-lyrion_2.0.2-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-lyrion_2.0.2-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-mac-guardian_0.5.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-mac-guardian_0.5.0-r1_all.ipk index 5ac5c454..6fca6633 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-mac-guardian_0.5.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-mac-guardian_0.5.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-magicmirror2_0.4.0-r8_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-magicmirror2_0.4.0-r8_all.ipk index d61ded78..9accc5c1 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-magicmirror2_0.4.0-r8_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-magicmirror2_0.4.0-r8_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-mailinabox_2.0.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-mailinabox_2.0.0-r1_all.ipk index a809c2eb..53bb2757 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-mailinabox_2.0.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-mailinabox_2.0.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-mailserver_2.0.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-mailserver_2.0.0-r1_all.ipk index 74666648..dfce3521 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-mailserver_2.0.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-mailserver_2.0.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-matrix_1.0.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-matrix_1.0.0-r1_all.ipk index b7af4528..6bd47c64 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-matrix_1.0.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-matrix_1.0.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-metabolizer_1.0.0-r3_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-metabolizer_1.0.0-r3_all.ipk index 3916d6c7..23448c75 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-metabolizer_1.0.0-r3_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-metabolizer_1.0.0-r3_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-mitmproxy_0.5.0-r19_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-mitmproxy_0.5.0-r19_all.ipk index 7c4e2b49..d9cca11e 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-mitmproxy_0.5.0-r19_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-mitmproxy_0.5.0-r19_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-mmpm_0.2.0-r5_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-mmpm_0.2.0-r5_all.ipk index 7becaabd..8c3e4a3b 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-mmpm_0.2.0-r5_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-mmpm_0.2.0-r5_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-nextcloud_1.0.0-r2_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-nextcloud_1.0.0-r2_all.ipk index 720ec893..d2e55b45 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-nextcloud_1.0.0-r2_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-nextcloud_1.0.0-r2_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-ollama_0.1.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-ollama_0.1.0-r1_all.ipk index e16f67ad..c68ac0b6 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-ollama_0.1.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-ollama_0.1.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-picobrew_1.0.0-r7_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-picobrew_1.0.0-r7_all.ipk index f6b02341..6bf81a36 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-picobrew_1.0.0-r7_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-picobrew_1.0.0-r7_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-rezapp_1.0.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-rezapp_1.0.0-r1_all.ipk new file mode 100644 index 00000000..547a15ce Binary files /dev/null and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-rezapp_1.0.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-rustdesk_1.0.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-rustdesk_1.0.0-r1_all.ipk index aa13b287..7f0bcab5 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-rustdesk_1.0.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-rustdesk_1.0.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-simplex_1.0.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-simplex_1.0.0-r1_all.ipk index e781eb5c..349d0642 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-simplex_1.0.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-simplex_1.0.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-smbfs_1.0.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-smbfs_1.0.0-r1_all.ipk index 09cb83c2..d74d0df6 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-smbfs_1.0.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-smbfs_1.0.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-streamlit-forge_1.0.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-streamlit-forge_1.0.0-r1_all.ipk new file mode 100644 index 00000000..98ef049a Binary files /dev/null and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-streamlit-forge_1.0.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-streamlit_1.0.0-r5_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-streamlit_1.0.0-r5_all.ipk index 4d8b12de..4aabe22c 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-streamlit_1.0.0-r5_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-streamlit_1.0.0-r5_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-tor_1.0.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-tor_1.0.0-r1_all.ipk index e7aafa6d..b1b9b182 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-tor_1.0.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-tor_1.0.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-voip_1.0.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-voip_1.0.0-r1_all.ipk index dc912e81..ba287ce2 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-voip_1.0.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-voip_1.0.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-webapp_1.5.0-r7_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-webapp_1.5.0-r7_all.ipk index 64b4af28..7e8f55b7 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-webapp_1.5.0-r7_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-webapp_1.5.0-r7_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-zigbee2mqtt_1.0.0-r3_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-zigbee2mqtt_1.0.0-r3_all.ipk index 71e636ee..a66fe5f9 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-zigbee2mqtt_1.0.0-r3_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app-zigbee2mqtt_1.0.0-r3_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app_1.0.0-r2_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app_1.0.0-r2_all.ipk index eb90ded4..7169940b 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app_1.0.0-r2_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-app_1.0.0-r2_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-config-advisor_0.1.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-config-advisor_0.1.0-r1_all.ipk index 66aa0d59..ec2c0935 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-config-advisor_0.1.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-config-advisor_0.1.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-content-pkg_1.0.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-content-pkg_1.0.0-r1_all.ipk index cbbed23b..eeab1351 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-content-pkg_1.0.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-content-pkg_1.0.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-cookie-tracker_1.0.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-cookie-tracker_1.0.0-r1_all.ipk index eb6f2a46..3352f73c 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-cookie-tracker_1.0.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-cookie-tracker_1.0.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-core_0.10.0-r16_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-core_0.10.0-r16_all.ipk index 4e48d59e..598cd0b2 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-core_0.10.0-r16_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-core_0.10.0-r16_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-cve-triage_1.0.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-cve-triage_1.0.0-r1_all.ipk index 3d4b8ac5..e2f3109f 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-cve-triage_1.0.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-cve-triage_1.0.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-dns-guard_1.0.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-dns-guard_1.0.0-r1_all.ipk index 9c71490e..171a614b 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-dns-guard_1.0.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-dns-guard_1.0.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-identity_0.1.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-identity_0.1.0-r1_all.ipk index a789d2f0..fb5395d0 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-identity_0.1.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-identity_0.1.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-iot-guard_1.0.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-iot-guard_1.0.0-r1_all.ipk index e72cc1ef..8f6996a5 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-iot-guard_1.0.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-iot-guard_1.0.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-localrecall_1.0.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-localrecall_1.0.0-r1_all.ipk index 6b3c4cf7..1a24fe16 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-localrecall_1.0.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-localrecall_1.0.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-master-link_1.0.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-master-link_1.0.0-r1_all.ipk index 18e37328..d0c034a6 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-master-link_1.0.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-master-link_1.0.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-mcp-server_1.0.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-mcp-server_1.0.0-r1_all.ipk index 70f2cd1c..c41ef578 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-mcp-server_1.0.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-mcp-server_1.0.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-mirrornet_0.1.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-mirrornet_0.1.0-r1_all.ipk index 0aa93e8e..5af11e71 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-mirrornet_0.1.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-mirrornet_0.1.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-network-anomaly_1.0.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-network-anomaly_1.0.0-r1_all.ipk index bc1e8838..ff7f2e0f 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-network-anomaly_1.0.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-network-anomaly_1.0.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-p2p-intel_0.1.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-p2p-intel_0.1.0-r1_all.ipk index 8d1bcff7..f28c943b 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-p2p-intel_0.1.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-p2p-intel_0.1.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-p2p_0.6.0-r3_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-p2p_0.6.0-r3_all.ipk index 68e2d17b..8846a93e 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-p2p_0.6.0-r3_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-p2p_0.6.0-r3_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-threat-analyst_1.0.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-threat-analyst_1.0.0-r1_all.ipk index 2011dde7..24ccd719 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-threat-analyst_1.0.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-threat-analyst_1.0.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-vortex-dns_1.0.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-vortex-dns_1.0.0-r1_all.ipk index f85aefb0..a9df8d19 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-vortex-dns_1.0.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-vortex-dns_1.0.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-vortex-firewall_1.0.0-r1_all.ipk b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-vortex-firewall_1.0.0-r1_all.ipk index 0d8accac..7bdd004b 100644 Binary files a/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-vortex-firewall_1.0.0-r1_all.ipk and b/package/secubox/secubox-app-bonus/root/www/secubox-feed/secubox-vortex-firewall_1.0.0-r1_all.ipk differ diff --git a/package/secubox/secubox-app-rezapp/Makefile b/package/secubox/secubox-app-rezapp/Makefile new file mode 100644 index 00000000..ea1a22a8 --- /dev/null +++ b/package/secubox/secubox-app-rezapp/Makefile @@ -0,0 +1,51 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=secubox-app-rezapp +PKG_VERSION:=1.0.0 +PKG_RELEASE:=1 + +include $(INCLUDE_DIR)/package.mk + +define Package/secubox-app-rezapp + SECTION:=secubox + CATEGORY:=SecuBox + SUBMENU:=Apps + TITLE:=RezApp Forge - Docker to LXC Converter + DEPENDS:=+docker +lxc +lxc-common +curl +wget-ssl +jsonfilter + PKGARCH:=all +endef + +define Package/secubox-app-rezapp/description + RezApp Forge converts Docker images to LXC containers and generates + SecuBox addon packages. Browse Docker Hub, GHCR, and LinuxServer.io + catalogs, convert images to LXC, and publish to the SecuBox app store. +endef + +define Package/secubox-app-rezapp/conffiles +/etc/config/rezapp +endef + +define Build/Compile +endef + +define Package/secubox-app-rezapp/install + $(INSTALL_DIR) $(1)/etc/config + $(INSTALL_CONF) ./files/etc/config/rezapp $(1)/etc/config/ + + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) ./files/usr/sbin/rezappctl $(1)/usr/sbin/ + + $(INSTALL_DIR) $(1)/usr/share/rezapp/templates + $(CP) ./files/usr/share/rezapp/templates/* $(1)/usr/share/rezapp/templates/ +endef + +define Package/secubox-app-rezapp/postinst +#!/bin/sh +[ -n "$${IPKG_INSTROOT}" ] || { + mkdir -p /srv/rezapp/{cache,apps,generated} + echo "RezApp Forge installed. Run 'rezappctl help' for usage." +} +exit 0 +endef + +$(eval $(call BuildPackage,secubox-app-rezapp)) diff --git a/package/secubox/secubox-app-rezapp/README.md b/package/secubox/secubox-app-rezapp/README.md new file mode 100644 index 00000000..24a2b58f --- /dev/null +++ b/package/secubox/secubox-app-rezapp/README.md @@ -0,0 +1,149 @@ +# RezApp Forge + +Docker to SecuBox LXC App Converter. + +## Overview + +RezApp Forge converts Docker images into LXC containers and generates SecuBox addon packages. Browse Docker Hub, GHCR, and LinuxServer.io catalogs, convert images to LXC, and publish to the SecuBox app store. + +## Features + +- **Catalog Management** - Docker Hub, LinuxServer.io, GHCR support +- **Docker Search** - Search images across all enabled catalogs +- **Image Info** - View available tags and architectures +- **Docker to LXC** - Convert Docker images to LXC containers +- **Package Generation** - Auto-generate SecuBox addon packages +- **Catalog Publishing** - Add converted apps to SecuBox catalog + +## Installation + +```bash +opkg install secubox-app-rezapp +``` + +## CLI Usage + +```bash +# Catalog management +rezappctl catalog list # List enabled catalogs +rezappctl catalog add # Add custom catalog +rezappctl catalog remove # Remove catalog + +# Search Docker images +rezappctl search # Search all catalogs +rezappctl search heimdall # Example: search for heimdall +rezappctl info # Show image details + +# Convert Docker to LXC +rezappctl convert [options] + --name # Custom app name + --tag # Image tag (default: latest) + --memory # Memory limit (default: 512M) + +# Generate SecuBox package +rezappctl package # Create package from converted app + +# Publish to catalog +rezappctl publish # Add manifest to SecuBox catalog + +# List converted apps +rezappctl list # Show all converted apps +``` + +## Example Workflow + +```bash +# 1. Search for an app +rezappctl search heimdall + +# 2. Check available tags +rezappctl info linuxserver/heimdall + +# 3. Convert to LXC +rezappctl convert linuxserver/heimdall --name heimdall --memory 512M + +# 4. Generate SecuBox package +rezappctl package heimdall + +# 5. Publish to catalog +rezappctl publish heimdall +``` + +## Configuration + +UCI config: `/etc/config/rezapp` + +``` +config main 'main' + option cache_dir '/srv/rezapp/cache' + option output_dir '/srv/rezapp/generated' + option apps_dir '/srv/rezapp/apps' + option lxc_dir '/srv/lxc' + option default_memory '512M' + +config catalog 'dockerhub' + option name 'Docker Hub' + option type 'dockerhub' + option enabled '1' + +config catalog 'linuxserver' + option name 'LinuxServer.io' + option type 'dockerhub' + option namespace 'linuxserver' + option enabled '1' +``` + +## Conversion Process + +1. **Pull** - Download Docker image +2. **Export** - Create container and export filesystem +3. **Extract** - Unpack to LXC rootfs +4. **Configure** - Generate LXC config from Docker metadata +5. **Wrap** - Create start script for LXC execution + +## Generated Package Structure + +``` +/srv/rezapp/generated/secubox-app-/ +├── Makefile # OpenWrt package makefile +├── files/ +│ ├── etc/config/ # UCI configuration +│ ├── etc/init.d/ # Procd init script +│ └── usr/sbin/ctl # Management CLI +└── README.md +``` + +## LuCI Interface + +Install `luci-app-rezapp` for web interface at **Services > RezApp Forge**. + +## Dependencies + +- docker +- lxc, lxc-common +- curl, wget-ssl +- jsonfilter + +## File Locations + +| Path | Description | +|------|-------------| +| `/etc/config/rezapp` | UCI configuration | +| `/usr/sbin/rezappctl` | CLI tool | +| `/srv/rezapp/cache/` | Downloaded images | +| `/srv/rezapp/apps/` | Converted app metadata | +| `/srv/rezapp/generated/` | Generated packages | +| `/srv/lxc//` | LXC container rootfs | +| `/usr/share/rezapp/templates/` | Package templates | + +## Templates + +Templates at `/usr/share/rezapp/templates/`: + +- `Makefile.tpl` - Package Makefile +- `init.d.tpl` - Procd init script +- `ctl.tpl` - Management CLI +- `config.tpl` - UCI defaults +- `start-lxc.tpl` - LXC startup wrapper +- `lxc-config.tpl` - LXC configuration +- `manifest.tpl` - App catalog manifest diff --git a/package/secubox/secubox-app-rezapp/files/etc/config/rezapp b/package/secubox/secubox-app-rezapp/files/etc/config/rezapp new file mode 100644 index 00000000..078f8d1c --- /dev/null +++ b/package/secubox/secubox-app-rezapp/files/etc/config/rezapp @@ -0,0 +1,25 @@ +config main 'main' + option cache_dir '/srv/rezapp/cache' + option output_dir '/srv/rezapp/generated' + option apps_dir '/srv/rezapp/apps' + option lxc_dir '/srv/lxc' + option default_memory '512M' + option default_network 'host' + +config catalog 'dockerhub' + option name 'Docker Hub' + option type 'dockerhub' + option url 'https://hub.docker.com' + option enabled '1' + +config catalog 'linuxserver' + option name 'LinuxServer.io' + option type 'dockerhub' + option namespace 'linuxserver' + option enabled '1' + +config catalog 'ghcr' + option name 'GitHub Container Registry' + option type 'ghcr' + option url 'https://ghcr.io' + option enabled '0' diff --git a/package/secubox/secubox-app-rezapp/files/usr/sbin/rezappctl b/package/secubox/secubox-app-rezapp/files/usr/sbin/rezappctl new file mode 100644 index 00000000..35291256 --- /dev/null +++ b/package/secubox/secubox-app-rezapp/files/usr/sbin/rezappctl @@ -0,0 +1,669 @@ +#!/bin/sh +# RezApp Forge - Docker to LXC Converter +# Copyright (C) 2026 SecuBox + +. /lib/functions.sh + +CONFIG="rezapp" +CACHE_DIR="" +OUTPUT_DIR="" +APPS_DIR="" +LXC_DIR="" +DEFAULT_MEMORY="" +DEFAULT_NETWORK="" +TEMPLATES_DIR="/usr/share/rezapp/templates" + +# Logging +log_info() { echo "[INFO] $*"; } +log_warn() { echo "[WARN] $*" >&2; } +log_error() { echo "[ERROR] $*" >&2; } + +# Load configuration +load_config() { + config_load "$CONFIG" + config_get CACHE_DIR main cache_dir "/srv/rezapp/cache" + config_get OUTPUT_DIR main output_dir "/srv/rezapp/generated" + config_get APPS_DIR main apps_dir "/srv/rezapp/apps" + config_get LXC_DIR main lxc_dir "/srv/lxc" + config_get DEFAULT_MEMORY main default_memory "512M" + config_get DEFAULT_NETWORK main default_network "host" +} + +# Ensure directories exist +ensure_dirs() { + mkdir -p "$CACHE_DIR" "$OUTPUT_DIR" "$APPS_DIR" +} + +# ========================================== +# Catalog Commands +# ========================================== + +cmd_catalog_list() { + echo "Enabled Catalogs:" + echo "=================" + + _print_catalog() { + local section="$1" + local name enabled type namespace + + config_get name "$section" name "$section" + config_get enabled "$section" enabled "0" + config_get type "$section" type "dockerhub" + config_get namespace "$section" namespace "" + + [ "$enabled" = "1" ] || return + + if [ -n "$namespace" ]; then + printf " %-15s %-12s %s\n" "$section" "$type" "$namespace/*" + else + printf " %-15s %-12s (all)\n" "$section" "$type" + fi + } + + config_load "$CONFIG" + config_foreach _print_catalog catalog +} + +cmd_catalog_add() { + local name="$1" + local namespace="$2" + + [ -z "$name" ] && { log_error "Catalog name required"; return 1; } + + uci set rezapp.$name=catalog + uci set rezapp.$name.name="$name" + uci set rezapp.$name.type="dockerhub" + [ -n "$namespace" ] && uci set rezapp.$name.namespace="$namespace" + uci set rezapp.$name.enabled="1" + uci commit rezapp + + log_info "Catalog added: $name" +} + +cmd_catalog_remove() { + local name="$1" + + [ -z "$name" ] && { log_error "Catalog name required"; return 1; } + + uci delete rezapp.$name 2>/dev/null + uci commit rezapp + + log_info "Catalog removed: $name" +} + +# ========================================== +# Search Commands +# ========================================== + +cmd_search() { + local query="$1" + local catalog="$2" + + [ -z "$query" ] && { log_error "Search query required"; return 1; } + + log_info "Searching Docker Hub for: $query" + + local url="https://hub.docker.com/v2/search/repositories/?query=${query}&page_size=25" + local result=$(curl -s "$url") + + if [ -z "$result" ]; then + log_error "Search failed" + return 1 + fi + + echo "" + echo "Search Results:" + echo "===============" + + echo "$result" | jsonfilter -e '@.results[*]' | while read -r item; do + local name=$(echo "$item" | jsonfilter -e '@.repo_name') + local desc=$(echo "$item" | jsonfilter -e '@.short_description' | head -c 60) + local stars=$(echo "$item" | jsonfilter -e '@.star_count') + local official=$(echo "$item" | jsonfilter -e '@.is_official') + + local badge="" + [ "$official" = "true" ] && badge="[official]" + + printf " %-35s %5s* %s %s\n" "$name" "$stars" "$badge" "$desc" + done +} + +cmd_info() { + local image="$1" + + [ -z "$image" ] && { log_error "Image name required"; return 1; } + + # Parse image name + local namespace="${image%%/*}" + local repo="${image#*/}" + + if [ "$namespace" = "$image" ]; then + namespace="library" + repo="$image" + fi + + log_info "Fetching info for: $image" + + # Get tags + local tags_url="https://hub.docker.com/v2/repositories/${namespace}/${repo}/tags?page_size=10" + local tags=$(curl -s "$tags_url") + + echo "" + echo "Image: $image" + echo "========================================" + echo "" + echo "Available Tags:" + echo "$tags" | jsonfilter -e '@.results[*].name' | head -10 | while read tag; do + echo " - $tag" + done + + # Try to get config for latest + echo "" + echo "To convert: rezappctl convert $image --name " +} + +# ========================================== +# Convert Command +# ========================================== + +cmd_convert() { + local image="" + local name="" + local tag="latest" + local memory="" + local network="" + local ports="" + local mounts="" + + # Parse arguments + while [ $# -gt 0 ]; do + case "$1" in + --name) name="$2"; shift 2 ;; + --tag) tag="$2"; shift 2 ;; + --memory) memory="$2"; shift 2 ;; + --network) network="$2"; shift 2 ;; + --port) ports="$ports $2"; shift 2 ;; + --mount) mounts="$mounts $2"; shift 2 ;; + -*) log_error "Unknown option: $1"; return 1 ;; + *) image="$1"; shift ;; + esac + done + + [ -z "$image" ] && { log_error "Image name required"; return 1; } + + # Default name from image + if [ -z "$name" ]; then + name="${image##*/}" + name="${name%%:*}" + fi + + [ -z "$memory" ] && memory="$DEFAULT_MEMORY" + [ -z "$network" ] && network="$DEFAULT_NETWORK" + + local full_image="${image}:${tag}" + local app_dir="$APPS_DIR/$name" + local lxc_path="$LXC_DIR/$name" + local tarball="$CACHE_DIR/${name}.tar" + + log_info "Converting $full_image -> $name" + + # Step 1: Ensure Docker is running + if ! docker info >/dev/null 2>&1; then + log_info "Starting Docker daemon..." + /etc/init.d/dockerd start 2>/dev/null + sleep 5 + if ! docker info >/dev/null 2>&1; then + log_error "Docker is not available" + return 1 + fi + fi + + # Step 2: Pull image + log_info "Pulling Docker image..." + docker pull "$full_image" || { log_error "Failed to pull image"; return 1; } + + # Step 3: Inspect image + log_info "Inspecting image metadata..." + mkdir -p "$app_dir" + docker inspect "$full_image" > "$app_dir/docker-inspect.json" + + # Extract metadata + local entrypoint=$(jsonfilter -i "$app_dir/docker-inspect.json" -e '@[0].Config.Entrypoint[*]' 2>/dev/null | tr '\n' ' ') + local cmd=$(jsonfilter -i "$app_dir/docker-inspect.json" -e '@[0].Config.Cmd[*]' 2>/dev/null | tr '\n' ' ') + local workdir=$(jsonfilter -i "$app_dir/docker-inspect.json" -e '@[0].Config.WorkingDir' 2>/dev/null) + local user=$(jsonfilter -i "$app_dir/docker-inspect.json" -e '@[0].Config.User' 2>/dev/null) + local exposed=$(jsonfilter -i "$app_dir/docker-inspect.json" -e '@[0].Config.ExposedPorts' 2>/dev/null) + + # Step 4: Export filesystem + log_info "Exporting container filesystem..." + docker create --name rezapp-export-$$ "$full_image" >/dev/null 2>&1 + docker export rezapp-export-$$ > "$tarball" + docker rm rezapp-export-$$ >/dev/null 2>&1 + + # Step 5: Create LXC rootfs + log_info "Creating LXC container..." + rm -rf "$lxc_path" + mkdir -p "$lxc_path/rootfs" + tar xf "$tarball" -C "$lxc_path/rootfs" + + # Step 6: Generate start script + log_info "Generating start script..." + local start_script="$lxc_path/rootfs/start-lxc.sh" + + cat > "$start_script" << STARTEOF +#!/bin/sh +# Auto-generated by RezApp Forge + +cd ${workdir:-/} + +# Run entrypoint/cmd +exec ${entrypoint:-${cmd:-/bin/sh}} +STARTEOF + chmod +x "$start_script" + + # Step 7: Generate LXC config + log_info "Generating LXC config..." + + # Parse user for UID/GID + local uid="0" + local gid="0" + if [ -n "$user" ] && [ "$user" != "root" ]; then + uid="${user%%:*}" + gid="${user#*:}" + [ "$gid" = "$user" ] && gid="$uid" + fi + + # Convert memory to bytes + local mem_bytes + case "$memory" in + *G) mem_bytes=$(( ${memory%G} * 1073741824 )) ;; + *M) mem_bytes=$(( ${memory%M} * 1048576 )) ;; + *) mem_bytes="$memory" ;; + esac + + cat > "$lxc_path/config" << LXCEOF +# LXC config for $name (auto-generated by RezApp Forge) +lxc.uts.name = $name +lxc.rootfs.path = dir:$lxc_path/rootfs +lxc.net.0.type = none +lxc.mount.auto = proc:mixed sys:ro +lxc.mount.entry = /srv/$name config none bind,create=dir 0 0 +lxc.cap.drop = sys_admin sys_module mac_admin mac_override +lxc.cgroup2.memory.max = $mem_bytes +lxc.init.uid = $uid +lxc.init.gid = $gid +lxc.init.cmd = /start-lxc.sh +lxc.console.size = 1024 +lxc.pty.max = 1024 +lxc.cgroup2.devices.allow = c 1:* rwm +lxc.cgroup2.devices.allow = c 5:* rwm +lxc.cgroup2.devices.allow = c 136:* rwm +lxc.seccomp.profile = +lxc.start.auto = 0 +LXCEOF + + # Step 8: Create data directory + mkdir -p "/srv/$name" + [ "$uid" != "0" ] && chown "$uid:$gid" "/srv/$name" + + # Step 9: Save metadata + cat > "$app_dir/metadata.json" << METAEOF +{ + "name": "$name", + "source_image": "$full_image", + "converted_at": "$(date -Iseconds)", + "entrypoint": "$entrypoint", + "cmd": "$cmd", + "workdir": "$workdir", + "user": "$user", + "uid": "$uid", + "gid": "$gid", + "memory": "$memory", + "network": "$network", + "lxc_path": "$lxc_path", + "data_path": "/srv/$name" +} +METAEOF + + log_info "Conversion complete!" + echo "" + echo "Container: $name" + echo " LXC Path: $lxc_path" + echo " Data Path: /srv/$name" + echo "" + echo "To test: lxc-start -n $name -F" + echo "To package: rezappctl package $name" +} + +# ========================================== +# Package Command +# ========================================== + +cmd_package() { + local name="$1" + local install_after="" + + [ "$name" = "--install" ] && { install_after="1"; name="$2"; } + [ -z "$name" ] && { log_error "App name required"; return 1; } + + local app_dir="$APPS_DIR/$name" + local meta_file="$app_dir/metadata.json" + local pkg_dir="$OUTPUT_DIR/secubox-app-$name" + + [ ! -f "$meta_file" ] && { log_error "App not found: $name (run convert first)"; return 1; } + + # Load metadata + local source_image=$(jsonfilter -i "$meta_file" -e '@.source_image') + local memory=$(jsonfilter -i "$meta_file" -e '@.memory') + local uid=$(jsonfilter -i "$meta_file" -e '@.uid') + local gid=$(jsonfilter -i "$meta_file" -e '@.gid') + + log_info "Generating package for: $name" + + # Create package structure + rm -rf "$pkg_dir" + mkdir -p "$pkg_dir/files/etc/config" + mkdir -p "$pkg_dir/files/etc/init.d" + mkdir -p "$pkg_dir/files/usr/sbin" + + # Generate Makefile + cat > "$pkg_dir/Makefile" << MAKEEOF +include \$(TOPDIR)/rules.mk + +PKG_NAME:=secubox-app-$name +PKG_VERSION:=1.0.0 +PKG_RELEASE:=1 + +include \$(INCLUDE_DIR)/package.mk + +define Package/secubox-app-$name + SECTION:=secubox + CATEGORY:=SecuBox + SUBMENU:=Apps + TITLE:=$name (via RezApp Forge) + DEPENDS:=+lxc +lxc-common + PKGARCH:=all +endef + +define Package/secubox-app-$name/description + $name - converted from Docker image $source_image + Generated by RezApp Forge. +endef + +define Package/secubox-app-$name/conffiles +/etc/config/$name +endef + +define Build/Compile +endef + +define Package/secubox-app-$name/install + \$(INSTALL_DIR) \$(1)/etc/config + \$(INSTALL_CONF) ./files/etc/config/$name \$(1)/etc/config/ + + \$(INSTALL_DIR) \$(1)/etc/init.d + \$(INSTALL_BIN) ./files/etc/init.d/$name \$(1)/etc/init.d/ + + \$(INSTALL_DIR) \$(1)/usr/sbin + \$(INSTALL_BIN) ./files/usr/sbin/${name}ctl \$(1)/usr/sbin/ +endef + +\$(eval \$(call BuildPackage,secubox-app-$name)) +MAKEEOF + + # Generate UCI config + cat > "$pkg_dir/files/etc/config/$name" << UCIEOF +config main 'main' + option enabled '0' + option container '$name' + option memory '$memory' + option data_path '/srv/$name' +UCIEOF + + # Generate init script + cat > "$pkg_dir/files/etc/init.d/$name" << 'INITEOF' +#!/bin/sh /etc/rc.common + +START=95 +STOP=10 +EXTRA_COMMANDS="status" +EXTRA_HELP=" status Show container status" + +CONF="APPNAME" + +load_config() { + . /lib/functions.sh + config_load "$CONF" + config_get ENABLED main enabled "0" + config_get CONTAINER main container "APPNAME" +} + +start() { + load_config + [ "$ENABLED" != "1" ] && { echo "APPNAME disabled"; return 0; } + + if lxc-info -n "$CONTAINER" 2>/dev/null | grep -q "RUNNING"; then + echo "APPNAME already running" + else + echo "Starting APPNAME..." + lxc-start -n "$CONTAINER" -d + sleep 3 + lxc-info -n "$CONTAINER" | grep State + fi +} + +stop() { + load_config + if lxc-info -n "$CONTAINER" 2>/dev/null | grep -q "RUNNING"; then + echo "Stopping APPNAME..." + lxc-stop -n "$CONTAINER" + else + echo "APPNAME not running" + fi +} + +restart() { + stop + sleep 2 + start +} + +status() { + load_config + lxc-info -n "$CONTAINER" 2>/dev/null || echo "Container not found" +} +INITEOF + sed -i "s/APPNAME/$name/g" "$pkg_dir/files/etc/init.d/$name" + chmod +x "$pkg_dir/files/etc/init.d/$name" + + # Generate CLI tool + cat > "$pkg_dir/files/usr/sbin/${name}ctl" << 'CTLEOF' +#!/bin/sh +# Generated by RezApp Forge + +CONF="APPNAME" +CONTAINER="APPNAME" + +. /lib/functions.sh + +load_config() { + config_load "$CONF" + config_get CONTAINER main container "APPNAME" +} + +usage() { + cat << EOF +Usage: APPNAMEctl + +Commands: + start Start container + stop Stop container + restart Restart container + status Show status + logs Show logs + shell Open shell + enable Enable autostart + disable Disable autostart +EOF +} + +case "$1" in + start) /etc/init.d/APPNAME start ;; + stop) /etc/init.d/APPNAME stop ;; + restart) /etc/init.d/APPNAME restart ;; + status) /etc/init.d/APPNAME status ;; + logs) load_config; lxc-attach -n "$CONTAINER" -- tail -100 /var/log/*.log 2>/dev/null ;; + shell) load_config; lxc-attach -n "$CONTAINER" -- /bin/sh ;; + enable) uci set APPNAME.main.enabled=1; uci commit APPNAME; echo "Enabled" ;; + disable) uci set APPNAME.main.enabled=0; uci commit APPNAME; echo "Disabled" ;; + *) usage ;; +esac +CTLEOF + sed -i "s/APPNAME/$name/g" "$pkg_dir/files/usr/sbin/${name}ctl" + chmod +x "$pkg_dir/files/usr/sbin/${name}ctl" + + log_info "Package generated: $pkg_dir" + echo "" + echo "To build:" + echo " 1. rsync -av $pkg_dir/ secubox-tools/local-feed/secubox-app-$name/" + echo " 2. ./secubox-tools/local-build.sh build secubox-app-$name" +} + +# ========================================== +# Publish Command +# ========================================== + +cmd_publish() { + local name="$1" + + [ -z "$name" ] && { log_error "App name required"; return 1; } + + local app_dir="$APPS_DIR/$name" + local meta_file="$app_dir/metadata.json" + local catalog_dir="/usr/share/secubox/plugins/catalog" + + [ ! -f "$meta_file" ] && { log_error "App not found: $name"; return 1; } + + # Load metadata + local source_image=$(jsonfilter -i "$meta_file" -e '@.source_image') + + log_info "Publishing $name to catalog..." + + mkdir -p "$catalog_dir" + + cat > "$catalog_dir/$name.json" << CATEOF +{ + "id": "$name", + "name": "$name", + "category": "utilities", + "runtime": "lxc", + "maturity": "community", + "description": "Converted from $source_image via RezApp Forge", + "source": { + "docker_image": "$source_image" + }, + "packages": ["secubox-app-$name"], + "capabilities": ["lxc-container"], + "requirements": { + "arch": ["aarch64"], + "min_ram_mb": 256, + "min_storage_mb": 500 + }, + "actions": { + "install": "${name}ctl enable", + "status": "${name}ctl status" + } +} +CATEOF + + log_info "Published to: $catalog_dir/$name.json" +} + +# ========================================== +# List Command +# ========================================== + +cmd_list() { + echo "Converted Apps:" + echo "===============" + + if [ -d "$APPS_DIR" ]; then + for app in "$APPS_DIR"/*/metadata.json; do + [ -f "$app" ] || continue + local name=$(dirname "$app") + name="${name##*/}" + local image=$(jsonfilter -i "$app" -e '@.source_image') + printf " %-20s %s\n" "$name" "$image" + done + else + echo " (none)" + fi +} + +# ========================================== +# Help +# ========================================== + +usage() { + cat << EOF +RezApp Forge - Docker to SecuBox Converter + +Usage: rezappctl [options] + +Catalog Commands: + catalog list List enabled catalogs + catalog add [ns] Add catalog (optional namespace) + catalog remove Remove catalog + +Search: + search Search Docker Hub + info Show image details + +Convert: + convert [opts] Convert Docker image to LXC + --name App name (default: from image) + --tag Image tag (default: latest) + --memory Memory limit (default: 512M) + --network Network type (default: host) + +Package: + package Generate SecuBox package + publish Add to app catalog + +List: + list Show converted apps + +Examples: + rezappctl search heimdall + rezappctl convert linuxserver/heimdall --name heimdall + rezappctl package heimdall + rezappctl publish heimdall + +EOF +} + +# ========================================== +# Main +# ========================================== + +load_config +ensure_dirs + +case "$1" in + catalog) + case "$2" in + list) cmd_catalog_list ;; + add) shift 2; cmd_catalog_add "$@" ;; + remove) shift 2; cmd_catalog_remove "$@" ;; + *) usage ;; + esac + ;; + search) shift; cmd_search "$@" ;; + info) shift; cmd_info "$@" ;; + convert) shift; cmd_convert "$@" ;; + package) shift; cmd_package "$@" ;; + publish) shift; cmd_publish "$@" ;; + list) cmd_list ;; + help|--help|-h) usage ;; + *) usage ;; +esac diff --git a/package/secubox/secubox-app-rezapp/files/usr/share/rezapp/templates/Makefile.tpl b/package/secubox/secubox-app-rezapp/files/usr/share/rezapp/templates/Makefile.tpl new file mode 100644 index 00000000..133daed5 --- /dev/null +++ b/package/secubox/secubox-app-rezapp/files/usr/share/rezapp/templates/Makefile.tpl @@ -0,0 +1,52 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=secubox-app-APPNAME +PKG_VERSION:=1.0.0 +PKG_RELEASE:=1 + +include $(INCLUDE_DIR)/package.mk + +define Package/secubox-app-APPNAME + SECTION:=secubox + CATEGORY:=SecuBox + SUBMENU:=Apps + TITLE:=APPNAME - RezApp Generated + DEPENDS:=+lxc +lxc-common + PKGARCH:=all +endef + +define Package/secubox-app-APPNAME/description + Auto-generated SecuBox app from Docker image: SOURCE_IMAGE + Converted by RezApp Forge. +endef + +define Package/secubox-app-APPNAME/conffiles +/etc/config/APPNAME +endef + +define Build/Compile +endef + +define Package/secubox-app-APPNAME/install + $(INSTALL_DIR) $(1)/etc/config + $(INSTALL_CONF) ./files/etc/config/APPNAME $(1)/etc/config/ + + $(INSTALL_DIR) $(1)/etc/init.d + $(INSTALL_BIN) ./files/etc/init.d/APPNAME $(1)/etc/init.d/ + + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) ./files/usr/sbin/APPNAMEctl $(1)/usr/sbin/ + + $(INSTALL_DIR) $(1)/srv/lxc/APPNAME + $(CP) ./files/srv/lxc/APPNAME/* $(1)/srv/lxc/APPNAME/ +endef + +define Package/secubox-app-APPNAME/postinst +#!/bin/sh +[ -n "$${IPKG_INSTROOT}" ] || { + echo "APPNAME installed. Run 'APPNAMEctl start' to launch." +} +exit 0 +endef + +$(eval $(call BuildPackage,secubox-app-APPNAME)) diff --git a/package/secubox/secubox-app-rezapp/files/usr/share/rezapp/templates/README b/package/secubox/secubox-app-rezapp/files/usr/share/rezapp/templates/README new file mode 100644 index 00000000..718c8217 --- /dev/null +++ b/package/secubox/secubox-app-rezapp/files/usr/share/rezapp/templates/README @@ -0,0 +1,14 @@ +RezApp Forge Templates +====================== + +This directory contains templates for generating SecuBox packages from +Docker images. The templates use simple sed-based variable substitution. + +Variables: + APPNAME - Application name + SOURCE_IMAGE - Original Docker image + MEMORY - Memory limit + UID - Container user ID + GID - Container group ID + +Templates are automatically applied by rezappctl package command. diff --git a/package/secubox/secubox-app-rezapp/files/usr/share/rezapp/templates/config.tpl b/package/secubox/secubox-app-rezapp/files/usr/share/rezapp/templates/config.tpl new file mode 100644 index 00000000..3b8cb8cf --- /dev/null +++ b/package/secubox/secubox-app-rezapp/files/usr/share/rezapp/templates/config.tpl @@ -0,0 +1,6 @@ +config APPNAME 'main' + option enabled '1' + option container 'APPNAME' + option lxc_dir '/srv/lxc' + option memory_limit 'MEMORY' + option network 'host' diff --git a/package/secubox/secubox-app-rezapp/files/usr/share/rezapp/templates/ctl.tpl b/package/secubox/secubox-app-rezapp/files/usr/share/rezapp/templates/ctl.tpl new file mode 100644 index 00000000..2ecf2d88 --- /dev/null +++ b/package/secubox/secubox-app-rezapp/files/usr/share/rezapp/templates/ctl.tpl @@ -0,0 +1,104 @@ +#!/bin/sh +# APPNAMEctl - Management CLI for APPNAME +# Auto-generated by RezApp Forge from SOURCE_IMAGE + +CONTAINER="APPNAME" +CONFIG="APPNAME" + +usage() { + cat < + +Commands: + start Start the APPNAME container + stop Stop the APPNAME container + restart Restart the APPNAME container + status Show container status + logs Show container logs + shell Open shell in container + enable Enable auto-start + disable Disable auto-start + help Show this help + +EOF +} + +cmd_start() { + /etc/init.d/$CONFIG start +} + +cmd_stop() { + /etc/init.d/$CONFIG stop +} + +cmd_restart() { + /etc/init.d/$CONFIG restart +} + +cmd_status() { + echo "=== APPNAME Status ===" + if lxc-info -n "$CONTAINER" 2>/dev/null | grep -q "RUNNING"; then + lxc-info -n "$CONTAINER" + else + echo "Container is not running" + echo "" + echo "Config: /etc/config/$CONFIG" + uci show $CONFIG 2>/dev/null || echo "(no config)" + fi +} + +cmd_logs() { + if lxc-info -n "$CONTAINER" 2>/dev/null | grep -q "RUNNING"; then + # Try common log locations + for log in /var/log/APPNAME.log /var/log/messages /tmp/APPNAME.log; do + if lxc-attach -n "$CONTAINER" -- test -f "$log" 2>/dev/null; then + lxc-attach -n "$CONTAINER" -- tail -100 "$log" + return + fi + done + echo "No log files found in container" + else + echo "Container is not running" + fi +} + +cmd_shell() { + if lxc-info -n "$CONTAINER" 2>/dev/null | grep -q "RUNNING"; then + lxc-attach -n "$CONTAINER" -- /bin/sh + else + echo "Container is not running. Start it first with: APPNAMEctl start" + fi +} + +cmd_enable() { + uci set $CONFIG.main.enabled='1' + uci commit $CONFIG + /etc/init.d/$CONFIG enable + echo "APPNAME enabled for auto-start" +} + +cmd_disable() { + uci set $CONFIG.main.enabled='0' + uci commit $CONFIG + /etc/init.d/$CONFIG disable + echo "APPNAME disabled" +} + +case "$1" in + start) cmd_start ;; + stop) cmd_stop ;; + restart) cmd_restart ;; + status) cmd_status ;; + logs) cmd_logs ;; + shell) cmd_shell ;; + enable) cmd_enable ;; + disable) cmd_disable ;; + help|--help|-h|"") + usage ;; + *) + echo "Unknown command: $1" + usage + exit 1 ;; +esac diff --git a/package/secubox/secubox-app-rezapp/files/usr/share/rezapp/templates/init.d.tpl b/package/secubox/secubox-app-rezapp/files/usr/share/rezapp/templates/init.d.tpl new file mode 100644 index 00000000..d4e4bee1 --- /dev/null +++ b/package/secubox/secubox-app-rezapp/files/usr/share/rezapp/templates/init.d.tpl @@ -0,0 +1,98 @@ +#!/bin/sh /etc/rc.common + +START=99 +STOP=10 + +USE_PROCD=1 + +EXTRA_COMMANDS="status" +EXTRA_HELP=" status Show container status" + +start_service() { + local enabled + config_load APPNAME + config_get enabled main enabled '0' + + [ "$enabled" = "1" ] || { + echo "APPNAME is disabled in /etc/config/APPNAME" + return 0 + } + + local container memory_limit + config_get container main container 'APPNAME' + config_get memory_limit main memory_limit 'MEMORY' + + # Generate LXC config + generate_lxc_config + + echo "Starting APPNAME container..." + lxc-start -n "$container" -d + sleep 2 + + if lxc-info -n "$container" 2>/dev/null | grep -q "RUNNING"; then + echo "APPNAME started successfully" + else + echo "Failed to start APPNAME" + return 1 + fi +} + +stop_service() { + local container + config_load APPNAME + config_get container main container 'APPNAME' + + if lxc-info -n "$container" 2>/dev/null | grep -q "RUNNING"; then + echo "Stopping APPNAME container..." + lxc-stop -n "$container" -t 30 + echo "APPNAME stopped" + else + echo "APPNAME is not running" + fi +} + +status() { + local container + config_load APPNAME + config_get container main container 'APPNAME' + + if lxc-info -n "$container" 2>/dev/null | grep -q "RUNNING"; then + lxc-info -n "$container" + else + echo "APPNAME is not running" + fi +} + +generate_lxc_config() { + local container lxc_dir memory_limit network + config_load APPNAME + config_get container main container 'APPNAME' + config_get lxc_dir main lxc_dir '/srv/lxc' + config_get memory_limit main memory_limit 'MEMORY' + config_get network main network 'host' + + local config_file="${lxc_dir}/${container}/config" + local rootfs="${lxc_dir}/${container}/rootfs" + + cat > "$config_file" << EOF +lxc.uts.name = ${container} +lxc.rootfs.path = dir:${rootfs} +lxc.init.cmd = /start-lxc.sh + +# Namespaces +lxc.namespace.share.net = 1 + +# Capabilities +lxc.cap.drop = sys_admin sys_boot sys_module + +# Memory limit +lxc.cgroup2.memory.max = ${memory_limit} + +# TTY +lxc.tty.max = 1 +lxc.pty.max = 1 + +# Mounts +lxc.mount.auto = proc:mixed sys:ro cgroup:mixed +EOF +} diff --git a/package/secubox/secubox-app-rezapp/files/usr/share/rezapp/templates/lxc-config.tpl b/package/secubox/secubox-app-rezapp/files/usr/share/rezapp/templates/lxc-config.tpl new file mode 100644 index 00000000..fa727e96 --- /dev/null +++ b/package/secubox/secubox-app-rezapp/files/usr/share/rezapp/templates/lxc-config.tpl @@ -0,0 +1,27 @@ +# LXC configuration for APPNAME +# Auto-generated by RezApp Forge from SOURCE_IMAGE + +lxc.uts.name = APPNAME +lxc.rootfs.path = dir:/srv/lxc/APPNAME/rootfs +lxc.init.cmd = /start-lxc.sh + +# Share host network namespace +lxc.namespace.share.net = 1 + +# Drop dangerous capabilities +lxc.cap.drop = sys_admin sys_boot sys_module sys_rawio sys_time + +# Memory limit +lxc.cgroup2.memory.max = MEMORY + +# TTY configuration +lxc.tty.max = 1 +lxc.pty.max = 1 + +# Mount configuration +lxc.mount.auto = proc:mixed sys:ro cgroup:mixed + +# Environment +lxc.environment = PUID=UID +lxc.environment = PGID=GID +lxc.environment = TZ=UTC diff --git a/package/secubox/secubox-app-rezapp/files/usr/share/rezapp/templates/manifest.tpl b/package/secubox/secubox-app-rezapp/files/usr/share/rezapp/templates/manifest.tpl new file mode 100644 index 00000000..9c2de9fe --- /dev/null +++ b/package/secubox/secubox-app-rezapp/files/usr/share/rezapp/templates/manifest.tpl @@ -0,0 +1,31 @@ +{ + "id": "APPNAME", + "name": "APPNAME", + "version": "1.0.0", + "category": "utilities", + "runtime": "lxc", + "maturity": "community", + "description": "Auto-generated from SOURCE_IMAGE by RezApp Forge", + "source": { + "docker_image": "SOURCE_IMAGE", + "converted_by": "rezappctl", + "converted_at": "TIMESTAMP" + }, + "packages": ["secubox-app-APPNAME"], + "capabilities": ["lxc-container"], + "requirements": { + "arch": ["aarch64", "x86_64"], + "min_ram_mb": 256, + "min_storage_mb": 500 + }, + "network": { + "inbound_ports": [], + "protocols": [] + }, + "actions": { + "install": "opkg install secubox-app-APPNAME", + "start": "APPNAMEctl start", + "stop": "APPNAMEctl stop", + "status": "APPNAMEctl status" + } +} diff --git a/package/secubox/secubox-app-rezapp/files/usr/share/rezapp/templates/start-lxc.tpl b/package/secubox/secubox-app-rezapp/files/usr/share/rezapp/templates/start-lxc.tpl new file mode 100644 index 00000000..b0475272 --- /dev/null +++ b/package/secubox/secubox-app-rezapp/files/usr/share/rezapp/templates/start-lxc.tpl @@ -0,0 +1,23 @@ +#!/bin/bash +# LXC startup wrapper for APPNAME +# Auto-generated by RezApp Forge from SOURCE_IMAGE + +# Set UID/GID if specified +export PUID=${PUID:-UID} +export PGID=${PGID:-GID} + +# Create required directories +mkdir -p /config /data /tmp + +# Change to non-root user if specified +if [ "$PUID" != "0" ] && [ "$PGID" != "0" ]; then + # Create user if not exists + if ! id -u app >/dev/null 2>&1; then + addgroup -g $PGID app 2>/dev/null || true + adduser -D -u $PUID -G app app 2>/dev/null || true + fi +fi + +# Execute the original entrypoint +# ENTRYPOINT_PLACEHOLDER +exec /bin/sh diff --git a/package/secubox/secubox-app-streamlit-forge/Makefile b/package/secubox/secubox-app-streamlit-forge/Makefile new file mode 100644 index 00000000..2eeb167b --- /dev/null +++ b/package/secubox/secubox-app-streamlit-forge/Makefile @@ -0,0 +1,55 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=secubox-app-streamlit-forge +PKG_VERSION:=1.0.0 +PKG_RELEASE:=1 + +include $(INCLUDE_DIR)/package.mk + +define Package/secubox-app-streamlit-forge + SECTION:=secubox + CATEGORY:=SecuBox + SUBMENU:=Apps + TITLE:=Streamlit Forge - App Publishing Platform + DEPENDS:=+jsonfilter + PKGARCH:=all +endef + +define Package/secubox-app-streamlit-forge/description + Streamlit Forge is a comprehensive platform for creating, managing, + and publishing Streamlit applications. Features include Gitea source + management, preview generation, UCI configuration sync, and mesh + appstore publishing. +endef + +define Package/secubox-app-streamlit-forge/conffiles +/etc/config/streamlit-forge +endef + +define Build/Compile +endef + +define Package/secubox-app-streamlit-forge/install + $(INSTALL_DIR) $(1)/etc/config + $(INSTALL_CONF) ./files/etc/config/streamlit-forge $(1)/etc/config/ + + $(INSTALL_DIR) $(1)/etc/init.d + $(INSTALL_BIN) ./files/etc/init.d/streamlit-forge $(1)/etc/init.d/ + + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) ./files/usr/sbin/slforge $(1)/usr/sbin/ + + $(INSTALL_DIR) $(1)/usr/share/streamlit-forge/templates + $(CP) ./files/usr/share/streamlit-forge/templates/* $(1)/usr/share/streamlit-forge/templates/ +endef + +define Package/secubox-app-streamlit-forge/postinst +#!/bin/sh +[ -n "$${IPKG_INSTROOT}" ] || { + mkdir -p /srv/streamlit/{apps,previews,templates} + echo "Streamlit Forge installed. Run 'slforge help' for usage." +} +exit 0 +endef + +$(eval $(call BuildPackage,secubox-app-streamlit-forge)) diff --git a/package/secubox/secubox-app-streamlit-forge/README.md b/package/secubox/secubox-app-streamlit-forge/README.md new file mode 100644 index 00000000..8f95cac5 --- /dev/null +++ b/package/secubox/secubox-app-streamlit-forge/README.md @@ -0,0 +1,184 @@ +# Streamlit Forge + +Streamlit App Publishing Platform for SecuBox. + +## Overview + +Streamlit Forge is a comprehensive platform for creating, managing, and publishing Streamlit applications. Create apps from templates, manage instances, expose via HAProxy with SSL, and publish to the SecuBox mesh catalog. + +## Features + +- **App Templates** - Basic, Dashboard, Data-Viewer starter templates +- **Instance Management** - Start, stop, restart app instances +- **Port Allocation** - Automatic port assignment +- **HAProxy Integration** - One-command vhost + SSL exposure +- **Mesh Publishing** - Share apps across SecuBox mesh network +- **UCI Configuration** - Persistent app settings + +## Installation + +```bash +opkg install secubox-app-streamlit-forge +``` + +## CLI Usage + +```bash +# App Management +slforge create [options] + --from-template # Use template (basic, dashboard, data-viewer) + --from-upload # Create from ZIP file + --from-git # Clone from Git repository + +slforge list # List all apps +slforge info # Show app details +slforge delete # Remove app + +# Instance Control +slforge start # Start app instance +slforge stop # Stop app instance +slforge restart # Restart app +slforge status [app] # Show status +slforge logs [-f] # View logs + +# Configuration +slforge config list # List config +slforge config get # Get value +slforge config set # Set value + +# Publishing +slforge expose [--domain ] # Create vhost + SSL +slforge hide # Remove public access +slforge publish # Add to mesh catalog +slforge unpublish # Remove from mesh + +# Templates +slforge templates # List available templates +``` + +## Example Workflow + +```bash +# 1. Create app from dashboard template +slforge create mydashboard --from-template dashboard + +# 2. Start the app +slforge start mydashboard +# URL: http://192.168.255.1:8501 + +# 3. Expose with SSL +slforge expose mydashboard --domain mydashboard.gk2.secubox.in + +# 4. Publish to mesh catalog +slforge publish mydashboard +``` + +## Templates + +### Basic +Minimal Streamlit app with sidebar and two-column layout. + +### Dashboard +Multi-page dashboard with: +- Metric cards with delta indicators +- Line and area charts +- Data table with CSV export +- Settings page + +### Data-Viewer +CSV/Excel data explorer with: +- File upload (CSV, XLSX) +- Dynamic column filtering +- Histograms and scatter plots +- Statistical summary +- Correlation matrix + +## Configuration + +UCI config: `/etc/config/streamlit-forge` + +``` +config forge 'main' + option enabled '1' + option gitea_url 'http://127.0.0.1:3000' + option gitea_org 'streamlit-apps' + option apps_dir '/srv/streamlit/apps' + option previews_dir '/srv/streamlit/previews' + option base_domain 'apps.secubox.in' + option default_port_start '8501' + option default_memory '512M' + +config app 'myapp' + option name 'myapp' + option enabled '1' + option port '8501' + option entrypoint 'app.py' + option memory '512M' + option domain 'myapp.gk2.secubox.in' +``` + +## App Directory Structure + +``` +/srv/streamlit/apps// +├── src/ # App source code +│ ├── app.py # Main Streamlit entry +│ ├── requirements.txt # Python dependencies +│ └── ... +├── data/ # Persistent data +└── config.json # Runtime config +``` + +## LuCI Interface + +Install `luci-app-streamlit-forge` for web interface at **Services > Streamlit Forge**. + +Features: +- Status dashboard (running/total apps, LXC status) +- Create app dialog with template selection +- App table with Start/Stop/Open/Expose/Publish/Delete +- Auto-refresh polling + +## Runtime + +Apps run inside the `streamlit` LXC container: +- Apps mounted at `/srv/apps/` inside container +- Python virtualenv with Streamlit pre-installed +- Port forwarding to host network + +## Dependencies + +- python3, python3-pip +- lxc, lxc-common +- jsonfilter + +## File Locations + +| Path | Description | +|------|-------------| +| `/etc/config/streamlit-forge` | UCI configuration | +| `/usr/sbin/slforge` | CLI tool | +| `/srv/streamlit/apps/` | App source directories | +| `/srv/streamlit/previews/` | Generated previews | +| `/usr/share/streamlit-forge/templates/` | App templates | +| `/var/run/streamlit-*.pid` | PID files | +| `/var/log/streamlit-*.log` | App logs | + +## Mesh Catalog Manifest + +Published apps create a manifest at `/usr/share/secubox/plugins/catalog/`: + +```json +{ + "id": "streamlit-myapp", + "name": "myapp", + "type": "streamlit-app", + "version": "1.0.0", + "category": "apps", + "runtime": "streamlit", + "actions": { + "start": "slforge start myapp", + "stop": "slforge stop myapp" + } +} +``` diff --git a/package/secubox/secubox-app-streamlit-forge/files/etc/config/streamlit-forge b/package/secubox/secubox-app-streamlit-forge/files/etc/config/streamlit-forge new file mode 100644 index 00000000..c2acb43e --- /dev/null +++ b/package/secubox/secubox-app-streamlit-forge/files/etc/config/streamlit-forge @@ -0,0 +1,11 @@ +config forge 'main' + option enabled '1' + option gitea_url 'http://127.0.0.1:3000' + option gitea_org 'streamlit-apps' + option apps_dir '/srv/streamlit/apps' + option previews_dir '/srv/streamlit/previews' + option templates_dir '/usr/share/streamlit-forge/templates' + option base_domain 'apps.secubox.in' + option default_port_start '8501' + option default_memory '512M' + option auto_sync '1' diff --git a/package/secubox/secubox-app-streamlit-forge/files/etc/init.d/streamlit-forge b/package/secubox/secubox-app-streamlit-forge/files/etc/init.d/streamlit-forge new file mode 100644 index 00000000..3a29f856 --- /dev/null +++ b/package/secubox/secubox-app-streamlit-forge/files/etc/init.d/streamlit-forge @@ -0,0 +1,48 @@ +#!/bin/sh /etc/rc.common + +START=99 +STOP=10 + +USE_PROCD=1 + +EXTRA_COMMANDS="status" +EXTRA_HELP=" status Show all app instances status" + +start_service() { + config_load streamlit-forge + + local enabled + config_get enabled main enabled '0' + [ "$enabled" = "1" ] || return 0 + + # Start all enabled app instances + config_foreach start_app app +} + +start_app() { + local section="$1" + local enabled name port + + config_get enabled "$section" enabled '0' + [ "$enabled" = "1" ] || return 0 + + config_get name "$section" name "$section" + config_get port "$section" port '8501' + + echo "Starting Streamlit app: $name on port $port" + slforge start "$name" --quiet +} + +stop_service() { + # Stop all running app instances + for pid_file in /var/run/streamlit-*.pid; do + [ -f "$pid_file" ] || continue + local pid=$(cat "$pid_file") + [ -n "$pid" ] && kill "$pid" 2>/dev/null + rm -f "$pid_file" + done +} + +status() { + slforge status +} diff --git a/package/secubox/secubox-app-streamlit-forge/files/usr/sbin/slforge b/package/secubox/secubox-app-streamlit-forge/files/usr/sbin/slforge new file mode 100644 index 00000000..66bfd0e8 --- /dev/null +++ b/package/secubox/secubox-app-streamlit-forge/files/usr/sbin/slforge @@ -0,0 +1,678 @@ +#!/bin/sh +# slforge - Streamlit Forge CLI +# Manage Streamlit apps: create, deploy, publish + +. /lib/functions.sh + +# Load config +config_load streamlit-forge +config_get GITEA_URL main gitea_url 'http://127.0.0.1:3000' +config_get GITEA_ORG main gitea_org 'streamlit-apps' +config_get APPS_DIR main apps_dir '/srv/streamlit/apps' +config_get PREVIEWS_DIR main previews_dir '/srv/streamlit/previews' +config_get TEMPLATES_DIR main templates_dir '/usr/share/streamlit-forge/templates' +config_get BASE_DOMAIN main base_domain 'apps.secubox.in' +config_get DEFAULT_PORT main default_port_start '8501' +config_get DEFAULT_MEMORY main default_memory '512M' + +# Colors +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' + +log_info() { echo -e "${BLUE}[INFO]${NC} $1"; } +log_ok() { echo -e "${GREEN}[OK]${NC} $1"; } +log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; } +log_err() { echo -e "${RED}[ERROR]${NC} $1"; } + +usage() { + cat < [options] + +App Management: + create [opts] Create new Streamlit app + --from-upload Create from uploaded ZIP file + --from-git Create from Git repository + --from-template Create from template (basic, dashboard, data-viewer) + list List all apps + info Show app details + delete Remove app and all data + +Instance Control: + start [--port N] Start app instance + stop Stop app instance + restart Restart app instance + status [app] Show instance status + logs [-f] View app logs + shell Open shell in app container + +Configuration: + config list List app config + config get Get config value + config set Set config value + sync-config Sync UCI <-> app config + +Source Management: + edit Open in Gitea web editor + pull Pull latest from Gitea + push Push changes to Gitea + +Preview & Publishing: + preview Generate preview screenshot + expose [--domain] Create vhost + SSL + hide Remove public access + +Mesh AppStore: + publish Publish to mesh catalog + unpublish Remove from mesh catalog + catalog Browse mesh catalog + install Install from mesh + +Templates: + templates List available templates + +Examples: + slforge create myapp --from-template dashboard + slforge start myapp --port 8510 + slforge expose myapp --domain myapp.gk2.secubox.in + slforge publish myapp +EOF +} + +# Get next available port +get_next_port() { + local port=$DEFAULT_PORT + while netstat -tln 2>/dev/null | grep -q ":$port " || \ + grep -q "option port '$port'" /etc/config/streamlit-forge 2>/dev/null; do + port=$((port + 1)) + done + echo "$port" +} + +# Check if app exists +app_exists() { + local name="$1" + [ -d "$APPS_DIR/$name" ] || uci -q get streamlit-forge."$name" >/dev/null 2>&1 +} + +# Get app UCI section +get_app_config() { + local name="$1" + local key="$2" + uci -q get streamlit-forge."$name"."$key" +} + +# Set app UCI config +set_app_config() { + local name="$1" + local key="$2" + local value="$3" + uci set streamlit-forge."$name"."$key"="$value" + uci commit streamlit-forge +} + +# Create app from template +cmd_create() { + local name="$1" + shift + + [ -z "$name" ] && { log_err "App name required"; return 1; } + + # Check if exists + app_exists "$name" && { log_err "App '$name' already exists"; return 1; } + + local from_upload="" from_git="" from_template="basic" + + while [ $# -gt 0 ]; do + case "$1" in + --from-upload) from_upload="$2"; shift 2 ;; + --from-git) from_git="$2"; shift 2 ;; + --from-template) from_template="$2"; shift 2 ;; + *) shift ;; + esac + done + + local app_dir="$APPS_DIR/$name" + mkdir -p "$app_dir/src" "$app_dir/data" + + if [ -n "$from_upload" ]; then + # Extract ZIP + log_info "Extracting from $from_upload..." + if [ -f "$from_upload" ]; then + unzip -q "$from_upload" -d "$app_dir/src" 2>/dev/null || { + log_err "Failed to extract ZIP" + rm -rf "$app_dir" + return 1 + } + # Move files if extracted to subdirectory + local subdir=$(ls -1 "$app_dir/src" 2>/dev/null | head -1) + if [ -d "$app_dir/src/$subdir" ] && [ "$subdir" != "." ]; then + mv "$app_dir/src/$subdir"/* "$app_dir/src/" 2>/dev/null + rmdir "$app_dir/src/$subdir" 2>/dev/null + fi + else + log_err "File not found: $from_upload" + rm -rf "$app_dir" + return 1 + fi + + elif [ -n "$from_git" ]; then + # Clone from Git + log_info "Cloning from $from_git..." + git clone "$from_git" "$app_dir/src" 2>/dev/null || { + log_err "Failed to clone repository" + rm -rf "$app_dir" + return 1 + } + + else + # Use template + local tpl_dir="$TEMPLATES_DIR/$from_template" + if [ -d "$tpl_dir" ]; then + log_info "Creating from template: $from_template" + cp -r "$tpl_dir"/* "$app_dir/src/" + # Replace placeholders + find "$app_dir/src" -type f -name "*.py" -exec sed -i "s/APPNAME/$name/g" {} \; + find "$app_dir/src" -type f -name "*.md" -exec sed -i "s/APPNAME/$name/g" {} \; + else + # Create minimal app + log_info "Creating minimal Streamlit app" + cat > "$app_dir/src/app.py" <<-PYEOF +import streamlit as st + +st.set_page_config(page_title="$name", page_icon="🚀") + +st.title("$name") +st.write("Welcome to your new Streamlit app!") + +st.sidebar.header("Navigation") +page = st.sidebar.radio("Go to", ["Home", "About"]) + +if page == "Home": + st.header("Home") + st.write("Edit src/app.py to customize this app.") +else: + st.header("About") + st.write("Created with Streamlit Forge") +PYEOF + cat > "$app_dir/src/requirements.txt" <<-REQEOF +streamlit>=1.30.0 +REQEOF + fi + fi + + # Create UCI config + local port=$(get_next_port) + uci set streamlit-forge."$name"=app + uci set streamlit-forge."$name".name="$name" + uci set streamlit-forge."$name".enabled='0' + uci set streamlit-forge."$name".port="$port" + uci set streamlit-forge."$name".entrypoint='app.py' + uci set streamlit-forge."$name".memory="$DEFAULT_MEMORY" + uci set streamlit-forge."$name".created="$(date +%Y-%m-%d)" + uci commit streamlit-forge + + # Create Gitea repo if available + if curl -s "$GITEA_URL/api/v1/version" >/dev/null 2>&1; then + log_info "Creating Gitea repository..." + # TODO: Create repo via Gitea API + fi + + log_ok "Created app: $name" + log_info " Directory: $app_dir" + log_info " Port: $port" + log_info " Start with: slforge start $name" +} + +# List all apps +cmd_list() { + echo "" + echo "Streamlit Apps" + echo "==============" + echo "" + + local found=0 + for app_dir in "$APPS_DIR"/*/; do + [ -d "$app_dir" ] || continue + local name=$(basename "$app_dir") + local enabled=$(get_app_config "$name" enabled) + local port=$(get_app_config "$name" port) + local domain=$(get_app_config "$name" domain) + local status="stopped" + + # Check if running by port + if [ -n "$port" ] && netstat -tln 2>/dev/null | grep -q ":$port "; then + status="running" + fi + + printf " %-20s %-8s port:%-5s %s\n" "$name" "[$status]" "${port:-?}" "${domain:-}" + found=1 + done + + [ "$found" = "0" ] && echo " No apps found. Create one with: slforge create " + echo "" +} + +# Show app info +cmd_info() { + local name="$1" + [ -z "$name" ] && { log_err "App name required"; return 1; } + + if ! app_exists "$name"; then + log_err "App not found: $name" + return 1 + fi + + local app_dir="$APPS_DIR/$name" + + echo "" + echo "App: $name" + echo "=========================================" + echo "" + echo "Directory: $app_dir" + echo "Enabled: $(get_app_config "$name" enabled)" + echo "Port: $(get_app_config "$name" port)" + echo "Memory: $(get_app_config "$name" memory)" + echo "Domain: $(get_app_config "$name" domain)" + echo "Entrypoint: $(get_app_config "$name" entrypoint)" + echo "Created: $(get_app_config "$name" created)" + echo "" + + # Check status by port + local port=$(get_app_config "$name" port) + if [ -n "$port" ] && netstat -tln 2>/dev/null | grep -q ":$port "; then + echo "Status: RUNNING on port $port" + else + echo "Status: STOPPED" + fi + + # Show files + if [ -d "$app_dir/src" ]; then + echo "" + echo "Source Files:" + ls -la "$app_dir/src" 2>/dev/null | head -10 + fi + echo "" +} + +# Start app instance +cmd_start() { + local name="$1" + shift + + [ -z "$name" ] && { log_err "App name required"; return 1; } + + if ! app_exists "$name"; then + log_err "App not found: $name" + return 1 + fi + + local port=$(get_app_config "$name" port) + local quiet=0 + + while [ $# -gt 0 ]; do + case "$1" in + --port) port="$2"; shift 2 ;; + --quiet) quiet=1; shift ;; + *) shift ;; + esac + done + + local app_dir="$APPS_DIR/$name" + local entrypoint=$(get_app_config "$name" entrypoint) + [ -z "$entrypoint" ] && entrypoint="app.py" + + # Check if already running + if [ -f "/var/run/streamlit-$name.pid" ]; then + local pid=$(cat "/var/run/streamlit-$name.pid") + if kill -0 "$pid" 2>/dev/null; then + [ "$quiet" = "0" ] && log_warn "App $name already running (PID: $pid)" + return 0 + fi + fi + + [ "$quiet" = "0" ] && log_info "Starting $name on port $port..." + + # Check for Streamlit in LXC container + if lxc-info -n streamlit 2>/dev/null | grep -q "RUNNING"; then + # Run in Streamlit LXC container + # Note: /srv/streamlit/apps is mounted at /srv/apps inside container + # Create wrapper script to avoid shell escaping issues + cat > "$APPS_DIR/.slforge-start.sh" <<-'STARTSCRIPT' +#!/bin/sh +cd "$1" +[ -f requirements.txt ] && pip3 install -q -r requirements.txt 2>/dev/null +nohup streamlit run "$2" --server.port "$3" --server.address 0.0.0.0 --server.headless true > /tmp/streamlit-$4.log 2>&1 & +echo $! +STARTSCRIPT + chmod +x "$APPS_DIR/.slforge-start.sh" + lxc-attach -n streamlit -- /srv/apps/.slforge-start.sh \ + "/srv/apps/$name/src" "$entrypoint" "$port" "$name" \ + > "/var/run/streamlit-$name.pid" + else + # Run directly on host + cd "$app_dir/src" + if [ -f requirements.txt ]; then + pip3 install -q -r requirements.txt 2>/dev/null + fi + nohup streamlit run "$entrypoint" \ + --server.port "$port" \ + --server.address 0.0.0.0 \ + --server.headless true \ + > "/var/log/streamlit-$name.log" 2>&1 & + echo $! > "/var/run/streamlit-$name.pid" + fi + + # Update UCI + set_app_config "$name" enabled '1' + set_app_config "$name" port "$port" + + # Wait for port to become available + sleep 3 + if netstat -tln 2>/dev/null | grep -q ":$port "; then + [ "$quiet" = "0" ] && log_ok "Started $name" + [ "$quiet" = "0" ] && log_info "URL: http://192.168.255.1:$port" + return 0 + fi + + [ "$quiet" = "0" ] && log_err "Failed to start $name" + return 1 +} + +# Stop app instance +cmd_stop() { + local name="$1" + [ -z "$name" ] && { log_err "App name required"; return 1; } + + if [ -f "/var/run/streamlit-$name.pid" ]; then + local pid=$(cat "/var/run/streamlit-$name.pid") + if kill -0 "$pid" 2>/dev/null; then + log_info "Stopping $name (PID: $pid)..." + kill "$pid" 2>/dev/null + sleep 1 + kill -9 "$pid" 2>/dev/null + fi + rm -f "/var/run/streamlit-$name.pid" + fi + + set_app_config "$name" enabled '0' + log_ok "Stopped $name" +} + +# Restart app +cmd_restart() { + local name="$1" + cmd_stop "$name" + sleep 1 + cmd_start "$name" +} + +# Show status +cmd_status() { + local name="$1" + + if [ -n "$name" ]; then + cmd_info "$name" + else + cmd_list + fi +} + +# View logs +cmd_logs() { + local name="$1" + local follow=0 + + [ -z "$name" ] && { log_err "App name required"; return 1; } + + shift + [ "$1" = "-f" ] && follow=1 + + local logfile="/var/log/streamlit-$name.log" + + if [ ! -f "$logfile" ]; then + log_err "No logs found for $name" + return 1 + fi + + if [ "$follow" = "1" ]; then + tail -f "$logfile" + else + tail -100 "$logfile" + fi +} + +# Delete app +cmd_delete() { + local name="$1" + [ -z "$name" ] && { log_err "App name required"; return 1; } + + if ! app_exists "$name"; then + log_err "App not found: $name" + return 1 + fi + + # Stop if running + cmd_stop "$name" 2>/dev/null + + # Remove files + rm -rf "$APPS_DIR/$name" + rm -rf "$PREVIEWS_DIR/$name" + rm -f "/var/log/streamlit-$name.log" + + # Remove UCI config + uci delete streamlit-forge."$name" 2>/dev/null + uci commit streamlit-forge + + log_ok "Deleted app: $name" +} + +# Expose app with vhost + SSL +cmd_expose() { + local name="$1" + shift + + [ -z "$name" ] && { log_err "App name required"; return 1; } + + if ! app_exists "$name"; then + log_err "App not found: $name" + return 1 + fi + + local domain="" + while [ $# -gt 0 ]; do + case "$1" in + --domain) domain="$2"; shift 2 ;; + *) shift ;; + esac + done + + # Default domain + [ -z "$domain" ] && domain="$name.$BASE_DOMAIN" + + local port=$(get_app_config "$name" port) + + log_info "Exposing $name at $domain..." + + # Create HAProxy vhost + if command -v haproxyctl >/dev/null 2>&1; then + haproxyctl vhost add "$domain" 2>/dev/null + # Add mitmproxy route + local routes_file="/srv/mitmproxy/haproxy-routes.json" + if [ -f "$routes_file" ]; then + # Add route using jsonfilter + sed + local tmp=$(mktemp) + cat "$routes_file" | sed "s/}$/,\"$domain\":[\"192.168.255.1\",$port]}/" > "$tmp" + mv "$tmp" "$routes_file" + fi + log_info "Requesting SSL certificate..." + haproxyctl ssl request "$domain" 2>/dev/null + else + log_warn "haproxyctl not available - manual vhost setup required" + fi + + # Update UCI + set_app_config "$name" domain "$domain" + + log_ok "Exposed at: https://$domain" +} + +# Hide app (remove public access) +cmd_hide() { + local name="$1" + [ -z "$name" ] && { log_err "App name required"; return 1; } + + local domain=$(get_app_config "$name" domain) + + if [ -n "$domain" ] && command -v haproxyctl >/dev/null 2>&1; then + log_info "Removing vhost: $domain" + haproxyctl vhost remove "$domain" 2>/dev/null + fi + + set_app_config "$name" domain "" + log_ok "Hidden app: $name" +} + +# List templates +cmd_templates() { + echo "" + echo "Available Templates" + echo "===================" + echo "" + + for tpl in "$TEMPLATES_DIR"/*/; do + [ -d "$tpl" ] || continue + local name=$(basename "$tpl") + local desc="" + [ -f "$tpl/README.md" ] && desc=$(head -1 "$tpl/README.md" | sed 's/^#\s*//') + printf " %-15s %s\n" "$name" "$desc" + done + + echo "" + echo "Usage: slforge create myapp --from-template