feat(metablogizer): KISS UI redesign with backend status

- Replace overview.js with dashboard.js using standard cbi-* classes
- Add api.js module for RPC declarations
- Show port, runtime, backend_running status in sites table
- Add sync_config, discover_vhosts, import_vhost RPC methods
- Update ACL with new method permissions
- Menu: Sites -> Dashboard

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
CyberMind-FR 2026-02-01 08:06:22 +01:00
parent e07fec6cb4
commit 163364843e
88 changed files with 1238 additions and 534 deletions

View File

@ -12,7 +12,7 @@ LUCI_PKGARCH:=all
PKG_NAME:=luci-app-metablogizer PKG_NAME:=luci-app-metablogizer
PKG_VERSION:=1.0.0 PKG_VERSION:=1.0.0
PKG_RELEASE:=3 PKG_RELEASE:=5
PKG_MAINTAINER:=CyberMind <contact@cybermind.fr> PKG_MAINTAINER:=CyberMind <contact@cybermind.fr>
PKG_LICENSE:=GPL-2.0 PKG_LICENSE:=GPL-2.0

View File

@ -0,0 +1,234 @@
'use strict';
'require rpc';
'require baseclass';
/**
* MetaBlogizer API Module
* RPCD interface for MetaBlogizer static site publisher
*/
var callStatus = rpc.declare({
object: 'luci.metablogizer',
method: 'status',
expect: { result: {} }
});
var callListSites = rpc.declare({
object: 'luci.metablogizer',
method: 'list_sites',
expect: { sites: [] }
});
var callCreateSite = rpc.declare({
object: 'luci.metablogizer',
method: 'create_site',
params: ['name', 'domain', 'gitea_repo', 'ssl', 'description'],
expect: { result: {} }
});
var callUpdateSite = rpc.declare({
object: 'luci.metablogizer',
method: 'update_site',
params: ['id', 'name', 'domain', 'gitea_repo', 'ssl', 'enabled', 'description'],
expect: { result: {} }
});
var callDeleteSite = rpc.declare({
object: 'luci.metablogizer',
method: 'delete_site',
params: ['id'],
expect: { result: {} }
});
var callSyncSite = rpc.declare({
object: 'luci.metablogizer',
method: 'sync_site',
params: ['id'],
expect: { result: {} }
});
var callGetHostingStatus = rpc.declare({
object: 'luci.metablogizer',
method: 'get_hosting_status',
expect: { result: {} }
});
var callCheckSiteHealth = rpc.declare({
object: 'luci.metablogizer',
method: 'check_site_health',
params: ['id'],
expect: { result: {} }
});
var callGetPublishInfo = rpc.declare({
object: 'luci.metablogizer',
method: 'get_publish_info',
params: ['id'],
expect: { result: {} }
});
var callUploadFile = rpc.declare({
object: 'luci.metablogizer',
method: 'upload_file',
params: ['site_id', 'filename', 'content'],
expect: { result: {} }
});
var callListFiles = rpc.declare({
object: 'luci.metablogizer',
method: 'list_files',
params: ['site_id'],
expect: { result: {} }
});
var callGetSettings = rpc.declare({
object: 'luci.metablogizer',
method: 'get_settings',
expect: { result: {} }
});
var callEnableTor = rpc.declare({
object: 'luci.metablogizer',
method: 'enable_tor',
params: ['id'],
expect: { result: {} }
});
var callDisableTor = rpc.declare({
object: 'luci.metablogizer',
method: 'disable_tor',
params: ['id'],
expect: { result: {} }
});
var callGetTorStatus = rpc.declare({
object: 'luci.metablogizer',
method: 'get_tor_status',
params: ['id'],
expect: { result: {} }
});
var callRepairSite = rpc.declare({
object: 'luci.metablogizer',
method: 'repair_site',
params: ['id'],
expect: { result: {} }
});
var callDiscoverVhosts = rpc.declare({
object: 'luci.metablogizer',
method: 'discover_vhosts',
expect: { result: {} }
});
var callImportVhost = rpc.declare({
object: 'luci.metablogizer',
method: 'import_vhost',
params: ['instance', 'name', 'domain'],
expect: { result: {} }
});
var callSyncConfig = rpc.declare({
object: 'luci.metablogizer',
method: 'sync_config',
expect: { result: {} }
});
return baseclass.extend({
getStatus: function() {
return callStatus();
},
listSites: function() {
return callListSites().then(function(res) {
return res.sites || [];
});
},
createSite: function(name, domain, giteaRepo, ssl, description) {
return callCreateSite(name, domain, giteaRepo || '', ssl || '1', description || '');
},
updateSite: function(id, name, domain, giteaRepo, ssl, enabled, description) {
return callUpdateSite(id, name, domain, giteaRepo || '', ssl || '1', enabled || '1', description || '');
},
deleteSite: function(id) {
return callDeleteSite(id);
},
syncSite: function(id) {
return callSyncSite(id);
},
getHostingStatus: function() {
return callGetHostingStatus();
},
checkSiteHealth: function(id) {
return callCheckSiteHealth(id);
},
getPublishInfo: function(id) {
return callGetPublishInfo(id);
},
uploadFile: function(siteId, filename, content) {
return callUploadFile(siteId, filename, content);
},
listFiles: function(siteId) {
return callListFiles(siteId).then(function(res) {
return res.files || [];
});
},
getSettings: function() {
return callGetSettings();
},
enableTor: function(id) {
return callEnableTor(id);
},
disableTor: function(id) {
return callDisableTor(id);
},
getTorStatus: function(id) {
return callGetTorStatus(id);
},
repairSite: function(id) {
return callRepairSite(id);
},
discoverVhosts: function() {
return callDiscoverVhosts().then(function(res) {
return res.discovered || [];
});
},
importVhost: function(instance, name, domain) {
return callImportVhost(instance, name, domain);
},
syncConfig: function() {
return callSyncConfig();
},
getDashboardData: function() {
var self = this;
return Promise.all([
self.getStatus(),
self.listSites(),
self.getHostingStatus().catch(function() { return {}; })
]).then(function(results) {
return {
status: results[0] || {},
sites: results[1] || [],
hosting: results[2] || {}
};
});
}
});

View File

@ -0,0 +1,695 @@
'use strict';
'require view';
'require ui';
'require fs';
'require metablogizer.api as api';
'require metablogizer/qrcode as qrcode';
return view.extend({
status: {},
sites: [],
hosting: {},
uploadFiles: [],
currentSite: null,
load: function() {
var self = this;
return api.getDashboardData().then(function(data) {
self.status = data.status || {};
self.sites = data.sites || [];
self.hosting = data.hosting || {};
});
},
render: function() {
var self = this;
var status = this.status;
var sites = this.sites;
var hosting = this.hosting;
return E('div', { 'class': 'cbi-map' }, [
E('h2', {}, _('MetaBlogizer')),
E('div', { 'class': 'cbi-map-descr' }, _('Static site publisher with HAProxy vhosts and SSL')),
// Status Section
E('div', { 'class': 'cbi-section' }, [
E('h3', {}, _('Status')),
E('table', { 'class': 'table' }, [
E('tr', { 'class': 'tr' }, [
E('td', { 'class': 'td', 'style': 'width:200px' }, _('Runtime')),
E('td', { 'class': 'td' }, status.detected_runtime || 'uhttpd')
]),
E('tr', { 'class': 'tr' }, [
E('td', { 'class': 'td' }, _('HAProxy')),
E('td', { 'class': 'td' }, hosting.haproxy_status === 'running' ?
E('span', { 'style': 'color:#0a0' }, _('Running')) :
E('span', { 'style': 'color:#a00' }, _('Stopped')))
]),
E('tr', { 'class': 'tr' }, [
E('td', { 'class': 'td' }, _('Public IP')),
E('td', { 'class': 'td' }, hosting.public_ip || '-')
]),
E('tr', { 'class': 'tr' }, [
E('td', { 'class': 'td' }, _('Sites')),
E('td', { 'class': 'td' }, String(sites.length))
]),
E('tr', { 'class': 'tr' }, [
E('td', { 'class': 'td' }, _('Backends Running')),
E('td', { 'class': 'td' }, String(sites.filter(function(s) { return s.backend_running; }).length) + ' / ' + sites.length)
])
]),
E('div', { 'style': 'margin-top:1em' }, [
E('button', {
'class': 'cbi-button cbi-button-action',
'click': ui.createHandlerFn(this, 'handleSyncConfig')
}, _('Sync Config')),
' ',
E('span', { 'class': 'cbi-value-description' }, _('Update port/runtime info for all sites'))
])
]),
// Sites Section
E('div', { 'class': 'cbi-section' }, [
E('h3', {}, _('Sites')),
sites.length > 0 ? this.renderSitesTable(sites) : E('div', { 'class': 'cbi-section-descr' }, _('No sites configured'))
]),
// Create Site Section
E('div', { 'class': 'cbi-section' }, [
E('h3', {}, _('Create Site')),
E('div', { 'class': 'cbi-section-descr' }, _('Add a new static site with auto-configured HAProxy vhost and SSL')),
E('div', { 'class': 'cbi-value' }, [
E('label', { 'class': 'cbi-value-title' }, _('Site Name')),
E('div', { 'class': 'cbi-value-field' }, [
E('input', { 'type': 'text', 'id': 'new-site-name', 'class': 'cbi-input-text',
'placeholder': 'myblog' }),
E('div', { 'class': 'cbi-value-description' }, _('Lowercase letters, numbers, and hyphens only'))
])
]),
E('div', { 'class': 'cbi-value' }, [
E('label', { 'class': 'cbi-value-title' }, _('Domain')),
E('div', { 'class': 'cbi-value-field' },
E('input', { 'type': 'text', 'id': 'new-site-domain', 'class': 'cbi-input-text',
'placeholder': 'blog.example.com' }))
]),
E('div', { 'class': 'cbi-value' }, [
E('label', { 'class': 'cbi-value-title' }, _('Gitea Repository')),
E('div', { 'class': 'cbi-value-field' }, [
E('input', { 'type': 'text', 'id': 'new-site-gitea', 'class': 'cbi-input-text',
'placeholder': 'user/repo' }),
E('div', { 'class': 'cbi-value-description' }, _('Optional: Sync content from Gitea'))
])
]),
E('div', { 'class': 'cbi-value' }, [
E('label', { 'class': 'cbi-value-title' }, _('Description')),
E('div', { 'class': 'cbi-value-field' },
E('input', { 'type': 'text', 'id': 'new-site-desc', 'class': 'cbi-input-text',
'placeholder': 'Short description (optional)' }))
]),
E('div', { 'class': 'cbi-value' }, [
E('label', { 'class': 'cbi-value-title' }, _('HTTPS')),
E('div', { 'class': 'cbi-value-field' },
E('select', { 'id': 'new-site-ssl', 'class': 'cbi-input-select' }, [
E('option', { 'value': '1', 'selected': true }, _('Enabled (ACME)')),
E('option', { 'value': '0' }, _('Disabled'))
]))
]),
E('div', { 'class': 'cbi-page-actions' },
E('button', {
'class': 'cbi-button cbi-button-positive',
'click': ui.createHandlerFn(this, 'handleCreateSite')
}, _('Create Site')))
]),
// Hosting Status Section
this.renderHostingSection(hosting)
]);
},
renderSitesTable: function(sites) {
var self = this;
return E('table', { 'class': 'table' }, [
E('tr', { 'class': 'tr table-titles' }, [
E('th', { 'class': 'th' }, _('Name')),
E('th', { 'class': 'th' }, _('Domain')),
E('th', { 'class': 'th' }, _('Port')),
E('th', { 'class': 'th' }, _('Backend')),
E('th', { 'class': 'th' }, _('Content')),
E('th', { 'class': 'th' }, _('Actions'))
])
].concat(sites.map(function(site) {
var backendStatus = site.backend_running ?
E('span', { 'style': 'color:#0a0' }, _('Running')) :
E('span', { 'style': 'color:#a00' }, _('Stopped'));
var contentStatus = site.has_content ?
E('span', { 'style': 'color:#0a0' }, _('OK')) :
E('span', { 'style': 'color:#888' }, _('Empty'));
return E('tr', { 'class': 'tr' }, [
E('td', { 'class': 'td' }, [
E('strong', {}, site.name),
site.runtime ? E('br') : '',
site.runtime ? E('small', { 'style': 'color:#888' }, site.runtime) : ''
]),
E('td', { 'class': 'td' }, site.domain ?
E('a', { 'href': site.url || ('https://' + site.domain), 'target': '_blank' }, site.domain) :
E('em', {}, '-')),
E('td', { 'class': 'td' }, site.port ? String(site.port) : '-'),
E('td', { 'class': 'td' }, backendStatus),
E('td', { 'class': 'td' }, contentStatus),
E('td', { 'class': 'td' }, [
E('button', {
'class': 'cbi-button cbi-button-action',
'click': ui.createHandlerFn(self, 'showShareModal', site),
'title': _('Share')
}, _('Share')),
' ',
E('button', {
'class': 'cbi-button cbi-button-action',
'click': ui.createHandlerFn(self, 'showUploadModal', site),
'title': _('Upload')
}, _('Upload')),
' ',
E('button', {
'class': 'cbi-button cbi-button-action',
'click': ui.createHandlerFn(self, 'showFilesModal', site),
'title': _('Files')
}, _('Files')),
' ',
E('button', {
'class': 'cbi-button cbi-button-action',
'click': ui.createHandlerFn(self, 'showEditModal', site),
'title': _('Edit')
}, _('Edit')),
' ',
site.gitea_repo ? E('button', {
'class': 'cbi-button cbi-button-action',
'click': ui.createHandlerFn(self, 'handleSync', site),
'title': _('Sync')
}, _('Sync')) : '',
' ',
E('button', {
'class': 'cbi-button cbi-button-remove',
'click': ui.createHandlerFn(self, 'handleDelete', site),
'title': _('Delete')
}, _('Delete'))
])
]);
})));
},
renderHostingSection: function(hosting) {
var hostingSites = hosting.sites || [];
if (hostingSites.length === 0) return E('div');
return E('div', { 'class': 'cbi-section' }, [
E('h3', {}, _('Hosting Status')),
E('div', { 'class': 'cbi-section-descr' }, _('DNS, SSL certificates, and publish status for each site')),
E('table', { 'class': 'table' }, [
E('tr', { 'class': 'tr table-titles' }, [
E('th', { 'class': 'th' }, _('Site')),
E('th', { 'class': 'th' }, _('DNS')),
E('th', { 'class': 'th' }, _('IP')),
E('th', { 'class': 'th' }, _('Certificate')),
E('th', { 'class': 'th' }, _('Status'))
])
].concat(hostingSites.map(function(site) {
return E('tr', { 'class': 'tr' }, [
E('td', { 'class': 'td' }, E('strong', {}, site.name)),
E('td', { 'class': 'td' }, site.dns_status === 'ok' ?
E('span', { 'style': 'color:#0a0' }, 'OK') :
E('span', { 'style': 'color:#a00' }, site.dns_status || 'unknown')),
E('td', { 'class': 'td' }, site.dns_ip || '-'),
E('td', { 'class': 'td' }, site.cert_status === 'ok' ?
E('span', { 'style': 'color:#0a0' }, (site.cert_days || 0) + 'd') :
E('span', { 'style': 'color:#a00' }, site.cert_status || 'missing')),
E('td', { 'class': 'td' }, site.publish_status === 'published' ?
E('span', { 'style': 'color:#0a0' }, _('Published')) :
E('span', { 'style': 'color:#888' }, site.publish_status || 'pending'))
]);
})))
]);
},
handleCreateSite: function() {
var self = this;
var name = document.getElementById('new-site-name').value.trim();
var domain = document.getElementById('new-site-domain').value.trim();
var gitea = document.getElementById('new-site-gitea').value.trim();
var desc = document.getElementById('new-site-desc').value.trim();
var ssl = document.getElementById('new-site-ssl').value;
if (!name) {
ui.addNotification(null, E('p', _('Site name is required')), 'error');
return;
}
if (!domain) {
ui.addNotification(null, E('p', _('Domain is required')), 'error');
return;
}
if (!/^[a-z0-9-]+$/.test(name)) {
ui.addNotification(null, E('p', _('Invalid name format: use lowercase letters, numbers, and hyphens')), 'error');
return;
}
ui.showModal(_('Creating Site'), [
E('p', { 'class': 'spinning' }, _('Setting up site and HAProxy vhost...'))
]);
api.createSite(name, domain, gitea, ssl, desc).then(function(r) {
ui.hideModal();
if (r.success) {
ui.addNotification(null, E('p', _('Site created successfully')));
self.showShareModal({ name: r.name || name, domain: r.domain || domain, url: r.url });
setTimeout(function() { window.location.reload(); }, 500);
} else {
ui.addNotification(null, E('p', _('Failed: ') + (r.error || 'Unknown error')), 'error');
}
}).catch(function(e) {
ui.hideModal();
ui.addNotification(null, E('p', _('Error: ') + e.message), 'error');
});
},
showEditModal: function(site) {
var self = this;
ui.showModal(_('Edit Site: ') + site.name, [
E('div', { 'class': 'cbi-section' }, [
E('div', { 'class': 'cbi-value' }, [
E('label', { 'class': 'cbi-value-title' }, _('Domain')),
E('div', { 'class': 'cbi-value-field' },
E('input', { 'type': 'text', 'id': 'edit-site-domain', 'class': 'cbi-input-text',
'value': site.domain || '' }))
]),
E('div', { 'class': 'cbi-value' }, [
E('label', { 'class': 'cbi-value-title' }, _('Gitea Repository')),
E('div', { 'class': 'cbi-value-field' },
E('input', { 'type': 'text', 'id': 'edit-site-gitea', 'class': 'cbi-input-text',
'value': site.gitea_repo || '', 'placeholder': 'user/repo' }))
]),
E('div', { 'class': 'cbi-value' }, [
E('label', { 'class': 'cbi-value-title' }, _('Description')),
E('div', { 'class': 'cbi-value-field' },
E('input', { 'type': 'text', 'id': 'edit-site-desc', 'class': 'cbi-input-text',
'value': site.description || '' }))
]),
E('div', { 'class': 'cbi-value' }, [
E('label', { 'class': 'cbi-value-title' }, _('HTTPS')),
E('div', { 'class': 'cbi-value-field' },
E('select', { 'id': 'edit-site-ssl', 'class': 'cbi-input-select' }, [
E('option', { 'value': '1', 'selected': site.ssl !== false }, _('Enabled')),
E('option', { 'value': '0', 'selected': site.ssl === false }, _('Disabled'))
]))
]),
E('div', { 'class': 'cbi-value' }, [
E('label', { 'class': 'cbi-value-title' }, _('Enabled')),
E('div', { 'class': 'cbi-value-field' },
E('select', { 'id': 'edit-site-enabled', 'class': 'cbi-input-select' }, [
E('option', { 'value': '1', 'selected': site.enabled !== false }, _('Yes')),
E('option', { 'value': '0', 'selected': site.enabled === false }, _('No'))
]))
])
]),
E('div', { 'class': 'right' }, [
E('button', { 'class': 'cbi-button', 'click': ui.hideModal }, _('Cancel')),
' ',
E('button', { 'class': 'cbi-button cbi-button-positive', 'click': function() {
var domain = document.getElementById('edit-site-domain').value.trim();
var gitea = document.getElementById('edit-site-gitea').value.trim();
var desc = document.getElementById('edit-site-desc').value.trim();
var ssl = document.getElementById('edit-site-ssl').value;
var enabled = document.getElementById('edit-site-enabled').value;
if (!domain) {
ui.addNotification(null, E('p', _('Domain required')), 'error');
return;
}
ui.hideModal();
ui.showModal(_('Saving'), [E('p', { 'class': 'spinning' }, _('Updating site...'))]);
api.updateSite(site.id, site.name, domain, gitea, ssl, enabled, desc).then(function(r) {
ui.hideModal();
if (r.success) {
ui.addNotification(null, E('p', _('Site updated')));
window.location.reload();
} else {
ui.addNotification(null, E('p', _('Failed: ') + (r.error || 'Unknown')), 'error');
}
}).catch(function(e) {
ui.hideModal();
ui.addNotification(null, E('p', _('Error: ') + e.message), 'error');
});
}}, _('Save'))
])
]);
},
showUploadModal: function(site) {
var self = this;
this.uploadFiles = [];
this.currentSite = site;
var fileList = E('div', { 'id': 'upload-file-list', 'style': 'margin:1em 0; max-height:200px; overflow-y:auto' });
ui.showModal(_('Upload to: ') + site.name, [
E('div', { 'class': 'cbi-section' }, [
E('div', { 'class': 'cbi-value' }, [
E('label', { 'class': 'cbi-value-title' }, _('Files')),
E('div', { 'class': 'cbi-value-field' }, [
E('input', { 'type': 'file', 'id': 'upload-file-input', 'multiple': true,
'change': function(e) { self.handleFileSelect(e, fileList); } }),
E('div', { 'class': 'cbi-value-description' }, _('Select HTML, CSS, JS, images, etc.'))
])
]),
fileList,
E('div', { 'class': 'cbi-value' }, [
E('label', { 'class': 'cbi-value-title' }, _('Set first HTML as index')),
E('div', { 'class': 'cbi-value-field' },
E('input', { 'type': 'checkbox', 'id': 'upload-as-index', 'checked': true }))
]),
E('div', { 'class': 'cbi-value' }, [
E('label', { 'class': 'cbi-value-title' }, ''),
E('div', { 'class': 'cbi-value-field cbi-value-description' },
_('After upload, use Ctrl+Shift+R to refresh cached pages'))
])
]),
E('div', { 'class': 'right' }, [
E('button', { 'class': 'cbi-button', 'click': ui.hideModal }, _('Cancel')),
' ',
E('button', { 'class': 'cbi-button cbi-button-positive', 'click': ui.createHandlerFn(this, 'handleUpload') }, _('Upload'))
])
]);
},
handleFileSelect: function(e, listEl) {
var files = e.target.files;
for (var i = 0; i < files.length; i++) {
this.uploadFiles.push(files[i]);
}
this.updateFileList(listEl);
},
updateFileList: function(listEl) {
var self = this;
listEl.innerHTML = '';
if (this.uploadFiles.length === 0) return;
this.uploadFiles.forEach(function(f, i) {
var row = E('div', { 'style': 'display:flex; align-items:center; gap:0.5em; margin:0.25em 0; padding:0.25em; background:#f8f8f8; border-radius:4px' }, [
E('span', { 'style': 'flex:1' }, f.name),
E('span', { 'style': 'color:#888; font-size:0.9em' }, self.formatSize(f.size)),
E('button', { 'class': 'cbi-button cbi-button-remove', 'style': 'padding:0.25em 0.5em',
'click': function() { self.uploadFiles.splice(i, 1); self.updateFileList(listEl); } }, 'X')
]);
listEl.appendChild(row);
});
},
handleUpload: function() {
var self = this;
if (!this.uploadFiles.length) {
ui.addNotification(null, E('p', _('No files selected')), 'error');
return;
}
var site = this.currentSite;
var asIndex = document.getElementById('upload-as-index').checked;
var firstHtml = null;
if (asIndex) {
for (var i = 0; i < this.uploadFiles.length; i++) {
if (this.uploadFiles[i].name.endsWith('.html')) {
firstHtml = this.uploadFiles[i];
break;
}
}
}
ui.hideModal();
ui.showModal(_('Uploading'), [E('p', { 'class': 'spinning' }, _('Uploading files...'))]);
var sitesRoot = '/srv/metablogizer/sites';
Promise.all(this.uploadFiles.map(function(f) {
return new Promise(function(resolve) {
var reader = new FileReader();
reader.onload = function(e) {
var dest = (asIndex && f === firstHtml) ? 'index.html' : f.name;
fs.write(sitesRoot + '/' + site.name + '/' + dest, e.target.result)
.then(function() { resolve({ ok: true, name: f.name }); })
.catch(function() { resolve({ ok: false, name: f.name }); });
};
reader.onerror = function() { resolve({ ok: false, name: f.name }); };
reader.readAsText(f);
});
})).then(function(results) {
ui.hideModal();
var ok = results.filter(function(r) { return r.ok; }).length;
ui.addNotification(null, E('p', ok + _(' file(s) uploaded successfully')));
self.uploadFiles = [];
});
},
showFilesModal: function(site) {
var self = this;
this.currentSite = site;
var sitesRoot = '/srv/metablogizer/sites';
ui.showModal(_('Files: ') + site.name, [
E('div', { 'id': 'files-list' }, [
E('p', { 'class': 'spinning' }, _('Loading files...'))
]),
E('div', { 'class': 'right' }, [
E('button', { 'class': 'cbi-button', 'click': ui.hideModal }, _('Close'))
])
]);
fs.list(sitesRoot + '/' + site.name).then(function(files) {
var container = document.getElementById('files-list');
container.innerHTML = '';
if (!files || !files.length) {
container.appendChild(E('p', { 'style': 'color:#888' }, _('No files')));
return;
}
var table = E('table', { 'class': 'table' }, [
E('tr', { 'class': 'tr table-titles' }, [
E('th', { 'class': 'th' }, _('File')),
E('th', { 'class': 'th' }, _('Size')),
E('th', { 'class': 'th' }, _('Actions'))
])
]);
files.forEach(function(f) {
if (f.type !== 'file') return;
var isIndex = f.name === 'index.html';
table.appendChild(E('tr', { 'class': 'tr' }, [
E('td', { 'class': 'td' }, [
isIndex ? E('strong', {}, f.name + ' (homepage)') : f.name
]),
E('td', { 'class': 'td' }, self.formatSize(f.size)),
E('td', { 'class': 'td' }, [
(!isIndex && f.name.endsWith('.html')) ? E('button', {
'class': 'cbi-button cbi-button-action',
'click': function() { self.setAsHomepage(site, f.name); }
}, _('Set as Homepage')) : '',
' ',
E('button', {
'class': 'cbi-button cbi-button-remove',
'click': function() { self.deleteFile(site, f.name); }
}, _('Delete'))
])
]));
});
container.appendChild(table);
}).catch(function(e) {
var container = document.getElementById('files-list');
container.innerHTML = '';
container.appendChild(E('p', { 'style': 'color:#a00' }, _('Error: ') + e.message));
});
},
setAsHomepage: function(site, filename) {
var sitesRoot = '/srv/metablogizer/sites';
var path = sitesRoot + '/' + site.name;
ui.showModal(_('Setting Homepage'), [E('p', { 'class': 'spinning' }, _('Renaming...'))]);
fs.read(path + '/' + filename).then(function(content) {
return fs.write(path + '/index.html', content);
}).then(function() {
return fs.remove(path + '/' + filename);
}).then(function() {
ui.hideModal();
ui.addNotification(null, E('p', filename + _(' set as homepage')));
}).catch(function(e) {
ui.hideModal();
ui.addNotification(null, E('p', _('Error: ') + e.message), 'error');
});
},
deleteFile: function(site, filename) {
var self = this;
var sitesRoot = '/srv/metablogizer/sites';
if (!confirm(_('Delete ') + filename + '?')) return;
fs.remove(sitesRoot + '/' + site.name + '/' + filename).then(function() {
ui.addNotification(null, E('p', _('File deleted')));
self.showFilesModal(site);
}).catch(function(e) {
ui.addNotification(null, E('p', _('Error: ') + e.message), 'error');
});
},
showShareModal: function(site) {
var self = this;
var url = site.url || ('https://' + site.domain);
var title = site.name + ' - SecuBox';
var enc = encodeURIComponent;
var qrSvg = '';
try {
qrSvg = qrcode.generateSVG(url, 180);
} catch (e) {
qrSvg = '<p>QR code unavailable</p>';
}
ui.showModal(_('Share: ') + site.name, [
E('div', { 'style': 'text-align:center' }, [
E('div', { 'class': 'cbi-value', 'style': 'display:flex; gap:0.5em; margin-bottom:1em' }, [
E('input', { 'type': 'text', 'readonly': true, 'value': url, 'id': 'share-url',
'class': 'cbi-input-text', 'style': 'flex:1' }),
E('button', { 'class': 'cbi-button cbi-button-action', 'click': function() {
self.copyToClipboard(url);
}}, _('Copy'))
]),
E('div', { 'style': 'display:inline-block; padding:1em; background:#f8f8f8; border-radius:8px; margin:1em 0' }, [
E('div', { 'innerHTML': qrSvg })
]),
E('div', { 'style': 'margin-top:1em' }, [
E('p', { 'style': 'margin-bottom:0.5em' }, _('Share on:')),
E('div', { 'style': 'display:flex; gap:0.5em; justify-content:center; flex-wrap:wrap' }, [
E('a', { 'href': 'https://twitter.com/intent/tweet?url=' + enc(url) + '&text=' + enc(title),
'target': '_blank', 'class': 'cbi-button cbi-button-action' }, 'Twitter'),
E('a', { 'href': 'https://www.linkedin.com/sharing/share-offsite/?url=' + enc(url),
'target': '_blank', 'class': 'cbi-button cbi-button-action' }, 'LinkedIn'),
E('a', { 'href': 'https://t.me/share/url?url=' + enc(url) + '&text=' + enc(title),
'target': '_blank', 'class': 'cbi-button cbi-button-action' }, 'Telegram'),
E('a', { 'href': 'https://wa.me/?text=' + enc(title + ' ' + url),
'target': '_blank', 'class': 'cbi-button cbi-button-action' }, 'WhatsApp'),
E('a', { 'href': 'mailto:?subject=' + enc(title) + '&body=' + enc(url),
'class': 'cbi-button cbi-button-action' }, 'Email')
])
])
]),
E('div', { 'class': 'right', 'style': 'margin-top:1em' }, [
E('a', { 'href': url, 'target': '_blank', 'class': 'cbi-button cbi-button-positive',
'style': 'text-decoration:none' }, _('Visit Site')),
' ',
E('button', { 'class': 'cbi-button', 'click': ui.hideModal }, _('Close'))
])
]);
},
handleSync: function(site) {
ui.showModal(_('Syncing'), [E('p', { 'class': 'spinning' }, _('Pulling from Gitea...'))]);
api.syncSite(site.id).then(function(r) {
ui.hideModal();
if (r.success) {
ui.addNotification(null, E('p', _('Site synced successfully')));
} else {
ui.addNotification(null, E('p', _('Sync failed: ') + (r.error || 'Unknown')), 'error');
}
}).catch(function(e) {
ui.hideModal();
ui.addNotification(null, E('p', _('Error: ') + e.message), 'error');
});
},
handleDelete: function(site) {
var self = this;
ui.showModal(_('Delete Site'), [
E('p', {}, _('Are you sure you want to delete "') + site.name + '"?'),
E('p', { 'style': 'color:#a00' }, _('This will remove the site, HAProxy vhost, and all files.')),
E('div', { 'class': 'right', 'style': 'margin-top:1em' }, [
E('button', { 'class': 'cbi-button', 'click': ui.hideModal }, _('Cancel')),
' ',
E('button', { 'class': 'cbi-button cbi-button-remove', 'click': function() {
ui.hideModal();
ui.showModal(_('Deleting'), [E('p', { 'class': 'spinning' }, _('Removing site...'))]);
api.deleteSite(site.id).then(function(r) {
ui.hideModal();
if (r.success) {
ui.addNotification(null, E('p', _('Site deleted')));
window.location.reload();
} else {
ui.addNotification(null, E('p', _('Failed: ') + (r.error || 'Unknown')), 'error');
}
}).catch(function(e) {
ui.hideModal();
ui.addNotification(null, E('p', _('Error: ') + e.message), 'error');
});
}}, _('Delete'))
])
]);
},
copyToClipboard: function(text) {
if (navigator.clipboard) {
navigator.clipboard.writeText(text).then(function() {
ui.addNotification(null, E('p', _('URL copied to clipboard')));
});
} else {
var input = document.getElementById('share-url');
if (input) {
input.select();
document.execCommand('copy');
ui.addNotification(null, E('p', _('URL copied to clipboard')));
}
}
},
handleSyncConfig: function() {
ui.showModal(_('Syncing Configuration'), [
E('p', { 'class': 'spinning' }, _('Updating port and runtime info for all sites...'))
]);
api.syncConfig().then(function(r) {
ui.hideModal();
if (r.success) {
var msg = _('Configuration synced');
if (r.fixed > 0) {
msg += ' (' + r.fixed + _(' entries updated)');
}
ui.addNotification(null, E('p', msg));
window.location.reload();
} else {
ui.addNotification(null, E('p', _('Sync failed: ') + (r.error || 'Unknown')), 'error');
}
}).catch(function(e) {
ui.hideModal();
ui.addNotification(null, E('p', _('Error: ') + e.message), 'error');
});
},
formatSize: function(bytes) {
if (bytes < 1024) return bytes + ' B';
if (bytes < 1048576) return (bytes / 1024).toFixed(1) + ' KB';
return (bytes / 1048576).toFixed(1) + ' MB';
},
handleSaveApply: null,
handleSave: null,
handleReset: null
});

View File

@ -213,8 +213,8 @@ method_list_sites() {
_add_site() { _add_site() {
local section="$1" local section="$1"
local name domain gitea_repo ssl enabled description tor_enabled local name domain gitea_repo ssl enabled description tor_enabled port runtime
local has_content last_sync onion_address local has_content last_sync onion_address backend_running
config_get name "$section" name "" config_get name "$section" name ""
config_get domain "$section" domain "" config_get domain "$section" domain ""
@ -223,6 +223,8 @@ _add_site() {
config_get enabled "$section" enabled "1" config_get enabled "$section" enabled "1"
config_get description "$section" description "" config_get description "$section" description ""
config_get tor_enabled "$section" tor_enabled "0" config_get tor_enabled "$section" tor_enabled "0"
config_get port "$section" port ""
config_get runtime "$section" runtime ""
# Check if site has content # Check if site has content
has_content="0" has_content="0"
@ -242,6 +244,16 @@ _add_site() {
onion_address=$(get_onion_address "$name") onion_address=$(get_onion_address "$name")
fi fi
# Check if backend is running (uhttpd listening on port)
backend_running="0"
if [ -n "$port" ]; then
# Check if port is listening using /proc/net/tcp (hex port)
local hex_port=$(printf '%04X' "$port" 2>/dev/null)
if grep -qi ":${hex_port}" /proc/net/tcp 2>/dev/null; then
backend_running="1"
fi
fi
json_add_object json_add_object
json_add_string "id" "$section" json_add_string "id" "$section"
json_add_string "name" "$name" json_add_string "name" "$name"
@ -253,6 +265,9 @@ _add_site() {
json_add_boolean "has_content" "$has_content" json_add_boolean "has_content" "$has_content"
json_add_string "last_sync" "$last_sync" json_add_string "last_sync" "$last_sync"
json_add_string "url" "https://$domain" json_add_string "url" "https://$domain"
[ -n "$port" ] && json_add_int "port" "$port"
[ -n "$runtime" ] && json_add_string "runtime" "$runtime"
json_add_boolean "backend_running" "$backend_running"
# Tor hidden service info # Tor hidden service info
json_add_boolean "tor_enabled" "$(has_tor_service "$name" && echo 1 || echo 0)" json_add_boolean "tor_enabled" "$(has_tor_service "$name" && echo 1 || echo 0)"
@ -1623,6 +1638,149 @@ method_save_settings() {
json_dump json_dump
} }
# Discover uhttpd vhosts not tracked in metablogizer
method_discover_vhosts() {
SITES_ROOT=$(get_uci main sites_root "$SITES_ROOT")
json_init
json_add_array "discovered"
# Find all uhttpd instances with metablog prefix
uci show uhttpd 2>/dev/null | grep "=uhttpd" | while read -r line; do
local instance=$(echo "$line" | cut -d'=' -f1 | cut -d'.' -f2)
# Skip non-metablog instances
case "$instance" in
metablog_*) ;;
*) continue ;;
esac
# Extract site ID from instance name (metablog_site_xxx -> site_xxx)
local section_id="${instance#metablog_}"
# Check if this site exists in metablogizer config
local tracked_name=$(get_uci "$section_id" name "")
# If not tracked, discover it
if [ -z "$tracked_name" ]; then
local home=$(uci -q get "uhttpd.${instance}.home")
local listen=$(uci -q get "uhttpd.${instance}.listen_http")
local port=$(echo "$listen" | sed 's/.*://')
local name=$(basename "$home" 2>/dev/null)
if [ -n "$name" ] && [ -n "$port" ]; then
json_add_object
json_add_string "instance" "$instance"
json_add_string "section_id" "$section_id"
json_add_string "name" "$name"
json_add_string "home" "$home"
json_add_int "port" "$port"
json_add_boolean "has_content" "$([ -f "$home/index.html" ] && echo 1 || echo 0)"
json_close_object
fi
fi
done
json_close_array
json_dump
}
# Import a discovered uhttpd vhost into metablogizer
method_import_vhost() {
local instance name domain
read -r input
json_load "$input"
json_get_var instance instance
json_get_var name name
json_get_var domain domain
if [ -z "$instance" ] || [ -z "$name" ]; then
json_init
json_add_boolean "success" 0
json_add_string "error" "Missing instance or name"
json_dump
return
fi
# Get uhttpd instance details
local home=$(uci -q get "uhttpd.${instance}.home")
local listen=$(uci -q get "uhttpd.${instance}.listen_http")
local port=$(echo "$listen" | sed 's/.*://')
if [ -z "$home" ] || [ -z "$port" ]; then
json_init
json_add_boolean "success" 0
json_add_string "error" "uhttpd instance not found or invalid"
json_dump
return
fi
# Extract section_id from instance name
local section_id="${instance#metablog_}"
# Create metablogizer site entry
uci set "$UCI_CONFIG.$section_id=site"
uci set "$UCI_CONFIG.$section_id.name=$name"
uci set "$UCI_CONFIG.$section_id.domain=${domain:-$name.local}"
uci set "$UCI_CONFIG.$section_id.port=$port"
uci set "$UCI_CONFIG.$section_id.runtime=uhttpd"
uci set "$UCI_CONFIG.$section_id.ssl=1"
uci set "$UCI_CONFIG.$section_id.enabled=1"
uci commit "$UCI_CONFIG"
json_init
json_add_boolean "success" 1
json_add_string "id" "$section_id"
json_add_string "name" "$name"
json_add_int "port" "$port"
json_dump
}
# Sync all sites - ensure all have correct port/runtime in UCI
method_sync_config() {
local fixed=0
# Iterate through all metablog uhttpd instances
uci show uhttpd 2>/dev/null | grep "=uhttpd" | while read -r line; do
local instance=$(echo "$line" | cut -d'=' -f1 | cut -d'.' -f2)
case "$instance" in
metablog_*) ;;
*) continue ;;
esac
local section_id="${instance#metablog_}"
local listen=$(uci -q get "uhttpd.${instance}.listen_http")
local port=$(echo "$listen" | sed 's/.*://')
local home=$(uci -q get "uhttpd.${instance}.home")
# Check if site exists in metablogizer
local tracked_name=$(get_uci "$section_id" name "")
if [ -n "$tracked_name" ]; then
# Update port and runtime if missing
local current_port=$(get_uci "$section_id" port "")
local current_runtime=$(get_uci "$section_id" runtime "")
if [ -z "$current_port" ] && [ -n "$port" ]; then
uci set "$UCI_CONFIG.$section_id.port=$port"
fixed=$((fixed + 1))
fi
if [ -z "$current_runtime" ]; then
uci set "$UCI_CONFIG.$section_id.runtime=uhttpd"
fixed=$((fixed + 1))
fi
fi
done
uci commit "$UCI_CONFIG"
json_init
json_add_boolean "success" 1
json_add_int "fixed" "$fixed"
json_dump
}
# Main RPC interface # Main RPC interface
case "$1" in case "$1" in
list) list)
@ -1645,7 +1803,10 @@ case "$1" in
"repair_site": { "id": "string" }, "repair_site": { "id": "string" },
"enable_tor": { "id": "string" }, "enable_tor": { "id": "string" },
"disable_tor": { "id": "string" }, "disable_tor": { "id": "string" },
"get_tor_status": {} "get_tor_status": {},
"discover_vhosts": {},
"import_vhost": { "instance": "string", "name": "string", "domain": "string" },
"sync_config": {}
} }
EOF EOF
;; ;;
@ -1669,6 +1830,9 @@ EOF
enable_tor) method_enable_tor ;; enable_tor) method_enable_tor ;;
disable_tor) method_disable_tor ;; disable_tor) method_disable_tor ;;
get_tor_status) method_get_tor_status ;; get_tor_status) method_get_tor_status ;;
discover_vhosts) method_discover_vhosts ;;
import_vhost) method_import_vhost ;;
sync_config) method_sync_config ;;
*) echo '{"error": "unknown method"}' ;; *) echo '{"error": "unknown method"}' ;;
esac esac
;; ;;

View File

@ -10,12 +10,12 @@
"uci": {"metablogizer": true} "uci": {"metablogizer": true}
} }
}, },
"admin/services/metablogizer/overview": { "admin/services/metablogizer/dashboard": {
"title": "Sites", "title": "Dashboard",
"order": 10, "order": 10,
"action": { "action": {
"type": "view", "type": "view",
"path": "metablogizer/overview" "path": "metablogizer/dashboard"
} }
}, },
"admin/services/metablogizer/settings": { "admin/services/metablogizer/settings": {

View File

@ -10,7 +10,9 @@
"get_publish_info", "get_publish_info",
"get_settings", "get_settings",
"get_hosting_status", "get_hosting_status",
"check_site_health" "check_site_health",
"get_tor_status",
"discover_vhosts"
], ],
"file": ["read", "list", "stat"] "file": ["read", "list", "stat"]
}, },
@ -28,7 +30,12 @@
"sync_site", "sync_site",
"save_settings", "save_settings",
"upload_file", "upload_file",
"list_files" "list_files",
"repair_site",
"enable_tor",
"disable_tor",
"import_vhost",
"sync_config"
], ],
"luci.haproxy": [ "luci.haproxy": [
"create_backend", "create_backend",

View File

@ -8,7 +8,7 @@ Architecture: all
Installed-Size: 71680 Installed-Size: 71680
Description: Comprehensive authentication and session management with captive portal, OAuth2/OIDC integration, voucher system, and time-based access control 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 Filename: luci-app-auth-guardian_0.4.0-r3_all.ipk
Size: 12081 Size: 12078
Package: luci-app-bandwidth-manager Package: luci-app-bandwidth-manager
Version: 0.5.0-r2 Version: 0.5.0-r2
@ -20,7 +20,7 @@ Architecture: all
Installed-Size: 378880 Installed-Size: 378880
Description: Advanced bandwidth management with QoS rules, client quotas, and SQM integration Description: Advanced bandwidth management with QoS rules, client quotas, and SQM integration
Filename: luci-app-bandwidth-manager_0.5.0-r2_all.ipk Filename: luci-app-bandwidth-manager_0.5.0-r2_all.ipk
Size: 66970 Size: 66969
Package: luci-app-cdn-cache Package: luci-app-cdn-cache
Version: 0.5.0-r3 Version: 0.5.0-r3
@ -32,7 +32,7 @@ Architecture: all
Installed-Size: 122880 Installed-Size: 122880
Description: Dashboard for managing local CDN caching proxy on OpenWrt Description: Dashboard for managing local CDN caching proxy on OpenWrt
Filename: luci-app-cdn-cache_0.5.0-r3_all.ipk Filename: luci-app-cdn-cache_0.5.0-r3_all.ipk
Size: 23190 Size: 23192
Package: luci-app-client-guardian Package: luci-app-client-guardian
Version: 0.4.0-r7 Version: 0.4.0-r7
@ -44,7 +44,7 @@ Architecture: all
Installed-Size: 307200 Installed-Size: 307200
Description: Network Access Control with client monitoring, zone management, captive portal, parental controls, and SMS/email alerts 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 Filename: luci-app-client-guardian_0.4.0-r7_all.ipk
Size: 57045 Size: 57042
Package: luci-app-crowdsec-dashboard Package: luci-app-crowdsec-dashboard
Version: 0.7.0-r29 Version: 0.7.0-r29
@ -56,7 +56,7 @@ Architecture: all
Installed-Size: 296960 Installed-Size: 296960
Description: Real-time security monitoring dashboard for CrowdSec on OpenWrt Description: Real-time security monitoring dashboard for CrowdSec on OpenWrt
Filename: luci-app-crowdsec-dashboard_0.7.0-r29_all.ipk Filename: luci-app-crowdsec-dashboard_0.7.0-r29_all.ipk
Size: 55583 Size: 55584
Package: luci-app-cyberfeed Package: luci-app-cyberfeed
Version: 0.1.1-r1 Version: 0.1.1-r1
@ -68,7 +68,7 @@ Architecture: all
Installed-Size: 71680 Installed-Size: 71680
Description: Cyberpunk-themed RSS feed aggregator dashboard with social media support Description: Cyberpunk-themed RSS feed aggregator dashboard with social media support
Filename: luci-app-cyberfeed_0.1.1-r1_all.ipk Filename: luci-app-cyberfeed_0.1.1-r1_all.ipk
Size: 12838 Size: 12837
Package: luci-app-exposure Package: luci-app-exposure
Version: 1.0.0-r3 Version: 1.0.0-r3
@ -80,7 +80,7 @@ Architecture: all
Installed-Size: 153600 Installed-Size: 153600
Description: LuCI SecuBox Service Exposure Manager Description: LuCI SecuBox Service Exposure Manager
Filename: luci-app-exposure_1.0.0-r3_all.ipk Filename: luci-app-exposure_1.0.0-r3_all.ipk
Size: 20535 Size: 20536
Package: luci-app-gitea Package: luci-app-gitea
Version: 1.0.0-r2 Version: 1.0.0-r2
@ -92,7 +92,7 @@ Architecture: all
Installed-Size: 92160 Installed-Size: 92160
Description: Modern dashboard for Gitea Platform management on OpenWrt Description: Modern dashboard for Gitea Platform management on OpenWrt
Filename: luci-app-gitea_1.0.0-r2_all.ipk Filename: luci-app-gitea_1.0.0-r2_all.ipk
Size: 15586 Size: 15587
Package: luci-app-glances Package: luci-app-glances
Version: 1.0.0-r2 Version: 1.0.0-r2
@ -104,7 +104,7 @@ Architecture: all
Installed-Size: 40960 Installed-Size: 40960
Description: Modern dashboard for Glances system monitoring with SecuBox theme Description: Modern dashboard for Glances system monitoring with SecuBox theme
Filename: luci-app-glances_1.0.0-r2_all.ipk Filename: luci-app-glances_1.0.0-r2_all.ipk
Size: 6969 Size: 6966
Package: luci-app-haproxy Package: luci-app-haproxy
Version: 1.0.0-r8 Version: 1.0.0-r8
@ -128,7 +128,7 @@ Architecture: all
Installed-Size: 215040 Installed-Size: 215040
Description: Modern dashboard for Hexo static site generator on OpenWrt Description: Modern dashboard for Hexo static site generator on OpenWrt
Filename: luci-app-hexojs_1.0.0-r3_all.ipk Filename: luci-app-hexojs_1.0.0-r3_all.ipk
Size: 32980 Size: 32975
Package: luci-app-jitsi Package: luci-app-jitsi
Version: 1.0.0-r1 Version: 1.0.0-r1
@ -152,7 +152,7 @@ Architecture: all
Installed-Size: 112640 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. 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 Filename: luci-app-ksm-manager_0.4.0-r2_all.ipk
Size: 18719 Size: 18723
Package: luci-app-localai Package: luci-app-localai
Version: 0.1.0-r15 Version: 0.1.0-r15
@ -164,7 +164,7 @@ Architecture: all
Installed-Size: 81920 Installed-Size: 81920
Description: Modern dashboard for LocalAI LLM management on OpenWrt Description: Modern dashboard for LocalAI LLM management on OpenWrt
Filename: luci-app-localai_0.1.0-r15_all.ipk Filename: luci-app-localai_0.1.0-r15_all.ipk
Size: 14361 Size: 14362
Package: luci-app-lyrion Package: luci-app-lyrion
Version: 1.0.0-r1 Version: 1.0.0-r1
@ -176,7 +176,7 @@ Architecture: all
Installed-Size: 40960 Installed-Size: 40960
Description: LuCI support for Lyrion Music Server Description: LuCI support for Lyrion Music Server
Filename: luci-app-lyrion_1.0.0-r1_all.ipk Filename: luci-app-lyrion_1.0.0-r1_all.ipk
Size: 6729 Size: 6725
Package: luci-app-magicmirror2 Package: luci-app-magicmirror2
Version: 0.4.0-r6 Version: 0.4.0-r6
@ -188,7 +188,7 @@ Architecture: all
Installed-Size: 71680 Installed-Size: 71680
Description: Modern dashboard for MagicMirror2 smart display platform with module manager and SecuBox theme Description: Modern dashboard for MagicMirror2 smart display platform with module manager and SecuBox theme
Filename: luci-app-magicmirror2_0.4.0-r6_all.ipk Filename: luci-app-magicmirror2_0.4.0-r6_all.ipk
Size: 12279 Size: 12277
Package: luci-app-mailinabox Package: luci-app-mailinabox
Version: 1.0.0-r1 Version: 1.0.0-r1
@ -200,7 +200,7 @@ Architecture: all
Installed-Size: 30720 Installed-Size: 30720
Description: LuCI support for Mail-in-a-Box Description: LuCI support for Mail-in-a-Box
Filename: luci-app-mailinabox_1.0.0-r1_all.ipk Filename: luci-app-mailinabox_1.0.0-r1_all.ipk
Size: 5482 Size: 5481
Package: luci-app-media-flow Package: luci-app-media-flow
Version: 0.6.4-r1 Version: 0.6.4-r1
@ -224,7 +224,7 @@ Architecture: all
Installed-Size: 112640 Installed-Size: 112640
Description: LuCI support for MetaBlogizer Static Site Publisher Description: LuCI support for MetaBlogizer Static Site Publisher
Filename: luci-app-metablogizer_1.0.0-r3_all.ipk Filename: luci-app-metablogizer_1.0.0-r3_all.ipk
Size: 23506 Size: 23505
Package: luci-app-metabolizer Package: luci-app-metabolizer
Version: 1.0.0-r2 Version: 1.0.0-r2
@ -236,7 +236,7 @@ Architecture: all
Installed-Size: 30720 Installed-Size: 30720
Description: LuCI support for Metabolizer CMS Description: LuCI support for Metabolizer CMS
Filename: luci-app-metabolizer_1.0.0-r2_all.ipk Filename: luci-app-metabolizer_1.0.0-r2_all.ipk
Size: 4758 Size: 4756
Package: luci-app-mitmproxy Package: luci-app-mitmproxy
Version: 0.5.0-r1 Version: 0.5.0-r1
@ -260,7 +260,7 @@ Architecture: all
Installed-Size: 51200 Installed-Size: 51200
Description: Web interface for MMPM - MagicMirror Package Manager Description: Web interface for MMPM - MagicMirror Package Manager
Filename: luci-app-mmpm_0.2.0-r3_all.ipk Filename: luci-app-mmpm_0.2.0-r3_all.ipk
Size: 7901 Size: 7900
Package: luci-app-mqtt-bridge Package: luci-app-mqtt-bridge
Version: 0.4.0-r4 Version: 0.4.0-r4
@ -272,7 +272,7 @@ Architecture: all
Installed-Size: 122880 Installed-Size: 122880
Description: USB-to-MQTT IoT hub with SecuBox theme Description: USB-to-MQTT IoT hub with SecuBox theme
Filename: luci-app-mqtt-bridge_0.4.0-r4_all.ipk Filename: luci-app-mqtt-bridge_0.4.0-r4_all.ipk
Size: 22782 Size: 22774
Package: luci-app-ndpid Package: luci-app-ndpid
Version: 1.1.2-r2 Version: 1.1.2-r2
@ -284,7 +284,7 @@ Architecture: all
Installed-Size: 122880 Installed-Size: 122880
Description: Modern dashboard for nDPId deep packet inspection on OpenWrt Description: Modern dashboard for nDPId deep packet inspection on OpenWrt
Filename: luci-app-ndpid_1.1.2-r2_all.ipk Filename: luci-app-ndpid_1.1.2-r2_all.ipk
Size: 22454 Size: 22456
Package: luci-app-netdata-dashboard Package: luci-app-netdata-dashboard
Version: 0.5.0-r2 Version: 0.5.0-r2
@ -296,7 +296,7 @@ Architecture: all
Installed-Size: 133120 Installed-Size: 133120
Description: Real-time system monitoring dashboard with Netdata integration for OpenWrt Description: Real-time system monitoring dashboard with Netdata integration for OpenWrt
Filename: luci-app-netdata-dashboard_0.5.0-r2_all.ipk Filename: luci-app-netdata-dashboard_0.5.0-r2_all.ipk
Size: 22399 Size: 22401
Package: luci-app-network-modes Package: luci-app-network-modes
Version: 0.5.0-r3 Version: 0.5.0-r3
@ -308,7 +308,7 @@ Architecture: all
Installed-Size: 307200 Installed-Size: 307200
Description: Configure OpenWrt for different network modes: Sniffer, Access Point, Relay, Router Description: Configure OpenWrt for different network modes: Sniffer, Access Point, Relay, Router
Filename: luci-app-network-modes_0.5.0-r3_all.ipk Filename: luci-app-network-modes_0.5.0-r3_all.ipk
Size: 55611 Size: 55613
Package: luci-app-network-tweaks Package: luci-app-network-tweaks
Version: 1.0.0-r7 Version: 1.0.0-r7
@ -320,7 +320,7 @@ Architecture: all
Installed-Size: 81920 Installed-Size: 81920
Description: Unified network services dashboard with DNS/hosts sync, CDN cache control, and WPAD auto-proxy configuration 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 Filename: luci-app-network-tweaks_1.0.0-r7_all.ipk
Size: 15460 Size: 15461
Package: luci-app-nextcloud Package: luci-app-nextcloud
Version: 1.0.0-r1 Version: 1.0.0-r1
@ -344,7 +344,7 @@ Architecture: all
Installed-Size: 71680 Installed-Size: 71680
Description: Modern dashboard for Ollama LLM management on OpenWrt Description: Modern dashboard for Ollama LLM management on OpenWrt
Filename: luci-app-ollama_0.1.0-r1_all.ipk Filename: luci-app-ollama_0.1.0-r1_all.ipk
Size: 11998 Size: 11997
Package: luci-app-picobrew Package: luci-app-picobrew
Version: 1.0.0-r1 Version: 1.0.0-r1
@ -356,7 +356,7 @@ Architecture: all
Installed-Size: 51200 Installed-Size: 51200
Description: Modern dashboard for PicoBrew Server management on OpenWrt Description: Modern dashboard for PicoBrew Server management on OpenWrt
Filename: luci-app-picobrew_1.0.0-r1_all.ipk Filename: luci-app-picobrew_1.0.0-r1_all.ipk
Size: 9981 Size: 9975
Package: luci-app-secubox Package: luci-app-secubox
Version: 0.7.1-r4 Version: 0.7.1-r4
@ -368,7 +368,7 @@ Architecture: all
Installed-Size: 266240 Installed-Size: 266240
Description: Central control hub for all SecuBox modules. Provides unified dashboard, module status, system health monitoring, and quick actions. 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 Filename: luci-app-secubox_0.7.1-r4_all.ipk
Size: 49907 Size: 49901
Package: luci-app-secubox-admin Package: luci-app-secubox-admin
Version: 1.0.0-r19 Version: 1.0.0-r19
@ -379,7 +379,7 @@ Architecture: all
Installed-Size: 337920 Installed-Size: 337920
Description: Unified admin control center for SecuBox appstore plugins with system monitoring Description: Unified admin control center for SecuBox appstore plugins with system monitoring
Filename: luci-app-secubox-admin_1.0.0-r19_all.ipk Filename: luci-app-secubox-admin_1.0.0-r19_all.ipk
Size: 57096 Size: 57098
Package: luci-app-secubox-crowdsec Package: luci-app-secubox-crowdsec
Version: 1.0.0-r3 Version: 1.0.0-r3
@ -391,7 +391,7 @@ Architecture: all
Installed-Size: 81920 Installed-Size: 81920
Description: LuCI SecuBox CrowdSec Dashboard Description: LuCI SecuBox CrowdSec Dashboard
Filename: luci-app-secubox-crowdsec_1.0.0-r3_all.ipk Filename: luci-app-secubox-crowdsec_1.0.0-r3_all.ipk
Size: 13918 Size: 13919
Package: luci-app-secubox-netdiag Package: luci-app-secubox-netdiag
Version: 1.0.0-r1 Version: 1.0.0-r1
@ -451,7 +451,7 @@ Architecture: all
Installed-Size: 71680 Installed-Size: 71680
Description: Unified dashboard integrating netifyd DPI threats with CrowdSec intelligence for real-time threat monitoring and automated blocking 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 Filename: luci-app-secubox-security-threats_1.0.0-r4_all.ipk
Size: 13905 Size: 13903
Package: luci-app-service-registry Package: luci-app-service-registry
Version: 1.0.0-r1 Version: 1.0.0-r1
@ -463,19 +463,19 @@ Architecture: all
Installed-Size: 194560 Installed-Size: 194560
Description: Unified service aggregation with HAProxy vhosts, Tor hidden services, and QR-coded landing page 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 Filename: luci-app-service-registry_1.0.0-r1_all.ipk
Size: 39828 Size: 39826
Package: luci-app-streamlit Package: luci-app-streamlit
Version: 1.0.0-r9 Version: 1.0.0-r11
Depends: luci-base, luci-lib-jsonc, rpcd, rpcd-mod-luci, secubox-app-streamlit Depends: luci-base, luci-lib-jsonc, rpcd, rpcd-mod-luci, secubox-app-streamlit
License: Apache-2.0 License: Apache-2.0
Section: luci Section: luci
Maintainer: OpenWrt LuCI community Maintainer: OpenWrt LuCI community
Architecture: all Architecture: all
Installed-Size: 122880 Installed-Size: 81920
Description: Modern dashboard for Streamlit Platform management on OpenWrt Description: Multi-instance Streamlit management with Gitea integration
Filename: luci-app-streamlit_1.0.0-r9_all.ipk Filename: luci-app-streamlit_1.0.0-r11_all.ipk
Size: 20472 Size: 14749
Package: luci-app-system-hub Package: luci-app-system-hub
Version: 0.5.1-r4 Version: 0.5.1-r4
@ -487,7 +487,7 @@ Architecture: all
Installed-Size: 358400 Installed-Size: 358400
Description: Central system control with monitoring, services, logs, and backup Description: Central system control with monitoring, services, logs, and backup
Filename: luci-app-system-hub_0.5.1-r4_all.ipk Filename: luci-app-system-hub_0.5.1-r4_all.ipk
Size: 66351 Size: 66349
Package: luci-app-tor-shield Package: luci-app-tor-shield
Version: 1.0.0-r10 Version: 1.0.0-r10
@ -499,7 +499,7 @@ Architecture: all
Installed-Size: 133120 Installed-Size: 133120
Description: Modern dashboard for Tor anonymization on OpenWrt Description: Modern dashboard for Tor anonymization on OpenWrt
Filename: luci-app-tor-shield_1.0.0-r10_all.ipk Filename: luci-app-tor-shield_1.0.0-r10_all.ipk
Size: 24535 Size: 24537
Package: luci-app-traffic-shaper Package: luci-app-traffic-shaper
Version: 0.4.0-r2 Version: 0.4.0-r2
@ -511,7 +511,7 @@ Architecture: all
Installed-Size: 92160 Installed-Size: 92160
Description: Advanced traffic shaping with TC/CAKE for precise bandwidth control Description: Advanced traffic shaping with TC/CAKE for precise bandwidth control
Filename: luci-app-traffic-shaper_0.4.0-r2_all.ipk Filename: luci-app-traffic-shaper_0.4.0-r2_all.ipk
Size: 15637 Size: 15636
Package: luci-app-vhost-manager Package: luci-app-vhost-manager
Version: 0.5.0-r5 Version: 0.5.0-r5
@ -547,7 +547,7 @@ Architecture: all
Installed-Size: 40960 Installed-Size: 40960
Description: Graphical interface for managing the Zigbee2MQTT docker application. Description: Graphical interface for managing the Zigbee2MQTT docker application.
Filename: luci-app-zigbee2mqtt_1.0.0-r2_all.ipk Filename: luci-app-zigbee2mqtt_1.0.0-r2_all.ipk
Size: 7090 Size: 7087
Package: luci-theme-secubox Package: luci-theme-secubox
Version: 0.4.7-r1 Version: 0.4.7-r1
@ -559,7 +559,7 @@ Architecture: all
Installed-Size: 460800 Installed-Size: 460800
Description: Global CyberMood design system (CSS/JS/i18n) shared by all SecuBox dashboards. Description: Global CyberMood design system (CSS/JS/i18n) shared by all SecuBox dashboards.
Filename: luci-theme-secubox_0.4.7-r1_all.ipk Filename: luci-theme-secubox_0.4.7-r1_all.ipk
Size: 111797 Size: 111796
Package: secubox-app Package: secubox-app
Version: 1.0.0-r2 Version: 1.0.0-r2
@ -570,7 +570,7 @@ Installed-Size: 92160
Description: Command line helper for SecuBox App Store manifests. Installs /usr/sbin/secubox-app Description: Command line helper for SecuBox App Store manifests. Installs /usr/sbin/secubox-app
and ships the default manifests under /usr/share/secubox/plugins/. and ships the default manifests under /usr/share/secubox/plugins/.
Filename: secubox-app_1.0.0-r2_all.ipk Filename: secubox-app_1.0.0-r2_all.ipk
Size: 11186 Size: 11184
Package: secubox-app-adguardhome Package: secubox-app-adguardhome
Version: 1.0.0-r2 Version: 1.0.0-r2
@ -584,7 +584,7 @@ Description: Installer, configuration, and service manager for running AdGuard
inside Docker on SecuBox-powered OpenWrt systems. Network-wide ad blocker inside Docker on SecuBox-powered OpenWrt systems. Network-wide ad blocker
with DNS-over-HTTPS/TLS support and detailed analytics. with DNS-over-HTTPS/TLS support and detailed analytics.
Filename: secubox-app-adguardhome_1.0.0-r2_all.ipk Filename: secubox-app-adguardhome_1.0.0-r2_all.ipk
Size: 2882 Size: 2880
Package: secubox-app-auth-logger Package: secubox-app-auth-logger
Version: 1.2.2-r1 Version: 1.2.2-r1
@ -625,7 +625,7 @@ Description: Custom CrowdSec configurations for SecuBox web interface protectio
- Webapp generic auth bruteforce protection - Webapp generic auth bruteforce protection
- Whitelist for trusted networks - Whitelist for trusted networks
Filename: secubox-app-crowdsec-custom_1.1.0-r1_all.ipk Filename: secubox-app-crowdsec-custom_1.1.0-r1_all.ipk
Size: 5763 Size: 5762
Package: secubox-app-cs-firewall-bouncer Package: secubox-app-cs-firewall-bouncer
Version: 0.0.31-r4 Version: 0.0.31-r4
@ -666,7 +666,7 @@ Description: Cyberpunk-themed RSS feed aggregator for OpenWrt/SecuBox.
Features emoji injection, neon styling, and RSS-Bridge support Features emoji injection, neon styling, and RSS-Bridge support
for social media feeds (Facebook, Twitter, Mastodon). for social media feeds (Facebook, Twitter, Mastodon).
Filename: secubox-app-cyberfeed_0.2.1-r1_all.ipk Filename: secubox-app-cyberfeed_0.2.1-r1_all.ipk
Size: 12454 Size: 12450
Package: secubox-app-domoticz Package: secubox-app-domoticz
Version: 1.0.0-r2 Version: 1.0.0-r2
@ -679,7 +679,7 @@ Installed-Size: 10240
Description: Installer, configuration, and service manager for running Domoticz Description: Installer, configuration, and service manager for running Domoticz
inside Docker on SecuBox-powered OpenWrt systems. inside Docker on SecuBox-powered OpenWrt systems.
Filename: secubox-app-domoticz_1.0.0-r2_all.ipk Filename: secubox-app-domoticz_1.0.0-r2_all.ipk
Size: 2548 Size: 2546
Package: secubox-app-exposure Package: secubox-app-exposure
Version: 1.0.0-r1 Version: 1.0.0-r1
@ -694,7 +694,7 @@ Description: Unified service exposure manager for SecuBox.
- Dynamic Tor hidden service management - Dynamic Tor hidden service management
- HAProxy SSL reverse proxy configuration - HAProxy SSL reverse proxy configuration
Filename: secubox-app-exposure_1.0.0-r1_all.ipk Filename: secubox-app-exposure_1.0.0-r1_all.ipk
Size: 6837 Size: 6829
Package: secubox-app-gitea Package: secubox-app-gitea
Version: 1.0.0-r5 Version: 1.0.0-r5
@ -740,7 +740,7 @@ Description: Glances - Cross-platform system monitoring tool for SecuBox.
Runs in LXC container for isolation and security. Runs in LXC container for isolation and security.
Configure in /etc/config/glances. Configure in /etc/config/glances.
Filename: secubox-app-glances_1.0.0-r1_all.ipk Filename: secubox-app-glances_1.0.0-r1_all.ipk
Size: 5536 Size: 5534
Package: secubox-app-haproxy Package: secubox-app-haproxy
Version: 1.0.0-r23 Version: 1.0.0-r23
@ -784,7 +784,7 @@ Description: Hexo CMS - Self-hosted static blog generator for OpenWrt
Runs in LXC container with Alpine Linux. Runs in LXC container with Alpine Linux.
Configure in /etc/config/hexojs. Configure in /etc/config/hexojs.
Filename: secubox-app-hexojs_1.0.0-r8_all.ipk Filename: secubox-app-hexojs_1.0.0-r8_all.ipk
Size: 94935 Size: 94931
Package: secubox-app-jitsi Package: secubox-app-jitsi
Version: 1.0.0-r1 Version: 1.0.0-r1
@ -809,7 +809,7 @@ Description: Jitsi Meet - Secure, fully featured video conferencing for SecuBox
Integrates with HAProxy for SSL termination. Integrates with HAProxy for SSL termination.
Configure in /etc/config/jitsi. Configure in /etc/config/jitsi.
Filename: secubox-app-jitsi_1.0.0-r1_all.ipk Filename: secubox-app-jitsi_1.0.0-r1_all.ipk
Size: 8918 Size: 8913
Package: secubox-app-localai Package: secubox-app-localai
Version: 2.25.0-r1 Version: 2.25.0-r1
@ -831,7 +831,7 @@ Description: LocalAI native binary package for OpenWrt.
API: http://<router-ip>:8081/v1 API: http://<router-ip>:8081/v1
Filename: secubox-app-localai_2.25.0-r1_all.ipk Filename: secubox-app-localai_2.25.0-r1_all.ipk
Size: 5721 Size: 5727
Package: secubox-app-localai-wb Package: secubox-app-localai-wb
Version: 2.25.0-r1 Version: 2.25.0-r1
@ -855,7 +855,7 @@ Description: LocalAI native binary package for OpenWrt.
API: http://<router-ip>:8080/v1 API: http://<router-ip>:8080/v1
Filename: secubox-app-localai-wb_2.25.0-r1_all.ipk Filename: secubox-app-localai-wb_2.25.0-r1_all.ipk
Size: 7951 Size: 7949
Package: secubox-app-lyrion Package: secubox-app-lyrion
Version: 2.0.2-r1 Version: 2.0.2-r1
@ -875,7 +875,7 @@ Description: Lyrion Media Server (formerly Logitech Media Server / Squeezebox S
Auto-detects available runtime, preferring LXC for lower resource usage. Auto-detects available runtime, preferring LXC for lower resource usage.
Configure runtime in /etc/config/lyrion. Configure runtime in /etc/config/lyrion.
Filename: secubox-app-lyrion_2.0.2-r1_all.ipk Filename: secubox-app-lyrion_2.0.2-r1_all.ipk
Size: 7287 Size: 7278
Package: secubox-app-magicmirror2 Package: secubox-app-magicmirror2
Version: 0.4.0-r8 Version: 0.4.0-r8
@ -897,7 +897,7 @@ Description: MagicMirror² - Open source modular smart mirror platform for Secu
Runs in LXC container for isolation and security. Runs in LXC container for isolation and security.
Configure in /etc/config/magicmirror2. Configure in /etc/config/magicmirror2.
Filename: secubox-app-magicmirror2_0.4.0-r8_all.ipk Filename: secubox-app-magicmirror2_0.4.0-r8_all.ipk
Size: 9253 Size: 9254
Package: secubox-app-mailinabox Package: secubox-app-mailinabox
Version: 2.0.0-r1 Version: 2.0.0-r1
@ -922,7 +922,7 @@ Description: Complete email server solution using docker-mailserver for SecuBox
Commands: mailinaboxctl --help Commands: mailinaboxctl --help
Filename: secubox-app-mailinabox_2.0.0-r1_all.ipk Filename: secubox-app-mailinabox_2.0.0-r1_all.ipk
Size: 7574 Size: 7571
Package: secubox-app-metabolizer Package: secubox-app-metabolizer
Version: 1.0.0-r3 Version: 1.0.0-r3
@ -943,7 +943,7 @@ Description: Metabolizer Blog Pipeline - Integrated CMS with Git-based workflow
Pipeline: Edit in Streamlit -> Push to Gitea -> Build with Hexo -> Publish Pipeline: Edit in Streamlit -> Push to Gitea -> Build with Hexo -> Publish
Filename: secubox-app-metabolizer_1.0.0-r3_all.ipk Filename: secubox-app-metabolizer_1.0.0-r3_all.ipk
Size: 13980 Size: 13978
Package: secubox-app-mitmproxy Package: secubox-app-mitmproxy
Version: 0.5.0-r19 Version: 0.5.0-r19
@ -991,7 +991,7 @@ Description: MMPM (MagicMirror Package Manager) for SecuBox.
Runs inside the MagicMirror2 LXC container. Runs inside the MagicMirror2 LXC container.
Filename: secubox-app-mmpm_0.2.0-r5_all.ipk Filename: secubox-app-mmpm_0.2.0-r5_all.ipk
Size: 3977 Size: 3980
Package: secubox-app-nextcloud Package: secubox-app-nextcloud
Version: 1.0.0-r2 Version: 1.0.0-r2
@ -1005,7 +1005,7 @@ Description: Installer, configuration, and service manager for running Nextclou
inside Docker on SecuBox-powered OpenWrt systems. Self-hosted file inside Docker on SecuBox-powered OpenWrt systems. Self-hosted file
sync and share with calendar, contacts, and collaboration. sync and share with calendar, contacts, and collaboration.
Filename: secubox-app-nextcloud_1.0.0-r2_all.ipk Filename: secubox-app-nextcloud_1.0.0-r2_all.ipk
Size: 2958 Size: 2961
Package: secubox-app-ollama Package: secubox-app-ollama
Version: 0.1.0-r1 Version: 0.1.0-r1
@ -1027,7 +1027,7 @@ Description: Ollama - Simple local LLM runtime for SecuBox-powered OpenWrt syst
Runs in Docker/Podman container. Runs in Docker/Podman container.
Configure in /etc/config/ollama. Configure in /etc/config/ollama.
Filename: secubox-app-ollama_0.1.0-r1_all.ipk Filename: secubox-app-ollama_0.1.0-r1_all.ipk
Size: 5739 Size: 5735
Package: secubox-app-picobrew Package: secubox-app-picobrew
Version: 1.0.0-r7 Version: 1.0.0-r7
@ -1049,7 +1049,7 @@ Description: PicoBrew Server - Self-hosted brewing controller for PicoBrew devi
Runs in LXC container with Python/Flask backend. Runs in LXC container with Python/Flask backend.
Configure in /etc/config/picobrew. Configure in /etc/config/picobrew.
Filename: secubox-app-picobrew_1.0.0-r7_all.ipk Filename: secubox-app-picobrew_1.0.0-r7_all.ipk
Size: 5542 Size: 5539
Package: secubox-app-streamlit Package: secubox-app-streamlit
Version: 1.0.0-r5 Version: 1.0.0-r5
@ -1076,7 +1076,7 @@ Description: Streamlit App Platform - Self-hosted Python data app platform
Configure in /etc/config/streamlit. Configure in /etc/config/streamlit.
Filename: secubox-app-streamlit_1.0.0-r5_all.ipk Filename: secubox-app-streamlit_1.0.0-r5_all.ipk
Size: 11722 Size: 11720
Package: secubox-app-tor Package: secubox-app-tor
Version: 1.0.0-r1 Version: 1.0.0-r1
@ -1099,7 +1099,7 @@ Description: SecuBox Tor Shield - One-click Tor anonymization for OpenWrt
Configure in /etc/config/tor-shield. Configure in /etc/config/tor-shield.
Filename: secubox-app-tor_1.0.0-r1_all.ipk Filename: secubox-app-tor_1.0.0-r1_all.ipk
Size: 7380 Size: 7382
Package: secubox-app-webapp Package: secubox-app-webapp
Version: 1.5.0-r7 Version: 1.5.0-r7
@ -1117,7 +1117,7 @@ Description: SecuBox Control Center Dashboard - A web-based dashboard for monit
- Service management - Service management
- Network interface control - Network interface control
Filename: secubox-app-webapp_1.5.0-r7_all.ipk Filename: secubox-app-webapp_1.5.0-r7_all.ipk
Size: 39170 Size: 39169
Package: secubox-app-zigbee2mqtt Package: secubox-app-zigbee2mqtt
Version: 1.0.0-r3 Version: 1.0.0-r3
@ -1130,7 +1130,7 @@ Installed-Size: 20480
Description: Installer, configuration, and service manager for running Zigbee2MQTT Description: Installer, configuration, and service manager for running Zigbee2MQTT
inside Docker on SecuBox-powered OpenWrt systems. inside Docker on SecuBox-powered OpenWrt systems.
Filename: secubox-app-zigbee2mqtt_1.0.0-r3_all.ipk Filename: secubox-app-zigbee2mqtt_1.0.0-r3_all.ipk
Size: 3546 Size: 3545
Package: secubox-core Package: secubox-core
Version: 0.10.0-r11 Version: 0.10.0-r11
@ -1150,7 +1150,7 @@ Description: SecuBox Core Framework provides the foundational infrastructure fo
- Unified CLI interface - Unified CLI interface
- ubus RPC backend - ubus RPC backend
Filename: secubox-core_0.10.0-r11_all.ipk Filename: secubox-core_0.10.0-r11_all.ipk
Size: 87810 Size: 87809
Package: secubox-p2p Package: secubox-p2p
Version: 0.6.0-r3 Version: 0.6.0-r3
@ -1169,5 +1169,5 @@ Description: SecuBox P2P Hub backend providing peer discovery, mesh networking
and MirrorBox NetMesh Catalog for cross-chain distributed service and MirrorBox NetMesh Catalog for cross-chain distributed service
registry with HAProxy vhost discovery and multi-endpoint access URLs. registry with HAProxy vhost discovery and multi-endpoint access URLs.
Filename: secubox-p2p_0.6.0-r3_all.ipk Filename: secubox-p2p_0.6.0-r3_all.ipk
Size: 42021 Size: 42014

View File

@ -1,12 +1,12 @@
{ {
"feed_url": "/secubox-feed", "feed_url": "/secubox-feed",
"generated": "2026-02-01T07:08:21+01:00", "generated": "2026-02-01T07:26:25+01:00",
"packages": [ "packages": [
{ {
"name": "luci-app-auth-guardian", "name": "luci-app-auth-guardian",
"version": "0.4.0-r3", "version": "0.4.0-r3",
"filename": "luci-app-auth-guardian_0.4.0-r3_all.ipk", "filename": "luci-app-auth-guardian_0.4.0-r3_all.ipk",
"size": 12081, "size": 12078,
"category": "security", "category": "security",
"icon": "key", "icon": "key",
"description": "Authentication management", "description": "Authentication management",
@ -18,7 +18,7 @@
"name": "luci-app-bandwidth-manager", "name": "luci-app-bandwidth-manager",
"version": "0.5.0-r2", "version": "0.5.0-r2",
"filename": "luci-app-bandwidth-manager_0.5.0-r2_all.ipk", "filename": "luci-app-bandwidth-manager_0.5.0-r2_all.ipk",
"size": 66970, "size": 66969,
"category": "network", "category": "network",
"icon": "activity", "icon": "activity",
"description": "Bandwidth monitoring and control", "description": "Bandwidth monitoring and control",
@ -30,7 +30,7 @@
"name": "luci-app-cdn-cache", "name": "luci-app-cdn-cache",
"version": "0.5.0-r3", "version": "0.5.0-r3",
"filename": "luci-app-cdn-cache_0.5.0-r3_all.ipk", "filename": "luci-app-cdn-cache_0.5.0-r3_all.ipk",
"size": 23190, "size": 23192,
"category": "network", "category": "network",
"icon": "globe", "icon": "globe",
"description": "CDN caching", "description": "CDN caching",
@ -42,7 +42,7 @@
"name": "luci-app-client-guardian", "name": "luci-app-client-guardian",
"version": "0.4.0-r7", "version": "0.4.0-r7",
"filename": "luci-app-client-guardian_0.4.0-r7_all.ipk", "filename": "luci-app-client-guardian_0.4.0-r7_all.ipk",
"size": 57045, "size": 57042,
"category": "network", "category": "network",
"icon": "users", "icon": "users",
"description": "Client management and monitoring", "description": "Client management and monitoring",
@ -54,7 +54,7 @@
"name": "luci-app-crowdsec-dashboard", "name": "luci-app-crowdsec-dashboard",
"version": "0.7.0-r29", "version": "0.7.0-r29",
"filename": "luci-app-crowdsec-dashboard_0.7.0-r29_all.ipk", "filename": "luci-app-crowdsec-dashboard_0.7.0-r29_all.ipk",
"size": 55583, "size": 55584,
"category": "security", "category": "security",
"icon": "shield", "icon": "shield",
"description": "CrowdSec security monitoring", "description": "CrowdSec security monitoring",
@ -66,7 +66,7 @@
"name": "luci-app-cyberfeed", "name": "luci-app-cyberfeed",
"version": "0.1.1-r1", "version": "0.1.1-r1",
"filename": "luci-app-cyberfeed_0.1.1-r1_all.ipk", "filename": "luci-app-cyberfeed_0.1.1-r1_all.ipk",
"size": 12838, "size": 12837,
"category": "utility", "category": "utility",
"icon": "package", "icon": "package",
"description": "SecuBox package", "description": "SecuBox package",
@ -78,7 +78,7 @@
"name": "luci-app-exposure", "name": "luci-app-exposure",
"version": "1.0.0-r3", "version": "1.0.0-r3",
"filename": "luci-app-exposure_1.0.0-r3_all.ipk", "filename": "luci-app-exposure_1.0.0-r3_all.ipk",
"size": 20535, "size": 20536,
"category": "utility", "category": "utility",
"icon": "package", "icon": "package",
"description": "SecuBox package", "description": "SecuBox package",
@ -90,7 +90,7 @@
"name": "luci-app-gitea", "name": "luci-app-gitea",
"version": "1.0.0-r2", "version": "1.0.0-r2",
"filename": "luci-app-gitea_1.0.0-r2_all.ipk", "filename": "luci-app-gitea_1.0.0-r2_all.ipk",
"size": 15586, "size": 15587,
"category": "utility", "category": "utility",
"icon": "package", "icon": "package",
"description": "SecuBox package", "description": "SecuBox package",
@ -102,7 +102,7 @@
"name": "luci-app-glances", "name": "luci-app-glances",
"version": "1.0.0-r2", "version": "1.0.0-r2",
"filename": "luci-app-glances_1.0.0-r2_all.ipk", "filename": "luci-app-glances_1.0.0-r2_all.ipk",
"size": 6969, "size": 6966,
"category": "utility", "category": "utility",
"icon": "package", "icon": "package",
"description": "SecuBox package", "description": "SecuBox package",
@ -126,7 +126,7 @@
"name": "luci-app-hexojs", "name": "luci-app-hexojs",
"version": "1.0.0-r3", "version": "1.0.0-r3",
"filename": "luci-app-hexojs_1.0.0-r3_all.ipk", "filename": "luci-app-hexojs_1.0.0-r3_all.ipk",
"size": 32980, "size": 32975,
"category": "utility", "category": "utility",
"icon": "package", "icon": "package",
"description": "SecuBox package", "description": "SecuBox package",
@ -150,7 +150,7 @@
"name": "luci-app-ksm-manager", "name": "luci-app-ksm-manager",
"version": "0.4.0-r2", "version": "0.4.0-r2",
"filename": "luci-app-ksm-manager_0.4.0-r2_all.ipk", "filename": "luci-app-ksm-manager_0.4.0-r2_all.ipk",
"size": 18719, "size": 18723,
"category": "system", "category": "system",
"icon": "cpu", "icon": "cpu",
"description": "Kernel memory management", "description": "Kernel memory management",
@ -162,7 +162,7 @@
"name": "luci-app-localai", "name": "luci-app-localai",
"version": "0.1.0-r15", "version": "0.1.0-r15",
"filename": "luci-app-localai_0.1.0-r15_all.ipk", "filename": "luci-app-localai_0.1.0-r15_all.ipk",
"size": 14361, "size": 14362,
"category": "utility", "category": "utility",
"icon": "package", "icon": "package",
"description": "SecuBox package", "description": "SecuBox package",
@ -174,7 +174,7 @@
"name": "luci-app-lyrion", "name": "luci-app-lyrion",
"version": "1.0.0-r1", "version": "1.0.0-r1",
"filename": "luci-app-lyrion_1.0.0-r1_all.ipk", "filename": "luci-app-lyrion_1.0.0-r1_all.ipk",
"size": 6729, "size": 6725,
"category": "utility", "category": "utility",
"icon": "package", "icon": "package",
"description": "SecuBox package", "description": "SecuBox package",
@ -186,7 +186,7 @@
"name": "luci-app-magicmirror2", "name": "luci-app-magicmirror2",
"version": "0.4.0-r6", "version": "0.4.0-r6",
"filename": "luci-app-magicmirror2_0.4.0-r6_all.ipk", "filename": "luci-app-magicmirror2_0.4.0-r6_all.ipk",
"size": 12279, "size": 12277,
"category": "iot", "category": "iot",
"icon": "monitor", "icon": "monitor",
"description": "Smart mirror display", "description": "Smart mirror display",
@ -198,7 +198,7 @@
"name": "luci-app-mailinabox", "name": "luci-app-mailinabox",
"version": "1.0.0-r1", "version": "1.0.0-r1",
"filename": "luci-app-mailinabox_1.0.0-r1_all.ipk", "filename": "luci-app-mailinabox_1.0.0-r1_all.ipk",
"size": 5482, "size": 5481,
"category": "utility", "category": "utility",
"icon": "package", "icon": "package",
"description": "SecuBox package", "description": "SecuBox package",
@ -222,7 +222,7 @@
"name": "luci-app-metablogizer", "name": "luci-app-metablogizer",
"version": "1.0.0-r3", "version": "1.0.0-r3",
"filename": "luci-app-metablogizer_1.0.0-r3_all.ipk", "filename": "luci-app-metablogizer_1.0.0-r3_all.ipk",
"size": 23506, "size": 23505,
"category": "utility", "category": "utility",
"icon": "package", "icon": "package",
"description": "SecuBox package", "description": "SecuBox package",
@ -234,7 +234,7 @@
"name": "luci-app-metabolizer", "name": "luci-app-metabolizer",
"version": "1.0.0-r2", "version": "1.0.0-r2",
"filename": "luci-app-metabolizer_1.0.0-r2_all.ipk", "filename": "luci-app-metabolizer_1.0.0-r2_all.ipk",
"size": 4758, "size": 4756,
"category": "utility", "category": "utility",
"icon": "package", "icon": "package",
"description": "SecuBox package", "description": "SecuBox package",
@ -258,7 +258,7 @@
"name": "luci-app-mmpm", "name": "luci-app-mmpm",
"version": "0.2.0-r3", "version": "0.2.0-r3",
"filename": "luci-app-mmpm_0.2.0-r3_all.ipk", "filename": "luci-app-mmpm_0.2.0-r3_all.ipk",
"size": 7901, "size": 7900,
"category": "utility", "category": "utility",
"icon": "package", "icon": "package",
"description": "SecuBox package", "description": "SecuBox package",
@ -270,7 +270,7 @@
"name": "luci-app-mqtt-bridge", "name": "luci-app-mqtt-bridge",
"version": "0.4.0-r4", "version": "0.4.0-r4",
"filename": "luci-app-mqtt-bridge_0.4.0-r4_all.ipk", "filename": "luci-app-mqtt-bridge_0.4.0-r4_all.ipk",
"size": 22782, "size": 22774,
"category": "iot", "category": "iot",
"icon": "message-square", "icon": "message-square",
"description": "MQTT bridge", "description": "MQTT bridge",
@ -282,7 +282,7 @@
"name": "luci-app-ndpid", "name": "luci-app-ndpid",
"version": "1.1.2-r2", "version": "1.1.2-r2",
"filename": "luci-app-ndpid_1.1.2-r2_all.ipk", "filename": "luci-app-ndpid_1.1.2-r2_all.ipk",
"size": 22454, "size": 22456,
"category": "security", "category": "security",
"icon": "eye", "icon": "eye",
"description": "Deep packet inspection", "description": "Deep packet inspection",
@ -294,7 +294,7 @@
"name": "luci-app-netdata-dashboard", "name": "luci-app-netdata-dashboard",
"version": "0.5.0-r2", "version": "0.5.0-r2",
"filename": "luci-app-netdata-dashboard_0.5.0-r2_all.ipk", "filename": "luci-app-netdata-dashboard_0.5.0-r2_all.ipk",
"size": 22399, "size": 22401,
"category": "monitoring", "category": "monitoring",
"icon": "bar-chart-2", "icon": "bar-chart-2",
"description": "System monitoring dashboard", "description": "System monitoring dashboard",
@ -306,7 +306,7 @@
"name": "luci-app-network-modes", "name": "luci-app-network-modes",
"version": "0.5.0-r3", "version": "0.5.0-r3",
"filename": "luci-app-network-modes_0.5.0-r3_all.ipk", "filename": "luci-app-network-modes_0.5.0-r3_all.ipk",
"size": 55611, "size": 55613,
"category": "network", "category": "network",
"icon": "wifi", "icon": "wifi",
"description": "Network configuration", "description": "Network configuration",
@ -318,7 +318,7 @@
"name": "luci-app-network-tweaks", "name": "luci-app-network-tweaks",
"version": "1.0.0-r7", "version": "1.0.0-r7",
"filename": "luci-app-network-tweaks_1.0.0-r7_all.ipk", "filename": "luci-app-network-tweaks_1.0.0-r7_all.ipk",
"size": 15460, "size": 15461,
"category": "network", "category": "network",
"icon": "wifi", "icon": "wifi",
"description": "Network configuration", "description": "Network configuration",
@ -342,7 +342,7 @@
"name": "luci-app-ollama", "name": "luci-app-ollama",
"version": "0.1.0-r1", "version": "0.1.0-r1",
"filename": "luci-app-ollama_0.1.0-r1_all.ipk", "filename": "luci-app-ollama_0.1.0-r1_all.ipk",
"size": 11998, "size": 11997,
"category": "utility", "category": "utility",
"icon": "package", "icon": "package",
"description": "SecuBox package", "description": "SecuBox package",
@ -354,7 +354,7 @@
"name": "luci-app-picobrew", "name": "luci-app-picobrew",
"version": "1.0.0-r1", "version": "1.0.0-r1",
"filename": "luci-app-picobrew_1.0.0-r1_all.ipk", "filename": "luci-app-picobrew_1.0.0-r1_all.ipk",
"size": 9981, "size": 9975,
"category": "utility", "category": "utility",
"icon": "package", "icon": "package",
"description": "SecuBox package", "description": "SecuBox package",
@ -366,7 +366,7 @@
"name": "luci-app-secubox", "name": "luci-app-secubox",
"version": "0.7.1-r4", "version": "0.7.1-r4",
"filename": "luci-app-secubox_0.7.1-r4_all.ipk", "filename": "luci-app-secubox_0.7.1-r4_all.ipk",
"size": 49907, "size": 49901,
"category": "system", "category": "system",
"icon": "box", "icon": "box",
"description": "SecuBox system component", "description": "SecuBox system component",
@ -378,7 +378,7 @@
"name": "luci-app-secubox-admin", "name": "luci-app-secubox-admin",
"version": "1.0.0-r19", "version": "1.0.0-r19",
"filename": "luci-app-secubox-admin_1.0.0-r19_all.ipk", "filename": "luci-app-secubox-admin_1.0.0-r19_all.ipk",
"size": 57096, "size": 57098,
"category": "system", "category": "system",
"icon": "box", "icon": "box",
"description": "SecuBox system component", "description": "SecuBox system component",
@ -390,7 +390,7 @@
"name": "luci-app-secubox-crowdsec", "name": "luci-app-secubox-crowdsec",
"version": "1.0.0-r3", "version": "1.0.0-r3",
"filename": "luci-app-secubox-crowdsec_1.0.0-r3_all.ipk", "filename": "luci-app-secubox-crowdsec_1.0.0-r3_all.ipk",
"size": 13918, "size": 13919,
"category": "system", "category": "system",
"icon": "box", "icon": "box",
"description": "SecuBox system component", "description": "SecuBox system component",
@ -450,7 +450,7 @@
"name": "luci-app-secubox-security-threats", "name": "luci-app-secubox-security-threats",
"version": "1.0.0-r4", "version": "1.0.0-r4",
"filename": "luci-app-secubox-security-threats_1.0.0-r4_all.ipk", "filename": "luci-app-secubox-security-threats_1.0.0-r4_all.ipk",
"size": 13905, "size": 13903,
"category": "system", "category": "system",
"icon": "box", "icon": "box",
"description": "SecuBox system component", "description": "SecuBox system component",
@ -462,7 +462,7 @@
"name": "luci-app-service-registry", "name": "luci-app-service-registry",
"version": "1.0.0-r1", "version": "1.0.0-r1",
"filename": "luci-app-service-registry_1.0.0-r1_all.ipk", "filename": "luci-app-service-registry_1.0.0-r1_all.ipk",
"size": 39828, "size": 39826,
"category": "utility", "category": "utility",
"icon": "package", "icon": "package",
"description": "SecuBox package", "description": "SecuBox package",
@ -472,9 +472,9 @@
, ,
{ {
"name": "luci-app-streamlit", "name": "luci-app-streamlit",
"version": "1.0.0-r9", "version": "1.0.0-r11",
"filename": "luci-app-streamlit_1.0.0-r9_all.ipk", "filename": "luci-app-streamlit_1.0.0-r11_all.ipk",
"size": 20472, "size": 14749,
"category": "utility", "category": "utility",
"icon": "package", "icon": "package",
"description": "SecuBox package", "description": "SecuBox package",
@ -486,7 +486,7 @@
"name": "luci-app-system-hub", "name": "luci-app-system-hub",
"version": "0.5.1-r4", "version": "0.5.1-r4",
"filename": "luci-app-system-hub_0.5.1-r4_all.ipk", "filename": "luci-app-system-hub_0.5.1-r4_all.ipk",
"size": 66351, "size": 66349,
"category": "system", "category": "system",
"icon": "settings", "icon": "settings",
"description": "System management", "description": "System management",
@ -498,7 +498,7 @@
"name": "luci-app-tor-shield", "name": "luci-app-tor-shield",
"version": "1.0.0-r10", "version": "1.0.0-r10",
"filename": "luci-app-tor-shield_1.0.0-r10_all.ipk", "filename": "luci-app-tor-shield_1.0.0-r10_all.ipk",
"size": 24535, "size": 24537,
"category": "utility", "category": "utility",
"icon": "package", "icon": "package",
"description": "SecuBox package", "description": "SecuBox package",
@ -510,7 +510,7 @@
"name": "luci-app-traffic-shaper", "name": "luci-app-traffic-shaper",
"version": "0.4.0-r2", "version": "0.4.0-r2",
"filename": "luci-app-traffic-shaper_0.4.0-r2_all.ipk", "filename": "luci-app-traffic-shaper_0.4.0-r2_all.ipk",
"size": 15637, "size": 15636,
"category": "network", "category": "network",
"icon": "filter", "icon": "filter",
"description": "Traffic shaping and QoS", "description": "Traffic shaping and QoS",
@ -546,7 +546,7 @@
"name": "luci-app-zigbee2mqtt", "name": "luci-app-zigbee2mqtt",
"version": "1.0.0-r2", "version": "1.0.0-r2",
"filename": "luci-app-zigbee2mqtt_1.0.0-r2_all.ipk", "filename": "luci-app-zigbee2mqtt_1.0.0-r2_all.ipk",
"size": 7090, "size": 7087,
"category": "iot", "category": "iot",
"icon": "radio", "icon": "radio",
"description": "Zigbee device management", "description": "Zigbee device management",
@ -558,7 +558,7 @@
"name": "luci-theme-secubox", "name": "luci-theme-secubox",
"version": "0.4.7-r1", "version": "0.4.7-r1",
"filename": "luci-theme-secubox_0.4.7-r1_all.ipk", "filename": "luci-theme-secubox_0.4.7-r1_all.ipk",
"size": 111797, "size": 111796,
"category": "theme", "category": "theme",
"icon": "palette", "icon": "palette",
"description": "LuCI theme", "description": "LuCI theme",
@ -570,7 +570,7 @@
"name": "secubox-app", "name": "secubox-app",
"version": "1.0.0-r2", "version": "1.0.0-r2",
"filename": "secubox-app_1.0.0-r2_all.ipk", "filename": "secubox-app_1.0.0-r2_all.ipk",
"size": 11186, "size": 11184,
"category": "utility", "category": "utility",
"icon": "package", "icon": "package",
"description": "SecuBox package", "description": "SecuBox package",
@ -582,7 +582,7 @@
"name": "secubox-app-adguardhome", "name": "secubox-app-adguardhome",
"version": "1.0.0-r2", "version": "1.0.0-r2",
"filename": "secubox-app-adguardhome_1.0.0-r2_all.ipk", "filename": "secubox-app-adguardhome_1.0.0-r2_all.ipk",
"size": 2882, "size": 2880,
"category": "secubox", "category": "secubox",
"icon": "package", "icon": "package",
"description": "SecuBox backend service", "description": "SecuBox backend service",
@ -606,7 +606,7 @@
"name": "secubox-app-crowdsec-custom", "name": "secubox-app-crowdsec-custom",
"version": "1.1.0-r1", "version": "1.1.0-r1",
"filename": "secubox-app-crowdsec-custom_1.1.0-r1_all.ipk", "filename": "secubox-app-crowdsec-custom_1.1.0-r1_all.ipk",
"size": 5763, "size": 5762,
"category": "secubox", "category": "secubox",
"icon": "package", "icon": "package",
"description": "SecuBox backend service", "description": "SecuBox backend service",
@ -630,7 +630,7 @@
"name": "secubox-app-cyberfeed", "name": "secubox-app-cyberfeed",
"version": "0.2.1-r1", "version": "0.2.1-r1",
"filename": "secubox-app-cyberfeed_0.2.1-r1_all.ipk", "filename": "secubox-app-cyberfeed_0.2.1-r1_all.ipk",
"size": 12454, "size": 12450,
"category": "secubox", "category": "secubox",
"icon": "package", "icon": "package",
"description": "SecuBox backend service", "description": "SecuBox backend service",
@ -642,7 +642,7 @@
"name": "secubox-app-domoticz", "name": "secubox-app-domoticz",
"version": "1.0.0-r2", "version": "1.0.0-r2",
"filename": "secubox-app-domoticz_1.0.0-r2_all.ipk", "filename": "secubox-app-domoticz_1.0.0-r2_all.ipk",
"size": 2548, "size": 2546,
"category": "secubox", "category": "secubox",
"icon": "package", "icon": "package",
"description": "SecuBox backend service", "description": "SecuBox backend service",
@ -654,7 +654,7 @@
"name": "secubox-app-exposure", "name": "secubox-app-exposure",
"version": "1.0.0-r1", "version": "1.0.0-r1",
"filename": "secubox-app-exposure_1.0.0-r1_all.ipk", "filename": "secubox-app-exposure_1.0.0-r1_all.ipk",
"size": 6837, "size": 6829,
"category": "secubox", "category": "secubox",
"icon": "package", "icon": "package",
"description": "SecuBox backend service", "description": "SecuBox backend service",
@ -678,7 +678,7 @@
"name": "secubox-app-glances", "name": "secubox-app-glances",
"version": "1.0.0-r1", "version": "1.0.0-r1",
"filename": "secubox-app-glances_1.0.0-r1_all.ipk", "filename": "secubox-app-glances_1.0.0-r1_all.ipk",
"size": 5536, "size": 5534,
"category": "secubox", "category": "secubox",
"icon": "package", "icon": "package",
"description": "SecuBox backend service", "description": "SecuBox backend service",
@ -702,7 +702,7 @@
"name": "secubox-app-hexojs", "name": "secubox-app-hexojs",
"version": "1.0.0-r8", "version": "1.0.0-r8",
"filename": "secubox-app-hexojs_1.0.0-r8_all.ipk", "filename": "secubox-app-hexojs_1.0.0-r8_all.ipk",
"size": 94935, "size": 94931,
"category": "secubox", "category": "secubox",
"icon": "package", "icon": "package",
"description": "SecuBox backend service", "description": "SecuBox backend service",
@ -714,7 +714,7 @@
"name": "secubox-app-jitsi", "name": "secubox-app-jitsi",
"version": "1.0.0-r1", "version": "1.0.0-r1",
"filename": "secubox-app-jitsi_1.0.0-r1_all.ipk", "filename": "secubox-app-jitsi_1.0.0-r1_all.ipk",
"size": 8918, "size": 8913,
"category": "secubox", "category": "secubox",
"icon": "package", "icon": "package",
"description": "SecuBox backend service", "description": "SecuBox backend service",
@ -726,7 +726,7 @@
"name": "secubox-app-localai", "name": "secubox-app-localai",
"version": "2.25.0-r1", "version": "2.25.0-r1",
"filename": "secubox-app-localai_2.25.0-r1_all.ipk", "filename": "secubox-app-localai_2.25.0-r1_all.ipk",
"size": 5721, "size": 5727,
"category": "secubox", "category": "secubox",
"icon": "package", "icon": "package",
"description": "SecuBox backend service", "description": "SecuBox backend service",
@ -738,7 +738,7 @@
"name": "secubox-app-localai-wb", "name": "secubox-app-localai-wb",
"version": "2.25.0-r1", "version": "2.25.0-r1",
"filename": "secubox-app-localai-wb_2.25.0-r1_all.ipk", "filename": "secubox-app-localai-wb_2.25.0-r1_all.ipk",
"size": 7951, "size": 7949,
"category": "secubox", "category": "secubox",
"icon": "package", "icon": "package",
"description": "SecuBox backend service", "description": "SecuBox backend service",
@ -750,7 +750,7 @@
"name": "secubox-app-lyrion", "name": "secubox-app-lyrion",
"version": "2.0.2-r1", "version": "2.0.2-r1",
"filename": "secubox-app-lyrion_2.0.2-r1_all.ipk", "filename": "secubox-app-lyrion_2.0.2-r1_all.ipk",
"size": 7287, "size": 7278,
"category": "secubox", "category": "secubox",
"icon": "package", "icon": "package",
"description": "SecuBox backend service", "description": "SecuBox backend service",
@ -762,7 +762,7 @@
"name": "secubox-app-magicmirror2", "name": "secubox-app-magicmirror2",
"version": "0.4.0-r8", "version": "0.4.0-r8",
"filename": "secubox-app-magicmirror2_0.4.0-r8_all.ipk", "filename": "secubox-app-magicmirror2_0.4.0-r8_all.ipk",
"size": 9253, "size": 9254,
"category": "secubox", "category": "secubox",
"icon": "package", "icon": "package",
"description": "SecuBox backend service", "description": "SecuBox backend service",
@ -774,7 +774,7 @@
"name": "secubox-app-mailinabox", "name": "secubox-app-mailinabox",
"version": "2.0.0-r1", "version": "2.0.0-r1",
"filename": "secubox-app-mailinabox_2.0.0-r1_all.ipk", "filename": "secubox-app-mailinabox_2.0.0-r1_all.ipk",
"size": 7574, "size": 7571,
"category": "secubox", "category": "secubox",
"icon": "package", "icon": "package",
"description": "SecuBox backend service", "description": "SecuBox backend service",
@ -786,7 +786,7 @@
"name": "secubox-app-metabolizer", "name": "secubox-app-metabolizer",
"version": "1.0.0-r3", "version": "1.0.0-r3",
"filename": "secubox-app-metabolizer_1.0.0-r3_all.ipk", "filename": "secubox-app-metabolizer_1.0.0-r3_all.ipk",
"size": 13980, "size": 13978,
"category": "secubox", "category": "secubox",
"icon": "package", "icon": "package",
"description": "SecuBox backend service", "description": "SecuBox backend service",
@ -810,7 +810,7 @@
"name": "secubox-app-mmpm", "name": "secubox-app-mmpm",
"version": "0.2.0-r5", "version": "0.2.0-r5",
"filename": "secubox-app-mmpm_0.2.0-r5_all.ipk", "filename": "secubox-app-mmpm_0.2.0-r5_all.ipk",
"size": 3977, "size": 3980,
"category": "secubox", "category": "secubox",
"icon": "package", "icon": "package",
"description": "SecuBox backend service", "description": "SecuBox backend service",
@ -822,7 +822,7 @@
"name": "secubox-app-nextcloud", "name": "secubox-app-nextcloud",
"version": "1.0.0-r2", "version": "1.0.0-r2",
"filename": "secubox-app-nextcloud_1.0.0-r2_all.ipk", "filename": "secubox-app-nextcloud_1.0.0-r2_all.ipk",
"size": 2958, "size": 2961,
"category": "secubox", "category": "secubox",
"icon": "package", "icon": "package",
"description": "SecuBox backend service", "description": "SecuBox backend service",
@ -834,7 +834,7 @@
"name": "secubox-app-ollama", "name": "secubox-app-ollama",
"version": "0.1.0-r1", "version": "0.1.0-r1",
"filename": "secubox-app-ollama_0.1.0-r1_all.ipk", "filename": "secubox-app-ollama_0.1.0-r1_all.ipk",
"size": 5739, "size": 5735,
"category": "secubox", "category": "secubox",
"icon": "package", "icon": "package",
"description": "SecuBox backend service", "description": "SecuBox backend service",
@ -846,7 +846,7 @@
"name": "secubox-app-picobrew", "name": "secubox-app-picobrew",
"version": "1.0.0-r7", "version": "1.0.0-r7",
"filename": "secubox-app-picobrew_1.0.0-r7_all.ipk", "filename": "secubox-app-picobrew_1.0.0-r7_all.ipk",
"size": 5542, "size": 5539,
"category": "secubox", "category": "secubox",
"icon": "package", "icon": "package",
"description": "SecuBox backend service", "description": "SecuBox backend service",
@ -858,7 +858,7 @@
"name": "secubox-app-streamlit", "name": "secubox-app-streamlit",
"version": "1.0.0-r5", "version": "1.0.0-r5",
"filename": "secubox-app-streamlit_1.0.0-r5_all.ipk", "filename": "secubox-app-streamlit_1.0.0-r5_all.ipk",
"size": 11722, "size": 11720,
"category": "secubox", "category": "secubox",
"icon": "package", "icon": "package",
"description": "SecuBox backend service", "description": "SecuBox backend service",
@ -870,7 +870,7 @@
"name": "secubox-app-tor", "name": "secubox-app-tor",
"version": "1.0.0-r1", "version": "1.0.0-r1",
"filename": "secubox-app-tor_1.0.0-r1_all.ipk", "filename": "secubox-app-tor_1.0.0-r1_all.ipk",
"size": 7380, "size": 7382,
"category": "secubox", "category": "secubox",
"icon": "package", "icon": "package",
"description": "SecuBox backend service", "description": "SecuBox backend service",
@ -882,7 +882,7 @@
"name": "secubox-app-webapp", "name": "secubox-app-webapp",
"version": "1.5.0-r7", "version": "1.5.0-r7",
"filename": "secubox-app-webapp_1.5.0-r7_all.ipk", "filename": "secubox-app-webapp_1.5.0-r7_all.ipk",
"size": 39170, "size": 39169,
"category": "secubox", "category": "secubox",
"icon": "package", "icon": "package",
"description": "SecuBox backend service", "description": "SecuBox backend service",
@ -894,7 +894,7 @@
"name": "secubox-app-zigbee2mqtt", "name": "secubox-app-zigbee2mqtt",
"version": "1.0.0-r3", "version": "1.0.0-r3",
"filename": "secubox-app-zigbee2mqtt_1.0.0-r3_all.ipk", "filename": "secubox-app-zigbee2mqtt_1.0.0-r3_all.ipk",
"size": 3546, "size": 3545,
"category": "secubox", "category": "secubox",
"icon": "package", "icon": "package",
"description": "SecuBox backend service", "description": "SecuBox backend service",
@ -906,7 +906,7 @@
"name": "secubox-core", "name": "secubox-core",
"version": "0.10.0-r11", "version": "0.10.0-r11",
"filename": "secubox-core_0.10.0-r11_all.ipk", "filename": "secubox-core_0.10.0-r11_all.ipk",
"size": 87810, "size": 87809,
"category": "system", "category": "system",
"icon": "box", "icon": "box",
"description": "SecuBox core components", "description": "SecuBox core components",
@ -918,7 +918,7 @@
"name": "secubox-p2p", "name": "secubox-p2p",
"version": "0.6.0-r3", "version": "0.6.0-r3",
"filename": "secubox-p2p_0.6.0-r3_all.ipk", "filename": "secubox-p2p_0.6.0-r3_all.ipk",
"size": 42021, "size": 42014,
"category": "utility", "category": "utility",
"icon": "package", "icon": "package",
"description": "SecuBox package", "description": "SecuBox package",