From c8b7459fbcb7450ab7d39173bd3f8b433f0e08de Mon Sep 17 00:00:00 2001 From: Origami74 Date: Thu, 19 Mar 2026 16:23:13 +0000 Subject: [PATCH] Add sidecar-nostr-relay example and fix openwrt CI path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a complete example running a strfry Nostr relay exclusively over the FIPS mesh using the sidecar pattern. Includes Docker Compose stack, network isolation via iptables, .fips DNS resolution, nak CLI, build script with cross-compilation support, and documentation. Also fix the package-openwrt.yml workflow path to match the openwrt → openwrt-ipk directory rename. --- .github/workflows/package-openwrt.yml | 2 +- examples/sidecar-nostr-relay/.env | 12 + examples/sidecar-nostr-relay/.gitignore | 3 + examples/sidecar-nostr-relay/Dockerfile | 53 ++++ examples/sidecar-nostr-relay/Dockerfile.app | 49 +++ examples/sidecar-nostr-relay/README.md | 289 ++++++++++++++++++ .../docker-compose.external-net.yml | 6 + .../sidecar-nostr-relay/docker-compose.yml | 54 ++++ examples/sidecar-nostr-relay/entrypoint.sh | 86 ++++++ .../sidecar-nostr-relay/relay/config.toml | 49 +++ .../sidecar-nostr-relay/relay/strfry.conf | 71 +++++ examples/sidecar-nostr-relay/resolv.conf | 1 + examples/sidecar-nostr-relay/scripts/build.sh | 57 ++++ packaging/{openwrt => openwrt-ipk}/Makefile | 0 packaging/{openwrt => openwrt-ipk}/README.md | 0 .../{openwrt => openwrt-ipk}/build-ipk.sh | 0 .../files/etc/dnsmasq.d/fips.conf | 0 .../files/etc/fips/fips.yaml | 0 .../files/etc/fips/firewall.sh | 0 .../files/etc/hotplug.d/net/99-fips | 0 .../files/etc/init.d/fips | 0 .../files/etc/sysctl.d/fips-bridge.conf | 0 .../files/etc/uci-defaults/90-fips-setup | 0 .../files/lib/upgrade/keep.d/fips | 0 24 files changed, 731 insertions(+), 1 deletion(-) create mode 100644 examples/sidecar-nostr-relay/.env create mode 100644 examples/sidecar-nostr-relay/.gitignore create mode 100644 examples/sidecar-nostr-relay/Dockerfile create mode 100644 examples/sidecar-nostr-relay/Dockerfile.app create mode 100644 examples/sidecar-nostr-relay/README.md create mode 100644 examples/sidecar-nostr-relay/docker-compose.external-net.yml create mode 100644 examples/sidecar-nostr-relay/docker-compose.yml create mode 100755 examples/sidecar-nostr-relay/entrypoint.sh create mode 100644 examples/sidecar-nostr-relay/relay/config.toml create mode 100644 examples/sidecar-nostr-relay/relay/strfry.conf create mode 100644 examples/sidecar-nostr-relay/resolv.conf create mode 100755 examples/sidecar-nostr-relay/scripts/build.sh rename packaging/{openwrt => openwrt-ipk}/Makefile (100%) rename packaging/{openwrt => openwrt-ipk}/README.md (100%) rename packaging/{openwrt => openwrt-ipk}/build-ipk.sh (100%) rename packaging/{openwrt => openwrt-ipk}/files/etc/dnsmasq.d/fips.conf (100%) rename packaging/{openwrt => openwrt-ipk}/files/etc/fips/fips.yaml (100%) rename packaging/{openwrt => openwrt-ipk}/files/etc/fips/firewall.sh (100%) rename packaging/{openwrt => openwrt-ipk}/files/etc/hotplug.d/net/99-fips (100%) rename packaging/{openwrt => openwrt-ipk}/files/etc/init.d/fips (100%) rename packaging/{openwrt => openwrt-ipk}/files/etc/sysctl.d/fips-bridge.conf (100%) rename packaging/{openwrt => openwrt-ipk}/files/etc/uci-defaults/90-fips-setup (100%) rename packaging/{openwrt => openwrt-ipk}/files/lib/upgrade/keep.d/fips (100%) diff --git a/.github/workflows/package-openwrt.yml b/.github/workflows/package-openwrt.yml index 113c3a6..f7340b5 100644 --- a/.github/workflows/package-openwrt.yml +++ b/.github/workflows/package-openwrt.yml @@ -96,7 +96,7 @@ jobs: env: PKG_VERSION: ${{ steps.version.outputs.version }} LLVM_STRIP: llvm-strip - run: ./packaging/openwrt/build-ipk.sh --arch ${{ matrix.build_arch }} + run: ./packaging/openwrt-ipk/build-ipk.sh --arch ${{ matrix.build_arch }} - name: Upload artifact uses: actions/upload-artifact@v4 diff --git a/examples/sidecar-nostr-relay/.env b/examples/sidecar-nostr-relay/.env new file mode 100644 index 0000000..b3e3866 --- /dev/null +++ b/examples/sidecar-nostr-relay/.env @@ -0,0 +1,12 @@ +# FIPS sidecar default configuration. +# Override these values or create a .env.local file. + +# Node identity — generate with: fipsctl keygen +# Must be set before running: export FIPS_NSEC= +FIPS_NSEC= + +# Peer configuration (leave empty for standalone operation) +FIPS_PEER_NPUB=npub1qmc3cvfz0yu2hx96nq3gp55zdan2qclealn7xshgr448d3nh6lks7zel98 +FIPS_PEER_ADDR=217.77.8.91:2121 +FIPS_PEER_ALIAS=vps +FIPS_PEER_TRANSPORT=udp diff --git a/examples/sidecar-nostr-relay/.gitignore b/examples/sidecar-nostr-relay/.gitignore new file mode 100644 index 0000000..4d658a8 --- /dev/null +++ b/examples/sidecar-nostr-relay/.gitignore @@ -0,0 +1,3 @@ +fips +fipsctl +fipstop diff --git a/examples/sidecar-nostr-relay/Dockerfile b/examples/sidecar-nostr-relay/Dockerfile new file mode 100644 index 0000000..4c92975 --- /dev/null +++ b/examples/sidecar-nostr-relay/Dockerfile @@ -0,0 +1,53 @@ +FROM debian:trixie-slim + +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + ca-certificates \ + iproute2 iputils-ping dnsutils dnsmasq iptables \ + openssh-client openssh-server python3 \ + tcpdump netcat-openbsd curl iperf3 && \ + rm -rf /var/lib/apt/lists/* + +# Install nak (Nostr Army Knife) — detect arch and download the correct binary. +# Asset naming: nak--linux- +RUN ARCH=$(dpkg --print-architecture) && \ + case "$ARCH" in \ + amd64) NAK_ARCH="linux-amd64" ;; \ + arm64) NAK_ARCH="linux-arm64" ;; \ + armhf) NAK_ARCH="linux-arm" ;; \ + *) echo "Unsupported arch: $ARCH" && exit 1 ;; \ + esac && \ + NAK_VERSION=$(curl -sSL --retry 3 \ + "https://api.github.com/repos/fiatjaf/nak/releases/latest" \ + | grep '"tag_name"' | head -1 | sed 's/.*"tag_name": *"\(.*\)".*/\1/') && \ + echo "Installing nak ${NAK_VERSION} for ${NAK_ARCH}" && \ + curl -sSL --retry 3 \ + "https://github.com/fiatjaf/nak/releases/download/${NAK_VERSION}/nak-${NAK_VERSION}-${NAK_ARCH}" \ + -o /usr/local/bin/nak && \ + chmod +x /usr/local/bin/nak && \ + nak --version + +# Setup SSH server with no authentication (test only!) +RUN mkdir -p /var/run/sshd && \ + ssh-keygen -A && \ + sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config && \ + sed -i 's/#PermitEmptyPasswords no/PermitEmptyPasswords yes/' /etc/ssh/sshd_config && \ + sed -i 's/UsePAM yes/UsePAM no/' /etc/ssh/sshd_config && \ + passwd -d root + +# dnsmasq: forward .fips to FIPS daemon, everything else to Docker DNS +RUN printf '%s\n' \ + 'port=53' \ + 'listen-address=127.0.0.1' \ + 'bind-interfaces' \ + 'server=/fips/127.0.0.1#5354' \ + 'server=127.0.0.11' \ + 'no-resolv' \ + >> /etc/dnsmasq.conf + +COPY fips fipsctl fipstop /usr/local/bin/ +RUN chmod +x /usr/local/bin/fips /usr/local/bin/fipsctl /usr/local/bin/fipstop + +COPY entrypoint.sh /entrypoint.sh + +ENTRYPOINT ["/entrypoint.sh"] diff --git a/examples/sidecar-nostr-relay/Dockerfile.app b/examples/sidecar-nostr-relay/Dockerfile.app new file mode 100644 index 0000000..5f6348f --- /dev/null +++ b/examples/sidecar-nostr-relay/Dockerfile.app @@ -0,0 +1,49 @@ +# strfry: official multi-arch image (linux/amd64 + linux/arm64) +# replaces the nostr-rs-relay source build which was amd64-only. +# +# IMPORTANT: use alpine (same musl-based libc as the strfry source image) as +# the final stage. Copying the strfry binary into a glibc-based image such as +# debian:bookworm-slim causes "not found" at exec time because the musl dynamic +# linker (/lib/ld-musl-*.so.1) and its shared libraries are absent there. +FROM ghcr.io/hoytech/strfry:latest AS strfry + +FROM alpine:3.18 + +RUN apk add --no-cache nginx + +# nginx: reverse proxy port 80 (IPv4 + IPv6) → strfry 127.0.0.1:7777 +RUN printf 'server {\n\ + listen 80;\n\ + listen [::]:80;\n\ + location / {\n\ + proxy_pass http://127.0.0.1:7777;\n\ + proxy_http_version 1.1;\n\ + proxy_read_timeout 1d;\n\ + proxy_send_timeout 1d;\n\ + proxy_set_header Upgrade $http_upgrade;\n\ + proxy_set_header Connection "Upgrade";\n\ + proxy_set_header Host $host;\n\ + }\n\ +}\n' > /etc/nginx/http.d/nostr-relay.conf && \ + rm -f /etc/nginx/http.d/default.conf + +COPY --from=strfry /app/strfry /usr/local/bin/strfry +# Copy musl shared libraries that strfry depends on from the source image. +COPY --from=strfry \ + /usr/lib/liblmdb.so.0 \ + /usr/lib/libcrypto.so.50 \ + /usr/lib/libssl.so.53 \ + /usr/lib/libsecp256k1.so.2 \ + /usr/lib/libzstd.so.1 \ + /usr/lib/libstdc++.so.6 \ + /usr/lib/libgcc_s.so.1 \ + /usr/lib/ +COPY --from=strfry /lib/libz.so.1 /lib/ + +WORKDIR /usr/src/app +RUN mkdir -p strfry-db + +RUN printf '#!/bin/sh\nnginx\nexec strfry relay\n' > /entrypoint-app.sh && \ + chmod +x /entrypoint-app.sh + +ENTRYPOINT ["/entrypoint-app.sh"] diff --git a/examples/sidecar-nostr-relay/README.md b/examples/sidecar-nostr-relay/README.md new file mode 100644 index 0000000..967b7b3 --- /dev/null +++ b/examples/sidecar-nostr-relay/README.md @@ -0,0 +1,289 @@ +# FIPS Nostr Relay Sidecar + +Runs a [strfry](https://github.com/hoytech/strfry) Nostr relay reachable +exclusively over the FIPS mesh. The relay container shares the FIPS +sidecar's network namespace and is isolated from the host network by +iptables — it can only be reached via the node's `.fips` name. + +## How to Run + +### 1. Build the FIPS binaries + +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: + +```bash +fipsctl keygen +``` + +Then set it in `.env`: + +```bash +# .env +FIPS_NSEC=nsec1... # paste your nsec here +``` + +`FIPS_NSEC` is required — the container will refuse to start without it. + +### 3. Start the stack + +```bash +docker compose up -d +``` + +This starts two containers that share a network namespace: + +- **fips** — FIPS daemon + dnsmasq. Owns the namespace, creates `fips0`. +- **app** — strfry relay + nginx. Joins the namespace via `network_mode: service:fips`. + +### 4. Verify + +```bash +# FIPS node is up and has a mesh address: +docker exec sidecar-nostr-relay-fips-1 fipsctl show status + +# Relay is listening (should show nginx on :80 and strfry on :7777): +docker exec sidecar-nostr-relay-fips-1 ss -tlnp + +# Peer link to the public node is established: +docker exec sidecar-nostr-relay-fips-1 fipsctl show peers + +# Or check the logs: +docker compose logs -f +``` + +### 5. Connect to the relay + +Your node's npub (and therefore its `.fips` name) is derived from its keypair: + +```bash +docker exec sidecar-nostr-relay-fips-1 fipsctl show status +``` + +Connect from any FIPS-peered client using the node's npub: + +``` +ws://npub1xxxx.fips:80 +``` + +## Security Model + +The sidecar pattern enforces strict network isolation on the app container: + +- **No IPv4 access**: iptables blocks all eth0 traffic except FIPS UDP + transport (port 2121) and TCP transport (port 443). The app container + cannot reach the Docker bridge, the host network, or any IPv4 address. +- **No IPv6 on eth0**: ip6tables blocks all IPv6 traffic on eth0. The app + container cannot use link-local or any Docker-assigned IPv6 addresses. +- **FIPS mesh only**: The only routable network path is through `fips0` + (`fd::/8`). All application traffic traverses the FIPS mesh with + end-to-end encryption. +- **Loopback allowed**: `lo` is unrestricted for inter-process communication + within the shared namespace. + +This means the app container treats the FIPS mesh as its sole network. Even +if the application is compromised, it cannot bypass the mesh or communicate +with the transport layer directly. + +## Architecture + +```text +┌───────────────────────────────────────────────────┐ +│ Shared network namespace │ +│ │ +│ ┌───────────────┐ ┌──────────────────────────┐ │ +│ │ fips-sidecar │ │ fips-app │ │ +│ │ │ │ │ │ +│ │ fips daemon │ │ your workload │ │ +│ │ fipsctl │ │ │ │ +│ │ dnsmasq │ │ │ │ +│ └───────────────┘ └──────────────────────────┘ │ +│ │ +│ Interfaces: │ +│ lo — loopback (unrestricted) │ +│ eth0 — Docker bridge (iptables: FIPS only) │ +│ fips0 — FIPS TUN (fd::/8, unrestricted) │ +└───────────────────────────────────────────────────┘ +``` + +The FIPS sidecar owns the network namespace and creates the `fips0` TUN +interface. The app container joins via `network_mode: service:fips` and +sees the same interfaces. The entrypoint script applies iptables rules +before launching the FIPS daemon: + +**IPv4 rules** (iptables): + +- ACCEPT on `lo` (both directions) +- ACCEPT UDP sport/dport 2121 on `eth0` (FIPS UDP transport) +- ACCEPT TCP dport 443 / sport 443 on `eth0` (FIPS TCP transport) +- DROP everything else on `eth0` + +**IPv6 rules** (ip6tables): + +- ACCEPT on `lo` (both directions) +- ACCEPT on `fips0` (both directions) +- DROP everything on `eth0` + +### DNS Resolution + +DNS inside the container is handled by dnsmasq (127.0.0.1:53): + +- `.fips` queries are forwarded to the FIPS daemon's built-in DNS resolver + (127.0.0.1:5354), which resolves npub-based names to `fd::/8` addresses +- All other queries are forwarded to Docker's embedded DNS (127.0.0.11) + +The `resolv.conf` mount points the container's resolver at 127.0.0.1, +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 + +To connect the sidecar to an existing mesh, provide the peer's npub and +transport address: + +```bash +FIPS_PEER_NPUB=npub1... \ +FIPS_PEER_ADDR=203.0.113.10:2121 \ +FIPS_PEER_ALIAS=gateway \ +docker compose up -d +``` + +Verify the peer link: + +```bash +docker exec sidecar-nostr-relay-fips-1 fipsctl show peers +docker exec sidecar-nostr-relay-fips-1 fipsctl show links +``` + +## Verify Connectivity and Isolation + +From the app container: + +```bash +# Ping a mesh node by npub (resolves via .fips DNS): +docker exec sidecar-nostr-relay-app-1 ping6 -c3 npub1xxxx.fips + +# Fetch a web page from a mesh node over FIPS: +docker exec sidecar-nostr-relay-app-1 curl -6 "http://npub1xxxx.fips:8000/" + +# Docker bridge is blocked — this should fail: +docker exec sidecar-nostr-relay-app-1 ping -c1 -W2 172.20.0.13 + +# Loopback is allowed: +docker exec sidecar-nostr-relay-app-1 ping -c1 127.0.0.1 +``` + +## Environment Variables + +| Variable | Default | Description | +|---|---|---| +| `FIPS_NSEC` | *(required)* | Node secret key (hex or nsec1 bech32) | +| `FIPS_PEER_NPUB` | *(empty)* | Peer's npub to connect to | +| `FIPS_PEER_ADDR` | *(empty)* | Peer's transport address (e.g. `203.0.113.10:2121`) | +| `FIPS_PEER_ALIAS` | `peer` | Human-readable peer name | +| `FIPS_UDP_BIND` | `0.0.0.0:2121` | UDP transport bind address | +| `FIPS_TCP_BIND` | `0.0.0.0:8443` | TCP transport bind address | +| `FIPS_PEER_TRANSPORT` | `udp` | Peer transport type (`udp` or `tcp`) | +| `FIPS_TUN_MTU` | `1280` | TUN interface MTU | +| `FIPS_NETWORK` | `fips-sidecar-net` | Docker network name (set to join external network) | +| `FIPS_SUBNET` | `172.20.1.0/24` | Docker network subnet | +| `FIPS_IPV4` | `172.20.1.20` | Sidecar's IPv4 address on the Docker network | +| `RUST_LOG` | `info` | FIPS log level | + +## Troubleshooting + +**`FIPS_NSEC is required`** — The `FIPS_NSEC` environment variable is not +set. Either add it to `.env` or pass it on the command line. Generate a +random key with: `openssl rand -hex 32` + +**`fips0` interface not appearing** — The FIPS daemon needs `/dev/net/tun` +and `NET_ADMIN` capability. Check that the compose file includes both: + +```yaml +cap_add: + - NET_ADMIN +devices: + - /dev/net/tun:/dev/net/tun +``` + +**No peer connection established** — Verify the peer address is reachable +from the sidecar container (`docker exec sidecar-nostr-relay-fips-1 ping -c1 `). +If joining an external Docker network, ensure `FIPS_NETWORK`, `FIPS_SUBNET`, +and `FIPS_IPV4` match the target network. Check logs with +`docker logs sidecar-nostr-relay-fips-1`. + +**DNS not resolving `.fips` names** — Verify dnsmasq is running: +`docker exec sidecar-nostr-relay-fips-1 pgrep dnsmasq`. Check that `resolv.conf` is +mounted (should contain `nameserver 127.0.0.1`). Verify the FIPS DNS +resolver is listening: `docker exec sidecar-nostr-relay-fips-1 dig @127.0.0.1 -p 5354 .fips AAAA`. + +**iptables errors in entrypoint** — The sidecar container requires +`NET_ADMIN` capability for iptables. Without it, the isolation rules +cannot be applied and the entrypoint will fail. + +## Production Considerations + +**Secrets management**: The default `.env` contains a hardcoded nsec for +development. In production, use Docker secrets, a vault, or inject the key +via a secure CI/CD pipeline. Never commit production keys to version control. + +**Logging**: Set `RUST_LOG` to control log verbosity (`debug`, `info`, +`warn`, `error`). For production, configure the Docker logging driver with +size limits: + +```yaml +logging: + driver: json-file + options: + max-size: "10m" + max-file: "3" +``` + +**Resource limits**: Add memory and CPU constraints in the compose file: + +```yaml +deploy: + resources: + limits: + memory: 256M + cpus: "0.5" +``` + +**Multiple peers**: The entrypoint supports a single peer via environment +variables. For multiple peers, mount a custom `fips.yaml` directly: + +```yaml +volumes: + - ./my-fips.yaml:/etc/fips/fips.yaml:ro +``` + +**Health checks**: Add a Docker health check using `fipsctl`: + +```yaml +healthcheck: + test: ["CMD", "fipsctl", "show", "status"] + interval: 30s + timeout: 5s + retries: 3 +``` diff --git a/examples/sidecar-nostr-relay/docker-compose.external-net.yml b/examples/sidecar-nostr-relay/docker-compose.external-net.yml new file mode 100644 index 0000000..c88c522 --- /dev/null +++ b/examples/sidecar-nostr-relay/docker-compose.external-net.yml @@ -0,0 +1,6 @@ +# Override: use a pre-existing external network instead of creating one. +# Used by test-sidecar.sh for multi-instance testing on a shared network. +networks: + fips-net: + external: true + name: ${FIPS_NETWORK:-fips-sidecar-net} diff --git a/examples/sidecar-nostr-relay/docker-compose.yml b/examples/sidecar-nostr-relay/docker-compose.yml new file mode 100644 index 0000000..c7d287d --- /dev/null +++ b/examples/sidecar-nostr-relay/docker-compose.yml @@ -0,0 +1,54 @@ +networks: + fips-net: + name: ${FIPS_NETWORK:-fips-sidecar-net} + driver: bridge + ipam: + config: + - subnet: ${FIPS_SUBNET:-172.20.1.0/24} + +services: + fips: + build: + context: . + hostname: fips-sidecar + cap_add: + - NET_ADMIN + devices: + - /dev/net/tun:/dev/net/tun + sysctls: + - net.ipv6.conf.all.disable_ipv6=0 + restart: "no" + ports: + - "2121:2121/udp" # FIPS UDP transport + - "8443:8443/tcp" # FIPS TCP transport + - "80:80/tcp" # Nostr relay WebSocket (via nginx) + environment: + - RUST_LOG=${RUST_LOG:-info} + - FIPS_NSEC=${FIPS_NSEC} + - FIPS_PEER_NPUB=${FIPS_PEER_NPUB:-} + - FIPS_PEER_ADDR=${FIPS_PEER_ADDR:-} + - FIPS_PEER_ALIAS=${FIPS_PEER_ALIAS:-peer} + - FIPS_UDP_BIND=${FIPS_UDP_BIND:-0.0.0.0:2121} + - FIPS_TUN_MTU=${FIPS_TUN_MTU:-1280} + - FIPS_PEER_TRANSPORT=${FIPS_PEER_TRANSPORT:-udp} + volumes: + - ./resolv.conf:/etc/resolv.conf:ro + networks: + fips-net: + ipv4_address: ${FIPS_IPV4:-172.20.1.20} + + app: + build: + context: . + dockerfile: Dockerfile.app + network_mode: "service:fips" + restart: unless-stopped + depends_on: + - fips + volumes: + - relay-data:/usr/src/app/strfry-db + - ./relay/strfry.conf:/usr/src/app/strfry.conf:ro + - ./resolv.conf:/etc/resolv.conf:ro + +volumes: + relay-data: diff --git a/examples/sidecar-nostr-relay/entrypoint.sh b/examples/sidecar-nostr-relay/entrypoint.sh new file mode 100755 index 0000000..06b826d --- /dev/null +++ b/examples/sidecar-nostr-relay/entrypoint.sh @@ -0,0 +1,86 @@ +#!/bin/bash +# FIPS sidecar entrypoint: generate config, apply iptables isolation, launch FIPS. +set -e + +# --- Generate FIPS config from environment variables --- + +FIPS_NSEC="${FIPS_NSEC:?FIPS_NSEC is required}" +FIPS_UDP_BIND="${FIPS_UDP_BIND:-0.0.0.0:2121}" +FIPS_TCP_BIND="${FIPS_TCP_BIND:-0.0.0.0:8443}" +FIPS_TUN_MTU="${FIPS_TUN_MTU:-1280}" +FIPS_PEER_TRANSPORT="${FIPS_PEER_TRANSPORT:-udp}" + +mkdir -p /etc/fips + +# Build peers section +PEERS_SECTION="" +if [ -n "$FIPS_PEER_NPUB" ] && [ -n "$FIPS_PEER_ADDR" ]; then + FIPS_PEER_ALIAS="${FIPS_PEER_ALIAS:-peer}" + PEERS_SECTION=" - npub: \"${FIPS_PEER_NPUB}\" + alias: \"${FIPS_PEER_ALIAS}\" + addresses: + - transport: ${FIPS_PEER_TRANSPORT} + addr: \"${FIPS_PEER_ADDR}\" + connect_policy: auto_connect" +fi + +cat > /etc/fips/fips.yaml <]:8080 after first start +name = "FIPS Nostr Relay" +description = "A Nostr relay accessible over the FIPS mesh network." +pubkey = "" # Optional: your npub (hex) as relay operator +contact = "" # Optional: contact address + +[database] +# SQLite database path inside the container (mapped to relay-data volume). +data_directory = "/usr/src/app/db" + +[network] +# Bind on all interfaces (IPv4 + IPv6) — FIPS delivers traffic via the fips0 +# TUN as IPv6 (fd00::/8). Using 0.0.0.0 with port 8080; the relay also needs +# to accept IPv6 connections so we set port separately and rely on the OS +# dual-stack socket (IPV6_V6ONLY=0). +# nostr-rs-relay address field is just the IP, port is separate. +address = "0.0.0.0" +port = 8080 +ping_interval_seconds = 300 + +[limits] +# Adjust to taste. These are conservative defaults for a personal relay. +messages_per_sec = 10 +subscriptions_per_min = 20 +max_blocking_threads = 4 +max_event_bytes = 131072 # 128 KiB per event +max_ws_message_bytes = 131072 +max_ws_frame_bytes = 131072 +broadcast_buffer = 16384 +event_persist_buffer = 4096 + +[authorization] +# Set to true to require NIP-42 AUTH before accepting events. +# Useful for a private relay — only authenticated users can publish. +nip42_auth = false +nip42_dms = false + +[verified_users] +# NIP-05 verification (optional). +mode = "disabled" + +[pay_to_relay] +# Lightning payments for relay access (optional). +enabled = false \ No newline at end of file diff --git a/examples/sidecar-nostr-relay/relay/strfry.conf b/examples/sidecar-nostr-relay/relay/strfry.conf new file mode 100644 index 0000000..5f4c333 --- /dev/null +++ b/examples/sidecar-nostr-relay/relay/strfry.conf @@ -0,0 +1,71 @@ +## +## strfry configuration for FIPS mesh deployment. +## Full reference: https://github.com/hoytech/strfry +## + +db = "/usr/src/app/strfry-db/" + +dbParams { + # Maximum size of the database (bytes). 10 GiB is a safe default. + mapsize = 10737418240 +} + +relay { + # Bind on all interfaces so the FIPS TUN (IPv4 + IPv6) can reach it. + bind = "0.0.0.0" + port = 7777 + + nofiles = 0 + + info { + name = "FIPS Nostr Relay" + description = "A Nostr relay accessible over the FIPS mesh network." + pubkey = "" + contact = "" + } + + # Maximum size of an inbound WebSocket message (bytes). + maxWebsocketPayloadSize = 131072 + + # Send a ping every N seconds to keep connections alive. + autoPingSeconds = 55 + + # Enable per-message compression. + enableTcpNoDelay = false + + rejectFutureEventsSeconds = 900 + rejectEphemeralEventsOlderThanSeconds = 60 + rejectEventsNewerThanSeconds = 900 + + maxFilterLimit = 500 + maxSubsPerConnection = 20 + + writePolicy { + # Plugin executable for write-policy decisions (leave empty to allow all). + plugin = "" + } + + compression { + enabled = true + slidingWindow = true + } + + logging { + dumpInAll = false + dumpInEvents = false + dumpInReqs = false + dbScanPerf = false + } + + numThreads { + ingester = 3 + reqWorker = 3 + reqMonitor = 3 + negentropy = 2 + } + + negentropy { + enabled = true + maxSyncEvents = 1000000 + } +} diff --git a/examples/sidecar-nostr-relay/resolv.conf b/examples/sidecar-nostr-relay/resolv.conf new file mode 100644 index 0000000..bbc8559 --- /dev/null +++ b/examples/sidecar-nostr-relay/resolv.conf @@ -0,0 +1 @@ +nameserver 127.0.0.1 diff --git a/examples/sidecar-nostr-relay/scripts/build.sh b/examples/sidecar-nostr-relay/scripts/build.sh new file mode 100755 index 0000000..f45998e --- /dev/null +++ b/examples/sidecar-nostr-relay/scripts/build.sh @@ -0,0 +1,57 @@ +#!/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: /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" diff --git a/packaging/openwrt/Makefile b/packaging/openwrt-ipk/Makefile similarity index 100% rename from packaging/openwrt/Makefile rename to packaging/openwrt-ipk/Makefile diff --git a/packaging/openwrt/README.md b/packaging/openwrt-ipk/README.md similarity index 100% rename from packaging/openwrt/README.md rename to packaging/openwrt-ipk/README.md diff --git a/packaging/openwrt/build-ipk.sh b/packaging/openwrt-ipk/build-ipk.sh similarity index 100% rename from packaging/openwrt/build-ipk.sh rename to packaging/openwrt-ipk/build-ipk.sh diff --git a/packaging/openwrt/files/etc/dnsmasq.d/fips.conf b/packaging/openwrt-ipk/files/etc/dnsmasq.d/fips.conf similarity index 100% rename from packaging/openwrt/files/etc/dnsmasq.d/fips.conf rename to packaging/openwrt-ipk/files/etc/dnsmasq.d/fips.conf diff --git a/packaging/openwrt/files/etc/fips/fips.yaml b/packaging/openwrt-ipk/files/etc/fips/fips.yaml similarity index 100% rename from packaging/openwrt/files/etc/fips/fips.yaml rename to packaging/openwrt-ipk/files/etc/fips/fips.yaml diff --git a/packaging/openwrt/files/etc/fips/firewall.sh b/packaging/openwrt-ipk/files/etc/fips/firewall.sh similarity index 100% rename from packaging/openwrt/files/etc/fips/firewall.sh rename to packaging/openwrt-ipk/files/etc/fips/firewall.sh diff --git a/packaging/openwrt/files/etc/hotplug.d/net/99-fips b/packaging/openwrt-ipk/files/etc/hotplug.d/net/99-fips similarity index 100% rename from packaging/openwrt/files/etc/hotplug.d/net/99-fips rename to packaging/openwrt-ipk/files/etc/hotplug.d/net/99-fips diff --git a/packaging/openwrt/files/etc/init.d/fips b/packaging/openwrt-ipk/files/etc/init.d/fips similarity index 100% rename from packaging/openwrt/files/etc/init.d/fips rename to packaging/openwrt-ipk/files/etc/init.d/fips diff --git a/packaging/openwrt/files/etc/sysctl.d/fips-bridge.conf b/packaging/openwrt-ipk/files/etc/sysctl.d/fips-bridge.conf similarity index 100% rename from packaging/openwrt/files/etc/sysctl.d/fips-bridge.conf rename to packaging/openwrt-ipk/files/etc/sysctl.d/fips-bridge.conf diff --git a/packaging/openwrt/files/etc/uci-defaults/90-fips-setup b/packaging/openwrt-ipk/files/etc/uci-defaults/90-fips-setup similarity index 100% rename from packaging/openwrt/files/etc/uci-defaults/90-fips-setup rename to packaging/openwrt-ipk/files/etc/uci-defaults/90-fips-setup diff --git a/packaging/openwrt/files/lib/upgrade/keep.d/fips b/packaging/openwrt-ipk/files/lib/upgrade/keep.d/fips similarity index 100% rename from packaging/openwrt/files/lib/upgrade/keep.d/fips rename to packaging/openwrt-ipk/files/lib/upgrade/keep.d/fips