Browse Source

bug-fix build

imwald
Silberengel 2 weeks ago
parent
commit
f7eeeead7b
  1. 2
      PROXY_SETUP.md
  2. 30
      docker-compose.prod.yml
  3. 4
      package-lock.json
  4. 2
      package.json
  5. 30
      scripts/README-deploy.md
  6. 20
      scripts/build-and-push-prod.sh
  7. 12
      scripts/stack-remote.sh
  8. 2
      src/lib/read-aloud.ts

2
PROXY_SETUP.md

@ -185,7 +185,7 @@ VITE_LANGUAGE_TOOL_URL=/api/languagetool @@ -185,7 +185,7 @@ VITE_LANGUAGE_TOOL_URL=/api/languagetool
VITE_TRANSLATE_URL=/api/translate
```
**Production:** `docker compose -f docker-compose.prod.yml --profile editor-tools up -d languagetool libretranslate` publishes **127.0.0.1:8010** and **127.0.0.1:5000** (loopback-only). Proxy those paths from Apache/nginx to the SPA origin, and bake the client with `LANGUAGE_TOOL_URL=/api/languagetool` and `TRANSLATE_URL=/api/translate` when running `./scripts/build-and-push-prod.sh`.
**Production:** `docker compose -f docker-compose.prod.yml pull && docker compose -f docker-compose.prod.yml up -d` starts the full stack (including LanguageTool on **127.0.0.1:8010** and LibreTranslate on **127.0.0.1:5000**). Run `bash scripts/ensure-libretranslate-dirs.sh` once on the server for LibreTranslate volume permissions. Proxy `/api/languagetool` and `/api/translate` from Apache/nginx to those ports, and bake the client with `LANGUAGE_TOOL_URL=/api/languagetool` and `TRANSLATE_URL=/api/translate` when running `./scripts/build-and-push-prod.sh`.
**Notes:** LanguageTool’s JVM image often needs **~1–2GiB** RAM. LibreTranslate **does not listen on port 5000 until models are ready**; without **`LT_LOAD_ONLY`** it may pull **many gigabytes** first, so the Vite proxy can show **`ECONNRESET` on `/translate`** while booting. Compose defaults **`LT_LOAD_ONLY`** to **ten** widely used codes (**en, de, es, fr, it, pt, ru, zh, ja, ar** — see `libretranslate` in `docker-compose.dev.yml`). Override with **`LT_LOAD_ONLY`** to add or remove codes; first start downloads packs for every listed code. **`LT_UPDATE_MODELS`** defaults to **`true`** so if you **expand** `LT_LOAD_ONLY` later, a **recreated** container still **installs missing** Argos packages into the bind-mounted `.local-libretranslate` tree (otherwise an older en/de-only cache sticks). Set **`LT_UPDATE_MODELS=false`** after everything is installed if you want faster routine restarts. Models are stored under **`.local-libretranslate/share`** and **`.local-libretranslate/cache`** (gitignored) with **bind mounts** so they survive **`docker compose down`**, image updates, and container recreate. **`scripts/ensure-libretranslate-dirs.sh`** (run automatically by **`npm run dev:all`**, **`npm run stack:remote`**, **`npm run docker:editor-tools`**, etc.) creates those dirs and **`chown`s them to UID 1032** via a short **Alpine** container so the LibreTranslate user can write. If you start **`libretranslate` by hand**, run **`npm run docker:prep-libretranslate`** once first. First download can still take **several minutes**; use **`docker logs -f jumble-libretranslate`** until **`curl http://127.0.0.1:5000/languages`** returns JSON. If logs show **`Cannot update models`** / **`Unavailable language codes: …`**, one bad token in **`LT_LOAD_ONLY` aborts the whole install** (you stay on whatever was already on disk, often en/de only). **Norwegian** must be **`nb`** (Bokmål), not ISO **`no`**. After you shrink **`LT_LOAD_ONLY`**, run **`npm run docker:prune-libretranslate-packages`** to remove leftover Argos package dirs under **`.local-libretranslate/share/argos-translate/packages`** (and unused **MiniSBD** `.onnx` files); the script briefly stops **`jumble-libretranslate`** or **`imwald-libretranslate`**. Override codes with **`LT_LOAD_ONLY=…`** on the same command if they differ from the compose default.

30
docker-compose.prod.yml

@ -1,6 +1,7 @@ @@ -1,6 +1,7 @@
# Minimal compose for running the published image (e.g. on remote server).
# Full stack (jumble + NIP-66 + og-proxy + Piper + LanguageTool + LibreTranslate): npm run stack:remote
# Usage (app only): docker compose -f docker-compose.prod.yml pull && docker compose -f docker-compose.prod.yml up -d
# Production stack: jumble + NIP-66 monitor + og-proxy + Wyoming Piper + Piper HTTP proxy + LanguageTool + LibreTranslate.
# Remote: docker compose -f docker-compose.prod.yml pull && docker compose -f docker-compose.prod.yml up -d
# First-time LibreTranslate bind mounts: bash scripts/ensure-libretranslate-dirs.sh (see scripts/README-deploy.md).
# Images built/pushed by ./scripts/build-and-push-prod.sh (app, monitor, piper-tts-proxy); others pull from Hub.
#
# Apache (unchanged on your host) should keep (order: specific paths before catch-all /):
# ProxyPass /sites/ http://127.0.0.1:8090/sites/
@ -14,10 +15,8 @@ @@ -14,10 +15,8 @@
# - Cron service `jumble-nip66-monitor` (Imwald NIP-66 monitor image) uses NIP66_MONITOR_NSEC to publish 30166/10166; nsec never goes to the client.
# - Set NIP66_MONITOR_NPUB (npub1... derived from the same key) so the relay info page shows the monitor's avatar and handle in the NIP-66 liveliness section.
#
# Optional editor tools (LanguageTool + LibreTranslate): profile `editor-tools`
# docker compose -f docker-compose.prod.yml --profile editor-tools up -d languagetool libretranslate
# Then Apache (or nginx) must proxy same-origin paths baked into the SPA, e.g. /api/languagetool → http://127.0.0.1:8010
# and /api/translate → http://127.0.0.1:5000. Build the app image with:
# Apache (or nginx) must proxy same-origin paths baked into the SPA, e.g. /api/languagetool → http://127.0.0.1:8010
# and /api/translate → http://127.0.0.1:5000. Build the app with:
# LANGUAGE_TOOL_URL=/api/languagetool TRANSLATE_URL=/api/translate ./scripts/build-and-push-prod.sh
services:
@ -68,7 +67,6 @@ services: @@ -68,7 +67,6 @@ services:
languagetool:
image: silviof/docker-languagetool:latest
profiles: ['editor-tools']
container_name: imwald-languagetool
ports:
- '127.0.0.1:8010:8010'
@ -80,7 +78,6 @@ services: @@ -80,7 +78,6 @@ services:
libretranslate:
image: libretranslate/libretranslate:latest
profiles: ['editor-tools']
container_name: imwald-libretranslate
ports:
- '127.0.0.1:5000:5000'
@ -97,12 +94,11 @@ services: @@ -97,12 +94,11 @@ services:
limits:
memory: 2048M
# --- profile `stack`: OG proxy + Piper (Apache → 8090 / 9876). One command: npm run stack:remote ---
# First-party images: silberengel/* (override with OG_PROXY_IMAGE / WYOMING_PIPER_IMAGE / PIPER_HTTP_PROXY_IMAGE).
# OG proxy + Piper (Apache → 8090 / 9876). Piper HTTP image: silberengel/imwald-piper-tts-proxy (see build-and-push-prod.sh).
og-proxy:
image: ${OG_PROXY_IMAGE:-silberengel/wikistr:latest-og-proxy}
profiles: ['stack']
container_name: og-proxy
# Distinct name so `docker compose` does not assume an unrelated `og-proxy` container belongs to this project.
container_name: imwald-og-proxy
dns:
- 1.1.1.1
- 8.8.8.8
@ -119,8 +115,8 @@ services: @@ -119,8 +115,8 @@ services:
piper-wyoming:
image: ${WYOMING_PIPER_IMAGE:-silberengel/wyoming-piper:latest}
profiles: ['stack']
container_name: piper-tts
# Distinct from ad-hoc stacks named `piper-tts`; Piper HTTP proxy reaches this service as `piper-wyoming`.
container_name: imwald-piper-wyoming
command:
- --voice
- en_US-lessac-medium
@ -135,11 +131,7 @@ services: @@ -135,11 +131,7 @@ services:
restart: unless-stopped
piper-tts-proxy:
profiles: ['stack']
container_name: imwald-piper-tts-proxy
build:
context: .
dockerfile: services/piper-tts-proxy/Dockerfile
image: ${PIPER_HTTP_PROXY_IMAGE:-silberengel/imwald-piper-tts-proxy:latest}
environment:
NODE_ENV: production

4
package-lock.json generated

@ -1,12 +1,12 @@ @@ -1,12 +1,12 @@
{
"name": "imwald",
"version": "23.0.0",
"version": "23.0.1",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "imwald",
"version": "23.0.0",
"version": "23.0.1",
"license": "MIT",
"dependencies": {
"@asciidoctor/core": "^3.0.4",

2
package.json

@ -1,6 +1,6 @@ @@ -1,6 +1,6 @@
{
"name": "imwald",
"version": "23.0.0",
"version": "23.0.1",
"description": "Imwald — a user-friendly Nostr client focused on relay feed browsing, publications, and relay discovery",
"private": true,
"type": "module",

30
scripts/README-deploy.md

@ -11,12 +11,13 @@ docker login # once, if needed @@ -11,12 +11,13 @@ docker login # once, if needed
./scripts/build-and-push-prod.sh
```
This builds both images and pushes two tags each (`latest` and the version from `package.json`, e.g. `17.0.0`):
This builds and pushes **three** images, each with `latest` and the version from `package.json` (e.g. `17.0.0`):
- **Main app (Imwald):** `silberengel/imwald-jumble`
- **NIP-66 monitor:** `silberengel/imwald-jumble-nip66-monitor`
- **NIP-66 monitor:** `silberengel/imwald-jumble-nip66-monitor`
- **Piper HTTP proxy:** `silberengel/imwald-piper-tts-proxy` (Wyoming Piper still pulls `silberengel/wyoming-piper` and `silberengel/wikistr` on the server.)
Registry paths keep the historical `imwald-jumble` name; retagging to e.g. `silberengel/imwald` is optional and requires updating `docker-compose.prod.yml` and pull scripts.
Registry paths keep the historical `imwald-jumble` name; retagging is optional and requires updating `docker-compose.prod.yml`.
## Remote server: one-time setup
@ -36,17 +37,38 @@ This builds both images and pushes two tags each (`latest` and the version from @@ -36,17 +37,38 @@ This builds both images and pushes two tags each (`latest` and the version from
NIP66_MONITOR_NPUB=npub1...
```
4. **Once per machine** (LibreTranslate bind mounts need UID 1032 on the host dirs):
```bash
bash scripts/ensure-libretranslate-dirs.sh
```
## Remote server: pull and run
Use a **current** `docker-compose.prod.yml` from this repo (`git pull` in the clone). If `docker compose pull` only lists two images, the file is outdated and **LanguageTool / LibreTranslate will never start**.
After you’ve pushed from local:
```bash
cd jumble
git pull
bash scripts/ensure-libretranslate-dirs.sh # once per host
docker compose -f docker-compose.prod.yml pull
docker compose -f docker-compose.prod.yml up -d
```
The app is on **port 8089**. Both services use `:latest`; to pin a version, set the image in `docker-compose.prod.yml` to e.g. `silberengel/imwald-jumble:17.0.0` and `silberengel/imwald-jumble-nip66-monitor:17.0.0`.
That starts the **full** stack in `docker-compose.prod.yml` (app, NIP-66 monitor, OG proxy, Piper, LanguageTool, LibreTranslate). The SPA is on **port 8089**; see `docker-compose.prod.yml` header for Apache paths.
**Grammar + translate in the browser** also require the SPA to be built with API paths baked in, for example:
`LANGUAGE_TOOL_URL=/api/languagetool TRANSLATE_URL=/api/translate ./scripts/build-and-push-prod.sh`
and Apache (or nginx) must proxy `/api/languagetool``127.0.0.1:8010` and `/api/translate``127.0.0.1:5000`.
**Shared host:** if you already run another `og-proxy` on `127.0.0.0.1:8090` or another Wyoming Piper on the same ports, `docker compose up -d` can fail with a port or name conflict. Either stop the duplicates or start only the pieces you need, e.g. `docker compose up -d jumble jumble-nip66-monitor languagetool libretranslate` (and point `PIPER_TTS_HOST` / Apache at your existing Piper stack if applicable).
Equivalent one-liner: `npm run stack:remote`
Images default to `:latest`; to pin a version, set image tags in `docker-compose.prod.yml`.
## Useful commands (server)

20
scripts/build-and-push-prod.sh

@ -1,6 +1,10 @@ @@ -1,6 +1,10 @@
#!/usr/bin/env bash
# Build main app and NIP-66 monitor images locally; push to silberengel/imwald-jumble and silberengel/imwald-jumble-nip66-monitor as :latest and :<version from package.json>.
# Build and push first-party production images (same tags :latest and :<version from package.json>):
# - silberengel/imwald-jumble (SPA)
# - silberengel/imwald-jumble-nip66-monitor
# - silberengel/imwald-piper-tts-proxy (HTTP → Wyoming Piper; matches docker-compose.prod.yml)
# Then create git tag v<version> and push it.
# Other compose services (og-proxy, wyoming-piper, LanguageTool, LibreTranslate) pull from Hub on the server.
# Run from repo root. Requires: docker, docker login, git.
#
# Optional env:
@ -19,6 +23,7 @@ VERSION="$(node -p "require('./package.json').version")" @@ -19,6 +23,7 @@ VERSION="$(node -p "require('./package.json').version")"
GIT_TAG="v${VERSION}"
IMAGE_APP="silberengel/imwald-jumble"
IMAGE_MONITOR="silberengel/imwald-jumble-nip66-monitor"
IMAGE_PIPER_PROXY="silberengel/imwald-piper-tts-proxy"
# OG / link-preview HTML: VITE_PROXY_SERVER is baked into the client bundle at image build time (not runtime).
# Use public origin only (no /proxy path): web.service builds <origin>/sites/?url=…
@ -39,11 +44,18 @@ docker build \ @@ -39,11 +44,18 @@ docker build \
echo "Building NIP-66 monitor (version: $VERSION)"
docker build -t "$IMAGE_MONITOR:latest" -t "$IMAGE_MONITOR:$VERSION" ./nip66-cron
echo "Pushing $IMAGE_APP and $IMAGE_MONITOR"
echo "Building Piper HTTP TTS proxy (version: $VERSION)"
docker build \
-f services/piper-tts-proxy/Dockerfile \
-t "$IMAGE_PIPER_PROXY:latest" -t "$IMAGE_PIPER_PROXY:$VERSION" .
echo "Pushing $IMAGE_APP, $IMAGE_MONITOR, and $IMAGE_PIPER_PROXY"
docker push "$IMAGE_APP:latest"
docker push "$IMAGE_APP:$VERSION"
docker push "$IMAGE_MONITOR:latest"
docker push "$IMAGE_MONITOR:$VERSION"
docker push "$IMAGE_PIPER_PROXY:latest"
docker push "$IMAGE_PIPER_PROXY:$VERSION"
# --- Git tag (matches package.json version) ---
if git rev-parse "$GIT_TAG" >/dev/null 2>&1; then
@ -62,5 +74,5 @@ git tag -a "$GIT_TAG" -m "Release $GIT_TAG" @@ -62,5 +74,5 @@ git tag -a "$GIT_TAG" -m "Release $GIT_TAG"
echo "Pushing tag $GIT_TAG to origin"
git push origin "$GIT_TAG"
echo "Done. On the server: docker compose -f docker-compose.prod.yml pull && docker compose -f docker-compose.prod.yml up -d"
echo "Optional LanguageTool + LibreTranslate: docker compose -f docker-compose.prod.yml --profile editor-tools up -d languagetool libretranslate (see PROXY_SETUP.md)"
echo "Done. On the server (repo clone): bash scripts/ensure-libretranslate-dirs.sh # once, for LibreTranslate volume permissions"
echo " docker compose -f docker-compose.prod.yml pull && docker compose -f docker-compose.prod.yml up -d"

12
scripts/stack-remote.sh

@ -1,14 +1,12 @@ @@ -1,14 +1,12 @@
#!/usr/bin/env bash
# One remote command from repo clone: silberengel/imwald-jumble + nip66 + wikistr og-proxy + wyoming-piper +
# imwald-piper-tts-proxy (built here; push silberengel/imwald-piper-tts-proxy:latest to Hub for pull-only hosts) +
# LanguageTool + LibreTranslate. Apache → 8089 / 8090 / 9876.
# One remote command from repo clone: full docker-compose.prod.yml stack (pull + up).
# Same as: ensure-libretranslate-dirs.sh && docker compose -f docker-compose.prod.yml pull && docker compose -f docker-compose.prod.yml up -d
# First-party images must be pushed from ./scripts/build-and-push-prod.sh before pull will get new app/monitor/piper-proxy revisions.
set -euo pipefail
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
cd "$ROOT"
bash "$ROOT/scripts/ensure-libretranslate-dirs.sh"
COMPOSE=(docker compose -f docker-compose.prod.yml --profile stack --profile editor-tools)
# Pull Hub images only; piper-tts-proxy is built from this repo (push silberengel/imwald-piper-tts-proxy:latest when ready).
"${COMPOSE[@]}" pull jumble jumble-nip66-monitor og-proxy piper-wyoming languagetool libretranslate
"${COMPOSE[@]}" build piper-tts-proxy
COMPOSE=(docker compose -f docker-compose.prod.yml)
"${COMPOSE[@]}" pull
"${COMPOSE[@]}" up -d
echo "[stack:remote] jumble :8089 | og-proxy :8090 | piper HTTP :9876 | LT :8010 | translate :5000"

2
src/lib/read-aloud.ts

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
import { ExtendedKind, READ_ALOUD_TTS_URL } from '@/constants'
import i18n, { LocalizedLanguageNames, normalizeToSupportedAppLanguage, type TLanguage } from '@/i18n'
import i18n, { LocalizedLanguageNames, normalizeToSupportedAppLanguage } from '@/i18n'
import { getNoteTranslation } from '@/lib/note-translation-display'
import {
getPiperVoiceForChosenLanguage,

Loading…
Cancel
Save