Skip to content

Consolidated from ADR-0019, ADR-0024, and ADR-0036 on 2026-05-02 per ADR-0047. Source files retained with deprecation banners at docs/adr/0019-systemd-timesyncd-over-chrony.md, docs/adr/0024-region-based-node-naming.md, and docs/adr/0036-sudo-provider-pin.md.

PLAT-0004 — Fleet Conventions: Node Naming, NTP, and Sudo Provider

Field Value
Status Accepted
Date 2026-04-22 (latest source)
Author Ben Peries
Sources ADR-0019 (NTP), ADR-0024 (node naming), ADR-0036 (sudo provider)

Context

Three independent fleet-wide conventions were established across separate ADRs as the platform fleet grew. This file consolidates them into a single reference for node provisioning: how nodes are named, how time is synchronized, and which sudo provider is used on Ubuntu 25.10+.

Decision

1. Region-Based Node Naming (from ADR-0024)

Internal naming pattern: {region}{site}{type}{n}

Segment Meaning Examples
region Geographic region code cae, caw, cac
site Site number within region 1, 2, 3
type Device type node, mqtt, fw, jmp, ot
n Sequential device number 1, 2, 3

Region codes:

Code Region Notes
cae Canada East Primary site — Montreal area
caw Canada West Future — Vancouver area
cac Canada Central Future — Ontario/Prairies

Site numbering per region:

Site Location
cae1 Primary home
cae2 Family site (future)
cae3 Cottage (future)
caw1 Vancouver site (future)

Public alias: All public-facing documentation uses site1 as a sanitized alias. No region codes, site numbers, or geographic references are exposed externally. sanitize.py and sanitize-devices.py enforce this on every pipeline run.

OT sensor pattern: {region}{site}ot{zone}esp{n}

Zone Location
ot-zone Basement
ot-zone Main floor / garage
ot-zone Outdoor
ot-zone Rack monitoring

Example: caneast-site1-ot1-snr01 — Canada East, site 1, basement zone, ESP32 node 1

Naming is forward-compatible with multi-site expansion. New sites require a new region/site code — document in reference/naming.md. OT-0001 (sensor hardware conventions) remains valid; this ADR extends it.

2. systemd-timesyncd on Ubuntu 25.10+ (from ADR-0019)

All Archon nodes running Ubuntu >= 25.10 use systemd-timesyncd for NTP.

  • chrony is purged if present (Ubuntu >= 25.10 only — conditional on distribution version)
  • systemd-timesyncd package is explicitly installed before the service is enabled
  • NTP servers configured via /etc/systemd/timesyncd.conf using the timesyncd.conf.j2 template
  • NTP server list defined in common_ntp_servers (defaults: time.nrc.ca, time.chu.nrc.ca, ca.pool.ntp.org)

Template — timesyncd.conf.j2:

[Time]
NTP={{ common_ntp_servers | join(' ') }}
FallbackNTP=pool.ntp.org
RootDistanceMaxSec=5
PollIntervalMinSec=32
PollIntervalMaxSec=2048

Why timesyncd, not chrony: Ubuntu 25.10 ships systemd-timesyncd as the sole default NTP implementation. chrony is no longer installed by default. The prior state (stub ntp.yml) left nodes without time synchronisation, causing TLS failures, log correlation issues, and Infisical token validation errors. The chrony purge is version-gated (ansible_distribution_version is version('25.10', '>=')) to avoid breaking older nodes.

Alternatives rejected: - chrony — Dropped from Ubuntu 25.10 default install; unnecessary complexity. - ntpd — Legacy, higher overhead. - No NTP — Prior state; unacceptable for production baseline.

3. Pin Classic Sudo Provider on Ubuntu 25.10+ (from ADR-0036)

Ubuntu 25.10 installs sudo-rs (a Rust reimplementation of sudo) as the default /usr/bin/sudo. sudo-rs is not a drop-in replacement: it does not respond to Ansible's become prompt mechanism, causing SSH connections to hang until timeout during privilege escalation.

Decision: Add an idempotent task to ansible/roles/common/tasks/sudo.yml that:

  1. Queries the current sudo alternative via update-alternatives --query sudo
  2. Runs update-alternatives --set sudo /usr/bin/sudo.ws only if the current value is not already /usr/bin/sudo.ws
  3. Is gated on ansible_distribution == "Ubuntu" and ansible_distribution_version >= 25.10

The task is included from roles/common/tasks/main.yml under the [common, sudo] tag set, matching the existing per-task import pattern.

Why not sudo-rs: Configuration is non-trivial and diverges from upstream Ansible become design. Increases maintenance surface for no practical benefit at this fleet scale.

Why not su as become_method: Requires root password on all nodes and conflicts with the ansible-svc-account NOPASSWD model (IAM-0003).

Consequence note: If Ubuntu removes classic sudo from the archive (possible by 26.10), the task will fail gracefully (failed_when: false on the query step) and a new ADR will be required.

Consequences

  • All nodes provisioned after ADR-0024 acceptance follow the {region}{site}{type}{n} pattern
  • The systemd-timesyncd package must be installed before the service is enabled — explicit in ntp.yml
  • Chrony purge is version-gated; older Ubuntu nodes are unaffected
  • Ansible become works correctly on all Ubuntu 25.10+ nodes after baseline run
  • Classic sudo is pinned; sudo-rs remains installed but de-prioritised

References

  • IAM-0003 — IT Ansible service account (ansible-svc-account, NOPASSWD model)
  • OT-0001 — OT sensor hardware conventions (extended by this ADR, not replaced)
  • ansible/roles/common/tasks/ntp.yml
  • ansible/roles/common/templates/timesyncd.conf.j2
  • ansible/roles/common/tasks/sudo.yml
  • WI-288 — caneast-site1-node5 onboarding (sudo incompatibility first observed)
  • WI-297 — Codify sudo provider preference in IT baseline role