mirror of
https://github.com/jmcorgan/fips.git
synced 2026-07-22 07:48:26 +00:00
Add OpenWrt .ipk packaging with CI workflow
Adds packaging/openwrt/ with everything needed to produce and distribute FIPS .ipk packages for OpenWrt routers: - Makefile: OpenWrt feed package definition using rust/host toolchain, maps OpenWrt ARCH to Rust musl target triples - build-ipk.sh: local build script using cargo-zigbuild + direct tar assembly — no OpenWrt SDK or Docker required. Handles macOS BSD tar (ustar format, resource fork suppression) and portable ar header generation for cross-platform .ipk creation. Accepts PKG_VERSION env var override for CI use. - files/: procd init script, default fips.yaml (persistent identity, br-lan and wwan interface examples), firewall helper, dnsmasq .fips forwarding, br_netfilter sysctl, hotplug for fips0, UCI defaults for first-boot setup, sysupgrade keeplist - .github/workflows/package-openwrt.yml: CI workflow (ubuntu-latest + cargo-zigbuild) building aarch64 and x86_64 .ipk packages using build-ipk.sh; llvm-strip for cross-compiled binaries; triggers on every push; publishes to GitHub Releases on version tags. MIPS targets disabled pending portable-atomic crate (32-bit MIPS lacks native AtomicU64), with nightly/rust-src toolchain steps prepared for re-enablement. - .gitignore: add reference/, dist/, *.ipk
This commit is contained in:
committed by
Johnathan Corgan
parent
6ab8b35755
commit
46ccd9744e
127
.github/workflows/package-openwrt.yml
vendored
Normal file
127
.github/workflows/package-openwrt.yml
vendored
Normal file
@@ -0,0 +1,127 @@
|
||||
name: OpenWrt Package
|
||||
|
||||
on:
|
||||
push:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
arch:
|
||||
description: "Target architecture (leave empty to build all)"
|
||||
required: false
|
||||
default: ""
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build .ipk (${{ matrix.openwrt_arch }})
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- build_arch: aarch64
|
||||
openwrt_arch: aarch64_cortex-a53
|
||||
rust_target: aarch64-unknown-linux-musl
|
||||
rust_channel: stable
|
||||
# MT3000, MT6000, Flint 2, RPi 3/4/5
|
||||
# MIPS disabled: 32-bit MIPS lacks AtomicU64; needs portable-atomic crate
|
||||
# - build_arch: mipsel
|
||||
# openwrt_arch: mipsel_24kc
|
||||
# rust_target: mipsel-unknown-linux-musl
|
||||
# rust_channel: nightly
|
||||
# - build_arch: mips
|
||||
# openwrt_arch: mips_24kc
|
||||
# rust_target: mips-unknown-linux-musl
|
||||
# rust_channel: nightly
|
||||
- build_arch: x86_64
|
||||
openwrt_arch: x86_64
|
||||
rust_target: x86_64-unknown-linux-musl
|
||||
rust_channel: stable
|
||||
# x86 routers / VMs
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Derive package version
|
||||
id: version
|
||||
run: |
|
||||
if [[ "$GITHUB_REF" == refs/tags/* ]]; then
|
||||
VERSION="${GITHUB_REF_NAME#v}"
|
||||
else
|
||||
BRANCH=$(echo "$GITHUB_REF_NAME" | sed 's|/|-|g')
|
||||
HEIGHT=$(git rev-list --count HEAD)
|
||||
HASH=$(git rev-parse --short HEAD)
|
||||
VERSION="${BRANCH}.${HEIGHT}.${HASH}"
|
||||
fi
|
||||
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
|
||||
echo "filename=fips_${VERSION}_${{ matrix.openwrt_arch }}.ipk" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Install Rust toolchain (stable)
|
||||
if: matrix.rust_channel == 'stable'
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
targets: ${{ matrix.rust_target }}
|
||||
|
||||
- name: Install Rust toolchain (nightly, Tier 3)
|
||||
if: matrix.rust_channel == 'nightly'
|
||||
uses: dtolnay/rust-toolchain@nightly
|
||||
with:
|
||||
components: rust-src
|
||||
|
||||
- name: Cache Cargo registry + build
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.cargo/registry
|
||||
~/.cargo/git
|
||||
target/${{ matrix.rust_target }}
|
||||
key: openwrt-${{ matrix.rust_target }}-${{ hashFiles('**/Cargo.lock') }}
|
||||
restore-keys: |
|
||||
openwrt-${{ matrix.rust_target }}-
|
||||
|
||||
- name: Install cargo-zigbuild
|
||||
run: cargo install cargo-zigbuild --locked
|
||||
|
||||
- name: Install zig (required by cargo-zigbuild)
|
||||
uses: goto-bus-stop/setup-zig@v2
|
||||
|
||||
- name: Install llvm-strip
|
||||
run: sudo apt-get install -y --no-install-recommends llvm
|
||||
|
||||
- name: Build .ipk
|
||||
env:
|
||||
PKG_VERSION: ${{ steps.version.outputs.version }}
|
||||
LLVM_STRIP: llvm-strip
|
||||
run: ./packaging/openwrt/build-ipk.sh --arch ${{ matrix.build_arch }}
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ steps.version.outputs.filename }}
|
||||
path: dist/${{ steps.version.outputs.filename }}
|
||||
retention-days: 30
|
||||
|
||||
release:
|
||||
name: Publish GitHub Release
|
||||
runs-on: ubuntu-latest
|
||||
needs: build
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
steps:
|
||||
- name: Download all .ipk artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: dist
|
||||
merge-multiple: true
|
||||
|
||||
- name: Create release
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
files: dist/*.ipk
|
||||
generate_release_notes: true
|
||||
7
.gitignore
vendored
7
.gitignore
vendored
@@ -15,4 +15,9 @@
|
||||
.claude/
|
||||
|
||||
deploy/
|
||||
vps.env
|
||||
vps.env
|
||||
|
||||
reference/
|
||||
|
||||
dist/
|
||||
*.ipk
|
||||
127
packaging/openwrt/Makefile
Normal file
127
packaging/openwrt/Makefile
Normal file
@@ -0,0 +1,127 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=fips
|
||||
PKG_VERSION:=0.1.0
|
||||
PKG_RELEASE:=1
|
||||
|
||||
# Pin to a specific commit for reproducible builds.
|
||||
# Update PKG_SOURCE_VERSION and PKG_MIRROR_HASH when upgrading.
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_URL:=https://github.com/fips-network/fips.git
|
||||
PKG_SOURCE_VERSION:=master
|
||||
PKG_MIRROR_HASH:=skip
|
||||
|
||||
PKG_MAINTAINER:=FIPS Network
|
||||
PKG_LICENSE:=MIT
|
||||
PKG_LICENSE_FILES:=LICENSE
|
||||
|
||||
# Rust host toolchain must be present in the build system.
|
||||
# In the OpenWrt build system, enable via: make menuconfig → Advanced → Rust
|
||||
PKG_BUILD_DEPENDS:=rust/host
|
||||
PKG_BUILD_PARALLEL:=1
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Map OpenWrt ARCH to Rust target triple.
|
||||
# All OpenWrt targets use musl libc.
|
||||
# ---------------------------------------------------------------------------
|
||||
ifeq ($(ARCH),aarch64)
|
||||
RUST_TARGET:=aarch64-unknown-linux-musl
|
||||
else ifeq ($(ARCH),x86_64)
|
||||
RUST_TARGET:=x86_64-unknown-linux-musl
|
||||
else ifeq ($(ARCH),mipsel)
|
||||
RUST_TARGET:=mipsel-unknown-linux-musl
|
||||
else ifeq ($(ARCH),mips)
|
||||
RUST_TARGET:=mips-unknown-linux-musl
|
||||
else ifeq ($(ARCH),arm)
|
||||
# OpenWrt ARM targets predominantly use hardfloat ABI.
|
||||
# Override RUST_TARGET in your build if your target uses softfloat.
|
||||
RUST_TARGET:=arm-unknown-linux-musleabihf
|
||||
else
|
||||
$(error Unsupported architecture: $(ARCH). Add a RUST_TARGET mapping in packaging/openwrt/Makefile.)
|
||||
endif
|
||||
|
||||
RUST_RELEASE_DIR:=$(PKG_BUILD_DIR)/target/$(RUST_TARGET)/release
|
||||
|
||||
define Package/fips
|
||||
SECTION:=net
|
||||
CATEGORY:=Network
|
||||
TITLE:=FIPS Mesh Network Daemon
|
||||
URL:=https://github.com/fips-network/fips
|
||||
DEPENDS:=+kmod-tun +kmod-br-netfilter
|
||||
endef
|
||||
|
||||
define Package/fips/description
|
||||
FIPS is a distributed, decentralized mesh networking daemon. It routes
|
||||
traffic across nodes connected over UDP, TCP, or raw Ethernet (EtherType
|
||||
0x2121). Provides a TUN interface (fips0) with ULA IPv6 mesh addressing
|
||||
and a local DNS responder for .fips name resolution.
|
||||
|
||||
Three binaries are installed:
|
||||
fips — mesh daemon
|
||||
fipsctl — CLI control and inspection tool
|
||||
fipstop — live TUI dashboard (requires a terminal)
|
||||
endef
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Build
|
||||
#
|
||||
# We write a temporary .cargo/config.toml to set the cross-linker without
|
||||
# polluting the source tree. CARGO_HOME is scoped to the staging directory
|
||||
# to avoid touching the developer's ~/.cargo during SDK builds.
|
||||
# ---------------------------------------------------------------------------
|
||||
define Build/Compile
|
||||
mkdir -p $(PKG_BUILD_DIR)/.cargo
|
||||
printf '[target.$(RUST_TARGET)]\nlinker = "$(TARGET_CC)"\n' \
|
||||
> $(PKG_BUILD_DIR)/.cargo/config.toml
|
||||
cd $(PKG_BUILD_DIR) && \
|
||||
CARGO_HOME=$(STAGING_DIR_HOST)/share/cargo \
|
||||
cargo build \
|
||||
--release \
|
||||
--target $(RUST_TARGET) \
|
||||
--bin fips \
|
||||
--bin fipsctl \
|
||||
--bin fipstop
|
||||
endef
|
||||
|
||||
define Package/fips/install
|
||||
# Binaries
|
||||
$(INSTALL_DIR) $(1)/usr/bin
|
||||
$(INSTALL_BIN) $(RUST_RELEASE_DIR)/fips $(1)/usr/bin/fips
|
||||
$(INSTALL_BIN) $(RUST_RELEASE_DIR)/fipsctl $(1)/usr/bin/fipsctl
|
||||
$(INSTALL_BIN) $(RUST_RELEASE_DIR)/fipstop $(1)/usr/bin/fipstop
|
||||
|
||||
# procd init script
|
||||
$(INSTALL_DIR) $(1)/etc/init.d
|
||||
$(INSTALL_BIN) $(CURDIR)/files/etc/init.d/fips $(1)/etc/init.d/fips
|
||||
|
||||
# Default config — installed as CONF so opkg will not overwrite it on upgrade
|
||||
$(INSTALL_DIR) $(1)/etc/fips
|
||||
$(INSTALL_CONF) $(CURDIR)/files/etc/fips/fips.yaml $(1)/etc/fips/fips.yaml
|
||||
|
||||
# Firewall helper script (called by UCI include and hotplug)
|
||||
$(INSTALL_BIN) $(CURDIR)/files/etc/fips/firewall.sh $(1)/etc/fips/firewall.sh
|
||||
|
||||
# dnsmasq drop-in: forward .fips queries to the FIPS DNS responder
|
||||
$(INSTALL_DIR) $(1)/etc/dnsmasq.d
|
||||
$(INSTALL_DATA) $(CURDIR)/files/etc/dnsmasq.d/fips.conf $(1)/etc/dnsmasq.d/fips.conf
|
||||
|
||||
# sysctl: enable br_netfilter so AF_PACKET sees frames on bridge member ports
|
||||
$(INSTALL_DIR) $(1)/etc/sysctl.d
|
||||
$(INSTALL_DATA) $(CURDIR)/files/etc/sysctl.d/fips-bridge.conf $(1)/etc/sysctl.d/fips-bridge.conf
|
||||
|
||||
# Hotplug: apply firewall rules when the FIPS TUN interface comes up
|
||||
$(INSTALL_DIR) $(1)/etc/hotplug.d/net
|
||||
$(INSTALL_BIN) $(CURDIR)/files/etc/hotplug.d/net/99-fips $(1)/etc/hotplug.d/net/99-fips
|
||||
|
||||
# UCI defaults: one-time first-boot firewall and module setup
|
||||
$(INSTALL_DIR) $(1)/etc/uci-defaults
|
||||
$(INSTALL_BIN) $(CURDIR)/files/etc/uci-defaults/90-fips-setup $(1)/etc/uci-defaults/90-fips-setup
|
||||
|
||||
# sysupgrade: preserve /etc/fips/ (config + identity key) across firmware upgrades
|
||||
$(INSTALL_DIR) $(1)/lib/upgrade/keep.d
|
||||
$(INSTALL_DATA) $(CURDIR)/files/lib/upgrade/keep.d/fips $(1)/lib/upgrade/keep.d/fips
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,fips))
|
||||
174
packaging/openwrt/README.md
Normal file
174
packaging/openwrt/README.md
Normal file
@@ -0,0 +1,174 @@
|
||||
# FIPS OpenWrt Package
|
||||
|
||||
This directory is an OpenWrt feed package that builds and installs FIPS on any
|
||||
OpenWrt 22.03+ router via the standard `opkg` package system.
|
||||
|
||||
For ad-hoc deployment without the build system, see
|
||||
[`deploy/native/`](../../deploy/native/README.md) instead.
|
||||
|
||||
## Package contents
|
||||
|
||||
| Installed path | Purpose |
|
||||
|---|---|
|
||||
| `/usr/bin/fips` | Mesh daemon |
|
||||
| `/usr/bin/fipsctl` | CLI control tool (`fipsctl peers`, `fipsctl links`, …) |
|
||||
| `/usr/bin/fipstop` | Live TUI dashboard |
|
||||
| `/etc/init.d/fips` | procd service (auto-start, crash respawn) |
|
||||
| `/etc/fips/fips.yaml` | Node configuration (edit before first start) |
|
||||
| `/etc/fips/firewall.sh` | Firewall helper — accepts traffic on `fips0` |
|
||||
| `/etc/dnsmasq.d/fips.conf` | Forwards `.fips` DNS queries to the daemon |
|
||||
| `/etc/sysctl.d/fips-bridge.conf` | `br_netfilter` settings for Ethernet transport |
|
||||
| `/etc/hotplug.d/net/99-fips` | Applies firewall rules when `fips0` comes up |
|
||||
| `/etc/uci-defaults/90-fips-setup` | First-boot kernel module and firewall setup |
|
||||
| `/lib/upgrade/keep.d/fips` | Preserves `/etc/fips/` across `sysupgrade` |
|
||||
|
||||
## Requirements
|
||||
|
||||
### Build host
|
||||
|
||||
| Requirement | Notes |
|
||||
|---|---|
|
||||
| OpenWrt SDK 22.03+ | Older versions lack fw4 / nftables support |
|
||||
| Rust host toolchain | Enable in `make menuconfig` → Advanced → Rust, or install rustup |
|
||||
| Rust target for your router | Added automatically by the Makefile via `rustup target add` |
|
||||
|
||||
### Router
|
||||
|
||||
| Requirement | Notes |
|
||||
|---|---|
|
||||
| `kmod-tun` | Required for `fips0` TUN interface |
|
||||
| `kmod-br-netfilter` | Required for Ethernet transport on bridge member ports |
|
||||
|
||||
Both kernel modules are listed as package dependencies (`DEPENDS`) and will be
|
||||
installed automatically by `opkg`.
|
||||
|
||||
## Target architectures
|
||||
|
||||
The Makefile maps the OpenWrt `ARCH` variable to the correct Rust musl target:
|
||||
|
||||
| OpenWrt `ARCH` | Rust target |
|
||||
|---|---|
|
||||
| `aarch64` | `aarch64-unknown-linux-musl` |
|
||||
| `x86_64` | `x86_64-unknown-linux-musl` |
|
||||
| `mipsel` | `mipsel-unknown-linux-musl` |
|
||||
| `mips` | `mips-unknown-linux-musl` |
|
||||
| `arm` | `arm-unknown-linux-musleabihf` |
|
||||
|
||||
To add a missing architecture, add an `ifeq` block in `Makefile` mapping the
|
||||
OpenWrt `ARCH` value to the Rust target triple.
|
||||
|
||||
## Building with the OpenWrt SDK
|
||||
|
||||
### 1. Obtain the SDK
|
||||
|
||||
Download the SDK for your router's target from
|
||||
[downloads.openwrt.org](https://downloads.openwrt.org) and extract it.
|
||||
|
||||
### 2. Add this package
|
||||
|
||||
Copy or symlink this directory into the SDK's `package/` tree:
|
||||
|
||||
```bash
|
||||
# From inside the SDK root:
|
||||
ln -s /path/to/fips/packaging/openwrt package/fips
|
||||
```
|
||||
|
||||
Or add the FIPS repository as a feed in `feeds.conf`:
|
||||
|
||||
```
|
||||
src-git-full fips https://github.com/fips-network/fips.git
|
||||
```
|
||||
|
||||
Then update and install feeds:
|
||||
|
||||
```bash
|
||||
./scripts/feeds update fips
|
||||
./scripts/feeds install -a -p fips
|
||||
```
|
||||
|
||||
### 3. Build
|
||||
|
||||
```bash
|
||||
make package/fips/compile V=s
|
||||
```
|
||||
|
||||
The resulting `.ipk` is placed in `bin/packages/<arch>/`.
|
||||
|
||||
### 4. Pin the source version
|
||||
|
||||
For reproducible production builds, replace `PKG_SOURCE_VERSION:=master` in
|
||||
`Makefile` with a specific commit SHA and set `PKG_MIRROR_HASH` to the correct
|
||||
hash (or keep `skip` for development):
|
||||
|
||||
```makefile
|
||||
PKG_SOURCE_VERSION:=bf117dfabc123... # full 40-char SHA
|
||||
PKG_MIRROR_HASH:=skip
|
||||
```
|
||||
|
||||
## Installing on the router
|
||||
|
||||
```bash
|
||||
scp bin/packages/<arch>/fips_0.1.0-1_<arch>.ipk root@192.168.1.1:/tmp/
|
||||
ssh root@192.168.1.1 opkg install /tmp/fips_0.1.0-1_<arch>.ipk
|
||||
```
|
||||
|
||||
## First-time configuration
|
||||
|
||||
Edit `/etc/fips/fips.yaml` on the router before starting the daemon:
|
||||
|
||||
```bash
|
||||
ssh root@192.168.1.1
|
||||
vi /etc/fips/fips.yaml
|
||||
```
|
||||
|
||||
The default config enables:
|
||||
- Persistent identity (key generated on first start, saved to `/etc/fips/fips.key`)
|
||||
- TUN interface `fips0`
|
||||
- DNS responder on `127.0.0.1:5354`
|
||||
- UDP transport on `0.0.0.0:2121`
|
||||
|
||||
For Ethernet transport, uncomment the `ethernet:` section and set the correct
|
||||
physical interface names for your router. **Always use physical port names
|
||||
(`eth0`, `eth1`), never bridge names (`br-lan`).** See
|
||||
[`deploy/native/README.md`](../../deploy/native/README.md) for details.
|
||||
|
||||
## Service management
|
||||
|
||||
```bash
|
||||
/etc/init.d/fips start
|
||||
/etc/init.d/fips stop
|
||||
/etc/init.d/fips restart
|
||||
/etc/init.d/fips enable # start at boot (already enabled by opkg postinstall)
|
||||
/etc/init.d/fips disable
|
||||
```
|
||||
|
||||
## Inspection and logs
|
||||
|
||||
```bash
|
||||
# Peer table
|
||||
fipsctl peers
|
||||
|
||||
# Active sessions
|
||||
fipsctl sessions
|
||||
|
||||
# Transport links
|
||||
fipsctl links
|
||||
|
||||
# Live TUI dashboard
|
||||
fipstop
|
||||
|
||||
# Daemon logs (OpenWrt syslog)
|
||||
logread | grep fips
|
||||
```
|
||||
|
||||
## Upgrading
|
||||
|
||||
Install the new `.ipk` over the existing one:
|
||||
|
||||
```bash
|
||||
opkg install --force-reinstall fips_<new-version>_<arch>.ipk
|
||||
```
|
||||
|
||||
The config in `/etc/fips/fips.yaml` and the identity key `/etc/fips/fips.key`
|
||||
are preserved by `opkg` (the yaml is installed as a conffile; the key is not a
|
||||
package file). Both survive `sysupgrade` via `/lib/upgrade/keep.d/fips`.
|
||||
265
packaging/openwrt/build-ipk.sh
Executable file
265
packaging/openwrt/build-ipk.sh
Executable file
@@ -0,0 +1,265 @@
|
||||
#!/bin/bash
|
||||
# Build a FIPS .ipk package for OpenWrt without the OpenWrt SDK.
|
||||
#
|
||||
# Uses cargo-zigbuild for cross-compilation and assembles the .ipk directly.
|
||||
# An .ipk is just an ar archive containing two tarballs — no SDK required.
|
||||
#
|
||||
# Usage:
|
||||
# ./packaging/openwrt/build-ipk.sh [--arch <name>]
|
||||
#
|
||||
# Architectures (--arch):
|
||||
# aarch64 GL.iNet MT3000/MT6000, RPi 3/4/5, most modern routers [default]
|
||||
# mipsel Older MIPS routers (TP-Link, Netgear, GL.iNet AR750)
|
||||
# mips MIPS big-endian routers (ath79)
|
||||
# arm 32-bit ARM routers (Cortex-A7)
|
||||
# x86_64 x86 routers / VMs
|
||||
#
|
||||
# Output: dist/fips_<version>_<openwrt-arch>.ipk
|
||||
#
|
||||
# Prerequisites:
|
||||
# cargo install cargo-zigbuild
|
||||
# rustup target add <rust-triple> (added automatically if missing)
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Arguments
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
ARCH="aarch64"
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--arch) ARCH="$2"; shift 2 ;;
|
||||
--arch=*) ARCH="${1#*=}"; shift ;;
|
||||
*) echo "Unknown argument: $1" >&2; exit 1 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Architecture mapping
|
||||
#
|
||||
# RUST_TARGET — passed to cargo --target
|
||||
# OPENWRT_ARCH — goes in the .ipk control file and filename
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
case "$ARCH" in
|
||||
aarch64)
|
||||
RUST_TARGET="aarch64-unknown-linux-musl"
|
||||
OPENWRT_ARCH="aarch64_cortex-a53"
|
||||
;;
|
||||
mipsel)
|
||||
RUST_TARGET="mipsel-unknown-linux-musl"
|
||||
OPENWRT_ARCH="mipsel_24kc"
|
||||
;;
|
||||
mips)
|
||||
RUST_TARGET="mips-unknown-linux-musl"
|
||||
OPENWRT_ARCH="mips_24kc"
|
||||
;;
|
||||
arm)
|
||||
RUST_TARGET="arm-unknown-linux-musleabihf"
|
||||
OPENWRT_ARCH="arm_cortex-a7"
|
||||
;;
|
||||
x86_64)
|
||||
RUST_TARGET="x86_64-unknown-linux-musl"
|
||||
OPENWRT_ARCH="x86_64"
|
||||
;;
|
||||
*)
|
||||
echo "Unknown arch: $ARCH" >&2
|
||||
echo "Valid: aarch64, mipsel, mips, arm, x86_64" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Paths
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
FILES_DIR="$SCRIPT_DIR/files"
|
||||
DIST_DIR="$PROJECT_ROOT/dist"
|
||||
|
||||
PKG_NAME="fips"
|
||||
PKG_VERSION="${PKG_VERSION:-$(cd "$PROJECT_ROOT" && git describe --tags --always --dirty 2>/dev/null || echo "0.1.0")}"
|
||||
|
||||
echo "==> Building $PKG_NAME $PKG_VERSION for $OPENWRT_ARCH ($RUST_TARGET)"
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Prerequisites
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
if ! command -v cargo-zigbuild &>/dev/null; then
|
||||
echo "Error: cargo-zigbuild not found." >&2
|
||||
echo " Install: cargo install cargo-zigbuild" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! rustup target list --installed | grep -q "^$RUST_TARGET$"; then
|
||||
echo "==> Adding Rust target $RUST_TARGET..."
|
||||
rustup target add "$RUST_TARGET"
|
||||
fi
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# 1. Build
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
echo "==> Compiling..."
|
||||
cd "$PROJECT_ROOT"
|
||||
cargo zigbuild \
|
||||
--release \
|
||||
--target "$RUST_TARGET" \
|
||||
--bin fips \
|
||||
--bin fipsctl \
|
||||
--bin fipstop
|
||||
|
||||
RELEASE_DIR="$PROJECT_ROOT/target/$RUST_TARGET/release"
|
||||
|
||||
echo "==> Stripping binaries..."
|
||||
STRIP="${LLVM_STRIP:-strip}"
|
||||
for bin in fips fipsctl fipstop; do
|
||||
"$STRIP" "$RELEASE_DIR/$bin" 2>/dev/null || true
|
||||
done
|
||||
|
||||
SIZE=$(du -sh "$RELEASE_DIR/fips" | cut -f1)
|
||||
echo " fips: $SIZE after strip"
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# 2. Assemble .ipk
|
||||
# ---------------------------------------------------------------------------
|
||||
# An .ipk is an ar archive with three members:
|
||||
# debian-binary — format version ("2.0\n")
|
||||
# control.tar.gz — package metadata, conffiles, pre/post scripts
|
||||
# data.tar.gz — the actual filesystem tree
|
||||
|
||||
WORK_DIR="$(mktemp -d)"
|
||||
trap 'rm -rf "$WORK_DIR"' EXIT
|
||||
|
||||
CONTROL_DIR="$WORK_DIR/control"
|
||||
DATA_DIR="$WORK_DIR/data"
|
||||
mkdir -p "$CONTROL_DIR" "$DATA_DIR"
|
||||
|
||||
# ---- data tree ----
|
||||
|
||||
install -d "$DATA_DIR/usr/bin"
|
||||
install -m 0755 "$RELEASE_DIR/fips" "$DATA_DIR/usr/bin/fips"
|
||||
install -m 0755 "$RELEASE_DIR/fipsctl" "$DATA_DIR/usr/bin/fipsctl"
|
||||
install -m 0755 "$RELEASE_DIR/fipstop" "$DATA_DIR/usr/bin/fipstop"
|
||||
|
||||
install -d "$DATA_DIR/etc/init.d"
|
||||
install -m 0755 "$FILES_DIR/etc/init.d/fips" "$DATA_DIR/etc/init.d/fips"
|
||||
|
||||
install -d "$DATA_DIR/etc/fips"
|
||||
install -m 0600 "$FILES_DIR/etc/fips/fips.yaml" "$DATA_DIR/etc/fips/fips.yaml"
|
||||
install -m 0755 "$FILES_DIR/etc/fips/firewall.sh" "$DATA_DIR/etc/fips/firewall.sh"
|
||||
|
||||
install -d "$DATA_DIR/etc/dnsmasq.d"
|
||||
install -m 0644 "$FILES_DIR/etc/dnsmasq.d/fips.conf" "$DATA_DIR/etc/dnsmasq.d/fips.conf"
|
||||
|
||||
install -d "$DATA_DIR/etc/sysctl.d"
|
||||
install -m 0644 "$FILES_DIR/etc/sysctl.d/fips-bridge.conf" "$DATA_DIR/etc/sysctl.d/fips-bridge.conf"
|
||||
|
||||
install -d "$DATA_DIR/etc/hotplug.d/net"
|
||||
install -m 0755 "$FILES_DIR/etc/hotplug.d/net/99-fips" "$DATA_DIR/etc/hotplug.d/net/99-fips"
|
||||
|
||||
install -d "$DATA_DIR/etc/uci-defaults"
|
||||
install -m 0755 "$FILES_DIR/etc/uci-defaults/90-fips-setup" "$DATA_DIR/etc/uci-defaults/90-fips-setup"
|
||||
|
||||
install -d "$DATA_DIR/lib/upgrade/keep.d"
|
||||
install -m 0644 "$FILES_DIR/lib/upgrade/keep.d/fips" "$DATA_DIR/lib/upgrade/keep.d/fips"
|
||||
|
||||
# ---- control files ----
|
||||
|
||||
PKG_SIZE=$(du -sk "$DATA_DIR" | cut -f1)
|
||||
|
||||
cat > "$CONTROL_DIR/control" <<EOF
|
||||
Package: $PKG_NAME
|
||||
Version: $PKG_VERSION
|
||||
Architecture: $OPENWRT_ARCH
|
||||
Maintainer: FIPS Network
|
||||
Section: net
|
||||
Priority: optional
|
||||
Depends: kmod-tun, kmod-br-netfilter
|
||||
Description: FIPS Mesh Network Daemon
|
||||
Distributed, decentralized mesh networking over UDP, TCP, and raw Ethernet.
|
||||
Provides a TUN interface (fips0) with ULA IPv6 addressing and a DNS
|
||||
responder for .fips name resolution.
|
||||
Installed-Size: $PKG_SIZE
|
||||
EOF
|
||||
|
||||
# Mark fips.yaml as a conffile so opkg won't overwrite user edits on upgrade.
|
||||
cat > "$CONTROL_DIR/conffiles" <<EOF
|
||||
/etc/fips/fips.yaml
|
||||
EOF
|
||||
|
||||
cat > "$CONTROL_DIR/postinst" <<'EOF'
|
||||
#!/bin/sh
|
||||
# Run first-boot UCI setup (the script deletes itself when done).
|
||||
if [ -x /etc/uci-defaults/90-fips-setup ]; then
|
||||
/etc/uci-defaults/90-fips-setup && rm -f /etc/uci-defaults/90-fips-setup
|
||||
fi
|
||||
|
||||
/etc/init.d/fips enable
|
||||
/etc/init.d/fips start
|
||||
exit 0
|
||||
EOF
|
||||
chmod 0755 "$CONTROL_DIR/postinst"
|
||||
|
||||
cat > "$CONTROL_DIR/prerm" <<'EOF'
|
||||
#!/bin/sh
|
||||
/etc/init.d/fips stop 2>/dev/null || true
|
||||
/etc/init.d/fips disable 2>/dev/null || true
|
||||
exit 0
|
||||
EOF
|
||||
chmod 0755 "$CONTROL_DIR/prerm"
|
||||
|
||||
# ---- pack ----
|
||||
|
||||
PKG_FILENAME="${PKG_NAME}_${PKG_VERSION}_${OPENWRT_ARCH}.ipk"
|
||||
IPK_WORK="$WORK_DIR/ipk"
|
||||
mkdir -p "$IPK_WORK"
|
||||
|
||||
echo "2.0" > "$IPK_WORK/debian-binary"
|
||||
|
||||
# Detect a tar that supports --format=gnu.
|
||||
# On macOS, Homebrew's GNU tar is installed as 'gtar'; the system tar is BSD.
|
||||
# Our filenames are short so BSD tar (ustar) works too, but gnu is preferred
|
||||
# to match ipkg-build exactly and to embed numeric UID/GID.
|
||||
# COPYFILE_DISABLE=1 suppresses macOS resource-fork (._*) files; no-op on Linux.
|
||||
if command -v gtar &>/dev/null; then
|
||||
# Homebrew GNU tar on macOS
|
||||
TAR_CMD="gtar"
|
||||
TAR_EXTRA_FLAGS="--format=gnu --numeric-owner"
|
||||
elif tar --version 2>/dev/null | grep -q 'GNU tar'; then
|
||||
# System tar is GNU tar (Linux)
|
||||
TAR_CMD="tar"
|
||||
TAR_EXTRA_FLAGS="--format=gnu --numeric-owner"
|
||||
else
|
||||
# macOS BSD tar (libarchive). Its default format is PAX (typeflag 0x78),
|
||||
# which OpenWrt's busybox tar cannot handle. Force ustar explicitly.
|
||||
TAR_CMD="tar"
|
||||
TAR_EXTRA_FLAGS="--format=ustar"
|
||||
fi
|
||||
|
||||
ipk_tar() {
|
||||
# ipk_tar <output.tar.gz> <source-dir> [paths...]
|
||||
local out="$1" src="$2"; shift 2
|
||||
COPYFILE_DISABLE=1 "$TAR_CMD" $TAR_EXTRA_FLAGS -czf "$out" -C "$src" "$@"
|
||||
}
|
||||
|
||||
ipk_tar "$IPK_WORK/control.tar.gz" "$CONTROL_DIR" .
|
||||
ipk_tar "$IPK_WORK/data.tar.gz" "$DATA_DIR" .
|
||||
|
||||
# The outer .ipk container is a gzip-compressed tar — NOT an ar archive.
|
||||
# (Debian .deb uses ar; OpenWrt .ipk uses tar.gz.)
|
||||
# Entries must be named with ./ prefix, as ipkg-build produces.
|
||||
mkdir -p "$DIST_DIR"
|
||||
ipk_tar "$DIST_DIR/$PKG_FILENAME" "$IPK_WORK" ./debian-binary ./control.tar.gz ./data.tar.gz
|
||||
|
||||
echo ""
|
||||
echo "==> Done: dist/$PKG_FILENAME"
|
||||
echo " $(du -sh "$DIST_DIR/$PKG_FILENAME" | cut -f1)"
|
||||
echo ""
|
||||
echo "Install on router:"
|
||||
echo " scp -O dist/$PKG_FILENAME root@192.168.1.1:/tmp/"
|
||||
echo " ssh root@192.168.1.1 opkg install /tmp/$PKG_FILENAME"
|
||||
11
packaging/openwrt/files/etc/dnsmasq.d/fips.conf
Normal file
11
packaging/openwrt/files/etc/dnsmasq.d/fips.conf
Normal file
@@ -0,0 +1,11 @@
|
||||
# FIPS mesh DNS — forward .fips queries to the local FIPS DNS responder.
|
||||
#
|
||||
# server= forward all .fips queries to 127.0.0.1:5354
|
||||
# rebind-domain-ok= disable DNS-rebind protection for .fips; FIPS node
|
||||
# addresses live in fd00::/8 (ULA), which dnsmasq blocks by
|
||||
# default as a rebind-attack countermeasure.
|
||||
#
|
||||
# If your fips.yaml sets dns.port to something other than 5354, update the
|
||||
# port number below to match.
|
||||
server=/fips/127.0.0.1#5354
|
||||
rebind-domain-ok=/fips/
|
||||
64
packaging/openwrt/files/etc/fips/fips.yaml
Normal file
64
packaging/openwrt/files/etc/fips/fips.yaml
Normal file
@@ -0,0 +1,64 @@
|
||||
# FIPS Node Configuration
|
||||
#
|
||||
# Edit this file before starting the FIPS daemon.
|
||||
# Full reference: https://github.com/jmcorgan/fips/blob/master/docs/design/fips-configuration.md
|
||||
#
|
||||
# After editing, restart the daemon:
|
||||
# /etc/init.d/fips restart
|
||||
|
||||
node:
|
||||
identity:
|
||||
# A persistent keypair is generated on first start and saved to
|
||||
# /etc/fips/fips.key (private) and /etc/fips/fips.pub (public).
|
||||
# The router keeps the same FIPS identity across reboots.
|
||||
#
|
||||
# To use an explicit key instead, comment out 'persistent' and set:
|
||||
# nsec: "your-64-char-hex-private-key"
|
||||
persistent: true
|
||||
|
||||
tun:
|
||||
enabled: true
|
||||
name: fips0
|
||||
mtu: 1280
|
||||
|
||||
dns:
|
||||
enabled: true
|
||||
bind_addr: "127.0.0.1"
|
||||
port: 5354
|
||||
|
||||
transports:
|
||||
udp:
|
||||
bind_addr: "0.0.0.0:2121"
|
||||
|
||||
# Ethernet transport — uncomment and set your interface names.
|
||||
# Use physical port names, NOT bridge names (e.g. eth1, not br-lan).
|
||||
# Run 'ip link show' on the router to identify port names.
|
||||
# See: https://github.com/jmcorgan/fips/blob/master/deploy/native/README.md
|
||||
#
|
||||
# ethernet:
|
||||
# wan:
|
||||
# interface: "eth0" # WAN
|
||||
# discovery: true
|
||||
# announce: true
|
||||
# auto_connect: true
|
||||
# accept_connections: true
|
||||
# wwan:
|
||||
# interface: "phy0-sta0" # WWAN
|
||||
# discovery: true
|
||||
# announce: true
|
||||
# auto_connect: true
|
||||
# accept_connections: true
|
||||
# lan:
|
||||
# interface: "br-lan" # LAN
|
||||
# discovery: true
|
||||
# announce: true
|
||||
# auto_connect: true
|
||||
# accept_connections: true
|
||||
|
||||
peers: []
|
||||
# Static peers for bootstrapping (add at least one if using UDP-only):
|
||||
# - npub: "npub1..."
|
||||
# alias: "gateway"
|
||||
# addresses:
|
||||
# - transport: udp
|
||||
# addr: "1.2.3.4:2121"
|
||||
33
packaging/openwrt/files/etc/fips/firewall.sh
Normal file
33
packaging/openwrt/files/etc/fips/firewall.sh
Normal file
@@ -0,0 +1,33 @@
|
||||
#!/bin/sh
|
||||
# FIPS firewall rules — accept all traffic on the FIPS TUN interface.
|
||||
#
|
||||
# Called by:
|
||||
# - /etc/hotplug.d/net/99-fips when fips0 comes up
|
||||
# - the UCI firewall include on every firewall reload
|
||||
#
|
||||
# Supports both fw4 (nftables, OpenWrt 22.03+) and older iptables builds.
|
||||
|
||||
TUN="fips0"
|
||||
|
||||
if command -v nft >/dev/null 2>&1 && nft list table inet fw4 >/dev/null 2>&1; then
|
||||
for chain in input output forward; do
|
||||
case "$chain" in
|
||||
input|forward) match="iifname \"$TUN\"" ;;
|
||||
output) match="oifname \"$TUN\"" ;;
|
||||
esac
|
||||
nft list chain inet fw4 "$chain" 2>/dev/null | grep -q "$match" || \
|
||||
nft insert rule inet fw4 "$chain" $match accept comment "\"fips\""
|
||||
done
|
||||
# Also accept forwarded traffic leaving via fips0
|
||||
nft list chain inet fw4 forward 2>/dev/null | grep -q "oifname \"$TUN\"" || \
|
||||
nft insert rule inet fw4 forward oifname "$TUN" accept comment '"fips"'
|
||||
fi
|
||||
|
||||
if command -v iptables >/dev/null 2>&1; then
|
||||
iptables -C INPUT -i "$TUN" -j ACCEPT 2>/dev/null || \
|
||||
iptables -I INPUT 1 -i "$TUN" -j ACCEPT
|
||||
iptables -C OUTPUT -o "$TUN" -j ACCEPT 2>/dev/null || \
|
||||
iptables -I OUTPUT 1 -o "$TUN" -j ACCEPT
|
||||
iptables -C FORWARD -i "$TUN" -j ACCEPT 2>/dev/null || \
|
||||
iptables -I FORWARD 1 -i "$TUN" -j ACCEPT
|
||||
fi
|
||||
8
packaging/openwrt/files/etc/hotplug.d/net/99-fips
Normal file
8
packaging/openwrt/files/etc/hotplug.d/net/99-fips
Normal file
@@ -0,0 +1,8 @@
|
||||
#!/bin/sh
|
||||
# FIPS hotplug — apply firewall rules when the FIPS TUN interface comes up.
|
||||
# The kernel fires net hotplug events for every interface including TUN devices.
|
||||
|
||||
[ "$INTERFACE" = "fips0" ] || exit 0
|
||||
[ "$ACTION" = "add" ] || [ "$ACTION" = "register" ] || exit 0
|
||||
|
||||
/etc/fips/firewall.sh
|
||||
28
packaging/openwrt/files/etc/init.d/fips
Normal file
28
packaging/openwrt/files/etc/init.d/fips
Normal file
@@ -0,0 +1,28 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
# FIPS mesh daemon — procd init script for OpenWrt
|
||||
|
||||
USE_PROCD=1
|
||||
START=95
|
||||
STOP=10
|
||||
|
||||
PROG=/usr/bin/fips
|
||||
CONFIG=/etc/fips/fips.yaml
|
||||
|
||||
start_service() {
|
||||
# Ensure TUN module is loaded before starting the daemon.
|
||||
modprobe tun 2>/dev/null || true
|
||||
|
||||
procd_open_instance
|
||||
procd_set_param command "$PROG" --config "$CONFIG"
|
||||
procd_set_param env RUST_LOG=info
|
||||
# Respawn: restart after 5 s, give up after 5 consecutive failures within
|
||||
# a 3600 s window, then reset the failure counter and try again.
|
||||
procd_set_param respawn 3600 5 5
|
||||
procd_set_param stdout 1
|
||||
procd_set_param stderr 1
|
||||
procd_close_instance
|
||||
}
|
||||
|
||||
reload_service() {
|
||||
restart
|
||||
}
|
||||
12
packaging/openwrt/files/etc/sysctl.d/fips-bridge.conf
Normal file
12
packaging/openwrt/files/etc/sysctl.d/fips-bridge.conf
Normal file
@@ -0,0 +1,12 @@
|
||||
# FIPS: bridge netfilter settings
|
||||
#
|
||||
# kmod-br-netfilter must be loaded for AF_PACKET sockets to receive frames
|
||||
# on bridge member ports (e.g. eth1 when it is a member of br-lan).
|
||||
# Without it, the bridge's rx_handler intercepts frames before they reach
|
||||
# the packet socket layer.
|
||||
#
|
||||
# We load br_netfilter for the AF_PACKET visibility benefit but disable its
|
||||
# IP/IPv6/ARP call hooks to avoid double-processing of routed traffic.
|
||||
net.bridge.bridge-nf-call-iptables=0
|
||||
net.bridge.bridge-nf-call-ip6tables=0
|
||||
net.bridge.bridge-nf-call-arptables=0
|
||||
72
packaging/openwrt/files/etc/uci-defaults/90-fips-setup
Normal file
72
packaging/openwrt/files/etc/uci-defaults/90-fips-setup
Normal file
@@ -0,0 +1,72 @@
|
||||
#!/bin/sh
|
||||
# FIPS first-boot setup — runs once after package installation.
|
||||
# Configures the firewall and kernel modules for FIPS operation.
|
||||
# This script is executed by /etc/rc.d/S19sysctl on first boot and
|
||||
# then deleted by the UCI defaults mechanism.
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# 1. Kernel modules
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
# kmod-tun is listed as a package dependency, but ensure the module is loaded.
|
||||
modprobe tun 2>/dev/null || true
|
||||
echo "tun" > /etc/modules.d/tun
|
||||
|
||||
# kmod-br-netfilter makes AF_PACKET visible on bridge member ports.
|
||||
modprobe br_netfilter 2>/dev/null || true
|
||||
echo "br_netfilter" > /etc/modules.d/br-netfilter
|
||||
|
||||
# Apply the sysctl settings shipped in /etc/sysctl.d/fips-bridge.conf now
|
||||
# (the file will be applied automatically on subsequent boots).
|
||||
sysctl -p /etc/sysctl.d/fips-bridge.conf 2>/dev/null || true
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# 2. Firewall — add fips0 to the lan zone (fw4 / UCI)
|
||||
# ---------------------------------------------------------------------------
|
||||
# fw4 (nftables) matches zones by device name, so adding fips0 as a 'device'
|
||||
# to the lan zone makes all traffic on the TUN interface accepted without
|
||||
# needing raw nft rules in the base chains.
|
||||
|
||||
z=0
|
||||
while uci -q get "firewall.@zone[$z]" >/dev/null 2>&1; do
|
||||
if [ "$(uci -q get "firewall.@zone[$z].name" 2>/dev/null)" = "lan" ]; then
|
||||
uci -q del_list "firewall.@zone[$z].device=fips0" 2>/dev/null || true
|
||||
uci add_list "firewall.@zone[$z].device=fips0"
|
||||
break
|
||||
fi
|
||||
z=$((z + 1))
|
||||
done
|
||||
|
||||
# Install a firewall include so /etc/fips/firewall.sh is re-applied on every
|
||||
# firewall reload (belt-and-suspenders for iptables-based OpenWrt builds).
|
||||
FOUND=0
|
||||
j=0
|
||||
while uci -q get "firewall.@include[$j]" >/dev/null 2>&1; do
|
||||
if [ "$(uci -q get "firewall.@include[$j].path" 2>/dev/null)" = "/etc/fips/firewall.sh" ]; then
|
||||
FOUND=1
|
||||
break
|
||||
fi
|
||||
j=$((j + 1))
|
||||
done
|
||||
if [ "$FOUND" = "0" ]; then
|
||||
uci add firewall include
|
||||
uci set "firewall.@include[-1].path=/etc/fips/firewall.sh"
|
||||
uci set "firewall.@include[-1].reload=1"
|
||||
fi
|
||||
|
||||
uci commit firewall
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# 3. dnsmasq UCI registration
|
||||
# ---------------------------------------------------------------------------
|
||||
# /etc/dnsmasq.d/fips.conf already handles runtime forwarding.
|
||||
# Register via UCI as well so the settings survive a full dnsmasq config
|
||||
# regeneration (e.g. after a firmware upgrade that rebuilds dnsmasq.conf).
|
||||
|
||||
uci -q del_list dhcp.@dnsmasq[0].server="/fips/127.0.0.1#5354" 2>/dev/null || true
|
||||
uci add_list dhcp.@dnsmasq[0].server="/fips/127.0.0.1#5354"
|
||||
uci -q del_list dhcp.@dnsmasq[0].rebind_domain="fips" 2>/dev/null || true
|
||||
uci add_list dhcp.@dnsmasq[0].rebind_domain="fips"
|
||||
uci commit dhcp
|
||||
|
||||
exit 0
|
||||
2
packaging/openwrt/files/lib/upgrade/keep.d/fips
Normal file
2
packaging/openwrt/files/lib/upgrade/keep.d/fips
Normal file
@@ -0,0 +1,2 @@
|
||||
# Preserve FIPS configuration and persistent identity key across sysupgrade.
|
||||
/etc/fips/
|
||||
Reference in New Issue
Block a user