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, anddocs/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.
chronyis purged if present (Ubuntu >= 25.10 only — conditional on distribution version)systemd-timesyncdpackage is explicitly installed before the service is enabled- NTP servers configured via
/etc/systemd/timesyncd.confusing thetimesyncd.conf.j2template - 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:
- Queries the current
sudoalternative viaupdate-alternatives --query sudo - Runs
update-alternatives --set sudo /usr/bin/sudo.wsonly if the current value is not already/usr/bin/sudo.ws - Is gated on
ansible_distribution == "Ubuntu"andansible_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-timesyncdpackage must be installed before the service is enabled — explicit inntp.yml - Chrony purge is version-gated; older Ubuntu nodes are unaffected
- Ansible
becomeworks 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.ymlansible/roles/common/templates/timesyncd.conf.j2ansible/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