feat(jellyfin): Add secubox-app-jellyfin and luci-app-jellyfin packages
Docker-based Jellyfin media server with UCI config (port, image, media paths, GPU transcoding), procd init, jellyfinctl CLI, and LuCI frontend with status/config/logs view. Also adds Punk Exposure Engine architectural README documenting the Peek/Poke/Emancipate service exposure model and DNS provider API roadmap. CLAUDE.md updated with architectural directive. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
c6de8b2b1b
commit
297917e79a
@ -266,7 +266,8 @@
|
||||
"Bash(gdbus call:*)",
|
||||
"Bash(git mv:*)",
|
||||
"Bash(DISPLAY=:1 scrot:*)",
|
||||
"Bash(node -c:*)"
|
||||
"Bash(node -c:*)",
|
||||
"Bash(/home/reepost/CyberMindStudio/secubox-openwrt/secubox-tools/local-build.sh:*)"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
41
CLAUDE.md
41
CLAUDE.md
@ -169,3 +169,44 @@ ssh root@192.168.255.1 '/etc/init.d/rpcd restart'
|
||||
- **RPC params order matters**: The `params` array in `rpc.declare()` must match the positional arguments in `addPeer(arg1, arg2, ...)` calls — adding a new param means updating ALL callers
|
||||
- **sessionStorage is volatile**: Data stored in `sessionStorage` is lost on tab close/refresh — don't rely on it for persistent data; use UCI backend storage instead
|
||||
- **Interface name conflicts**: When creating WireGuard interfaces, always check for existing names (wg0, wg1, etc.) and auto-increment to the next available name
|
||||
|
||||
## Punk Exposure Engine — Architectural Directive
|
||||
|
||||
The SecuBox service exposure architecture follows a three-verb model called **Peek / Poke / Emancipate**. All new service components, exposure features, and mesh integrations must align with this model.
|
||||
|
||||
### Core Concepts
|
||||
|
||||
- **Peek**: Discover and scan. Any feature that detects services, lists DNS records, shows mesh peers, or aggregates visibility across nodes.
|
||||
- **Poke**: Target and configure. Any feature that selects a service and configures an exposure channel (Tor, DNS/SSL, mesh publish).
|
||||
- **Emancipate**: Activate the linking flow. Any feature that atomically makes a service reachable through one or more channels.
|
||||
|
||||
### Three Exposure Channels
|
||||
|
||||
1. **Tor** — `.onion` hidden services via `secubox-app-tor` + `secubox-exposure tor add`
|
||||
2. **DNS/SSL** — Classical HTTPS via HAProxy + ACME + DNS provider API (OVH, Gandi, Cloudflare) via `secubox-app-dns-provider` + `dnsctl`
|
||||
3. **Mesh** — P2P service registry via `secubox-p2p publish` + gossip chain sync
|
||||
|
||||
### Key Architectural Rules
|
||||
|
||||
- **Match services by port, not name** — when cross-referencing scan results with Tor/SSL/vhost/mesh entries, always use the backend port number as the join key
|
||||
- **DNS provider API integration** — use `dnsctl` (from `secubox-app-dns-provider`) for programmatic DNS record management; support DNS-01 ACME challenges as alternative to HTTP-01 webroot
|
||||
- **Emancipate is multi-channel** — exposing a service should support activating Tor + DNS + Mesh in a single flow; each channel is independently togglable
|
||||
- **Every station is generative** — each SecuBox node can discover local services, create new exposure endpoints, and propagate them to mesh peers
|
||||
- **Guard against local-only exposure** — never auto-expose services bound to 127.0.0.1; only services on 0.0.0.0 or specific LAN IPs are eligible for external exposure
|
||||
|
||||
### Reference Document
|
||||
|
||||
Full architectural spec: `package/secubox/PUNK-EXPOSURE.md`
|
||||
|
||||
### Affected Packages
|
||||
|
||||
| Package | Role in Punk Exposure |
|
||||
|---------|----------------------|
|
||||
| `secubox-app-exposure` | Peek scanner + Tor/SSL orchestrator |
|
||||
| `luci-app-exposure` | Dashboard: Peek table + Poke toggles |
|
||||
| `secubox-app-tor` | Tor channel backend |
|
||||
| `secubox-app-haproxy` | SSL/ACME channel backend |
|
||||
| `secubox-app-dns-provider` | DNS provider API (to build) |
|
||||
| `secubox-p2p` | Mesh channel + gossip sync |
|
||||
| `secubox-master-link` | Node onboarding + trust hierarchy |
|
||||
| `luci-app-service-registry` | Aggregated service catalog + health checks |
|
||||
|
||||
243
package/secubox/PUNK-EXPOSURE.md
Normal file
243
package/secubox/PUNK-EXPOSURE.md
Normal file
@ -0,0 +1,243 @@
|
||||
# Punk Exposure Engine
|
||||
|
||||
## Vision
|
||||
|
||||
Every SecuBox node is a **generative station** — it discovers what runs locally, and offers a unified flow to make any service reachable through all available channels: Tor .onion, classical DNS/HTTPS, P2P mesh, or all three at once.
|
||||
|
||||
Three verbs define the workflow:
|
||||
|
||||
- **Peek** — Scan, discover, look around. What's running? What's exposed? What domains are mapped? What peers are online?
|
||||
- **Poke** — Target a service. Pick the exposure channels. Configure the linking flow.
|
||||
- **Emancipate** — Activate. The service becomes reachable. DNS records are created, certificates are issued, .onion addresses are generated, mesh peers are notified.
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
EMANCIPATE
|
||||
|
|
||||
+----------------+----------------+
|
||||
| | |
|
||||
Tor Layer DNS/SSL Layer Mesh Layer
|
||||
(.onion) (HTTPS+ACME) (P2P peers)
|
||||
| | |
|
||||
tor-shield haproxyctl secubox-p2p
|
||||
hidden svc + dns-provider-api + gossip sync
|
||||
+ acme.sh
|
||||
|
|
||||
DNS Provider APIs
|
||||
(OVH, Gandi, Cloudflare)
|
||||
|
|
||||
A/AAAA/CNAME records
|
||||
created programmatically
|
||||
```
|
||||
|
||||
## Components
|
||||
|
||||
### Existing (already built)
|
||||
|
||||
| Component | Package | What it does |
|
||||
|-----------|---------|--------------|
|
||||
| Service scanner | `secubox-app-exposure` | `netstat` scan enriched with UCI/Docker/process names |
|
||||
| Tor exposure | `secubox-app-tor` + `secubox-app-exposure` | `tor_add()` creates hidden service dir + torrc entry |
|
||||
| SSL/HAProxy exposure | `secubox-app-haproxy` + `secubox-app-exposure` | `ssl_add()` creates HAProxy backend + vhost + ACME cert |
|
||||
| ACME certificates | `secubox-app-haproxy` | `acme.sh` with HTTP-01 webroot validation via port 8402 |
|
||||
| VHost manager | `luci-app-vhost-manager` | Nginx-based vhost CRUD with ACME + templates |
|
||||
| P2P mesh | `secubox-p2p` | mDNS discovery, WireGuard mesh, service registry, gossip chain |
|
||||
| Master-Link | `secubox-master-link` | Hierarchical node onboarding with HMAC tokens + blockchain audit |
|
||||
| Service registry | `luci-app-service-registry` | Aggregates services across mesh, health checks, landing page |
|
||||
| Exposure dashboard | `luci-app-exposure` | Single-table KISS view: scan + Tor/SSL toggles per service |
|
||||
|
||||
### Missing (to build)
|
||||
|
||||
| Component | Purpose | Priority |
|
||||
|-----------|---------|----------|
|
||||
| **DNS provider API** | Programmatic DNS record management (OVH, Gandi, Cloudflare) | **High** |
|
||||
| **DNS-01 ACME** | Wildcard certs + domains without port 80 access | **High** |
|
||||
| **Unified Poke flow** | Single action to expose service on all channels | Medium |
|
||||
| **Peek aggregation** | Combined view: local scan + mesh peers + DNS records + Tor | Medium |
|
||||
| **Emancipate orchestrator** | Atomic multi-channel activation with rollback | Medium |
|
||||
|
||||
## DNS Provider API Integration
|
||||
|
||||
### Design
|
||||
|
||||
New package: `secubox-app-dns-provider`
|
||||
|
||||
```
|
||||
package/secubox/secubox-app-dns-provider/
|
||||
files/etc/config/dns-provider # UCI: provider type, API keys, zone
|
||||
files/etc/init.d/dns-provider # (optional) cron for record sync
|
||||
files/usr/sbin/dnsctl # CLI: record add/rm/list/sync
|
||||
files/usr/lib/secubox/dns/ # Provider adapters
|
||||
ovh.sh # OVH API (app key + secret + consumer key)
|
||||
gandi.sh # Gandi LiveDNS (API key)
|
||||
cloudflare.sh # Cloudflare (API token + zone ID)
|
||||
```
|
||||
|
||||
### UCI config
|
||||
|
||||
```uci
|
||||
config dns_provider 'main'
|
||||
option enabled '1'
|
||||
option provider 'ovh' # ovh | gandi | cloudflare
|
||||
option zone 'example.com' # managed DNS zone
|
||||
|
||||
config ovh 'ovh'
|
||||
option endpoint 'ovh-eu' # ovh-eu | ovh-ca | ovh-us
|
||||
option app_key ''
|
||||
option app_secret ''
|
||||
option consumer_key ''
|
||||
|
||||
config gandi 'gandi'
|
||||
option api_key ''
|
||||
|
||||
config cloudflare 'cloudflare'
|
||||
option api_token ''
|
||||
option zone_id ''
|
||||
```
|
||||
|
||||
### dnsctl commands
|
||||
|
||||
```
|
||||
dnsctl list # List all DNS records in zone
|
||||
dnsctl add A myservice 1.2.3.4 # Create A record
|
||||
dnsctl add CNAME blog mycdn.net # Create CNAME
|
||||
dnsctl rm A myservice # Remove record
|
||||
dnsctl sync # Sync local vhosts to DNS records
|
||||
dnsctl verify myservice.example.com # Check DNS propagation
|
||||
```
|
||||
|
||||
### acme.sh DNS-01 integration
|
||||
|
||||
Once `dnsctl` works, enable DNS-01 challenges in `haproxyctl cert add`:
|
||||
|
||||
```sh
|
||||
# Current (HTTP-01 only):
|
||||
acme.sh --issue -d "$domain" --webroot /var/www/acme-challenge
|
||||
|
||||
# New (DNS-01 via provider):
|
||||
provider=$(uci -q get dns-provider.main.provider)
|
||||
case "$provider" in
|
||||
ovh)
|
||||
export OVH_END_POINT=$(uci -q get dns-provider.ovh.endpoint)
|
||||
export OVH_APPLICATION_KEY=$(uci -q get dns-provider.ovh.app_key)
|
||||
export OVH_APPLICATION_SECRET=$(uci -q get dns-provider.ovh.app_secret)
|
||||
export OVH_CONSUMER_KEY=$(uci -q get dns-provider.ovh.consumer_key)
|
||||
acme.sh --issue -d "$domain" --dns dns_ovh
|
||||
;;
|
||||
gandi)
|
||||
export GANDI_LIVEDNS_KEY=$(uci -q get dns-provider.gandi.api_key)
|
||||
acme.sh --issue -d "$domain" --dns dns_gandi_livedns
|
||||
;;
|
||||
cloudflare)
|
||||
export CF_Token=$(uci -q get dns-provider.cloudflare.api_token)
|
||||
export CF_Zone_ID=$(uci -q get dns-provider.cloudflare.zone_id)
|
||||
acme.sh --issue -d "$domain" --dns dns_cf
|
||||
;;
|
||||
esac
|
||||
```
|
||||
|
||||
This unlocks **wildcard certificates** (`*.example.com`) and domains behind firewalls without port 80.
|
||||
|
||||
## The Emancipate Flow
|
||||
|
||||
When a user pokes a service and chooses "Emancipate", the orchestrator runs all selected channels atomically:
|
||||
|
||||
```
|
||||
User selects: Gitea (port 3001) → Emancipate [Tor + DNS + Mesh]
|
||||
|
||||
1. Tor channel:
|
||||
secubox-exposure tor add gitea 3001 80
|
||||
→ .onion address generated
|
||||
|
||||
2. DNS channel:
|
||||
dnsctl add A gitea <public-ip>
|
||||
haproxyctl vhost add gitea.example.com 3001
|
||||
haproxyctl cert add gitea.example.com --dns
|
||||
→ HTTPS live at gitea.example.com
|
||||
|
||||
3. Mesh channel:
|
||||
secubox-p2p publish gitea 3001 "Gitea"
|
||||
gossip_sync
|
||||
→ All mesh peers discover the service
|
||||
|
||||
4. Registry update:
|
||||
Service registry refreshed
|
||||
Landing page regenerated
|
||||
Exposure dashboard shows all three badges
|
||||
```
|
||||
|
||||
### Rollback on failure
|
||||
|
||||
If any channel fails, previously completed channels are not torn down — they remain active. The failure is reported, and the user can retry or remove individual channels via the Exposure dashboard toggles.
|
||||
|
||||
## Peek: What Exists Today
|
||||
|
||||
The current Exposure dashboard (`luci-app-exposure/services.js`) already implements Peek:
|
||||
|
||||
- Scans all listening ports via `netstat -tlnp`
|
||||
- Enriches with real names from uhttpd, streamlit, Docker, glances configs
|
||||
- Cross-references Tor hidden services by backend port
|
||||
- Cross-references HAProxy vhosts by backend port
|
||||
- Shows toggle switches for Tor and SSL per service
|
||||
|
||||
### What Peek needs next
|
||||
|
||||
- **DNS records column**: Show which services have DNS A/CNAME records via `dnsctl list`
|
||||
- **Mesh visibility column**: Show which services are published to mesh peers
|
||||
- **Multi-node view**: Aggregate services across all mesh peers (already available via `secubox-p2p get_shared_services`)
|
||||
|
||||
## Poke: What Exists Today
|
||||
|
||||
The toggle switches in the Exposure dashboard are already "Poke" actions:
|
||||
|
||||
- Toggle Tor ON → modal → service name + onion port → Enable
|
||||
- Toggle SSL ON → modal → service name + domain → Enable
|
||||
|
||||
### What Poke needs next
|
||||
|
||||
- **DNS toggle**: Third toggle column for DNS record management
|
||||
- **Emancipate button**: "Expose everywhere" single action per service
|
||||
- **Provider selection**: Choose which DNS zone/provider for the domain
|
||||
|
||||
## Integration Points with Existing Packages
|
||||
|
||||
| Package | Integration | Direction |
|
||||
|---------|------------|-----------|
|
||||
| `secubox-app-exposure` | Peek scan + Tor/SSL add/remove | Already working |
|
||||
| `secubox-app-haproxy` | HAProxy vhost + ACME cert | Already working |
|
||||
| `secubox-app-tor` | Hidden service lifecycle | Already working |
|
||||
| `secubox-p2p` | Service publish + gossip sync | Add `publish` RPC call |
|
||||
| `luci-app-exposure` | Dashboard: add DNS column + Emancipate button | Frontend extension |
|
||||
| `secubox-app-dns-provider` | **NEW**: DNS record CRUD via provider APIs | To build |
|
||||
| `luci-app-dns-provider` | **NEW**: LuCI config for provider credentials | To build |
|
||||
|
||||
## Implementation Order
|
||||
|
||||
1. **`secubox-app-dns-provider`** — CLI tool + UCI config + provider adapters (OVH first)
|
||||
2. **DNS-01 in haproxyctl** — Wire `dnsctl` into ACME flow as alternative to HTTP-01
|
||||
3. **`luci-app-dns-provider`** — LuCI frontend for provider configuration
|
||||
4. **Exposure dashboard DNS column** — Add DNS toggle + `dnsctl` integration
|
||||
5. **Emancipate flow** — Unified orchestrator in `secubox-exposure emancipate`
|
||||
6. **Mesh publish integration** — Wire `secubox-p2p publish` into Emancipate
|
||||
|
||||
## Naming Convention
|
||||
|
||||
The project uses punk/DIY metaphors:
|
||||
|
||||
| Term | Meaning | Technical equivalent |
|
||||
|------|---------|---------------------|
|
||||
| **Peek** | Discover, scan, observe | `secubox-exposure scan` + service registry |
|
||||
| **Poke** | Target, configure, aim | Toggle switches + modal config |
|
||||
| **Emancipate** | Activate, make free, expose | Multi-channel atomic activation |
|
||||
| **Station** | A SecuBox node | One OpenWrt device running the mesh |
|
||||
| **Generative** | Each station can create new endpoints | Docker apps + exposure channels |
|
||||
|
||||
## Security Considerations
|
||||
|
||||
- DNS provider API keys stored in UCI with restricted ACL
|
||||
- ACME private keys in `/etc/acme/` with 600 permissions
|
||||
- Tor hidden service keys in `/var/lib/tor/` owned by tor:tor
|
||||
- Emancipate flow never exposes 127.0.0.1-only services (guard in scan)
|
||||
- DNS records only created for services the user explicitly Pokes
|
||||
- Rollback does NOT auto-delete — user must explicitly remove exposure
|
||||
29
package/secubox/luci-app-jellyfin/Makefile
Normal file
29
package/secubox/luci-app-jellyfin/Makefile
Normal file
@ -0,0 +1,29 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
LUCI_TITLE:=LuCI Jellyfin Media Server Configuration
|
||||
LUCI_DEPENDS:=+secubox-app-jellyfin
|
||||
LUCI_PKGARCH:=all
|
||||
|
||||
PKG_NAME:=luci-app-jellyfin
|
||||
PKG_VERSION:=1.0.0
|
||||
PKG_RELEASE:=1
|
||||
PKG_MAINTAINER:=CyberMind Studio <contact@cybermind.fr>
|
||||
PKG_LICENSE:=Apache-2.0
|
||||
|
||||
include $(TOPDIR)/feeds/luci/luci.mk
|
||||
|
||||
define Package/luci-app-jellyfin/install
|
||||
$(INSTALL_DIR) $(1)/usr/share/luci/menu.d
|
||||
$(INSTALL_DATA) ./root/usr/share/luci/menu.d/luci-app-jellyfin.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-jellyfin.json $(1)/usr/share/rpcd/acl.d/
|
||||
|
||||
$(INSTALL_DIR) $(1)/www/luci-static/resources/view/jellyfin
|
||||
$(INSTALL_DATA) ./htdocs/luci-static/resources/view/jellyfin/*.js $(1)/www/luci-static/resources/view/jellyfin/
|
||||
|
||||
$(INSTALL_DIR) $(1)/usr/libexec/rpcd
|
||||
$(INSTALL_BIN) ./root/usr/libexec/rpcd/luci.jellyfin $(1)/usr/libexec/rpcd/
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,luci-app-jellyfin))
|
||||
@ -0,0 +1,236 @@
|
||||
'use strict';
|
||||
'require view';
|
||||
'require form';
|
||||
'require uci';
|
||||
'require rpc';
|
||||
'require ui';
|
||||
|
||||
var callStatus = rpc.declare({
|
||||
object: 'luci.jellyfin',
|
||||
method: 'status',
|
||||
expect: {}
|
||||
});
|
||||
|
||||
var callStart = rpc.declare({
|
||||
object: 'luci.jellyfin',
|
||||
method: 'start',
|
||||
expect: {}
|
||||
});
|
||||
|
||||
var callStop = rpc.declare({
|
||||
object: 'luci.jellyfin',
|
||||
method: 'stop',
|
||||
expect: {}
|
||||
});
|
||||
|
||||
var callRestart = rpc.declare({
|
||||
object: 'luci.jellyfin',
|
||||
method: 'restart',
|
||||
expect: {}
|
||||
});
|
||||
|
||||
var callInstall = rpc.declare({
|
||||
object: 'luci.jellyfin',
|
||||
method: 'install',
|
||||
expect: {}
|
||||
});
|
||||
|
||||
var callLogs = rpc.declare({
|
||||
object: 'luci.jellyfin',
|
||||
method: 'logs',
|
||||
params: ['lines'],
|
||||
expect: {}
|
||||
});
|
||||
|
||||
return view.extend({
|
||||
load: function() {
|
||||
return Promise.all([
|
||||
uci.load('jellyfin'),
|
||||
callStatus()
|
||||
]);
|
||||
},
|
||||
|
||||
render: function(data) {
|
||||
var status = data[1] || {};
|
||||
var m, s, o;
|
||||
|
||||
m = new form.Map('jellyfin', _('Jellyfin Media Server'),
|
||||
_('Free media server for streaming movies, TV shows, music, and photos.'));
|
||||
|
||||
/* ---- Status Section ---- */
|
||||
s = m.section(form.NamedSection, 'main', 'jellyfin', _('Service Status'));
|
||||
s.anonymous = true;
|
||||
|
||||
o = s.option(form.DummyValue, '_status', _('Status'));
|
||||
o.rawhtml = true;
|
||||
o.cfgvalue = function() {
|
||||
var cs = status.container_status || 'unknown';
|
||||
var color = cs === 'running' ? '#27ae60' : (cs === 'stopped' ? '#e74c3c' : '#8892b0');
|
||||
var label = cs === 'running' ? 'Running' : (cs === 'stopped' ? 'Stopped' : 'Not Installed');
|
||||
var html = '<span style="color:' + color + '; font-weight: bold;">' + label + '</span>';
|
||||
if (cs === 'running' && status.container_uptime)
|
||||
html += ' <span style="color: #8892b0;">(' + status.container_uptime + ')</span>';
|
||||
return html;
|
||||
};
|
||||
|
||||
o = s.option(form.DummyValue, '_docker', _('Docker'));
|
||||
o.rawhtml = true;
|
||||
o.cfgvalue = function() {
|
||||
return status.docker_available
|
||||
? '<span style="color:#27ae60;">Available</span>'
|
||||
: '<span style="color:#e74c3c;">Not available</span>';
|
||||
};
|
||||
|
||||
o = s.option(form.DummyValue, '_info', _('Details'));
|
||||
o.rawhtml = true;
|
||||
o.cfgvalue = function() {
|
||||
var port = status.port || 8096;
|
||||
var html = '<table style="border-collapse:collapse;">';
|
||||
html += '<tr><td style="padding:2px 12px 2px 0;color:#8892b0;">Image:</td><td>' + (status.image || '-') + '</td></tr>';
|
||||
html += '<tr><td style="padding:2px 12px 2px 0;color:#8892b0;">Port:</td><td>' + port + '</td></tr>';
|
||||
html += '<tr><td style="padding:2px 12px 2px 0;color:#8892b0;">Data:</td><td>' + (status.data_path || '-') + '</td></tr>';
|
||||
if (status.media_paths && status.media_paths.length > 0)
|
||||
html += '<tr><td style="padding:2px 12px 2px 0;color:#8892b0;">Media:</td><td>' + status.media_paths.join('<br>') + '</td></tr>';
|
||||
html += '</table>';
|
||||
return html;
|
||||
};
|
||||
|
||||
/* ---- Action Buttons ---- */
|
||||
o = s.option(form.DummyValue, '_actions', _('Actions'));
|
||||
o.rawhtml = true;
|
||||
o.cfgvalue = function() {
|
||||
return '';
|
||||
};
|
||||
|
||||
var cs = status.container_status || 'not_installed';
|
||||
|
||||
if (cs === 'not_installed') {
|
||||
o = s.option(form.Button, '_install', _('Install'));
|
||||
o.inputtitle = _('Install Jellyfin');
|
||||
o.inputstyle = 'apply';
|
||||
o.onclick = function() {
|
||||
ui.showModal(_('Installing...'), [
|
||||
E('p', { 'class': 'spinning' }, _('Pulling Docker image and configuring...'))
|
||||
]);
|
||||
return callInstall().then(function(res) {
|
||||
ui.hideModal();
|
||||
if (res && res.success) {
|
||||
ui.addNotification(null, E('p', {}, _('Jellyfin installed successfully.')), 'info');
|
||||
} else {
|
||||
ui.addNotification(null, E('p', {}, _('Installation failed: ') + (res.output || 'Unknown error')), 'danger');
|
||||
}
|
||||
window.location.href = window.location.pathname + '?' + Date.now();
|
||||
});
|
||||
};
|
||||
} else {
|
||||
if (cs === 'stopped') {
|
||||
o = s.option(form.Button, '_start', _('Start'));
|
||||
o.inputtitle = _('Start');
|
||||
o.inputstyle = 'apply';
|
||||
o.onclick = function() {
|
||||
return callStart().then(function() {
|
||||
window.location.href = window.location.pathname + '?' + Date.now();
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
if (cs === 'running') {
|
||||
o = s.option(form.Button, '_stop', _('Stop'));
|
||||
o.inputtitle = _('Stop');
|
||||
o.inputstyle = 'remove';
|
||||
o.onclick = function() {
|
||||
return callStop().then(function() {
|
||||
window.location.href = window.location.pathname + '?' + Date.now();
|
||||
});
|
||||
};
|
||||
|
||||
o = s.option(form.Button, '_restart', _('Restart'));
|
||||
o.inputtitle = _('Restart');
|
||||
o.inputstyle = 'reload';
|
||||
o.onclick = function() {
|
||||
return callRestart().then(function() {
|
||||
window.location.href = window.location.pathname + '?' + Date.now();
|
||||
});
|
||||
};
|
||||
|
||||
o = s.option(form.Button, '_webui', _('Web UI'));
|
||||
o.inputtitle = _('Open Web UI');
|
||||
o.inputstyle = 'action';
|
||||
o.onclick = function() {
|
||||
var port = status.port || 8096;
|
||||
window.open('http://' + window.location.hostname + ':' + port, '_blank');
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/* ---- Configuration Section ---- */
|
||||
s = m.section(form.NamedSection, 'main', 'jellyfin', _('Configuration'));
|
||||
s.anonymous = true;
|
||||
|
||||
o = s.option(form.Flag, 'enabled', _('Enabled'),
|
||||
_('Enable the Jellyfin service.'));
|
||||
o.rmempty = false;
|
||||
|
||||
o = s.option(form.Value, 'port', _('Port'),
|
||||
_('HTTP port for the Jellyfin web interface.'));
|
||||
o.datatype = 'port';
|
||||
o.placeholder = '8096';
|
||||
|
||||
o = s.option(form.Value, 'image', _('Docker Image'),
|
||||
_('Docker image to use.'));
|
||||
o.placeholder = 'jellyfin/jellyfin:latest';
|
||||
|
||||
o = s.option(form.Value, 'data_path', _('Data Path'),
|
||||
_('Path for Jellyfin config and cache data.'));
|
||||
o.placeholder = '/srv/jellyfin';
|
||||
|
||||
o = s.option(form.Value, 'timezone', _('Timezone'));
|
||||
o.placeholder = 'Europe/Paris';
|
||||
|
||||
/* ---- Media Libraries ---- */
|
||||
s = m.section(form.NamedSection, 'media', 'jellyfin', _('Media Libraries'));
|
||||
s.anonymous = true;
|
||||
|
||||
o = s.option(form.DynamicList, 'media_path', _('Media Paths'),
|
||||
_('Directories containing your media files. Mounted read-only into the container.'));
|
||||
o.placeholder = '/mnt/media/movies';
|
||||
|
||||
/* ---- Transcoding ---- */
|
||||
s = m.section(form.NamedSection, 'transcoding', 'jellyfin', _('Hardware Transcoding'));
|
||||
s.anonymous = true;
|
||||
|
||||
o = s.option(form.Flag, 'hw_accel', _('Hardware Acceleration'),
|
||||
_('Enable GPU hardware transcoding. Requires a compatible GPU device.'));
|
||||
o.rmempty = false;
|
||||
|
||||
o = s.option(form.Value, 'gpu_device', _('GPU Device'),
|
||||
_('Path to the GPU device for hardware transcoding.'));
|
||||
o.placeholder = '/dev/dri';
|
||||
o.depends('hw_accel', '1');
|
||||
|
||||
/* ---- Logs Section ---- */
|
||||
s = m.section(form.NamedSection, 'main', 'jellyfin', _('Logs'));
|
||||
s.anonymous = true;
|
||||
|
||||
o = s.option(form.DummyValue, '_logs', ' ');
|
||||
o.rawhtml = true;
|
||||
o.cfgvalue = function() {
|
||||
return '<div id="jellyfin-logs" style="background:#0a0a1a; color:#ccc; padding:8px; ' +
|
||||
'border-radius:4px; font-family:monospace; font-size:12px; max-height:300px; ' +
|
||||
'overflow-y:auto; white-space:pre-wrap; min-height:40px;">Click "Fetch Logs" to view container output.</div>';
|
||||
};
|
||||
|
||||
o = s.option(form.Button, '_fetch_logs', _('Fetch Logs'));
|
||||
o.inputtitle = _('Fetch Logs');
|
||||
o.inputstyle = 'action';
|
||||
o.onclick = function() {
|
||||
var logsDiv = document.getElementById('jellyfin-logs');
|
||||
if (logsDiv) logsDiv.textContent = 'Loading...';
|
||||
return callLogs(50).then(function(res) {
|
||||
if (logsDiv) logsDiv.textContent = (res && res.logs) ? res.logs : 'No logs available.';
|
||||
});
|
||||
};
|
||||
|
||||
return m.render();
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,100 @@
|
||||
#!/bin/sh
|
||||
|
||||
. /lib/functions.sh
|
||||
. /usr/share/libubox/jshn.sh
|
||||
|
||||
CONTAINER="secbx-jellyfin"
|
||||
CONFIG="jellyfin"
|
||||
|
||||
case "$1" in
|
||||
list)
|
||||
echo '{"status":{},"start":{},"stop":{},"restart":{},"install":{},"logs":{"lines":"int"}}'
|
||||
;;
|
||||
call)
|
||||
case "$2" in
|
||||
status)
|
||||
json_init
|
||||
|
||||
enabled=$(uci -q get ${CONFIG}.main.enabled)
|
||||
image=$(uci -q get ${CONFIG}.main.image)
|
||||
port=$(uci -q get ${CONFIG}.main.port)
|
||||
data_path=$(uci -q get ${CONFIG}.main.data_path)
|
||||
timezone=$(uci -q get ${CONFIG}.main.timezone)
|
||||
hw_accel=$(uci -q get ${CONFIG}.transcoding.hw_accel)
|
||||
|
||||
json_add_boolean "enabled" ${enabled:-0}
|
||||
json_add_string "image" "${image:-jellyfin/jellyfin:latest}"
|
||||
json_add_int "port" ${port:-8096}
|
||||
json_add_string "data_path" "${data_path:-/srv/jellyfin}"
|
||||
json_add_string "timezone" "${timezone:-Europe/Paris}"
|
||||
json_add_boolean "hw_accel" ${hw_accel:-0}
|
||||
|
||||
# Docker availability
|
||||
if command -v docker >/dev/null 2>&1; then
|
||||
json_add_boolean "docker_available" 1
|
||||
else
|
||||
json_add_boolean "docker_available" 0
|
||||
fi
|
||||
|
||||
# Container status
|
||||
if docker ps --filter "name=$CONTAINER" --format '{{.Status}}' 2>/dev/null | grep -q .; then
|
||||
json_add_string "container_status" "running"
|
||||
uptime=$(docker ps --filter "name=$CONTAINER" --format '{{.Status}}' 2>/dev/null)
|
||||
json_add_string "container_uptime" "$uptime"
|
||||
elif docker ps -a --filter "name=$CONTAINER" --format '{{.Status}}' 2>/dev/null | grep -q .; then
|
||||
json_add_string "container_status" "stopped"
|
||||
json_add_string "container_uptime" ""
|
||||
else
|
||||
json_add_string "container_status" "not_installed"
|
||||
json_add_string "container_uptime" ""
|
||||
fi
|
||||
|
||||
# Media paths
|
||||
json_add_array "media_paths"
|
||||
for mp in $(uci -q get ${CONFIG}.media.media_path); do
|
||||
json_add_string "" "$mp"
|
||||
done
|
||||
json_close_array
|
||||
|
||||
json_dump
|
||||
;;
|
||||
|
||||
start)
|
||||
/etc/init.d/jellyfin start >/dev/null 2>&1
|
||||
echo '{"success":true}'
|
||||
;;
|
||||
|
||||
stop)
|
||||
/etc/init.d/jellyfin stop >/dev/null 2>&1
|
||||
echo '{"success":true}'
|
||||
;;
|
||||
|
||||
restart)
|
||||
/etc/init.d/jellyfin restart >/dev/null 2>&1
|
||||
echo '{"success":true}'
|
||||
;;
|
||||
|
||||
install)
|
||||
output=$(/usr/sbin/jellyfinctl install 2>&1)
|
||||
code=$?
|
||||
json_init
|
||||
json_add_boolean "success" $((code == 0))
|
||||
json_add_string "output" "$output"
|
||||
json_dump
|
||||
;;
|
||||
|
||||
logs)
|
||||
read -r input
|
||||
lines=$(echo "$input" | jsonfilter -e '@.lines' 2>/dev/null)
|
||||
[ -z "$lines" ] && lines=50
|
||||
|
||||
logs=$(docker logs --tail "$lines" "$CONTAINER" 2>&1 | tail -100)
|
||||
json_init
|
||||
json_add_string "logs" "$logs"
|
||||
json_dump
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
||||
@ -0,0 +1,14 @@
|
||||
{
|
||||
"admin/services/jellyfin": {
|
||||
"title": "Jellyfin",
|
||||
"order": 60,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "jellyfin/overview"
|
||||
},
|
||||
"depends": {
|
||||
"acl": ["luci-app-jellyfin"],
|
||||
"uci": {"jellyfin": true}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,24 @@
|
||||
{
|
||||
"luci-app-jellyfin": {
|
||||
"description": "Grant access to Jellyfin media server configuration",
|
||||
"read": {
|
||||
"file": {
|
||||
"/etc/config/jellyfin": ["read"]
|
||||
},
|
||||
"ubus": {
|
||||
"file": ["read", "stat"],
|
||||
"luci.jellyfin": ["*"]
|
||||
},
|
||||
"uci": ["jellyfin"]
|
||||
},
|
||||
"write": {
|
||||
"file": {
|
||||
"/etc/config/jellyfin": ["write"]
|
||||
},
|
||||
"ubus": {
|
||||
"luci.jellyfin": ["*"]
|
||||
},
|
||||
"uci": ["jellyfin"]
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -8,7 +8,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: 11737
|
||||
Size: 11733
|
||||
|
||||
Package: luci-app-bandwidth-manager
|
||||
Version: 0.5.0-r2
|
||||
@ -20,7 +20,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: 61538
|
||||
Size: 61537
|
||||
|
||||
Package: luci-app-cdn-cache
|
||||
Version: 0.5.0-r3
|
||||
@ -32,7 +32,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: 23186
|
||||
Size: 23183
|
||||
|
||||
Package: luci-app-client-guardian
|
||||
Version: 0.4.0-r7
|
||||
@ -44,7 +44,7 @@ Architecture: all
|
||||
Installed-Size: 286720
|
||||
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: 54535
|
||||
Size: 54534
|
||||
|
||||
Package: luci-app-crowdsec-dashboard
|
||||
Version: 0.7.0-r32
|
||||
@ -56,7 +56,7 @@ Architecture: all
|
||||
Installed-Size: 184320
|
||||
Description: Real-time security monitoring dashboard for CrowdSec on OpenWrt
|
||||
Filename: luci-app-crowdsec-dashboard_0.7.0-r32_all.ipk
|
||||
Size: 33798
|
||||
Size: 33797
|
||||
|
||||
Package: luci-app-cyberfeed
|
||||
Version: 0.1.1-r1
|
||||
@ -68,7 +68,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: 12840
|
||||
Size: 12837
|
||||
|
||||
Package: luci-app-dnsguard
|
||||
Version: 1.0.0-r1
|
||||
@ -79,7 +79,7 @@ Architecture: all
|
||||
Installed-Size: 40960
|
||||
Description: SecuBox DNS Guard - Privacy DNS Manager
|
||||
Filename: luci-app-dnsguard_1.0.0-r1_all.ipk
|
||||
Size: 7550
|
||||
Size: 7545
|
||||
|
||||
Package: luci-app-exposure
|
||||
Version: 1.0.0-r3
|
||||
@ -88,10 +88,10 @@ License: MIT
|
||||
Section: luci
|
||||
Maintainer: OpenWrt LuCI community
|
||||
Architecture: all
|
||||
Installed-Size: 153600
|
||||
Installed-Size: 61440
|
||||
Description: LuCI SecuBox Service Exposure Manager
|
||||
Filename: luci-app-exposure_1.0.0-r3_all.ipk
|
||||
Size: 20534
|
||||
Size: 9685
|
||||
|
||||
Package: luci-app-gitea
|
||||
Version: 1.0.0-r2
|
||||
@ -115,7 +115,7 @@ Architecture: all
|
||||
Installed-Size: 40960
|
||||
Description: Modern dashboard for Glances system monitoring with SecuBox theme
|
||||
Filename: luci-app-glances_1.0.0-r2_all.ipk
|
||||
Size: 6969
|
||||
Size: 6965
|
||||
|
||||
Package: luci-app-haproxy
|
||||
Version: 1.0.0-r8
|
||||
@ -127,7 +127,7 @@ Architecture: all
|
||||
Installed-Size: 204800
|
||||
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: 34560
|
||||
Size: 34559
|
||||
|
||||
Package: luci-app-hexojs
|
||||
Version: 1.0.0-r3
|
||||
@ -139,7 +139,7 @@ Architecture: all
|
||||
Installed-Size: 184320
|
||||
Description: Modern dashboard for Hexo static site generator on OpenWrt
|
||||
Filename: luci-app-hexojs_1.0.0-r3_all.ipk
|
||||
Size: 30307
|
||||
Size: 30309
|
||||
|
||||
Package: luci-app-jitsi
|
||||
Version: 1.0.0-r1
|
||||
@ -163,7 +163,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: 18721
|
||||
Size: 18725
|
||||
|
||||
Package: luci-app-localai
|
||||
Version: 0.1.0-r15
|
||||
@ -175,7 +175,7 @@ Architecture: all
|
||||
Installed-Size: 71680
|
||||
Description: Modern dashboard for LocalAI LLM management on OpenWrt
|
||||
Filename: luci-app-localai_0.1.0-r15_all.ipk
|
||||
Size: 13183
|
||||
Size: 13181
|
||||
|
||||
Package: luci-app-lyrion
|
||||
Version: 1.0.0-r1
|
||||
@ -187,7 +187,7 @@ Architecture: all
|
||||
Installed-Size: 40960
|
||||
Description: LuCI support for Lyrion Music Server
|
||||
Filename: luci-app-lyrion_1.0.0-r1_all.ipk
|
||||
Size: 6729
|
||||
Size: 6723
|
||||
|
||||
Package: luci-app-magicmirror2
|
||||
Version: 0.4.0-r6
|
||||
@ -199,7 +199,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: 12277
|
||||
Size: 12279
|
||||
|
||||
Package: luci-app-mailinabox
|
||||
Version: 1.0.0-r1
|
||||
@ -211,7 +211,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: 5483
|
||||
Size: 5484
|
||||
|
||||
Package: luci-app-master-link
|
||||
Version: 1.0.0-r1
|
||||
@ -223,7 +223,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: 6247
|
||||
Size: 6248
|
||||
|
||||
Package: luci-app-media-flow
|
||||
Version: 0.6.4-r1
|
||||
@ -235,7 +235,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: 25416
|
||||
Size: 25417
|
||||
|
||||
Package: luci-app-metablogizer
|
||||
Version: 1.0.0-r5
|
||||
@ -259,7 +259,7 @@ Architecture: all
|
||||
Installed-Size: 30720
|
||||
Description: LuCI support for Metabolizer CMS
|
||||
Filename: luci-app-metabolizer_1.0.0-r2_all.ipk
|
||||
Size: 4760
|
||||
Size: 4758
|
||||
|
||||
Package: luci-app-mitmproxy
|
||||
Version: 0.5.0-r2
|
||||
@ -271,7 +271,7 @@ Architecture: all
|
||||
Installed-Size: 61440
|
||||
Description: Modern dashboard for mitmproxy HTTPS traffic inspection with SecuBox theme
|
||||
Filename: luci-app-mitmproxy_0.5.0-r2_all.ipk
|
||||
Size: 11149
|
||||
Size: 11148
|
||||
|
||||
Package: luci-app-mmpm
|
||||
Version: 0.2.0-r3
|
||||
@ -283,7 +283,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: 7901
|
||||
Size: 7905
|
||||
|
||||
Package: luci-app-mqtt-bridge
|
||||
Version: 0.4.0-r4
|
||||
@ -295,7 +295,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: 22777
|
||||
Size: 22779
|
||||
|
||||
Package: luci-app-ndpid
|
||||
Version: 1.1.2-r2
|
||||
@ -319,7 +319,7 @@ Architecture: all
|
||||
Installed-Size: 112640
|
||||
Description: Real-time system monitoring dashboard with Netdata integration for OpenWrt
|
||||
Filename: luci-app-netdata-dashboard_0.5.0-r2_all.ipk
|
||||
Size: 20486
|
||||
Size: 20484
|
||||
|
||||
Package: luci-app-network-modes
|
||||
Version: 0.5.0-r3
|
||||
@ -331,7 +331,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: 54147
|
||||
Size: 54150
|
||||
|
||||
Package: luci-app-network-tweaks
|
||||
Version: 1.0.0-r7
|
||||
@ -343,7 +343,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: 14957
|
||||
Size: 14969
|
||||
|
||||
Package: luci-app-nextcloud
|
||||
Version: 1.0.0-r1
|
||||
@ -355,7 +355,7 @@ Architecture: all
|
||||
Installed-Size: 30720
|
||||
Description: LuCI support for Nextcloud
|
||||
Filename: luci-app-nextcloud_1.0.0-r1_all.ipk
|
||||
Size: 6486
|
||||
Size: 6487
|
||||
|
||||
Package: luci-app-ollama
|
||||
Version: 0.1.0-r1
|
||||
@ -367,7 +367,7 @@ Architecture: all
|
||||
Installed-Size: 61440
|
||||
Description: Modern dashboard for Ollama LLM management on OpenWrt
|
||||
Filename: luci-app-ollama_0.1.0-r1_all.ipk
|
||||
Size: 12353
|
||||
Size: 12352
|
||||
|
||||
Package: luci-app-picobrew
|
||||
Version: 1.0.0-r1
|
||||
@ -379,7 +379,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: 9457
|
||||
Size: 9458
|
||||
|
||||
Package: luci-app-secubox
|
||||
Version: 0.7.1-r4
|
||||
@ -391,7 +391,7 @@ Architecture: all
|
||||
Installed-Size: 419840
|
||||
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: 77680
|
||||
Size: 77679
|
||||
|
||||
Package: luci-app-secubox-admin
|
||||
Version: 1.0.0-r19
|
||||
@ -402,7 +402,7 @@ Architecture: all
|
||||
Installed-Size: 337920
|
||||
Description: Unified admin control center for SecuBox appstore plugins with system monitoring
|
||||
Filename: luci-app-secubox-admin_1.0.0-r19_all.ipk
|
||||
Size: 57250
|
||||
Size: 57249
|
||||
|
||||
Package: luci-app-secubox-crowdsec
|
||||
Version: 1.0.0-r3
|
||||
@ -414,7 +414,7 @@ Architecture: all
|
||||
Installed-Size: 81920
|
||||
Description: LuCI SecuBox CrowdSec Dashboard
|
||||
Filename: luci-app-secubox-crowdsec_1.0.0-r3_all.ipk
|
||||
Size: 13923
|
||||
Size: 13918
|
||||
|
||||
Package: luci-app-secubox-netdiag
|
||||
Version: 1.0.0-r1
|
||||
@ -438,7 +438,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: 36547
|
||||
Size: 36542
|
||||
|
||||
Package: luci-app-secubox-p2p
|
||||
Version: 0.1.0-r1
|
||||
@ -450,7 +450,7 @@ Architecture: all
|
||||
Installed-Size: 215040
|
||||
Description: LuCI SecuBox P2P Hub
|
||||
Filename: luci-app-secubox-p2p_0.1.0-r1_all.ipk
|
||||
Size: 39237
|
||||
Size: 39234
|
||||
|
||||
Package: luci-app-secubox-portal
|
||||
Version: 0.7.0-r2
|
||||
@ -462,7 +462,7 @@ Architecture: all
|
||||
Installed-Size: 122880
|
||||
Description: Unified entry point for all SecuBox applications with tabbed navigation
|
||||
Filename: luci-app-secubox-portal_0.7.0-r2_all.ipk
|
||||
Size: 24646
|
||||
Size: 24644
|
||||
|
||||
Package: luci-app-secubox-security-threats
|
||||
Version: 1.0.0-r4
|
||||
@ -474,7 +474,7 @@ Architecture: all
|
||||
Installed-Size: 102400
|
||||
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: 21897
|
||||
Size: 21895
|
||||
|
||||
Package: luci-app-service-registry
|
||||
Version: 1.0.0-r1
|
||||
@ -486,7 +486,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: 39827
|
||||
Size: 39826
|
||||
|
||||
Package: luci-app-simplex
|
||||
Version: 1.0.0-r1
|
||||
@ -498,7 +498,7 @@ Architecture: all
|
||||
Installed-Size: 40960
|
||||
Description: LuCI SimpleX Chat Server Configuration
|
||||
Filename: luci-app-simplex_1.0.0-r1_all.ipk
|
||||
Size: 7001
|
||||
Size: 6997
|
||||
|
||||
Package: luci-app-streamlit
|
||||
Version: 1.0.0-r11
|
||||
@ -522,7 +522,7 @@ Architecture: all
|
||||
Installed-Size: 317440
|
||||
Description: Central system control with monitoring, services, logs, and backup
|
||||
Filename: luci-app-system-hub_0.5.1-r4_all.ipk
|
||||
Size: 61105
|
||||
Size: 61102
|
||||
|
||||
Package: luci-app-tor-shield
|
||||
Version: 1.0.0-r10
|
||||
@ -534,7 +534,7 @@ Architecture: all
|
||||
Installed-Size: 122880
|
||||
Description: Modern dashboard for Tor anonymization on OpenWrt
|
||||
Filename: luci-app-tor-shield_1.0.0-r10_all.ipk
|
||||
Size: 22364
|
||||
Size: 22359
|
||||
|
||||
Package: luci-app-traffic-shaper
|
||||
Version: 0.4.0-r2
|
||||
@ -546,7 +546,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: 14533
|
||||
Size: 14532
|
||||
|
||||
Package: luci-app-vhost-manager
|
||||
Version: 0.5.0-r5
|
||||
@ -558,7 +558,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: 26185
|
||||
Size: 26187
|
||||
|
||||
Package: luci-app-wireguard-dashboard
|
||||
Version: 0.7.0-r5
|
||||
@ -570,7 +570,7 @@ Architecture: all
|
||||
Installed-Size: 204800
|
||||
Description: Modern dashboard for WireGuard VPN monitoring on OpenWrt
|
||||
Filename: luci-app-wireguard-dashboard_0.7.0-r5_all.ipk
|
||||
Size: 39607
|
||||
Size: 39604
|
||||
|
||||
Package: luci-app-zigbee2mqtt
|
||||
Version: 1.0.0-r2
|
||||
@ -582,7 +582,7 @@ Architecture: all
|
||||
Installed-Size: 40960
|
||||
Description: Graphical interface for managing the Zigbee2MQTT docker application.
|
||||
Filename: luci-app-zigbee2mqtt_1.0.0-r2_all.ipk
|
||||
Size: 6813
|
||||
Size: 6815
|
||||
|
||||
Package: luci-theme-secubox
|
||||
Version: 0.4.7-r1
|
||||
@ -594,7 +594,7 @@ Architecture: all
|
||||
Installed-Size: 450560
|
||||
Description: Global CyberMood design system (CSS/JS/i18n) shared by all SecuBox dashboards.
|
||||
Filename: luci-theme-secubox_0.4.7-r1_all.ipk
|
||||
Size: 110242
|
||||
Size: 110241
|
||||
|
||||
Package: secubox-app
|
||||
Version: 1.0.0-r2
|
||||
@ -619,7 +619,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: 2883
|
||||
Size: 2880
|
||||
|
||||
Package: secubox-app-auth-logger
|
||||
Version: 1.2.2-r1
|
||||
@ -637,7 +637,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: 9379
|
||||
Size: 9376
|
||||
|
||||
Package: secubox-app-crowdsec-custom
|
||||
Version: 1.1.0-r1
|
||||
@ -687,7 +687,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: 5049328
|
||||
Size: 5049322
|
||||
|
||||
Package: secubox-app-cyberfeed
|
||||
Version: 0.2.1-r1
|
||||
@ -701,7 +701,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: 12452
|
||||
Size: 12449
|
||||
|
||||
Package: secubox-app-domoticz
|
||||
Version: 1.0.0-r2
|
||||
@ -714,7 +714,7 @@ Installed-Size: 10240
|
||||
Description: Installer, configuration, and service manager for running Domoticz
|
||||
inside Docker on SecuBox-powered OpenWrt systems.
|
||||
Filename: secubox-app-domoticz_1.0.0-r2_all.ipk
|
||||
Size: 2550
|
||||
Size: 2544
|
||||
|
||||
Package: secubox-app-exposure
|
||||
Version: 1.0.0-r1
|
||||
@ -729,7 +729,7 @@ Description: Unified service exposure manager for SecuBox.
|
||||
- Dynamic Tor hidden service management
|
||||
- HAProxy SSL reverse proxy configuration
|
||||
Filename: secubox-app-exposure_1.0.0-r1_all.ipk
|
||||
Size: 6938
|
||||
Size: 6931
|
||||
|
||||
Package: secubox-app-gitea
|
||||
Version: 1.0.0-r5
|
||||
@ -752,7 +752,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: 9409
|
||||
Size: 9406
|
||||
|
||||
Package: secubox-app-glances
|
||||
Version: 1.0.0-r1
|
||||
@ -775,7 +775,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: 5542
|
||||
Size: 5533
|
||||
|
||||
Package: secubox-app-haproxy
|
||||
Version: 1.0.0-r23
|
||||
@ -795,7 +795,7 @@ Description: HAProxy load balancer and reverse proxy running in an LXC containe
|
||||
- Stats dashboard
|
||||
- Rate limiting and ACLs
|
||||
Filename: secubox-app-haproxy_1.0.0-r23_all.ipk
|
||||
Size: 15687
|
||||
Size: 15681
|
||||
|
||||
Package: secubox-app-hexojs
|
||||
Version: 1.0.0-r8
|
||||
@ -819,7 +819,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: 94937
|
||||
Size: 94933
|
||||
|
||||
Package: secubox-app-jitsi
|
||||
Version: 1.0.0-r1
|
||||
@ -844,7 +844,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: 8916
|
||||
Size: 8914
|
||||
|
||||
Package: secubox-app-localai
|
||||
Version: 2.25.0-r1
|
||||
@ -866,7 +866,7 @@ Description: LocalAI native binary package for OpenWrt.
|
||||
|
||||
API: http://<router-ip>:8081/v1
|
||||
Filename: secubox-app-localai_2.25.0-r1_all.ipk
|
||||
Size: 5718
|
||||
Size: 5725
|
||||
|
||||
Package: secubox-app-localai-wb
|
||||
Version: 2.25.0-r1
|
||||
@ -890,7 +890,7 @@ Description: LocalAI native binary package for OpenWrt.
|
||||
|
||||
API: http://<router-ip>:8080/v1
|
||||
Filename: secubox-app-localai-wb_2.25.0-r1_all.ipk
|
||||
Size: 7954
|
||||
Size: 7951
|
||||
|
||||
Package: secubox-app-lyrion
|
||||
Version: 2.0.2-r1
|
||||
@ -910,7 +910,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: 7288
|
||||
Size: 7292
|
||||
|
||||
Package: secubox-app-magicmirror2
|
||||
Version: 0.4.0-r8
|
||||
@ -932,7 +932,7 @@ Description: MagicMirror² - Open source modular smart mirror platform for Secu
|
||||
Runs in LXC container for isolation and security.
|
||||
Configure in /etc/config/magicmirror2.
|
||||
Filename: secubox-app-magicmirror2_0.4.0-r8_all.ipk
|
||||
Size: 9254
|
||||
Size: 9250
|
||||
|
||||
Package: secubox-app-mailinabox
|
||||
Version: 2.0.0-r1
|
||||
@ -957,7 +957,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: 7573
|
||||
Size: 7570
|
||||
|
||||
Package: secubox-app-metabolizer
|
||||
Version: 1.0.0-r3
|
||||
@ -1005,7 +1005,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: 22958
|
||||
Size: 22956
|
||||
|
||||
Package: secubox-app-mmpm
|
||||
Version: 0.2.0-r5
|
||||
@ -1026,7 +1026,7 @@ Description: MMPM (MagicMirror Package Manager) for SecuBox.
|
||||
|
||||
Runs inside the MagicMirror2 LXC container.
|
||||
Filename: secubox-app-mmpm_0.2.0-r5_all.ipk
|
||||
Size: 3982
|
||||
Size: 3980
|
||||
|
||||
Package: secubox-app-nextcloud
|
||||
Version: 1.0.0-r2
|
||||
@ -1040,7 +1040,7 @@ Description: Installer, configuration, and service manager for running Nextclou
|
||||
inside Docker on SecuBox-powered OpenWrt systems. Self-hosted file
|
||||
sync and share with calendar, contacts, and collaboration.
|
||||
Filename: secubox-app-nextcloud_1.0.0-r2_all.ipk
|
||||
Size: 2961
|
||||
Size: 2959
|
||||
|
||||
Package: secubox-app-ollama
|
||||
Version: 0.1.0-r1
|
||||
@ -1062,7 +1062,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: 5737
|
||||
Size: 5734
|
||||
|
||||
Package: secubox-app-picobrew
|
||||
Version: 1.0.0-r7
|
||||
@ -1084,7 +1084,7 @@ 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: 5538
|
||||
Size: 5539
|
||||
|
||||
Package: secubox-app-simplex
|
||||
Version: 1.0.0-r1
|
||||
@ -1108,7 +1108,7 @@ Description: SimpleX Chat self-hosted messaging infrastructure for SecuBox.
|
||||
Privacy-first messaging relay that you control.
|
||||
Configure in /etc/config/simplex.
|
||||
Filename: secubox-app-simplex_1.0.0-r1_all.ipk
|
||||
Size: 9233
|
||||
Size: 9232
|
||||
|
||||
Package: secubox-app-streamlit
|
||||
Version: 1.0.0-r5
|
||||
@ -1135,7 +1135,7 @@ 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: 11718
|
||||
Size: 11723
|
||||
|
||||
Package: secubox-app-tor
|
||||
Version: 1.0.0-r1
|
||||
@ -1176,7 +1176,7 @@ Description: SecuBox Control Center Dashboard - A web-based dashboard for monit
|
||||
- Service management
|
||||
- Network interface control
|
||||
Filename: secubox-app-webapp_1.5.0-r7_all.ipk
|
||||
Size: 39174
|
||||
Size: 39172
|
||||
|
||||
Package: secubox-app-zigbee2mqtt
|
||||
Version: 1.0.0-r3
|
||||
@ -1189,7 +1189,7 @@ Installed-Size: 20480
|
||||
Description: Installer, configuration, and service manager for running Zigbee2MQTT
|
||||
inside Docker on SecuBox-powered OpenWrt systems.
|
||||
Filename: secubox-app-zigbee2mqtt_1.0.0-r3_all.ipk
|
||||
Size: 3544
|
||||
Size: 3545
|
||||
|
||||
Package: secubox-core
|
||||
Version: 0.10.0-r11
|
||||
@ -1209,7 +1209,7 @@ Description: SecuBox Core Framework provides the foundational infrastructure fo
|
||||
- Unified CLI interface
|
||||
- ubus RPC backend
|
||||
Filename: secubox-core_0.10.0-r11_all.ipk
|
||||
Size: 87973
|
||||
Size: 87974
|
||||
|
||||
Package: secubox-master-link
|
||||
Version: 1.0.0-r1
|
||||
@ -1231,7 +1231,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: 12455
|
||||
Size: 12454
|
||||
|
||||
Package: secubox-p2p
|
||||
Version: 0.6.0-r3
|
||||
@ -1250,5 +1250,5 @@ Description: SecuBox P2P Hub backend providing peer discovery, mesh networking
|
||||
and MirrorBox NetMesh Catalog for cross-chain distributed service
|
||||
registry with HAProxy vhost discovery and multi-endpoint access URLs.
|
||||
Filename: secubox-p2p_0.6.0-r3_all.ipk
|
||||
Size: 42015
|
||||
Size: 42016
|
||||
|
||||
|
||||
Binary file not shown.
@ -1,12 +1,12 @@
|
||||
{
|
||||
"feed_url": "/secubox-feed",
|
||||
"generated": "2026-02-03T06:19:17+01:00",
|
||||
"generated": "2026-02-04T14:31:38+01:00",
|
||||
"packages": [
|
||||
{
|
||||
"name": "luci-app-auth-guardian",
|
||||
"version": "0.4.0-r3",
|
||||
"filename": "luci-app-auth-guardian_0.4.0-r3_all.ipk",
|
||||
"size": 11737,
|
||||
"size": 11733,
|
||||
"category": "security",
|
||||
"icon": "key",
|
||||
"description": "Authentication management",
|
||||
@ -18,7 +18,7 @@
|
||||
"name": "luci-app-bandwidth-manager",
|
||||
"version": "0.5.0-r2",
|
||||
"filename": "luci-app-bandwidth-manager_0.5.0-r2_all.ipk",
|
||||
"size": 61538,
|
||||
"size": 61537,
|
||||
"category": "network",
|
||||
"icon": "activity",
|
||||
"description": "Bandwidth monitoring and control",
|
||||
@ -30,7 +30,7 @@
|
||||
"name": "luci-app-cdn-cache",
|
||||
"version": "0.5.0-r3",
|
||||
"filename": "luci-app-cdn-cache_0.5.0-r3_all.ipk",
|
||||
"size": 23186,
|
||||
"size": 23183,
|
||||
"category": "network",
|
||||
"icon": "globe",
|
||||
"description": "CDN caching",
|
||||
@ -42,7 +42,7 @@
|
||||
"name": "luci-app-client-guardian",
|
||||
"version": "0.4.0-r7",
|
||||
"filename": "luci-app-client-guardian_0.4.0-r7_all.ipk",
|
||||
"size": 54535,
|
||||
"size": 54534,
|
||||
"category": "network",
|
||||
"icon": "users",
|
||||
"description": "Client management and monitoring",
|
||||
@ -54,7 +54,7 @@
|
||||
"name": "luci-app-crowdsec-dashboard",
|
||||
"version": "0.7.0-r32",
|
||||
"filename": "luci-app-crowdsec-dashboard_0.7.0-r32_all.ipk",
|
||||
"size": 33798,
|
||||
"size": 33797,
|
||||
"category": "security",
|
||||
"icon": "shield",
|
||||
"description": "CrowdSec security monitoring",
|
||||
@ -66,7 +66,7 @@
|
||||
"name": "luci-app-cyberfeed",
|
||||
"version": "0.1.1-r1",
|
||||
"filename": "luci-app-cyberfeed_0.1.1-r1_all.ipk",
|
||||
"size": 12840,
|
||||
"size": 12837,
|
||||
"category": "utility",
|
||||
"icon": "package",
|
||||
"description": "SecuBox package",
|
||||
@ -78,7 +78,7 @@
|
||||
"name": "luci-app-dnsguard",
|
||||
"version": "1.0.0-r1",
|
||||
"filename": "luci-app-dnsguard_1.0.0-r1_all.ipk",
|
||||
"size": 7550,
|
||||
"size": 7545,
|
||||
"category": "utility",
|
||||
"icon": "package",
|
||||
"description": "SecuBox package",
|
||||
@ -90,7 +90,7 @@
|
||||
"name": "luci-app-exposure",
|
||||
"version": "1.0.0-r3",
|
||||
"filename": "luci-app-exposure_1.0.0-r3_all.ipk",
|
||||
"size": 20534,
|
||||
"size": 9685,
|
||||
"category": "utility",
|
||||
"icon": "package",
|
||||
"description": "SecuBox package",
|
||||
@ -114,7 +114,7 @@
|
||||
"name": "luci-app-glances",
|
||||
"version": "1.0.0-r2",
|
||||
"filename": "luci-app-glances_1.0.0-r2_all.ipk",
|
||||
"size": 6969,
|
||||
"size": 6965,
|
||||
"category": "utility",
|
||||
"icon": "package",
|
||||
"description": "SecuBox package",
|
||||
@ -126,7 +126,7 @@
|
||||
"name": "luci-app-haproxy",
|
||||
"version": "1.0.0-r8",
|
||||
"filename": "luci-app-haproxy_1.0.0-r8_all.ipk",
|
||||
"size": 34560,
|
||||
"size": 34559,
|
||||
"category": "utility",
|
||||
"icon": "package",
|
||||
"description": "SecuBox package",
|
||||
@ -138,7 +138,7 @@
|
||||
"name": "luci-app-hexojs",
|
||||
"version": "1.0.0-r3",
|
||||
"filename": "luci-app-hexojs_1.0.0-r3_all.ipk",
|
||||
"size": 30307,
|
||||
"size": 30309,
|
||||
"category": "utility",
|
||||
"icon": "package",
|
||||
"description": "SecuBox package",
|
||||
@ -162,7 +162,7 @@
|
||||
"name": "luci-app-ksm-manager",
|
||||
"version": "0.4.0-r2",
|
||||
"filename": "luci-app-ksm-manager_0.4.0-r2_all.ipk",
|
||||
"size": 18721,
|
||||
"size": 18725,
|
||||
"category": "system",
|
||||
"icon": "cpu",
|
||||
"description": "Kernel memory management",
|
||||
@ -174,7 +174,7 @@
|
||||
"name": "luci-app-localai",
|
||||
"version": "0.1.0-r15",
|
||||
"filename": "luci-app-localai_0.1.0-r15_all.ipk",
|
||||
"size": 13183,
|
||||
"size": 13181,
|
||||
"category": "utility",
|
||||
"icon": "package",
|
||||
"description": "SecuBox package",
|
||||
@ -186,7 +186,7 @@
|
||||
"name": "luci-app-lyrion",
|
||||
"version": "1.0.0-r1",
|
||||
"filename": "luci-app-lyrion_1.0.0-r1_all.ipk",
|
||||
"size": 6729,
|
||||
"size": 6723,
|
||||
"category": "utility",
|
||||
"icon": "package",
|
||||
"description": "SecuBox package",
|
||||
@ -198,7 +198,7 @@
|
||||
"name": "luci-app-magicmirror2",
|
||||
"version": "0.4.0-r6",
|
||||
"filename": "luci-app-magicmirror2_0.4.0-r6_all.ipk",
|
||||
"size": 12277,
|
||||
"size": 12279,
|
||||
"category": "iot",
|
||||
"icon": "monitor",
|
||||
"description": "Smart mirror display",
|
||||
@ -210,7 +210,7 @@
|
||||
"name": "luci-app-mailinabox",
|
||||
"version": "1.0.0-r1",
|
||||
"filename": "luci-app-mailinabox_1.0.0-r1_all.ipk",
|
||||
"size": 5483,
|
||||
"size": 5484,
|
||||
"category": "utility",
|
||||
"icon": "package",
|
||||
"description": "SecuBox package",
|
||||
@ -222,7 +222,7 @@
|
||||
"name": "luci-app-master-link",
|
||||
"version": "1.0.0-r1",
|
||||
"filename": "luci-app-master-link_1.0.0-r1_all.ipk",
|
||||
"size": 6247,
|
||||
"size": 6248,
|
||||
"category": "utility",
|
||||
"icon": "package",
|
||||
"description": "SecuBox package",
|
||||
@ -234,7 +234,7 @@
|
||||
"name": "luci-app-media-flow",
|
||||
"version": "0.6.4-r1",
|
||||
"filename": "luci-app-media-flow_0.6.4-r1_all.ipk",
|
||||
"size": 25416,
|
||||
"size": 25417,
|
||||
"category": "media",
|
||||
"icon": "film",
|
||||
"description": "Media streaming",
|
||||
@ -258,7 +258,7 @@
|
||||
"name": "luci-app-metabolizer",
|
||||
"version": "1.0.0-r2",
|
||||
"filename": "luci-app-metabolizer_1.0.0-r2_all.ipk",
|
||||
"size": 4760,
|
||||
"size": 4758,
|
||||
"category": "utility",
|
||||
"icon": "package",
|
||||
"description": "SecuBox package",
|
||||
@ -270,7 +270,7 @@
|
||||
"name": "luci-app-mitmproxy",
|
||||
"version": "0.5.0-r2",
|
||||
"filename": "luci-app-mitmproxy_0.5.0-r2_all.ipk",
|
||||
"size": 11149,
|
||||
"size": 11148,
|
||||
"category": "security",
|
||||
"icon": "lock",
|
||||
"description": "HTTPS proxy and traffic inspection",
|
||||
@ -282,7 +282,7 @@
|
||||
"name": "luci-app-mmpm",
|
||||
"version": "0.2.0-r3",
|
||||
"filename": "luci-app-mmpm_0.2.0-r3_all.ipk",
|
||||
"size": 7901,
|
||||
"size": 7905,
|
||||
"category": "utility",
|
||||
"icon": "package",
|
||||
"description": "SecuBox package",
|
||||
@ -294,7 +294,7 @@
|
||||
"name": "luci-app-mqtt-bridge",
|
||||
"version": "0.4.0-r4",
|
||||
"filename": "luci-app-mqtt-bridge_0.4.0-r4_all.ipk",
|
||||
"size": 22777,
|
||||
"size": 22779,
|
||||
"category": "iot",
|
||||
"icon": "message-square",
|
||||
"description": "MQTT bridge",
|
||||
@ -318,7 +318,7 @@
|
||||
"name": "luci-app-netdata-dashboard",
|
||||
"version": "0.5.0-r2",
|
||||
"filename": "luci-app-netdata-dashboard_0.5.0-r2_all.ipk",
|
||||
"size": 20486,
|
||||
"size": 20484,
|
||||
"category": "monitoring",
|
||||
"icon": "bar-chart-2",
|
||||
"description": "System monitoring dashboard",
|
||||
@ -330,7 +330,7 @@
|
||||
"name": "luci-app-network-modes",
|
||||
"version": "0.5.0-r3",
|
||||
"filename": "luci-app-network-modes_0.5.0-r3_all.ipk",
|
||||
"size": 54147,
|
||||
"size": 54150,
|
||||
"category": "network",
|
||||
"icon": "wifi",
|
||||
"description": "Network configuration",
|
||||
@ -342,7 +342,7 @@
|
||||
"name": "luci-app-network-tweaks",
|
||||
"version": "1.0.0-r7",
|
||||
"filename": "luci-app-network-tweaks_1.0.0-r7_all.ipk",
|
||||
"size": 14957,
|
||||
"size": 14969,
|
||||
"category": "network",
|
||||
"icon": "wifi",
|
||||
"description": "Network configuration",
|
||||
@ -354,7 +354,7 @@
|
||||
"name": "luci-app-nextcloud",
|
||||
"version": "1.0.0-r1",
|
||||
"filename": "luci-app-nextcloud_1.0.0-r1_all.ipk",
|
||||
"size": 6486,
|
||||
"size": 6487,
|
||||
"category": "utility",
|
||||
"icon": "package",
|
||||
"description": "SecuBox package",
|
||||
@ -366,7 +366,7 @@
|
||||
"name": "luci-app-ollama",
|
||||
"version": "0.1.0-r1",
|
||||
"filename": "luci-app-ollama_0.1.0-r1_all.ipk",
|
||||
"size": 12353,
|
||||
"size": 12352,
|
||||
"category": "utility",
|
||||
"icon": "package",
|
||||
"description": "SecuBox package",
|
||||
@ -378,7 +378,7 @@
|
||||
"name": "luci-app-picobrew",
|
||||
"version": "1.0.0-r1",
|
||||
"filename": "luci-app-picobrew_1.0.0-r1_all.ipk",
|
||||
"size": 9457,
|
||||
"size": 9458,
|
||||
"category": "utility",
|
||||
"icon": "package",
|
||||
"description": "SecuBox package",
|
||||
@ -390,7 +390,7 @@
|
||||
"name": "luci-app-secubox",
|
||||
"version": "0.7.1-r4",
|
||||
"filename": "luci-app-secubox_0.7.1-r4_all.ipk",
|
||||
"size": 77680,
|
||||
"size": 77679,
|
||||
"category": "system",
|
||||
"icon": "box",
|
||||
"description": "SecuBox system component",
|
||||
@ -402,7 +402,7 @@
|
||||
"name": "luci-app-secubox-admin",
|
||||
"version": "1.0.0-r19",
|
||||
"filename": "luci-app-secubox-admin_1.0.0-r19_all.ipk",
|
||||
"size": 57250,
|
||||
"size": 57249,
|
||||
"category": "system",
|
||||
"icon": "box",
|
||||
"description": "SecuBox system component",
|
||||
@ -414,7 +414,7 @@
|
||||
"name": "luci-app-secubox-crowdsec",
|
||||
"version": "1.0.0-r3",
|
||||
"filename": "luci-app-secubox-crowdsec_1.0.0-r3_all.ipk",
|
||||
"size": 13923,
|
||||
"size": 13918,
|
||||
"category": "system",
|
||||
"icon": "box",
|
||||
"description": "SecuBox system component",
|
||||
@ -438,7 +438,7 @@
|
||||
"name": "luci-app-secubox-netifyd",
|
||||
"version": "1.2.1-r1",
|
||||
"filename": "luci-app-secubox-netifyd_1.2.1-r1_all.ipk",
|
||||
"size": 36547,
|
||||
"size": 36542,
|
||||
"category": "system",
|
||||
"icon": "box",
|
||||
"description": "SecuBox system component",
|
||||
@ -450,7 +450,7 @@
|
||||
"name": "luci-app-secubox-p2p",
|
||||
"version": "0.1.0-r1",
|
||||
"filename": "luci-app-secubox-p2p_0.1.0-r1_all.ipk",
|
||||
"size": 39237,
|
||||
"size": 39234,
|
||||
"category": "system",
|
||||
"icon": "box",
|
||||
"description": "SecuBox system component",
|
||||
@ -462,7 +462,7 @@
|
||||
"name": "luci-app-secubox-portal",
|
||||
"version": "0.7.0-r2",
|
||||
"filename": "luci-app-secubox-portal_0.7.0-r2_all.ipk",
|
||||
"size": 24646,
|
||||
"size": 24644,
|
||||
"category": "system",
|
||||
"icon": "box",
|
||||
"description": "SecuBox system component",
|
||||
@ -474,7 +474,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": 21897,
|
||||
"size": 21895,
|
||||
"category": "system",
|
||||
"icon": "box",
|
||||
"description": "SecuBox system component",
|
||||
@ -486,7 +486,7 @@
|
||||
"name": "luci-app-service-registry",
|
||||
"version": "1.0.0-r1",
|
||||
"filename": "luci-app-service-registry_1.0.0-r1_all.ipk",
|
||||
"size": 39827,
|
||||
"size": 39826,
|
||||
"category": "utility",
|
||||
"icon": "package",
|
||||
"description": "SecuBox package",
|
||||
@ -498,7 +498,7 @@
|
||||
"name": "luci-app-simplex",
|
||||
"version": "1.0.0-r1",
|
||||
"filename": "luci-app-simplex_1.0.0-r1_all.ipk",
|
||||
"size": 7001,
|
||||
"size": 6997,
|
||||
"category": "utility",
|
||||
"icon": "package",
|
||||
"description": "SecuBox package",
|
||||
@ -522,7 +522,7 @@
|
||||
"name": "luci-app-system-hub",
|
||||
"version": "0.5.1-r4",
|
||||
"filename": "luci-app-system-hub_0.5.1-r4_all.ipk",
|
||||
"size": 61105,
|
||||
"size": 61102,
|
||||
"category": "system",
|
||||
"icon": "settings",
|
||||
"description": "System management",
|
||||
@ -534,7 +534,7 @@
|
||||
"name": "luci-app-tor-shield",
|
||||
"version": "1.0.0-r10",
|
||||
"filename": "luci-app-tor-shield_1.0.0-r10_all.ipk",
|
||||
"size": 22364,
|
||||
"size": 22359,
|
||||
"category": "utility",
|
||||
"icon": "package",
|
||||
"description": "SecuBox package",
|
||||
@ -546,7 +546,7 @@
|
||||
"name": "luci-app-traffic-shaper",
|
||||
"version": "0.4.0-r2",
|
||||
"filename": "luci-app-traffic-shaper_0.4.0-r2_all.ipk",
|
||||
"size": 14533,
|
||||
"size": 14532,
|
||||
"category": "network",
|
||||
"icon": "filter",
|
||||
"description": "Traffic shaping and QoS",
|
||||
@ -558,7 +558,7 @@
|
||||
"name": "luci-app-vhost-manager",
|
||||
"version": "0.5.0-r5",
|
||||
"filename": "luci-app-vhost-manager_0.5.0-r5_all.ipk",
|
||||
"size": 26185,
|
||||
"size": 26187,
|
||||
"category": "network",
|
||||
"icon": "server",
|
||||
"description": "Virtual host management",
|
||||
@ -570,7 +570,7 @@
|
||||
"name": "luci-app-wireguard-dashboard",
|
||||
"version": "0.7.0-r5",
|
||||
"filename": "luci-app-wireguard-dashboard_0.7.0-r5_all.ipk",
|
||||
"size": 39607,
|
||||
"size": 39604,
|
||||
"category": "vpn",
|
||||
"icon": "shield",
|
||||
"description": "WireGuard VPN dashboard",
|
||||
@ -582,7 +582,7 @@
|
||||
"name": "luci-app-zigbee2mqtt",
|
||||
"version": "1.0.0-r2",
|
||||
"filename": "luci-app-zigbee2mqtt_1.0.0-r2_all.ipk",
|
||||
"size": 6813,
|
||||
"size": 6815,
|
||||
"category": "iot",
|
||||
"icon": "radio",
|
||||
"description": "Zigbee device management",
|
||||
@ -594,7 +594,7 @@
|
||||
"name": "luci-theme-secubox",
|
||||
"version": "0.4.7-r1",
|
||||
"filename": "luci-theme-secubox_0.4.7-r1_all.ipk",
|
||||
"size": 110242,
|
||||
"size": 110241,
|
||||
"category": "theme",
|
||||
"icon": "palette",
|
||||
"description": "LuCI theme",
|
||||
@ -618,7 +618,7 @@
|
||||
"name": "secubox-app-adguardhome",
|
||||
"version": "1.0.0-r2",
|
||||
"filename": "secubox-app-adguardhome_1.0.0-r2_all.ipk",
|
||||
"size": 2883,
|
||||
"size": 2880,
|
||||
"category": "secubox",
|
||||
"icon": "package",
|
||||
"description": "SecuBox backend service",
|
||||
@ -630,7 +630,7 @@
|
||||
"name": "secubox-app-auth-logger",
|
||||
"version": "1.2.2-r1",
|
||||
"filename": "secubox-app-auth-logger_1.2.2-r1_all.ipk",
|
||||
"size": 9379,
|
||||
"size": 9376,
|
||||
"category": "secubox",
|
||||
"icon": "package",
|
||||
"description": "SecuBox backend service",
|
||||
@ -654,7 +654,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": 5049328,
|
||||
"size": 5049322,
|
||||
"category": "secubox",
|
||||
"icon": "package",
|
||||
"description": "SecuBox backend service",
|
||||
@ -666,7 +666,7 @@
|
||||
"name": "secubox-app-cyberfeed",
|
||||
"version": "0.2.1-r1",
|
||||
"filename": "secubox-app-cyberfeed_0.2.1-r1_all.ipk",
|
||||
"size": 12452,
|
||||
"size": 12449,
|
||||
"category": "secubox",
|
||||
"icon": "package",
|
||||
"description": "SecuBox backend service",
|
||||
@ -678,7 +678,7 @@
|
||||
"name": "secubox-app-domoticz",
|
||||
"version": "1.0.0-r2",
|
||||
"filename": "secubox-app-domoticz_1.0.0-r2_all.ipk",
|
||||
"size": 2550,
|
||||
"size": 2544,
|
||||
"category": "secubox",
|
||||
"icon": "package",
|
||||
"description": "SecuBox backend service",
|
||||
@ -690,7 +690,7 @@
|
||||
"name": "secubox-app-exposure",
|
||||
"version": "1.0.0-r1",
|
||||
"filename": "secubox-app-exposure_1.0.0-r1_all.ipk",
|
||||
"size": 6938,
|
||||
"size": 6931,
|
||||
"category": "secubox",
|
||||
"icon": "package",
|
||||
"description": "SecuBox backend service",
|
||||
@ -702,7 +702,7 @@
|
||||
"name": "secubox-app-gitea",
|
||||
"version": "1.0.0-r5",
|
||||
"filename": "secubox-app-gitea_1.0.0-r5_all.ipk",
|
||||
"size": 9409,
|
||||
"size": 9406,
|
||||
"category": "secubox",
|
||||
"icon": "package",
|
||||
"description": "SecuBox backend service",
|
||||
@ -714,7 +714,7 @@
|
||||
"name": "secubox-app-glances",
|
||||
"version": "1.0.0-r1",
|
||||
"filename": "secubox-app-glances_1.0.0-r1_all.ipk",
|
||||
"size": 5542,
|
||||
"size": 5533,
|
||||
"category": "secubox",
|
||||
"icon": "package",
|
||||
"description": "SecuBox backend service",
|
||||
@ -726,7 +726,7 @@
|
||||
"name": "secubox-app-haproxy",
|
||||
"version": "1.0.0-r23",
|
||||
"filename": "secubox-app-haproxy_1.0.0-r23_all.ipk",
|
||||
"size": 15687,
|
||||
"size": 15681,
|
||||
"category": "secubox",
|
||||
"icon": "package",
|
||||
"description": "SecuBox backend service",
|
||||
@ -738,7 +738,7 @@
|
||||
"name": "secubox-app-hexojs",
|
||||
"version": "1.0.0-r8",
|
||||
"filename": "secubox-app-hexojs_1.0.0-r8_all.ipk",
|
||||
"size": 94937,
|
||||
"size": 94933,
|
||||
"category": "secubox",
|
||||
"icon": "package",
|
||||
"description": "SecuBox backend service",
|
||||
@ -750,7 +750,7 @@
|
||||
"name": "secubox-app-jitsi",
|
||||
"version": "1.0.0-r1",
|
||||
"filename": "secubox-app-jitsi_1.0.0-r1_all.ipk",
|
||||
"size": 8916,
|
||||
"size": 8914,
|
||||
"category": "secubox",
|
||||
"icon": "package",
|
||||
"description": "SecuBox backend service",
|
||||
@ -762,7 +762,7 @@
|
||||
"name": "secubox-app-localai",
|
||||
"version": "2.25.0-r1",
|
||||
"filename": "secubox-app-localai_2.25.0-r1_all.ipk",
|
||||
"size": 5718,
|
||||
"size": 5725,
|
||||
"category": "secubox",
|
||||
"icon": "package",
|
||||
"description": "SecuBox backend service",
|
||||
@ -774,7 +774,7 @@
|
||||
"name": "secubox-app-localai-wb",
|
||||
"version": "2.25.0-r1",
|
||||
"filename": "secubox-app-localai-wb_2.25.0-r1_all.ipk",
|
||||
"size": 7954,
|
||||
"size": 7951,
|
||||
"category": "secubox",
|
||||
"icon": "package",
|
||||
"description": "SecuBox backend service",
|
||||
@ -786,7 +786,7 @@
|
||||
"name": "secubox-app-lyrion",
|
||||
"version": "2.0.2-r1",
|
||||
"filename": "secubox-app-lyrion_2.0.2-r1_all.ipk",
|
||||
"size": 7288,
|
||||
"size": 7292,
|
||||
"category": "secubox",
|
||||
"icon": "package",
|
||||
"description": "SecuBox backend service",
|
||||
@ -798,7 +798,7 @@
|
||||
"name": "secubox-app-magicmirror2",
|
||||
"version": "0.4.0-r8",
|
||||
"filename": "secubox-app-magicmirror2_0.4.0-r8_all.ipk",
|
||||
"size": 9254,
|
||||
"size": 9250,
|
||||
"category": "secubox",
|
||||
"icon": "package",
|
||||
"description": "SecuBox backend service",
|
||||
@ -810,7 +810,7 @@
|
||||
"name": "secubox-app-mailinabox",
|
||||
"version": "2.0.0-r1",
|
||||
"filename": "secubox-app-mailinabox_2.0.0-r1_all.ipk",
|
||||
"size": 7573,
|
||||
"size": 7570,
|
||||
"category": "secubox",
|
||||
"icon": "package",
|
||||
"description": "SecuBox backend service",
|
||||
@ -834,7 +834,7 @@
|
||||
"name": "secubox-app-mitmproxy",
|
||||
"version": "0.5.0-r19",
|
||||
"filename": "secubox-app-mitmproxy_0.5.0-r19_all.ipk",
|
||||
"size": 22958,
|
||||
"size": 22956,
|
||||
"category": "secubox",
|
||||
"icon": "package",
|
||||
"description": "SecuBox backend service",
|
||||
@ -846,7 +846,7 @@
|
||||
"name": "secubox-app-mmpm",
|
||||
"version": "0.2.0-r5",
|
||||
"filename": "secubox-app-mmpm_0.2.0-r5_all.ipk",
|
||||
"size": 3982,
|
||||
"size": 3980,
|
||||
"category": "secubox",
|
||||
"icon": "package",
|
||||
"description": "SecuBox backend service",
|
||||
@ -858,7 +858,7 @@
|
||||
"name": "secubox-app-nextcloud",
|
||||
"version": "1.0.0-r2",
|
||||
"filename": "secubox-app-nextcloud_1.0.0-r2_all.ipk",
|
||||
"size": 2961,
|
||||
"size": 2959,
|
||||
"category": "secubox",
|
||||
"icon": "package",
|
||||
"description": "SecuBox backend service",
|
||||
@ -870,7 +870,7 @@
|
||||
"name": "secubox-app-ollama",
|
||||
"version": "0.1.0-r1",
|
||||
"filename": "secubox-app-ollama_0.1.0-r1_all.ipk",
|
||||
"size": 5737,
|
||||
"size": 5734,
|
||||
"category": "secubox",
|
||||
"icon": "package",
|
||||
"description": "SecuBox backend service",
|
||||
@ -882,7 +882,7 @@
|
||||
"name": "secubox-app-picobrew",
|
||||
"version": "1.0.0-r7",
|
||||
"filename": "secubox-app-picobrew_1.0.0-r7_all.ipk",
|
||||
"size": 5538,
|
||||
"size": 5539,
|
||||
"category": "secubox",
|
||||
"icon": "package",
|
||||
"description": "SecuBox backend service",
|
||||
@ -894,7 +894,7 @@
|
||||
"name": "secubox-app-simplex",
|
||||
"version": "1.0.0-r1",
|
||||
"filename": "secubox-app-simplex_1.0.0-r1_all.ipk",
|
||||
"size": 9233,
|
||||
"size": 9232,
|
||||
"category": "secubox",
|
||||
"icon": "package",
|
||||
"description": "SecuBox backend service",
|
||||
@ -906,7 +906,7 @@
|
||||
"name": "secubox-app-streamlit",
|
||||
"version": "1.0.0-r5",
|
||||
"filename": "secubox-app-streamlit_1.0.0-r5_all.ipk",
|
||||
"size": 11718,
|
||||
"size": 11723,
|
||||
"category": "secubox",
|
||||
"icon": "package",
|
||||
"description": "SecuBox backend service",
|
||||
@ -930,7 +930,7 @@
|
||||
"name": "secubox-app-webapp",
|
||||
"version": "1.5.0-r7",
|
||||
"filename": "secubox-app-webapp_1.5.0-r7_all.ipk",
|
||||
"size": 39174,
|
||||
"size": 39172,
|
||||
"category": "secubox",
|
||||
"icon": "package",
|
||||
"description": "SecuBox backend service",
|
||||
@ -942,7 +942,7 @@
|
||||
"name": "secubox-app-zigbee2mqtt",
|
||||
"version": "1.0.0-r3",
|
||||
"filename": "secubox-app-zigbee2mqtt_1.0.0-r3_all.ipk",
|
||||
"size": 3544,
|
||||
"size": 3545,
|
||||
"category": "secubox",
|
||||
"icon": "package",
|
||||
"description": "SecuBox backend service",
|
||||
@ -954,7 +954,7 @@
|
||||
"name": "secubox-core",
|
||||
"version": "0.10.0-r11",
|
||||
"filename": "secubox-core_0.10.0-r11_all.ipk",
|
||||
"size": 87973,
|
||||
"size": 87974,
|
||||
"category": "system",
|
||||
"icon": "box",
|
||||
"description": "SecuBox core components",
|
||||
@ -966,7 +966,7 @@
|
||||
"name": "secubox-master-link",
|
||||
"version": "1.0.0-r1",
|
||||
"filename": "secubox-master-link_1.0.0-r1_all.ipk",
|
||||
"size": 12455,
|
||||
"size": 12454,
|
||||
"category": "utility",
|
||||
"icon": "package",
|
||||
"description": "SecuBox package",
|
||||
@ -978,7 +978,7 @@
|
||||
"name": "secubox-p2p",
|
||||
"version": "0.6.0-r3",
|
||||
"filename": "secubox-p2p_0.6.0-r3_all.ipk",
|
||||
"size": 42015,
|
||||
"size": 42016,
|
||||
"category": "utility",
|
||||
"icon": "package",
|
||||
"description": "SecuBox package",
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
65
package/secubox/secubox-app-jellyfin/Makefile
Normal file
65
package/secubox/secubox-app-jellyfin/Makefile
Normal file
@ -0,0 +1,65 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=secubox-app-jellyfin
|
||||
PKG_VERSION:=1.0.0
|
||||
PKG_RELEASE:=1
|
||||
PKG_ARCH:=all
|
||||
PKG_MAINTAINER:=CyberMind Studio <contact@cybermind.fr>
|
||||
PKG_LICENSE:=Apache-2.0
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/secubox-app-jellyfin
|
||||
SECTION:=utils
|
||||
CATEGORY:=Utilities
|
||||
PKGARCH:=all
|
||||
SUBMENU:=SecuBox Apps
|
||||
TITLE:=SecuBox Jellyfin media server
|
||||
DEPENDS:=+dockerd +docker +containerd
|
||||
endef
|
||||
|
||||
define Package/secubox-app-jellyfin/description
|
||||
Installer, configuration, and service manager for running Jellyfin
|
||||
inside Docker on SecuBox-powered OpenWrt systems. Free media server
|
||||
for streaming movies, TV shows, music, and photos.
|
||||
endef
|
||||
|
||||
define Package/secubox-app-jellyfin/conffiles
|
||||
/etc/config/jellyfin
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
endef
|
||||
|
||||
define Package/secubox-app-jellyfin/install
|
||||
$(INSTALL_DIR) $(1)/etc/config
|
||||
$(INSTALL_CONF) ./files/etc/config/jellyfin $(1)/etc/config/jellyfin
|
||||
|
||||
$(INSTALL_DIR) $(1)/etc/init.d
|
||||
$(INSTALL_BIN) ./files/etc/init.d/jellyfin $(1)/etc/init.d/jellyfin
|
||||
|
||||
$(INSTALL_DIR) $(1)/usr/sbin
|
||||
$(INSTALL_BIN) ./files/usr/sbin/jellyfinctl $(1)/usr/sbin/jellyfinctl
|
||||
endef
|
||||
|
||||
define Package/secubox-app-jellyfin/postinst
|
||||
#!/bin/sh
|
||||
[ -n "$${IPKG_INSTROOT}" ] || {
|
||||
echo ""
|
||||
echo "============================================"
|
||||
echo " Jellyfin Media Server Installed"
|
||||
echo "============================================"
|
||||
echo ""
|
||||
echo "Quick Start:"
|
||||
echo " 1. Install: jellyfinctl install"
|
||||
echo " 2. Configure media: uci add_list jellyfin.media.media_path='/path/to/media'"
|
||||
echo " 3. Commit: uci commit jellyfin"
|
||||
echo " 4. Start: /etc/init.d/jellyfin start"
|
||||
echo ""
|
||||
echo "Web UI: http://<device-ip>:8096"
|
||||
echo ""
|
||||
}
|
||||
exit 0
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,secubox-app-jellyfin))
|
||||
@ -0,0 +1,15 @@
|
||||
config jellyfin 'main'
|
||||
option enabled '0'
|
||||
option image 'jellyfin/jellyfin:latest'
|
||||
option data_path '/srv/jellyfin'
|
||||
option port '8096'
|
||||
option timezone 'Europe/Paris'
|
||||
|
||||
config jellyfin 'media'
|
||||
# list media_path '/mnt/media/movies'
|
||||
# list media_path '/mnt/media/music'
|
||||
# list media_path '/mnt/media/shows'
|
||||
|
||||
config jellyfin 'transcoding'
|
||||
option hw_accel '0'
|
||||
option gpu_device ''
|
||||
@ -0,0 +1,28 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
|
||||
START=95
|
||||
STOP=10
|
||||
USE_PROCD=1
|
||||
|
||||
SERVICE_BIN="/usr/sbin/jellyfinctl"
|
||||
|
||||
start_service() {
|
||||
local enabled=$(uci -q get jellyfin.main.enabled)
|
||||
[ "$enabled" = "1" ] || return 0
|
||||
|
||||
procd_open_instance
|
||||
procd_set_param command "$SERVICE_BIN" service-run
|
||||
procd_set_param respawn 3600 5 5
|
||||
procd_set_param stdout 1
|
||||
procd_set_param stderr 1
|
||||
procd_close_instance
|
||||
}
|
||||
|
||||
stop_service() {
|
||||
"$SERVICE_BIN" service-stop >/dev/null 2>&1
|
||||
}
|
||||
|
||||
restart_service() {
|
||||
stop_service
|
||||
start_service
|
||||
}
|
||||
187
package/secubox/secubox-app-jellyfin/files/usr/sbin/jellyfinctl
Normal file
187
package/secubox/secubox-app-jellyfin/files/usr/sbin/jellyfinctl
Normal file
@ -0,0 +1,187 @@
|
||||
#!/bin/sh
|
||||
# SecuBox Jellyfin Media Server manager
|
||||
|
||||
CONFIG="jellyfin"
|
||||
CONTAINER="secbx-jellyfin"
|
||||
OPKG_UPDATED=0
|
||||
|
||||
usage() {
|
||||
cat <<'USAGE'
|
||||
Usage: jellyfinctl <command>
|
||||
|
||||
Commands:
|
||||
install Install prerequisites, prepare directories, pull image
|
||||
check Run prerequisite checks
|
||||
update Pull new image and restart
|
||||
status Show container status
|
||||
logs Show container logs (use -f to follow)
|
||||
shell Open shell inside container
|
||||
service-run Internal: run container via procd
|
||||
service-stop Stop container
|
||||
USAGE
|
||||
}
|
||||
|
||||
require_root() { [ "$(id -u)" -eq 0 ]; }
|
||||
|
||||
uci_get() { uci -q get ${CONFIG}.$1; }
|
||||
|
||||
defaults() {
|
||||
image="$(uci_get main.image)"
|
||||
[ -z "$image" ] && image="jellyfin/jellyfin:latest"
|
||||
data_path="$(uci_get main.data_path)"
|
||||
[ -z "$data_path" ] && data_path="/srv/jellyfin"
|
||||
port="$(uci_get main.port)"
|
||||
[ -z "$port" ] && port="8096"
|
||||
timezone="$(uci_get main.timezone)"
|
||||
[ -z "$timezone" ] && timezone="Europe/Paris"
|
||||
hw_accel="$(uci_get transcoding.hw_accel)"
|
||||
[ -z "$hw_accel" ] && hw_accel="0"
|
||||
gpu_device="$(uci_get transcoding.gpu_device)"
|
||||
}
|
||||
|
||||
ensure_dir() { [ -d "$1" ] || mkdir -p "$1"; }
|
||||
|
||||
ensure_packages() {
|
||||
for pkg in "$@"; do
|
||||
if ! opkg status "$pkg" 2>/dev/null | grep -q "Status:.*installed"; then
|
||||
if [ "$OPKG_UPDATED" -eq 0 ]; then
|
||||
opkg update || return 1
|
||||
OPKG_UPDATED=1
|
||||
fi
|
||||
opkg install "$pkg" || return 1
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
check_prereqs() {
|
||||
defaults
|
||||
ensure_dir "$data_path"
|
||||
[ -d /sys/fs/cgroup ] || { echo "[ERROR] /sys/fs/cgroup missing" >&2; return 1; }
|
||||
ensure_packages dockerd docker containerd
|
||||
/etc/init.d/dockerd enable >/dev/null 2>&1
|
||||
/etc/init.d/dockerd start >/dev/null 2>&1
|
||||
}
|
||||
|
||||
pull_image() { defaults; docker pull "$image"; }
|
||||
|
||||
stop_container() {
|
||||
docker stop "$CONTAINER" >/dev/null 2>&1 || true
|
||||
docker rm "$CONTAINER" >/dev/null 2>&1 || true
|
||||
}
|
||||
|
||||
build_media_mounts() {
|
||||
local mounts=""
|
||||
local paths
|
||||
paths=$(uci -q get ${CONFIG}.media.media_path)
|
||||
if [ -n "$paths" ]; then
|
||||
for p in $paths; do
|
||||
[ -d "$p" ] && mounts="$mounts -v ${p}:${p}:ro"
|
||||
done
|
||||
fi
|
||||
echo "$mounts"
|
||||
}
|
||||
|
||||
build_gpu_args() {
|
||||
if [ "$hw_accel" = "1" ]; then
|
||||
local dev="${gpu_device:-/dev/dri}"
|
||||
if [ -e "$dev" ]; then
|
||||
echo "--device=${dev}:${dev}"
|
||||
else
|
||||
echo ""
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
cmd_install() {
|
||||
require_root || { echo "Root required" >&2; exit 1; }
|
||||
echo "[Jellyfin] Installing prerequisites..."
|
||||
check_prereqs || exit 1
|
||||
ensure_dir "$data_path/config"
|
||||
ensure_dir "$data_path/cache"
|
||||
echo "[Jellyfin] Pulling Docker image..."
|
||||
pull_image || exit 1
|
||||
uci set ${CONFIG}.main.enabled='1'
|
||||
uci commit ${CONFIG}
|
||||
/etc/init.d/jellyfin enable
|
||||
echo ""
|
||||
echo "Jellyfin installed successfully."
|
||||
echo "Configure media paths:"
|
||||
echo " uci add_list jellyfin.media.media_path='/path/to/media'"
|
||||
echo " uci commit jellyfin"
|
||||
echo "Start with: /etc/init.d/jellyfin start"
|
||||
echo "Web UI: http://<device-ip>:${port}"
|
||||
}
|
||||
|
||||
cmd_check() { check_prereqs; echo "Prerequisite check completed."; }
|
||||
|
||||
cmd_update() {
|
||||
require_root || { echo "Root required" >&2; exit 1; }
|
||||
echo "[Jellyfin] Pulling latest image..."
|
||||
pull_image || exit 1
|
||||
echo "[Jellyfin] Restarting..."
|
||||
/etc/init.d/jellyfin restart
|
||||
}
|
||||
|
||||
cmd_status() {
|
||||
defaults
|
||||
echo "Jellyfin Media Server"
|
||||
echo "====================="
|
||||
echo " Image: $image"
|
||||
echo " Port: $port"
|
||||
echo " Data: $data_path"
|
||||
echo ""
|
||||
if docker ps --filter "name=$CONTAINER" --format '{{.Status}}' 2>/dev/null | grep -q .; then
|
||||
echo " Container: RUNNING"
|
||||
docker ps --filter "name=$CONTAINER" --format ' Uptime: {{.Status}}'
|
||||
elif docker ps -a --filter "name=$CONTAINER" --format '{{.Status}}' 2>/dev/null | grep -q .; then
|
||||
echo " Container: STOPPED"
|
||||
else
|
||||
echo " Container: NOT INSTALLED"
|
||||
fi
|
||||
}
|
||||
|
||||
cmd_logs() { docker logs "$@" "$CONTAINER" 2>&1; }
|
||||
|
||||
cmd_shell() { docker exec -it "$CONTAINER" /bin/bash 2>/dev/null || docker exec -it "$CONTAINER" /bin/sh; }
|
||||
|
||||
cmd_service_run() {
|
||||
require_root || { echo "Root required" >&2; exit 1; }
|
||||
check_prereqs || exit 1
|
||||
defaults
|
||||
stop_container
|
||||
|
||||
local media_mounts
|
||||
media_mounts=$(build_media_mounts)
|
||||
|
||||
local gpu_args
|
||||
gpu_args=$(build_gpu_args)
|
||||
|
||||
local docker_args="--name $CONTAINER"
|
||||
docker_args="$docker_args -p ${port}:8096"
|
||||
docker_args="$docker_args -v ${data_path}/config:/config"
|
||||
docker_args="$docker_args -v ${data_path}/cache:/cache"
|
||||
docker_args="$docker_args -e TZ=${timezone}"
|
||||
|
||||
# shellcheck disable=SC2086
|
||||
exec docker run --rm $docker_args $media_mounts $gpu_args "$image"
|
||||
}
|
||||
|
||||
cmd_service_stop() {
|
||||
require_root || { echo "Root required" >&2; exit 1; }
|
||||
stop_container
|
||||
}
|
||||
|
||||
case "${1:-}" in
|
||||
install) shift; cmd_install "$@" ;;
|
||||
check) shift; cmd_check "$@" ;;
|
||||
update) shift; cmd_update "$@" ;;
|
||||
status) shift; cmd_status "$@" ;;
|
||||
logs) shift; cmd_logs "$@" ;;
|
||||
shell) shift; cmd_shell "$@" ;;
|
||||
service-run) shift; cmd_service_run "$@" ;;
|
||||
service-stop) shift; cmd_service_stop "$@" ;;
|
||||
help|--help|-h|'') usage ;;
|
||||
*) echo "Unknown command: $1" >&2; usage >&2; exit 1 ;;
|
||||
esac
|
||||
|
||||
exit 0
|
||||
Loading…
Reference in New Issue
Block a user