Files
fips/packaging/systemd/install.sh
T
Johnathan Corgan c5d62a6387 Restart fips-dns and fips-gateway after a tarball upgrade
install.sh stopped fips before checking fips-dns. Both fips-dns and
fips-gateway require fips.service, so stopping fips had already stopped
them: the script saw fips-dns inactive and restarted only fips. .fips
resolution stayed down and the gateway stayed stopped until started by
hand. The script now records which of the three units were active
before stopping any, and starts each of those again.

A new tarball-install suite runs install.sh as an upgrade under real
systemd, with stub binaries, in both local and GitHub CI.
2026-09-30 14:12:22 +00:00

211 lines
7.6 KiB
Bash
Executable File

#!/usr/bin/env bash
# FIPS Install Script
#
# Installs the FIPS mesh network daemon as a systemd service.
#
# Usage: sudo ./install.sh
#
# Files installed:
# /usr/local/bin/fips Daemon binary
# /usr/local/bin/fipsctl CLI query tool
# /usr/local/bin/fipstop TUI monitor
# /usr/local/bin/fips-gateway Outbound LAN gateway binary (opt-in)
# /etc/fips/fips.yaml Configuration (preserved if exists)
# /etc/fips/hosts Host-to-npub mappings (preserved if exists)
# /etc/fips/fips.nft Mesh-interface nftables baseline (preserved if exists)
# /etc/fips/fips.d/ Operator drop-in directory for nft rules
# /etc/systemd/system/fips.service Daemon unit (enabled)
# /etc/systemd/system/fips-dns.service DNS routing for .fips domain (enabled)
# /etc/systemd/system/fips-gateway.service Gateway unit (NOT enabled; opt-in)
# /etc/systemd/system/fips-firewall.service Firewall baseline unit (NOT enabled; opt-in)
set -euo pipefail
INSTALL_PREFIX="/usr/local"
CONFIG_DIR="/etc/fips"
CONFIG_FILE="${CONFIG_DIR}/fips.yaml"
SYSTEMD_DIR="/etc/systemd/system"
FIPS_GROUP="fips"
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
# --- Preflight checks ---
if [ "$(id -u)" -ne 0 ]; then
echo "Error: This script must be run as root (use sudo)." >&2
exit 1
fi
if [ ! -f "${SCRIPT_DIR}/fips" ]; then
echo "Error: fips binary not found in ${SCRIPT_DIR}" >&2
exit 1
fi
if ! command -v systemctl &>/dev/null; then
echo "Error: systemctl not found. This script requires systemd." >&2
exit 1
fi
if [ ! -e /dev/net/tun ]; then
echo "Warning: /dev/net/tun not found. TUN support may not work." >&2
echo " Load the module with: modprobe tun" >&2
fi
# --- Create fips group for control socket access ---
if ! getent group "${FIPS_GROUP}" &>/dev/null; then
groupadd --system "${FIPS_GROUP}"
echo "Created system group '${FIPS_GROUP}'."
fi
# --- Install binaries ---
echo "Installing binaries to ${INSTALL_PREFIX}/bin/"
install -m 0755 "${SCRIPT_DIR}/fips" "${INSTALL_PREFIX}/bin/fips"
install -m 0755 "${SCRIPT_DIR}/fipsctl" "${INSTALL_PREFIX}/bin/fipsctl"
if [ -f "${SCRIPT_DIR}/fipstop" ]; then
install -m 0755 "${SCRIPT_DIR}/fipstop" "${INSTALL_PREFIX}/bin/fipstop"
fi
if [ -f "${SCRIPT_DIR}/fips-gateway" ]; then
install -m 0755 "${SCRIPT_DIR}/fips-gateway" "${INSTALL_PREFIX}/bin/fips-gateway"
fi
# --- Install configuration ---
mkdir -p "${CONFIG_DIR}"
if [ -f "${CONFIG_FILE}" ]; then
echo "Configuration exists at ${CONFIG_FILE}, not overwriting."
install -m 0644 "${SCRIPT_DIR}/fips.yaml" "${CONFIG_DIR}/fips.yaml.template"
echo " New template installed as ${CONFIG_DIR}/fips.yaml.template"
else
install -m 0600 "${SCRIPT_DIR}/fips.yaml" "${CONFIG_FILE}"
echo "Configuration installed to ${CONFIG_FILE}"
fi
HOSTS_FILE="${CONFIG_DIR}/hosts"
if [ -f "${HOSTS_FILE}" ]; then
echo "Hosts file exists at ${HOSTS_FILE}, not overwriting."
else
install -m 0644 "${SCRIPT_DIR}/hosts" "${HOSTS_FILE}"
echo "Hosts file installed to ${HOSTS_FILE}"
fi
# Mesh-interface nftables baseline. Preserved on upgrade like fips.yaml
# so operator edits aren't clobbered.
NFT_FILE="${CONFIG_DIR}/fips.nft"
if [ -f "${NFT_FILE}" ]; then
echo "Firewall baseline exists at ${NFT_FILE}, not overwriting."
install -m 0644 "${SCRIPT_DIR}/fips.nft" "${CONFIG_DIR}/fips.nft.template"
echo " New template installed as ${CONFIG_DIR}/fips.nft.template"
elif [ -f "${SCRIPT_DIR}/fips.nft" ]; then
install -m 0644 "${SCRIPT_DIR}/fips.nft" "${NFT_FILE}"
echo "Firewall baseline installed to ${NFT_FILE}"
fi
# Drop-in directory for operator nftables rules included by
# /etc/fips/fips.nft. Empty by default; the include glob matches
# nothing cleanly out of the box.
if [ ! -d "${CONFIG_DIR}/fips.d" ]; then
install -d -m 0755 "${CONFIG_DIR}/fips.d"
echo "Drop-in directory created at ${CONFIG_DIR}/fips.d/"
fi
# --- Install systemd units ---
# fips-dns and fips-gateway carry Requires=fips.service, so stopping fips
# stops them too. Record all three before stopping any of them.
declare -A was_active=()
for unit in fips fips-dns fips-gateway; do
if systemctl is-active --quiet "${unit}.service" 2>/dev/null; then
was_active[$unit]=true
fi
done
for unit in fips-gateway fips-dns fips; do
if [ "${was_active[$unit]:-}" = true ]; then
echo "Stopping running ${unit} service..."
systemctl stop "${unit}.service"
fi
done
install -m 0644 "${SCRIPT_DIR}/fips.service" "${SYSTEMD_DIR}/fips.service"
install -m 0644 "${SCRIPT_DIR}/fips-dns.service" "${SYSTEMD_DIR}/fips-dns.service"
if [ -f "${SCRIPT_DIR}/fips-gateway.service" ]; then
install -m 0644 "${SCRIPT_DIR}/fips-gateway.service" "${SYSTEMD_DIR}/fips-gateway.service"
fi
if [ -f "${SCRIPT_DIR}/fips-firewall.service" ]; then
install -m 0644 "${SCRIPT_DIR}/fips-firewall.service" "${SYSTEMD_DIR}/fips-firewall.service"
fi
# DNS helpers ship flat in the tarball alongside install.sh; from a
# source checkout they live under packaging/common/. Resolve from
# either layout.
install -d -m 0755 /usr/lib/fips
if [ -f "${SCRIPT_DIR}/fips-dns-setup" ]; then
install -m 0755 "${SCRIPT_DIR}/fips-dns-setup" /usr/lib/fips/fips-dns-setup
install -m 0755 "${SCRIPT_DIR}/fips-dns-teardown" /usr/lib/fips/fips-dns-teardown
else
install -m 0755 "${SCRIPT_DIR}/../common/fips-dns-setup" /usr/lib/fips/fips-dns-setup
install -m 0755 "${SCRIPT_DIR}/../common/fips-dns-teardown" /usr/lib/fips/fips-dns-teardown
fi
systemctl daemon-reload
echo "systemd units and DNS scripts installed."
# --- Configure runtime directory group ownership ---
# systemd creates /run/fips/ with RuntimeDirectory, but we need the
# group set to 'fips' so group members can access the control socket.
# Create a tmpfiles.d entry for this.
cat > /etc/tmpfiles.d/fips.conf <<'TMPFILES'
d /run/fips 0750 root fips -
TMPFILES
echo "tmpfiles.d entry created for /run/fips/ ownership."
# --- Enable service ---
systemctl enable fips.service
systemctl enable fips-dns.service
echo "Services enabled (will start on boot)."
# Restart each unit that was running before
for unit in fips fips-dns fips-gateway; do
if [ "${was_active[$unit]:-}" = true ]; then
echo "Restarting ${unit} service..."
systemctl start "${unit}.service"
fi
done
echo ""
echo "=== Installation complete ==="
echo ""
echo "Before starting the service, edit ${CONFIG_FILE}:"
echo ""
echo " 1. Set a persistent identity (if publishing npub for static peers)"
echo " Uncomment 'persistent: true' in the identity section."
echo " A keypair will be generated and saved on first start."
echo ""
echo " 2. Configure Ethernet transport interface (if using)"
echo " Uncomment the ethernet section and set the interface name."
echo ""
echo " 3. Add static peers (if bootstrapping over UDP/TCP)"
echo ""
echo "Start the service:"
echo " sudo systemctl start fips"
echo ""
echo "Optional services (NOT enabled by default):"
echo ""
echo " Mesh-interface firewall baseline (default-deny on fips0):"
echo " sudo systemctl enable --now fips-firewall.service"
echo " Operator drop-ins under /etc/fips/fips.d/*.nft"
echo ""
echo " Outbound LAN gateway (bridge unmodified LAN hosts to .fips):"
echo " sudo systemctl enable --now fips-gateway.service"
echo " Configure under the gateway: section of ${CONFIG_FILE}"
echo ""
echo "Monitor:"
echo " sudo journalctl -u fips -f"
echo " fipsctl show status"
echo " fipstop"
echo ""
echo "To use fipsctl/fipstop without sudo, add your user to the fips group:"
echo " sudo usermod -aG fips \$USER"
echo " (log out and back in for group membership to take effect)"