jdsjkdjk
This commit is contained in:
@@ -48,8 +48,7 @@ jobs:
|
|||||||
echo "lean=$lean" >> "$GITHUB_OUTPUT"
|
echo "lean=$lean" >> "$GITHUB_OUTPUT"
|
||||||
echo "app=$app lean=$lean"
|
echo "app=$app lean=$lean"
|
||||||
|
|
||||||
# The wiki app itself. Its deploy (`compose pull && up -d`) also pulls
|
# The wiki app itself — its deploy step never touches the lean service.
|
||||||
# whatever mathew-lean:latest the registry holds — the lean job keeps it current.
|
|
||||||
deploy:
|
deploy:
|
||||||
runs-on: docker
|
runs-on: docker
|
||||||
needs: changes
|
needs: changes
|
||||||
@@ -91,13 +90,16 @@ jobs:
|
|||||||
scp docker-compose.yml deploy@${{ secrets.DEPLOY_HOST }}:/var/www/app/
|
scp docker-compose.yml deploy@${{ secrets.DEPLOY_HOST }}:/var/www/app/
|
||||||
scp nginx.conf deploy@${{ secrets.DEPLOY_HOST }}:/var/www/app/nginx.conf
|
scp nginx.conf deploy@${{ secrets.DEPLOY_HOST }}:/var/www/app/nginx.conf
|
||||||
|
|
||||||
|
# Scoped to the services this job owns: never pulls/builds lean from
|
||||||
|
# here (that would need the lean tag or lean/ sources on the host).
|
||||||
|
# deploy-lean.yml owns the lean service's pull and up.
|
||||||
- name: Deploy
|
- name: Deploy
|
||||||
run: |
|
run: |
|
||||||
ssh deploy@${{ secrets.DEPLOY_HOST }} << 'EOF'
|
ssh deploy@${{ secrets.DEPLOY_HOST }} << 'EOF'
|
||||||
echo "${{ secrets.REGISTRY_PASSWORD }}" | docker login git.aranroig.com -u "${{ secrets.REGISTRY_USER }}" --password-stdin
|
echo "${{ secrets.REGISTRY_PASSWORD }}" | docker login git.aranroig.com -u "${{ secrets.REGISTRY_USER }}" --password-stdin
|
||||||
cd /var/www/app/
|
cd /var/www/app/
|
||||||
docker compose pull
|
docker compose pull nginx frontend backend
|
||||||
docker compose up -d --remove-orphans
|
docker compose up -d frontend backend nginx
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
# The Lean editor (lean4web): multi-stage, heavy by nature (it fetches
|
# The Lean editor (lean4web): multi-stage, heavy by nature (it fetches
|
||||||
|
|||||||
11
AGENTS.md
11
AGENTS.md
@@ -43,7 +43,11 @@ Frontend API URL comes from `NUXT_PUBLIC_API_BASE`
|
|||||||
(default `http://localhost:5000`, read via `runtimeConfig.public.apiBase`). The Lean
|
(default `http://localhost:5000`, read via `runtimeConfig.public.apiBase`). The Lean
|
||||||
editor's address comes from `NUXT_PUBLIC_LEAN_URL` (default `http://localhost:8080`,
|
editor's address comes from `NUXT_PUBLIC_LEAN_URL` (default `http://localhost:8080`,
|
||||||
read via `runtimeConfig.public.leanUrl`) — on an HTTPS site it must be an https://
|
read via `runtimeConfig.public.leanUrl`) — on an HTTPS site it must be an https://
|
||||||
address too, or the browser blocks it (and the `wss://` derived from it) as mixed content (see `lean/README.md`). The frontend image
|
address too, or the browser blocks it (and the `wss://` derived from it) as mixed content (see `lean/README.md`). Production
|
||||||
|
passes `https://mathew.aranroig.com/api/lean`: nginx strips the `/api/lean` prefix and
|
||||||
|
proxies the rest to `lean:8080`, so the editor's websocket rides the site's own origin
|
||||||
|
instead of a public port 8080 (the compose service binds that port to the host's
|
||||||
|
loopback, for dev only). The frontend image
|
||||||
builds it empty: the browser then calls `/api` on its own origin, which nginx routes to
|
builds it empty: the browser then calls `/api` on its own origin, which nginx routes to
|
||||||
`backend:5000`, while the Nuxt server's own (SSR) `/api` calls go through a `routeRules` proxy
|
`backend:5000`, while the Nuxt server's own (SSR) `/api` calls go through a `routeRules` proxy
|
||||||
aimed at `NUXT_API_PROXY_TARGET` (`https://mathew.aranroig.com` baked in at image build — the
|
aimed at `NUXT_API_PROXY_TARGET` (`https://mathew.aranroig.com` baked in at image build — the
|
||||||
@@ -447,7 +451,10 @@ copy + an `APP_LANGUAGES` entry + the code in the backend's `SUPPORTED_LOCALES`.
|
|||||||
puts `#check` output; there is no `$/lean/plainMessages` anymore). Dev runs the server
|
puts `#check` output; there is no `$/lean/plainMessages` anymore). Dev runs the server
|
||||||
with `./dev.sh` (via docker compose; or lean4web natively: `NO_BWRAP=true PORT=8080 npm run prod`).
|
with `./dev.sh` (via docker compose; or lean4web natively: `NO_BWRAP=true PORT=8080 npm run prod`).
|
||||||
On an HTTPS site the address must be https (its `wss://` is derived from it — an `http://`
|
On an HTTPS site the address must be https (its `wss://` is derived from it — an `http://`
|
||||||
Lean server refuses an https wiki outright).
|
Lean server refuses an https wiki outright). Production uses
|
||||||
|
`https://mathew.aranroig.com/api/lean`, which `nginx.conf` proxies to `lean:8080`; the
|
||||||
|
bundled classic lean4web client still assumes it is served from a root, so behind
|
||||||
|
`/api/lean` the status bar's link opens a page whose assets 404.
|
||||||
A tool page like this is wired in step: `ToolPage`/`TOOL_PAGE_PATHS`
|
A tool page like this is wired in step: `ToolPage`/`TOOL_PAGE_PATHS`
|
||||||
(`utils/routes.ts`), the page file, `TOOL_LABEL_KEYS`, the `ToolPane` branch and spine
|
(`utils/routes.ts`), the page file, `TOOL_LABEL_KEYS`, the `ToolPane` branch and spine
|
||||||
glyph, the sidebar link, and the `PAGE_TOOLS` entry.
|
glyph, the sidebar link, and the `PAGE_TOOLS` entry.
|
||||||
|
|||||||
@@ -206,10 +206,11 @@ convenience only, and anyone holding it can mint a session.
|
|||||||
|
|
||||||
The stack also runs `lean` — the Lean server built from [`lean/`](lean/README.md),
|
The stack also runs `lean` — the Lean server built from [`lean/`](lean/README.md),
|
||||||
listening on `8080` with its websocket on that one port; the wiki's editor speaks the
|
listening on `8080` with its websocket on that one port; the wiki's editor speaks the
|
||||||
Lean language protocol to it directly. It keeps no
|
Lean language protocol to it directly. Production serves it through nginx at
|
||||||
|
`https://mathew.aranroig.com/api/lean` (`NUXT_PUBLIC_LEAN_URL`); the container's own
|
||||||
|
8080 is bound to the host loopback for development, not published. It keeps no
|
||||||
state of the wiki's, but it runs real Lean for every session, so plan the machine
|
state of the wiki's, but it runs real Lean for every session, so plan the machine
|
||||||
accordingly; point `NUXT_PUBLIC_LEAN_URL` at the address the browser reaches (https if
|
accordingly.
|
||||||
the site is https — the `wss://` is derived from it, and mixed content is blocked).
|
|
||||||
|
|
||||||
## Notes for contributors
|
## Notes for contributors
|
||||||
|
|
||||||
|
|||||||
@@ -15,10 +15,11 @@ services:
|
|||||||
frontend:
|
frontend:
|
||||||
image: git.aranroig.com/syndria98/mathew-frontend:latest
|
image: git.aranroig.com/syndria98/mathew-frontend:latest
|
||||||
environment:
|
environment:
|
||||||
# Where the browser finds the Lean editor server below (the wiki's
|
# Where the browser finds the Lean editor server: the site's own https
|
||||||
# /lean frames it). An https:// site needs an https:// address here,
|
# origin, proxied to the lean service by nginx (/api/lean). An https://
|
||||||
# or the browser refuses the frame — see lean/README.md.
|
# site needs an https:// address here — the websocket's wss:// is derived
|
||||||
NUXT_PUBLIC_LEAN_URL: ${NUXT_PUBLIC_LEAN_URL:-http://mathew.aranroig.com:8080}
|
# from it, and an http:// server would be refused as mixed content.
|
||||||
|
NUXT_PUBLIC_LEAN_URL: ${NUXT_PUBLIC_LEAN_URL:-https://mathew.aranroig.com/api/lean}
|
||||||
restart: always
|
restart: always
|
||||||
|
|
||||||
# The Lean editor (lean4web) — its own server, since it runs a real Lean
|
# The Lean editor (lean4web) — its own server, since it runs a real Lean
|
||||||
@@ -33,8 +34,11 @@ services:
|
|||||||
# args:
|
# args:
|
||||||
# BAKE_MATHLIB: "false"
|
# BAKE_MATHLIB: "false"
|
||||||
image: git.aranroig.com/syndria98/mathew-lean:latest
|
image: git.aranroig.com/syndria98/mathew-lean:latest
|
||||||
|
# Reachable only from this host (dev's frontend) and nginx; the public way
|
||||||
|
# in is https://mathew.aranroig.com/api/lean. Publishing the port would
|
||||||
|
# hand anyone on the internet a Lean shell — see lean/README.md.
|
||||||
ports:
|
ports:
|
||||||
- "8080:8080"
|
- "127.0.0.1:8080:8080"
|
||||||
restart: always
|
restart: always
|
||||||
# Only with BAKE_MATHLIB: "false" above:
|
# Only with BAKE_MATHLIB: "false" above:
|
||||||
# volumes:
|
# volumes:
|
||||||
|
|||||||
@@ -61,13 +61,16 @@ The `BAKE_MATHLIB=false` image still ships the pinned elan toolchain, but not
|
|||||||
the project's `.lake`: the entrypoint notices a fresh volume and fills it once
|
the project's `.lake`: the entrypoint notices a fresh volume and fills it once
|
||||||
at first start — `lake update` fetches the sources pinned in
|
at first start — `lake update` fetches the sources pinned in
|
||||||
`lake-manifest.json`, Mathlib's post-update hook downloads the matching
|
`lake-manifest.json`, Mathlib's post-update hook downloads the matching
|
||||||
precompiled cache, `lake build` writes the project's own module. Expect ~10
|
precompiled cache, `lake build` writes the project's own module. The manifest
|
||||||
minutes and a few hundred MB of download; restarts after that are instant,
|
`lake update` resolved gets saved into the volume and re-applied at every
|
||||||
and **image rebuilds never touch Mathlib again** (the volume stays). The
|
start, so the packages in the volume and the manifest in the image never tell
|
||||||
trade: the cache must survive on the host, first start needs network, and it
|
different stories (an unsynced pair would try to re-fetch Mathlib from GitHub
|
||||||
redoes once if you recreate with a clean volume — hence the default staying
|
at each session). Expect ~10 minutes and a few hundred MB of download;
|
||||||
`BAKE_MATHLIB=true`. The commented blocks in `docker-compose.yml` wire this
|
restarts after that are instant, and **image rebuilds never touch Mathlib
|
||||||
up for the production stack.
|
again** (the volume stays). The trade: the cache must survive on the host,
|
||||||
|
first start needs network, and it redoes once if you recreate with a clean
|
||||||
|
volume — hence the default staying `BAKE_MATHLIB=true`. The commented blocks
|
||||||
|
in `docker-compose.yml` wire this up for the production stack.
|
||||||
|
|
||||||
## The protocol the wiki's client speaks
|
## The protocol the wiki's client speaks
|
||||||
|
|
||||||
@@ -138,7 +141,12 @@ browser will refuse the editor's `ws://` connection to an `http://` server
|
|||||||
(mixed content). Serve the
|
(mixed content). Serve the
|
||||||
Lean server over HTTPS — either its own `SSL_CRT_FILE`/`SSL_KEY_FILE`, or a
|
Lean server over HTTPS — either its own `SSL_CRT_FILE`/`SSL_KEY_FILE`, or a
|
||||||
reverse proxy in front (websocket upgrade on the same path) — and point
|
reverse proxy in front (websocket upgrade on the same path) — and point
|
||||||
`NUXT_PUBLIC_LEAN_URL` at the `https://` address.
|
`NUXT_PUBLIC_LEAN_URL` at the `https://` address. The production stack does
|
||||||
|
the latter: nginx serves it at `https://mathew.aranroig.com/api/lean` and
|
||||||
|
proxies to `lean:8080`; the compose service publishes 8080 on loopback only
|
||||||
|
(dev's frontend), so the public way in is that one address. Note that the
|
||||||
|
bundled classic client expects to sit at the server root — under `/api/lean`
|
||||||
|
its assets resolve against the wiki and 404; the wiki's own editor is fine.
|
||||||
|
|
||||||
## Updating
|
## Updating
|
||||||
|
|
||||||
|
|||||||
@@ -8,19 +8,33 @@
|
|||||||
# "Keeping Mathlib out of the image"), the project's .lake is meant to be a
|
# "Keeping Mathlib out of the image"), the project's .lake is meant to be a
|
||||||
# volume: a fresh one gets filled once, at first start, so Mathlib's ~7GB of
|
# volume: a fresh one gets filled once, at first start, so Mathlib's ~7GB of
|
||||||
# compiled cache never travels through the registry.
|
# compiled cache never travels through the registry.
|
||||||
|
#
|
||||||
|
# The manifest pairing matters: `lake update` advances the packages in .lake
|
||||||
|
# AND rewrites lake-manifest.json — but the manifest sits in the (ephemeral)
|
||||||
|
# image while the packages sit in the (permanent) volume. Without help, a new
|
||||||
|
# container would find manifest ≠ volume and try to re-sync Mathlib from
|
||||||
|
# GitHub at every session. So the first start saves the manifest it resolved
|
||||||
|
# into the volume, and every later start puts that saved copy over the
|
||||||
|
# image's — manifest and packages always tell the same story.
|
||||||
set -eu
|
set -eu
|
||||||
|
|
||||||
PROJECT=/opt/lean4web/Projects/MathlibDemo
|
PROJECT=/opt/lean4web/Projects/MathlibDemo
|
||||||
|
MANIFEST="$PROJECT/lake-manifest.json"
|
||||||
|
SAVED_MANIFEST="$PROJECT/.lake/mathew-lake-manifest.json"
|
||||||
|
|
||||||
|
if [ -f "$SAVED_MANIFEST" ]; then
|
||||||
|
cp "$SAVED_MANIFEST" "$MANIFEST"
|
||||||
|
fi
|
||||||
|
|
||||||
if [ ! -f "$PROJECT/.lake/build/lib/lean/MathlibDemo.olean" ]; then
|
if [ ! -f "$PROJECT/.lake/build/lib/lean/MathlibDemo.olean" ]; then
|
||||||
echo "[mathew-lean] $PROJECT/.lake holds no built Mathlib — fetching it once (expect ~10 minutes)"
|
echo "[mathew-lean] $PROJECT/.lake holds no built Mathlib — fetching it once (expect ~10 minutes)"
|
||||||
cd "$PROJECT"
|
|
||||||
# lake update pulls the sources pinned in lake-manifest.json, and Mathlib's
|
# lake update pulls the sources pinned in lake-manifest.json, and Mathlib's
|
||||||
# post-update hook fetches the matching precompiled cache; lake build then
|
# post-update hook fetches the matching precompiled cache; lake build then
|
||||||
# only writes the project's own module. The image's pinned toolchain
|
# only writes the project's own module. The image's pinned toolchain
|
||||||
# (elan) stays as it is — no lean-toolchain re-curl, no surprise downloads.
|
# (elan) stays as it is — no lean-toolchain re-curl, no surprise downloads.
|
||||||
lake update -R
|
# (subshell: its cd must not leak into the server's working directory)
|
||||||
lake build
|
( cd "$PROJECT" && lake update -R && lake build )
|
||||||
|
cp "$MANIFEST" "$SAVED_MANIFEST"
|
||||||
echo "[mathew-lean] Mathlib ready"
|
echo "[mathew-lean] Mathlib ready"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
31
nginx.conf
31
nginx.conf
@@ -10,6 +10,37 @@ http {
|
|||||||
listen 80;
|
listen 80;
|
||||||
server_name _;
|
server_name _;
|
||||||
|
|
||||||
|
# The Lean editor server, at the site's own https origin instead of a
|
||||||
|
# bare :8080 (NUXT_PUBLIC_LEAN_URL points here). Longest-prefix wins,
|
||||||
|
# so this beats /api below. lean4web serves from its root, so the
|
||||||
|
# /api/lean prefix is stripped before proxying: the wiki's client asks
|
||||||
|
# for /api/lean/websocket/<project> and /api/lean/api/projects.
|
||||||
|
location = /api/lean {
|
||||||
|
# relative Location: the outer TLS proxy's scheme/host stay the
|
||||||
|
# browser's (an absolute redirect would say http://)
|
||||||
|
absolute_redirect off;
|
||||||
|
return 301 /api/lean/;
|
||||||
|
}
|
||||||
|
|
||||||
|
location /api/lean/ {
|
||||||
|
set $lean_upstream lean:8080;
|
||||||
|
# `break` ends the rewrite phase, so the variable above is set first
|
||||||
|
rewrite ^/api/lean/(.*)$ /$1 break;
|
||||||
|
proxy_pass http://$lean_upstream;
|
||||||
|
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
proxy_set_header Connection "upgrade";
|
||||||
|
# A Lean session can sit idle while the reader thinks; the 60s
|
||||||
|
# default would drop its websocket.
|
||||||
|
proxy_read_timeout 1h;
|
||||||
|
proxy_send_timeout 1h;
|
||||||
|
}
|
||||||
|
|
||||||
# Api Requests ("/api" without a trailing slash must land here too,
|
# Api Requests ("/api" without a trailing slash must land here too,
|
||||||
# or it falls through to the frontend and loops through its SSR proxy)
|
# or it falls through to the frontend and loops through its SSR proxy)
|
||||||
location /api {
|
location /api {
|
||||||
|
|||||||
Reference in New Issue
Block a user