Commit graph

20 commits

Author SHA1 Message Date
Ullrich Schäfer
c89c5798bb
Add packages/fit to journal and planner Dockerfiles
The deps stage was missing the COPY for packages/fit/package.json, so
@trails-cool/fit was absent from the workspace at install time and
@garmin/fitsdk could not be resolved during the journal build.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-01 08:10:15 +02:00
Ullrich Schäfer
2e5606458d Fix Planner/Journal healthchecks; auto-clean compose orphans
The compose healthcheck for both apps was `curl -sf http://localhost:.../health`,
but node:25-slim (Debian trixie-slim) ships neither curl nor wget, so
the check always reported the containers as `unhealthy` even while they
were happily serving 200s. Install curl in both Dockerfiles.

Separately, today's flagship BRouter cleanup (PR #297) left an orphan
`brouter` container behind because cd-infra's `docker compose up -d <list>`
doesn't pass `--remove-orphans`. I had to remove it by hand. Pass the
flag in both cd-infra and cd-apps so future service deletions clean up
on the next deploy.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-24 18:28:04 +02:00
Ullrich Schäfer
e16bd6de99
Ship app/jobs dir in the journal image
server.ts imports from ./app/jobs/demo-bot-generate.ts and ./app/jobs/
demo-bot-prune.ts, but the Dockerfile only COPYs app/lib. On prod the
worker crashes on boot with ERR_MODULE_NOT_FOUND and neither the
generate nor the prune cron gets scheduled. Add the jobs dir to the
runtime layer.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 10:53:22 +02:00
Ullrich Schäfer
01f002cc46
Stop Sentry on logout; fix E2E + Dockerfile for merged consolidation
- sentry.client.ts: add stopSentryClient() that awaits Sentry.close() so
  the SDK tears down when a user logs out. Hub methods become no-ops
  until initSentryClient() is called again on next login.
- root.tsx: call stopSentryClient() from the user-effect when user === null.
- Add sentry-config to journal + planner Dockerfiles (was missing after
  #237 introduced the new workspace package, breaking the Dockerfile
  package check).
- Footer: replace inner <nav> with <div> — nested nav landmarks broke
  the journal "nav bar shows on all pages" e2e test (two navigation
  roles on the page).
- e2e auth: tick the required ToS checkbox in the shared registerUser
  helper so passkey registration tests pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 00:40:36 +02:00
Ullrich Schäfer
8886764ec8 Remove premature app/jobs COPY from journal Dockerfile
The journal doesn't have an app/jobs directory yet — that will arrive
with the Komoot import PR. The COPY line was added prematurely and
breaks the Docker build.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 12:26:10 +02:00
Ullrich Schäfer
fe57a690c0 Fix Dockerfiles: add jobs package for pg-boss resolution
Both Dockerfiles were missing packages/jobs/package.json in the deps stage,
causing pnpm install to skip pg-boss. Also copy app/jobs directories into
the runtime stage so job handlers are available at runtime.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 12:13:09 +02:00
Ullrich Schäfer
3c172c1e56
Fix CD: add api and map-core packages to Journal Dockerfile
The journal now depends on @trails-cool/api which depends on zod.
The Dockerfile was missing these package.json files, causing pnpm
install to skip them and the build to fail.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 02:27:09 +02:00
Ullrich Schäfer
8631c8ff14
Fix journal Dockerfile: copy app/lib for custom server imports
The custom server.ts imports logger and metrics from app/lib/ which
are TypeScript source files run via --experimental-strip-types. The
runtime image needs these source files copied (same as planner).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 16:30:17 +02:00
Ullrich Schäfer
7994ea79f4
Fix overview error rate panel, add request metrics to journal
Dashboard: switch error rate panel from app-level http_request_duration
(never observed) to Caddy's caddy_http_response_duration_seconds_count.

Journal: add custom server.ts (matching planner pattern) that observes
http_request_duration_seconds on every request. Replaces react-router-serve
with a custom Node HTTP server that handles /api/health, /api/metrics,
static assets, and request timing. Removes redundant React Router routes
for health and metrics.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 16:20:18 +02:00
Ullrich Schäfer
48fa94e51b
Install ca-certificates in Docker base image for Sentry uploads
node:25-slim doesn't include CA certificates, causing sentry-cli
SSL errors: "unable to get local issuer certificate". Also removes
debug logging from previous troubleshooting.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 18:35:46 +01:00
Ullrich Schäfer
318f0c93c1
Strip trailing newline from Sentry auth token
The token file may have a trailing newline that causes sentry-cli
API requests to fail with "API request failed".

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 18:23:20 +01:00
Ullrich Schäfer
5d7b8c82e8
Fix Sentry build: disable telemetry, fix release version passing
- Disable Sentry Vite plugin telemetry (telemetry: false)
- Pass SENTRY_RELEASE as build-arg (not secret) since it's just the git sha
- Keep only SENTRY_AUTH_TOKEN as Docker secret

The release version was showing as *** because Docker secrets get masked
by GitHub Actions. Git sha is not sensitive — safe as a build arg.

The sourcemap warning from react-router is a known upstream issue (ships
without sourcemaps) and is harmless.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 18:18:00 +01:00
Ullrich Schäfer
6b147d04ec
Use pnpm.onlyBuiltDependencies for @sentry/cli and esbuild
pnpm approve-builds in Dockerfile ran after install, so the approval
wasn't picked up. Use onlyBuiltDependencies in package.json instead —
this is read during install and allows build scripts to run.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 18:07:25 +01:00
Ullrich Schäfer
5e200c8b62
Fix Sentry source map upload in Docker builds
- Approve @sentry/cli and esbuild build scripts so postinstall runs
- Use --mount=type=secret instead of ARG for SENTRY_AUTH_TOKEN
  (fixes Docker warning about secrets in build args)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 18:01:54 +01:00
Ullrich Schäfer
871ed81869
Fix Docker builds: corepack removed in Node 25
Node 25 no longer ships corepack. Replace corepack enable/prepare with
npm install -g pnpm.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 22:42:54 +01:00
dependabot[bot]
2df9172161 Bump node from 24-slim to 25-slim in /apps/journal
Bumps node from 24-slim to 25-slim.

---
updated-dependencies:
- dependency-name: node
  dependency-version: 25-slim
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-25 12:32:34 +01:00
Ullrich Schäfer
be3e69c10b
Security hardening: headers, scanning, Docker, firewall
- Caddy: HSTS, CSP, X-Frame-Options, nosniff, Referrer-Policy,
  Permissions-Policy on all responses
- Caddy: Block scanner paths (.env, .git, wp-config, etc.) with 403
- CI: Gitleaks secret scanning + pnpm audit for vulnerabilities
- Dependabot: Weekly npm + GitHub Actions + monthly Docker updates
- Docker: Non-root user in journal, planner, and brouter containers
- Server: UFW firewall (22/80/443 only) + fail2ban (8 IPs already banned)
- SECURITY.md: Vulnerability disclosure policy
- Privacy page: Security practices section added

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 09:58:12 +01:00
Ullrich Schäfer
091fc0a4bd
Add Sentry source maps and release tracking
- @sentry/vite-plugin uploads source maps during Docker build
- Release tagged with git SHA (SENTRY_RELEASE) on both client and server
- Environment set to production/development for filtering
- CD passes SENTRY_AUTH_TOKEN + SENTRY_RELEASE as Docker build args
- docker-compose passes SENTRY_RELEASE to runtime containers

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 02:43:28 +01:00
Ullrich Schäfer
0a09df27f4
Fix Docker builds: missing deps + bump actions
Dockerfiles:
- Add db package.json to deps stage
- Copy full node_modules (including app-level) to runtime
- Copy packages/ dir for workspace imports at runtime

CD workflow:
- docker/login-action v3 → v4
- docker/build-push-action v6 → v7

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 01:10:01 +01:00
Ullrich Schäfer
7908a518b1
Add infrastructure: Terraform, Docker Compose, BRouter, CD pipeline (#2)
Terraform:
- Hetzner CX22 server with Docker, firewall (80/443/22)
- SSH key and output for server IP

Docker Compose:
- Caddy reverse proxy (auto HTTPS)
- Journal and Planner app containers
- BRouter routing engine container
- PostgreSQL + PostGIS
- Garage S3 storage

BRouter:
- Dockerfile based on eclipse-temurin:11-jre
- Segment download script for Germany (4 tiles, ~750MB)

CD Pipeline:
- Build & push Docker images to ghcr.io on main push
- Deploy step commented out (enable when server provisioned)

Scripts:
- PostgreSQL daily backup with 14-day retention
- Dockerfiles for both apps (multi-stage builds)

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 13:32:01 +01:00