Zones, address sets (IPv4 and IPv6 mixed, dynamic sets with timeouts) and services, ordered rules in the early, input, forward and output chains, port forwards with hairpin NAT and IPv6 pinholes, source NAT, redirects, and switchable built-ins (loopback, conntrack, ICMPv6, antispoofing, MSS clamping, DHCPv6 client, flowtable). Every change is validated, checked with nft -c and applied in one transaction to Housecarl's own table, inet housecarl; changes made over the network roll back unless confirmed, and the confirmed ruleset is loaded at boot by housecarl-ruleset.service. An empty configuration applies nothing. Also: hit counters and the drop log (nflog), 'hc import' of an existing nftables ruleset and 'hc takeover', the hc CLI, the REST API and the web UI, users, scoped tokens (sets:write:NAME), the audit log, the web UI's certificate through Jarl, Debian packages, docs, unit tests with real nft 1.1.3, and an e2e test with real traffic (71 checks). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
150 lines
7.1 KiB
Makefile
150 lines
7.1 KiB
Makefile
# Housecarl build.
|
|
#
|
|
# make build bin/housecarld and bin/hc (and their bash completion)
|
|
# make test vet, gofmt check and unit tests
|
|
# make logo rebuild the web UI's logo and the README banner from artwork/
|
|
# make e2e end-to-end test with real traffic through a firewall in Docker (scripts/e2e.sh)
|
|
# sudo make install install binaries, bash completion, systemd units,
|
|
# sysusers/tmpfiles files and an example /etc/housecarl/housecarl.yaml
|
|
# make deb Debian packages in dist/ (DEB_ARCH=arm64 for another
|
|
# architecture): housecarl (the server) and housecarl-cli (hc,
|
|
# which housecarl depends on)
|
|
# make dist static binaries for linux/amd64 and linux/arm64 in dist/
|
|
# make cli-dist the CLI alone for Linux, macOS and Windows in dist/
|
|
# (housecarl-cli-<version>-<os>-<arch>[.exe])
|
|
#
|
|
# Installing, the systemd unit and the Debian packages come with the daemon
|
|
# (as in Steward's Makefile).
|
|
|
|
VERSION ?= $(shell cat VERSION 2>/dev/null || echo 0.0.0-dev)
|
|
# RELEASE_TAG marks a build of a release (the web UI then shows and links
|
|
# the release rather than the commit): set when HEAD is tagged v$(VERSION)
|
|
# and no tracked file is changed.
|
|
RELEASE_TAG ?= $(shell t=v$(VERSION); git tag --points-at HEAD 2>/dev/null | grep -qx "$$t" && git diff --quiet HEAD 2>/dev/null && echo $$t)
|
|
# DESCRIBE places other builds relative to the last tag ("3 commits after
|
|
# v0.2.0-rc.1").
|
|
DESCRIBE ?= $(shell git describe --tags --long --match 'v[0-9]*' --abbrev=12 HEAD 2>/dev/null)
|
|
LDFLAGS := -s -w -X housecarl/internal/version.Version=$(VERSION) -X housecarl/internal/version.Tag=$(RELEASE_TAG) \
|
|
-X housecarl/internal/version.Describe=$(DESCRIBE)
|
|
GOFLAGS := -trimpath
|
|
export CGO_ENABLED := 0
|
|
|
|
PREFIX ?= /usr/local
|
|
BINDIR ?= $(PREFIX)/bin
|
|
DOCDIR ?= $(PREFIX)/share/doc/housecarl
|
|
# bash-completion also looks in /usr/local/share (XDG_DATA_DIRS).
|
|
BASHCOMPDIR ?= $(PREFIX)/share/bash-completion/completions
|
|
UNITDIR ?= /etc/systemd/system
|
|
SYSUSERSDIR ?= /usr/lib/sysusers.d
|
|
TMPFILESDIR ?= /usr/lib/tmpfiles.d
|
|
DESTDIR ?=
|
|
|
|
# The binaries install-files copies (make deb points these at other
|
|
# architectures' builds).
|
|
HOUSECARLD_BIN ?= bin/housecarld
|
|
HC_BIN ?= bin/hc
|
|
|
|
# make deb: the package's architecture (Debian name) and version. A
|
|
# release is VERSION with ~ for - (0.1.0-rc.1 -> 0.1.0~rc.1, which apt
|
|
# sorts before 0.1.0). A development build is versioned after the last
|
|
# tag (0.1.0~rc.1+git3.gca0f148); uncommitted changes add the build time.
|
|
DEB_ARCH ?= $(shell dpkg --print-architecture 2>/dev/null || go env GOARCH)
|
|
DEB_DEV_VERSION := $(shell [ -n '$(DESCRIBE)' ] || exit 0; \
|
|
m=; git diff --quiet HEAD 2>/dev/null || m=.m$$(date -u +%Y%m%d%H%M%S); \
|
|
echo '$(DESCRIBE)' | sed -E 's/^v(.*)-([0-9]+)-g([0-9a-f]{7})[0-9a-f]*$$/\1+git\2.g\3/' | tr - '~' | sed "s/$$/$$m/")
|
|
DEB_VERSION ?= $(if $(RELEASE_TAG),$(subst -,~,$(VERSION)),$(or $(DEB_DEV_VERSION),$(subst -,~,$(VERSION))))
|
|
|
|
.PHONY: all build completion test vet logo e2e install install-files uninstall deb dist cli-dist clean
|
|
|
|
all: build
|
|
|
|
build:
|
|
go build $(GOFLAGS) -ldflags '$(LDFLAGS)' -o bin/housecarld ./cmd/housecarld
|
|
go build $(GOFLAGS) -ldflags '$(LDFLAGS)' -o bin/hc ./cmd/hc
|
|
$(MAKE) --no-print-directory completion
|
|
|
|
# Bash completion scripts, generated by the binaries themselves.
|
|
completion:
|
|
@mkdir -p bin/completion
|
|
bin/hc completion bash > bin/completion/hc
|
|
bin/housecarld completion bash > bin/completion/housecarld
|
|
|
|
vet:
|
|
go vet ./...
|
|
@test -z "$$(gofmt -l cmd internal)" || { echo "gofmt needed:"; gofmt -l cmd internal; exit 1; }
|
|
|
|
test: vet
|
|
go test ./...
|
|
|
|
logo:
|
|
python3 scripts/logo.py
|
|
|
|
e2e:
|
|
scripts/e2e.sh
|
|
|
|
install: build install-files
|
|
@if [ ! -e $(DESTDIR)/etc/housecarl/housecarl.yaml ]; then \
|
|
install -d -m 0750 $(DESTDIR)/etc/housecarl; \
|
|
bin/housecarld config --example > $(DESTDIR)/etc/housecarl/housecarl.yaml; \
|
|
chmod 0640 $(DESTDIR)/etc/housecarl/housecarl.yaml; \
|
|
echo "wrote $(DESTDIR)/etc/housecarl/housecarl.yaml"; \
|
|
fi
|
|
@echo
|
|
@echo "Next (as root): systemd-sysusers housecarl.conf && systemd-tmpfiles --create housecarl.conf"
|
|
@echo " chgrp housecarl /etc/housecarl /etc/housecarl/housecarl.yaml && systemctl daemon-reload"
|
|
@echo " systemctl enable housecarl-ruleset.service"
|
|
@echo "Then follow docs/install.md (init, import your ruleset, start)."
|
|
|
|
# Everything but /etc/housecarl/housecarl.yaml (shared by install and deb).
|
|
install-files:
|
|
install -D -m 0755 $(HOUSECARLD_BIN) $(DESTDIR)$(BINDIR)/housecarld
|
|
install -D -m 0755 $(HC_BIN) $(DESTDIR)$(BINDIR)/hc
|
|
install -D -m 0644 bin/completion/hc $(DESTDIR)$(BASHCOMPDIR)/hc
|
|
install -D -m 0644 bin/completion/housecarld $(DESTDIR)$(BASHCOMPDIR)/housecarld
|
|
for u in housecarl.service housecarl-ruleset.service housecarl-backup.service housecarl-backup.timer; do \
|
|
install -D -m 0644 deploy/systemd/$$u $(DESTDIR)$(UNITDIR)/$$u && \
|
|
sed -i 's#/usr/local/bin/housecarld#$(BINDIR)/housecarld#; s#/usr/local/share/doc/housecarl#$(DOCDIR)#' $(DESTDIR)$(UNITDIR)/$$u || exit 1; \
|
|
done
|
|
install -D -m 0644 deploy/sysusers.d/housecarl.conf $(DESTDIR)$(SYSUSERSDIR)/housecarl.conf
|
|
install -D -m 0644 deploy/tmpfiles.d/housecarl.conf $(DESTDIR)$(TMPFILESDIR)/housecarl.conf
|
|
install -D -m 0644 README.md $(DESTDIR)$(DOCDIR)/README.md
|
|
install -D -m 0644 LICENSE $(DESTDIR)$(DOCDIR)/LICENSE
|
|
install -D -m 0644 CHANGELOG.md $(DESTDIR)$(DOCDIR)/CHANGELOG.md
|
|
install -d $(DESTDIR)$(DOCDIR)/docs
|
|
install -m 0644 docs/*.md $(DESTDIR)$(DOCDIR)/docs/
|
|
|
|
uninstall:
|
|
rm -f $(DESTDIR)$(BINDIR)/housecarld $(DESTDIR)$(BINDIR)/hc $(DESTDIR)$(UNITDIR)/housecarl.service \
|
|
$(DESTDIR)$(UNITDIR)/housecarl-ruleset.service \
|
|
$(DESTDIR)$(UNITDIR)/housecarl-backup.service $(DESTDIR)$(UNITDIR)/housecarl-backup.timer \
|
|
$(DESTDIR)$(BASHCOMPDIR)/hc $(DESTDIR)$(BASHCOMPDIR)/housecarld \
|
|
$(DESTDIR)$(SYSUSERSDIR)/housecarl.conf $(DESTDIR)$(TMPFILESDIR)/housecarl.conf
|
|
rm -rf $(DESTDIR)$(DOCDIR)
|
|
@echo "Kept /etc/housecarl, /var/lib/housecarl and /var/backups/housecarl. The ruleset in force stays until the next boot."
|
|
|
|
# Debian packages, built with dpkg-deb (no root needed); scripts/mkdeb.sh
|
|
# explains the layout.
|
|
deb: build
|
|
DEB_ARCH='$(DEB_ARCH)' DEB_VERSION='$(DEB_VERSION)' VERSION='$(VERSION)' \
|
|
LDFLAGS='$(LDFLAGS)' GOFLAGS='$(GOFLAGS)' scripts/mkdeb.sh
|
|
|
|
dist: build
|
|
for arch in amd64 arm64; do \
|
|
GOOS=linux GOARCH=$$arch go build $(GOFLAGS) -ldflags '$(LDFLAGS)' -o dist/housecarl-$(VERSION)-linux-$$arch/housecarld ./cmd/housecarld && \
|
|
GOOS=linux GOARCH=$$arch go build $(GOFLAGS) -ldflags '$(LDFLAGS)' -o dist/housecarl-$(VERSION)-linux-$$arch/hc ./cmd/hc && \
|
|
tar -C dist -czf dist/housecarl-$(VERSION)-linux-$$arch.tar.gz housecarl-$(VERSION)-linux-$$arch || exit 1; \
|
|
done
|
|
|
|
# The platforms cli-dist builds the CLI for.
|
|
CLI_PLATFORMS ?= linux/amd64 linux/arm64 darwin/amd64 darwin/arm64 windows/amd64 windows/arm64
|
|
|
|
cli-dist:
|
|
@mkdir -p dist
|
|
for p in $(CLI_PLATFORMS); do \
|
|
os=$${p%/*} arch=$${p#*/} ext=; [ $$os = windows ] && ext=.exe; \
|
|
GOOS=$$os GOARCH=$$arch go build $(GOFLAGS) -ldflags '$(LDFLAGS)' -o dist/housecarl-cli-$(VERSION)-$$os-$$arch$$ext ./cmd/hc || exit 1; \
|
|
done
|
|
|
|
clean:
|
|
rm -rf bin dist
|