Commit Graph

13 Commits

Author SHA1 Message Date
roof 238db60702 feat: secure build phase 1 — cosign cell-side image verification (warn default) + Dockerfile validation
Unit Tests / test (push) Successful in 13m28s
- config/cosign/cosign.pub: public verification key committed to repo (safe);
  cosign private key lives in /home/roof/.pic-secrets/ and is NEVER committed
- api/config_manager.py: image_verification config block (modes: off|warn|enforce,
  default: warn) so existing deployments are unaffected until images are signed
- api/service_composer.py: cosign verify before pull/up; enforce aborts the
  operation, warn logs and proceeds, off skips entirely; also fixes the prior
  unsafe proceed-on-pull-failure path
- api/service_store_manager.py: store-image digest requirement (warn default,
  reject under enforce)
- api/Dockerfile: cosign binary copied from the official cosign image
- docker-compose.yml: config/cosign/ bind-mounted into cell-api container
- install.sh: ensure/verify bundled cosign pubkey on new cell installs
- api/manifest_validator.py: validate_build_context() — Dockerfile lint
- tests: full coverage for config modes, composer verify paths, store digest
  guard, and validate_build_context

Verification defaults to warn so nothing breaks in production until images are
signed (phase 2). Private key stored outside git at /home/roof/.pic-secrets/.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 03:53:47 -04:00
roof 5cb8ebe430 fix: quiet installer output for non-technical users; Makefile/compose cleanup
Unit Tests / test (push) Successful in 12m18s
The installer dumped ~200 lines of docker layer spam, a leaked apt error,
and obsolete version warnings, alarming for non-technical users.

install.sh:
- Clean, progress-only default output; full log to /var/log/pic-install.log
- Admin password still surfaced on stdout at the end
- PIC_DEBUG=1 / --debug flag restores verbose output
- On error, prints the last 20 lines from the log file

Makefile:
- start / update / start-core compose invocations get @ prefix to suppress
  command echo, plus --quiet-pull to kill layer-download spam

docker-compose.yml + docker-compose.services.yml:
- Removed obsolete `version: '3.3'` top-level key (triggers deprecation
  warning with current Docker Compose)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 13:01:48 -04:00
roof a9c7235347 fix: install chrony for host NTP and enable pic.service on cold install
Unit Tests / test (push) Successful in 12m0s
Root-cause fix for ACME failures caused by clock drift breaking TOTP
during DDNS registration: install and start chrony (all supported package
managers) before the setup wizard runs, so the host clock is accurate from
day one.

Also enables and starts the pic systemd unit at the end of a cold install —
previously the unit file was written but never activated, so the stack would
not survive a reboot without a manual `systemctl enable --now pic`.

Makefile uninstall hardened: `disable --now` instead of bare `disable` so the
running unit is stopped before the unit file is removed; daemon-reload called
afterwards to flush the stale unit; and all lingering cell-* containers
(tor/sshuttle/redsocks/store services) are now force-removed so subsequent
reinstalls start from a clean Docker state.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 09:38:03 -04:00
roof 4a42ff5dcc wizard: move all config to /setup; install.sh is infrastructure-only
Unit Tests / test (push) Successful in 15m41s
install.sh no longer prompts for anything. It installs packages (with sudo),
creates the system user, clones the repo, and runs 'make install' — all as
the invoking user. Only package installs and system-level ops use sudo.
All folder creation happens under the user's own account, no chown needed.

/setup wizard gains the missing validation that was previously in install.sh:
- Step 1: checks pic.ngo name availability via backend (non-blocking)
- Step 4: 'Verify token' button for Cloudflare and DuckDNS tokens,
  validated server-side through new /api/setup/validate steps

API changes (routes/setup.py):
- validate step 'pic_ngo_available': proxy check to ddns.pic.ngo
- validate step 'cloudflare_token': verify via Cloudflare tokens API
- validate step 'duckdns_token': verify via DuckDNS update endpoint

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-25 16:07:56 -04:00
roof 2d842abe5b installer: restore cell identity prompts and domain setup
Unit Tests / test (push) Successful in 15m39s
Reverts 8d1ef39. The installer must collect cell name, domain mode, and
provider tokens before 'make install' so that DDNS registration,
availability checks, and Caddy TLS can be configured at first boot.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-25 15:01:32 -04:00
roof 8d1ef39ca5 installer: remove cell identity prompts — wizard handles all config
Unit Tests / test (push) Successful in 15m44s
The /setup wizard now collects cell name, domain mode, credentials,
password, services, and timezone.  The bash installer's job is just
infrastructure: packages, user, repo clone, make install, start.

Removes: prompt/prompt_secret helpers, verify_cf_token, verify_duckdns,
check_pic_ngo_available, and the entire Step 5 identity block.
TOTAL_STEPS 8 → 7.  Step numbers renumbered accordingly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-25 14:41:46 -04:00
roof 579f49ba13 Installer: interactive cell identity prompts with live token validation
Unit Tests / test (push) Successful in 15m24s
install.sh now guides the user through the full identity setup before
running make install:
- Cell name prompt with format validation and pic.ngo availability check
- Domain mode selection: pic.ngo / Cloudflare / DuckDNS / HTTP-01 / LAN
- Cloudflare API token: collected and verified against CF tokens/verify API
- DuckDNS: subdomain + token verified against duckdns.org/update
- HTTP-01: domain name collected, port-80 warning shown
- All collected values passed as env vars to make install
- After two failed token attempts user can continue (re-verified at boot)
- Final banner shows configured cell name and domain

setup_cell.py: updated to handle all domain modes
- Reads DOMAIN_MODE / CELL_DOMAIN_NAME / CLOUDFLARE_API_TOKEN /
  DUCKDNS_TOKEN / DUCKDNS_SUBDOMAIN from env
- write_cell_config() now writes domain_mode + domain_name to _identity
  and builds the ddns section for each provider (not hardcoded to pic_ngo)
- register_with_ddns() only called when DOMAIN_MODE == 'pic_ngo'

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-25 11:34:22 -04:00
roof 439886624e Fix config/data ownership — chown to invoking user after make install
Unit Tests / test (push) Successful in 8m46s
make install runs as root so all generated files (config/, data/) land
as root:root. Added a chown pass in install.sh after make install
completes, re-applying REPO_OWNER ownership. Also fixed the make setup
chown to use SUDO_USER when invoked via sudo rather than always id -u
(which is 0 when running as root).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-11 06:46:12 -04:00
roof 24877df976 Fix setup wizard and installer for fresh-install flow
Unit Tests / test (push) Successful in 8m53s
- setup_manager: fall back to update_password if admin already exists
  (installer bootstrap creates admin; wizard now updates rather than fails)
- install.sh: chown repo to SUDO_USER instead of pic user so the
  invoking operator can run make update without git safe.directory errors
- test: update mock to also stub update_password when testing total auth failure

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-11 06:08:55 -04:00
roof bfa0d99dd1 Fix git safe.directory error for non-root users after install
Unit Tests / test (push) Successful in 8m55s
The installer runs as root and chowns /opt/pic to the pic user.
Any other user (roof, operator) running make update then hits
"detected dubious ownership". Fix: add /opt/pic to system-wide
git safe.directory after clone, and add same guard in make update.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-11 05:46:40 -04:00
roof 5dab6377bc Restore https:// now that git.pic.ngo has a TLS certificate
Unit Tests / test (push) Failing after 15m59s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-11 04:33:51 -04:00
roof 46599bd37e Fix installer: use http://git.pic.ngo without port (nginx forwards)
Unit Tests / test (push) Successful in 8m55s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-11 02:57:13 -04:00
roof cf1b9672f4 Phase 1: first-run setup wizard, bash installer, Docker profiles
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-09 08:05:38 -04:00