Skip to content

Technical guide · Overview

Page status: Active

NutsNews Backend Service Baseline

This documents the read-only service baseline attestation for ramideltoro/nutsnews-backend and 65.75.201.18.

Visual overview

Primary diagram

System map

This documents the read-only service baseline attestation for ramideltoro/nutsnews-backend and 65.75.201.18.

Render the repository-owned system map when you need it.

Diagram is not rendered yet.

View as text
NutsNews Backend Service Baseline

This documents the read-only service baseline attestation for ramideltoro/nutsnews-backend and 65.75.201.18.

flowchart TD
  accTitle: NutsNews Backend Service Baseline
  accDescr {
    This documents the read-only service baseline attestation for ramideltoro/nutsnews-backend and 65.75.201.18.
  }
  A[Run SSH attestation on backend host] --> B[Capture public listeners and failed systemd units]
  B --> C[Load docs/backend-service-baseline.json]
  C --> D[Validate no public services outside approved policy]
  D --> E{Violations found?}
  E -->|yes| F[Fail baseline and report blockers]
  E -->|no| G[Publish baseline and decision status]
  F --> H[Block protected drift actions until reviewed]
  G --> I[Expose baseline for re-attestation review]
  I --> J[Re-run attestation after protected changes or drift]

NutsNews Backend Service Baseline

Fullscreen diagram view.

This documents the read-only service baseline attestation for ramideltoro/nutsnews-backend and 65.75.201.18.

Captured over read-only SSH on 2026-07-16:

host: backend
ssh user: rami
kernel: 7.0.0-14-generic
failed systemd units: 0
cloud-init status: done

Current public listeners:

AddressPortPurpose
0.0.0.022/tcpSSH
[::]22/tcpSSH

Current local listeners are system DNS and chrony only.

Not deployed at attestation time:

  • Docker Engine
  • Docker Compose
  • Caddy
  • backend app service
  • public HTTP/HTTPS
  • PostgreSQL
  • Redis or Valkey
  • search service
  • ops dashboard

The backend repo includes a machine-readable inventory:

docs/backend-service-baseline.json

Validation:

Terminal window
python3 scripts/validate_service_baseline.py

The validator fails if the baseline lists a public TCP port other than SSH or any failed systemd units.

Current expected public exposure is SSH only.

HTTP/HTTPS must remain closed until a reviewed reverse-proxy/routing PR enables Caddy, health checks, TLS strategy, and compatible UFW policy. Database, cache, search, and dashboard ports must not be public.

Backend issue #27 records a no-install decision for Redis/Valkey.

Simple Summary:

NutsNews is not adding Redis or Valkey right now because there is no current job that needs it.

Intermediate Summary:

The app currently uses Supabase, Next.js caching, CDN cache headers, and route-level anti-abuse behavior. The inspected app dependency list does not include a Redis or Valkey client, and the backend host has no deployed queue, cache, job-progress, session, or retry-buffer workload. Adding Redis/Valkey now would add another service to operate without a concrete reliability or product benefit.

Expert Summary:

The backend repo now has docs/backend-redis-valkey-decision.json, runbooks/REDIS_VALKEY_DECISION.md, and scripts/validate_redis_valkey_decision.py. The validator fails if the service baseline stops marking Redis/Valkey as not deployed while the decision still says do_not_install_now. Any future Redis/Valkey implementation must be private-only, authenticated or equivalently access-bound, resource-capped, observable, and covered by persistence/backup/fallback rules before protected apply.

Backend issue #29 records a no-install decision for a dedicated search daemon.

Simple Summary:

NutsNews is not adding Meilisearch, Typesense, OpenSearch, or Elasticsearch to the backend server right now because the app already has working Postgres search.

Intermediate Summary:

The current app has a Supabase/Postgres full-text search migration with a generated tsvector, a GIN index, and public.search_articles. The /api/search route already bounds query inputs, uses a runtime feature flag, and emits public search cache headers. A separate search daemon would add always-on memory, disk, backup, rebuild, and observability work before there is measured need.

Expert Summary:

The backend repo now has docs/backend-search-service-decision.json, runbooks/SEARCH_SERVICE_DECISION.md, and scripts/validate_search_service_decision.py. The validator fails if the service baseline stops marking search service as not deployed while the decision still says keep_postgres_full_text_search_now. A future search service requires private-only binding, resource sizing, rebuild or snapshot strategy, health checks, low-cardinality observability, app fallback, and a concrete ramideltoro/nutsnews integration issue before protected apply.

References used for resource expectations:

Backend issue #28 records the plan for replacing Supabase only after a non-production replacement is proven.

Simple Summary:

NutsNews is not moving off Supabase yet. A new database has to be tested, backed up, restorable, and safe to roll back before it can hold production data.

Intermediate Summary:

The app currently uses Supabase/PostgREST-style APIs with anon and service-role keys, not a direct PostgreSQL driver. A bare self-hosted PostgreSQL server would not be a drop-in replacement. The plan keeps one production writer, forbids public database ports, requires a PostgREST-compatible layer or app rewrite, and sets future targets of 15-minute RPO and 4-hour RTO only after WAL/PITR and restore drills pass.

Expert Summary:

The backend repo now has docs/backend-postgres-replacement-plan.json, runbooks/POSTGRES_REPLACEMENT_PLAN.md, and scripts/validate_postgres_replacement_plan.py. The validator fails if the service baseline stops marking PostgreSQL as not deployed while the decision still says keep_supabase_until_replacement_is_proven. The plan maps Supabase tables/functions, REST/PostgREST, anon/service-role behavior, RLS/grants, Auth, Storage, Realtime, Edge Functions, full-text search, and backups before any production install or cutover.

Update the attestation after protected apply changes listeners or services, after Docker/Caddy/app/database/cache/search/dashboard work lands, or whenever read-only audit finds drift.