commit
aeda39b516
@ -122,7 +122,24 @@
|
||||
"Bash(gh run:*)",
|
||||
"Bash(dig:*)",
|
||||
"Bash(nslookup:*)",
|
||||
"Bash(host:*)"
|
||||
"Bash(host:*)",
|
||||
"Bash(git fetch:*)",
|
||||
"Bash(/home/reepost/CyberMindStudio/secubox-openwrt/secubox-tools/deploy-remote.sh:*)",
|
||||
"Bash(for i in 1 2 3 4 5)",
|
||||
"Bash(do echo \"Attempt $i...\")",
|
||||
"Bash(if ssh -o ConnectTimeout=10 root@192.168.255.1 'echo \"\"Connected\"\"; df -h /')",
|
||||
"Bash(then break)",
|
||||
"Bash(fi)",
|
||||
"Bash(done)",
|
||||
"Bash(for i in 1 2 3 4 5 6)",
|
||||
"Bash(do echo \"Checking... \\($i\\)\")",
|
||||
"Bash(if ssh -o ConnectTimeout=10 root@192.168.255.1 'df -h / /overlay 2>/dev/null')",
|
||||
"Bash(./secubox-tools/deploy-remote.sh:*)",
|
||||
"Bash(do)",
|
||||
"Bash(if ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no root@192.168.255.1 \"echo ''Router is back!''\")",
|
||||
"Bash(then)",
|
||||
"Bash(exit 0)",
|
||||
"Bash(if ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no root@192.168.255.1 \"echo ''Router online!''\")"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=luci-app-crowdsec-dashboard
|
||||
PKG_VERSION:=0.7.0
|
||||
PKG_RELEASE:=28
|
||||
PKG_RELEASE:=29
|
||||
PKG_ARCH:=all
|
||||
|
||||
PKG_LICENSE:=Apache-2.0
|
||||
|
||||
@ -181,14 +181,14 @@ get_status() {
|
||||
elif ! grep -q "password:" "$creds_file" 2>/dev/null; then
|
||||
lapi_reason="credentials incomplete"
|
||||
else
|
||||
# Check if LAPI port is listening (8080 hex = 1F90)
|
||||
# Check if LAPI port is listening (8180 hex = 1FF4)
|
||||
local port_up=0
|
||||
if grep -qi ":1F90 " /proc/net/tcp 2>/dev/null; then
|
||||
if grep -qi ":1FF4 " /proc/net/tcp 2>/dev/null; then
|
||||
port_up=1
|
||||
fi
|
||||
|
||||
if [ "$port_up" = "0" ]; then
|
||||
lapi_reason="port 8080 not listening"
|
||||
lapi_reason="port 8180 not listening"
|
||||
else
|
||||
# Try actual LAPI status check
|
||||
if run_cscli lapi status >/dev/null 2>&1; then
|
||||
@ -746,7 +746,7 @@ get_firewall_bouncer_config() {
|
||||
val=$(uci -q get crowdsec.bouncer.ipv6 || echo "1")
|
||||
json_add_string "ipv6" "$val"
|
||||
|
||||
val=$(uci -q get crowdsec.bouncer.api_url || echo "http://127.0.0.1:8080/")
|
||||
val=$(uci -q get crowdsec.bouncer.api_url || echo "http://127.0.0.1:8180/")
|
||||
json_add_string "api_url" "$val"
|
||||
|
||||
val=$(uci -q get crowdsec.bouncer.update_frequency || echo "10s")
|
||||
@ -1822,7 +1822,7 @@ get_health_check() {
|
||||
|
||||
# LAPI status
|
||||
local lapi_status="unavailable"
|
||||
local lapi_url="http://127.0.0.1:8080"
|
||||
local lapi_url="http://127.0.0.1:8180"
|
||||
if [ -x "$CSCLI" ]; then
|
||||
if run_with_timeout 5 "$CSCLI" lapi status >/dev/null 2>&1; then
|
||||
lapi_status="available"
|
||||
|
||||
0
package/secubox/luci-app-cyberfeed/root/usr/libexec/rpcd/luci.cyberfeed
Normal file → Executable file
0
package/secubox/luci-app-cyberfeed/root/usr/libexec/rpcd/luci.cyberfeed
Normal file → Executable file
0
package/secubox/luci-app-gitea/root/usr/libexec/rpcd/luci.gitea
Normal file → Executable file
0
package/secubox/luci-app-gitea/root/usr/libexec/rpcd/luci.gitea
Normal file → Executable file
0
package/secubox/luci-app-glances/root/usr/libexec/rpcd/luci.glances
Normal file → Executable file
0
package/secubox/luci-app-glances/root/usr/libexec/rpcd/luci.glances
Normal file → Executable file
0
package/secubox/luci-app-haproxy/root/usr/libexec/rpcd/luci.haproxy
Normal file → Executable file
0
package/secubox/luci-app-haproxy/root/usr/libexec/rpcd/luci.haproxy
Normal file → Executable file
@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=luci-app-hexojs
|
||||
PKG_VERSION:=1.0.0
|
||||
PKG_RELEASE:=2
|
||||
PKG_RELEASE:=3
|
||||
PKG_ARCH:=all
|
||||
|
||||
PKG_LICENSE:=MIT
|
||||
|
||||
@ -154,6 +154,13 @@ var callDeployStatus = rpc.declare({
|
||||
expect: {}
|
||||
});
|
||||
|
||||
var callPublishToWww = rpc.declare({
|
||||
object: 'luci.hexojs',
|
||||
method: 'publish_to_www',
|
||||
params: ['path'],
|
||||
expect: {}
|
||||
});
|
||||
|
||||
// ============================================
|
||||
// Preview
|
||||
// ============================================
|
||||
@ -478,6 +485,7 @@ return baseclass.extend({
|
||||
clean: callClean,
|
||||
deploy: callDeploy,
|
||||
getDeployStatus: callDeployStatus,
|
||||
publishToWww: callPublishToWww,
|
||||
|
||||
// Preview
|
||||
previewStart: callPreviewStart,
|
||||
|
||||
@ -28,6 +28,19 @@ var callGiteaSaveConfig = rpc.declare({
|
||||
params: ['enabled', 'gitea_url', 'gitea_user', 'gitea_token', 'content_repo', 'content_branch', 'auto_sync']
|
||||
});
|
||||
|
||||
var callBuild = rpc.declare({
|
||||
object: 'luci.hexojs',
|
||||
method: 'generate',
|
||||
expect: {}
|
||||
});
|
||||
|
||||
var callPublishToWww = rpc.declare({
|
||||
object: 'luci.hexojs',
|
||||
method: 'publish_to_www',
|
||||
params: ['path'],
|
||||
expect: {}
|
||||
});
|
||||
|
||||
return view.extend({
|
||||
title: _('Content Sync'),
|
||||
wizardStep: 0,
|
||||
@ -210,6 +223,50 @@ return view.extend({
|
||||
});
|
||||
},
|
||||
|
||||
// ============================================
|
||||
// Build & Publish Actions
|
||||
// ============================================
|
||||
|
||||
handleBuild: function() {
|
||||
ui.showModal(_('Building Site'), [
|
||||
E('p', { 'class': 'spinning' }, _('Generating static files...'))
|
||||
]);
|
||||
|
||||
callBuild().then(function(result) {
|
||||
ui.hideModal();
|
||||
if (result.success) {
|
||||
ui.addNotification(null, E('p', _('Site built successfully!')), 'info');
|
||||
} else {
|
||||
ui.addNotification(null, E('p', result.error || _('Build failed')), 'error');
|
||||
}
|
||||
}).catch(function(err) {
|
||||
ui.hideModal();
|
||||
ui.addNotification(null, E('p', _('Error: %s').format(err.message || err)), 'error');
|
||||
});
|
||||
},
|
||||
|
||||
handlePublish: function() {
|
||||
var self = this;
|
||||
var path = document.querySelector('#publish-path');
|
||||
var publishPath = path ? path.value : '/www/blog';
|
||||
|
||||
ui.showModal(_('Publishing Site'), [
|
||||
E('p', { 'class': 'spinning' }, _('Building and publishing to %s...').format(publishPath))
|
||||
]);
|
||||
|
||||
callPublishToWww(publishPath).then(function(result) {
|
||||
ui.hideModal();
|
||||
if (result.success) {
|
||||
ui.addNotification(null, E('p', _('Published to %s!').format(result.path || publishPath)), 'info');
|
||||
} else {
|
||||
ui.addNotification(null, E('p', result.error || _('Publish failed')), 'error');
|
||||
}
|
||||
}).catch(function(err) {
|
||||
ui.hideModal();
|
||||
ui.addNotification(null, E('p', _('Error: %s').format(err.message || err)), 'error');
|
||||
});
|
||||
},
|
||||
|
||||
// ============================================
|
||||
// Gitea Actions
|
||||
// ============================================
|
||||
@ -297,6 +354,49 @@ return view.extend({
|
||||
]) : ''
|
||||
]),
|
||||
|
||||
// Build & Publish Card
|
||||
E('div', { 'class': 'hexo-card' }, [
|
||||
E('div', { 'class': 'hexo-card-header' }, [
|
||||
E('div', { 'class': 'hexo-card-title' }, [
|
||||
E('span', { 'style': 'margin-right: 8px;' }, '\uD83D\uDE80'),
|
||||
_('Build & Publish')
|
||||
])
|
||||
]),
|
||||
E('p', { 'style': 'margin-bottom: 16px; color: var(--hexo-text-muted);' },
|
||||
_('Build static files and publish to web server.')),
|
||||
E('div', { 'style': 'display: grid; grid-template-columns: 1fr 1fr; gap: 16px;' }, [
|
||||
// Build Section
|
||||
E('div', { 'class': 'hexo-card', 'style': 'background: var(--hexo-bg-input);' }, [
|
||||
E('h4', { 'style': 'margin-bottom: 8px;' }, ['\uD83D\uDD28 ', _('Build')]),
|
||||
E('p', { 'style': 'font-size: 13px; color: var(--hexo-text-muted); margin-bottom: 12px;' },
|
||||
_('Generate static HTML files from your content.')),
|
||||
E('button', {
|
||||
'class': 'hexo-btn hexo-btn-primary',
|
||||
'click': function() { self.handleBuild(); }
|
||||
}, _('Build Site'))
|
||||
]),
|
||||
// Publish Section
|
||||
E('div', { 'class': 'hexo-card', 'style': 'background: var(--hexo-bg-input);' }, [
|
||||
E('h4', { 'style': 'margin-bottom: 8px;' }, ['\uD83C\uDF10 ', _('Publish')]),
|
||||
E('p', { 'style': 'font-size: 13px; color: var(--hexo-text-muted); margin-bottom: 12px;' },
|
||||
_('Copy built files to web server directory.')),
|
||||
E('div', { 'class': 'hexo-form-group', 'style': 'margin-bottom: 8px;' }, [
|
||||
E('input', {
|
||||
'type': 'text',
|
||||
'id': 'publish-path',
|
||||
'class': 'hexo-input',
|
||||
'value': '/www/blog',
|
||||
'placeholder': '/www/blog'
|
||||
})
|
||||
]),
|
||||
E('button', {
|
||||
'class': 'hexo-btn hexo-btn-success',
|
||||
'click': function() { self.handlePublish(); }
|
||||
}, _('Publish to Web'))
|
||||
])
|
||||
])
|
||||
]),
|
||||
|
||||
// Gitea Integration Card
|
||||
E('div', { 'class': 'hexo-card' }, [
|
||||
E('div', { 'class': 'hexo-card-header' }, [
|
||||
|
||||
43
package/secubox/luci-app-hexojs/root/usr/libexec/rpcd/luci.hexojs
Normal file → Executable file
43
package/secubox/luci-app-hexojs/root/usr/libexec/rpcd/luci.hexojs
Normal file → Executable file
@ -1544,6 +1544,45 @@ gitea_save_config() {
|
||||
json_dump
|
||||
}
|
||||
|
||||
# Publish to /www (portal)
|
||||
publish_to_www() {
|
||||
read input
|
||||
json_load "$input"
|
||||
json_get_var path path
|
||||
|
||||
json_init
|
||||
|
||||
if ! is_running; then
|
||||
json_add_boolean "success" 0
|
||||
json_add_string "error" "Container not running"
|
||||
json_dump
|
||||
return
|
||||
fi
|
||||
|
||||
# Default path is /www/blog
|
||||
[ -z "$path" ] && path="/www/blog"
|
||||
|
||||
# Set portal path in UCI for hexoctl
|
||||
uci set hexojs.portal=hexojs
|
||||
uci set hexojs.portal.path="$path"
|
||||
uci commit hexojs
|
||||
|
||||
# Run publish command
|
||||
local output=$("$HEXOCTL" publish 2>&1)
|
||||
local result=$?
|
||||
|
||||
if [ "$result" -eq 0 ]; then
|
||||
json_add_boolean "success" 1
|
||||
json_add_string "message" "Published to $path"
|
||||
json_add_string "path" "$path"
|
||||
else
|
||||
json_add_boolean "success" 0
|
||||
json_add_string "error" "$output"
|
||||
fi
|
||||
|
||||
json_dump
|
||||
}
|
||||
|
||||
# ============================================
|
||||
# Service Control
|
||||
# ============================================
|
||||
@ -1634,7 +1673,8 @@ case "$1" in
|
||||
"gitea_setup": {},
|
||||
"gitea_clone": {},
|
||||
"gitea_sync": {},
|
||||
"gitea_save_config": {"enabled": "bool", "gitea_url": "str", "gitea_user": "str", "gitea_token": "str", "content_repo": "str", "content_branch": "str", "auto_sync": "bool"}
|
||||
"gitea_save_config": {"enabled": "bool", "gitea_url": "str", "gitea_user": "str", "gitea_token": "str", "content_repo": "str", "content_branch": "str", "auto_sync": "bool"},
|
||||
"publish_to_www": {"path": "str"}
|
||||
}
|
||||
EOF
|
||||
;;
|
||||
@ -1686,6 +1726,7 @@ EOF
|
||||
gitea_clone) gitea_clone ;;
|
||||
gitea_sync) gitea_sync ;;
|
||||
gitea_save_config) gitea_save_config ;;
|
||||
publish_to_www) publish_to_www ;;
|
||||
*) echo '{"error": "Unknown method"}' ;;
|
||||
esac
|
||||
;;
|
||||
|
||||
@ -56,7 +56,8 @@
|
||||
"gitea_setup",
|
||||
"gitea_clone",
|
||||
"gitea_sync",
|
||||
"gitea_save_config"
|
||||
"gitea_save_config",
|
||||
"publish_to_www"
|
||||
]
|
||||
},
|
||||
"uci": ["hexojs"]
|
||||
|
||||
0
package/secubox/luci-app-localai/root/usr/libexec/rpcd/luci.localai
Normal file → Executable file
0
package/secubox/luci-app-localai/root/usr/libexec/rpcd/luci.localai
Normal file → Executable file
0
package/secubox/luci-app-magicmirror2/root/usr/libexec/rpcd/luci.magicmirror2
Normal file → Executable file
0
package/secubox/luci-app-magicmirror2/root/usr/libexec/rpcd/luci.magicmirror2
Normal file → Executable file
0
package/secubox/luci-app-metabolizer/root/usr/libexec/rpcd/luci.metabolizer
Normal file → Executable file
0
package/secubox/luci-app-metabolizer/root/usr/libexec/rpcd/luci.metabolizer
Normal file → Executable file
0
package/secubox/luci-app-mmpm/root/usr/libexec/rpcd/luci.mmpm
Normal file → Executable file
0
package/secubox/luci-app-mmpm/root/usr/libexec/rpcd/luci.mmpm
Normal file → Executable file
0
package/secubox/luci-app-ollama/root/usr/libexec/rpcd/luci.ollama
Normal file → Executable file
0
package/secubox/luci-app-ollama/root/usr/libexec/rpcd/luci.ollama
Normal file → Executable file
0
package/secubox/luci-app-picobrew/root/usr/libexec/rpcd/luci.picobrew
Normal file → Executable file
0
package/secubox/luci-app-picobrew/root/usr/libexec/rpcd/luci.picobrew
Normal file → Executable file
0
package/secubox/luci-app-streamlit/root/usr/libexec/rpcd/luci.streamlit
Normal file → Executable file
0
package/secubox/luci-app-streamlit/root/usr/libexec/rpcd/luci.streamlit
Normal file → Executable file
0
package/secubox/luci-app-tor-shield/root/usr/libexec/rpcd/luci.tor-shield
Normal file → Executable file
0
package/secubox/luci-app-tor-shield/root/usr/libexec/rpcd/luci.tor-shield
Normal file → Executable file
@ -10,7 +10,7 @@ include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=secubox-app-cs-firewall-bouncer
|
||||
PKG_VERSION:=0.0.31
|
||||
PKG_RELEASE:=3
|
||||
PKG_RELEASE:=4
|
||||
|
||||
# Source from upstream CrowdSec
|
||||
# Note: v0.0.31 is the last version compatible with Go 1.23 (OpenWrt 24.10 SDK)
|
||||
|
||||
@ -88,7 +88,7 @@ merge_config() {
|
||||
uci set crowdsec.bouncer.enabled='0'
|
||||
uci set crowdsec.bouncer.ipv4='1'
|
||||
uci set crowdsec.bouncer.ipv6='1'
|
||||
uci set crowdsec.bouncer.api_url='http://127.0.0.1:8080/'
|
||||
uci set crowdsec.bouncer.api_url='http://127.0.0.1:8180/'
|
||||
uci set crowdsec.bouncer.update_frequency='10s'
|
||||
uci set crowdsec.bouncer.deny_action='drop'
|
||||
uci set crowdsec.bouncer.deny_log='1'
|
||||
|
||||
@ -50,7 +50,7 @@ init_yaml() {
|
||||
config_get hook_priority $section priority "4"
|
||||
config_get update_frequency $section update_frequency '10s'
|
||||
config_get log_level $section log_level 'info'
|
||||
config_get api_url $section api_url "http://127.0.0.1:8080"
|
||||
config_get api_url $section api_url "http://127.0.0.1:8180"
|
||||
config_get api_key $section api_key "API_KEY"
|
||||
config_get_bool ipv6 $section ipv6 '1'
|
||||
config_get deny_action $section deny_action "drop"
|
||||
|
||||
@ -8,7 +8,7 @@ config bouncer
|
||||
option enabled '0'
|
||||
option ipv4 '1'
|
||||
option ipv6 '1'
|
||||
option api_url 'http://127.0.0.1:8080/'
|
||||
option api_url 'http://127.0.0.1:8180/'
|
||||
option api_key ''
|
||||
option update_frequency '10s'
|
||||
option priority '4'
|
||||
|
||||
0
package/secubox/secubox-app-cyberfeed/files/etc/init.d/cyberfeed
Normal file → Executable file
0
package/secubox/secubox-app-cyberfeed/files/etc/init.d/cyberfeed
Normal file → Executable file
0
package/secubox/secubox-app-gitea/files/etc/init.d/gitea
Normal file → Executable file
0
package/secubox/secubox-app-gitea/files/etc/init.d/gitea
Normal file → Executable file
0
package/secubox/secubox-app-glances/files/etc/init.d/glances
Normal file → Executable file
0
package/secubox/secubox-app-glances/files/etc/init.d/glances
Normal file → Executable file
@ -6,7 +6,7 @@ include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=secubox-app-haproxy
|
||||
PKG_VERSION:=1.0.0
|
||||
PKG_RELEASE:=19
|
||||
PKG_RELEASE:=21
|
||||
|
||||
PKG_MAINTAINER:=CyberMind <contact@cybermind.fr>
|
||||
PKG_LICENSE:=MIT
|
||||
|
||||
0
package/secubox/secubox-app-haproxy/files/etc/init.d/haproxy
Normal file → Executable file
0
package/secubox/secubox-app-haproxy/files/etc/init.d/haproxy
Normal file → Executable file
@ -19,6 +19,7 @@ CONFIG_PATH="$DATA_PATH/config"
|
||||
|
||||
# Logging
|
||||
log_info() { echo "[INFO] $*"; logger -t haproxy "$*"; }
|
||||
log_warn() { echo "[WARN] $*" >&2; logger -t haproxy -p warning "$*"; }
|
||||
log_error() { echo "[ERROR] $*" >&2; logger -t haproxy -p err "$*"; }
|
||||
log_debug() { [ "$DEBUG" = "1" ] && echo "[DEBUG] $*"; }
|
||||
|
||||
@ -44,6 +45,7 @@ load_config() {
|
||||
memory_limit="$(uci_get main.memory_limit)" || memory_limit="256M"
|
||||
maxconn="$(uci_get main.maxconn)" || maxconn="4096"
|
||||
log_level="$(uci_get main.log_level)" || log_level="warning"
|
||||
default_backend="$(uci_get main.default_backend)" || default_backend="default_luci"
|
||||
|
||||
CERTS_PATH="$data_path/certs"
|
||||
CONFIG_PATH="$data_path/config"
|
||||
@ -288,11 +290,12 @@ frontend stats
|
||||
frontend http-in
|
||||
bind *:80
|
||||
mode http
|
||||
default_backend fallback
|
||||
default_backend default_luci
|
||||
|
||||
backend fallback
|
||||
backend default_luci
|
||||
mode http
|
||||
server local 127.0.0.1:8080 check
|
||||
balance roundrobin
|
||||
server luci 192.168.255.1:8081 check
|
||||
CFGEOF
|
||||
fi
|
||||
|
||||
@ -415,7 +418,7 @@ EOF
|
||||
# Add vhost ACLs for HTTP
|
||||
config_foreach _add_vhost_acl vhost "http"
|
||||
|
||||
echo " default_backend fallback"
|
||||
echo " default_backend $default_backend"
|
||||
echo ""
|
||||
|
||||
# HTTPS Frontend (if certificates exist)
|
||||
@ -432,7 +435,7 @@ EOF
|
||||
# Add vhost ACLs for HTTPS
|
||||
config_foreach _add_vhost_acl vhost "https"
|
||||
|
||||
echo " default_backend fallback"
|
||||
echo " default_backend $default_backend"
|
||||
echo ""
|
||||
fi
|
||||
}
|
||||
@ -481,18 +484,43 @@ _add_vhost_acl() {
|
||||
_generate_backends() {
|
||||
config_load haproxy
|
||||
|
||||
# Track which backends are generated
|
||||
_generated_backends=""
|
||||
|
||||
# Generate each backend from UCI
|
||||
config_foreach _generate_backend backend
|
||||
|
||||
# Only add default fallback if no "fallback" backend exists in UCI
|
||||
if ! uci -q get haproxy.fallback >/dev/null 2>&1; then
|
||||
# Collect all backends referenced by vhosts
|
||||
_referenced_backends=""
|
||||
_collect_vhost_backend() {
|
||||
local section="$1"
|
||||
local enabled backend
|
||||
config_get enabled "$section" enabled "0"
|
||||
[ "$enabled" = "1" ] || return
|
||||
config_get backend "$section" backend
|
||||
[ -n "$backend" ] && _referenced_backends="$_referenced_backends $backend"
|
||||
}
|
||||
config_foreach _collect_vhost_backend vhost
|
||||
|
||||
# Add default_backend to referenced list
|
||||
_referenced_backends="$_referenced_backends $default_backend"
|
||||
|
||||
# Generate fallback backends for any referenced but not generated
|
||||
# These common backends route to uhttpd on the host
|
||||
for backend_name in default_luci luci apps; do
|
||||
# Check if this backend is referenced
|
||||
echo "$_referenced_backends" | grep -qw "$backend_name" || continue
|
||||
# Check if already generated
|
||||
echo "$_generated_backends" | grep -qw "$backend_name" && continue
|
||||
# Generate fallback
|
||||
cat << EOF
|
||||
|
||||
backend fallback
|
||||
backend $backend_name
|
||||
mode http
|
||||
http-request deny deny_status 503
|
||||
balance roundrobin
|
||||
server $backend_name 192.168.255.1:8081 check
|
||||
EOF
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
_generate_backend() {
|
||||
@ -507,6 +535,9 @@ _generate_backend() {
|
||||
config_get balance "$section" balance "roundrobin"
|
||||
config_get health_check "$section" health_check ""
|
||||
|
||||
# Track generated backend
|
||||
_generated_backends="$_generated_backends $name"
|
||||
|
||||
echo ""
|
||||
echo "backend $name"
|
||||
echo " mode $mode"
|
||||
@ -759,7 +790,7 @@ cmd_cert_add() {
|
||||
# Register account if needed
|
||||
if [ ! -f "$LE_WORKING_DIR/account.conf" ]; then
|
||||
log_info "Registering ACME account..."
|
||||
"$ACME_SH" --register-account -m "$email" $staging_flag --home "$LE_WORKING_DIR" || true
|
||||
"$ACME_SH" --register-account -m "$email" --server letsencrypt $staging_flag --home "$LE_WORKING_DIR" || true
|
||||
fi
|
||||
|
||||
# Check if HAProxy is using the port
|
||||
@ -775,6 +806,7 @@ cmd_cert_add() {
|
||||
log_info "Issuing certificate (standalone mode on port $http_port)..."
|
||||
local acme_result=0
|
||||
"$ACME_SH" --issue -d "$domain" \
|
||||
--server letsencrypt \
|
||||
--standalone --httpport "$http_port" \
|
||||
--keylength "$key_type" \
|
||||
$staging_flag \
|
||||
|
||||
@ -45,7 +45,7 @@ frontend http-in
|
||||
|
||||
# Default: redirect to HTTPS
|
||||
http-request redirect scheme https code 301 unless is_acme
|
||||
default_backend fallback
|
||||
default_backend default_luci
|
||||
|
||||
# HTTPS frontend - SSL termination
|
||||
frontend https-in
|
||||
@ -62,14 +62,15 @@ frontend https-in
|
||||
http-request set-header X-Real-IP %[src]
|
||||
http-request set-header X-Forwarded-For %[src]
|
||||
|
||||
default_backend fallback
|
||||
default_backend default_luci
|
||||
|
||||
# ACME challenge backend
|
||||
backend acme
|
||||
mode http
|
||||
server acme 127.0.0.1:8080 check
|
||||
|
||||
# Fallback backend
|
||||
backend fallback
|
||||
# Default LuCI backend - routes to uhttpd
|
||||
backend default_luci
|
||||
mode http
|
||||
http-request deny deny_status 503
|
||||
balance roundrobin
|
||||
server luci 192.168.255.1:8081 check
|
||||
|
||||
@ -8,7 +8,7 @@ include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=secubox-app-hexojs
|
||||
PKG_VERSION:=1.0.0
|
||||
PKG_RELEASE:=6
|
||||
PKG_RELEASE:=8
|
||||
PKG_ARCH:=all
|
||||
|
||||
PKG_MAINTAINER:=CyberMind Studio <contact@cybermind.fr>
|
||||
|
||||
0
package/secubox/secubox-app-hexojs/files/etc/init.d/hexojs
Normal file → Executable file
0
package/secubox/secubox-app-hexojs/files/etc/init.d/hexojs
Normal file → Executable file
File diff suppressed because it is too large
Load Diff
0
package/secubox/secubox-app-localai/files/etc/init.d/localai
Normal file → Executable file
0
package/secubox/secubox-app-localai/files/etc/init.d/localai
Normal file → Executable file
0
package/secubox/secubox-app-magicmirror2/files/etc/init.d/magicmirror2
Normal file → Executable file
0
package/secubox/secubox-app-magicmirror2/files/etc/init.d/magicmirror2
Normal file → Executable file
0
package/secubox/secubox-app-metabolizer/files/etc/init.d/metabolizer
Normal file → Executable file
0
package/secubox/secubox-app-metabolizer/files/etc/init.d/metabolizer
Normal file → Executable file
0
package/secubox/secubox-app-mmpm/files/etc/init.d/mmpm
Normal file → Executable file
0
package/secubox/secubox-app-mmpm/files/etc/init.d/mmpm
Normal file → Executable file
0
package/secubox/secubox-app-ollama/files/etc/init.d/ollama
Normal file → Executable file
0
package/secubox/secubox-app-ollama/files/etc/init.d/ollama
Normal file → Executable file
0
package/secubox/secubox-app-picobrew/files/etc/init.d/picobrew
Normal file → Executable file
0
package/secubox/secubox-app-picobrew/files/etc/init.d/picobrew
Normal file → Executable file
@ -8,7 +8,7 @@ include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=secubox-app-streamlit
|
||||
PKG_VERSION:=1.0.0
|
||||
PKG_RELEASE:=4
|
||||
PKG_RELEASE:=5
|
||||
PKG_ARCH:=all
|
||||
|
||||
PKG_MAINTAINER:=CyberMind Studio <contact@cybermind.fr>
|
||||
@ -22,22 +22,25 @@ define Package/secubox-app-streamlit
|
||||
PKGARCH:=all
|
||||
SUBMENU:=SecuBox Apps
|
||||
TITLE:=SecuBox Streamlit Platform
|
||||
DEPENDS:=+uci +libuci +jsonfilter +wget-ssl +tar +lxc +lxc-common
|
||||
DEPENDS:=+uci +libuci +jsonfilter +wget-ssl +tar +lxc +lxc-common +git
|
||||
endef
|
||||
|
||||
define Package/secubox-app-streamlit/description
|
||||
Streamlit App Platform - Self-hosted Python data app platform
|
||||
|
||||
Features:
|
||||
- Run Streamlit apps in LXC container
|
||||
- Folder-based app structure (app.py, requirements.txt, .streamlit/)
|
||||
- Multi-instance support (multiple apps on different ports)
|
||||
- Python 3.12 with Streamlit 1.53.x
|
||||
- Auto-install requirements.txt dependencies
|
||||
- Gitea integration for app deployment and updates
|
||||
- Python 3.12 with Streamlit in LXC container
|
||||
- Auto-install requirements.txt with hash-based caching
|
||||
- HAProxy publish wizard for vhost routing
|
||||
- Web dashboard integration
|
||||
- Configurable port and memory limits
|
||||
|
||||
Runs in LXC container with Alpine Linux.
|
||||
App folder structure:
|
||||
/srv/streamlit/apps/<appname>/
|
||||
app.py, requirements.txt, .streamlit/
|
||||
|
||||
Configure in /etc/config/streamlit.
|
||||
endef
|
||||
|
||||
@ -74,7 +77,9 @@ define Package/secubox-app-streamlit/postinst
|
||||
echo ""
|
||||
echo "Web interface: http://<router-ip>:8501"
|
||||
echo ""
|
||||
echo "Deploy your apps with: streamlitctl app add <name> /path/to/app.py"
|
||||
echo "Create apps: streamlitctl app create myapp"
|
||||
echo "Add instance: streamlitctl instance add myapp 8502"
|
||||
echo "Gitea clone: streamlitctl gitea clone myapp user/repo"
|
||||
echo ""
|
||||
}
|
||||
exit 0
|
||||
|
||||
0
package/secubox/secubox-app-streamlit/files/etc/init.d/streamlit
Normal file → Executable file
0
package/secubox/secubox-app-streamlit/files/etc/init.d/streamlit
Normal file → Executable file
File diff suppressed because it is too large
Load Diff
0
package/secubox/secubox-app-tor/files/etc/init.d/tor-shield
Normal file → Executable file
0
package/secubox/secubox-app-tor/files/etc/init.d/tor-shield
Normal file → Executable file
235
package/secubox/secubox-core/files/etc/init.d/secubox-extroot
Executable file
235
package/secubox/secubox-core/files/etc/init.d/secubox-extroot
Executable file
@ -0,0 +1,235 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
# SecuBox Extroot Auto-Setup
|
||||
# Automatically configures overlay on mmcblk0p3 after fresh install/upgrade
|
||||
# Copyright (C) 2025 CyberMind.fr
|
||||
|
||||
START=10
|
||||
STOP=90
|
||||
|
||||
EXTRA_COMMANDS="status setup"
|
||||
EXTRA_HELP=" status Show extroot status
|
||||
setup Configure extroot on mmcblk0p3"
|
||||
|
||||
OVERLAY_DEV="/dev/mmcblk0p3"
|
||||
OVERLAY_LABEL="rootfs_data"
|
||||
LOG_TAG="secubox-extroot"
|
||||
|
||||
log() { logger -t "$LOG_TAG" "$*"; echo "$*"; }
|
||||
|
||||
# Check if extroot is already active
|
||||
is_extroot_active() {
|
||||
mount | grep -q "on /overlay type" && [ -d /overlay/upper ]
|
||||
}
|
||||
|
||||
# Check if overlay partition exists
|
||||
has_overlay_partition() {
|
||||
[ -b "$OVERLAY_DEV" ] || return 1
|
||||
blkid "$OVERLAY_DEV" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
# Get filesystem type of overlay partition
|
||||
get_overlay_fstype() {
|
||||
blkid "$OVERLAY_DEV" -s TYPE -o value 2>/dev/null
|
||||
}
|
||||
|
||||
# Get UUID of overlay partition
|
||||
get_overlay_uuid() {
|
||||
blkid "$OVERLAY_DEV" -s UUID -o value 2>/dev/null
|
||||
}
|
||||
|
||||
# Install required filesystem support
|
||||
install_fs_support() {
|
||||
local fstype="$1"
|
||||
|
||||
case "$fstype" in
|
||||
f2fs)
|
||||
if ! opkg list-installed 2>/dev/null | grep -q "^kmod-fs-f2fs"; then
|
||||
log "Installing f2fs support..."
|
||||
opkg update >/dev/null 2>&1
|
||||
opkg install kmod-fs-f2fs f2fs-tools 2>/dev/null || true
|
||||
fi
|
||||
;;
|
||||
ext4)
|
||||
if ! opkg list-installed 2>/dev/null | grep -q "^kmod-fs-ext4"; then
|
||||
log "Installing ext4 support..."
|
||||
opkg update >/dev/null 2>&1
|
||||
opkg install kmod-fs-ext4 e2fsprogs 2>/dev/null || true
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
# Always ensure block-mount is available
|
||||
if ! opkg list-installed 2>/dev/null | grep -q "^block-mount"; then
|
||||
log "Installing block-mount..."
|
||||
opkg install block-mount 2>/dev/null || true
|
||||
fi
|
||||
}
|
||||
|
||||
# Prepare overlay partition structure
|
||||
prepare_overlay() {
|
||||
local fstype="$1"
|
||||
local mount_point="/tmp/extroot_setup"
|
||||
|
||||
mkdir -p "$mount_point"
|
||||
|
||||
# Mount the partition
|
||||
if ! mount -t "$fstype" "$OVERLAY_DEV" "$mount_point" 2>/dev/null; then
|
||||
log "Failed to mount $OVERLAY_DEV"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Create overlay directories
|
||||
mkdir -p "$mount_point/upper"
|
||||
mkdir -p "$mount_point/work"
|
||||
|
||||
# Copy existing data if overlay was previously active
|
||||
if [ -d /overlay/upper ] && [ "$(ls -A /overlay/upper 2>/dev/null)" ]; then
|
||||
log "Migrating existing overlay data..."
|
||||
cp -a /overlay/upper/* "$mount_point/upper/" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
sync
|
||||
umount "$mount_point"
|
||||
rmdir "$mount_point"
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
# Configure fstab for extroot
|
||||
configure_fstab() {
|
||||
local uuid="$1"
|
||||
local fstype="$2"
|
||||
|
||||
# Check if already configured
|
||||
if uci -q get fstab.extroot >/dev/null 2>&1; then
|
||||
local current_uuid=$(uci -q get fstab.extroot.uuid)
|
||||
if [ "$current_uuid" = "$uuid" ]; then
|
||||
log "Extroot already configured"
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
|
||||
log "Configuring fstab for extroot..."
|
||||
|
||||
# Remove old extroot config if exists
|
||||
uci -q delete fstab.extroot 2>/dev/null || true
|
||||
|
||||
# Add new extroot configuration
|
||||
uci set fstab.extroot=mount
|
||||
uci set fstab.extroot.target="/overlay"
|
||||
uci set fstab.extroot.uuid="$uuid"
|
||||
uci set fstab.extroot.enabled="1"
|
||||
|
||||
if [ "$fstype" = "f2fs" ]; then
|
||||
uci set fstab.extroot.fstype="f2fs"
|
||||
uci set fstab.extroot.options="rw,noatime"
|
||||
fi
|
||||
|
||||
uci commit fstab
|
||||
|
||||
log "Fstab configured - reboot required to activate"
|
||||
return 0
|
||||
}
|
||||
|
||||
# Main setup function
|
||||
setup_extroot() {
|
||||
log "SecuBox Extroot Setup starting..."
|
||||
|
||||
# Check if already active
|
||||
if is_extroot_active; then
|
||||
log "Extroot already active on /overlay"
|
||||
df -h /overlay | tail -1
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Check for overlay partition
|
||||
if ! has_overlay_partition; then
|
||||
log "No overlay partition found at $OVERLAY_DEV"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Get filesystem info
|
||||
local fstype=$(get_overlay_fstype)
|
||||
local uuid=$(get_overlay_uuid)
|
||||
|
||||
if [ -z "$fstype" ] || [ -z "$uuid" ]; then
|
||||
log "Cannot determine filesystem type or UUID"
|
||||
return 1
|
||||
fi
|
||||
|
||||
log "Found overlay partition: $OVERLAY_DEV ($fstype, UUID=$uuid)"
|
||||
|
||||
# Install filesystem support
|
||||
install_fs_support "$fstype"
|
||||
|
||||
# Prepare the partition
|
||||
if ! prepare_overlay "$fstype"; then
|
||||
log "Failed to prepare overlay partition"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Configure fstab
|
||||
if ! configure_fstab "$uuid" "$fstype"; then
|
||||
log "Failed to configure fstab"
|
||||
return 1
|
||||
fi
|
||||
|
||||
log "Extroot setup complete - REBOOT REQUIRED"
|
||||
|
||||
# Create flag file to indicate reboot needed
|
||||
touch /tmp/extroot-reboot-required
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
start() {
|
||||
# Only run setup if not already configured or after upgrade
|
||||
if is_extroot_active; then
|
||||
log "Extroot active"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if has_overlay_partition; then
|
||||
setup_extroot
|
||||
fi
|
||||
}
|
||||
|
||||
stop() {
|
||||
return 0
|
||||
}
|
||||
|
||||
boot() {
|
||||
start
|
||||
}
|
||||
|
||||
# Manual commands
|
||||
status() {
|
||||
echo "=== SecuBox Extroot Status ==="
|
||||
echo ""
|
||||
|
||||
if is_extroot_active; then
|
||||
echo "Status: ACTIVE"
|
||||
echo ""
|
||||
echo "Overlay mount:"
|
||||
mount | grep overlay
|
||||
echo ""
|
||||
echo "Storage:"
|
||||
df -h /overlay
|
||||
else
|
||||
echo "Status: NOT ACTIVE"
|
||||
echo ""
|
||||
if has_overlay_partition; then
|
||||
echo "Overlay partition available: $OVERLAY_DEV"
|
||||
echo "Filesystem: $(get_overlay_fstype)"
|
||||
echo "UUID: $(get_overlay_uuid)"
|
||||
echo ""
|
||||
echo "Run '/etc/init.d/secubox-extroot setup' to configure"
|
||||
else
|
||||
echo "No overlay partition found"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
setup() {
|
||||
setup_extroot
|
||||
}
|
||||
23
secubox-tools/deploy-extroot-init.sh
Executable file
23
secubox-tools/deploy-extroot-init.sh
Executable file
@ -0,0 +1,23 @@
|
||||
#!/bin/bash
|
||||
# Deploy SecuBox Extroot init.d script to router
|
||||
# Usage: ./deploy-extroot-init.sh [ROUTER_IP]
|
||||
|
||||
ROUTER_IP="${1:-192.168.255.1}"
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
||||
echo "Deploying secubox-extroot to $ROUTER_IP..."
|
||||
|
||||
# Deploy the init script
|
||||
cat "$SCRIPT_DIR/../package/secubox/secubox-core/files/etc/init.d/secubox-extroot" | \
|
||||
ssh root@$ROUTER_IP 'cat > /etc/init.d/secubox-extroot && chmod 755 /etc/init.d/secubox-extroot'
|
||||
|
||||
# Enable and run setup
|
||||
ssh root@$ROUTER_IP '
|
||||
/etc/init.d/secubox-extroot enable
|
||||
/etc/init.d/secubox-extroot setup
|
||||
/etc/init.d/secubox-extroot status
|
||||
'
|
||||
|
||||
echo ""
|
||||
echo "Done! If setup was successful, reboot to activate extroot:"
|
||||
echo " ssh root@$ROUTER_IP reboot"
|
||||
226
secubox-tools/deploy-remote.sh
Executable file
226
secubox-tools/deploy-remote.sh
Executable file
@ -0,0 +1,226 @@
|
||||
#!/bin/bash
|
||||
# SecuBox Remote Deployment Script
|
||||
# Deploys all SecuBox packages to a remote OpenWrt router
|
||||
|
||||
set -e
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
BUILD_DIR="$SCRIPT_DIR/sdk/bin/packages/aarch64_cortex-a72/secubox"
|
||||
ROUTER_IP="${1:-192.168.255.1}"
|
||||
ROUTER_USER="${2:-root}"
|
||||
|
||||
# Colors
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m'
|
||||
|
||||
info() { echo -e "${BLUE}ℹ️ $*${NC}"; }
|
||||
success() { echo -e "${GREEN}✅ $*${NC}"; }
|
||||
warn() { echo -e "${YELLOW}⚠️ $*${NC}"; }
|
||||
error() { echo -e "${RED}❌ $*${NC}"; exit 1; }
|
||||
|
||||
# Check SSH connectivity
|
||||
check_ssh() {
|
||||
info "Checking SSH connectivity to $ROUTER_IP..."
|
||||
if ! ssh -o ConnectTimeout=10 "$ROUTER_USER@$ROUTER_IP" "echo ok" 2>/dev/null; then
|
||||
error "Cannot connect to $ROUTER_IP via SSH"
|
||||
fi
|
||||
success "SSH connection OK"
|
||||
}
|
||||
|
||||
# Setup local feed on router
|
||||
setup_feed() {
|
||||
info "Setting up local package feed on router..."
|
||||
|
||||
ssh "$ROUTER_USER@$ROUTER_IP" 'mkdir -p /www/secubox-feed /tmp/secubox-install'
|
||||
|
||||
# Copy packages
|
||||
info "Copying packages to router (this may take a while)..."
|
||||
scp -q "$BUILD_DIR"/*.ipk "$ROUTER_USER@$ROUTER_IP:/www/secubox-feed/" 2>/dev/null || true
|
||||
|
||||
# Generate Packages index
|
||||
info "Generating package index..."
|
||||
ssh "$ROUTER_USER@$ROUTER_IP" 'cd /www/secubox-feed && {
|
||||
rm -f Packages Packages.gz
|
||||
for ipk in *.ipk; do
|
||||
[ -f "$ipk" ] || continue
|
||||
tar -xOzf "$ipk" ./control.tar.gz 2>/dev/null | tar -xOz ./control 2>/dev/null >> Packages
|
||||
echo "Filename: $ipk" >> Packages
|
||||
echo "" >> Packages
|
||||
done
|
||||
gzip -k Packages
|
||||
}'
|
||||
|
||||
# Configure opkg
|
||||
ssh "$ROUTER_USER@$ROUTER_IP" 'grep -q "secubox-feed" /etc/opkg/customfeeds.conf 2>/dev/null || {
|
||||
echo "src/gz secubox file:///www/secubox-feed" >> /etc/opkg/customfeeds.conf
|
||||
}'
|
||||
|
||||
success "Local feed configured"
|
||||
}
|
||||
|
||||
# Install core packages first
|
||||
install_core() {
|
||||
info "Installing core SecuBox packages..."
|
||||
|
||||
ssh "$ROUTER_USER@$ROUTER_IP" 'opkg update 2>/dev/null
|
||||
|
||||
# Core packages (order matters)
|
||||
for pkg in secubox-core; do
|
||||
if [ -f "/www/secubox-feed/${pkg}_"*.ipk ]; then
|
||||
echo "Installing $pkg..."
|
||||
opkg install --force-reinstall /www/secubox-feed/${pkg}_*.ipk 2>&1 || true
|
||||
fi
|
||||
done'
|
||||
|
||||
success "Core packages installed"
|
||||
}
|
||||
|
||||
# Install LuCI apps
|
||||
install_luci_apps() {
|
||||
info "Installing LuCI applications..."
|
||||
|
||||
ssh "$ROUTER_USER@$ROUTER_IP" '
|
||||
cd /www/secubox-feed
|
||||
|
||||
# Skip large bonus package and packages with missing deps
|
||||
SKIP="secubox-bonus|auth-guardian|ksm-manager|vhost-manager|zigbee"
|
||||
|
||||
for ipk in luci-app-*.ipk; do
|
||||
[ -f "$ipk" ] || continue
|
||||
|
||||
# Skip excluded packages
|
||||
if echo "$ipk" | grep -qE "$SKIP"; then
|
||||
echo "Skipping: $ipk (excluded)"
|
||||
continue
|
||||
fi
|
||||
|
||||
pkg_name=$(echo "$ipk" | sed "s/_[0-9].*//")
|
||||
echo "Installing: $pkg_name"
|
||||
opkg install --force-reinstall "/www/secubox-feed/$ipk" 2>&1 | grep -v "^Collected" || true
|
||||
done'
|
||||
|
||||
success "LuCI apps installed"
|
||||
}
|
||||
|
||||
# Install service packages
|
||||
install_services() {
|
||||
info "Installing service packages..."
|
||||
|
||||
ssh "$ROUTER_USER@$ROUTER_IP" '
|
||||
cd /www/secubox-feed
|
||||
|
||||
for ipk in secubox-app-*.ipk; do
|
||||
[ -f "$ipk" ] || continue
|
||||
|
||||
pkg_name=$(echo "$ipk" | sed "s/_[0-9].*//")
|
||||
echo "Installing: $pkg_name"
|
||||
opkg install --force-reinstall "/www/secubox-feed/$ipk" 2>&1 | grep -v "^Collected" || true
|
||||
done'
|
||||
|
||||
success "Service packages installed"
|
||||
}
|
||||
|
||||
# Fix permissions and restart services
|
||||
finalize() {
|
||||
info "Finalizing installation..."
|
||||
|
||||
ssh "$ROUTER_USER@$ROUTER_IP" '
|
||||
# Fix RPCD script permissions
|
||||
chmod 755 /usr/libexec/rpcd/luci.* 2>/dev/null || true
|
||||
|
||||
# Restart rpcd
|
||||
/etc/init.d/rpcd restart
|
||||
|
||||
# Clear LuCI cache
|
||||
rm -rf /tmp/luci-modulecache /tmp/luci-indexcache 2>/dev/null
|
||||
|
||||
# Show installed packages
|
||||
echo ""
|
||||
echo "=== Installed SecuBox packages ==="
|
||||
opkg list-installed | grep -E "^(luci-app-|secubox-)" | wc -l
|
||||
echo "packages installed"
|
||||
'
|
||||
|
||||
success "Installation complete!"
|
||||
}
|
||||
|
||||
# Generate apps-local.json for store UI
|
||||
generate_apps_json() {
|
||||
info "Generating apps manifest..."
|
||||
|
||||
ssh "$ROUTER_USER@$ROUTER_IP" 'cd /www/secubox-feed && {
|
||||
cat > apps-local.json << "HEADER"
|
||||
{
|
||||
"feed_url": "/secubox-feed",
|
||||
"generated": "TIMESTAMP",
|
||||
"packages": [
|
||||
HEADER
|
||||
sed -i "s/TIMESTAMP/$(date -Iseconds)/" apps-local.json
|
||||
|
||||
first=true
|
||||
for pkg in *.ipk; do
|
||||
[ -f "$pkg" ] || continue
|
||||
filename="$pkg"
|
||||
name=$(echo "$filename" | sed "s/_[0-9].*$//")
|
||||
version=$(echo "$filename" | sed "s/^[^_]*_//; s/_[^_]*$//")
|
||||
size=$(stat -c%s "$pkg" 2>/dev/null || ls -l "$pkg" | awk "{print \$5}")
|
||||
|
||||
# Category based on name
|
||||
category="utility"
|
||||
case "$name" in
|
||||
*crowdsec*|*mitmproxy*|*tor*) category="security";;
|
||||
*bandwidth*|*traffic*|*network*|*wireguard*) category="network";;
|
||||
*hexojs*|*gitea*|*streamlit*) category="apps";;
|
||||
*secubox*) category="system";;
|
||||
esac
|
||||
|
||||
[ "$first" = "true" ] || echo "," >> apps-local.json
|
||||
first=false
|
||||
|
||||
cat >> apps-local.json << ENTRY
|
||||
{
|
||||
"name": "$name",
|
||||
"version": "$version",
|
||||
"filename": "$filename",
|
||||
"size": $size,
|
||||
"category": "$category"
|
||||
}
|
||||
ENTRY
|
||||
done
|
||||
|
||||
echo " ]" >> apps-local.json
|
||||
echo "}" >> apps-local.json
|
||||
}'
|
||||
|
||||
success "Apps manifest generated"
|
||||
}
|
||||
|
||||
# Main
|
||||
main() {
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo " SecuBox Remote Deployment"
|
||||
echo " Target: $ROUTER_USER@$ROUTER_IP"
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo ""
|
||||
|
||||
check_ssh
|
||||
setup_feed
|
||||
install_core
|
||||
install_services
|
||||
install_luci_apps
|
||||
generate_apps_json
|
||||
finalize
|
||||
|
||||
echo ""
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
success "Deployment complete!"
|
||||
echo " Access LuCI at: http://$ROUTER_IP"
|
||||
echo " Local feed at: http://$ROUTER_IP/secubox-feed/"
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
}
|
||||
|
||||
main "$@"
|
||||
85
secubox-tools/fix-extroot.sh
Executable file
85
secubox-tools/fix-extroot.sh
Executable file
@ -0,0 +1,85 @@
|
||||
#!/bin/sh
|
||||
# Fix extroot by formatting mmcblk0p3 fresh
|
||||
# Run this from console or SSH after failsafe boot
|
||||
|
||||
OVERLAY_DEV="/dev/mmcblk0p3"
|
||||
|
||||
echo "=== SecuBox Extroot Fix ==="
|
||||
echo ""
|
||||
|
||||
# Stop services using overlay
|
||||
echo "Stopping services..."
|
||||
for svc in /etc/init.d/*; do
|
||||
[ -x "$svc" ] && "$svc" stop 2>/dev/null &
|
||||
done
|
||||
sleep 3
|
||||
|
||||
# Kill processes using overlay
|
||||
echo "Killing processes using overlay..."
|
||||
fuser -km /overlay 2>/dev/null || true
|
||||
sleep 2
|
||||
|
||||
# Unmount everything
|
||||
echo "Unmounting filesystems..."
|
||||
umount -l /overlay 2>/dev/null || true
|
||||
umount -l /mnt/extroot 2>/dev/null || true
|
||||
umount -l "$OVERLAY_DEV" 2>/dev/null || true
|
||||
sync
|
||||
sleep 2
|
||||
|
||||
# Verify unmounted
|
||||
if mount | grep -q "$OVERLAY_DEV"; then
|
||||
echo "ERROR: Cannot unmount $OVERLAY_DEV"
|
||||
echo "Try: reboot into failsafe mode and run this script"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "Formatting $OVERLAY_DEV as f2fs..."
|
||||
mkfs.f2fs -f -l rootfs_data "$OVERLAY_DEV" || {
|
||||
echo "Format failed! Try: mkfs.ext4 -L rootfs_data $OVERLAY_DEV"
|
||||
exit 1
|
||||
}
|
||||
|
||||
echo ""
|
||||
echo "Preparing overlay structure..."
|
||||
mkdir -p /mnt/extroot
|
||||
mount -t f2fs "$OVERLAY_DEV" /mnt/extroot
|
||||
mkdir -p /mnt/extroot/upper /mnt/extroot/work
|
||||
sync
|
||||
umount /mnt/extroot
|
||||
|
||||
echo ""
|
||||
echo "Configuring fstab..."
|
||||
UUID=$(blkid "$OVERLAY_DEV" -s UUID -o value)
|
||||
echo "UUID: $UUID"
|
||||
|
||||
# Write fstab config
|
||||
cat > /etc/config/fstab << EOF
|
||||
config global
|
||||
option anon_swap '0'
|
||||
option anon_mount '0'
|
||||
option auto_swap '0'
|
||||
option auto_mount '1'
|
||||
option delay_root '5'
|
||||
option check_fs '1'
|
||||
|
||||
config mount 'extroot'
|
||||
option target '/overlay'
|
||||
option uuid '$UUID'
|
||||
option enabled '1'
|
||||
option fstype 'f2fs'
|
||||
option options 'rw,noatime'
|
||||
|
||||
config mount 'srv'
|
||||
option target '/srv'
|
||||
option uuid '443e8304-4d3b-4fd0-9f26-74c50ba64113'
|
||||
option enabled '1'
|
||||
EOF
|
||||
|
||||
echo ""
|
||||
echo "=== Setup complete ==="
|
||||
echo ""
|
||||
cat /etc/config/fstab
|
||||
echo ""
|
||||
echo "Now reboot: reboot"
|
||||
176
secubox-tools/setup-extroot.sh
Executable file
176
secubox-tools/setup-extroot.sh
Executable file
@ -0,0 +1,176 @@
|
||||
#!/bin/bash
|
||||
# SecuBox Extroot Setup Script
|
||||
# Configures overlay on mmcblk0p3 for expanded storage
|
||||
# Run after fresh install or upgrade
|
||||
|
||||
ROUTER_IP="${1:-192.168.255.1}"
|
||||
ROUTER_USER="${2:-root}"
|
||||
|
||||
# Colors
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m'
|
||||
|
||||
info() { echo -e "${BLUE}ℹ️ $*${NC}"; }
|
||||
success() { echo -e "${GREEN}✅ $*${NC}"; }
|
||||
warn() { echo -e "${YELLOW}⚠️ $*${NC}"; }
|
||||
error() { echo -e "${RED}❌ $*${NC}"; }
|
||||
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo " SecuBox Extroot Setup"
|
||||
echo " Target: $ROUTER_USER@$ROUTER_IP"
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo ""
|
||||
|
||||
info "Connecting to router..."
|
||||
|
||||
ssh "$ROUTER_USER@$ROUTER_IP" '
|
||||
#!/bin/sh
|
||||
# Extroot setup script - runs on router
|
||||
|
||||
set -e
|
||||
|
||||
OVERLAY_DEV="/dev/mmcblk0p3"
|
||||
OVERLAY_MOUNT="/mnt/extroot"
|
||||
|
||||
echo "=== Checking current setup ==="
|
||||
echo "Root filesystem:"
|
||||
df -h /
|
||||
echo ""
|
||||
|
||||
# Check if overlay already mounted
|
||||
if mount | grep -q "overlay on / "; then
|
||||
echo "Overlay already active!"
|
||||
df -h /overlay
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Check if partition exists
|
||||
if [ ! -b "$OVERLAY_DEV" ]; then
|
||||
echo "ERROR: Partition $OVERLAY_DEV not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Get partition info
|
||||
FSTYPE=$(blkid "$OVERLAY_DEV" -s TYPE -o value 2>/dev/null || echo "unknown")
|
||||
echo "Partition: $OVERLAY_DEV"
|
||||
echo "Filesystem: $FSTYPE"
|
||||
echo ""
|
||||
|
||||
# Install required packages if not present
|
||||
echo "=== Checking required packages ==="
|
||||
opkg update 2>/dev/null || true
|
||||
|
||||
if [ "$FSTYPE" = "f2fs" ]; then
|
||||
if ! opkg list-installed | grep -q "^kmod-fs-f2fs"; then
|
||||
echo "Installing f2fs support..."
|
||||
opkg install kmod-fs-f2fs f2fs-tools 2>/dev/null || true
|
||||
fi
|
||||
elif [ "$FSTYPE" = "ext4" ]; then
|
||||
if ! opkg list-installed | grep -q "^kmod-fs-ext4"; then
|
||||
echo "Installing ext4 support..."
|
||||
opkg install kmod-fs-ext4 e2fsprogs 2>/dev/null || true
|
||||
fi
|
||||
fi
|
||||
|
||||
# Ensure block-mount is installed
|
||||
if ! opkg list-installed | grep -q "^block-mount"; then
|
||||
echo "Installing block-mount..."
|
||||
opkg install block-mount 2>/dev/null || true
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "=== Preparing overlay partition ==="
|
||||
|
||||
# Mount partition temporarily
|
||||
mkdir -p "$OVERLAY_MOUNT"
|
||||
mount -t "$FSTYPE" "$OVERLAY_DEV" "$OVERLAY_MOUNT" || {
|
||||
echo "ERROR: Cannot mount $OVERLAY_DEV"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Create overlay directories
|
||||
mkdir -p "$OVERLAY_MOUNT/upper"
|
||||
mkdir -p "$OVERLAY_MOUNT/work"
|
||||
|
||||
# Copy existing overlay data if any
|
||||
if [ -d /overlay/upper ]; then
|
||||
echo "Copying existing overlay data..."
|
||||
cp -a /overlay/upper/* "$OVERLAY_MOUNT/upper/" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# Sync
|
||||
sync
|
||||
|
||||
# Unmount
|
||||
umount "$OVERLAY_MOUNT"
|
||||
|
||||
echo ""
|
||||
echo "=== Configuring fstab ==="
|
||||
|
||||
# Get block info
|
||||
eval $(block info "$OVERLAY_DEV" | grep -o "UUID=\S*")
|
||||
echo "UUID: $UUID"
|
||||
|
||||
# Configure fstab using UCI
|
||||
uci -q delete fstab.extroot 2>/dev/null || true
|
||||
uci set fstab.extroot=mount
|
||||
uci set fstab.extroot.target="/overlay"
|
||||
uci set fstab.extroot.uuid="$UUID"
|
||||
uci set fstab.extroot.enabled="1"
|
||||
if [ "$FSTYPE" = "f2fs" ]; then
|
||||
uci set fstab.extroot.fstype="f2fs"
|
||||
uci set fstab.extroot.options="rw,noatime"
|
||||
fi
|
||||
uci commit fstab
|
||||
|
||||
echo ""
|
||||
echo "=== Updated fstab ==="
|
||||
cat /etc/config/fstab
|
||||
|
||||
echo ""
|
||||
echo "=== Setup complete! ==="
|
||||
echo ""
|
||||
echo "IMPORTANT: Reboot to activate the overlay"
|
||||
echo "After reboot, /overlay will be mounted on the 14GB partition"
|
||||
echo ""
|
||||
echo "Run: reboot"
|
||||
'
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
success "Extroot configuration complete!"
|
||||
echo ""
|
||||
warn "REBOOT REQUIRED to activate overlay"
|
||||
echo ""
|
||||
read -p "Reboot router now? [y/N] " -n 1 -r
|
||||
echo
|
||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||
info "Rebooting router..."
|
||||
ssh "$ROUTER_USER@$ROUTER_IP" "reboot" 2>/dev/null || true
|
||||
echo ""
|
||||
info "Waiting for router to come back online..."
|
||||
sleep 60
|
||||
|
||||
# Wait for router to come back
|
||||
for i in {1..30}; do
|
||||
if ssh -o ConnectTimeout=5 "$ROUTER_USER@$ROUTER_IP" "echo ok" 2>/dev/null; then
|
||||
success "Router is back online!"
|
||||
echo ""
|
||||
ssh "$ROUTER_USER@$ROUTER_IP" '
|
||||
echo "=== Overlay status ==="
|
||||
mount | grep overlay || echo "No overlay (yet)"
|
||||
echo ""
|
||||
echo "=== Disk usage ==="
|
||||
df -h / /overlay 2>/dev/null
|
||||
'
|
||||
break
|
||||
fi
|
||||
echo "Waiting... ($i/30)"
|
||||
sleep 5
|
||||
done
|
||||
fi
|
||||
else
|
||||
error "Setup failed"
|
||||
fi
|
||||
Loading…
Reference in New Issue
Block a user