summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Dockerfile10
-rw-r--r--clients/bokfweb.c26
-rw-r--r--deploy/cross-build.sh6
-rw-r--r--docs/DEPLOY.md4
-rw-r--r--docs/STATE.md6
5 files changed, 49 insertions, 3 deletions
diff --git a/Dockerfile b/Dockerfile
index a46e15e..5102a42 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -23,7 +23,9 @@ RUN if [ -x .prebuilt/bokfd ]; then \
VERSION="$VERSION" \
&& make test-core VERSION="$VERSION"; \
fi \
- && strip build/bokfd build/bokfctl build/bokftui build/bokfweb
+ && strip build/bokfd build/bokfctl build/bokftui build/bokfweb \
+ && mkdir -p build/locale \
+ && if [ -d .prebuilt/locale ]; then cp -a .prebuilt/locale/. build/locale/; fi
# The web frontend (image bokf-web, `--target web`): Caddy for routing, the
# bokfweb login gate, ttyd and bokftui in web mode. It reaches bokfd only
@@ -36,9 +38,13 @@ RUN apk add --no-cache ca-certificates caddy ttyd ncurses-terminfo-base \
&& addgroup -S bokfd \
&& adduser -S -D -H -u 10001 -G bokfd -s /sbin/nologin bokfd
COPY --from=build /src/build/bokftui /src/build/bokfweb /usr/local/bin/
+# glibc locale data for the cross-built static binaries (empty for a native
+# musl build, which needs none); the check fails the build without UTF-8
+COPY --from=build /src/build/locale/ /usr/lib/locale/
COPY deploy/bokftui-web deploy/web-entrypoint.sh /usr/local/bin/
COPY deploy/Caddyfile /etc/caddy/Caddyfile
-RUN chmod 0755 /usr/local/bin/bokftui-web /usr/local/bin/web-entrypoint.sh
+RUN chmod 0755 /usr/local/bin/bokftui-web /usr/local/bin/web-entrypoint.sh \
+ && LANG=C.UTF-8 bokfweb --check-locale
ENV BOKFD_SOCKET=/run/bokfd/bokfd.sock \
TERM=xterm-256color \
LANG=C.UTF-8
diff --git a/clients/bokfweb.c b/clients/bokfweb.c
index d04e2d6..cc19826 100644
--- a/clients/bokfweb.c
+++ b/clients/bokfweb.c
@@ -15,6 +15,7 @@
directly: only Caddy and the wrapper in the same container talk to it. */
#include <arpa/inet.h>
#include <errno.h>
+#include <locale.h>
#include <netinet/in.h>
#include <signal.h>
#include <stdio.h>
@@ -23,6 +24,7 @@
#include <sys/socket.h>
#include <sys/time.h>
#include <unistd.h>
+#include <wchar.h>
#include "client.h"
#include "log.h"
@@ -446,8 +448,30 @@ static void serve(int cfd, struct gate *g)
memset(buf, 0, n); /* the body may hold a password */
}
-int main(void)
+/* `bokfweb --check-locale`, run while the web image is built: bokftui in
+ the same image needs a UTF-8 locale for åäö, and a statically linked
+ glibc finds none unless its locale data is installed. Exits 1 without. */
+static int check_locale(void)
{
+ const char *l = setlocale(LC_ALL, "");
+ wchar_t w = 0;
+ mbstate_t st;
+ memset(&st, 0, sizeof st);
+ size_t n = mbrtowc(&w, "\xc3\xa5", 2, &st); /* å */
+ if (!l || n != 2 || w != 0xE5) {
+ fprintf(stderr, "bokfweb: no UTF-8 locale (setlocale: %s); bokftui "
+ "would show no åäö\n",
+ l ? l : "failed");
+ return 1;
+ }
+ printf("locale ok: %s\n", l);
+ return 0;
+}
+
+int main(int argc, char **argv)
+{
+ if (argc > 1 && strcmp(argv[1], "--check-locale") == 0)
+ return check_locale();
signal(SIGPIPE, SIG_IGN);
const char *lvl = getenv("BOKFWEB_LOG_LEVEL");
log_set_level(lvl ? log_level_from_name(lvl) : LOG_INFO);
diff --git a/deploy/cross-build.sh b/deploy/cross-build.sh
index 54a2929..75c181c 100644
--- a/deploy/cross-build.sh
+++ b/deploy/cross-build.sh
@@ -18,3 +18,9 @@ make -C /src -j"$(nproc)" BUILD=/tmp/build \
mkdir -p /out
cp /tmp/build/bokfd /tmp/build/bokfctl /tmp/build/bokftui \
/tmp/build/bokfweb /out/
+
+# A static glibc program loads its locale data from /usr/lib/locale, which
+# the Alpine runtime does not have: without C.utf8 setlocale() fails and
+# the TUI shows no åäö. Ship Debian's C.utf8 with the binaries.
+mkdir -p /out/locale
+cp -a /usr/lib/locale/C.utf8 /out/locale/
diff --git a/docs/DEPLOY.md b/docs/DEPLOY.md
index 99b7661..008093f 100644
--- a/docs/DEPLOY.md
+++ b/docs/DEPLOY.md
@@ -276,6 +276,10 @@ browser ──443──▶ host Caddy (TLS) ──▶ 127.0.0.1:8790 bokf-web c
Port 443 is already forwarded for the other sites. The container
publishes 8790 on the host's loopback only, so it is unreachable until
that block exists.
+- **UTF-8**: the cross-built binaries are static glibc, which needs its own
+ locale data; the image ships Debian's `C.utf8` in `/usr/lib/locale` and
+ the build runs `bokfweb --check-locale`, so an image whose TUI could not
+ show åäö fails to build instead of shipping.
- `BOKF_WEB_MAX_SESSIONS` (default 20) caps concurrent terminals.
`docker compose logs web` shows logins, logouts and failed attempts
(never passwords).
diff --git a/docs/STATE.md b/docs/STATE.md
index c33d80e..10286fb 100644
--- a/docs/STATE.md
+++ b/docs/STATE.md
@@ -14,6 +14,12 @@ unit tests and the docs consistency check.
## Resume here (2026-09-23)
+- **Web åäö fix (2026-09-23, `v0.1.70`)**: the web TUI showed no åäö on
+ the NAS: the cross-built static glibc bokftui found no locale data in
+ the Alpine image (setlocale failed, åäö were invalid bytes). The image
+ now ships Debian's `C.utf8` and the build checks it
+ (`bokfweb --check-locale`). Local amd64 tests missed it because the
+ native build uses musl.
- **Web frontend (2026-09-23, live since `v0.1.69`: https://bokf.makandra.eu/web)**:
image `bokf-web` (Caddy routing + `bokfweb` login gate + ttyd +
bokftui in web mode) as compose service `web` on `127.0.0.1:8790`; see