Skip to content

Conversation

davidhne
Copy link
Member

Closes #14

What and why

Gets the database and backend actually running on the group VM
(it2810-13.idi.ntnu.no), and protects the data import against the Kaggle
datasets changing or disappearing later.

  • backend/scripts/import.ts: records the SHA-256 of both Kaggle zips and
    the expected recipe/photo counts (17698 / 5653), and fails loudly instead
    of silently importing different data if either ever changes.
  • deploy/apache/project2.conf: proxies /project2/graphql to the backend
    on port 3001 (so the browser never needs that port, and there's no CORS),
    and serves data/images/ with a one-year cache lifetime.
  • deploy/systemd/t13-backend.service: runs the backend as a systemd
    service, restarting on crash or reboot.
  • README.md: a full "Deployment" section, including every gotcha we
    actually hit standing this up (see below) — the goal is that the next
    person (or a grader) can reproduce this without guessing.

The VM itself is now live with this setup: Postgres role + t13 database,
Node via nvm, the repo cloned, npm run import run (17698 recipes, 5653
with photo — matches the reference run exactly), the backend running as
t13-backend.service, and Apache proxying/serving as above.

Decisions worth flagging to a grader, found while actually bringing the
VM up rather than guessed in advance:

  • The VM's apt install nodejs package is built without TypeScript
    type-stripping support (amaro), which this backend's no-build-step
    design depends on (node_use_amaro is false). Switched to an
    nvm-installed Node instead, as the issue's acceptance criteria already
    allowed ("NodeSource or nvm").
  • git clone on the VM needs an SSH key registered on git.ntnu.no. A
    repo-scoped read-only deploy key needs admin on the repo, which wasn't
    available at the time, so we used a personal key on an existing
    collaborator's account instead, scoped to just that one clone via
    core.sshCommand. Documented both options in the README; a proper deploy
    key is a straightforward follow-up once someone with admin is around.
  • The t13 database already existed, owned by a different teammate's role —
    Postgres 15+'s default (no implicit CREATE on public for non-owners)
    blocked the import until we granted it explicitly.
  • The backend's default DATABASE_URL connects over TCP, which needs a
    Postgres password the deploy role doesn't have. Switched to the local
    unix socket (peer-authenticated) in the VM's backend/.env.
  • A bare home directory (drwx------) blocks Apache from traversing into
    it to reach data/images/, giving 403 even though the files underneath
    are world-readable. Fixed with chmod o+x ~ (traverse only, not list).

How to test

  1. npm run lint && npm run format:check && npm run typecheck && npm test
    — all pass.
  2. Checksum guard: corrupt the recorded hash for one dataset in
    backend/scripts/import.ts and run npm run import — it should throw
    checksum mismatch before touching the database. Revert and it imports
    normally. (Verified locally against the real downloaded datasets; also
    verified the count guard the same way.)
  3. Live on the VM:
    • curl http://it2810-13.idi.ntnu.no/project2/ → 200
    • curl http://it2810-13.idi.ntnu.no/project2/recipes/6 → 200 (SPA
      fallback, not Apache's 404)
    • curl -X POST http://it2810-13.idi.ntnu.no/project2/graphql -H 'Content-Type: application/json' -d '{"query":"{ recipes(limit:1){ totalCount } }"}'
      → {"data":{"recipes":{"totalCount":17698}}}
    • curl -I http://it2810-13.idi.ntnu.no/project2/images/6.webp → 200,
      Cache-Control: max-age=31536000
    • ssh it2810-13.idi.ntnu.no systemctl is-active t13-backend → active,
      is-enabled → enabled

AI usage

Done together with Claude Code, in an interactive session rather than
unattended: Claude wrote the import.ts checksum/count checks, the Apache
and systemd config files, and the README section, and drove the actual VM
setup over SSH (surveying the VM's existing state, running npm ci/
npm run import, installing nvm, diagnosing the three deployment gotchas
listed above). Every sudo-gated step (package installs, the Postgres
grant, installing the systemd unit and Apache config, enabling Apache
modules) and the git.ntnu.no deploy-key sign-in were run by the human
directly on the VM/in the browser, not by Claude, and reported back for the
next step. The human reviewed each generated file and the final README
before this PR, and verified the live endpoints above itself.

Checklist

  • Linked issue, labels and milestone set
  • Lint and tests pass locally
  • Tests added/updated for new logic (checksum/count guard verified
    against the real datasets, see "How to test")
  • Accessible (keyboard, labels, contrast, screen reader) if UI changed
    — n/a, no UI changes
  • README/CLAUDE.md updated if setup, commands or decisions changed
  • No secrets or personal data committed

dhn06 and others added 4 commits October 15, 2026 11:21
…proxy

- import.ts now records the SHA-256 of both Kaggle zips and the expected
  recipe/photo counts (17698 / 5653), and fails loudly instead of silently
  importing different data if either changes
- deploy/apache/project2.conf: proxy /project2/graphql to the backend and
  serve data/images/ with long cache headers
- deploy/systemd/t13-backend.service: run the backend as a systemd service
- README: Deployment section documenting the remaining manual VM steps
  (Postgres role, Node/npm, cloning, systemd, Apache)

Part of #14; the VM provisioning itself (sudo-gated steps) is still manual.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…port)

The VM's apt `nodejs` package is built without amaro (TypeScript
type-stripping), which the no-build-step backend depends on, and has no
npm either. Verified on the VM: node_use_amaro is false for apt's 22.22.1,
true for nvm's 22.23.3. Point the systemd unit and README at an
nvm-installed Node instead.

Also corrects the clone step: a repo-scoped deploy key needs admin on the
repo, which isn't always available, so document the personal-SSH-key
fallback actually used to bootstrap the VM clone.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
All discovered while actually bringing the VM up end-to-end:
- shared t13 database owned by another role -> GRANT ALL ON SCHEMA public
- default DATABASE_URL needs a password this role doesn't have -> connect
  over the unix socket instead (peer auth)
- a bare home directory blocks Apache from traversing into data/images/
  (403) even though the files underneath are readable -> chmod o+x ~

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@davidhne davidhne requested a review from a team as a code owner October 15, 2026 09:56
@davidhne davidhne added this to the Innlevering 2 milestone Oct 15, 2026
@davidhne davidhne added backend GraphQL server database Schema, data import, queries vm VM, Apache, deployment chore Tooling, config, housekeeping labels Oct 15, 2026
@davidhne davidhne self-assigned this Oct 15, 2026
Copy link
Member

@jonhella jonhella left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@jonhella jonhella merged commit 8970b4c into main Oct 15, 2026
Sign in to join this conversation on GitHub.
Labels
backend GraphQL server chore Tooling, config, housekeeping database Schema, data import, queries vm VM, Apache, deployment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Set up the VM: PostgreSQL, Node, data import and backend service
2 participants