summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Dockerfile34
-rw-r--r--Makefile7
-rw-r--r--deploy/Dockerfile.cross12
-rw-r--r--deploy/cross-build.sh13
-rwxr-xr-xdeploy/docker-entrypoint.sh2
-rw-r--r--docs/DEPLOY.md29
-rwxr-xr-xscripts/deploy.sh52
7 files changed, 49 insertions, 100 deletions
diff --git a/Dockerfile b/Dockerfile
index b7fae08..65ce8df 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,35 +1,25 @@
# syntax=docker/dockerfile:1
-FROM debian:bookworm-slim AS build
+FROM alpine:3.24 AS build
# VERSION is declared after the expensive layers: the legacy builder
# invalidates every layer that follows a changed build argument.
-RUN apt-get update \
- && apt-get install -y --no-install-recommends build-essential libncurses-dev \
- libssl-dev \
- && rm -rf /var/lib/apt/lists/*
+RUN apk add --no-cache build-base openssl-dev
WORKDIR /src
COPY . .
ARG VERSION=0.1.0-dev
-# With .prebuilt/ the binaries are cross-compiled on the development machine
-# (see deploy/Dockerfile.cross); otherwise build and test from source.
-RUN if [ -x .prebuilt/bokfd ]; then \
- mkdir -p build && \
- cp .prebuilt/bokfd .prebuilt/bokfctl .prebuilt/bokftui build/; \
- else \
- make -j"$(nproc)" VERSION="$VERSION" && make test VERSION="$VERSION"; \
- fi
+RUN make -j"$(nproc)" backend VERSION="$VERSION" \
+ && make test-core VERSION="$VERSION" \
+ && strip build/bokfd build/bokfctl
-FROM debian:bookworm-slim AS runtime
-RUN apt-get update \
- && apt-get install -y --no-install-recommends libncursesw6 libssl3 \
- ca-certificates util-linux \
- && rm -rf /var/lib/apt/lists/* \
- && useradd --system --uid 10001 --home-dir /var/lib/bokfd \
- --shell /usr/sbin/nologin bokfd \
+# The runtime image carries the daemon and bokfctl only. The ncurses TUI is a
+# frontend: build it from source on the machine you sit at.
+FROM alpine:3.24 AS runtime
+RUN apk add --no-cache libssl3 ca-certificates util-linux \
+ && addgroup -S bokfd \
+ && adduser -S -D -H -u 10001 -G bokfd -s /sbin/nologin bokfd \
&& install -d -o bokfd -g bokfd /var/lib/bokfd /var/lib/bokfd/backup \
/var/lib/bokfd/export /var/lib/bokfd/certs /run/bokfd
-COPY --from=build /src/build/bokfd /src/build/bokfctl /src/build/bokftui \
- /usr/local/bin/
+COPY --from=build /src/build/bokfd /src/build/bokfctl /usr/local/bin/
COPY --from=build /src/data/bas_k2.csv /src/data/bas_k3.csv \
/usr/local/share/bokf/
COPY deploy/docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh
diff --git a/Makefile b/Makefile
index fee00c9..d67e92e 100644
--- a/Makefile
+++ b/Makefile
@@ -25,6 +25,8 @@ CORE_OBJ = $(patsubst %.c,$(BUILD)/%.o,$(CORE_SRC))
all: $(BUILD)/bokfd $(BUILD)/bokfctl $(BUILD)/bokftui
+backend: $(BUILD)/bokfd $(BUILD)/bokfctl
+
SSL_LIBS = -lssl -lcrypto
$(BUILD)/bokfd: $(BUILD)/src/bokfd.o $(CORE_OBJ) $(VENDOR_OBJ)
@@ -54,6 +56,9 @@ test: $(BUILD)/test_core $(BUILD)/test_tui
$(BUILD)/test_core
$(BUILD)/test_tui
+test-core: $(BUILD)/test_core
+ $(BUILD)/test_core
+
$(BUILD)/vendor/%.o: vendor/%.c
@mkdir -p $(dir $@)
$(CC) $(CFLAGS) $(DEPFLAGS) $(CPPFLAGS) $(DEFS) -w -c $< -o $@
@@ -84,4 +89,4 @@ install: all
clean:
rm -rf $(BUILD)
-.PHONY: all test install clean
+.PHONY: all backend test test-core install clean
diff --git a/deploy/Dockerfile.cross b/deploy/Dockerfile.cross
deleted file mode 100644
index 9a568cf..0000000
--- a/deploy/Dockerfile.cross
+++ /dev/null
@@ -1,12 +0,0 @@
-# Cross-compile the arm64 binaries on an amd64 host. The runtime image is
-# assembled later on the target host from the produced binaries.
-FROM debian:bookworm
-RUN dpkg --add-architecture arm64 \
- && apt-get update \
- && apt-get install -y --no-install-recommends \
- make ca-certificates gcc-aarch64-linux-gnu \
- libncurses-dev:arm64 libssl-dev:arm64 \
- && rm -rf /var/lib/apt/lists/*
-COPY cross-build.sh /usr/local/bin/cross-build
-RUN chmod 0755 /usr/local/bin/cross-build
-ENTRYPOINT ["/usr/local/bin/cross-build"]
diff --git a/deploy/cross-build.sh b/deploy/cross-build.sh
deleted file mode 100644
index 7c90b0f..0000000
--- a/deploy/cross-build.sh
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/bin/sh
-# Cross-compile bokfd/bokfctl/bokftui for aarch64. Expects the source
-# read-only at /src, writes the binaries to /out and takes the version from
-# $VERSION. Run through deploy/Dockerfile.cross.
-set -eu
-
-make -C /src -j"$(nproc)" BUILD=/tmp/build \
- CC=aarch64-linux-gnu-gcc \
- CFLAGS="-O2 -g -L/usr/lib/aarch64-linux-gnu" \
- VERSION="${VERSION:-0.1.0-dev}"
-
-mkdir -p /out
-cp /tmp/build/bokfd /tmp/build/bokfctl /tmp/build/bokftui /out/
diff --git a/deploy/docker-entrypoint.sh b/deploy/docker-entrypoint.sh
index 3cab4bd..d63f9dd 100755
--- a/deploy/docker-entrypoint.sh
+++ b/deploy/docker-entrypoint.sh
@@ -12,7 +12,7 @@ mkdir -p "$BOKFD_BACKUP_DIR" "$BOKFD_EXPORT_DIR" "$(dirname "$BOKFD_SOCKET")" \
chown -R bokfd:bokfd /var/lib/bokfd "$(dirname "$BOKFD_SOCKET")"
case "${1:-}" in
- bokfd | bokfctl | bokftui | /*)
+ bokfd | bokfctl | /*)
exec setpriv --reuid=bokfd --regid=bokfd --clear-groups "$@"
;;
*)
diff --git a/docs/DEPLOY.md b/docs/DEPLOY.md
index 7694add..ed105f8 100644
--- a/docs/DEPLOY.md
+++ b/docs/DEPLOY.md
@@ -56,8 +56,6 @@ Normal deploys build an image and recreate the container. While developing,
`scripts/deploy.sh --dev` skips the image entirely:
- the gate (`make` + `make test`) still runs locally,
-- on an architecture mismatch the binaries are cross-compiled here
- (`deploy/Dockerfile.cross`, ~20 s on a PC),
- the binaries are copied into the running container with `docker cp`,
- the daemon is reloaded with `SIGHUP`, which re-execs the binary in place
(in-memory sessions are lost, clients reconnect),
@@ -65,7 +63,9 @@ Normal deploys build an image and recreate the container. While developing,
No image is built and the container is not recreated; a later normal deploy
replaces the copied binaries. Use a descriptive tag, e.g.
-`scripts/deploy.sh --dev v0.2.0-rc1`.
+`scripts/deploy.sh --dev v0.2.0-rc1`. Hot reload requires the host to share
+the dev machine's architecture; on a mismatch `--dev` falls back to a full
+remote build.
## Deploying upgrades
@@ -87,11 +87,12 @@ The script:
5. on failure, puts the previous `BOKF_TAG` back and rolls back to the image
that is still loaded on the host.
-Cross-architecture builds are automatic: `uname -m` is compared over SSH and
-a mismatch switches to a remote build. Override with `BOKF_BUILD=local` or
-`BOKF_BUILD=remote` (also settable in `.env`). A remote build pulls the
-Debian base image inside a container, so the host needs outbound network
-access but still no toolchain.
+Architecture mismatches are automatic: `uname -m` is compared over SSH and a
+mismatch switches to a remote build of the same Alpine image (compiled inside
+the host's Docker, so the host still needs no toolchain). Override with
+`BOKF_BUILD=local` or `BOKF_BUILD=remote` (also settable in `.env`). The
+runtime image is Alpine and carries `bokfd` + `bokfctl` only; the ncurses TUI
+is a frontend and never shipped.
Tags are `git describe` output unless passed. Tag releases (`v*`) so rollback
and support have meaningful versions. The rollback image must still exist on
@@ -121,17 +122,19 @@ to `main`. The normal `scripts/deploy.sh` flow does not need any of this.
## Clients
-Run clients inside the container — no host toolchain needed:
+The image ships only the daemon and `bokfctl`, which covers the healthcheck
+and quick admin calls:
```sh
-docker compose exec bokfd bokftui # interactive TUI
docker compose exec -e BOKFD_PASSWORD='<pw>' bokfd \
bokfctl --user admin fiscal_year.list
```
-The clients honor `BOKFD_SOCKET`; a host-installed client can also point at
-`var/run/bokfd.sock`, but that file is owned by uid 10001, so the host user
-must be in that group (or use `sudo`).
+The TUI (`bokftui`) is a frontend: build it from source on the machine you sit
+at (`make bokftui`, needs libncursesw) and point it at the host, normally the
+TLS listener. A host-installed client can also point at `var/run/bokfd.sock`,
+but that file is owned by uid 10001, so the host user must be in that group
+(or use `sudo`).
The TUI remembers the server and user (never the password) in
`$XDG_CONFIG_HOME/bokf/tui.conf` (`~/.config/bokf/tui.conf`), written after
diff --git a/scripts/deploy.sh b/scripts/deploy.sh
index 79d731f..ad5350c 100755
--- a/scripts/deploy.sh
+++ b/scripts/deploy.sh
@@ -3,10 +3,10 @@
#
# scripts/deploy.sh [--dev] [tag]
#
-# Normal mode builds an image (cross-compiled on this machine when the target
-# architecture differs) and recreates the container. --dev skips the image:
-# it copies the fresh binaries into the running container and reloads the
-# daemon with SIGHUP, which re-execs them in place.
+# Normal mode builds an image and recreates the container, building natively on
+# the host when the target architecture differs. --dev (same architecture only)
+# skips the image: it copies the fresh binaries into the running container and
+# reloads the daemon with SIGHUP, which re-execs them in place.
#
# BOKF_HOST (user@host) and BOKF_REMOTE_DIR are read from the environment or
# from .env in the repository root. The host needs only Docker and Compose.
@@ -61,21 +61,6 @@ wait_healthy() {
return 1
}
-cross_build() {
- echo "deploy: cross-compiling $host_arch binaries on this machine"
- rm -rf .prebuilt
- mkdir -p .prebuilt
- docker build -q -f deploy/Dockerfile.cross -t bokf-cross deploy/ >/dev/null
- docker run --rm -e "VERSION=$TAG" -v "$PWD":/src:ro \
- -v "$PWD/.prebuilt":/out bokf-cross
- if command -v file >/dev/null 2>&1 &&
- ! file .prebuilt/bokfd | grep -q aarch64; then
- echo "deploy: cross-build produced no arm64 binary" >&2
- rm -rf .prebuilt
- exit 1
- fi
-}
-
echo "deploy: gate: build + tests"
make -j"$(nproc)"
make test
@@ -88,7 +73,7 @@ case "$BOKF_BUILD" in
if [ "$(uname -m)" = "$host_arch" ]; then
BOKF_BUILD=local
else
- echo "deploy: host is $host_arch, cross-building here"
+ echo "deploy: host is $host_arch, building the image on the host"
BOKF_BUILD=remote
fi
;;
@@ -101,32 +86,20 @@ case "$BOKF_BUILD" in
;;
esac
-if [ "$DEV" = 1 ]; then
+if [ "$DEV" = 1 ] && [ "$BOKF_BUILD" = local ]; then
if ! remote "test -f '$BOKF_REMOTE_DIR/var/db/bokfd.db'"; then
echo "deploy: no database on $BOKF_HOST; run a normal deploy first" >&2
exit 1
fi
- if [ "$BOKF_BUILD" = local ]; then
- prebin="build"
- echo "deploy: dev: using the locally built binaries"
- else
- cross_build
- prebin=".prebuilt"
- fi
- echo "deploy: dev: copying binaries into the running container"
+ echo "deploy: dev: copying the locally built binaries into the running container"
remote "mkdir -p /tmp/bokf-dev"
- scp -q "$prebin/bokfd" "$prebin/bokfctl" "$prebin/bokftui" \
- "$BOKF_HOST:/tmp/bokf-dev/"
+ scp -q build/bokfd build/bokfctl "$BOKF_HOST:/tmp/bokf-dev/"
remote "cd '$BOKF_REMOTE_DIR'
cid=\$(docker compose ps -q bokfd)
test -n \"\$cid\" || { echo 'deploy: bokfd is not running' >&2; exit 1; }
docker cp /tmp/bokf-dev/bokfd \"\$cid:/usr/local/bin/bokfd\"
docker cp /tmp/bokf-dev/bokfctl \"\$cid:/usr/local/bin/bokfctl\"
- docker cp /tmp/bokf-dev/bokftui \"\$cid:/usr/local/bin/bokftui\"
docker kill --signal=HUP \"\$cid\""
- if [ "$prebin" = ".prebuilt" ]; then
- rm -rf .prebuilt
- fi
ver=""
for _ in $(seq 1 15); do
ver="$(remote "cd '$BOKF_REMOTE_DIR' && docker exec \$(docker compose ps -q bokfd) bokfctl meta 2>/dev/null" |
@@ -143,20 +116,23 @@ if [ "$DEV" = 1 ]; then
exit 1
fi
+if [ "$DEV" = 1 ]; then
+ echo "deploy: dev: host is $host_arch, hot reload needs a matching" \
+ "architecture; doing a full deploy" >&2
+fi
+
if [ "$BOKF_BUILD" = local ]; then
echo "deploy: building image bokf:$TAG locally"
docker build --build-arg "VERSION=$TAG" -t "bokf:$TAG" .
echo "deploy: shipping image to $BOKF_HOST"
docker save "bokf:$TAG" | gzip | "${SSH[@]}" 'gunzip | docker load'
else
- cross_build
- echo "deploy: assembling image bokf:$TAG on $BOKF_HOST"
+ echo "deploy: assembling image bokf:$TAG natively on $BOKF_HOST"
tar -cf - \
--exclude=./.git --exclude=./build --exclude=./var --exclude=./.env \
--exclude='./*.se' --exclude='./*.db' --exclude='./*.db-wal' \
--exclude='./*.db-shm' --exclude=./docs . |
"${SSH[@]}" "docker build --build-arg 'VERSION=$TAG' -t 'bokf:$TAG' -"
- rm -rf .prebuilt
fi
remote "mkdir -p '$BOKF_REMOTE_DIR'"