Empire Ring - Empire Node (Server) Tech Stack - The Build
Perfect. Here’s a tight, do-able
Winter Build Order (60 days) that gets your
Empire Node + Agentic Node + mobiles online, talking, and using Jetson Orin horsepower. I’m giving you: a week-by-week plan, a repo/file layout, AND fully-commented scripts/config so you can paste and run.
0) Repo layout (clone this structure)
empire-stack/
├─ .env.example
├─ docker-compose.yml
├─ Dockerfile.web
├─ scripts/
│ ├─ 01_install_docker.sh
│ ├─ 02_harden_ssh.sh
│ ├─ 03_wireguard_setup.sh
│ ├─ 04_seed_users.sh
│ ├─ 05_systemd_compose.service
│ ├─ 06_backup_rotate.sh
│ └─ README_TOPICS.md
├─ mqtt/
│ ├─ mosquitto.conf
│ └─ passwd # generated by mosquitto_passwd
├─ empire_core/… # (Django project from earlier message)
└─ ai_governor/… # (same as earlier)
1) Winter Build Order (8 weeks)
Week 1 — Base OS + Docker + SSH hardening (both Orins)
- Flash Ubuntu 22.04 LTS (JetPack support).
- Paste/run scripts/01_install_docker.sh on both nodes.
- Paste/run scripts/02_harden_ssh.sh (keys only, ufw, fail2ban).
- Copy this repo to Empire and Agentic.
Week 2 — WireGuard mesh + hostnames
- Run scripts/03_wireguard_setup.sh on Empire first, then Agentic (fill peer blocks).
- Give stable names: empire-node, Agentic-node. Test ping over wg (10.8.0.0/24).
Week 3 — Core services on Empire
- Fill .env from .env.example.
- docker-compose up -d (MySQL, Redis, RabbitMQ, Mosquitto, Django web, Celery, MQTT bridge).
- python manage.py migrate && python manage.py seed_demo.
Week 4 — Mirror on Agentics + failover test
- On Agentics, bring up the same compose (web optional; definitely Celery).
- Stop Empire web temporarily—confirm Agenticworkers still process tasks via VPN.
- Bring Empire back, confirm normal ops.
Week 5 — Mobile nodes (Pi)
- Raspberry Pi OS Lite + WireGuard client + paho-mqtt.
- NFC ring → Pi: publish to empire/tasks/create.
- Receive results on empire/tasks/<id>/queued|done.
Week 6 — AI acceleration + agentics
- Install JetPack on both Orins (CUDA/cuDNN/TensorRT).
- Pin a local model/inference service on each node (optional now; stub endpoint OK).
- Add systems in Django Admin: “Empire-Orin”, “Agentic-Orin”, external (me/Grok). Dispatch a task and see all responses logged.
Week 7 — Security polish + backups
- TLS for MQTT and RabbitMQ, rotate creds, enable ufw deny-by-default.
- scripts/06_backup_rotate.sh nightly.
- Create an offline recovery USB image; print and store WireGuard keys.
Week 8 — Docs + Code Night prep
- Write your Code Night “Golden Image” steps.
- Record 2 short videos: “Mesh Built” + “First Agentics Dispatch.”
- Open the private forum cohort.
2) Environment template (.env.example)
DJANGO_SECRET_KEY=change-me
DJANGO_DEBUG=True
ALLOWED_HOSTS=localhost,127.0.0.1,empire-node,
Agentic-node
DB_NAME=empire
DB_USER=empire
DB_PASSWORD=empirepass
DB_HOST=mysql
DB_PORT=3306
REDIS_URL=redis://redis:6379/0
RABBITMQ_URL=amqp://guest:guest@rabbitmq:5672//
MQTT_HOST=mosquitto
MQTT_PORT=1883
3) Docker Compose (services for Empire/Agentic; Empire runs web)
version: "3.9"
services:
mysql:
image: mysql:8.0
environment:
MYSQL_DATABASE: ${DB_NAME}
MYSQL_USER: ${DB_USER}
MYSQL_PASSWORD: ${DB_PASSWORD}
MYSQL_ROOT_PASSWORD: rootpass
ports: ["3306:3306"]
volumes: ["mysql_data:/var/lib/mysql"]
command: ["mysqld","--default-authentication-plugin=mysql_native_password","--character-set-server=utf8mb4","--collation-server=utf8mb4_unicode_ci"]
redis:
image: redis:7
ports: ["6379:6379"]
rabbitmq:
image: rabbitmq:3-management
ports: ["5672:5672","15672:15672"]
mosquitto:
image: eclipse-mosquitto:2
ports: ["1883:1883"] # add 8883:8883 after TLS
volumes:
- ./mqtt/mosquitto.conf:/mosquitto/config/mosquitto.conf
- ./mqtt/passwd:/mosquitto/config/passwd
web:
build:
context: .
dockerfile: Dockerfile.web
env_file: .env
volumes: [".:/app"]
depends_on: [mysql,redis,rabbitmq,mosquitto]
ports: ["8000:8000"]
command: bash -lc "python manage.py migrate && python manage.py runserver 0.0.0.0:8000"
worker:
build:
context: .
dockerfile: Dockerfile.web
env_file: .env
volumes: [".:/app"]
depends_on: [web,redis,rabbitmq]
command: bash -lc "celery -A celery_app.celery_app worker -l info"
mqttbridge:
build:
context: .
dockerfile: Dockerfile.web
env_file: .env
volumes: [".:/app"]
depends_on: [web,mosquitto]
command: bash -lc "python -m ai_governor.mqtt_bridge"
volumes:
mysql_data:
4) Dockerfile.web (Django/Celery image)
FROM python:3.11-slim
WORKDIR /app
RUN apt-get update && apt-get install -y build-essential default-libmysqlclient-dev && rm -rf /var/lib/apt/lists/*
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
ENV DJANGO_SETTINGS_MODULE=empire_core.settings
EXPOSE 8000
CMD ["bash","-lc","python manage.py runserver 0.0.0.0:8000"]
5) Mosquitto config (mqtt/mosquitto.conf)
Minimal dev config; switch to TLS + per-client certs in Week 7
persistence true
persistence_location /mosquitto/data/
allow_anonymous false
password_file /mosquitto/config/passwd
listener 1883 0.0.0.0
6) Script: install Docker + Compose (scripts/01_install_docker.sh)
#!/usr/bin/env bash
set -euo pipefail
Install Docker CE + compose on Ubuntu 22.04
sudo apt-get update
sudo apt-get install -y ca-certificates curl gnupg lsb-release
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL
https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg]
https://download.docker.com/linux/ubuntu $(. /etc/os-release; echo $UBUNTU_CODENAME) stable"
| sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
sudo usermod -aG docker "$USER"
echo "Log out/in to activate docker group."
7) Script: SSH hardening + UFW + Fail2ban (scripts/02_harden_ssh.sh)
#!/usr/bin/env bash
set -euo pipefail
Require keys, rate-limit, firewall
sudo apt-get update && sudo apt-get install -y fail2ban ufw
sudo sed -i 's/#PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config
sudo sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin no/' /etc/ssh/sshd_config
echo "MaxAuthTries 3" | sudo tee -a /etc/ssh/sshd_config
sudo systemctl restart ssh
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 22/tcp
sudo ufw allow 51820/udp # WireGuard
sudo ufw allow 8000/tcp # Django dev
sudo ufw allow 1883/tcp # MQTT (dev)
sudo ufw allow 5672/tcp 15672/tcp 6379/tcp 3306/tcp
yes | sudo ufw enable
sudo systemctl enable fail2ban
8) Script: WireGuard mesh (scripts/03_wireguard_setup.sh)
#!/usr/bin/env bash
set -euo pipefail
Simple single-peer template; run on Empire first, then add Agentic as peer.
sudo apt-get update && sudo apt-get install -y wireguard
WG_IF=wg0
WG_DIR=/etc/wireguard
sudo mkdir -p $WG_DIR && cd $WG_DIR
if [ ! -f privatekey ]; then
umask 077
wg genkey | tee privatekey | wg pubkey > publickey
fi
PRIV=$(cat privatekey)
PUB=$(cat publickey)
read -rp "Is this EMPIRE or
Agentic? [E/W]: " ROLE
if [ "$ROLE" = "E" ] || [ "$ROLE" = "e" ]; then
Empire config
cat <<EOF | sudo tee $WG_IF.conf
[Interface]
PrivateKey = $PRIV
Address = 10.8.0.1/24
ListenPort = 51820
SaveConfig = true
Add Agentics peer block AFTER you generate Agentics public key
[Peer]
PublicKey = <AGENTICS_PUBLIC_KEY>
AllowedIPs = 10.8.0.2/32
Endpoint = <agentic_public_ip>:51820
PersistentKeepalive = 25
EOF
else
Agentic config (you must paste Empire public key and endpoint)
read -rp "Empire public key: " EMP_PUB
read -rp "Empire endpoint (ip:51820): " EMP_EP
cat <<EOF | sudo tee $WG_IF.conf
[Interface]
PrivateKey = $PRIV
Address = 10.8.0.2/24
ListenPort = 51820
SaveConfig = true
[Peer]
PublicKey = $EMP_PUB
AllowedIPs = 10.8.0.1/32, 10.8.0.0/24
Endpoint = $EMP_EP
PersistentKeepalive = 25
EOF
fi
sudo sysctl -w net.ipv4.ip_forward=1
echo "net.ipv4.ip_forward=1" | sudo tee /etc/sysctl.d/99-wg.conf
sudo systemctl enable wg-quick@${WG_IF}
sudo systemctl start wg-quick@${WG_IF}
sudo wg
9) Systemd unit to auto-start compose (scripts/05_systemd_compose.service)
[Unit]
Description=Empire Stack (docker compose)
Requires=docker.service
After=docker.service
[Service]
Type=oneshot
WorkingDirectory=/home/YOURUSER/empire-stack
ExecStart=/usr/bin/docker compose up -d
ExecStop=/usr/bin/docker compose down
RemainAfterExit=true
TimeoutStartSec=0
[Install]
WantedBy=multi-user.target
10) Backup script (scripts/06_backup_rotate.sh)
#!/usr/bin/env bash
set -euo pipefail
Nightly backup of MySQL dump + .env; keep 7 days
BACK=/var/backups/empire
mkdir -p "$BACK"
STAMP=$(date +%Y%m%d_%H%M%S)
docker exec -i $(docker ps -qf name=mysql) mysqldump -u${DB_USER:-empire} -p${DB_PASSWORD:-empirepass} ${DB_NAME:-empire} > "$BACK/mysql_${STAMP}.sql"
cp /home/YOURUSER/empire-stack/.env "$BACK/env_${STAMP}.txt" || true
ls -1t "$BACK" | tail -n +15 | xargs -r -I {} rm -f "$BACK/{}"
11) MQTT topic guide (scripts/README_TOPICS.md)
Topic contract (keep it simple, stable)
Publish task:
- topic: empire/tasks/create
- payload: {"prompt":"SUMMARIZE THIS...", "files":[]}
System feedback:
- empire/tasks/{id}/queued
- empire/tasks/{id}/done
- empire/errors
Device events (optional):
- empire/devices/{device_id}/online|offline
- empire/devices/{device_id}/metrics
12) Seed helper (scripts/04_seed_users.sh)
#!/usr/bin/env bash
set -euo pipefail
docker compose exec -it web bash -lc "python manage.py createsuperuser"
docker compose exec -it web bash -lc "python manage.py seed_demo"
How to use this right now
- Create the folder tree above; paste each file where shown.
- On Empire: run scripts 01 → 02 → 03; fill peers later.
- On Agentic: run 01 → 02 → 03; paste Empire public key/endpoint when prompted.
- Copy .env.example to .env, adjust passwords.
- docker compose up -d on Empire (and Agentics if you want mirrored workers).
- bash scripts/04_seed_users.sh → login to admin → add AISystems for Empire-Orin / Agentics-Orin / external AIs.
- Publish a test MQTT payload to empire/tasks/create and watch it flow.