Add three-tier deployment infrastructure
Platform pivot from Raspberry Pi to three-tier model: - Tier 1: Bootable Debian Live USB for field reporters - Tier 2: Docker/K8s org server for newsrooms - Tier 3: Docker/K8s federation relay for VPS Tier 1 — Live USB (deploy/live-usb/): - build.sh: live-build based image builder for amd64 - Package list: Python + system deps + minimal GUI (openbox + Firefox) - Install hook: creates venv, pip installs soosef[web,cli,attest,...] - Hardening hook: disable swap/coredumps, UFW, auto-login to web UI - systemd service with security hardening (NoNewPrivileges, ProtectSystem) - Auto-opens Firefox kiosk to http://127.0.0.1:5000 on boot Tier 2+3 — Docker (deploy/docker/): - Multi-stage Dockerfile with two targets: - server: full web UI + stego + attestation + federation (Tier 2) - relay: lightweight FastAPI attestation API only (Tier 3) - docker-compose.yml with both services and persistent volumes - .dockerignore for clean builds Kubernetes (deploy/kubernetes/): - namespace.yaml, server-deployment.yaml, relay-deployment.yaml - PVCs, services, health checks, resource limits - Single-writer strategy (Recreate, not RollingUpdate) for SQLite safety - README with architecture diagram and deployment instructions Config presets (deploy/config-presets/): - low-threat.json: press freedom country (no killswitch, 30min sessions) - medium-threat.json: restricted press (48h deadman, USB monitoring) - high-threat.json: conflict zone (12h deadman, tamper monitoring, 5min sessions) - critical-threat.json: targeted surveillance (127.0.0.1 only, 6h deadman, 3min sessions) Deployment guide rewritten for three-tier model with RPi as legacy appendix. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
2a6900abed
commit
496198d49a
46
deploy/config-presets/README.md
Normal file
46
deploy/config-presets/README.md
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
# SooSeF Threat Level Configuration Presets
|
||||||
|
|
||||||
|
Select a preset based on your operational environment. Copy the appropriate
|
||||||
|
JSON file to `~/.soosef/config.json` (or let the setup wizard choose one).
|
||||||
|
|
||||||
|
## Presets
|
||||||
|
|
||||||
|
### low-threat.json — Press Freedom Country
|
||||||
|
Nordics, New Zealand, Canada. Risk is accidental data loss, not adversarial seizure.
|
||||||
|
- No killswitch or dead man's switch
|
||||||
|
- Relaxed session timeouts (30 min)
|
||||||
|
- Backup reminders every 14 days
|
||||||
|
- Chain enabled for provenance integrity
|
||||||
|
|
||||||
|
### medium-threat.json — Restricted Press
|
||||||
|
Turkey, Hungary, India. Risk of legal pressure, device seizure at borders.
|
||||||
|
- Killswitch available, dead man's switch at 48h/4h grace
|
||||||
|
- USB monitoring enabled
|
||||||
|
- Cover name: "Office Document Manager"
|
||||||
|
- Backup reminders every 7 days
|
||||||
|
|
||||||
|
### high-threat.json — Active Conflict Zone
|
||||||
|
Syria, Myanmar, Ethiopia, Iran. Risk of raids, equipment seizure, physical coercion.
|
||||||
|
- 5-minute session timeout
|
||||||
|
- Dead man's switch at 12h/1h grace
|
||||||
|
- Tamper monitoring enabled
|
||||||
|
- Cover name: "Local Inventory Tracker"
|
||||||
|
- Daily backup reminders
|
||||||
|
|
||||||
|
### critical-threat.json — Targeted Surveillance
|
||||||
|
Specific journalist or org targeted by state actor (Pegasus-level).
|
||||||
|
- Web UI bound to 127.0.0.1 only (access via SSH tunnel)
|
||||||
|
- 3-minute session timeout
|
||||||
|
- Dead man's switch at 6h/1h grace
|
||||||
|
- Cover name: "System Statistics"
|
||||||
|
- All monitoring enabled
|
||||||
|
- Consider: full-disk encryption, remove SSH after setup, Tor hidden service
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Copy preset to config location
|
||||||
|
cp deploy/config-presets/high-threat.json ~/.soosef/config.json
|
||||||
|
|
||||||
|
# Or via CLI (future: soosef init --threat-level high)
|
||||||
|
```
|
||||||
20
deploy/config-presets/critical-threat.json
Normal file
20
deploy/config-presets/critical-threat.json
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"host": "127.0.0.1",
|
||||||
|
"port": 5000,
|
||||||
|
"https_enabled": true,
|
||||||
|
"auth_enabled": true,
|
||||||
|
"session_timeout_minutes": 3,
|
||||||
|
"login_lockout_attempts": 3,
|
||||||
|
"login_lockout_minutes": 60,
|
||||||
|
"killswitch_enabled": true,
|
||||||
|
"deadman_enabled": true,
|
||||||
|
"deadman_interval_hours": 6,
|
||||||
|
"deadman_grace_hours": 1,
|
||||||
|
"deadman_warning_webhook": "",
|
||||||
|
"usb_monitoring_enabled": true,
|
||||||
|
"tamper_monitoring_enabled": true,
|
||||||
|
"chain_enabled": true,
|
||||||
|
"chain_auto_wrap": true,
|
||||||
|
"backup_reminder_days": 1,
|
||||||
|
"cover_name": "System Statistics"
|
||||||
|
}
|
||||||
20
deploy/config-presets/high-threat.json
Normal file
20
deploy/config-presets/high-threat.json
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"host": "0.0.0.0",
|
||||||
|
"port": 5000,
|
||||||
|
"https_enabled": true,
|
||||||
|
"auth_enabled": true,
|
||||||
|
"session_timeout_minutes": 5,
|
||||||
|
"login_lockout_attempts": 3,
|
||||||
|
"login_lockout_minutes": 30,
|
||||||
|
"killswitch_enabled": true,
|
||||||
|
"deadman_enabled": true,
|
||||||
|
"deadman_interval_hours": 12,
|
||||||
|
"deadman_grace_hours": 1,
|
||||||
|
"deadman_warning_webhook": "",
|
||||||
|
"usb_monitoring_enabled": true,
|
||||||
|
"tamper_monitoring_enabled": true,
|
||||||
|
"chain_enabled": true,
|
||||||
|
"chain_auto_wrap": true,
|
||||||
|
"backup_reminder_days": 1,
|
||||||
|
"cover_name": "Local Inventory Tracker"
|
||||||
|
}
|
||||||
20
deploy/config-presets/low-threat.json
Normal file
20
deploy/config-presets/low-threat.json
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"host": "0.0.0.0",
|
||||||
|
"port": 5000,
|
||||||
|
"https_enabled": true,
|
||||||
|
"auth_enabled": true,
|
||||||
|
"session_timeout_minutes": 30,
|
||||||
|
"login_lockout_attempts": 10,
|
||||||
|
"login_lockout_minutes": 5,
|
||||||
|
"killswitch_enabled": false,
|
||||||
|
"deadman_enabled": false,
|
||||||
|
"deadman_interval_hours": 24,
|
||||||
|
"deadman_grace_hours": 2,
|
||||||
|
"deadman_warning_webhook": "",
|
||||||
|
"usb_monitoring_enabled": false,
|
||||||
|
"tamper_monitoring_enabled": false,
|
||||||
|
"chain_enabled": true,
|
||||||
|
"chain_auto_wrap": true,
|
||||||
|
"backup_reminder_days": 14,
|
||||||
|
"cover_name": ""
|
||||||
|
}
|
||||||
20
deploy/config-presets/medium-threat.json
Normal file
20
deploy/config-presets/medium-threat.json
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"host": "0.0.0.0",
|
||||||
|
"port": 5000,
|
||||||
|
"https_enabled": true,
|
||||||
|
"auth_enabled": true,
|
||||||
|
"session_timeout_minutes": 15,
|
||||||
|
"login_lockout_attempts": 5,
|
||||||
|
"login_lockout_minutes": 15,
|
||||||
|
"killswitch_enabled": true,
|
||||||
|
"deadman_enabled": true,
|
||||||
|
"deadman_interval_hours": 48,
|
||||||
|
"deadman_grace_hours": 4,
|
||||||
|
"deadman_warning_webhook": "",
|
||||||
|
"usb_monitoring_enabled": true,
|
||||||
|
"tamper_monitoring_enabled": false,
|
||||||
|
"chain_enabled": true,
|
||||||
|
"chain_auto_wrap": true,
|
||||||
|
"backup_reminder_days": 7,
|
||||||
|
"cover_name": "Office Document Manager"
|
||||||
|
}
|
||||||
10
deploy/docker/.dockerignore
Normal file
10
deploy/docker/.dockerignore
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
.git
|
||||||
|
.claude
|
||||||
|
__pycache__
|
||||||
|
*.pyc
|
||||||
|
.coverage
|
||||||
|
.pytest_cache
|
||||||
|
docs
|
||||||
|
deploy/live-usb
|
||||||
|
test_data
|
||||||
|
*.egg-info
|
||||||
80
deploy/docker/Dockerfile
Normal file
80
deploy/docker/Dockerfile
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
# SooSeF Federation Server
|
||||||
|
# Multi-stage build for minimal image size.
|
||||||
|
#
|
||||||
|
# Tier 2: Org server (full features — web UI, attestation, federation, stego)
|
||||||
|
# docker build -t soosef-server .
|
||||||
|
# docker run -v soosef-data:/data -p 5000:5000 -p 8000:8000 soosef-server
|
||||||
|
#
|
||||||
|
# Tier 3: Federation relay (attestation + federation only, no stego, no web UI)
|
||||||
|
# docker build --target relay -t soosef-relay .
|
||||||
|
# docker run -v relay-data:/data -p 8000:8000 soosef-relay
|
||||||
|
|
||||||
|
# === Stage 1: Build dependencies ===
|
||||||
|
FROM python:3.12-slim-bookworm AS builder
|
||||||
|
|
||||||
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
|
gcc g++ gfortran \
|
||||||
|
libjpeg62-turbo-dev zlib1g-dev libffi-dev libssl-dev \
|
||||||
|
libopenblas-dev \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
WORKDIR /build
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
# Install into a virtual environment for clean copying
|
||||||
|
RUN python -m venv /opt/soosef-env \
|
||||||
|
&& /opt/soosef-env/bin/pip install --no-cache-dir \
|
||||||
|
".[web,cli,attest,stego-dct,api,federation]"
|
||||||
|
|
||||||
|
# === Stage 2: Federation relay (minimal) ===
|
||||||
|
FROM python:3.12-slim-bookworm AS relay
|
||||||
|
|
||||||
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
|
libjpeg62-turbo libopenblas0 \
|
||||||
|
&& rm -rf /var/lib/apt/lists/* \
|
||||||
|
&& useradd -m -s /bin/bash soosef
|
||||||
|
|
||||||
|
COPY --from=builder /opt/soosef-env /opt/soosef-env
|
||||||
|
|
||||||
|
ENV PATH="/opt/soosef-env/bin:$PATH" \
|
||||||
|
SOOSEF_DATA_DIR=/data \
|
||||||
|
PYTHONUNBUFFERED=1
|
||||||
|
|
||||||
|
VOLUME /data
|
||||||
|
EXPOSE 8000
|
||||||
|
|
||||||
|
USER soosef
|
||||||
|
|
||||||
|
# Federation relay: only the verisoo API with federation endpoints
|
||||||
|
CMD ["uvicorn", "soosef.verisoo.api:app", "--host", "0.0.0.0", "--port", "8000"]
|
||||||
|
|
||||||
|
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s \
|
||||||
|
CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:8000/health')"
|
||||||
|
|
||||||
|
# === Stage 3: Full org server ===
|
||||||
|
FROM python:3.12-slim-bookworm AS server
|
||||||
|
|
||||||
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
|
libjpeg62-turbo libopenblas0 \
|
||||||
|
&& rm -rf /var/lib/apt/lists/* \
|
||||||
|
&& useradd -m -s /bin/bash soosef
|
||||||
|
|
||||||
|
COPY --from=builder /opt/soosef-env /opt/soosef-env
|
||||||
|
|
||||||
|
# Copy frontend templates and static assets
|
||||||
|
COPY frontends/ /opt/soosef-env/lib/python3.12/site-packages/frontends/
|
||||||
|
|
||||||
|
ENV PATH="/opt/soosef-env/bin:$PATH" \
|
||||||
|
SOOSEF_DATA_DIR=/data \
|
||||||
|
PYTHONUNBUFFERED=1
|
||||||
|
|
||||||
|
VOLUME /data
|
||||||
|
EXPOSE 5000 8000
|
||||||
|
|
||||||
|
USER soosef
|
||||||
|
|
||||||
|
# Init on first run, then start web UI + federation API
|
||||||
|
CMD ["sh", "-c", "soosef init 2>/dev/null; soosef serve --host 0.0.0.0 --no-https"]
|
||||||
|
|
||||||
|
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s \
|
||||||
|
CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:5000/health')"
|
||||||
51
deploy/docker/docker-compose.yml
Normal file
51
deploy/docker/docker-compose.yml
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
# SooSeF Docker Compose — Three-Tier Deployment
|
||||||
|
#
|
||||||
|
# Tier 2 (Org Server): Full web UI + attestation + federation
|
||||||
|
# Tier 3 (Federation Relay): Lightweight attestation API only
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# Full org server: docker compose up server
|
||||||
|
# Federation relay only: docker compose up relay
|
||||||
|
# Both (e.g., testing): docker compose up
|
||||||
|
|
||||||
|
services:
|
||||||
|
# === Tier 2: Organizational Server ===
|
||||||
|
# Full SooSeF instance with web UI, stego, attestation, federation.
|
||||||
|
# Deploy on a mini PC in the newsroom or a trusted VPS.
|
||||||
|
server:
|
||||||
|
build:
|
||||||
|
context: ../..
|
||||||
|
dockerfile: deploy/docker/Dockerfile
|
||||||
|
target: server
|
||||||
|
ports:
|
||||||
|
- "5000:5000" # Web UI (Flask/Waitress)
|
||||||
|
- "8000:8000" # Federation API (FastAPI/uvicorn)
|
||||||
|
volumes:
|
||||||
|
- server-data:/data
|
||||||
|
environment:
|
||||||
|
- SOOSEF_DATA_DIR=/data
|
||||||
|
- VERISOO_GOSSIP_INTERVAL=60
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
# === Tier 3: Federation Relay ===
|
||||||
|
# Lightweight relay for cross-organization attestation sync.
|
||||||
|
# Deploy on a VPS in a friendly jurisdiction (Iceland, Switzerland).
|
||||||
|
# Stores only attestation records — no key material, no stego, no web UI.
|
||||||
|
relay:
|
||||||
|
build:
|
||||||
|
context: ../..
|
||||||
|
dockerfile: deploy/docker/Dockerfile
|
||||||
|
target: relay
|
||||||
|
ports:
|
||||||
|
- "8001:8000" # Federation API
|
||||||
|
volumes:
|
||||||
|
- relay-data:/data
|
||||||
|
environment:
|
||||||
|
- SOOSEF_DATA_DIR=/data
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
server-data:
|
||||||
|
driver: local
|
||||||
|
relay-data:
|
||||||
|
driver: local
|
||||||
52
deploy/kubernetes/README.md
Normal file
52
deploy/kubernetes/README.md
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
# SooSeF Kubernetes Deployment
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
```
|
||||||
|
Field Devices (Tier 1)
|
||||||
|
(Bootable USB + laptop)
|
||||||
|
|
|
||||||
|
| LAN / sneakernet
|
||||||
|
v
|
||||||
|
┌───────────────────────┐
|
||||||
|
│ Org Server (Tier 2) │ <-- server-deployment.yaml
|
||||||
|
│ Full web UI + stego │
|
||||||
|
│ + attestation + fed │
|
||||||
|
│ Newsroom mini PC │
|
||||||
|
└───────────┬───────────┘
|
||||||
|
|
|
||||||
|
| gossip / federation API
|
||||||
|
v
|
||||||
|
┌───────────────────────┐
|
||||||
|
│ Fed Relay (Tier 3) │ <-- relay-deployment.yaml
|
||||||
|
│ Attestation API only │
|
||||||
|
│ VPS (Iceland, CH) │
|
||||||
|
│ Zero key knowledge │
|
||||||
|
└───────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Build images
|
||||||
|
docker build -t soosef-server --target server -f deploy/docker/Dockerfile .
|
||||||
|
docker build -t soosef-relay --target relay -f deploy/docker/Dockerfile .
|
||||||
|
|
||||||
|
# Deploy to Kubernetes
|
||||||
|
kubectl apply -f deploy/kubernetes/namespace.yaml
|
||||||
|
kubectl apply -f deploy/kubernetes/server-deployment.yaml
|
||||||
|
kubectl apply -f deploy/kubernetes/relay-deployment.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
- **Single writer**: Both deployments use `replicas: 1` with `Recreate` strategy.
|
||||||
|
SooSeF uses SQLite and append-only binary logs that require single-writer access.
|
||||||
|
Do not scale horizontally.
|
||||||
|
- **PVCs**: Both deployments require persistent volumes. The server needs 10Gi,
|
||||||
|
the relay needs 5Gi. Adjust based on expected attestation volume.
|
||||||
|
- **Security**: The relay stores only attestation records (image hashes + signatures).
|
||||||
|
It never sees encryption keys, plaintext messages, or original images.
|
||||||
|
If the relay is seized, the attacker gets cryptographic hashes — nothing actionable.
|
||||||
|
- **Ingress**: Not included. Configure your own ingress controller with TLS termination.
|
||||||
|
The federation API should be TLS-encrypted in transit.
|
||||||
6
deploy/kubernetes/namespace.yaml
Normal file
6
deploy/kubernetes/namespace.yaml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: soosef
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: soosef
|
||||||
85
deploy/kubernetes/relay-deployment.yaml
Normal file
85
deploy/kubernetes/relay-deployment.yaml
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
# SooSeF Federation Relay — Lightweight attestation sync relay.
|
||||||
|
# Deploy on a VPS in a favorable jurisdiction for geographic redundancy.
|
||||||
|
# Stores only attestation records — zero knowledge of encryption keys.
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: soosef-relay
|
||||||
|
namespace: soosef
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: soosef
|
||||||
|
app.kubernetes.io/component: relay
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
strategy:
|
||||||
|
type: Recreate
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app.kubernetes.io/name: soosef
|
||||||
|
app.kubernetes.io/component: relay
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: soosef
|
||||||
|
app.kubernetes.io/component: relay
|
||||||
|
spec:
|
||||||
|
securityContext:
|
||||||
|
runAsUser: 1000
|
||||||
|
runAsGroup: 1000
|
||||||
|
fsGroup: 1000
|
||||||
|
containers:
|
||||||
|
- name: relay
|
||||||
|
image: soosef-relay:latest
|
||||||
|
ports:
|
||||||
|
- containerPort: 8000
|
||||||
|
name: federation
|
||||||
|
env:
|
||||||
|
- name: SOOSEF_DATA_DIR
|
||||||
|
value: /data
|
||||||
|
volumeMounts:
|
||||||
|
- name: data
|
||||||
|
mountPath: /data
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
memory: "256Mi"
|
||||||
|
cpu: "100m"
|
||||||
|
limits:
|
||||||
|
memory: "1Gi"
|
||||||
|
cpu: "1000m"
|
||||||
|
livenessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /health
|
||||||
|
port: 8000
|
||||||
|
initialDelaySeconds: 10
|
||||||
|
periodSeconds: 30
|
||||||
|
volumes:
|
||||||
|
- name: data
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: relay-data
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: relay-data
|
||||||
|
namespace: soosef
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 5Gi
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: soosef-relay
|
||||||
|
namespace: soosef
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
app.kubernetes.io/name: soosef
|
||||||
|
app.kubernetes.io/component: relay
|
||||||
|
ports:
|
||||||
|
- name: federation
|
||||||
|
port: 8000
|
||||||
|
targetPort: 8000
|
||||||
|
type: ClusterIP
|
||||||
97
deploy/kubernetes/server-deployment.yaml
Normal file
97
deploy/kubernetes/server-deployment.yaml
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
# SooSeF Org Server — Full deployment with persistent storage.
|
||||||
|
# For newsroom or trusted infrastructure deployment.
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: soosef-server
|
||||||
|
namespace: soosef
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: soosef
|
||||||
|
app.kubernetes.io/component: server
|
||||||
|
spec:
|
||||||
|
replicas: 1 # Single writer — do not scale horizontally
|
||||||
|
strategy:
|
||||||
|
type: Recreate # Not RollingUpdate — SQLite + append-only logs need single writer
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app.kubernetes.io/name: soosef
|
||||||
|
app.kubernetes.io/component: server
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: soosef
|
||||||
|
app.kubernetes.io/component: server
|
||||||
|
spec:
|
||||||
|
securityContext:
|
||||||
|
runAsUser: 1000
|
||||||
|
runAsGroup: 1000
|
||||||
|
fsGroup: 1000
|
||||||
|
containers:
|
||||||
|
- name: soosef
|
||||||
|
image: soosef-server:latest
|
||||||
|
ports:
|
||||||
|
- containerPort: 5000
|
||||||
|
name: web
|
||||||
|
- containerPort: 8000
|
||||||
|
name: federation
|
||||||
|
env:
|
||||||
|
- name: SOOSEF_DATA_DIR
|
||||||
|
value: /data
|
||||||
|
- name: VERISOO_GOSSIP_INTERVAL
|
||||||
|
value: "60"
|
||||||
|
volumeMounts:
|
||||||
|
- name: data
|
||||||
|
mountPath: /data
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
memory: "512Mi"
|
||||||
|
cpu: "250m"
|
||||||
|
limits:
|
||||||
|
memory: "2Gi"
|
||||||
|
cpu: "2000m"
|
||||||
|
livenessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /health
|
||||||
|
port: 5000
|
||||||
|
initialDelaySeconds: 15
|
||||||
|
periodSeconds: 30
|
||||||
|
readinessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /health
|
||||||
|
port: 5000
|
||||||
|
initialDelaySeconds: 10
|
||||||
|
periodSeconds: 10
|
||||||
|
volumes:
|
||||||
|
- name: data
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: soosef-data
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: soosef-data
|
||||||
|
namespace: soosef
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 10Gi
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: soosef-server
|
||||||
|
namespace: soosef
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
app.kubernetes.io/name: soosef
|
||||||
|
app.kubernetes.io/component: server
|
||||||
|
ports:
|
||||||
|
- name: web
|
||||||
|
port: 5000
|
||||||
|
targetPort: 5000
|
||||||
|
- name: federation
|
||||||
|
port: 8000
|
||||||
|
targetPort: 8000
|
||||||
|
type: ClusterIP
|
||||||
47
deploy/live-usb/build.sh
Executable file
47
deploy/live-usb/build.sh
Executable file
@ -0,0 +1,47 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Build a bootable Debian Live USB image with SooSeF pre-installed.
|
||||||
|
#
|
||||||
|
# Prerequisites:
|
||||||
|
# apt install live-build
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# cd deploy/live-usb
|
||||||
|
# sudo ./build.sh
|
||||||
|
#
|
||||||
|
# Output: live-image-amd64.hybrid.iso (flash to USB with dd or Balena Etcher)
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||||
|
SOOSEF_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||||
|
|
||||||
|
echo "=== SooSeF Live USB Image Builder ==="
|
||||||
|
echo "Source: $SOOSEF_ROOT"
|
||||||
|
echo
|
||||||
|
|
||||||
|
cd "$SCRIPT_DIR"
|
||||||
|
|
||||||
|
# Clean previous builds
|
||||||
|
lb clean 2>/dev/null || true
|
||||||
|
|
||||||
|
# Configure live-build
|
||||||
|
lb config \
|
||||||
|
--distribution bookworm \
|
||||||
|
--architectures amd64 \
|
||||||
|
--binary-images iso-hybrid \
|
||||||
|
--memtest none \
|
||||||
|
--bootappend-live "boot=live components locales=en_US.UTF-8 keyboard-layouts=us" \
|
||||||
|
--apt-indices false \
|
||||||
|
--security true \
|
||||||
|
--updates true
|
||||||
|
|
||||||
|
# Build
|
||||||
|
echo "Building image (this takes 10-20 minutes)..."
|
||||||
|
lb build
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "=== Build complete ==="
|
||||||
|
echo "Image: $(ls -lh live-image-*.iso 2>/dev/null || echo 'Check for .iso file')"
|
||||||
|
echo
|
||||||
|
echo "Flash to USB:"
|
||||||
|
echo " sudo dd if=live-image-amd64.hybrid.iso of=/dev/sdX bs=4M status=progress"
|
||||||
|
echo " (replace /dev/sdX with your USB device)"
|
||||||
26
deploy/live-usb/config/hooks/live/0100-install-soosef.hook.chroot
Executable file
26
deploy/live-usb/config/hooks/live/0100-install-soosef.hook.chroot
Executable file
@ -0,0 +1,26 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Install SooSeF and all dependencies into the live image.
|
||||||
|
# This runs inside the chroot during image build.
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
echo "=== Installing SooSeF ==="
|
||||||
|
|
||||||
|
# Create soosef user
|
||||||
|
useradd -m -s /bin/bash -G sudo soosef
|
||||||
|
echo "soosef:soosef" | chpasswd
|
||||||
|
|
||||||
|
# Create virtual environment
|
||||||
|
python3 -m venv /opt/soosef-env
|
||||||
|
source /opt/soosef-env/bin/activate
|
||||||
|
|
||||||
|
# Install soosef with all extras (pre-built wheels from PyPI)
|
||||||
|
pip install --no-cache-dir "soosef[web,cli,attest,stego-dct,stego-audio,fieldkit]"
|
||||||
|
|
||||||
|
# Verify installation
|
||||||
|
python3 -c "import soosef; print(f'SooSeF {soosef.__version__} installed')"
|
||||||
|
python3 -c "from soosef.stegasoo import encode; print('stegasoo OK')"
|
||||||
|
python3 -c "from soosef.verisoo import Attestation; print('verisoo OK')"
|
||||||
|
|
||||||
|
deactivate
|
||||||
|
|
||||||
|
echo "=== SooSeF installation complete ==="
|
||||||
39
deploy/live-usb/config/hooks/live/0200-harden.hook.chroot
Executable file
39
deploy/live-usb/config/hooks/live/0200-harden.hook.chroot
Executable file
@ -0,0 +1,39 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Security hardening for the live image.
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
echo "=== Applying security hardening ==="
|
||||||
|
|
||||||
|
# Disable core dumps (Python doesn't zero memory — core dumps leak keys)
|
||||||
|
echo "* hard core 0" >> /etc/security/limits.conf
|
||||||
|
echo "fs.suid_dumpable = 0" >> /etc/sysctl.d/99-soosef.conf
|
||||||
|
echo "kernel.core_pattern=|/bin/false" >> /etc/sysctl.d/99-soosef.conf
|
||||||
|
|
||||||
|
# Disable swap (keys persist in swap pages)
|
||||||
|
systemctl mask swap.target || true
|
||||||
|
echo "vm.swappiness = 0" >> /etc/sysctl.d/99-soosef.conf
|
||||||
|
|
||||||
|
# Enable UFW with deny-all + allow web UI
|
||||||
|
ufw default deny incoming
|
||||||
|
ufw default allow outgoing
|
||||||
|
ufw allow 5000/tcp comment "SooSeF Web UI"
|
||||||
|
ufw allow 22/tcp comment "SSH"
|
||||||
|
ufw --force enable || true
|
||||||
|
|
||||||
|
# Disable unnecessary services
|
||||||
|
systemctl disable bluetooth.service 2>/dev/null || true
|
||||||
|
systemctl disable avahi-daemon.service 2>/dev/null || true
|
||||||
|
systemctl disable cups.service 2>/dev/null || true
|
||||||
|
|
||||||
|
# Enable SooSeF service
|
||||||
|
systemctl enable soosef.service
|
||||||
|
|
||||||
|
# Auto-login to openbox (so the browser opens without login prompt)
|
||||||
|
mkdir -p /etc/lightdm/lightdm.conf.d
|
||||||
|
cat > /etc/lightdm/lightdm.conf.d/50-autologin.conf << 'EOF'
|
||||||
|
[Seat:*]
|
||||||
|
autologin-user=soosef
|
||||||
|
autologin-user-timeout=0
|
||||||
|
EOF
|
||||||
|
|
||||||
|
echo "=== Hardening complete ==="
|
||||||
@ -0,0 +1,28 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=SooSeF Security Fieldkit
|
||||||
|
After=network-online.target
|
||||||
|
Wants=network-online.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
User=soosef
|
||||||
|
Group=soosef
|
||||||
|
WorkingDirectory=/home/soosef
|
||||||
|
Environment=PATH=/opt/soosef-env/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
||||||
|
Environment=SOOSEF_DATA_DIR=/home/soosef/.soosef
|
||||||
|
ExecStartPre=/opt/soosef-env/bin/soosef init --no-identity --no-channel
|
||||||
|
ExecStart=/opt/soosef-env/bin/soosef serve --host 0.0.0.0 --no-https
|
||||||
|
Restart=on-failure
|
||||||
|
RestartSec=5
|
||||||
|
|
||||||
|
# Security hardening
|
||||||
|
NoNewPrivileges=yes
|
||||||
|
ProtectSystem=strict
|
||||||
|
ProtectHome=read-only
|
||||||
|
ReadWritePaths=/home/soosef/.soosef
|
||||||
|
PrivateTmp=yes
|
||||||
|
ProtectKernelTunables=yes
|
||||||
|
ProtectControlGroups=yes
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
@ -0,0 +1,4 @@
|
|||||||
|
# SooSeF Live USB — auto-open web UI in Firefox
|
||||||
|
# Wait for the SooSeF server to start, then open the browser
|
||||||
|
sleep 5
|
||||||
|
firefox-esr --kiosk http://127.0.0.1:5000 &
|
||||||
41
deploy/live-usb/config/package-lists/soosef.list.chroot
Normal file
41
deploy/live-usb/config/package-lists/soosef.list.chroot
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
## System essentials
|
||||||
|
python3
|
||||||
|
python3-pip
|
||||||
|
python3-venv
|
||||||
|
python3-dev
|
||||||
|
|
||||||
|
## Build dependencies for Python packages with C extensions
|
||||||
|
libjpeg62-turbo-dev
|
||||||
|
zlib1g-dev
|
||||||
|
libffi-dev
|
||||||
|
libssl-dev
|
||||||
|
gfortran
|
||||||
|
libopenblas-dev
|
||||||
|
|
||||||
|
## SooSeF runtime dependencies
|
||||||
|
gpsd
|
||||||
|
gpsd-clients
|
||||||
|
cryptsetup
|
||||||
|
ufw
|
||||||
|
shred
|
||||||
|
|
||||||
|
## Useful tools
|
||||||
|
curl
|
||||||
|
wget
|
||||||
|
git
|
||||||
|
htop
|
||||||
|
usbutils
|
||||||
|
pciutils
|
||||||
|
|
||||||
|
## GUI (minimal — just a browser for the web UI)
|
||||||
|
xorg
|
||||||
|
openbox
|
||||||
|
firefox-esr
|
||||||
|
lightdm
|
||||||
|
|
||||||
|
## Firmware for common laptop hardware
|
||||||
|
firmware-linux-free
|
||||||
|
firmware-misc-nonfree
|
||||||
|
firmware-iwlwifi
|
||||||
|
firmware-realtek
|
||||||
|
firmware-atheros
|
||||||
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user