mirror of
https://github.com/CyberMind-FR/secubox-deb.git
synced 2026-07-28 15:28:24 +00:00
feat(secubox): complete meta-script generator Tasks 14-17
Task 14: Arch Profiles - Add profiles/arch/arm64.yaml and profiles/arch/amd64.yaml - Add ResolveWithArch() to merger for base → arch → tier chain - Add tests for arch profile resolution Task 15: Package secubox.yaml for All Packages - Add scripts/generate-secubox-yaml.py generator script - Generate 131 debian/secubox.yaml files with: - Category detection (security, network, system, etc.) - Tier assignment (all, lite, standard, pro) - API socket and UI path detection Task 16: APT Repository Setup - Add apt/conf/ reprepro configuration (multi-arch arm64/amd64) - Add apt/hooks/lintian-check pre-publish validation - Add scripts/apt-publish.sh and scripts/apt-sync.sh - Add apt/README.md documentation Task 17: CI Integration - Add .github/workflows/build-secubox-cli.yml - Build for linux-amd64 and linux-arm64 - Version injection via ldflags - GitHub releases on tag push Code Quality Fixes (Tasks 10-13): - Add atomic writes for OTA boot control files (0600 perms) - Fix NVME device extraction (nvme0n1p2 → nvme0n1) - Add scanner.Err() checks in hardware detection - Fix URL injection validation in fetch command - Add proper cleanup on checksum failures Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
295a91aac4
commit
bd7dda0c6f
201
.github/workflows/build-secubox-cli.yml
vendored
Normal file
201
.github/workflows/build-secubox-cli.yml
vendored
Normal file
|
|
@ -0,0 +1,201 @@
|
|||
# SecuBox CLI — Build Go Binary
|
||||
# Builds the secubox meta-script generator for linux-amd64 and linux-arm64
|
||||
name: Build SecuBox CLI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master, main]
|
||||
paths:
|
||||
- 'cmd/secubox/**'
|
||||
- '.github/workflows/build-secubox-cli.yml'
|
||||
tags: ['v*']
|
||||
pull_request:
|
||||
branches: [master, main]
|
||||
paths:
|
||||
- 'cmd/secubox/**'
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
description: 'Version override (e.g., v2.8.0)'
|
||||
required: false
|
||||
|
||||
env:
|
||||
GO_VERSION: '1.22'
|
||||
|
||||
jobs:
|
||||
test:
|
||||
name: Test
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
cache-dependency-path: cmd/secubox/go.sum
|
||||
|
||||
- name: Download dependencies
|
||||
working-directory: cmd/secubox
|
||||
run: go mod download
|
||||
|
||||
- name: Run tests
|
||||
working-directory: cmd/secubox
|
||||
run: go test -v -race -coverprofile=coverage.out ./...
|
||||
|
||||
- name: Upload coverage
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: coverage
|
||||
path: cmd/secubox/coverage.out
|
||||
|
||||
build:
|
||||
name: Build
|
||||
needs: test
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- goos: linux
|
||||
goarch: amd64
|
||||
suffix: linux-amd64
|
||||
- goos: linux
|
||||
goarch: arm64
|
||||
suffix: linux-arm64
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0 # For git describe
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
cache-dependency-path: cmd/secubox/go.sum
|
||||
|
||||
- name: Determine version
|
||||
id: version
|
||||
run: |
|
||||
if [ -n "${{ github.event.inputs.version }}" ]; then
|
||||
VERSION="${{ github.event.inputs.version }}"
|
||||
elif [[ "${{ github.ref }}" == refs/tags/* ]]; then
|
||||
VERSION="${{ github.ref_name }}"
|
||||
else
|
||||
VERSION="$(git describe --tags --always --dirty 2>/dev/null || echo 'dev')"
|
||||
fi
|
||||
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
||||
echo "Building version: $VERSION"
|
||||
|
||||
- name: Build binary
|
||||
working-directory: cmd/secubox
|
||||
env:
|
||||
GOOS: ${{ matrix.goos }}
|
||||
GOARCH: ${{ matrix.goarch }}
|
||||
CGO_ENABLED: 0
|
||||
run: |
|
||||
VERSION="${{ steps.version.outputs.version }}"
|
||||
BUILD_TIME=$(date -u '+%Y-%m-%dT%H:%M:%SZ')
|
||||
COMMIT=$(git rev-parse --short HEAD)
|
||||
|
||||
go build -ldflags="-s -w \
|
||||
-X main.Version=$VERSION \
|
||||
-X main.BuildTime=$BUILD_TIME \
|
||||
-X main.Commit=$COMMIT" \
|
||||
-o secubox-${{ matrix.suffix }} .
|
||||
|
||||
- name: Compress binary
|
||||
working-directory: cmd/secubox
|
||||
run: |
|
||||
tar -czvf secubox-${{ matrix.suffix }}.tar.gz secubox-${{ matrix.suffix }}
|
||||
sha256sum secubox-${{ matrix.suffix }}.tar.gz > secubox-${{ matrix.suffix }}.tar.gz.sha256
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: secubox-${{ matrix.suffix }}
|
||||
path: |
|
||||
cmd/secubox/secubox-${{ matrix.suffix }}.tar.gz
|
||||
cmd/secubox/secubox-${{ matrix.suffix }}.tar.gz.sha256
|
||||
|
||||
release:
|
||||
name: Release
|
||||
needs: build
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
steps:
|
||||
- name: Download all artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: artifacts/
|
||||
merge-multiple: true
|
||||
|
||||
- name: Generate release notes
|
||||
run: |
|
||||
cat > RELEASE_NOTES.md << 'EOF'
|
||||
# SecuBox CLI ${{ github.ref_name }}
|
||||
|
||||
Meta-script generator for SecuBox-DEB image building.
|
||||
|
||||
## Features
|
||||
- Profile-based image generation
|
||||
- Board detection and auto-configuration
|
||||
- A/B partition OTA updates
|
||||
- GitHub releases integration
|
||||
|
||||
## Downloads
|
||||
|
||||
| Platform | File | SHA256 |
|
||||
|----------|------|--------|
|
||||
| Linux x64 | `secubox-linux-amd64.tar.gz` | [checksum] |
|
||||
| Linux ARM64 | `secubox-linux-arm64.tar.gz` | [checksum] |
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
# Linux x64
|
||||
curl -LO https://github.com/CyberMind-FR/secubox-deb/releases/download/${{ github.ref_name }}/secubox-linux-amd64.tar.gz
|
||||
tar xzf secubox-linux-amd64.tar.gz
|
||||
sudo mv secubox-linux-amd64 /usr/local/bin/secubox
|
||||
|
||||
# Linux ARM64
|
||||
curl -LO https://github.com/CyberMind-FR/secubox-deb/releases/download/${{ github.ref_name }}/secubox-linux-arm64.tar.gz
|
||||
tar xzf secubox-linux-arm64.tar.gz
|
||||
sudo mv secubox-linux-arm64 /usr/local/bin/secubox
|
||||
```
|
||||
|
||||
## Quick Start
|
||||
|
||||
```bash
|
||||
# Interactive wizard
|
||||
secubox gen
|
||||
|
||||
# Generate for specific board
|
||||
secubox gen --board mochabin --tier pro
|
||||
|
||||
# Build image
|
||||
secubox build --board mochabin --output secubox.img
|
||||
|
||||
# Check hardware
|
||||
secubox info
|
||||
|
||||
# OTA update
|
||||
secubox ota update --url https://releases.secubox.in/v2.8.0/secubox-mochabin.img.gz
|
||||
```
|
||||
EOF
|
||||
|
||||
- name: Create GitHub Release
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
name: SecuBox CLI ${{ github.ref_name }}
|
||||
body_path: RELEASE_NOTES.md
|
||||
files: |
|
||||
artifacts/*.tar.gz
|
||||
artifacts/*.sha256
|
||||
draft: false
|
||||
prerelease: ${{ contains(github.ref, 'alpha') || contains(github.ref, 'beta') || contains(github.ref, 'rc') }}
|
||||
137
apt/README.md
Normal file
137
apt/README.md
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
# SecuBox-DEB APT Repository
|
||||
|
||||
Configuration files for the SecuBox APT package repository.
|
||||
|
||||
## Repository Structure
|
||||
|
||||
```
|
||||
/srv/apt/
|
||||
├── conf/
|
||||
│ ├── distributions # Repository distributions config
|
||||
│ ├── options # Global reprepro options
|
||||
│ └── incoming # Incoming packages config
|
||||
├── db/ # Reprepro database
|
||||
├── dists/ # Distribution metadata
|
||||
│ ├── bookworm/ # Stable releases
|
||||
│ └── bookworm-testing/ # Testing releases
|
||||
├── pool/ # Package files
|
||||
│ ├── main/ # Main component
|
||||
│ └── contrib/ # Contrib component
|
||||
├── incoming/ # Incoming packages drop
|
||||
└── tmp/ # Temporary files
|
||||
```
|
||||
|
||||
## Setup
|
||||
|
||||
### Initialize Repository
|
||||
|
||||
```bash
|
||||
# Create directory structure
|
||||
sudo mkdir -p /srv/apt/{conf,db,dists,pool,incoming,tmp}
|
||||
|
||||
# Copy configuration
|
||||
sudo cp apt/conf/* /srv/apt/conf/
|
||||
|
||||
# Set ownership
|
||||
sudo chown -R $(whoami) /srv/apt
|
||||
|
||||
# Initialize
|
||||
cd /srv/apt
|
||||
reprepro export
|
||||
```
|
||||
|
||||
### GPG Key Setup
|
||||
|
||||
```bash
|
||||
# Generate signing key (if not exists)
|
||||
gpg --gen-key
|
||||
|
||||
# Export public key for clients
|
||||
gpg --armor --export your@email.com > /srv/apt/secubox.gpg
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### Publishing Packages
|
||||
|
||||
```bash
|
||||
# Publish a single package
|
||||
./scripts/apt-publish.sh packages/secubox-core/*.deb
|
||||
|
||||
# Publish to testing
|
||||
./scripts/apt-publish.sh -c bookworm-testing packages/*/*.deb
|
||||
|
||||
# Skip lintian (not recommended)
|
||||
./scripts/apt-publish.sh --skip-lintian packages/*/*.deb
|
||||
|
||||
# Dry run
|
||||
./scripts/apt-publish.sh -n packages/*/*.deb
|
||||
```
|
||||
|
||||
### Syncing to Remote
|
||||
|
||||
```bash
|
||||
# Preview sync
|
||||
./scripts/apt-sync.sh --dry-run
|
||||
|
||||
# Full sync
|
||||
./scripts/apt-sync.sh
|
||||
|
||||
# Verbose sync
|
||||
./scripts/apt-sync.sh --verbose
|
||||
```
|
||||
|
||||
### Manual reprepro Commands
|
||||
|
||||
```bash
|
||||
cd /srv/apt
|
||||
|
||||
# Add package
|
||||
reprepro -C main includedeb bookworm /path/to/package.deb
|
||||
|
||||
# Remove package
|
||||
reprepro remove bookworm package-name
|
||||
|
||||
# List packages
|
||||
reprepro list bookworm
|
||||
|
||||
# Check repository
|
||||
reprepro check
|
||||
```
|
||||
|
||||
## Client Configuration
|
||||
|
||||
### Adding Repository
|
||||
|
||||
```bash
|
||||
# Add GPG key
|
||||
curl -fsSL https://apt.secubox.in/secubox.gpg | sudo gpg --dearmor -o /usr/share/keyrings/secubox.gpg
|
||||
|
||||
# Add repository
|
||||
echo "deb [signed-by=/usr/share/keyrings/secubox.gpg] https://apt.secubox.in bookworm main" | \
|
||||
sudo tee /etc/apt/sources.list.d/secubox.list
|
||||
|
||||
# Update and install
|
||||
sudo apt update
|
||||
sudo apt install secubox-core
|
||||
```
|
||||
|
||||
## Distributions
|
||||
|
||||
| Codename | Description | Use Case |
|
||||
|----------|-------------|----------|
|
||||
| bookworm | Stable releases | Production |
|
||||
| bookworm-testing | Testing releases | Pre-release testing |
|
||||
|
||||
## Components
|
||||
|
||||
| Component | Description |
|
||||
|-----------|-------------|
|
||||
| main | Core SecuBox packages |
|
||||
| contrib | Community contributions |
|
||||
|
||||
## Architectures
|
||||
|
||||
- `arm64` - Primary target (MOCHAbin, ESPRESSObin, RPi)
|
||||
- `amd64` - VMs and x64 hardware
|
||||
- `all` - Architecture-independent packages
|
||||
27
apt/conf/distributions
Normal file
27
apt/conf/distributions
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
# apt/conf/distributions
|
||||
# Reprepro configuration for SecuBox-DEB APT repository
|
||||
# Multi-arch support: arm64 + amd64
|
||||
|
||||
Origin: SecuBox
|
||||
Label: SecuBox-DEB
|
||||
Suite: stable
|
||||
Codename: bookworm
|
||||
Version: 12
|
||||
Architectures: arm64 amd64 all source
|
||||
Components: main contrib
|
||||
Description: SecuBox-DEB packages for Debian Bookworm
|
||||
SignWith: default
|
||||
DebIndices: Packages Release . .gz .bz2
|
||||
DscIndices: Sources Release .gz .bz2
|
||||
|
||||
Origin: SecuBox
|
||||
Label: SecuBox-DEB
|
||||
Suite: testing
|
||||
Codename: bookworm-testing
|
||||
Version: 12
|
||||
Architectures: arm64 amd64 all source
|
||||
Components: main contrib
|
||||
Description: SecuBox-DEB testing packages
|
||||
SignWith: default
|
||||
DebIndices: Packages Release . .gz .bz2
|
||||
DscIndices: Sources Release .gz .bz2
|
||||
8
apt/conf/incoming
Normal file
8
apt/conf/incoming
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
# apt/conf/incoming
|
||||
# Reprepro incoming configuration
|
||||
|
||||
Name: default
|
||||
IncomingDir: incoming
|
||||
TempDir: tmp
|
||||
Allow: bookworm bookworm-testing
|
||||
Cleanup: on_deny on_error
|
||||
6
apt/conf/options
Normal file
6
apt/conf/options
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
# apt/conf/options
|
||||
# Reprepro global options
|
||||
|
||||
verbose
|
||||
ask-passphrase
|
||||
basedir /srv/apt
|
||||
32
apt/hooks/lintian-check
Executable file
32
apt/hooks/lintian-check
Executable file
|
|
@ -0,0 +1,32 @@
|
|||
#!/bin/bash
|
||||
# apt/hooks/lintian-check
|
||||
# Pre-publish hook to run lintian on packages before adding to repository
|
||||
# SecuBox-DEB - CyberMind
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
DEB_FILE="$1"
|
||||
|
||||
if [ ! -f "$DEB_FILE" ]; then
|
||||
echo "ERROR: Package file not found: $DEB_FILE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "=== Running lintian on $(basename "$DEB_FILE") ==="
|
||||
|
||||
# Run lintian with appropriate checks
|
||||
# --fail-on error: Fail if there are errors
|
||||
# --suppress-tags: Suppress some common warnings for our use case
|
||||
LINTIAN_OPTS="--fail-on error"
|
||||
LINTIAN_OPTS="$LINTIAN_OPTS --suppress-tags debian-changelog-file-missing-or-wrong-name"
|
||||
LINTIAN_OPTS="$LINTIAN_OPTS --suppress-tags changelog-file-missing-in-native-package"
|
||||
LINTIAN_OPTS="$LINTIAN_OPTS --suppress-tags file-missing-in-root-dir"
|
||||
|
||||
if lintian $LINTIAN_OPTS "$DEB_FILE"; then
|
||||
echo "=== Lintian check PASSED ==="
|
||||
exit 0
|
||||
else
|
||||
echo "=== Lintian check FAILED ==="
|
||||
echo "Package will not be added to repository."
|
||||
exit 1
|
||||
fi
|
||||
|
|
@ -92,7 +92,10 @@ func runBuild(cmd *cobra.Command, args []string) error {
|
|||
// Resolve output directory
|
||||
outputDir := buildOutput
|
||||
if !filepath.IsAbs(outputDir) {
|
||||
cwd, _ := os.Getwd()
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return fmt.Errorf("get working directory for output: %w", err)
|
||||
}
|
||||
outputDir = filepath.Join(cwd, outputDir)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import (
|
|||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
|
|
@ -33,6 +34,12 @@ const (
|
|||
progressBarSize = 50
|
||||
)
|
||||
|
||||
// Package-level HTTP client for connection reuse
|
||||
var httpClient = &http.Client{Timeout: defaultTimeout}
|
||||
|
||||
// Version tag regex for validation
|
||||
var versionTagRe = regexp.MustCompile(`^[a-zA-Z0-9._-]+$`)
|
||||
|
||||
// supportedBoards lists boards that have pre-built images
|
||||
var supportedBoards = []string{
|
||||
"mochabin",
|
||||
|
|
@ -161,6 +168,10 @@ func runFetch(cmd *cobra.Command, args []string) error {
|
|||
if checksumAsset != nil {
|
||||
fmt.Printf("\nVerifying checksum...\n")
|
||||
if err := verifyChecksum(outputPath, checksumAsset, imageAsset.Name); err != nil {
|
||||
// Clean up corrupted file
|
||||
if rmErr := os.Remove(outputPath); rmErr != nil {
|
||||
fmt.Fprintf(os.Stderr, "warning: could not remove corrupted file: %v\n", rmErr)
|
||||
}
|
||||
return fmt.Errorf("checksum verification failed: %w", err)
|
||||
}
|
||||
fmt.Printf("Checksum verified OK\n")
|
||||
|
|
@ -234,7 +245,6 @@ func listReleases() error {
|
|||
func getReleases() ([]GitHubRelease, error) {
|
||||
url := fmt.Sprintf("%s/repos/%s/%s/releases", githubAPIBase, githubOwner, githubRepo)
|
||||
|
||||
client := &http.Client{Timeout: 30 * time.Second}
|
||||
req, err := http.NewRequest("GET", url, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
@ -242,7 +252,7 @@ func getReleases() ([]GitHubRelease, error) {
|
|||
req.Header.Set("Accept", "application/vnd.github.v3+json")
|
||||
req.Header.Set("User-Agent", "secubox-cli/"+version)
|
||||
|
||||
resp, err := client.Do(req)
|
||||
resp, err := httpClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -261,20 +271,23 @@ func getReleases() ([]GitHubRelease, error) {
|
|||
return releases, nil
|
||||
}
|
||||
|
||||
func getRelease(version string) (*GitHubRelease, error) {
|
||||
func getRelease(ver string) (*GitHubRelease, error) {
|
||||
var url string
|
||||
if version == "" {
|
||||
if ver == "" {
|
||||
url = fmt.Sprintf("%s/repos/%s/%s/releases/latest", githubAPIBase, githubOwner, githubRepo)
|
||||
} else {
|
||||
// Normalize version tag
|
||||
tag := version
|
||||
tag := ver
|
||||
if !strings.HasPrefix(tag, "v") {
|
||||
tag = "v" + tag
|
||||
}
|
||||
// Validate version format to prevent URL injection
|
||||
if !versionTagRe.MatchString(tag) {
|
||||
return nil, fmt.Errorf("invalid version format: %s", ver)
|
||||
}
|
||||
url = fmt.Sprintf("%s/repos/%s/%s/releases/tags/%s", githubAPIBase, githubOwner, githubRepo, tag)
|
||||
}
|
||||
|
||||
client := &http.Client{Timeout: 30 * time.Second}
|
||||
req, err := http.NewRequest("GET", url, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
@ -282,17 +295,17 @@ func getRelease(version string) (*GitHubRelease, error) {
|
|||
req.Header.Set("Accept", "application/vnd.github.v3+json")
|
||||
req.Header.Set("User-Agent", "secubox-cli/"+version)
|
||||
|
||||
resp, err := client.Do(req)
|
||||
resp, err := httpClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode == http.StatusNotFound {
|
||||
if version == "" {
|
||||
if ver == "" {
|
||||
return nil, fmt.Errorf("no releases found")
|
||||
}
|
||||
return nil, fmt.Errorf("release %s not found", version)
|
||||
return nil, fmt.Errorf("release %s not found", ver)
|
||||
}
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
|
|
@ -347,8 +360,7 @@ func downloadWithProgress(url, destPath string, totalSize int64) error {
|
|||
defer out.Close()
|
||||
|
||||
// Start download
|
||||
client := &http.Client{Timeout: defaultTimeout}
|
||||
resp, err := client.Get(url)
|
||||
resp, err := httpClient.Get(url)
|
||||
if err != nil {
|
||||
return fmt.Errorf("download: %w", err)
|
||||
}
|
||||
|
|
@ -445,8 +457,7 @@ func (pr *progressReader) printProgress() {
|
|||
|
||||
func verifyChecksum(filePath string, checksumAsset *GitHubAsset, imageName string) error {
|
||||
// Download checksum file
|
||||
client := &http.Client{Timeout: 30 * time.Second}
|
||||
resp, err := client.Get(checksumAsset.BrowserDownloadURL)
|
||||
resp, err := httpClient.Get(checksumAsset.BrowserDownloadURL)
|
||||
if err != nil {
|
||||
return fmt.Errorf("download checksum: %w", err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package cmd
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
|
|
@ -225,7 +226,7 @@ type mockReader struct {
|
|||
|
||||
func (m *mockReader) Read(p []byte) (int, error) {
|
||||
if m.pos >= len(m.data) {
|
||||
return 0, fmt.Errorf("EOF")
|
||||
return 0, io.EOF
|
||||
}
|
||||
n := copy(p, m.data[m.pos:])
|
||||
m.pos += n
|
||||
|
|
|
|||
|
|
@ -10,18 +10,32 @@ import (
|
|||
)
|
||||
|
||||
var (
|
||||
cfgFile string
|
||||
verbose bool
|
||||
version = "2.8.0"
|
||||
cfgFile string
|
||||
verbose bool
|
||||
version = "2.8.0"
|
||||
buildTime = "unknown"
|
||||
commit = "unknown"
|
||||
)
|
||||
|
||||
// SetVersionInfo sets build-time version information
|
||||
func SetVersionInfo(v, bt, c string) {
|
||||
if v != "" {
|
||||
version = v
|
||||
}
|
||||
if bt != "" {
|
||||
buildTime = bt
|
||||
}
|
||||
if c != "" {
|
||||
commit = c
|
||||
}
|
||||
}
|
||||
|
||||
var rootCmd = &cobra.Command{
|
||||
Use: "secubox",
|
||||
Short: "SecuBox Image Generator & Manager",
|
||||
Long: `SecuBox CLI tool for profile-based image generation,
|
||||
building, fetching pre-built images, and OTA updates.
|
||||
|
||||
Version: ` + version,
|
||||
building, fetching pre-built images, and OTA updates.`,
|
||||
Version: version,
|
||||
}
|
||||
|
||||
func Execute() error {
|
||||
|
|
@ -32,6 +46,9 @@ func init() {
|
|||
cobra.OnInitialize(initConfig)
|
||||
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default: /etc/secubox/secubox.yaml)")
|
||||
rootCmd.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "verbose output")
|
||||
|
||||
// Set version template
|
||||
rootCmd.SetVersionTemplate(fmt.Sprintf("secubox version %s\nBuild: %s\nCommit: %s\n", version, buildTime, commit))
|
||||
}
|
||||
|
||||
func initConfig() {
|
||||
|
|
|
|||
|
|
@ -17,6 +17,9 @@ import (
|
|||
// ValidStages lists all valid build stages in order
|
||||
var ValidStages = []string{"rootfs", "partition", "boot", "compress", "checksums"}
|
||||
|
||||
// Package-level compiled regex for partition size parsing
|
||||
var partitionSizeRe = regexp.MustCompile(`^(\d+)([KMGT])$`)
|
||||
|
||||
// Options holds builder configuration
|
||||
type Options struct {
|
||||
Manifest *manifest.Manifest
|
||||
|
|
@ -82,8 +85,7 @@ func ParsePartitionSize(size string) (int64, error) {
|
|||
return 0, fmt.Errorf("empty size string")
|
||||
}
|
||||
|
||||
re := regexp.MustCompile(`^(\d+)([KMGT])$`)
|
||||
matches := re.FindStringSubmatch(strings.ToUpper(size))
|
||||
matches := partitionSizeRe.FindStringSubmatch(strings.ToUpper(size))
|
||||
if len(matches) != 3 {
|
||||
return 0, fmt.Errorf("invalid size format: %s", size)
|
||||
}
|
||||
|
|
@ -166,9 +168,11 @@ func (b *Builder) RunStage(stage string) ([]string, error) {
|
|||
return cmds, nil
|
||||
}
|
||||
|
||||
// execCommand executes a shell command
|
||||
// execCommand executes a shell command with error handling
|
||||
func (b *Builder) execCommand(cmd string) error {
|
||||
c := exec.Command("sh", "-c", cmd)
|
||||
// Wrap command with 'set -e' for fail-fast behavior
|
||||
wrappedCmd := fmt.Sprintf("set -e\n%s", cmd)
|
||||
c := exec.Command("sh", "-c", wrappedCmd)
|
||||
c.Stdout = os.Stdout
|
||||
c.Stderr = os.Stderr
|
||||
return c.Run()
|
||||
|
|
|
|||
|
|
@ -200,50 +200,62 @@ func (b *Builder) stagePartition() ([]string, error) {
|
|||
imagePath, dataStart, dataEnd,
|
||||
))
|
||||
|
||||
// Set up loop device
|
||||
cmds = append(cmds, fmt.Sprintf(
|
||||
"LOOPDEV=$(losetup --find --show --partscan %s)",
|
||||
imagePath,
|
||||
))
|
||||
|
||||
// Format partitions
|
||||
cmds = append(cmds, "mkfs.vfat -F 32 -n ESP ${LOOPDEV}p1")
|
||||
cmds = append(cmds, "mkfs.ext4 -L rootfs ${LOOPDEV}p2")
|
||||
cmds = append(cmds, "mkfs.ext4 -L data ${LOOPDEV}p3")
|
||||
|
||||
// Mount partitions and copy rootfs
|
||||
// Mount operations as single script with cleanup trap
|
||||
rootfs := b.rootfsPath()
|
||||
mntDir := filepath.Join(b.outputDir, "mnt")
|
||||
|
||||
cmds = append(cmds, fmt.Sprintf("mkdir -p %s", mntDir))
|
||||
cmds = append(cmds, fmt.Sprintf("mount ${LOOPDEV}p2 %s", mntDir))
|
||||
cmds = append(cmds, fmt.Sprintf("mkdir -p %s/boot/efi", mntDir))
|
||||
cmds = append(cmds, fmt.Sprintf("mount ${LOOPDEV}p1 %s/boot/efi", mntDir))
|
||||
cmds = append(cmds, fmt.Sprintf("mkdir -p %s/srv", mntDir))
|
||||
cmds = append(cmds, fmt.Sprintf("mount ${LOOPDEV}p3 %s/srv", mntDir))
|
||||
|
||||
// Copy rootfs to image
|
||||
cmds = append(cmds, fmt.Sprintf(
|
||||
"cp -a %s/* %s/",
|
||||
rootfs, mntDir,
|
||||
))
|
||||
|
||||
// Generate fstab
|
||||
// Generate fstab content
|
||||
fstab := `# /etc/fstab - SecuBox generated
|
||||
LABEL=rootfs / ext4 errors=remount-ro 0 1
|
||||
LABEL=ESP /boot/efi vfat umask=0077 0 2
|
||||
LABEL=data /srv ext4 defaults 0 2
|
||||
`
|
||||
cmds = append(cmds, fmt.Sprintf(
|
||||
"echo '%s' > %s/etc/fstab",
|
||||
fstab, mntDir,
|
||||
))
|
||||
|
||||
// Unmount and cleanup
|
||||
cmds = append(cmds, fmt.Sprintf("umount %s/srv", mntDir))
|
||||
cmds = append(cmds, fmt.Sprintf("umount %s/boot/efi", mntDir))
|
||||
cmds = append(cmds, fmt.Sprintf("umount %s", mntDir))
|
||||
cmds = append(cmds, "losetup -d ${LOOPDEV}")
|
||||
// Single script with trap for cleanup on failure
|
||||
mountScript := fmt.Sprintf(`set -e
|
||||
|
||||
# Set up loop device
|
||||
LOOPDEV=$(losetup --find --show --partscan %s)
|
||||
|
||||
# Cleanup function
|
||||
cleanup() {
|
||||
umount %s/srv 2>/dev/null || true
|
||||
umount %s/boot/efi 2>/dev/null || true
|
||||
umount %s 2>/dev/null || true
|
||||
losetup -d $LOOPDEV 2>/dev/null || true
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
# Format partitions
|
||||
mkfs.vfat -F 32 -n ESP ${LOOPDEV}p1
|
||||
mkfs.ext4 -L rootfs ${LOOPDEV}p2
|
||||
mkfs.ext4 -L data ${LOOPDEV}p3
|
||||
|
||||
# Mount partitions
|
||||
mkdir -p %s
|
||||
mount ${LOOPDEV}p2 %s
|
||||
mkdir -p %s/boot/efi
|
||||
mount ${LOOPDEV}p1 %s/boot/efi
|
||||
mkdir -p %s/srv
|
||||
mount ${LOOPDEV}p3 %s/srv
|
||||
|
||||
# Copy rootfs to image
|
||||
cp -a %s/* %s/
|
||||
|
||||
# Generate fstab
|
||||
cat > %s/etc/fstab << 'FSTAB_EOF'
|
||||
%sFSTAB_EOF
|
||||
|
||||
# Cleanup runs via trap on exit
|
||||
`,
|
||||
imagePath,
|
||||
mntDir, mntDir, mntDir,
|
||||
mntDir, mntDir, mntDir, mntDir, mntDir, mntDir,
|
||||
rootfs, mntDir,
|
||||
mntDir, fstab,
|
||||
)
|
||||
|
||||
cmds = append(cmds, mountScript)
|
||||
|
||||
return cmds, nil
|
||||
}
|
||||
|
|
@ -258,31 +270,51 @@ func (b *Builder) stageBoot() ([]string, error) {
|
|||
bootMethod = "uboot" // Default for ARM
|
||||
}
|
||||
|
||||
// Set up loop device again for boot installation
|
||||
cmds = append(cmds, fmt.Sprintf(
|
||||
"LOOPDEV=$(losetup --find --show --partscan %s)",
|
||||
imagePath,
|
||||
))
|
||||
|
||||
mntDir := filepath.Join(b.outputDir, "mnt")
|
||||
cmds = append(cmds, fmt.Sprintf("mount ${LOOPDEV}p2 %s", mntDir))
|
||||
cmds = append(cmds, fmt.Sprintf("mount ${LOOPDEV}p1 %s/boot/efi", mntDir))
|
||||
|
||||
// Get boot-specific commands
|
||||
var bootCmds []string
|
||||
switch bootMethod {
|
||||
case "uboot":
|
||||
cmds = append(cmds, b.installUBoot(mntDir)...)
|
||||
bootCmds = b.installUBoot(mntDir)
|
||||
case "grub":
|
||||
cmds = append(cmds, b.installGrub(mntDir)...)
|
||||
bootCmds = b.installGrub(mntDir)
|
||||
case "extlinux":
|
||||
cmds = append(cmds, b.installExtlinux(mntDir)...)
|
||||
bootCmds = b.installExtlinux(mntDir)
|
||||
default:
|
||||
cmds = append(cmds, fmt.Sprintf("# Unknown boot method: %s", bootMethod))
|
||||
bootCmds = []string{fmt.Sprintf("echo 'Unknown boot method: %s'", bootMethod)}
|
||||
}
|
||||
|
||||
// Unmount
|
||||
cmds = append(cmds, fmt.Sprintf("umount %s/boot/efi", mntDir))
|
||||
cmds = append(cmds, fmt.Sprintf("umount %s", mntDir))
|
||||
cmds = append(cmds, "losetup -d ${LOOPDEV}")
|
||||
// Single script with trap for cleanup on failure
|
||||
bootScript := fmt.Sprintf(`set -e
|
||||
|
||||
# Set up loop device
|
||||
LOOPDEV=$(losetup --find --show --partscan %s)
|
||||
|
||||
# Cleanup function
|
||||
cleanup() {
|
||||
umount %s/boot/efi 2>/dev/null || true
|
||||
umount %s 2>/dev/null || true
|
||||
losetup -d $LOOPDEV 2>/dev/null || true
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
# Mount partitions
|
||||
mount ${LOOPDEV}p2 %s
|
||||
mount ${LOOPDEV}p1 %s/boot/efi
|
||||
|
||||
# Boot installation commands
|
||||
%s
|
||||
|
||||
# Cleanup runs via trap on exit
|
||||
`,
|
||||
imagePath,
|
||||
mntDir, mntDir,
|
||||
mntDir, mntDir,
|
||||
strings.Join(bootCmds, "\n"),
|
||||
)
|
||||
|
||||
cmds = append(cmds, bootScript)
|
||||
|
||||
return cmds, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,9 @@ import (
|
|||
"strings"
|
||||
)
|
||||
|
||||
// Package-level compiled regex for performance
|
||||
var memTotalRe = regexp.MustCompile(`MemTotal:\s+(\d+)\s+kB`)
|
||||
|
||||
// Info holds detected hardware information
|
||||
type Info struct {
|
||||
Board string
|
||||
|
|
@ -102,6 +105,18 @@ func detectCPU() (string, int) {
|
|||
}
|
||||
}
|
||||
|
||||
// Check for scanner errors
|
||||
if err := scanner.Err(); err != nil {
|
||||
// Log error but continue with what we have
|
||||
if cores == 0 {
|
||||
cores = runtime.NumCPU()
|
||||
}
|
||||
if model == "" {
|
||||
model = "unknown"
|
||||
}
|
||||
return model, cores
|
||||
}
|
||||
|
||||
// Fallback to runtime if no cores found
|
||||
if cores == 0 {
|
||||
cores = runtime.NumCPU()
|
||||
|
|
@ -122,15 +137,23 @@ func detectRAM() uint64 {
|
|||
defer file.Close()
|
||||
|
||||
scanner := bufio.NewScanner(file)
|
||||
re := regexp.MustCompile(`MemTotal:\s+(\d+)\s+kB`)
|
||||
|
||||
for scanner.Scan() {
|
||||
matches := re.FindStringSubmatch(scanner.Text())
|
||||
matches := memTotalRe.FindStringSubmatch(scanner.Text())
|
||||
if len(matches) == 2 {
|
||||
kb, _ := strconv.ParseUint(matches[1], 10, 64)
|
||||
kb, err := strconv.ParseUint(matches[1], 10, 64)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return kb * 1024 // Convert to bytes
|
||||
}
|
||||
}
|
||||
|
||||
// Check for scanner errors
|
||||
if err := scanner.Err(); err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
|
|
|
|||
160
cmd/secubox/internal/hardware/detect_test.go
Normal file
160
cmd/secubox/internal/hardware/detect_test.go
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
package hardware
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestDetect(t *testing.T) {
|
||||
info, err := Detect()
|
||||
if err != nil {
|
||||
t.Fatalf("Detect() error = %v", err)
|
||||
}
|
||||
|
||||
if info == nil {
|
||||
t.Fatal("Detect() returned nil")
|
||||
}
|
||||
|
||||
// Arch should always be detected
|
||||
if info.Arch == "" {
|
||||
t.Error("Arch should not be empty")
|
||||
}
|
||||
|
||||
// CPUCores should be at least 1
|
||||
if info.CPUCores < 1 {
|
||||
t.Errorf("CPUCores = %d, want >= 1", info.CPUCores)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSuggestTier(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
ramTotalMB uint64
|
||||
want string
|
||||
}{
|
||||
{"lite - 1GB", 1024, "tier-lite"},
|
||||
{"lite - 2GB", 2048, "tier-lite"},
|
||||
{"standard - 4GB", 4096, "tier-standard"},
|
||||
{"standard - 6GB", 6144, "tier-standard"},
|
||||
{"pro - 8GB", 8192, "tier-pro"},
|
||||
{"pro - 16GB", 16384, "tier-pro"},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
info := &Info{RAMTotalMB: tt.ramTotalMB}
|
||||
got := info.SuggestTier()
|
||||
if got != tt.want {
|
||||
t.Errorf("SuggestTier() = %q, want %q", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestInfoString(t *testing.T) {
|
||||
info := &Info{
|
||||
Board: "mochabin",
|
||||
Arch: "arm64",
|
||||
CPUModel: "Test CPU",
|
||||
CPUCores: 4,
|
||||
RAMTotalMB: 8192,
|
||||
}
|
||||
|
||||
s := info.String()
|
||||
if s == "" {
|
||||
t.Error("String() returned empty string")
|
||||
}
|
||||
|
||||
// Check that key information is present
|
||||
if !contains(s, "mochabin") {
|
||||
t.Error("String() should contain board name")
|
||||
}
|
||||
if !contains(s, "arm64") {
|
||||
t.Error("String() should contain arch")
|
||||
}
|
||||
if !contains(s, "8192") {
|
||||
t.Error("String() should contain RAM")
|
||||
}
|
||||
}
|
||||
|
||||
func TestIdentifyBoardFromModel(t *testing.T) {
|
||||
tests := []struct {
|
||||
model string
|
||||
want string
|
||||
}{
|
||||
{"GlobalScale MOCHAbin", "mochabin"},
|
||||
{"Globalscale ESPRESSObin", "espressobin-v7"},
|
||||
{"ESPRESSObin Ultra", "espressobin-ultra"},
|
||||
{"Raspberry Pi 4 Model B", "rpi4"},
|
||||
{"Raspberry Pi 5", "rpi5"},
|
||||
{"Raspberry Pi 400", "rpi400"},
|
||||
{"Marvell Armada 7040", "mochabin"},
|
||||
{"Marvell Armada 3720", "espressobin-v7"},
|
||||
{"Unknown Board", ""},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.model, func(t *testing.T) {
|
||||
got := identifyBoardFromModel(tt.model)
|
||||
if got != tt.want {
|
||||
t.Errorf("identifyBoardFromModel(%q) = %q, want %q", tt.model, got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestIdentifyBoardFromCompatible(t *testing.T) {
|
||||
tests := []struct {
|
||||
compatible string
|
||||
want string
|
||||
}{
|
||||
{"globalscale,mochabin", "mochabin"},
|
||||
{"globalscale,espressobin", "espressobin-v7"},
|
||||
{"raspberrypi,4-model-b", "rpi4"},
|
||||
{"raspberrypi,400", "rpi400"},
|
||||
{"unknown,board", ""},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.compatible, func(t *testing.T) {
|
||||
got := identifyBoardFromCompatible(tt.compatible)
|
||||
if got != tt.want {
|
||||
t.Errorf("identifyBoardFromCompatible(%q) = %q, want %q", tt.compatible, got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestIdentifyBoardFromDMI(t *testing.T) {
|
||||
tests := []struct {
|
||||
product string
|
||||
want string
|
||||
}{
|
||||
{"VirtualBox", "vm-x64"},
|
||||
{"VMware Virtual Machine", "vm-x64"},
|
||||
{"QEMU KVM", "vm-x64"},
|
||||
{"Dell PowerEdge", ""},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.product, func(t *testing.T) {
|
||||
got := identifyBoardFromDMI(tt.product)
|
||||
if got != tt.want {
|
||||
t.Errorf("identifyBoardFromDMI(%q) = %q, want %q", tt.product, got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function
|
||||
func contains(s, substr string) bool {
|
||||
return len(s) >= len(substr) && (s == substr || len(s) > 0 && containsSubstr(s, substr))
|
||||
}
|
||||
|
||||
func containsSubstr(s, substr string) bool {
|
||||
for i := 0; i <= len(s)-len(substr); i++ {
|
||||
if s[i:i+len(substr)] == substr {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
|
@ -58,6 +58,57 @@ type BootState struct {
|
|||
IsRecovery bool
|
||||
}
|
||||
|
||||
// atomicWriteFile writes data to a file atomically using temp file + rename.
|
||||
// This prevents partial writes and race conditions.
|
||||
func atomicWriteFile(path string, data []byte, perm os.FileMode) error {
|
||||
dir := filepath.Dir(path)
|
||||
|
||||
// Create temp file in same directory (required for atomic rename)
|
||||
tmpFile, err := os.CreateTemp(dir, ".tmp-*")
|
||||
if err != nil {
|
||||
return fmt.Errorf("create temp file: %w", err)
|
||||
}
|
||||
tmpPath := tmpFile.Name()
|
||||
|
||||
// Clean up temp file on any error
|
||||
defer func() {
|
||||
if tmpPath != "" {
|
||||
os.Remove(tmpPath)
|
||||
}
|
||||
}()
|
||||
|
||||
// Set permissions before writing content
|
||||
if err := tmpFile.Chmod(perm); err != nil {
|
||||
tmpFile.Close()
|
||||
return fmt.Errorf("chmod temp file: %w", err)
|
||||
}
|
||||
|
||||
// Write data
|
||||
if _, err := tmpFile.Write(data); err != nil {
|
||||
tmpFile.Close()
|
||||
return fmt.Errorf("write temp file: %w", err)
|
||||
}
|
||||
|
||||
// Sync to disk
|
||||
if err := tmpFile.Sync(); err != nil {
|
||||
tmpFile.Close()
|
||||
return fmt.Errorf("sync temp file: %w", err)
|
||||
}
|
||||
|
||||
if err := tmpFile.Close(); err != nil {
|
||||
return fmt.Errorf("close temp file: %w", err)
|
||||
}
|
||||
|
||||
// Atomic rename
|
||||
if err := os.Rename(tmpPath, path); err != nil {
|
||||
return fmt.Errorf("rename temp file: %w", err)
|
||||
}
|
||||
|
||||
// Clear tmpPath so defer doesn't try to remove
|
||||
tmpPath = ""
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetActiveSlot reads the active boot slot from the boot control file
|
||||
func GetActiveSlot() (Slot, error) {
|
||||
data, err := os.ReadFile(ActiveSlotFile)
|
||||
|
|
@ -143,7 +194,7 @@ func GetBootState() (*BootState, error) {
|
|||
}, nil
|
||||
}
|
||||
|
||||
// SetActiveSlot writes the active slot to the boot control file
|
||||
// SetActiveSlot writes the active slot to the boot control file atomically
|
||||
func SetActiveSlot(slot Slot) error {
|
||||
if slot != SlotA && slot != SlotB {
|
||||
return fmt.Errorf("invalid slot: %s", slot)
|
||||
|
|
@ -154,14 +205,15 @@ func SetActiveSlot(slot Slot) error {
|
|||
return fmt.Errorf("create boot control dir: %w", err)
|
||||
}
|
||||
|
||||
if err := os.WriteFile(ActiveSlotFile, []byte(string(slot)+"\n"), 0644); err != nil {
|
||||
// Use atomic write: write to temp file then rename
|
||||
if err := atomicWriteFile(ActiveSlotFile, []byte(string(slot)+"\n"), 0600); err != nil {
|
||||
return fmt.Errorf("write active slot: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetFallbackSlot writes the fallback slot to the boot control file
|
||||
// SetFallbackSlot writes the fallback slot to the boot control file atomically
|
||||
func SetFallbackSlot(slot Slot) error {
|
||||
if slot != SlotA && slot != SlotB {
|
||||
return fmt.Errorf("invalid slot: %s", slot)
|
||||
|
|
@ -172,14 +224,15 @@ func SetFallbackSlot(slot Slot) error {
|
|||
return fmt.Errorf("create boot control dir: %w", err)
|
||||
}
|
||||
|
||||
if err := os.WriteFile(FallbackSlotFile, []byte(string(slot)+"\n"), 0644); err != nil {
|
||||
// Use atomic write with restrictive permissions
|
||||
if err := atomicWriteFile(FallbackSlotFile, []byte(string(slot)+"\n"), 0600); err != nil {
|
||||
return fmt.Errorf("write fallback slot: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetBootCount sets the boot count value
|
||||
// SetBootCount sets the boot count value atomically
|
||||
func SetBootCount(count int) error {
|
||||
if count < 0 {
|
||||
count = 0
|
||||
|
|
@ -190,7 +243,8 @@ func SetBootCount(count int) error {
|
|||
return fmt.Errorf("create boot control dir: %w", err)
|
||||
}
|
||||
|
||||
if err := os.WriteFile(BootCountFile, []byte(strconv.Itoa(count)+"\n"), 0644); err != nil {
|
||||
// Use atomic write with restrictive permissions
|
||||
if err := atomicWriteFile(BootCountFile, []byte(strconv.Itoa(count)+"\n"), 0600); err != nil {
|
||||
return fmt.Errorf("write boot count: %w", err)
|
||||
}
|
||||
|
||||
|
|
@ -312,13 +366,29 @@ func findRootDevice() (string, error) {
|
|||
|
||||
// extractBaseDevice extracts the base device from a partition device
|
||||
// e.g., /dev/mmcblk0p2 -> /dev/mmcblk0
|
||||
// e.g., /dev/nvme0n1p2 -> /dev/nvme0n1
|
||||
// e.g., /dev/sda2 -> /dev/sda
|
||||
// e.g., /dev/loop0p1 -> /dev/loop0
|
||||
func extractBaseDevice(partDev string) string {
|
||||
// Handle mmcblk and nvme style (e.g., /dev/mmcblk0p2 -> /dev/mmcblk0)
|
||||
if strings.Contains(partDev, "mmcblk") || strings.Contains(partDev, "nvme") {
|
||||
idx := strings.LastIndex(partDev, "p")
|
||||
if idx > 0 {
|
||||
return partDev[:idx]
|
||||
// Handle devices with 'p' separator before partition number
|
||||
// This includes: mmcblk0p2, nvme0n1p2, loop0p1
|
||||
if strings.Contains(partDev, "mmcblk") || strings.Contains(partDev, "nvme") || strings.Contains(partDev, "loop") {
|
||||
// Find the last 'p' followed by digits only
|
||||
for i := len(partDev) - 1; i >= 0; i-- {
|
||||
if partDev[i] == 'p' {
|
||||
// Check if everything after 'p' is digits
|
||||
suffix := partDev[i+1:]
|
||||
allDigits := len(suffix) > 0
|
||||
for _, c := range suffix {
|
||||
if c < '0' || c > '9' {
|
||||
allDigits = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if allDigits {
|
||||
return partDev[:i]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package profile
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
|
|
@ -38,6 +39,48 @@ func (m *Merger) Resolve(name string) (*Profile, error) {
|
|||
return m.resolveWithPath(name, make(map[string]bool))
|
||||
}
|
||||
|
||||
// ResolveWithArch resolves a tier profile with architecture layer inserted.
|
||||
// Chain: base → arch/<arch> → tier → (optional tweaks)
|
||||
// This is the recommended method for full profile resolution.
|
||||
func (m *Merger) ResolveWithArch(tierName, arch string) (*Profile, error) {
|
||||
// First resolve base
|
||||
base, err := m.Resolve("base")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("resolve base: %w", err)
|
||||
}
|
||||
|
||||
// Check if arch profile exists
|
||||
archProfilePath := filepath.Join(m.profilesDir, "arch", arch+".yaml")
|
||||
var archProfile *Profile
|
||||
if _, statErr := os.Stat(archProfilePath); statErr == nil {
|
||||
// Load arch profile directly (don't follow its inherits, we already have base)
|
||||
archProfile, err = Load(archProfilePath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("load arch profile %s: %w", arch, err)
|
||||
}
|
||||
}
|
||||
|
||||
// Load tier profile directly (don't follow its inherits, we build chain manually)
|
||||
tierProfilePath := filepath.Join(m.profilesDir, tierName+".yaml")
|
||||
tierProfile, err := Load(tierProfilePath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("load tier profile %s: %w", tierName, err)
|
||||
}
|
||||
|
||||
// Build merge chain: base → arch → tier
|
||||
result := base
|
||||
if archProfile != nil {
|
||||
result = m.merge(result, archProfile)
|
||||
}
|
||||
result = m.merge(result, tierProfile)
|
||||
|
||||
// Set final name/description from tier
|
||||
result.Name = tierProfile.Name
|
||||
result.Description = tierProfile.Description
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// resolveWithPath resolves with cycle detection via visited map
|
||||
func (m *Merger) resolveWithPath(name string, visited map[string]bool) (*Profile, error) {
|
||||
// Check for circular inheritance
|
||||
|
|
|
|||
|
|
@ -242,6 +242,154 @@ boot:
|
|||
}
|
||||
}
|
||||
|
||||
func TestResolveWithArch(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
|
||||
// Create base profile
|
||||
base := `
|
||||
name: base
|
||||
packages:
|
||||
required:
|
||||
- secubox-core
|
||||
kernel:
|
||||
version: "6.6"
|
||||
modules:
|
||||
enable:
|
||||
- wireguard
|
||||
sysctl:
|
||||
net.ipv4.ip_forward: 1
|
||||
`
|
||||
if err := os.WriteFile(filepath.Join(dir, "base.yaml"), []byte(base), 0644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Create arch/arm64 profile
|
||||
archDir := filepath.Join(dir, "arch")
|
||||
if err := os.MkdirAll(archDir, 0755); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
archProfile := `
|
||||
name: arch-arm64
|
||||
inherits: base
|
||||
packages:
|
||||
required:
|
||||
- qemu-user-static
|
||||
kernel:
|
||||
modules:
|
||||
enable:
|
||||
- cpufreq_dt
|
||||
sysctl:
|
||||
vm.nr_hugepages: 64
|
||||
`
|
||||
if err := os.WriteFile(filepath.Join(archDir, "arm64.yaml"), []byte(archProfile), 0644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Create tier profile
|
||||
tier := `
|
||||
name: tier-pro
|
||||
inherits: base
|
||||
packages:
|
||||
required:
|
||||
- secubox-full
|
||||
features:
|
||||
dpi: inline
|
||||
`
|
||||
if err := os.WriteFile(filepath.Join(dir, "tier-pro.yaml"), []byte(tier), 0644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
merger := NewMerger(dir)
|
||||
result, err := merger.ResolveWithArch("tier-pro", "arm64")
|
||||
if err != nil {
|
||||
t.Fatalf("ResolveWithArch() error = %v", err)
|
||||
}
|
||||
|
||||
// Should have base + arch + tier packages merged
|
||||
required := result.Packages.Required
|
||||
if !contains(required, "secubox-core") {
|
||||
t.Errorf("missing secubox-core from base")
|
||||
}
|
||||
if !contains(required, "qemu-user-static") {
|
||||
t.Errorf("missing qemu-user-static from arch/arm64")
|
||||
}
|
||||
if !contains(required, "secubox-full") {
|
||||
t.Errorf("missing secubox-full from tier-pro")
|
||||
}
|
||||
|
||||
// Should have merged kernel modules
|
||||
modules := result.Kernel.Modules.Enable
|
||||
if !contains(modules, "wireguard") {
|
||||
t.Errorf("missing wireguard from base")
|
||||
}
|
||||
if !contains(modules, "cpufreq_dt") {
|
||||
t.Errorf("missing cpufreq_dt from arch/arm64")
|
||||
}
|
||||
|
||||
// Should have merged sysctl (arch overrides base for same key)
|
||||
if result.Sysctl["net.ipv4.ip_forward"] != 1 {
|
||||
t.Errorf("sysctl net.ipv4.ip_forward = %v, want 1", result.Sysctl["net.ipv4.ip_forward"])
|
||||
}
|
||||
if result.Sysctl["vm.nr_hugepages"] != 64 {
|
||||
t.Errorf("sysctl vm.nr_hugepages = %v, want 64", result.Sysctl["vm.nr_hugepages"])
|
||||
}
|
||||
|
||||
// Final name should be from tier
|
||||
if result.Name != "tier-pro" {
|
||||
t.Errorf("Name = %q, want tier-pro", result.Name)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolveWithArch_NoArchProfile(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
|
||||
// Create base profile
|
||||
base := `
|
||||
name: base
|
||||
packages:
|
||||
required:
|
||||
- secubox-core
|
||||
`
|
||||
if err := os.WriteFile(filepath.Join(dir, "base.yaml"), []byte(base), 0644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Create tier profile (no arch/ directory)
|
||||
tier := `
|
||||
name: tier-lite
|
||||
inherits: base
|
||||
packages:
|
||||
required:
|
||||
- secubox-crowdsec
|
||||
`
|
||||
if err := os.WriteFile(filepath.Join(dir, "tier-lite.yaml"), []byte(tier), 0644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
merger := NewMerger(dir)
|
||||
result, err := merger.ResolveWithArch("tier-lite", "riscv64")
|
||||
if err != nil {
|
||||
t.Fatalf("ResolveWithArch() should succeed without arch profile, got error = %v", err)
|
||||
}
|
||||
|
||||
// Should still merge base + tier
|
||||
if !contains(result.Packages.Required, "secubox-core") {
|
||||
t.Errorf("missing secubox-core from base")
|
||||
}
|
||||
if !contains(result.Packages.Required, "secubox-crowdsec") {
|
||||
t.Errorf("missing secubox-crowdsec from tier-lite")
|
||||
}
|
||||
}
|
||||
|
||||
func contains(slice []string, item string) bool {
|
||||
for _, s := range slice {
|
||||
if s == item {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func TestLoadTweaks(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
boardDir := filepath.Join(dir, "test-board")
|
||||
|
|
|
|||
|
|
@ -7,7 +7,17 @@ import (
|
|||
"github.com/CyberMind-FR/secubox-deb/cmd/secubox/cmd"
|
||||
)
|
||||
|
||||
// Build-time variables (set via -ldflags)
|
||||
var (
|
||||
Version = "dev"
|
||||
BuildTime = "unknown"
|
||||
Commit = "unknown"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Pass version info to cmd package
|
||||
cmd.SetVersionInfo(Version, BuildTime, Commit)
|
||||
|
||||
if err := cmd.Execute(); err != nil {
|
||||
os.Exit(1)
|
||||
}
|
||||
|
|
|
|||
17
packages/secubox-ad-guard/debian/secubox.yaml
Normal file
17
packages/secubox-ad-guard/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-ad-guard
|
||||
category: misc
|
||||
tier: lite
|
||||
description: "SecuBox Ad Guard Module"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
|
||||
api:
|
||||
socket: /run/secubox/ad-guard.sock
|
||||
health: /api/v1/ad-guard/health
|
||||
|
||||
ui:
|
||||
path: /srv/secubox/www/ad-guard
|
||||
17
packages/secubox-admin/debian/secubox.yaml
Normal file
17
packages/secubox-admin/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-admin
|
||||
category: system
|
||||
tier: lite
|
||||
description: "SecuBox System Administration Dashboard"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
|
||||
api:
|
||||
socket: /run/secubox/admin.sock
|
||||
health: /api/v1/admin/health
|
||||
|
||||
ui:
|
||||
path: /srv/secubox/www/admin
|
||||
17
packages/secubox-ai-gateway/debian/secubox.yaml
Normal file
17
packages/secubox-ai-gateway/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-ai-gateway
|
||||
category: ai
|
||||
tier: pro
|
||||
description: "SecuBox Ai-gateway Module"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
|
||||
api:
|
||||
socket: /run/secubox/ai-gateway.sock
|
||||
health: /api/v1/ai-gateway/health
|
||||
|
||||
ui:
|
||||
path: /srv/secubox/www/ai-gateway
|
||||
17
packages/secubox-ai-insights/debian/secubox.yaml
Normal file
17
packages/secubox-ai-insights/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-ai-insights
|
||||
category: ai
|
||||
tier: pro
|
||||
description: "SecuBox AI Insights - ML-based Threat Detection"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
|
||||
api:
|
||||
socket: /run/secubox/ai-insights.sock
|
||||
health: /api/v1/ai-insights/health
|
||||
|
||||
ui:
|
||||
path: /srv/secubox/www/ai-insights
|
||||
17
packages/secubox-auth/debian/secubox.yaml
Normal file
17
packages/secubox-auth/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-auth
|
||||
category: security
|
||||
tier: lite
|
||||
description: "SecuBox Auth Guardian"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
|
||||
api:
|
||||
socket: /run/secubox/auth.sock
|
||||
health: /api/v1/auth/health
|
||||
|
||||
ui:
|
||||
path: /srv/secubox/www/auth
|
||||
17
packages/secubox-avatar/debian/secubox.yaml
Normal file
17
packages/secubox-avatar/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-avatar
|
||||
category: misc
|
||||
tier: lite
|
||||
description: "SecuBox Identity and Avatar Manager"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
|
||||
api:
|
||||
socket: /run/secubox/avatar.sock
|
||||
health: /api/v1/avatar/health
|
||||
|
||||
ui:
|
||||
path: /srv/secubox/www/avatar
|
||||
17
packages/secubox-backup/debian/secubox.yaml
Normal file
17
packages/secubox-backup/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-backup
|
||||
category: system
|
||||
tier: lite
|
||||
description: "SecuBox Backup Module"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
|
||||
api:
|
||||
socket: /run/secubox/backup.sock
|
||||
health: /api/v1/backup/health
|
||||
|
||||
ui:
|
||||
path: /srv/secubox/www/backup
|
||||
17
packages/secubox-c3box/debian/secubox.yaml
Normal file
17
packages/secubox-c3box/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-c3box
|
||||
category: dashboard
|
||||
tier: lite
|
||||
description: "SecuBox C3box Module"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
|
||||
api:
|
||||
socket: /run/secubox/c3box.sock
|
||||
health: /api/v1/c3box/health
|
||||
|
||||
ui:
|
||||
path: /srv/secubox/www/c3box
|
||||
17
packages/secubox-cdn/debian/secubox.yaml
Normal file
17
packages/secubox-cdn/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-cdn
|
||||
category: misc
|
||||
tier: standard
|
||||
description: "SecuBox CDN Cache"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
|
||||
api:
|
||||
socket: /run/secubox/cdn.sock
|
||||
health: /api/v1/cdn/health
|
||||
|
||||
ui:
|
||||
path: /srv/secubox/www/cdn
|
||||
17
packages/secubox-cloner/debian/secubox.yaml
Normal file
17
packages/secubox-cloner/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-cloner
|
||||
category: misc
|
||||
tier: lite
|
||||
description: "SecuBox Cloner - System backup and restore"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
|
||||
api:
|
||||
socket: /run/secubox/cloner.sock
|
||||
health: /api/v1/cloner/health
|
||||
|
||||
ui:
|
||||
path: /srv/secubox/www/cloner
|
||||
17
packages/secubox-config-advisor/debian/secubox.yaml
Normal file
17
packages/secubox-config-advisor/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-config-advisor
|
||||
category: system
|
||||
tier: lite
|
||||
description: "SecuBox Config-advisor Module"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
|
||||
api:
|
||||
socket: /run/secubox/config-advisor.sock
|
||||
health: /api/v1/config-advisor/health
|
||||
|
||||
ui:
|
||||
path: /srv/secubox/www/config-advisor
|
||||
7
packages/secubox-console/debian/secubox.yaml
Normal file
7
packages/secubox-console/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-console
|
||||
category: misc
|
||||
tier: lite
|
||||
description: "SecuBox Console TUI — Terminal Dashboard"
|
||||
17
packages/secubox-cookies/debian/secubox.yaml
Normal file
17
packages/secubox-cookies/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-cookies
|
||||
category: misc
|
||||
tier: lite
|
||||
description: "SecuBox Cookie Tracker"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
|
||||
api:
|
||||
socket: /run/secubox/cookies.sock
|
||||
health: /api/v1/cookies/health
|
||||
|
||||
ui:
|
||||
path: /srv/secubox/www/cookies
|
||||
|
|
@ -1,23 +1,10 @@
|
|||
# packages/secubox-core/debian/secubox.yaml
|
||||
# SecuBox package metadata for meta-script generator
|
||||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-core
|
||||
category: core
|
||||
description:
|
||||
en: SecuBox core libraries and utilities
|
||||
fr: Bibliotheques et utilitaires SecuBox
|
||||
category: system
|
||||
tier: all
|
||||
description: "SecuBox-DEB — bibliothèque centrale et infrastructure"
|
||||
|
||||
requirements:
|
||||
min_ram: 128M
|
||||
arch:
|
||||
- arm64
|
||||
- amd64
|
||||
|
||||
tags:
|
||||
- core
|
||||
- essential
|
||||
- required
|
||||
|
||||
services:
|
||||
- secubox-core.service
|
||||
|
||||
ports: []
|
||||
ui:
|
||||
path: /srv/secubox/www/core
|
||||
|
|
|
|||
17
packages/secubox-crowdsec/debian/secubox.yaml
Normal file
17
packages/secubox-crowdsec/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-crowdsec
|
||||
category: security
|
||||
tier: lite
|
||||
description: "SecuBox CrowdSec Dashboard"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
|
||||
api:
|
||||
socket: /run/secubox/crowdsec.sock
|
||||
health: /api/v1/crowdsec/health
|
||||
|
||||
ui:
|
||||
path: /srv/secubox/www/crowdsec
|
||||
17
packages/secubox-cve-triage/debian/secubox.yaml
Normal file
17
packages/secubox-cve-triage/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-cve-triage
|
||||
category: security
|
||||
tier: lite
|
||||
description: "SecuBox Cve-triage Module"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
|
||||
api:
|
||||
socket: /run/secubox/cve-triage.sock
|
||||
health: /api/v1/cve-triage/health
|
||||
|
||||
ui:
|
||||
path: /srv/secubox/www/cve-triage
|
||||
17
packages/secubox-cyberfeed/debian/secubox.yaml
Normal file
17
packages/secubox-cyberfeed/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-cyberfeed
|
||||
category: misc
|
||||
tier: lite
|
||||
description: "SecuBox CyberFeed - Threat Intelligence Feed Aggregator"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
|
||||
api:
|
||||
socket: /run/secubox/cyberfeed.sock
|
||||
health: /api/v1/cyberfeed/health
|
||||
|
||||
ui:
|
||||
path: /srv/secubox/www/cyberfeed
|
||||
7
packages/secubox-daemon/debian/secubox.yaml
Normal file
7
packages/secubox-daemon/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-daemon
|
||||
category: system
|
||||
tier: lite
|
||||
description: "SecuBox Mesh Daemon - WireGuard mesh with ZKP authentication"
|
||||
17
packages/secubox-device-intel/debian/secubox.yaml
Normal file
17
packages/secubox-device-intel/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-device-intel
|
||||
category: misc
|
||||
tier: lite
|
||||
description: "SecuBox Device-intel Module"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
|
||||
api:
|
||||
socket: /run/secubox/device-intel.sock
|
||||
health: /api/v1/device-intel/health
|
||||
|
||||
ui:
|
||||
path: /srv/secubox/www/device-intel
|
||||
17
packages/secubox-dns-guard/debian/secubox.yaml
Normal file
17
packages/secubox-dns-guard/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-dns-guard
|
||||
category: network
|
||||
tier: lite
|
||||
description: "SecuBox Dns-guard Module"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
|
||||
api:
|
||||
socket: /run/secubox/dns-guard.sock
|
||||
health: /api/v1/dns-guard/health
|
||||
|
||||
ui:
|
||||
path: /srv/secubox/www/dns-guard
|
||||
17
packages/secubox-dns-provider/debian/secubox.yaml
Normal file
17
packages/secubox-dns-provider/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-dns-provider
|
||||
category: network
|
||||
tier: lite
|
||||
description: "SecuBox DNS Provider Module"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
|
||||
api:
|
||||
socket: /run/secubox/dns-provider.sock
|
||||
health: /api/v1/dns-provider/health
|
||||
|
||||
ui:
|
||||
path: /srv/secubox/www/dns-provider
|
||||
17
packages/secubox-dns/debian/secubox.yaml
Normal file
17
packages/secubox-dns/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-dns
|
||||
category: network
|
||||
tier: lite
|
||||
description: "SecuBox Dns Module"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
|
||||
api:
|
||||
socket: /run/secubox/dns.sock
|
||||
health: /api/v1/dns/health
|
||||
|
||||
ui:
|
||||
path: /srv/secubox/www/dns
|
||||
17
packages/secubox-domoticz/debian/secubox.yaml
Normal file
17
packages/secubox-domoticz/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-domoticz
|
||||
category: misc
|
||||
tier: lite
|
||||
description: "Domoticz Home Automation for SecuBox"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
|
||||
api:
|
||||
socket: /run/secubox/domoticz.sock
|
||||
health: /api/v1/domoticz/health
|
||||
|
||||
ui:
|
||||
path: /srv/secubox/www/domoticz
|
||||
17
packages/secubox-dpi/debian/secubox.yaml
Normal file
17
packages/secubox-dpi/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-dpi
|
||||
category: misc
|
||||
tier: pro
|
||||
description: "SecuBox DPI — netifyd Dashboard"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
|
||||
api:
|
||||
socket: /run/secubox/dpi.sock
|
||||
health: /api/v1/dpi/health
|
||||
|
||||
ui:
|
||||
path: /srv/secubox/www/dpi
|
||||
17
packages/secubox-droplet/debian/secubox.yaml
Normal file
17
packages/secubox-droplet/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-droplet
|
||||
category: misc
|
||||
tier: lite
|
||||
description: "SecuBox Droplet File Publisher"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
|
||||
api:
|
||||
socket: /run/secubox/droplet.sock
|
||||
health: /api/v1/droplet/health
|
||||
|
||||
ui:
|
||||
path: /srv/secubox/www/droplet
|
||||
17
packages/secubox-exposure/debian/secubox.yaml
Normal file
17
packages/secubox-exposure/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-exposure
|
||||
category: misc
|
||||
tier: lite
|
||||
description: "SecuBox Exposure Manager"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
|
||||
api:
|
||||
socket: /run/secubox/exposure.sock
|
||||
health: /api/v1/exposure/health
|
||||
|
||||
ui:
|
||||
path: /srv/secubox/www/exposure
|
||||
17
packages/secubox-eye-remote/debian/secubox.yaml
Normal file
17
packages/secubox-eye-remote/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-eye-remote
|
||||
category: dashboard
|
||||
tier: lite
|
||||
description: "SecuBox Eye Remote USB Gadget Integration"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
|
||||
api:
|
||||
socket: /run/secubox/eye-remote.sock
|
||||
health: /api/v1/eye-remote/health
|
||||
|
||||
ui:
|
||||
path: /srv/secubox/www/eye-remote
|
||||
58
packages/secubox-full/debian/secubox.yaml
Normal file
58
packages/secubox-full/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-full
|
||||
category: misc
|
||||
tier: lite
|
||||
description: "SecuBox Full — All 49 modules"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
- secubox-hub
|
||||
- secubox-portal
|
||||
- secubox-system
|
||||
- secubox-crowdsec
|
||||
- secubox-waf
|
||||
- secubox-vortex-firewall
|
||||
- secubox-auth
|
||||
- secubox-nac
|
||||
- secubox-wireguard
|
||||
- secubox-mesh
|
||||
- secubox-p2p
|
||||
- secubox-netmodes
|
||||
- secubox-dpi
|
||||
- secubox-qos
|
||||
- secubox-traffic
|
||||
- secubox-vhost
|
||||
- secubox-haproxy
|
||||
- secubox-cdn
|
||||
- secubox-dns
|
||||
- secubox-vortex-dns
|
||||
- secubox-meshname
|
||||
- secubox-netdata
|
||||
- secubox-mediaflow
|
||||
- secubox-device-intel
|
||||
- secubox-watchdog
|
||||
- secubox-metrics
|
||||
- secubox-soc
|
||||
- secubox-roadmap
|
||||
- secubox-mail
|
||||
- secubox-mail-lxc
|
||||
- secubox-webmail
|
||||
- secubox-webmail-lxc
|
||||
- secubox-users
|
||||
- secubox-gitea
|
||||
- secubox-nextcloud
|
||||
- secubox-droplet
|
||||
- secubox-streamlit
|
||||
- secubox-streamforge
|
||||
- secubox-metablogizer
|
||||
- secubox-publish
|
||||
- secubox-c3box
|
||||
- secubox-backup
|
||||
- secubox-tor
|
||||
- secubox-exposure
|
||||
- secubox-zkp
|
||||
- secubox-mitmproxy
|
||||
- secubox-repo
|
||||
- secubox-hardening
|
||||
17
packages/secubox-gitea/debian/secubox.yaml
Normal file
17
packages/secubox-gitea/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-gitea
|
||||
category: publishing
|
||||
tier: pro
|
||||
description: "SecuBox Gitea Module"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
|
||||
api:
|
||||
socket: /run/secubox/gitea.sock
|
||||
health: /api/v1/gitea/health
|
||||
|
||||
ui:
|
||||
path: /srv/secubox/www/gitea
|
||||
17
packages/secubox-glances/debian/secubox.yaml
Normal file
17
packages/secubox-glances/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-glances
|
||||
category: misc
|
||||
tier: lite
|
||||
description: "SecuBox Glances Dashboard"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
|
||||
api:
|
||||
socket: /run/secubox/glances.sock
|
||||
health: /api/v1/glances/health
|
||||
|
||||
ui:
|
||||
path: /srv/secubox/www/glances
|
||||
17
packages/secubox-gotosocial/debian/secubox.yaml
Normal file
17
packages/secubox-gotosocial/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-gotosocial
|
||||
category: dashboard
|
||||
tier: lite
|
||||
description: "GoToSocial Fediverse server management"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
|
||||
api:
|
||||
socket: /run/secubox/gotosocial.sock
|
||||
health: /api/v1/gotosocial/health
|
||||
|
||||
ui:
|
||||
path: /srv/secubox/www/gotosocial
|
||||
17
packages/secubox-haproxy/debian/secubox.yaml
Normal file
17
packages/secubox-haproxy/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-haproxy
|
||||
category: network
|
||||
tier: standard
|
||||
description: "SecuBox HAProxy Dashboard"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
|
||||
api:
|
||||
socket: /run/secubox/haproxy.sock
|
||||
health: /api/v1/haproxy/health
|
||||
|
||||
ui:
|
||||
path: /srv/secubox/www/haproxy
|
||||
17
packages/secubox-hardening/debian/secubox.yaml
Normal file
17
packages/secubox-hardening/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-hardening
|
||||
category: security
|
||||
tier: lite
|
||||
description: "SecuBox Kernel and System Hardening"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
|
||||
api:
|
||||
socket: /run/secubox/hardening.sock
|
||||
health: /api/v1/hardening/health
|
||||
|
||||
ui:
|
||||
path: /srv/secubox/www/hardening
|
||||
17
packages/secubox-hexo/debian/secubox.yaml
Normal file
17
packages/secubox-hexo/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-hexo
|
||||
category: misc
|
||||
tier: lite
|
||||
description: "Hexo static blog generator management"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
|
||||
api:
|
||||
socket: /run/secubox/hexo.sock
|
||||
health: /api/v1/hexo/health
|
||||
|
||||
ui:
|
||||
path: /srv/secubox/www/hexo
|
||||
17
packages/secubox-homeassistant/debian/secubox.yaml
Normal file
17
packages/secubox-homeassistant/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-homeassistant
|
||||
category: iot
|
||||
tier: lite
|
||||
description: "Home Assistant IoT Hub for SecuBox"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
|
||||
api:
|
||||
socket: /run/secubox/homeassistant.sock
|
||||
health: /api/v1/homeassistant/health
|
||||
|
||||
ui:
|
||||
path: /srv/secubox/www/homeassistant
|
||||
17
packages/secubox-hub/debian/secubox.yaml
Normal file
17
packages/secubox-hub/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-hub
|
||||
category: system
|
||||
tier: all
|
||||
description: "SecuBox Hub — Tableau de bord central"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
|
||||
api:
|
||||
socket: /run/secubox/hub.sock
|
||||
health: /api/v1/hub/health
|
||||
|
||||
ui:
|
||||
path: /srv/secubox/www/hub
|
||||
17
packages/secubox-identity/debian/secubox.yaml
Normal file
17
packages/secubox-identity/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-identity
|
||||
category: misc
|
||||
tier: lite
|
||||
description: "SecuBox Identity Module"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
|
||||
api:
|
||||
socket: /run/secubox/identity.sock
|
||||
health: /api/v1/identity/health
|
||||
|
||||
ui:
|
||||
path: /srv/secubox/www/identity
|
||||
17
packages/secubox-interceptor/debian/secubox.yaml
Normal file
17
packages/secubox-interceptor/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-interceptor
|
||||
category: misc
|
||||
tier: lite
|
||||
description: "SecuBox Traffic Interceptor"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
|
||||
api:
|
||||
socket: /run/secubox/interceptor.sock
|
||||
health: /api/v1/interceptor/health
|
||||
|
||||
ui:
|
||||
path: /srv/secubox/www/interceptor
|
||||
17
packages/secubox-iot-guard/debian/secubox.yaml
Normal file
17
packages/secubox-iot-guard/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-iot-guard
|
||||
category: iot
|
||||
tier: lite
|
||||
description: "SecuBox Iot-guard Module"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
|
||||
api:
|
||||
socket: /run/secubox/iot-guard.sock
|
||||
health: /api/v1/iot-guard/health
|
||||
|
||||
ui:
|
||||
path: /srv/secubox/www/iot-guard
|
||||
17
packages/secubox-ipblock/debian/secubox.yaml
Normal file
17
packages/secubox-ipblock/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-ipblock
|
||||
category: misc
|
||||
tier: lite
|
||||
description: "SecuBox IP Blocklist Manager"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
|
||||
api:
|
||||
socket: /run/secubox/ipblock.sock
|
||||
health: /api/v1/ipblock/health
|
||||
|
||||
ui:
|
||||
path: /srv/secubox/www/ipblock
|
||||
17
packages/secubox-jabber/debian/secubox.yaml
Normal file
17
packages/secubox-jabber/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-jabber
|
||||
category: misc
|
||||
tier: lite
|
||||
description: "SecuBox Jabber XMPP Server"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
|
||||
api:
|
||||
socket: /run/secubox/jabber.sock
|
||||
health: /api/v1/jabber/health
|
||||
|
||||
ui:
|
||||
path: /srv/secubox/www/jabber
|
||||
17
packages/secubox-jellyfin/debian/secubox.yaml
Normal file
17
packages/secubox-jellyfin/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-jellyfin
|
||||
category: media
|
||||
tier: pro
|
||||
description: "Jellyfin media server management"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
|
||||
api:
|
||||
socket: /run/secubox/jellyfin.sock
|
||||
health: /api/v1/jellyfin/health
|
||||
|
||||
ui:
|
||||
path: /srv/secubox/www/jellyfin
|
||||
17
packages/secubox-jitsi/debian/secubox.yaml
Normal file
17
packages/secubox-jitsi/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-jitsi
|
||||
category: misc
|
||||
tier: lite
|
||||
description: "SecuBox Jitsi Meet - Video Conferencing"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
|
||||
api:
|
||||
socket: /run/secubox/jitsi.sock
|
||||
health: /api/v1/jitsi/health
|
||||
|
||||
ui:
|
||||
path: /srv/secubox/www/jitsi
|
||||
17
packages/secubox-ksm/debian/secubox.yaml
Normal file
17
packages/secubox-ksm/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-ksm
|
||||
category: misc
|
||||
tier: lite
|
||||
description: "SecuBox KSM Memory Optimization Dashboard"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
|
||||
api:
|
||||
socket: /run/secubox/ksm.sock
|
||||
health: /api/v1/ksm/health
|
||||
|
||||
ui:
|
||||
path: /srv/secubox/www/ksm
|
||||
10
packages/secubox-led-heartbeat/debian/secubox.yaml
Normal file
10
packages/secubox-led-heartbeat/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-led-heartbeat
|
||||
category: misc
|
||||
tier: lite
|
||||
description: "SecuBox LED heartbeat status indicator"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
18
packages/secubox-lite/debian/secubox.yaml
Normal file
18
packages/secubox-lite/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-lite
|
||||
category: misc
|
||||
tier: lite
|
||||
description: "SecuBox Lite — Essential modules for low-RAM devices"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
- secubox-hub
|
||||
- secubox-portal
|
||||
- secubox-crowdsec
|
||||
- secubox-wireguard
|
||||
- secubox-netmodes
|
||||
- secubox-nac
|
||||
- secubox-system
|
||||
- secubox-hardening
|
||||
17
packages/secubox-localai/debian/secubox.yaml
Normal file
17
packages/secubox-localai/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-localai
|
||||
category: misc
|
||||
tier: lite
|
||||
description: "SecuBox LocalAI - Self-hosted LLM inference"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
|
||||
api:
|
||||
socket: /run/secubox/localai.sock
|
||||
health: /api/v1/localai/health
|
||||
|
||||
ui:
|
||||
path: /srv/secubox/www/localai
|
||||
17
packages/secubox-localrecall/debian/secubox.yaml
Normal file
17
packages/secubox-localrecall/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-localrecall
|
||||
category: misc
|
||||
tier: lite
|
||||
description: "SecuBox Localrecall Module"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
|
||||
api:
|
||||
socket: /run/secubox/localrecall.sock
|
||||
health: /api/v1/localrecall/health
|
||||
|
||||
ui:
|
||||
path: /srv/secubox/www/localrecall
|
||||
17
packages/secubox-lyrion/debian/secubox.yaml
Normal file
17
packages/secubox-lyrion/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-lyrion
|
||||
category: misc
|
||||
tier: lite
|
||||
description: "Lyrion Music Server (LMS) for SecuBox"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
|
||||
api:
|
||||
socket: /run/secubox/lyrion.sock
|
||||
health: /api/v1/lyrion/health
|
||||
|
||||
ui:
|
||||
path: /srv/secubox/www/lyrion
|
||||
17
packages/secubox-mac-guard/debian/secubox.yaml
Normal file
17
packages/secubox-mac-guard/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-mac-guard
|
||||
category: misc
|
||||
tier: lite
|
||||
description: "SecuBox MAC Guard - MAC Address Control"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
|
||||
api:
|
||||
socket: /run/secubox/mac-guard.sock
|
||||
health: /api/v1/mac-guard/health
|
||||
|
||||
ui:
|
||||
path: /srv/secubox/www/mac-guard
|
||||
17
packages/secubox-magicmirror/debian/secubox.yaml
Normal file
17
packages/secubox-magicmirror/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-magicmirror
|
||||
category: misc
|
||||
tier: lite
|
||||
description: "SecuBox MagicMirror management"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
|
||||
api:
|
||||
socket: /run/secubox/magicmirror.sock
|
||||
health: /api/v1/magicmirror/health
|
||||
|
||||
ui:
|
||||
path: /srv/secubox/www/magicmirror
|
||||
17
packages/secubox-mail-lxc/debian/secubox.yaml
Normal file
17
packages/secubox-mail-lxc/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-mail-lxc
|
||||
category: email
|
||||
tier: lite
|
||||
description: "SecuBox Mail LXC Container (Backend)"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
|
||||
api:
|
||||
socket: /run/secubox/mail-lxc.sock
|
||||
health: /api/v1/mail-lxc/health
|
||||
|
||||
ui:
|
||||
path: /srv/secubox/www/mail-lxc
|
||||
17
packages/secubox-mail/debian/secubox.yaml
Normal file
17
packages/secubox-mail/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-mail
|
||||
category: email
|
||||
tier: lite
|
||||
description: "SecuBox Mail Module"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
|
||||
api:
|
||||
socket: /run/secubox/mail.sock
|
||||
health: /api/v1/mail/health
|
||||
|
||||
ui:
|
||||
path: /srv/secubox/www/mail
|
||||
17
packages/secubox-master-link/debian/secubox.yaml
Normal file
17
packages/secubox-master-link/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-master-link
|
||||
category: misc
|
||||
tier: lite
|
||||
description: "SecuBox Master-link Module"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
|
||||
api:
|
||||
socket: /run/secubox/master-link.sock
|
||||
health: /api/v1/master-link/health
|
||||
|
||||
ui:
|
||||
path: /srv/secubox/www/master-link
|
||||
17
packages/secubox-matrix/debian/secubox.yaml
Normal file
17
packages/secubox-matrix/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-matrix
|
||||
category: communication
|
||||
tier: pro
|
||||
description: "SecuBox Matrix Synapse - Federated Chat Server"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
|
||||
api:
|
||||
socket: /run/secubox/matrix.sock
|
||||
health: /api/v1/matrix/health
|
||||
|
||||
ui:
|
||||
path: /srv/secubox/www/matrix
|
||||
17
packages/secubox-mcp-server/debian/secubox.yaml
Normal file
17
packages/secubox-mcp-server/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-mcp-server
|
||||
category: misc
|
||||
tier: lite
|
||||
description: "SecuBox Mcp-server Module"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
|
||||
api:
|
||||
socket: /run/secubox/mcp-server.sock
|
||||
health: /api/v1/mcp-server/health
|
||||
|
||||
ui:
|
||||
path: /srv/secubox/www/mcp-server
|
||||
18
packages/secubox-mediaflow/debian/secubox.yaml
Normal file
18
packages/secubox-mediaflow/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-mediaflow
|
||||
category: media
|
||||
tier: lite
|
||||
description: "SecuBox Media Flow"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
- secubox-dpi
|
||||
|
||||
api:
|
||||
socket: /run/secubox/mediaflow.sock
|
||||
health: /api/v1/mediaflow/health
|
||||
|
||||
ui:
|
||||
path: /srv/secubox/www/mediaflow
|
||||
17
packages/secubox-mesh/debian/secubox.yaml
Normal file
17
packages/secubox-mesh/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-mesh
|
||||
category: vpn
|
||||
tier: lite
|
||||
description: "SecuBox Mesh DNS - Meshname DNS for mesh networks"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
|
||||
api:
|
||||
socket: /run/secubox/mesh.sock
|
||||
health: /api/v1/mesh/health
|
||||
|
||||
ui:
|
||||
path: /srv/secubox/www/mesh
|
||||
17
packages/secubox-meshname/debian/secubox.yaml
Normal file
17
packages/secubox-meshname/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-meshname
|
||||
category: vpn
|
||||
tier: lite
|
||||
description: "SecuBox Meshname Module"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
|
||||
api:
|
||||
socket: /run/secubox/meshname.sock
|
||||
health: /api/v1/meshname/health
|
||||
|
||||
ui:
|
||||
path: /srv/secubox/www/meshname
|
||||
17
packages/secubox-metablogizer/debian/secubox.yaml
Normal file
17
packages/secubox-metablogizer/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-metablogizer
|
||||
category: publishing
|
||||
tier: lite
|
||||
description: "SecuBox MetaBlogizer - Static Site Publisher"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
|
||||
api:
|
||||
socket: /run/secubox/metablogizer.sock
|
||||
health: /api/v1/metablogizer/health
|
||||
|
||||
ui:
|
||||
path: /srv/secubox/www/metablogizer
|
||||
17
packages/secubox-metabolizer/debian/secubox.yaml
Normal file
17
packages/secubox-metabolizer/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-metabolizer
|
||||
category: misc
|
||||
tier: lite
|
||||
description: "SecuBox Metabolizer - Log processor and analyzer"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
|
||||
api:
|
||||
socket: /run/secubox/metabolizer.sock
|
||||
health: /api/v1/metabolizer/health
|
||||
|
||||
ui:
|
||||
path: /srv/secubox/www/metabolizer
|
||||
17
packages/secubox-metacatalog/debian/secubox.yaml
Normal file
17
packages/secubox-metacatalog/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-metacatalog
|
||||
category: misc
|
||||
tier: lite
|
||||
description: "SecuBox Metacatalog - Service catalog and registry"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
|
||||
api:
|
||||
socket: /run/secubox/metacatalog.sock
|
||||
health: /api/v1/metacatalog/health
|
||||
|
||||
ui:
|
||||
path: /srv/secubox/www/metacatalog
|
||||
17
packages/secubox-metoblizer/debian/secubox.yaml
Normal file
17
packages/secubox-metoblizer/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-metoblizer
|
||||
category: misc
|
||||
tier: lite
|
||||
description: "SecuBox centralized log aggregator"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
|
||||
api:
|
||||
socket: /run/secubox/metoblizer.sock
|
||||
health: /api/v1/metoblizer/health
|
||||
|
||||
ui:
|
||||
path: /srv/secubox/www/metoblizer
|
||||
17
packages/secubox-metrics/debian/secubox.yaml
Normal file
17
packages/secubox-metrics/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-metrics
|
||||
category: monitoring
|
||||
tier: lite
|
||||
description: "SecuBox Metrics Dashboard"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
|
||||
api:
|
||||
socket: /run/secubox/metrics.sock
|
||||
health: /api/v1/metrics/health
|
||||
|
||||
ui:
|
||||
path: /srv/secubox/www/metrics
|
||||
17
packages/secubox-mirror/debian/secubox.yaml
Normal file
17
packages/secubox-mirror/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-mirror
|
||||
category: misc
|
||||
tier: lite
|
||||
description: "SecuBox Mirror/CDN Cache"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
|
||||
api:
|
||||
socket: /run/secubox/mirror.sock
|
||||
health: /api/v1/mirror/health
|
||||
|
||||
ui:
|
||||
path: /srv/secubox/www/mirror
|
||||
18
packages/secubox-mitmproxy/debian/secubox.yaml
Normal file
18
packages/secubox-mitmproxy/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-mitmproxy
|
||||
category: misc
|
||||
tier: lite
|
||||
description: "SecuBox Mitmproxy WAF — Web Application Firewall"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
- secubox-haproxy
|
||||
|
||||
api:
|
||||
socket: /run/secubox/mitmproxy.sock
|
||||
health: /api/v1/mitmproxy/health
|
||||
|
||||
ui:
|
||||
path: /srv/secubox/www/mitmproxy
|
||||
17
packages/secubox-mmpm/debian/secubox.yaml
Normal file
17
packages/secubox-mmpm/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-mmpm
|
||||
category: misc
|
||||
tier: lite
|
||||
description: "SecuBox MMPM - MagicMirror Package Manager"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
|
||||
api:
|
||||
socket: /run/secubox/mmpm.sock
|
||||
health: /api/v1/mmpm/health
|
||||
|
||||
ui:
|
||||
path: /srv/secubox/www/mmpm
|
||||
17
packages/secubox-modem/debian/secubox.yaml
Normal file
17
packages/secubox-modem/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-modem
|
||||
category: misc
|
||||
tier: lite
|
||||
description: "SecuBox LTE/5G Modem Management"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
|
||||
api:
|
||||
socket: /run/secubox/modem.sock
|
||||
health: /api/v1/modem/health
|
||||
|
||||
ui:
|
||||
path: /srv/secubox/www/modem
|
||||
17
packages/secubox-mqtt/debian/secubox.yaml
Normal file
17
packages/secubox-mqtt/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-mqtt
|
||||
category: iot
|
||||
tier: lite
|
||||
description: "SecuBox MQTT — Mosquitto Broker Management"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
|
||||
api:
|
||||
socket: /run/secubox/mqtt.sock
|
||||
health: /api/v1/mqtt/health
|
||||
|
||||
ui:
|
||||
path: /srv/secubox/www/mqtt
|
||||
17
packages/secubox-nac/debian/secubox.yaml
Normal file
17
packages/secubox-nac/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-nac
|
||||
category: security
|
||||
tier: lite
|
||||
description: "SecuBox NAC / Client Guardian"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
|
||||
api:
|
||||
socket: /run/secubox/nac.sock
|
||||
health: /api/v1/nac/health
|
||||
|
||||
ui:
|
||||
path: /srv/secubox/www/nac
|
||||
17
packages/secubox-ndpid/debian/secubox.yaml
Normal file
17
packages/secubox-ndpid/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-ndpid
|
||||
category: misc
|
||||
tier: lite
|
||||
description: "SecuBox nDPId Module"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
|
||||
api:
|
||||
socket: /run/secubox/ndpid.sock
|
||||
health: /api/v1/ndpid/health
|
||||
|
||||
ui:
|
||||
path: /srv/secubox/www/ndpid
|
||||
17
packages/secubox-netdata/debian/secubox.yaml
Normal file
17
packages/secubox-netdata/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-netdata
|
||||
category: monitoring
|
||||
tier: lite
|
||||
description: "SecuBox Netdata Dashboard"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
|
||||
api:
|
||||
socket: /run/secubox/netdata.sock
|
||||
health: /api/v1/netdata/health
|
||||
|
||||
ui:
|
||||
path: /srv/secubox/www/netdata
|
||||
17
packages/secubox-netdiag/debian/secubox.yaml
Normal file
17
packages/secubox-netdiag/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-netdiag
|
||||
category: misc
|
||||
tier: lite
|
||||
description: "SecuBox Network Diagnostics — Troubleshooting Tools"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
|
||||
api:
|
||||
socket: /run/secubox/netdiag.sock
|
||||
health: /api/v1/netdiag/health
|
||||
|
||||
ui:
|
||||
path: /srv/secubox/www/netdiag
|
||||
17
packages/secubox-netifyd/debian/secubox.yaml
Normal file
17
packages/secubox-netifyd/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-netifyd
|
||||
category: misc
|
||||
tier: lite
|
||||
description: "SecuBox Netifyd - Network Intelligence Daemon Dashboard"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
|
||||
api:
|
||||
socket: /run/secubox/netifyd.sock
|
||||
health: /api/v1/netifyd/health
|
||||
|
||||
ui:
|
||||
path: /srv/secubox/www/netifyd
|
||||
17
packages/secubox-netmodes/debian/secubox.yaml
Normal file
17
packages/secubox-netmodes/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-netmodes
|
||||
category: network
|
||||
tier: lite
|
||||
description: "SecuBox Network Modes"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
|
||||
api:
|
||||
socket: /run/secubox/netmodes.sock
|
||||
health: /api/v1/netmodes/health
|
||||
|
||||
ui:
|
||||
path: /srv/secubox/www/netmodes
|
||||
17
packages/secubox-nettweak/debian/secubox.yaml
Normal file
17
packages/secubox-nettweak/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-nettweak
|
||||
category: misc
|
||||
tier: lite
|
||||
description: "SecuBox Network Tuning Dashboard"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
|
||||
api:
|
||||
socket: /run/secubox/nettweak.sock
|
||||
health: /api/v1/nettweak/health
|
||||
|
||||
ui:
|
||||
path: /srv/secubox/www/nettweak
|
||||
17
packages/secubox-network-anomaly/debian/secubox.yaml
Normal file
17
packages/secubox-network-anomaly/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-network-anomaly
|
||||
category: network
|
||||
tier: lite
|
||||
description: "SecuBox Network-anomaly Module"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
|
||||
api:
|
||||
socket: /run/secubox/network-anomaly.sock
|
||||
health: /api/v1/network-anomaly/health
|
||||
|
||||
ui:
|
||||
path: /srv/secubox/www/network-anomaly
|
||||
17
packages/secubox-newsbin/debian/secubox.yaml
Normal file
17
packages/secubox-newsbin/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-newsbin
|
||||
category: misc
|
||||
tier: lite
|
||||
description: "Usenet downloader management for SecuBox"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
|
||||
api:
|
||||
socket: /run/secubox/newsbin.sock
|
||||
health: /api/v1/newsbin/health
|
||||
|
||||
ui:
|
||||
path: /srv/secubox/www/newsbin
|
||||
17
packages/secubox-nextcloud/debian/secubox.yaml
Normal file
17
packages/secubox-nextcloud/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-nextcloud
|
||||
category: misc
|
||||
tier: pro
|
||||
description: "SecuBox Nextcloud Module"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
|
||||
api:
|
||||
socket: /run/secubox/nextcloud.sock
|
||||
health: /api/v1/nextcloud/health
|
||||
|
||||
ui:
|
||||
path: /srv/secubox/www/nextcloud
|
||||
17
packages/secubox-ollama/debian/secubox.yaml
Normal file
17
packages/secubox-ollama/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-ollama
|
||||
category: ai
|
||||
tier: pro
|
||||
description: "Local AI inference with Ollama"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
|
||||
api:
|
||||
socket: /run/secubox/ollama.sock
|
||||
health: /api/v1/ollama/health
|
||||
|
||||
ui:
|
||||
path: /srv/secubox/www/ollama
|
||||
17
packages/secubox-openclaw/debian/secubox.yaml
Normal file
17
packages/secubox-openclaw/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-openclaw
|
||||
category: misc
|
||||
tier: lite
|
||||
description: "SecuBox OpenClaw OSINT Module"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
|
||||
api:
|
||||
socket: /run/secubox/openclaw.sock
|
||||
health: /api/v1/openclaw/health
|
||||
|
||||
ui:
|
||||
path: /srv/secubox/www/openclaw
|
||||
17
packages/secubox-ossec/debian/secubox.yaml
Normal file
17
packages/secubox-ossec/debian/secubox.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# debian/secubox.yaml
|
||||
# Auto-generated from debian/control
|
||||
|
||||
name: secubox-ossec
|
||||
category: misc
|
||||
tier: lite
|
||||
description: "SecuBox OSSEC HIDS integration"
|
||||
|
||||
depends:
|
||||
- secubox-core
|
||||
|
||||
api:
|
||||
socket: /run/secubox/ossec.sock
|
||||
health: /api/v1/ossec/health
|
||||
|
||||
ui:
|
||||
path: /srv/secubox/www/ossec
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user