diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..06b68af --- /dev/null +++ b/Dockerfile @@ -0,0 +1,38 @@ +# Self-hosted static build for the obsidian-vault-platform's Tier-A +# "obsidian-web serverless/OPFS" (plans/obsidian-vault-platform/SPEC.md §2/§4 +# in grepleria/grepleria-configs). Reuses the SAME static-asset pipeline the +# Cloudflare Workers deployment uses (src/deployments/cloudflare/), because +# that's the ONLY deployment mode with NO server-side vault storage — vaults +# live entirely in browser OPFS (see src/deployments/cloudflare/README.md). +# That property is load-bearing: SPEC's storm table forbids a shared +# server-backed vault folder across 2+ browsers, and OPFS-only sidesteps the +# question by construction (nothing server-side to share). +# +# The Node.js server deployment (src/runtime-server/server/) is NOT used +# here -- it defaults new vaults to server-backed storage ('server' vault +# type, real filesystem), which is the Tier-B (single-writer Coder +# workspace) shape, not Tier-A (SPEC §1/§3). +# +# Stage 1 does the actual "proprietary renderer" pull: the official Obsidian +# Android APK, extracted + build-time-patched into vendor/obsidian-mobile/ +# (scripts/update-obsidian-mobile.js) -- never committed to this repo +# (gitignored), never redistributed; it's baked into THIS image only, which +# is then pushed to the org's own artifact-keeper registry, never a public one. +FROM node:22-alpine AS builder +RUN apk add --no-cache unzip bash +WORKDIR /src +COPY . . +# Pulls + extracts + patches the Obsidian Android APK bundle into +# vendor/obsidian-mobile/ (network access to GitHub releases required). +RUN node scripts/update-obsidian-mobile.js +# build-assets.sh only shells out to `node -e` (built-ins) -- no `npm install` +# needed (that would also pull in wrangler, a deploy-only devDependency this +# self-hosted build never uses). Also pulls the LiveSync plugin release +# (network access to GitHub releases; WARNs and continues if unreachable -- +# see build-assets.sh, this is not a hard build dependency). +RUN bash src/deployments/cloudflare/scripts/build-assets.sh + +FROM nginx:1.27-alpine AS runtime +COPY --from=builder /src/.tmp/deployments/cloudflare/public /usr/share/nginx/html +COPY nginx.conf /etc/nginx/conf.d/default.conf +EXPOSE 80 diff --git a/nginx.conf b/nginx.conf new file mode 100644 index 0000000..6d6ff59 --- /dev/null +++ b/nginx.conf @@ -0,0 +1,25 @@ +# Self-hosted static server for the OPFS-only build (see Dockerfile header). +# Mirrors src/deployments/cloudflare/index.js's routing: /starter and +# /vault/ are client-side routes read from location.pathname by +# boot.js, not real files -- they must get the app shell back as a 200 (a +# redirect would lose the deep link). try_files with an /index.html +# fallback covers that generically for any unmatched path, which is a +# superset of the Worker's explicit /starter + /vault/* check. +server { + listen 80; + server_name _; + root /usr/share/nginx/html; + index index.html; + + location / { + try_files $uri $uri/ /index.html; + } + + # Known gap (mirrors the upstream CF deployment's own "Known gaps" #4): + # no self-hosted equivalent of /api/proxy-request exists here yet (the + # CORS proxy that lets the in-app community-plugin browser fetch + # GitHub/obsidian.md). Community-plugin install-from-UI will fail with a + # CORS error until src/deployments/cloudflare/proxy-worker.js is ported + # to an nginx/Node route. Not a blocker for Tier-A's pre-configured + # infra vaults (obsidian-runner seeds obsidian-livesync directly). +}