sidecar: build FIPS from source in Docker, handle fipstop terminal init

- Add multi-stage Dockerfile: Rust builder stage compiles FIPS with
  --no-default-features --features tui (excludes BLE/libdbus)
- Move build context to repo root so Dockerfile can access Cargo.toml/src
- Add .dockerignore to exclude target/, .git/, testing/ from context
- Fix UDP port mapping to 2121:2121
- Delete scripts/build.sh cross-compile workflow
- Simplify README setup steps (no local Rust toolchain needed)
- Replace ratatui::init() with try_init() for clean error on terminal
  init failure (e.g. Docker on macOS Sequoia)
This commit is contained in:
Origami74
2026-03-31 18:11:00 +00:00
committed by Johnathan Corgan
parent 8e38d889fa
commit 7224ce34f6
6 changed files with 38 additions and 89 deletions

View File

@@ -1,3 +1,19 @@
# ── Build stage: compile FIPS from source ──
FROM rust:1.94-slim-trixie AS builder
RUN apt-get update && \
apt-get install -y --no-install-recommends \
pkg-config && \
rm -rf /var/lib/apt/lists/*
WORKDIR /build
COPY Cargo.toml Cargo.lock rust-toolchain.toml build.rs ./
COPY src ./src
RUN cargo build --release --no-default-features --features tui && \
cp target/release/fips target/release/fipsctl target/release/fipstop /usr/local/bin/
# ── Runtime stage ──
FROM debian:trixie-slim FROM debian:trixie-slim
RUN apt-get update && \ RUN apt-get update && \
@@ -45,9 +61,8 @@ RUN printf '%s\n' \
'no-resolv' \ 'no-resolv' \
>> /etc/dnsmasq.conf >> /etc/dnsmasq.conf
COPY fips fipsctl fipstop /usr/local/bin/ COPY --from=builder /usr/local/bin/fips /usr/local/bin/fipsctl /usr/local/bin/fipstop /usr/local/bin/
RUN chmod +x /usr/local/bin/fips /usr/local/bin/fipsctl /usr/local/bin/fipstop
COPY entrypoint.sh /entrypoint.sh COPY examples/sidecar-nostr-relay/entrypoint.sh /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"] ENTRYPOINT ["/entrypoint.sh"]

View File

@@ -0,0 +1,6 @@
target/
.git/
.github/
testing/
examples/
!examples/sidecar-nostr-relay/

View File

@@ -7,19 +7,7 @@ iptables — it can only be reached via the node's `.fips` name.
## How to Run ## How to Run
### 1. Build the FIPS binaries ### 1. Set your node identity
From the repo root, compile FIPS for Linux and copy the binaries into the
Docker build context:
```bash
cd examples/sidecar-nostr-relay
./scripts/build.sh
```
Cross-compilation from macOS is supported via `cargo-zigbuild`.
### 2. Set your node identity
The relay needs a unique FIPS identity. Generate one with: The relay needs a unique FIPS identity. Generate one with:
@@ -36,9 +24,13 @@ FIPS_NSEC=nsec1... # paste your nsec here
`FIPS_NSEC` is required — the container will refuse to start without it. `FIPS_NSEC` is required — the container will refuse to start without it.
### 3. Start the stack ### 2. Start the stack
FIPS is compiled from source inside the Docker build stage — no local Rust
toolchain, Zig, or cargo-zigbuild needed.
```bash ```bash
cd examples/sidecar-nostr-relay
docker compose up -d docker compose up -d
``` ```
@@ -47,7 +39,7 @@ This starts two containers that share a network namespace:
- **fips** — FIPS daemon + dnsmasq. Owns the namespace, creates `fips0`. - **fips** — FIPS daemon + dnsmasq. Owns the namespace, creates `fips0`.
- **app** — strfry relay + nginx. Joins the namespace via `network_mode: service:fips`. - **app** — strfry relay + nginx. Joins the namespace via `network_mode: service:fips`.
### 4. Verify ### 3. Verify
```bash ```bash
# FIPS node is up and has a mesh address: # FIPS node is up and has a mesh address:
@@ -63,7 +55,7 @@ docker exec sidecar-nostr-relay-fips-1 fipsctl show peers
docker compose logs -f docker compose logs -f
``` ```
### 5. Connect to the relay ### 4. Connect to the relay
Your node's npub (and therefore its `.fips` name) is derived from its keypair: Your node's npub (and therefore its `.fips` name) is derived from its keypair:
@@ -146,17 +138,6 @@ DNS inside the container is handled by dnsmasq (127.0.0.1:53):
The `resolv.conf` mount points the container's resolver at 127.0.0.1, The `resolv.conf` mount points the container's resolver at 127.0.0.1,
where dnsmasq handles the routing. where dnsmasq handles the routing.
## Build
```bash
cd examples/sidecar-nostr-relay
./scripts/build.sh
```
This compiles FIPS for Linux, copies the binaries into the Docker context,
and builds the sidecar and app images. Cross-compilation from macOS is
supported via `cargo-zigbuild`.
## Run with Peers ## Run with Peers
To connect the sidecar to an existing mesh, provide the peer's npub and To connect the sidecar to an existing mesh, provide the peer's npub and

View File

@@ -9,7 +9,8 @@ networks:
services: services:
fips: fips:
build: build:
context: . context: ../..
dockerfile: examples/sidecar-nostr-relay/Dockerfile
hostname: fips-sidecar hostname: fips-sidecar
cap_add: cap_add:
- NET_ADMIN - NET_ADMIN

View File

@@ -1,57 +0,0 @@
#!/bin/bash
# Build the FIPS binary and Docker sidecar image.
# Usage: ./build.sh
set -e
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
DOCKER_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
# Find project root (directory containing Cargo.toml)
PROJECT_ROOT="$(cd "$DOCKER_DIR/../.." && pwd)"
if [ ! -f "$PROJECT_ROOT/Cargo.toml" ]; then
echo "Error: Cannot find Cargo.toml at $PROJECT_ROOT" >&2
echo "Expected layout: <project-root>/examples/sidecar-nostr-relay/scripts/build.sh" >&2
exit 1
fi
# Detect host OS
UNAME_S=$(uname -s)
CARGO_TARGET="x86_64-unknown-linux-musl"
if [ "$UNAME_S" = "Darwin" ]; then
echo "Detected macOS host — using cross-compilation for Linux..."
if ! command -v cargo-zigbuild &> /dev/null; then
echo "Error: cargo-zigbuild not found." >&2
echo "Please install it: cargo install cargo-zigbuild" >&2
exit 1
fi
if ! rustup target list --installed | grep -q "$CARGO_TARGET"; then
echo "Installing Rust target $CARGO_TARGET..."
rustup target add "$CARGO_TARGET"
fi
echo "Building FIPS for Linux (release) using cargo-zigbuild..."
cargo zigbuild --release --target "$CARGO_TARGET" --manifest-path="$PROJECT_ROOT/Cargo.toml"
echo "Copying binaries to docker context..."
cp "$PROJECT_ROOT/target/$CARGO_TARGET/release/fips" "$DOCKER_DIR/fips"
cp "$PROJECT_ROOT/target/$CARGO_TARGET/release/fipsctl" "$DOCKER_DIR/fipsctl"
cp "$PROJECT_ROOT/target/$CARGO_TARGET/release/fipstop" "$DOCKER_DIR/fipstop"
else
echo "Building FIPS (release)..."
cargo build --release --manifest-path="$PROJECT_ROOT/Cargo.toml"
echo "Copying binaries to docker context..."
cp "$PROJECT_ROOT/target/release/fips" "$DOCKER_DIR/fips"
cp "$PROJECT_ROOT/target/release/fipsctl" "$DOCKER_DIR/fipsctl"
cp "$PROJECT_ROOT/target/release/fipstop" "$DOCKER_DIR/fipstop"
fi
echo "Done. Binaries at $DOCKER_DIR/{fips,fipsctl,fipstop}"
echo ""
echo "Building Docker image..."
docker compose -f "$DOCKER_DIR/docker-compose.yml" build
echo ""
echo "Ready: cd examples/sidecar-nostr-relay && docker compose up -d"

View File

@@ -121,7 +121,10 @@ fn main() {
.expect("failed to create tokio runtime"); .expect("failed to create tokio runtime");
let client = ControlClient::new(&socket_path); let client = ControlClient::new(&socket_path);
let mut terminal = ratatui::init(); let mut terminal = ratatui::try_init().unwrap_or_else(|e| {
eprintln!("fipstop: failed to initialize terminal: {e}");
std::process::exit(1);
});
let mut app = App::new(refresh); let mut app = App::new(refresh);
let events = EventHandler::new(refresh); let events = EventHandler::new(refresh);