Autarch Will Control The Internet
This commit is contained in:
28
scripts/autarch-web.service
Normal file
28
scripts/autarch-web.service
Normal file
@@ -0,0 +1,28 @@
|
||||
[Unit]
|
||||
Description=AUTARCH Web Dashboard
|
||||
Documentation=file:///home/snake/autarch/GUIDE.md
|
||||
After=network.target
|
||||
Wants=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=snake
|
||||
Group=snake
|
||||
WorkingDirectory=/home/snake/autarch
|
||||
ExecStart=/usr/bin/python3 /home/snake/autarch/autarch.py --web --no-banner
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
StandardOutput=journal
|
||||
StandardError=journal
|
||||
SyslogIdentifier=autarch-web
|
||||
|
||||
# Security hardening
|
||||
NoNewPrivileges=false
|
||||
ProtectHome=false
|
||||
PrivateTmp=true
|
||||
|
||||
# Environment
|
||||
Environment=PYTHONUNBUFFERED=1
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
287
scripts/build-all.ps1
Normal file
287
scripts/build-all.ps1
Normal file
@@ -0,0 +1,287 @@
|
||||
# ═══════════════════════════════════════════════════════════════════════════
|
||||
# AUTARCH — Full Windows Installer Builder
|
||||
#
|
||||
# Auto-installs required tools, then builds:
|
||||
# dist\bin\AUTARCH\AUTARCH.exe — standalone executable bundle
|
||||
# dist\bin\AUTARCH-1.3-win64.msi — Windows installer
|
||||
#
|
||||
# Usage (run as Administrator or allow UAC prompt):
|
||||
# powershell -ExecutionPolicy Bypass -File scripts\build-all.ps1
|
||||
#
|
||||
# What this script installs (if not already present):
|
||||
# - pyinstaller (via pip)
|
||||
# - WiX Toolset 4 (via dotnet tool install --global wix)
|
||||
# - .NET SDK (via winget, if dotnet is missing)
|
||||
# ═══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
param(
|
||||
[string]$Python = "python",
|
||||
[string]$Version = "1.3",
|
||||
[switch]$SkipExe = $false, # Skip .exe build (use existing dist\bin\AUTARCH\)
|
||||
[switch]$SkipMsi = $false # Skip .msi build
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
$AppDir = Split-Path -Parent $PSScriptRoot
|
||||
$BinDir = Join-Path $AppDir "dist\bin"
|
||||
$DistDir = Join-Path $AppDir "dist"
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "████████████████████████████████████████████████████" -ForegroundColor Cyan
|
||||
Write-Host " AUTARCH $Version — Windows Build System" -ForegroundColor Cyan
|
||||
Write-Host "████████████████████████████████████████████████████" -ForegroundColor Cyan
|
||||
Write-Host ""
|
||||
|
||||
# ── Helper functions ──────────────────────────────────────────────────────────
|
||||
function Write-Step([string]$msg) {
|
||||
Write-Host ""
|
||||
Write-Host " ► $msg" -ForegroundColor Yellow
|
||||
}
|
||||
|
||||
function Write-OK([string]$msg) {
|
||||
Write-Host " ✔ $msg" -ForegroundColor Green
|
||||
}
|
||||
|
||||
function Write-Warn([string]$msg) {
|
||||
Write-Host " ⚠ $msg" -ForegroundColor Magenta
|
||||
}
|
||||
|
||||
function Test-Command([string]$cmd) {
|
||||
return $null -ne (Get-Command $cmd -ErrorAction SilentlyContinue)
|
||||
}
|
||||
|
||||
# ── 1. Verify Python ──────────────────────────────────────────────────────────
|
||||
Write-Step "Checking Python..."
|
||||
try {
|
||||
$pyVer = & $Python --version 2>&1
|
||||
Write-OK "$pyVer"
|
||||
} catch {
|
||||
Write-Host "ERROR: Python not found. Install Python 3.10+ from python.org" -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
|
||||
# ── 2. Install / verify PyInstaller ──────────────────────────────────────────
|
||||
Write-Step "Checking PyInstaller..."
|
||||
$piVer = & $Python -c "import PyInstaller; print(PyInstaller.__version__)" 2>&1
|
||||
if ($piVer -match "^\d") {
|
||||
Write-OK "PyInstaller $piVer"
|
||||
} else {
|
||||
Write-Warn "PyInstaller not found — installing..."
|
||||
& $Python -m pip install pyinstaller --quiet
|
||||
$piVer = & $Python -c "import PyInstaller; print(PyInstaller.__version__)" 2>&1
|
||||
Write-OK "PyInstaller $piVer installed"
|
||||
}
|
||||
|
||||
# ── 3. Install / verify .NET SDK (required for WiX 4) ────────────────────────
|
||||
if (-not $SkipMsi) {
|
||||
Write-Step "Checking .NET SDK (required for WiX)..."
|
||||
if (Test-Command "dotnet") {
|
||||
$dotnetVer = (dotnet --version 2>&1)
|
||||
Write-OK ".NET SDK $dotnetVer"
|
||||
} else {
|
||||
Write-Warn ".NET SDK not found — installing via winget..."
|
||||
if (Test-Command "winget") {
|
||||
winget install Microsoft.DotNet.SDK.8 --silent --accept-package-agreements --accept-source-agreements
|
||||
$env:Path = [System.Environment]::GetEnvironmentVariable("Path", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path", "User")
|
||||
if (Test-Command "dotnet") {
|
||||
Write-OK ".NET SDK installed"
|
||||
} else {
|
||||
Write-Host "ERROR: Failed to install .NET SDK. Install manually from https://dot.net" -ForegroundColor Red
|
||||
Write-Host " Then re-run this script." -ForegroundColor Yellow
|
||||
exit 1
|
||||
}
|
||||
} else {
|
||||
Write-Host "ERROR: winget not found. Install .NET SDK 8+ manually from https://dot.net" -ForegroundColor Red
|
||||
Write-Host " Then re-run this script." -ForegroundColor Yellow
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# ── 4. Install / verify WiX Toolset 4 ────────────────────────────────────────
|
||||
if (-not $SkipMsi) {
|
||||
Write-Step "Checking WiX Toolset 4..."
|
||||
$wixOk = $false
|
||||
if (Test-Command "wix") {
|
||||
$wixVer = (wix --version 2>&1)
|
||||
Write-OK "wix $wixVer"
|
||||
$wixOk = $true
|
||||
} else {
|
||||
# Try via dotnet tool
|
||||
$dtWix = (dotnet tool list --global 2>&1) | Select-String "wix"
|
||||
if ($dtWix) {
|
||||
Write-OK "WiX found (dotnet tool)"
|
||||
$wixOk = $true
|
||||
} else {
|
||||
Write-Warn "WiX not found — installing via dotnet tool..."
|
||||
dotnet tool install --global wix --prerelease 2>&1 | Out-Null
|
||||
# Refresh PATH
|
||||
$env:Path += ";$env:USERPROFILE\.dotnet\tools"
|
||||
if (Test-Command "wix") {
|
||||
$wixVer = (wix --version 2>&1)
|
||||
Write-OK "WiX $wixVer installed"
|
||||
$wixOk = $true
|
||||
} else {
|
||||
Write-Warn "WiX could not be installed automatically."
|
||||
Write-Warn "Install manually: dotnet tool install --global wix"
|
||||
Write-Warn "Skipping MSI build."
|
||||
$SkipMsi = $true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# ── 5. Create output directory ────────────────────────────────────────────────
|
||||
Write-Step "Preparing output directory..."
|
||||
if (-not (Test-Path $BinDir)) {
|
||||
New-Item -ItemType Directory -Path $BinDir -Force | Out-Null
|
||||
}
|
||||
Write-OK "dist\bin\"
|
||||
|
||||
# ── 6. Build .exe with PyInstaller ───────────────────────────────────────────
|
||||
if (-not $SkipExe) {
|
||||
Write-Step "Building AUTARCH.exe (PyInstaller one-directory bundle)..."
|
||||
Write-Host " This may take 3–10 minutes..." -ForegroundColor DarkGray
|
||||
|
||||
$SpecFile = Join-Path $AppDir "autarch.spec"
|
||||
$WorkDir = Join-Path $DistDir ".pyinstaller-work"
|
||||
|
||||
Set-Location $AppDir
|
||||
& $Python -m PyInstaller $SpecFile `
|
||||
--distpath $BinDir `
|
||||
--workpath $WorkDir `
|
||||
--noconfirm `
|
||||
--clean
|
||||
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-Host "ERROR: PyInstaller build failed." -ForegroundColor Red
|
||||
exit $LASTEXITCODE
|
||||
}
|
||||
|
||||
$exePath = Join-Path $BinDir "AUTARCH\AUTARCH.exe"
|
||||
if (Test-Path $exePath) {
|
||||
$sizeMB = [math]::Round((Get-ChildItem (Join-Path $BinDir "AUTARCH") -Recurse | Measure-Object -Property Length -Sum).Sum / 1MB, 1)
|
||||
Write-OK "dist\bin\AUTARCH\AUTARCH.exe ($sizeMB MB bundle)"
|
||||
} else {
|
||||
Write-Host "ERROR: AUTARCH.exe not found after build." -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
} else {
|
||||
Write-Warn "Skipping .exe build (-SkipExe)"
|
||||
$exePath = Join-Path $BinDir "AUTARCH\AUTARCH.exe"
|
||||
if (-not (Test-Path $exePath)) {
|
||||
Write-Host "ERROR: dist\bin\AUTARCH\AUTARCH.exe not found. Remove -SkipExe to build it." -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
||||
# ── 7. Generate WiX source (.wxs) from PyInstaller output ────────────────────
|
||||
if (-not $SkipMsi) {
|
||||
Write-Step "Generating WiX source from AUTARCH bundle..."
|
||||
|
||||
$WxsFile = Join-Path $DistDir ".wix\AUTARCH.wxs"
|
||||
$WxsDir = Split-Path $WxsFile
|
||||
$BundleDir = Join-Path $BinDir "AUTARCH"
|
||||
$MsiOut = Join-Path $BinDir "AUTARCH-${Version}-win64.msi"
|
||||
|
||||
if (-not (Test-Path $WxsDir)) {
|
||||
New-Item -ItemType Directory -Path $WxsDir -Force | Out-Null
|
||||
}
|
||||
|
||||
# Use WiX 4 harvest tool to generate component list from the bundle directory
|
||||
$HeatOut = Join-Path $WxsDir "components.wxs"
|
||||
|
||||
# Build WiX 4 MSI directly using wix build command
|
||||
Write-Host " Running wix build (WiX 4)..." -ForegroundColor DarkGray
|
||||
|
||||
# Create a minimal WiX 4 package definition
|
||||
$WixSrcDir = Join-Path $DistDir ".wix"
|
||||
$PackageWxs = Join-Path $WixSrcDir "Package.wxs"
|
||||
|
||||
# Generate file list for WiX
|
||||
$files = Get-ChildItem $BundleDir -Recurse -File
|
||||
$compLines = @()
|
||||
$fileLines = @()
|
||||
$i = 0
|
||||
foreach ($f in $files) {
|
||||
$rel = $f.FullName.Substring($BundleDir.Length + 1)
|
||||
$relDir = [System.IO.Path]::GetDirectoryName($rel)
|
||||
$id = "f$i"
|
||||
$compId = "c$i"
|
||||
$fileLines += " <File Id='$id' Source='$($f.FullName.Replace('\','\\'))' />"
|
||||
$compLines += " <Component Id='$compId' Guid='*'><File Id='${id}f' Source='$($f.FullName.Replace('\','\\'))' /></Component>"
|
||||
$i++
|
||||
}
|
||||
|
||||
# Write Package.wxs (WiX 4 syntax)
|
||||
@"
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
|
||||
<Package Name="AUTARCH" Version="$Version.0.0" Manufacturer="darkHal Security Group"
|
||||
UpgradeCode="A1B2C3D4-E5F6-7890-ABCD-EF1234567890"
|
||||
Language="1033" Codepage="1252">
|
||||
|
||||
<MajorUpgrade DowngradeErrorMessage="A newer version of AUTARCH is already installed." />
|
||||
<MediaTemplate EmbedCab="yes" />
|
||||
|
||||
<Feature Id="Main" Title="AUTARCH" Level="1">
|
||||
<ComponentGroupRef Id="AppFiles" />
|
||||
</Feature>
|
||||
|
||||
<StandardDirectory Id="ProgramFilesFolder">
|
||||
<Directory Id="INSTALLFOLDER" Name="AUTARCH">
|
||||
<ComponentGroup Id="AppFiles">
|
||||
"@ | Out-File -FilePath $PackageWxs -Encoding utf8
|
||||
|
||||
# Add all files as components
|
||||
$i = 0
|
||||
foreach ($f in $files) {
|
||||
$rel = $f.FullName.Substring($BundleDir.Length + 1)
|
||||
$relDir = [System.IO.Path]::GetDirectoryName($rel)
|
||||
$fid = "File_$i"
|
||||
$cid = "Comp_$i"
|
||||
$did = if ($relDir) { "Dir_$($relDir.Replace('\','_').Replace(' ','_'))" } else { "INSTALLFOLDER" }
|
||||
$srcPath = $f.FullName
|
||||
" <Component Id='$cid' Guid='*'><File Id='$fid' Source='$srcPath' /></Component>" |
|
||||
Out-File -FilePath $PackageWxs -Encoding utf8 -Append
|
||||
$i++
|
||||
}
|
||||
|
||||
@"
|
||||
</ComponentGroup>
|
||||
</Directory>
|
||||
</StandardDirectory>
|
||||
</Package>
|
||||
</Wix>
|
||||
"@ | Out-File -FilePath $PackageWxs -Encoding utf8 -Append
|
||||
|
||||
Write-Host " Compiling MSI with WiX 4..." -ForegroundColor DarkGray
|
||||
$env:Path += ";$env:USERPROFILE\.dotnet\tools"
|
||||
wix build $PackageWxs -out $MsiOut
|
||||
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-Host "ERROR: WiX MSI build failed." -ForegroundColor Red
|
||||
Write-Warn "The .exe bundle is still available at dist\bin\AUTARCH\AUTARCH.exe"
|
||||
exit $LASTEXITCODE
|
||||
}
|
||||
|
||||
if (Test-Path $MsiOut) {
|
||||
$sizeMB = [math]::Round((Get-Item $MsiOut).Length / 1MB, 1)
|
||||
Write-OK "dist\bin\AUTARCH-${Version}-win64.msi ($sizeMB MB)"
|
||||
}
|
||||
}
|
||||
|
||||
# ── 8. Summary ────────────────────────────────────────────────────────────────
|
||||
Write-Host ""
|
||||
Write-Host "████████████████████████████████████████████████████" -ForegroundColor Green
|
||||
Write-Host " BUILD COMPLETE" -ForegroundColor Green
|
||||
Write-Host "████████████████████████████████████████████████████" -ForegroundColor Green
|
||||
Write-Host ""
|
||||
Write-Host " Standalone bundle: dist\bin\AUTARCH\AUTARCH.exe" -ForegroundColor White
|
||||
if (-not $SkipMsi) {
|
||||
Write-Host " MSI installer: dist\bin\AUTARCH-${Version}-win64.msi" -ForegroundColor White
|
||||
}
|
||||
Write-Host ""
|
||||
Write-Host " Run standalone: .\dist\bin\AUTARCH\AUTARCH.exe --web" -ForegroundColor Cyan
|
||||
Write-Host " Install MSI: msiexec /i dist\bin\AUTARCH-${Version}-win64.msi" -ForegroundColor Cyan
|
||||
Write-Host ""
|
||||
309
scripts/build-deb.sh
Normal file
309
scripts/build-deb.sh
Normal file
@@ -0,0 +1,309 @@
|
||||
#!/usr/bin/env bash
|
||||
# ───────────────────────────────────────────────────────────────
|
||||
# AUTARCH .deb package builder
|
||||
#
|
||||
# Usage: bash scripts/build-deb.sh [version] [--arch arm64|amd64|all]
|
||||
# Output: dist/autarch_{version}_{arch}.deb
|
||||
#
|
||||
# No git. No debhelper. No pybuild. Just dpkg-deb.
|
||||
# ───────────────────────────────────────────────────────────────
|
||||
set -euo pipefail
|
||||
|
||||
APP_NAME="autarch"
|
||||
SRC_DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
|
||||
# ── Parse arguments ──────────────────────────────────────────
|
||||
FORCE_ARCH=""
|
||||
VERSION=""
|
||||
|
||||
for arg in "$@"; do
|
||||
case "$arg" in
|
||||
--arch=*) FORCE_ARCH="${arg#--arch=}" ;;
|
||||
--arch) ;; # handled by next iteration
|
||||
arm64|amd64|armhf|all)
|
||||
if [[ -z "$FORCE_ARCH" ]]; then
|
||||
FORCE_ARCH="$arg"
|
||||
elif [[ -z "$VERSION" ]]; then
|
||||
VERSION="$arg"
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
if [[ -z "$VERSION" && ! "$arg" =~ ^-- ]]; then
|
||||
VERSION="$arg"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Handle "all" — build for multiple architectures
|
||||
if [[ "$FORCE_ARCH" == "all" ]]; then
|
||||
echo "Building for all architectures..."
|
||||
for arch in arm64 amd64; do
|
||||
bash "$0" ${VERSION:+$VERSION} "$arch"
|
||||
done
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# ── Detect or override architecture ──────────────────────────
|
||||
if [[ -n "$FORCE_ARCH" ]]; then
|
||||
DEB_ARCH="$FORCE_ARCH"
|
||||
else
|
||||
DEB_ARCH="$(dpkg --print-architecture)"
|
||||
fi
|
||||
|
||||
case "$DEB_ARCH" in
|
||||
arm64) PLATFORM_TAG="linux-arm64" ;;
|
||||
amd64) PLATFORM_TAG="linux-x86_64" ;;
|
||||
armhf) PLATFORM_TAG="linux-armhf" ;;
|
||||
*) PLATFORM_TAG="linux-${DEB_ARCH}" ;;
|
||||
esac
|
||||
|
||||
# ── Determine version ────────────────────────────────────────
|
||||
if [[ -z "$VERSION" ]]; then
|
||||
VERSION="$(grep -m1 '^VERSION' "$SRC_DIR/autarch.py" | sed 's/.*"\(.*\)".*/\1/')"
|
||||
if [[ -z "$VERSION" ]]; then
|
||||
echo "ERROR: Could not extract VERSION from autarch.py" >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "Building ${APP_NAME} ${VERSION} for ${DEB_ARCH} (${PLATFORM_TAG})"
|
||||
|
||||
# ── Paths ─────────────────────────────────────────────────────
|
||||
DIST_DIR="$SRC_DIR/dist"
|
||||
BUILD_DIR="$DIST_DIR/.build"
|
||||
PKG_NAME="${APP_NAME}_${VERSION}_${DEB_ARCH}"
|
||||
STAGE="$BUILD_DIR/$PKG_NAME"
|
||||
OPT="$STAGE/opt/autarch"
|
||||
|
||||
# Clean previous build
|
||||
rm -rf "$STAGE"
|
||||
mkdir -p "$OPT" "$STAGE/DEBIAN" "$STAGE/usr/bin"
|
||||
|
||||
# ── Copy application files ────────────────────────────────────
|
||||
echo "Copying application files..."
|
||||
|
||||
# Core Python files at root
|
||||
cp "$SRC_DIR/autarch.py" "$OPT/"
|
||||
cp "$SRC_DIR/requirements.txt" "$OPT/"
|
||||
|
||||
# Settings: ship live config (dpkg conffile-protected) AND .default template
|
||||
cp "$SRC_DIR/autarch_settings.conf" "$OPT/autarch_settings.conf"
|
||||
cp "$SRC_DIR/autarch_settings.conf" "$OPT/autarch_settings.conf.default"
|
||||
|
||||
# User-editable data files
|
||||
cp "$SRC_DIR/custom_sites.inf" "$OPT/"
|
||||
cp "$SRC_DIR/custom_adultsites.json" "$OPT/"
|
||||
|
||||
# Documentation
|
||||
[[ -f "$SRC_DIR/GUIDE.md" ]] && cp "$SRC_DIR/GUIDE.md" "$OPT/"
|
||||
[[ -f "$SRC_DIR/user_manual.md" ]] && cp "$SRC_DIR/user_manual.md" "$OPT/"
|
||||
|
||||
# Directory trees
|
||||
for dir in core modules web; do
|
||||
cp -a "$SRC_DIR/$dir" "$OPT/"
|
||||
done
|
||||
|
||||
# Data (sites db etc.)
|
||||
cp -a "$SRC_DIR/data" "$OPT/"
|
||||
|
||||
# Hardware config templates
|
||||
if [[ -d "$SRC_DIR/.config" ]]; then
|
||||
cp -a "$SRC_DIR/.config" "$OPT/"
|
||||
fi
|
||||
|
||||
# Bundled tools for THIS architecture
|
||||
if [[ -d "$SRC_DIR/tools/$PLATFORM_TAG" ]]; then
|
||||
mkdir -p "$OPT/tools/$PLATFORM_TAG"
|
||||
cp -a "$SRC_DIR/tools/$PLATFORM_TAG/." "$OPT/tools/$PLATFORM_TAG/"
|
||||
fi
|
||||
|
||||
# Android tools (arch-independent — same adb/fastboot for the host)
|
||||
if [[ -d "$SRC_DIR/android" ]]; then
|
||||
cp -a "$SRC_DIR/android" "$OPT/"
|
||||
fi
|
||||
|
||||
# Companion APK (if built)
|
||||
APK="$SRC_DIR/autarch_companion/app/build/outputs/apk/debug/app-debug.apk"
|
||||
if [[ -f "$APK" ]]; then
|
||||
mkdir -p "$OPT/companion"
|
||||
cp "$APK" "$OPT/companion/archon.apk"
|
||||
fi
|
||||
|
||||
# Systemd service
|
||||
if [[ -f "$SRC_DIR/scripts/autarch-web.service" ]]; then
|
||||
mkdir -p "$STAGE/etc/systemd/system"
|
||||
cp "$SRC_DIR/scripts/autarch-web.service" "$STAGE/etc/systemd/system/autarch-web.service"
|
||||
fi
|
||||
|
||||
# ── Strip excluded files ──────────────────────────────────────
|
||||
echo "Stripping excluded files..."
|
||||
|
||||
# __pycache__ and .pyc
|
||||
find "$OPT" -type d -name "__pycache__" -exec rm -rf {} + 2>/dev/null || true
|
||||
find "$OPT" -name "*.pyc" -delete 2>/dev/null || true
|
||||
|
||||
# Backup files
|
||||
find "$OPT" -name "*.bk" -delete 2>/dev/null || true
|
||||
|
||||
# .claude directory
|
||||
rm -rf "$OPT/.claude"
|
||||
|
||||
# node_modules, src (build artifacts)
|
||||
rm -rf "$OPT/node_modules" "$OPT/src"
|
||||
|
||||
# User-generated data that shouldn't ship
|
||||
rm -f "$OPT"/*_profiles.json
|
||||
|
||||
# System/dev files
|
||||
rm -f "$OPT/system.inf" "$OPT/backupexec_dump.mtf"
|
||||
|
||||
# Dev docs
|
||||
rm -f "$OPT/DEVLOG.md" "$OPT/devjournal.md" "$OPT/autarch_dev.md"
|
||||
rm -f "$OPT/android_plan.md" "$OPT/master_plan.md"
|
||||
|
||||
# Node/package files
|
||||
rm -f "$OPT/package.json" "$OPT/package-lock.json" "$OPT/.gitignore"
|
||||
|
||||
# User data dirs — create empty structure but don't ship contents
|
||||
for datadir in results dossiers data/captures data/exports data/hardware data/pentest_sessions data/uploads; do
|
||||
rm -rf "$OPT/$datadir"
|
||||
done
|
||||
|
||||
# ── Generate DEBIAN/control ───────────────────────────────────
|
||||
INSTALLED_KB=$(du -sk "$STAGE" | cut -f1)
|
||||
|
||||
cat > "$STAGE/DEBIAN/control" <<EOF
|
||||
Package: ${APP_NAME}
|
||||
Version: ${VERSION}
|
||||
Architecture: ${DEB_ARCH}
|
||||
Maintainer: darkHal Security Group <noreply@darkhal.local>
|
||||
Description: AUTARCH - Autonomous Tactical Agent for Reconnaissance,
|
||||
Counterintelligence, and Hacking. Self-contained security framework
|
||||
with web UI, OSINT tools, network scanning, hardware flashing,
|
||||
and optional LLM integration.
|
||||
Section: utils
|
||||
Priority: optional
|
||||
Installed-Size: ${INSTALLED_KB}
|
||||
Depends: python3 (>= 3.10), python3-pip, python3-venv
|
||||
Recommends: nmap, tcpdump, tshark, miniupnpc, wireguard-tools
|
||||
Suggests: metasploit-framework, clamav
|
||||
EOF
|
||||
|
||||
# ── Generate DEBIAN/conffiles ─────────────────────────────────
|
||||
cat > "$STAGE/DEBIAN/conffiles" <<EOF
|
||||
/opt/autarch/autarch_settings.conf
|
||||
/opt/autarch/custom_sites.inf
|
||||
/opt/autarch/custom_adultsites.json
|
||||
EOF
|
||||
|
||||
# ── Generate DEBIAN/postinst ──────────────────────────────────
|
||||
cat > "$STAGE/DEBIAN/postinst" <<'POSTINST'
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
APP="/opt/autarch"
|
||||
|
||||
# First install: ensure live config exists (dpkg ships it, but just in case)
|
||||
if [ ! -f "$APP/autarch_settings.conf" ]; then
|
||||
cp "$APP/autarch_settings.conf.default" "$APP/autarch_settings.conf"
|
||||
fi
|
||||
|
||||
# Create writable data directories
|
||||
for d in results dossiers data/captures data/exports data/hardware data/pentest_sessions data/uploads; do
|
||||
mkdir -p "$APP/$d"
|
||||
done
|
||||
|
||||
# Set permissions on entry point
|
||||
chmod +x "$APP/autarch.py"
|
||||
|
||||
# Set permissions on bundled tools
|
||||
for f in "$APP"/tools/linux-*/nmap "$APP"/tools/linux-*/tcpdump \
|
||||
"$APP"/tools/linux-*/upnpc "$APP"/tools/linux-*/wg; do
|
||||
[ -f "$f" ] && chmod +x "$f"
|
||||
done
|
||||
|
||||
# Android binaries
|
||||
for f in "$APP"/android/adb "$APP"/android/fastboot; do
|
||||
[ -f "$f" ] && chmod +x "$f"
|
||||
done
|
||||
|
||||
# Create Python venv and install dependencies
|
||||
if [ ! -d "$APP/venv" ]; then
|
||||
echo "Creating Python virtual environment..."
|
||||
python3 -m venv "$APP/venv"
|
||||
fi
|
||||
|
||||
echo "Installing Python dependencies..."
|
||||
"$APP/venv/bin/pip" install --quiet --upgrade pip
|
||||
"$APP/venv/bin/pip" install --quiet -r "$APP/requirements.txt"
|
||||
|
||||
echo "AUTARCH installed successfully."
|
||||
echo "Run 'autarch --help' to get started."
|
||||
POSTINST
|
||||
chmod 0755 "$STAGE/DEBIAN/postinst"
|
||||
|
||||
# ── Generate DEBIAN/prerm ─────────────────────────────────────
|
||||
cat > "$STAGE/DEBIAN/prerm" <<'PRERM'
|
||||
#!/bin/bash
|
||||
set -e
|
||||
# Nothing to do before removal — just a placeholder for future needs.
|
||||
PRERM
|
||||
chmod 0755 "$STAGE/DEBIAN/prerm"
|
||||
|
||||
# ── Generate DEBIAN/postrm ────────────────────────────────────
|
||||
cat > "$STAGE/DEBIAN/postrm" <<'POSTRM'
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
APP="/opt/autarch"
|
||||
|
||||
if [ "$1" = "purge" ]; then
|
||||
# Remove venv (large, regenerable)
|
||||
rm -rf "$APP/venv"
|
||||
|
||||
# Remove empty data directories only
|
||||
for d in results dossiers data/captures data/exports data/hardware data/pentest_sessions data/uploads data; do
|
||||
[ -d "$APP/$d" ] && rmdir --ignore-fail-on-non-empty "$APP/$d" 2>/dev/null || true
|
||||
done
|
||||
|
||||
# Remove app dir if completely empty
|
||||
rmdir --ignore-fail-on-non-empty "$APP" 2>/dev/null || true
|
||||
fi
|
||||
POSTRM
|
||||
chmod 0755 "$STAGE/DEBIAN/postrm"
|
||||
|
||||
# ── Generate /usr/bin/autarch wrapper ─────────────────────────
|
||||
cat > "$STAGE/usr/bin/autarch" <<'WRAPPER'
|
||||
#!/bin/bash
|
||||
exec /opt/autarch/venv/bin/python3 /opt/autarch/autarch.py "$@"
|
||||
WRAPPER
|
||||
chmod 0755 "$STAGE/usr/bin/autarch"
|
||||
|
||||
# ── Build the .deb ────────────────────────────────────────────
|
||||
echo "Building .deb package..."
|
||||
mkdir -p "$DIST_DIR"
|
||||
|
||||
DEB_OUT="$DIST_DIR/${PKG_NAME}.deb"
|
||||
|
||||
if command -v fakeroot >/dev/null 2>&1; then
|
||||
fakeroot dpkg-deb --build "$STAGE" "$DEB_OUT"
|
||||
else
|
||||
dpkg-deb --build "$STAGE" "$DEB_OUT"
|
||||
fi
|
||||
|
||||
# ── Clean up staging ──────────────────────────────────────────
|
||||
rm -rf "$BUILD_DIR"
|
||||
|
||||
# ── Summary ───────────────────────────────────────────────────
|
||||
DEB_SIZE=$(du -h "$DEB_OUT" | cut -f1)
|
||||
echo ""
|
||||
echo "════════════════════════════════════════════════════"
|
||||
echo " Package: $DEB_OUT"
|
||||
echo " Size: $DEB_SIZE"
|
||||
echo " Arch: $DEB_ARCH ($PLATFORM_TAG)"
|
||||
echo "════════════════════════════════════════════════════"
|
||||
echo ""
|
||||
echo "Inspect: dpkg-deb --info $DEB_OUT"
|
||||
echo "Contents: dpkg-deb --contents $DEB_OUT | head -50"
|
||||
echo "Install: sudo dpkg -i $DEB_OUT && sudo apt-get install -f"
|
||||
128
scripts/build-exe.ps1
Normal file
128
scripts/build-exe.ps1
Normal file
@@ -0,0 +1,128 @@
|
||||
# ═══════════════════════════════════════════════════════════════════════════
|
||||
# AUTARCH — PyInstaller .exe Builder
|
||||
#
|
||||
# Creates a standalone Windows executable bundle using PyInstaller.
|
||||
# Output: dist\bin\AUTARCH\AUTARCH.exe (one-directory bundle)
|
||||
#
|
||||
# Usage:
|
||||
# powershell -ExecutionPolicy Bypass -File scripts\build-exe.ps1
|
||||
# powershell -ExecutionPolicy Bypass -File scripts\build-exe.ps1 -OneFile
|
||||
#
|
||||
# Prerequisites:
|
||||
# pip install pyinstaller
|
||||
# ═══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
param(
|
||||
[switch]$OneFile = $false, # --onefile build (larger, slower to start)
|
||||
[string]$Python = "python" # Python interpreter to use
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
$AppDir = Split-Path -Parent $PSScriptRoot
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "════════════════════════════════════════════════" -ForegroundColor Cyan
|
||||
Write-Host " AUTARCH .exe Builder (PyInstaller)" -ForegroundColor Cyan
|
||||
Write-Host "════════════════════════════════════════════════" -ForegroundColor Cyan
|
||||
Write-Host ""
|
||||
|
||||
# ── Verify PyInstaller ────────────────────────────────────────────────────────
|
||||
try {
|
||||
$ver = & $Python -c "import PyInstaller; print(PyInstaller.__version__)" 2>&1
|
||||
Write-Host "PyInstaller $ver" -ForegroundColor Green
|
||||
} catch {
|
||||
Write-Host "ERROR: PyInstaller not found." -ForegroundColor Red
|
||||
Write-Host "Install it: pip install pyinstaller" -ForegroundColor Yellow
|
||||
exit 1
|
||||
}
|
||||
|
||||
# ── Prepare output directory ──────────────────────────────────────────────────
|
||||
$BinDir = Join-Path $AppDir "dist\bin"
|
||||
if (-not (Test-Path $BinDir)) {
|
||||
New-Item -ItemType Directory -Path $BinDir -Force | Out-Null
|
||||
}
|
||||
|
||||
# ── Run PyInstaller ───────────────────────────────────────────────────────────
|
||||
$SpecFile = Join-Path $AppDir "autarch.spec"
|
||||
$DistDir = $BinDir
|
||||
$WorkDir = Join-Path $AppDir "dist\.pyinstaller-work"
|
||||
|
||||
Write-Host "Building AUTARCH.exe..." -ForegroundColor Yellow
|
||||
Write-Host " Spec: $SpecFile" -ForegroundColor DarkGray
|
||||
Write-Host " Output: $DistDir" -ForegroundColor DarkGray
|
||||
Write-Host ""
|
||||
|
||||
$Args = @(
|
||||
$SpecFile,
|
||||
"--distpath", $DistDir,
|
||||
"--workpath", $WorkDir,
|
||||
"--noconfirm",
|
||||
"--clean"
|
||||
)
|
||||
|
||||
if ($OneFile) {
|
||||
# Override spec and do a one-file build directly
|
||||
Write-Host "Mode: --onefile (single .exe, slower startup)" -ForegroundColor Magenta
|
||||
$Args = @(
|
||||
(Join-Path $AppDir "autarch.py"),
|
||||
"--onefile",
|
||||
"--name", "AUTARCH",
|
||||
"--distpath", $DistDir,
|
||||
"--workpath", $WorkDir,
|
||||
"--noconfirm",
|
||||
"--clean",
|
||||
"--add-data", "web/templates;web/templates",
|
||||
"--add-data", "web/static;web/static",
|
||||
"--add-data", "data;data",
|
||||
"--add-data", "modules;modules",
|
||||
"--add-data", "autarch_settings.conf;.",
|
||||
"--add-data", "user_manual.md;.",
|
||||
"--add-data", "windows_manual.md;.",
|
||||
"--add-data", "custom_sites.inf;.",
|
||||
"--add-data", "custom_adultsites.json;.",
|
||||
"--add-data", "android;android",
|
||||
"--add-data", "tools;tools",
|
||||
"--hidden-import", "flask",
|
||||
"--hidden-import", "werkzeug",
|
||||
"--hidden-import", "jinja2",
|
||||
"--hidden-import", "bcrypt",
|
||||
"--hidden-import", "requests",
|
||||
"--hidden-import", "msgpack",
|
||||
"--console"
|
||||
)
|
||||
}
|
||||
|
||||
Set-Location $AppDir
|
||||
& $Python -m PyInstaller @Args
|
||||
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-Host ""
|
||||
Write-Host "ERROR: PyInstaller build failed (exit code $LASTEXITCODE)" -ForegroundColor Red
|
||||
exit $LASTEXITCODE
|
||||
}
|
||||
|
||||
# ── Report ────────────────────────────────────────────────────────────────────
|
||||
Write-Host ""
|
||||
Write-Host "════════════════════════════════════════════════" -ForegroundColor Green
|
||||
Write-Host " Build complete!" -ForegroundColor Green
|
||||
Write-Host "════════════════════════════════════════════════" -ForegroundColor Green
|
||||
Write-Host ""
|
||||
|
||||
if ($OneFile) {
|
||||
$exePath = Join-Path $DistDir "AUTARCH.exe"
|
||||
if (Test-Path $exePath) {
|
||||
$sizeMB = [math]::Round((Get-Item $exePath).Length / 1MB, 1)
|
||||
Write-Host " Output: $exePath ($sizeMB MB)" -ForegroundColor White
|
||||
}
|
||||
} else {
|
||||
$exePath = Join-Path $DistDir "AUTARCH\AUTARCH.exe"
|
||||
if (Test-Path $exePath) {
|
||||
$sizeKB = [math]::Round((Get-Item $exePath).Length / 1KB, 0)
|
||||
Write-Host " Exe: $exePath ($sizeKB KB)" -ForegroundColor White
|
||||
$dirSize = [math]::Round((Get-ChildItem (Join-Path $DistDir "AUTARCH") -Recurse | Measure-Object -Property Length -Sum).Sum / 1MB, 1)
|
||||
Write-Host " Bundle: dist\bin\AUTARCH\ ($dirSize MB total)" -ForegroundColor White
|
||||
}
|
||||
}
|
||||
Write-Host ""
|
||||
Write-Host " Run it: .\dist\bin\AUTARCH\AUTARCH.exe --web" -ForegroundColor Cyan
|
||||
Write-Host ""
|
||||
54
scripts/build-hw-libs.sh
Normal file
54
scripts/build-hw-libs.sh
Normal file
@@ -0,0 +1,54 @@
|
||||
#!/bin/bash
|
||||
# Build browser-ready bundles for AUTARCH hardware direct-mode libraries
|
||||
# Run from project root: bash scripts/build-hw-libs.sh
|
||||
#
|
||||
# Requires: npm install (run once to install dependencies)
|
||||
# Output: web/static/js/lib/*.js (committed to project, no node needed at runtime)
|
||||
|
||||
set -e
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
|
||||
OUT_DIR="$PROJECT_DIR/web/static/js/lib"
|
||||
|
||||
mkdir -p "$OUT_DIR"
|
||||
|
||||
echo "Building hardware library bundles..."
|
||||
echo "Output: $OUT_DIR"
|
||||
|
||||
# ADB bundle (ya-webadb / Tango)
|
||||
echo " [1/3] Building adb-bundle.js..."
|
||||
npx esbuild "$PROJECT_DIR/src/adb-entry.js" \
|
||||
--bundle \
|
||||
--format=iife \
|
||||
--global-name=YumeAdb \
|
||||
--platform=browser \
|
||||
--target=chrome89 \
|
||||
--outfile="$OUT_DIR/adb-bundle.js" \
|
||||
--minify
|
||||
|
||||
# Fastboot bundle
|
||||
echo " [2/3] Building fastboot-bundle.js..."
|
||||
npx esbuild "$PROJECT_DIR/src/fastboot-entry.js" \
|
||||
--bundle \
|
||||
--format=iife \
|
||||
--global-name=Fastboot \
|
||||
--platform=browser \
|
||||
--target=chrome89 \
|
||||
--outfile="$OUT_DIR/fastboot-bundle.js" \
|
||||
--minify
|
||||
|
||||
# ESP32 bundle (esptool-js)
|
||||
echo " [3/3] Building esptool-bundle.js..."
|
||||
npx esbuild "$PROJECT_DIR/src/esptool-entry.js" \
|
||||
--bundle \
|
||||
--format=iife \
|
||||
--global-name=EspTool \
|
||||
--platform=browser \
|
||||
--target=chrome89 \
|
||||
--outfile="$OUT_DIR/esptool-bundle.js" \
|
||||
--minify
|
||||
|
||||
echo ""
|
||||
echo "Build complete:"
|
||||
ls -lh "$OUT_DIR"/*.js
|
||||
62
scripts/build-msi.ps1
Normal file
62
scripts/build-msi.ps1
Normal file
@@ -0,0 +1,62 @@
|
||||
# ═══════════════════════════════════════════════════════════════════════════
|
||||
# AUTARCH - Windows MSI Installer Builder
|
||||
#
|
||||
# Creates a Windows .msi installer using Python's built-in msilib.
|
||||
# Packages the PyInstaller bundle (dist\bin\AUTARCH\) into an MSI.
|
||||
# Output: dist\bin\AUTARCH-1.3-win64.msi
|
||||
#
|
||||
# Usage:
|
||||
# powershell -ExecutionPolicy Bypass -File scripts\build-msi.ps1
|
||||
#
|
||||
# Prerequisites:
|
||||
# - Python 3.10+ (msilib is a Windows standard library module)
|
||||
# - dist\bin\AUTARCH\ must exist (run build-exe.ps1 first)
|
||||
# ===============================================================================
|
||||
|
||||
param(
|
||||
[string]$Python = "python"
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
$AppDir = Split-Path -Parent $PSScriptRoot
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "===============================================" -ForegroundColor Cyan
|
||||
Write-Host " AUTARCH .msi Builder (msilib)" -ForegroundColor Cyan
|
||||
Write-Host "===============================================" -ForegroundColor Cyan
|
||||
Write-Host ""
|
||||
|
||||
$BundleDir = Join-Path $AppDir "dist\bin\AUTARCH"
|
||||
if (-not (Test-Path (Join-Path $BundleDir "AUTARCH.exe"))) {
|
||||
Write-Host "ERROR: dist\bin\AUTARCH\AUTARCH.exe not found." -ForegroundColor Red
|
||||
Write-Host " Run build-exe.ps1 first to create the bundle." -ForegroundColor Yellow
|
||||
exit 1
|
||||
}
|
||||
|
||||
Set-Location $AppDir
|
||||
Write-Host "Building MSI from dist\bin\AUTARCH\ bundle..." -ForegroundColor Yellow
|
||||
Write-Host ""
|
||||
|
||||
& $Python (Join-Path $AppDir "scripts\make_msi.py")
|
||||
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-Host ""
|
||||
Write-Host "ERROR: MSI build failed (exit code $LASTEXITCODE)" -ForegroundColor Red
|
||||
exit $LASTEXITCODE
|
||||
}
|
||||
|
||||
$msiFiles = Get-ChildItem (Join-Path $AppDir "dist\bin") -Filter "*.msi" -ErrorAction SilentlyContinue
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "===============================================" -ForegroundColor Green
|
||||
Write-Host " MSI build complete!" -ForegroundColor Green
|
||||
Write-Host "===============================================" -ForegroundColor Green
|
||||
Write-Host ""
|
||||
foreach ($msi in $msiFiles) {
|
||||
$sizeMB = [math]::Round($msi.Length / 1MB, 1)
|
||||
Write-Host " Output: $($msi.FullName) ($sizeMB MB)" -ForegroundColor White
|
||||
}
|
||||
Write-Host ""
|
||||
Write-Host " Install: Double-click the .msi file" -ForegroundColor Cyan
|
||||
Write-Host " Or: msiexec /i AUTARCH-1.3-win64.msi" -ForegroundColor Cyan
|
||||
Write-Host ""
|
||||
266
scripts/build-windows.sh
Normal file
266
scripts/build-windows.sh
Normal file
@@ -0,0 +1,266 @@
|
||||
#!/usr/bin/env bash
|
||||
# ───────────────────────────────────────────────────────────────
|
||||
# AUTARCH Windows Package Builder
|
||||
#
|
||||
# Creates a standalone Windows-ready ZIP with:
|
||||
# - All Python source + web assets
|
||||
# - Batch launcher (autarch.bat)
|
||||
# - PowerShell installer (install.ps1)
|
||||
# - requirements.txt for pip install
|
||||
# - Placeholder for Windows tools
|
||||
#
|
||||
# Usage: bash scripts/build-windows.sh [version]
|
||||
# Output: dist/autarch_{version}_windows.zip
|
||||
#
|
||||
# NOTE: This builds a SOURCE distribution, not a frozen .exe.
|
||||
# The install.ps1 script handles Python venv + dependency install.
|
||||
# For a frozen .exe, run PyInstaller ON a Windows machine.
|
||||
# ───────────────────────────────────────────────────────────────
|
||||
set -euo pipefail
|
||||
|
||||
APP_NAME="autarch"
|
||||
SRC_DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
|
||||
# ── Determine version ────────────────────────────────────────
|
||||
if [[ ${1:-} ]]; then
|
||||
VERSION="$1"
|
||||
else
|
||||
VERSION="$(grep -m1 '^VERSION' "$SRC_DIR/autarch.py" | sed 's/.*"\(.*\)".*/\1/')"
|
||||
if [[ -z "$VERSION" ]]; then
|
||||
echo "ERROR: Could not extract VERSION from autarch.py" >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "Building ${APP_NAME} ${VERSION} for Windows"
|
||||
|
||||
# ── Paths ─────────────────────────────────────────────────────
|
||||
DIST_DIR="$SRC_DIR/dist"
|
||||
BUILD_DIR="$DIST_DIR/.win-build"
|
||||
STAGE="$BUILD_DIR/${APP_NAME}_${VERSION}_windows"
|
||||
|
||||
# Clean
|
||||
rm -rf "$STAGE"
|
||||
mkdir -p "$STAGE"
|
||||
|
||||
# ── Copy application files ────────────────────────────────────
|
||||
echo "Copying application files..."
|
||||
|
||||
# Core
|
||||
cp "$SRC_DIR/autarch.py" "$STAGE/"
|
||||
cp "$SRC_DIR/requirements.txt" "$STAGE/"
|
||||
|
||||
# Config
|
||||
cp "$SRC_DIR/autarch_settings.conf" "$STAGE/autarch_settings.conf"
|
||||
cp "$SRC_DIR/autarch_settings.conf" "$STAGE/autarch_settings.conf.default"
|
||||
|
||||
# User files
|
||||
cp "$SRC_DIR/custom_sites.inf" "$STAGE/"
|
||||
cp "$SRC_DIR/custom_adultsites.json" "$STAGE/"
|
||||
|
||||
# Documentation
|
||||
[[ -f "$SRC_DIR/GUIDE.md" ]] && cp "$SRC_DIR/GUIDE.md" "$STAGE/"
|
||||
[[ -f "$SRC_DIR/user_manual.md" ]] && cp "$SRC_DIR/user_manual.md" "$STAGE/"
|
||||
|
||||
# Directory trees
|
||||
for dir in core modules web; do
|
||||
cp -a "$SRC_DIR/$dir" "$STAGE/"
|
||||
done
|
||||
|
||||
# Data (sites db etc.)
|
||||
cp -a "$SRC_DIR/data" "$STAGE/"
|
||||
|
||||
# Config templates
|
||||
if [[ -d "$SRC_DIR/.config" ]]; then
|
||||
cp -a "$SRC_DIR/.config" "$STAGE/"
|
||||
fi
|
||||
|
||||
# Windows tools directory (placeholder — user downloads nmap/tshark etc.)
|
||||
mkdir -p "$STAGE/tools/windows-x86_64"
|
||||
|
||||
# Companion APK
|
||||
APK="$SRC_DIR/autarch_companion/app/build/outputs/apk/debug/app-debug.apk"
|
||||
if [[ -f "$APK" ]]; then
|
||||
mkdir -p "$STAGE/companion"
|
||||
cp "$APK" "$STAGE/companion/archon.apk"
|
||||
fi
|
||||
|
||||
# ── Strip excluded files ──────────────────────────────────────
|
||||
echo "Stripping excluded files..."
|
||||
find "$STAGE" -type d -name "__pycache__" -exec rm -rf {} + 2>/dev/null || true
|
||||
find "$STAGE" -name "*.pyc" -delete 2>/dev/null || true
|
||||
find "$STAGE" -name "*.bk" -delete 2>/dev/null || true
|
||||
rm -rf "$STAGE/.claude" "$STAGE/node_modules" "$STAGE/src"
|
||||
rm -f "$STAGE"/*_profiles.json
|
||||
rm -f "$STAGE/system.inf" "$STAGE/backupexec_dump.mtf"
|
||||
rm -f "$STAGE/DEVLOG.md" "$STAGE/devjournal.md" "$STAGE/autarch_dev.md"
|
||||
rm -f "$STAGE/android_plan.md" "$STAGE/master_plan.md"
|
||||
rm -f "$STAGE/package.json" "$STAGE/package-lock.json" "$STAGE/.gitignore"
|
||||
for datadir in results dossiers data/captures data/exports data/hardware data/pentest_sessions data/uploads; do
|
||||
rm -rf "$STAGE/$datadir"
|
||||
done
|
||||
|
||||
# ── Create Windows launcher (autarch.bat) ─────────────────────
|
||||
cat > "$STAGE/autarch.bat" <<'BAT'
|
||||
@echo off
|
||||
REM AUTARCH Launcher for Windows
|
||||
REM Uses Python virtual environment if available, falls back to system Python
|
||||
|
||||
setlocal
|
||||
|
||||
set "APP_DIR=%~dp0"
|
||||
|
||||
if exist "%APP_DIR%venv\Scripts\python.exe" (
|
||||
"%APP_DIR%venv\Scripts\python.exe" "%APP_DIR%autarch.py" %*
|
||||
) else (
|
||||
python "%APP_DIR%autarch.py" %*
|
||||
)
|
||||
|
||||
endlocal
|
||||
BAT
|
||||
|
||||
# ── Create web dashboard launcher ─────────────────────────────
|
||||
cat > "$STAGE/start-web.bat" <<'BAT'
|
||||
@echo off
|
||||
REM Start AUTARCH Web Dashboard
|
||||
setlocal
|
||||
|
||||
set "APP_DIR=%~dp0"
|
||||
|
||||
echo Starting AUTARCH Web Dashboard...
|
||||
echo Open your browser to: http://localhost:8181
|
||||
echo Press Ctrl+C to stop.
|
||||
echo.
|
||||
|
||||
if exist "%APP_DIR%venv\Scripts\python.exe" (
|
||||
"%APP_DIR%venv\Scripts\python.exe" "%APP_DIR%autarch.py" --web %*
|
||||
) else (
|
||||
python "%APP_DIR%autarch.py" --web %*
|
||||
)
|
||||
|
||||
endlocal
|
||||
BAT
|
||||
|
||||
# ── Create installer script (PowerShell) ──────────────────────
|
||||
cat > "$STAGE/install.ps1" <<'PS1'
|
||||
# AUTARCH Windows Installer
|
||||
# Run: powershell -ExecutionPolicy Bypass -File install.ps1
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "================================" -ForegroundColor Green
|
||||
Write-Host " AUTARCH Installer for Windows" -ForegroundColor Green
|
||||
Write-Host "================================" -ForegroundColor Green
|
||||
Write-Host ""
|
||||
|
||||
$AppDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||||
|
||||
# Check Python
|
||||
$python = Get-Command python -ErrorAction SilentlyContinue
|
||||
if (-not $python) {
|
||||
Write-Host "ERROR: Python not found. Install Python 3.10+ from python.org" -ForegroundColor Red
|
||||
Write-Host "Make sure to check 'Add Python to PATH' during installation." -ForegroundColor Yellow
|
||||
exit 1
|
||||
}
|
||||
|
||||
$pyVer = python --version 2>&1
|
||||
Write-Host "Found: $pyVer" -ForegroundColor Cyan
|
||||
|
||||
# Create virtual environment
|
||||
$venvDir = Join-Path $AppDir "venv"
|
||||
if (-not (Test-Path $venvDir)) {
|
||||
Write-Host "Creating Python virtual environment..." -ForegroundColor Yellow
|
||||
python -m venv $venvDir
|
||||
}
|
||||
|
||||
# Install dependencies
|
||||
$pip = Join-Path $venvDir "Scripts\pip.exe"
|
||||
Write-Host "Installing dependencies..." -ForegroundColor Yellow
|
||||
& $pip install --quiet --upgrade pip
|
||||
& $pip install --quiet -r (Join-Path $AppDir "requirements.txt")
|
||||
|
||||
# Create data directories
|
||||
$dataDirs = @("results", "dossiers", "data\captures", "data\exports",
|
||||
"data\hardware", "data\pentest_sessions", "data\uploads")
|
||||
foreach ($d in $dataDirs) {
|
||||
$path = Join-Path $AppDir $d
|
||||
if (-not (Test-Path $path)) {
|
||||
New-Item -ItemType Directory -Path $path -Force | Out-Null
|
||||
}
|
||||
}
|
||||
|
||||
# Create desktop shortcut
|
||||
$desktop = [Environment]::GetFolderPath("Desktop")
|
||||
$shortcutPath = Join-Path $desktop "AUTARCH.lnk"
|
||||
$shell = New-Object -ComObject WScript.Shell
|
||||
$shortcut = $shell.CreateShortcut($shortcutPath)
|
||||
$shortcut.TargetPath = Join-Path $AppDir "autarch.bat"
|
||||
$shortcut.WorkingDirectory = $AppDir
|
||||
$shortcut.Description = "AUTARCH Security Platform"
|
||||
$shortcut.Save()
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "================================" -ForegroundColor Green
|
||||
Write-Host " Installation complete!" -ForegroundColor Green
|
||||
Write-Host "================================" -ForegroundColor Green
|
||||
Write-Host ""
|
||||
Write-Host "Run AUTARCH:" -ForegroundColor Cyan
|
||||
Write-Host " CLI: autarch.bat" -ForegroundColor White
|
||||
Write-Host " Web: start-web.bat" -ForegroundColor White
|
||||
Write-Host " Manual: python autarch.py --manual" -ForegroundColor White
|
||||
Write-Host ""
|
||||
Write-Host "Desktop shortcut created." -ForegroundColor Yellow
|
||||
Write-Host ""
|
||||
PS1
|
||||
|
||||
# ── Create README for Windows ─────────────────────────────────
|
||||
cat > "$STAGE/README-WINDOWS.txt" <<'README'
|
||||
AUTARCH for Windows
|
||||
===================
|
||||
|
||||
Quick Start:
|
||||
1. Run install.ps1 (right-click > Run with PowerShell)
|
||||
This creates a Python environment and installs dependencies.
|
||||
|
||||
2. Double-click autarch.bat to start the CLI menu.
|
||||
Or double-click start-web.bat for the browser dashboard.
|
||||
|
||||
Requirements:
|
||||
- Python 3.10 or newer (python.org - check "Add to PATH")
|
||||
- Windows 10 or newer
|
||||
|
||||
Optional Tools (place in tools\windows-x86_64\):
|
||||
- nmap.exe (nmap.org)
|
||||
- tshark.exe (wireshark.org)
|
||||
- wg.exe (wireguard.com)
|
||||
|
||||
Manual:
|
||||
python autarch.py --manual (in terminal)
|
||||
Open user_manual.md (any text editor/Markdown viewer)
|
||||
http://localhost:8181/manual (when web dashboard is running)
|
||||
|
||||
Companion App:
|
||||
The Archon Android companion app APK is in the companion\ folder.
|
||||
Install it on your phone via ADB or file transfer.
|
||||
README
|
||||
|
||||
# ── Create the ZIP ────────────────────────────────────────────
|
||||
echo "Creating ZIP archive..."
|
||||
mkdir -p "$DIST_DIR"
|
||||
|
||||
ZIP_NAME="${APP_NAME}_${VERSION}_windows.zip"
|
||||
ZIP_OUT="$DIST_DIR/$ZIP_NAME"
|
||||
|
||||
(cd "$BUILD_DIR" && zip -r -q "$ZIP_OUT" "$(basename "$STAGE")")
|
||||
|
||||
# ── Clean up ──────────────────────────────────────────────────
|
||||
rm -rf "$BUILD_DIR"
|
||||
|
||||
# ── Summary ───────────────────────────────────────────────────
|
||||
ZIP_SIZE=$(du -h "$ZIP_OUT" | cut -f1)
|
||||
echo ""
|
||||
echo "════════════════════════════════════════════════════"
|
||||
echo " Package: $ZIP_OUT"
|
||||
echo " Size: $ZIP_SIZE"
|
||||
echo "════════════════════════════════════════════════════"
|
||||
echo ""
|
||||
echo "Transfer this ZIP to a Windows machine and run install.ps1"
|
||||
86
scripts/encrypt_module.py
Normal file
86
scripts/encrypt_module.py
Normal file
@@ -0,0 +1,86 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
encrypt_module.py — Encrypt a Python module into AUTARCH .aes format.
|
||||
|
||||
Usage:
|
||||
python scripts/encrypt_module.py <source.py> [output.aes] [--password P] [--name N]
|
||||
|
||||
Examples:
|
||||
python scripts/encrypt_module.py modules/encmod_sources/floppy_dick.py
|
||||
python scripts/encrypt_module.py mymod.py modules/encrypted/mymod.aes --password s3cr3t
|
||||
python scripts/encrypt_module.py mymod.py --password s3cr3t --name "My Module" --version 1.1
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import getpass
|
||||
import json
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
SRC_DIR = Path(__file__).parent.parent
|
||||
sys.path.insert(0, str(SRC_DIR))
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description='Encrypt a Python module to AUTARCH .aes format')
|
||||
parser.add_argument('source', help='Path to the source .py file')
|
||||
parser.add_argument('output', nargs='?', help='Output .aes path (default: modules/encrypted/<stem>.aes)')
|
||||
parser.add_argument('--password', '-p', default='', help='Encryption password (prompted if omitted)')
|
||||
parser.add_argument('--name', default='', help='Display name for the module')
|
||||
parser.add_argument('--version', default='1.0', help='Module version (default: 1.0)')
|
||||
parser.add_argument('--author', default='', help='Module author')
|
||||
parser.add_argument('--description', default='', help='Module description')
|
||||
parser.add_argument('--tags', default='', help='Comma-separated tags')
|
||||
args = parser.parse_args()
|
||||
|
||||
src = Path(args.source)
|
||||
if not src.exists():
|
||||
print(f"ERROR: Source file not found: {src}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
# Determine output path
|
||||
if args.output:
|
||||
out = Path(args.output)
|
||||
else:
|
||||
enc_dir = SRC_DIR / 'modules' / 'encrypted'
|
||||
enc_dir.mkdir(parents=True, exist_ok=True)
|
||||
out = enc_dir / (src.stem + '.aes')
|
||||
|
||||
# Get password
|
||||
password = args.password
|
||||
if not password:
|
||||
password = getpass.getpass(f"Encryption password for {src.name}: ")
|
||||
confirm = getpass.getpass("Confirm password: ")
|
||||
if password != confirm:
|
||||
print("ERROR: Passwords do not match.", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
if not password:
|
||||
print("ERROR: Password cannot be empty.", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
# Build metadata
|
||||
tags = [t.strip() for t in args.tags.split(',') if t.strip()]
|
||||
metadata = {
|
||||
'name': args.name or src.stem.replace('_', ' ').title(),
|
||||
'version': args.version,
|
||||
'author': args.author,
|
||||
'description': args.description,
|
||||
'tags': tags,
|
||||
'source': src.name,
|
||||
}
|
||||
|
||||
# Encrypt
|
||||
from core.module_crypto import encrypt_file
|
||||
encrypt_file(src, out, password, metadata)
|
||||
|
||||
size_kb = round(out.stat().st_size / 1024, 1)
|
||||
print(f" Encrypted: {src.name} -> {out} ({size_kb} KB)")
|
||||
print(f" Name: {metadata['name']}")
|
||||
print(f" Version: {metadata['version']}")
|
||||
print(f" Tags: {', '.join(tags) or '(none)'}")
|
||||
print()
|
||||
print(" Copy the .aes file to modules/encrypted/ and it will appear in the web UI.")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
176
scripts/make_msi.py
Normal file
176
scripts/make_msi.py
Normal file
@@ -0,0 +1,176 @@
|
||||
"""
|
||||
make_msi.py — Create an MSI installer for AUTARCH using Python's built-in msilib.
|
||||
|
||||
Packages the contents of dist/bin/AUTARCH/ (PyInstaller one-dir build) into
|
||||
a Windows Installer .msi file at dist/bin/AUTARCH-{VERSION}-win64.msi.
|
||||
|
||||
Usage:
|
||||
python scripts/make_msi.py
|
||||
|
||||
Requires:
|
||||
- dist/bin/AUTARCH/ to exist (run PyInstaller first)
|
||||
- Windows (msilib is Windows-only)
|
||||
"""
|
||||
|
||||
import msilib
|
||||
import msilib.schema
|
||||
import msilib.sequence
|
||||
import msilib.text
|
||||
import os
|
||||
import sys
|
||||
import uuid
|
||||
from pathlib import Path
|
||||
|
||||
# ── Configuration ─────────────────────────────────────────────────────────────
|
||||
SRC_DIR = Path(__file__).parent.parent
|
||||
BUNDLE_DIR = SRC_DIR / 'dist' / 'bin' / 'AUTARCH'
|
||||
BIN_DIR = SRC_DIR / 'dist' / 'bin'
|
||||
VERSION = '1.3'
|
||||
APP_NAME = 'AUTARCH'
|
||||
MANUFACTURER = 'darkHal Security Group'
|
||||
PRODUCT_CODE = '{6E4A2B35-C8F1-4D28-A91E-8D4F7C3B2A91}'
|
||||
UPGRADE_CODE = '{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}'
|
||||
MSI_OUT = BIN_DIR / f'AUTARCH-{VERSION}-win64.msi'
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
def make_id(s: str, prefix: str = '') -> str:
|
||||
"""Create a valid MSI identifier from a string (max 72 chars, no spaces/slashes)."""
|
||||
safe = s.replace('\\', '_').replace('/', '_').replace(' ', '_').replace('.', '_').replace('-', '_')
|
||||
result = (prefix + safe)[:72]
|
||||
if result and result[0].isdigit():
|
||||
result = '_' + result[1:]
|
||||
return result
|
||||
|
||||
|
||||
def collect_files(bundle_dir: Path):
|
||||
"""Walk the bundle directory and return (relative_path, abs_path) tuples."""
|
||||
items = []
|
||||
for path in sorted(bundle_dir.rglob('*')):
|
||||
if path.is_file():
|
||||
rel = path.relative_to(bundle_dir)
|
||||
items.append((rel, path))
|
||||
return items
|
||||
|
||||
|
||||
def build_msi():
|
||||
if not BUNDLE_DIR.exists():
|
||||
print(f"ERROR: Bundle directory not found: {BUNDLE_DIR}")
|
||||
print("Run PyInstaller first: pyinstaller autarch.spec --distpath dist/bin")
|
||||
sys.exit(1)
|
||||
|
||||
BIN_DIR.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
print(f"Packaging {BUNDLE_DIR} -> {MSI_OUT}")
|
||||
|
||||
files = collect_files(BUNDLE_DIR)
|
||||
print(f" Files to package: {len(files)}")
|
||||
|
||||
# ── Create the MSI database ───────────────────────────────────────────────
|
||||
db = msilib.init_database(
|
||||
str(MSI_OUT),
|
||||
msilib.schema,
|
||||
APP_NAME,
|
||||
PRODUCT_CODE,
|
||||
VERSION,
|
||||
MANUFACTURER,
|
||||
)
|
||||
msilib.add_tables(db, msilib.sequence)
|
||||
|
||||
# ── Property table (extend — init_database already set some base properties) ──
|
||||
# Use the low-level view to INSERT only new properties
|
||||
try:
|
||||
msilib.add_data(db, 'Property', [
|
||||
('ALLUSERS', '1'),
|
||||
('ARPNOMODIFY', '1'),
|
||||
])
|
||||
except Exception:
|
||||
pass # Properties may already exist from init_database; skip
|
||||
|
||||
# ── Directory structure ───────────────────────────────────────────────────
|
||||
# Collect all unique subdirectories
|
||||
dirs = {}
|
||||
dirs['TARGETDIR'] = ('TARGETDIR', 'SourceDir')
|
||||
dirs['ProgramFilesFolder'] = ('TARGETDIR', 'PFiles')
|
||||
dirs['INSTALLFOLDER'] = ('ProgramFilesFolder', f'{APP_NAME}|{APP_NAME}')
|
||||
|
||||
subdir_set = set()
|
||||
for rel, _ in files:
|
||||
parts = rel.parts[:-1] # directory parts (no filename)
|
||||
for depth in range(len(parts)):
|
||||
sub = '\\'.join(parts[:depth + 1])
|
||||
subdir_set.add(sub)
|
||||
|
||||
# Map subdir path → directory ID
|
||||
dir_id_map = {'': 'INSTALLFOLDER'}
|
||||
dir_rows = [
|
||||
('TARGETDIR', None, 'SourceDir'),
|
||||
('ProgramFilesFolder', 'TARGETDIR', '.'),
|
||||
('INSTALLFOLDER', 'ProgramFilesFolder', APP_NAME),
|
||||
]
|
||||
|
||||
for sub in sorted(subdir_set):
|
||||
parts = sub.split('\\')
|
||||
parent_path = '\\'.join(parts[:-1])
|
||||
parent_id = dir_id_map.get(parent_path, 'INSTALLFOLDER')
|
||||
dir_id = make_id(sub, 'dir_')
|
||||
dir_id_map[sub] = dir_id
|
||||
short_name = parts[-1][:8] # 8.3 name (simplified)
|
||||
long_name = parts[-1]
|
||||
dir_name = f'{short_name}|{long_name}' if short_name != long_name else long_name
|
||||
dir_rows.append((dir_id, parent_id, dir_name))
|
||||
|
||||
msilib.add_data(db, 'Directory', dir_rows)
|
||||
|
||||
# ── Feature ───────────────────────────────────────────────────────────────
|
||||
msilib.add_data(db, 'Feature', [
|
||||
('Main', None, 'AUTARCH Application', 'Complete AUTARCH installation', 1, 1, None, 32),
|
||||
])
|
||||
|
||||
# ── Components and files ──────────────────────────────────────────────────
|
||||
comp_rows = []
|
||||
file_rows = []
|
||||
feat_comp = []
|
||||
|
||||
for idx, (rel, abs_path) in enumerate(files):
|
||||
parts = rel.parts
|
||||
subdir_key = '\\'.join(parts[:-1])
|
||||
dir_id = dir_id_map.get(subdir_key, 'INSTALLFOLDER')
|
||||
comp_id = f'c{idx}'
|
||||
file_id = f'f{idx}'
|
||||
comp_guid = str(uuid.uuid5(uuid.UUID(UPGRADE_CODE), str(rel))).upper()
|
||||
comp_guid = '{' + comp_guid + '}'
|
||||
|
||||
# Component row: (Component, ComponentId, Directory_, Attributes, Condition, KeyPath)
|
||||
comp_rows.append((comp_id, comp_guid, dir_id, 0, None, file_id))
|
||||
|
||||
# File row: (File, Component_, FileName, FileSize, Version, Language, Attributes, Sequence)
|
||||
fname = parts[-1]
|
||||
short = fname[:8]
|
||||
long = fname
|
||||
file_name = f'{short}|{long}' if short != long else long
|
||||
file_size = abs_path.stat().st_size
|
||||
file_rows.append((file_id, comp_id, file_name, file_size, None, None, 512, idx + 1))
|
||||
|
||||
# FeatureComponents: (Feature_, Component_)
|
||||
feat_comp.append(('Main', comp_id))
|
||||
|
||||
msilib.add_data(db, 'Component', comp_rows)
|
||||
msilib.add_data(db, 'File', file_rows)
|
||||
msilib.add_data(db, 'FeatureComponents', feat_comp)
|
||||
|
||||
# ── Media / cabinet ──────────────────────────────────────────────────────
|
||||
# CAB.commit() embeds the cabinet, adds the Media row, and calls db.Commit()
|
||||
cab = msilib.CAB('autarch.cab')
|
||||
for idx, (rel, abs_path) in enumerate(files):
|
||||
# append(full_path, file_id, logical_name_in_cab)
|
||||
cab.append(str(abs_path), f'f{idx}', rel.name)
|
||||
|
||||
cab.commit(db) # handles Media table insert + db.Commit() internally
|
||||
|
||||
size_mb = round(MSI_OUT.stat().st_size / (1024 * 1024), 1)
|
||||
print(f"\n OK: MSI created: {MSI_OUT} ({size_mb} MB)")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
build_msi()
|
||||
Reference in New Issue
Block a user