src.nth.io/

summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Hoersten <[email protected]>2026-07-28 21:11:08 -0500
committerLuke Hoersten <[email protected]>2026-07-28 21:11:08 -0500
commit207bff9cb9773e3e0ef7fe7114e4b1aa70ffd4b6 (patch)
treecc38ab4e2cb82ecdc9a8e4d03b3afbe2f6af6be0
parenta55c5e9d35530d03fa8c52ceef5d2457827f0851 (diff)
Rename mattertimesync role to mattertimectl (build + controller)HEADmain
- Rename role dir and all vars from mattertimesync to mattertimectl - Rename the server subrole to controller - Build via cargo instead of npm; run the binary directly (no node) - Default fabricLabel to "Matter Time Controller"
-rw-r--r--mattertimectl/build/defaults/main.yaml16
-rw-r--r--mattertimectl/build/meta/main.yaml5
-rw-r--r--mattertimectl/build/tasks/main.yaml71
-rw-r--r--mattertimectl/controller/defaults/main.yaml25
-rw-r--r--mattertimectl/controller/handlers/main.yaml (renamed from mattertimesync/server/handlers/main.yaml)0
-rw-r--r--mattertimectl/controller/meta/main.yaml5
-rw-r--r--mattertimectl/controller/tasks/main.yaml80
-rw-r--r--mattertimectl/controller/templates/config.json.j26
-rw-r--r--mattertimectl/controller/templates/mattertimectl.service.j215
-rw-r--r--mattertimectl/controller/templates/mattertimectl.timer.j210
-rw-r--r--mattertimesync/build/defaults/main.yaml9
-rw-r--r--mattertimesync/build/meta/main.yaml4
-rw-r--r--mattertimesync/build/tasks/main.yaml58
-rw-r--r--mattertimesync/server/defaults/main.yaml25
-rw-r--r--mattertimesync/server/meta/main.yaml4
-rw-r--r--mattertimesync/server/tasks/main.yaml80
-rw-r--r--mattertimesync/server/templates/config.json.j26
-rw-r--r--mattertimesync/server/templates/mattertimesync.service.j215
-rw-r--r--mattertimesync/server/templates/mattertimesync.timer.j210
19 files changed, 233 insertions, 211 deletions
diff --git a/mattertimectl/build/defaults/main.yaml b/mattertimectl/build/defaults/main.yaml
new file mode 100644
index 0000000..56cabdc
--- /dev/null
+++ b/mattertimectl/build/defaults/main.yaml
@@ -0,0 +1,16 @@
+---
+
+mattertimectl_version: "0.1.0"
+# https://github.com/lukehoersten/mattertimectl/tags
+# Rust project: cargo build --release produces one self-contained binary
+# (all runtime deps are pure Rust), so the target only needs the binary to
+# run it. The source tarball must point at the Rust implementation.
+mattertimectl_tar: "https://github.com/{{github_user}}/mattertimectl/archive/refs/tags/v{{mattertimectl_version}}.tar.gz"
+mattertimectl_build_dir: "{{build_work_dir}}/mattertimectl-{{mattertimectl_version}}"
+mattertimectl_srv_dir: "{{build_srv_dir}}"
+
+# Keep cargo's registry cache, the rustup toolchains, and the build output
+# on build_work_dir (the SSD), not the SD card.
+mattertimectl_cargo_home: "{{build_work_dir}}/.cargo"
+mattertimectl_rustup_home: "{{build_work_dir}}/.rustup"
+mattertimectl_cargo_target_dir: "{{build_work_dir}}/.cargo-target"
diff --git a/mattertimectl/build/meta/main.yaml b/mattertimectl/build/meta/main.yaml
new file mode 100644
index 0000000..dae4be5
--- /dev/null
+++ b/mattertimectl/build/meta/main.yaml
@@ -0,0 +1,5 @@
+---
+
+# No role dependency: the Rust toolchain is installed inline via rustup
+# (the distro rustc is too old for this crate's Rust edition).
+dependencies: []
diff --git a/mattertimectl/build/tasks/main.yaml b/mattertimectl/build/tasks/main.yaml
new file mode 100644
index 0000000..d5721d7
--- /dev/null
+++ b/mattertimectl/build/tasks/main.yaml
@@ -0,0 +1,71 @@
+---
+
+- name: ensure build work dir exists
+ become: yes
+ file:
+ path: "{{build_work_dir}}"
+ state: "directory"
+ owner: "{{ansible_user}}"
+ group: "{{ansible_user}}"
+ mode: "0755"
+
+- name: check if mattertimectl build exists
+ stat:
+ path: "{{mattertimectl_srv_dir}}/mattertimectl-{{mattertimectl_version}}.tar.gz"
+ register: build_file
+
+# NOTE: rustup is used only because rs-matter requires a newer rustc than
+# Ubuntu 24.04's apt ships (apt rustc is 1.75; rs-matter needs >= 1.87). Once
+# the build host runs an Ubuntu whose apt rustc/cargo are new enough, drop
+# rustup and the toolchain tasks below and just `apt install rustc cargo`.
+- name: install rustup
+ become: yes
+ apt:
+ name: "rustup"
+ state: "present"
+
+- name: install a current stable rust toolchain
+ command: "rustup toolchain install stable"
+ environment:
+ CARGO_HOME: "{{mattertimectl_cargo_home}}"
+ RUSTUP_HOME: "{{mattertimectl_rustup_home}}"
+ when: not build_file.stat.exists
+
+- name: unarchive mattertimectl source
+ unarchive:
+ remote_src: yes
+ src: "{{mattertimectl_tar}}"
+ dest: "{{build_work_dir}}/"
+ creates: "{{mattertimectl_build_dir}}"
+
+- name: build mattertimectl release binary
+ # rustup run stable dispatches cargo through the toolchain regardless of
+ # the apt rustup package's proxy layout or the configured default.
+ command: "rustup run stable cargo build --release"
+ args:
+ chdir: "{{mattertimectl_build_dir}}"
+ creates: "{{mattertimectl_cargo_target_dir}}/release/mattertimectl"
+ environment:
+ CARGO_HOME: "{{mattertimectl_cargo_home}}"
+ RUSTUP_HOME: "{{mattertimectl_rustup_home}}"
+ CARGO_TARGET_DIR: "{{mattertimectl_cargo_target_dir}}"
+ when: not build_file.stat.exists
+
+- name: create build server dir
+ become: yes
+ file:
+ path: "{{mattertimectl_srv_dir}}"
+ mode: "0755"
+ state: "directory"
+
+- name: create gz archive of mattertimectl binary
+ become: yes
+ archive:
+ path: "{{mattertimectl_cargo_target_dir}}/release/mattertimectl"
+ dest: "{{mattertimectl_srv_dir}}/mattertimectl-{{mattertimectl_version}}.tar.gz"
+ format: "gz"
+ # force a real tar for the single-file binary; the module otherwise gzips
+ # a lone file into a bare .gz that the server's unarchive can't extract.
+ # The tar preserves the executable bit the target relies on.
+ force_archive: true
+ when: not build_file.stat.exists
diff --git a/mattertimectl/controller/defaults/main.yaml b/mattertimectl/controller/defaults/main.yaml
new file mode 100644
index 0000000..933a4bb
--- /dev/null
+++ b/mattertimectl/controller/defaults/main.yaml
@@ -0,0 +1,25 @@
+---
+
+# https://github.com/lukehoersten/mattertimectl/tags
+mattertimectl_version: "0.1.0"
+
+mattertimectl_user: "mattertimectl"
+mattertimectl_install_dir: "/opt/mattertimectl"
+mattertimectl_config_dir: "/etc/mattertimectl"
+# Persistent Matter fabric state: holds the controller's private keys and
+# operational certs, so it stays mode 0700 and owned by the service user.
+mattertimectl_storage_path: "/var/lib/mattertimectl"
+
+# --- config.json ---
+# IANA time-zone name (never a fixed UTC offset; DST is derived from it).
+mattertimectl_timezone: "America/Chicago"
+mattertimectl_log_level: "info" # debug, info, warn, error
+mattertimectl_fabric_label: "Matter Time Controller"
+
+# --- systemd timer schedule ---
+mattertimectl_on_boot_sec: "2min"
+mattertimectl_on_active_sec: "1h"
+mattertimectl_randomized_delay_sec: "5min"
+
+# mattertimectl_bin_url: required, set in host_vars, e.g.
+# http://{{build_server_host}}:{{build_server_port}}/mattertimectl-{{mattertimectl_version}}.tar.gz
diff --git a/mattertimesync/server/handlers/main.yaml b/mattertimectl/controller/handlers/main.yaml
index 9b124e3..9b124e3 100644
--- a/mattertimesync/server/handlers/main.yaml
+++ b/mattertimectl/controller/handlers/main.yaml
diff --git a/mattertimectl/controller/meta/main.yaml b/mattertimectl/controller/meta/main.yaml
new file mode 100644
index 0000000..0fa3794
--- /dev/null
+++ b/mattertimectl/controller/meta/main.yaml
@@ -0,0 +1,5 @@
+---
+
+# No runtime dependency: the Rust build is a single self-contained binary,
+# so the target needs no node or other runtime.
+dependencies: []
diff --git a/mattertimectl/controller/tasks/main.yaml b/mattertimectl/controller/tasks/main.yaml
new file mode 100644
index 0000000..a77145c
--- /dev/null
+++ b/mattertimectl/controller/tasks/main.yaml
@@ -0,0 +1,80 @@
+---
+
+- name: add mattertimectl user
+ become: yes
+ user:
+ name: "{{mattertimectl_user}}"
+ system: "yes"
+ shell: "/usr/sbin/nologin"
+ home: "{{mattertimectl_storage_path}}"
+ create_home: "no"
+
+- name: create mattertimectl directories
+ become: yes
+ file:
+ path: "{{item.path}}"
+ state: "directory"
+ owner: "{{item.owner}}"
+ group: "{{item.owner}}"
+ mode: "{{item.mode}}"
+ loop:
+ - { path: "{{mattertimectl_install_dir}}", owner: "root", mode: "0755" }
+ - { path: "{{mattertimectl_config_dir}}", owner: "root", mode: "0755" }
+ - { path: "{{mattertimectl_storage_path}}", owner: "{{mattertimectl_user}}", mode: "0700" }
+
+- name: check installed mattertimectl version
+ become: yes
+ stat:
+ path: "{{mattertimectl_install_dir}}/.installed-{{mattertimectl_version}}"
+ register: mattertimectl_installed
+
+- name: install mattertimectl bundle
+ become: yes
+ unarchive:
+ remote_src: yes
+ src: "{{mattertimectl_bin_url}}"
+ dest: "{{mattertimectl_install_dir}}/"
+ owner: "root"
+ group: "root"
+ when: not mattertimectl_installed.stat.exists
+
+- name: stamp installed mattertimectl version
+ become: yes
+ copy:
+ dest: "{{mattertimectl_install_dir}}/.installed-{{mattertimectl_version}}"
+ content: "{{mattertimectl_version}}\n"
+ mode: "0644"
+ when: not mattertimectl_installed.stat.exists
+
+- name: configure mattertimectl
+ become: yes
+ template:
+ src: "config.json.j2"
+ dest: "{{mattertimectl_config_dir}}/config.json"
+ owner: "root"
+ group: "{{mattertimectl_user}}"
+ mode: "0640"
+
+- name: install mattertimectl systemd service
+ become: yes
+ template:
+ src: "mattertimectl.service.j2"
+ dest: "/etc/systemd/system/mattertimectl.service"
+ mode: "0644"
+ notify: reload systemd
+
+- name: install mattertimectl systemd timer
+ become: yes
+ template:
+ src: "mattertimectl.timer.j2"
+ dest: "/etc/systemd/system/mattertimectl.timer"
+ mode: "0644"
+ notify: reload systemd
+
+- name: enable mattertimectl timer
+ become: yes
+ systemd:
+ name: "mattertimectl.timer"
+ enabled: "yes"
+ state: "started"
+ daemon_reload: "yes"
diff --git a/mattertimectl/controller/templates/config.json.j2 b/mattertimectl/controller/templates/config.json.j2
new file mode 100644
index 0000000..34f319c
--- /dev/null
+++ b/mattertimectl/controller/templates/config.json.j2
@@ -0,0 +1,6 @@
+{
+ "storagePath": "{{mattertimectl_storage_path}}",
+ "timezone": "{{mattertimectl_timezone}}",
+ "logLevel": "{{mattertimectl_log_level}}",
+ "fabricLabel": "{{mattertimectl_fabric_label}}"
+}
diff --git a/mattertimectl/controller/templates/mattertimectl.service.j2 b/mattertimectl/controller/templates/mattertimectl.service.j2
new file mode 100644
index 0000000..96cbeee
--- /dev/null
+++ b/mattertimectl/controller/templates/mattertimectl.service.j2
@@ -0,0 +1,15 @@
+[Unit]
+Description=Matter device clock synchronization
+Wants=network-online.target
+After=network-online.target time-sync.target
+
+[Service]
+Type=oneshot
+User={{mattertimectl_user}}
+Group={{mattertimectl_user}}
+ExecStart={{mattertimectl_install_dir}}/mattertimectl --config {{mattertimectl_config_dir}}/config.json sync
+NoNewPrivileges=true
+PrivateTmp=true
+ProtectSystem=strict
+ProtectHome=true
+ReadWritePaths={{mattertimectl_storage_path}}
diff --git a/mattertimectl/controller/templates/mattertimectl.timer.j2 b/mattertimectl/controller/templates/mattertimectl.timer.j2
new file mode 100644
index 0000000..a4242de
--- /dev/null
+++ b/mattertimectl/controller/templates/mattertimectl.timer.j2
@@ -0,0 +1,10 @@
+[Unit]
+Description=Periodic Matter device clock synchronization
+
+[Timer]
+OnBootSec={{mattertimectl_on_boot_sec}}
+OnUnitActiveSec={{mattertimectl_on_active_sec}}
+RandomizedDelaySec={{mattertimectl_randomized_delay_sec}}
+
+[Install]
+WantedBy=timers.target
diff --git a/mattertimesync/build/defaults/main.yaml b/mattertimesync/build/defaults/main.yaml
deleted file mode 100644
index bee4e58..0000000
--- a/mattertimesync/build/defaults/main.yaml
+++ /dev/null
@@ -1,9 +0,0 @@
----
-
-mattertimesync_version: "0.1.0"
-# https://github.com/lukehoersten/mattertimesync/tags
-# Pure-JS project: npm run bundle produces one self-contained mattertimesync.mjs
-# (no native modules), so the target only needs node to run it.
-mattertimesync_tar: "https://github.com/{{github_user}}/mattertimesync/archive/refs/tags/v{{mattertimesync_version}}.tar.gz"
-mattertimesync_build_dir: "{{build_work_dir}}/mattertimesync-{{mattertimesync_version}}"
-mattertimesync_srv_dir: "{{build_srv_dir}}"
diff --git a/mattertimesync/build/meta/main.yaml b/mattertimesync/build/meta/main.yaml
deleted file mode 100644
index 6116998..0000000
--- a/mattertimesync/build/meta/main.yaml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-
-dependencies:
- - nodejs
diff --git a/mattertimesync/build/tasks/main.yaml b/mattertimesync/build/tasks/main.yaml
deleted file mode 100644
index c586e01..0000000
--- a/mattertimesync/build/tasks/main.yaml
+++ /dev/null
@@ -1,58 +0,0 @@
----
-
-- name: ensure build work dir exists
- become: yes
- file:
- path: "{{build_work_dir}}"
- state: "directory"
- owner: "{{ansible_user}}"
- group: "{{ansible_user}}"
- mode: "0755"
-
-- name: unarchive mattertimesync source
- unarchive:
- remote_src: yes
- src: "{{mattertimesync_tar}}"
- dest: "{{build_work_dir}}/"
- creates: "{{mattertimesync_build_dir}}"
-
-- name: check if mattertimesync build exists
- stat:
- path: "{{mattertimesync_srv_dir}}/mattertimesync-{{mattertimesync_version}}.tar.gz"
- register: build_file
-
-- name: install mattertimesync build dependencies
- command: "npm ci"
- args:
- chdir: "{{mattertimesync_build_dir}}"
- # Keep the npm cache on build_work_dir (the SSD) instead of the SD card.
- environment:
- npm_config_cache: "{{build_work_dir}}/.npm"
- when: not build_file.stat.exists
-
-- name: bundle mattertimesync
- command: "npm run bundle"
- args:
- chdir: "{{mattertimesync_build_dir}}"
- creates: "{{mattertimesync_build_dir}}/mattertimesync.mjs"
- environment:
- npm_config_cache: "{{build_work_dir}}/.npm"
- when: not build_file.stat.exists
-
-- name: create build server dir
- become: yes
- file:
- path: "{{mattertimesync_srv_dir}}"
- mode: "0755"
- state: "directory"
-
-- name: create gz archive of mattertimesync bundle
- become: yes
- archive:
- path: "{{mattertimesync_build_dir}}/mattertimesync.mjs"
- dest: "{{mattertimesync_srv_dir}}/mattertimesync-{{mattertimesync_version}}.tar.gz"
- format: "gz"
- # force a real tar for the single-file bundle; the module otherwise gzips a
- # lone file into a bare .gz that the server's unarchive can't extract.
- force_archive: true
- when: not build_file.stat.exists
diff --git a/mattertimesync/server/defaults/main.yaml b/mattertimesync/server/defaults/main.yaml
deleted file mode 100644
index e78e700..0000000
--- a/mattertimesync/server/defaults/main.yaml
+++ /dev/null
@@ -1,25 +0,0 @@
----
-
-# https://github.com/lukehoersten/mattertimesync/tags
-mattertimesync_version: "0.1.0"
-
-mattertimesync_user: "mattertimesync"
-mattertimesync_install_dir: "/opt/mattertimesync"
-mattertimesync_config_dir: "/etc/mattertimesync"
-# Persistent Matter fabric state — holds the controller's private keys and
-# operational certs, so it stays mode 0700 and owned by the service user.
-mattertimesync_storage_path: "/var/lib/mattertimesync"
-
-# --- config.json ---
-# IANA time-zone name (never a fixed UTC offset; DST is derived from it).
-mattertimesync_timezone: "America/Chicago"
-mattertimesync_log_level: "info" # debug, info, warn, error
-mattertimesync_fabric_label: "Matter Time Sync"
-
-# --- systemd timer schedule ---
-mattertimesync_on_boot_sec: "2min"
-mattertimesync_on_active_sec: "1h"
-mattertimesync_randomized_delay_sec: "5min"
-
-# mattertimesync_bin_url: — required, set in host_vars, e.g.
-# http://{{build_server_host}}:{{build_server_port}}/mattertimesync-{{mattertimesync_version}}.tar.gz
diff --git a/mattertimesync/server/meta/main.yaml b/mattertimesync/server/meta/main.yaml
deleted file mode 100644
index 6116998..0000000
--- a/mattertimesync/server/meta/main.yaml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-
-dependencies:
- - nodejs
diff --git a/mattertimesync/server/tasks/main.yaml b/mattertimesync/server/tasks/main.yaml
deleted file mode 100644
index 7be2392..0000000
--- a/mattertimesync/server/tasks/main.yaml
+++ /dev/null
@@ -1,80 +0,0 @@
----
-
-- name: add mattertimesync user
- become: yes
- user:
- name: "{{mattertimesync_user}}"
- system: "yes"
- shell: "/usr/sbin/nologin"
- home: "{{mattertimesync_storage_path}}"
- create_home: "no"
-
-- name: create mattertimesync directories
- become: yes
- file:
- path: "{{item.path}}"
- state: "directory"
- owner: "{{item.owner}}"
- group: "{{item.owner}}"
- mode: "{{item.mode}}"
- loop:
- - { path: "{{mattertimesync_install_dir}}", owner: "root", mode: "0755" }
- - { path: "{{mattertimesync_config_dir}}", owner: "root", mode: "0755" }
- - { path: "{{mattertimesync_storage_path}}", owner: "{{mattertimesync_user}}", mode: "0700" }
-
-- name: check installed mattertimesync version
- become: yes
- stat:
- path: "{{mattertimesync_install_dir}}/.installed-{{mattertimesync_version}}"
- register: mattertimesync_installed
-
-- name: install mattertimesync bundle
- become: yes
- unarchive:
- remote_src: yes
- src: "{{mattertimesync_bin_url}}"
- dest: "{{mattertimesync_install_dir}}/"
- owner: "root"
- group: "root"
- when: not mattertimesync_installed.stat.exists
-
-- name: stamp installed mattertimesync version
- become: yes
- copy:
- dest: "{{mattertimesync_install_dir}}/.installed-{{mattertimesync_version}}"
- content: "{{mattertimesync_version}}\n"
- mode: "0644"
- when: not mattertimesync_installed.stat.exists
-
-- name: configure mattertimesync
- become: yes
- template:
- src: "config.json.j2"
- dest: "{{mattertimesync_config_dir}}/config.json"
- owner: "root"
- group: "{{mattertimesync_user}}"
- mode: "0640"
-
-- name: install mattertimesync systemd service
- become: yes
- template:
- src: "mattertimesync.service.j2"
- dest: "/etc/systemd/system/mattertimesync.service"
- mode: "0644"
- notify: reload systemd
-
-- name: install mattertimesync systemd timer
- become: yes
- template:
- src: "mattertimesync.timer.j2"
- dest: "/etc/systemd/system/mattertimesync.timer"
- mode: "0644"
- notify: reload systemd
-
-- name: enable mattertimesync timer
- become: yes
- systemd:
- name: "mattertimesync.timer"
- enabled: "yes"
- state: "started"
- daemon_reload: "yes"
diff --git a/mattertimesync/server/templates/config.json.j2 b/mattertimesync/server/templates/config.json.j2
deleted file mode 100644
index a9b30c3..0000000
--- a/mattertimesync/server/templates/config.json.j2
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "storagePath": "{{mattertimesync_storage_path}}",
- "timezone": "{{mattertimesync_timezone}}",
- "logLevel": "{{mattertimesync_log_level}}",
- "fabricLabel": "{{mattertimesync_fabric_label}}"
-}
diff --git a/mattertimesync/server/templates/mattertimesync.service.j2 b/mattertimesync/server/templates/mattertimesync.service.j2
deleted file mode 100644
index e47cc35..0000000
--- a/mattertimesync/server/templates/mattertimesync.service.j2
+++ /dev/null
@@ -1,15 +0,0 @@
-[Unit]
-Description=Matter device clock synchronization
-Wants=network-online.target
-After=network-online.target time-sync.target
-
-[Service]
-Type=oneshot
-User={{mattertimesync_user}}
-Group={{mattertimesync_user}}
-ExecStart=/usr/bin/node {{mattertimesync_install_dir}}/mattertimesync.mjs --config {{mattertimesync_config_dir}}/config.json sync
-NoNewPrivileges=true
-PrivateTmp=true
-ProtectSystem=strict
-ProtectHome=true
-ReadWritePaths={{mattertimesync_storage_path}}
diff --git a/mattertimesync/server/templates/mattertimesync.timer.j2 b/mattertimesync/server/templates/mattertimesync.timer.j2
deleted file mode 100644
index e378dfc..0000000
--- a/mattertimesync/server/templates/mattertimesync.timer.j2
+++ /dev/null
@@ -1,10 +0,0 @@
-[Unit]
-Description=Periodic Matter device clock synchronization
-
-[Timer]
-OnBootSec={{mattertimesync_on_boot_sec}}
-OnUnitActiveSec={{mattertimesync_on_active_sec}}
-RandomizedDelaySec={{mattertimesync_randomized_delay_sec}}
-
-[Install]
-WantedBy=timers.target