From 9d6dc616115e08e3484081502ec9946f4d163cc3 Mon Sep 17 00:00:00 2001 From: Seongmin Lee Date: Thu, 17 Sep 2026 23:59:21 +0900 Subject: [PATCH] localinfra: add pocket Signed-off-by: Seongmin Lee --- docker-compose.yml | 24 +++++++++++++++++++ localinfra/Caddyfile | 6 +++++ localinfra/pocket.Dockerfile | 46 ++++++++++++++++++++++++++++++++++++ localinfra/pocket.patch | 32 +++++++++++++++++++++++++ localinfra/readme.md | 2 ++ 5 files changed, 110 insertions(+) create mode 100644 localinfra/pocket.Dockerfile create mode 100644 localinfra/pocket.patch diff --git a/docker-compose.yml b/docker-compose.yml index c7369fc1a..fef18e015 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -550,6 +550,29 @@ services: condition: service_started networks: [tngl] + pocket: + build: + context: . + dockerfile: localinfra/pocket.Dockerfile + restart: unless-stopped + environment: + POCKET_DB: /var/lib/pocket/prefs.sqlite3 + POCKET_DOMAIN: pocket.tngl.boltless.dev + POCKET_SLINGSHOT_URL: http://bobbin:8090 + RUST_LOG: info + volumes: + - pocket-data:/var/lib/pocket + - ./localinfra/certs/root.crt:/usr/local/share/ca-certificates/caddy.crt:ro + healthcheck: + test: ["CMD", "wget", "-qO-", "http://localhost:3000/.well-known/did.json"] + interval: 5s + timeout: 2s + retries: 15 + start_period: 10s + ports: + - "3100:3000" + networks: [tngl] + web: build: context: . @@ -759,6 +782,7 @@ volumes: tempo-data: loki-data: hydrant-data: + pocket-data: bobbin-cargo: bobbin-target: web-node-modules: diff --git a/localinfra/Caddyfile b/localinfra/Caddyfile index 0dd5aa781..d103bf2a6 100644 --- a/localinfra/Caddyfile +++ b/localinfra/Caddyfile @@ -132,6 +132,12 @@ deliberi.tngl.boltless.dev { } +# pocket - private data store +pocket.tngl.boltless.dev { + tls internal + reverse_proxy pocket:3000 +} + # bobbin (read appview / xrpc) bobbin.tngl.boltless.dev { tls internal diff --git a/localinfra/pocket.Dockerfile b/localinfra/pocket.Dockerfile new file mode 100644 index 000000000..4613b3049 --- /dev/null +++ b/localinfra/pocket.Dockerfile @@ -0,0 +1,46 @@ +# Development only. Not for production use. + +FROM docker.io/library/alpine:3.22 AS source +RUN apk add --no-cache git patch +WORKDIR /src +RUN git clone https://tangled.org/microcosm.blue/microcosm-rs . && \ + git checkout 3137b07d5268812d2de0f3177664be92196994d8 +# the patch's context is pinned to that commit, so it fails loudly on a bump +COPY localinfra/pocket.patch ./ +RUN patch -p1 < pocket.patch + +FROM docker.io/library/rust:1.96-slim-trixie AS builder +RUN apt-get update && apt-get install -y --no-install-recommends \ + ca-certificates pkg-config perl make cmake clang mold git libssl-dev libsqlite3-dev \ + && rm -rf /var/lib/apt/lists/* +ENV RUSTFLAGS="-C linker=clang -C link-arg=-fuse-ld=mold" +WORKDIR /src +COPY --from=source /src ./ +RUN cargo build --release --bin pocket --package pocket +RUN strip target/release/pocket + +FROM docker.io/library/debian:trixie-slim +RUN apt-get update && apt-get install -y --no-install-recommends \ + ca-certificates wget libssl3 libsqlite3-0 \ + && rm -rf /var/lib/apt/lists/* +WORKDIR /app +COPY --from=builder /src/target/release/pocket /usr/local/bin/pocket +# StaticFileEndpoint::new("./static/index.html") resolves against the working directory +COPY --from=builder /src/pocket/static /app/static + +ENV POCKET_DB=/var/lib/pocket/prefs.sqlite3 +ENV POCKET_DOMAIN=pocket.tngl.boltless.dev + +COPY <<'EOF' /usr/local/bin/pocket-entrypoint.sh +#!/bin/sh +set -eu +if [ -f /usr/local/share/ca-certificates/caddy.crt ]; then update-ca-certificates; fi +mkdir -p "$(dirname "$POCKET_DB")" +# Storage::init runs a bare `create table`, so it only succeeds on an empty db +[ -f "$POCKET_DB" ] || pocket --init-db --db "$POCKET_DB" +exec pocket --db "$POCKET_DB" --domain "$POCKET_DOMAIN" +EOF +RUN chmod +x /usr/local/bin/pocket-entrypoint.sh + +EXPOSE 3000 +ENTRYPOINT ["/usr/local/bin/pocket-entrypoint.sh"] diff --git a/localinfra/pocket.patch b/localinfra/pocket.patch new file mode 100644 index 000000000..f1e0c4084 --- /dev/null +++ b/localinfra/pocket.patch @@ -0,0 +1,32 @@ +Local-infra patches against microcosm.blue/microcosm-rs @ 3137b07. + +1. pocket binds its listener to loopback, which nothing outside the container + can reach. Drop this hunk once pocket takes a --bind of its own. +2. pocket hardcodes did resolution to the public slingshot, which cannot see + the local plc. Makes the host an env knob (POCKET_SLINGSHOT_URL) with + upstream's url as the default, so the image still works unconfigured. + +--- a/pocket/src/server.rs ++++ b/pocket/src/server.rs +@@ -260,6 +260,6 @@ + .with(CatchPanic::new()) + .with(Tracing); + +- let listener = TcpListener::bind("127.0.0.1:3000"); ++ let listener = TcpListener::bind("0.0.0.0:3000"); + Server::new(listener).name("pocket").run(app).await.unwrap(); + } +--- a/pocket/src/token.rs ++++ b/pocket/src/token.rs +@@ -71,8 +71,11 @@ + )); + } + +- let endpoint = +- "https://slingshot.microcosm.blue/xrpc/com.bad-example.identity.resolveMiniDoc"; ++ let slingshot = std::env::var("POCKET_SLINGSHOT_URL") ++ .unwrap_or_else(|_| "https://slingshot.microcosm.blue".to_string()); ++ let endpoint = format!("{slingshot}/xrpc/blue.microcosm.identity.resolveMiniDoc"); + let doc: MiniDoc = self + .client + .get(format!("{endpoint}?identifier={untrusted_did}")) diff --git a/localinfra/readme.md b/localinfra/readme.md index 1e2437e2f..e17c5f614 100644 --- a/localinfra/readme.md +++ b/localinfra/readme.md @@ -26,6 +26,8 @@ To make that work: - pdsls () - bobbin (, host `:8090`) - hydrant indexer + record/identity resolver feeding bobbin; jetstream +- [pocket](https://tangled.org/microcosm.blue/microcosm-rs) preferences store + (, host `:3100`). - camo () and avatar (), the workers from `camo/` and `avatar/` under wrangler. avatar resolves against the local plc, so it serves real -- 2.51.2