Install and configure Notarius

This commit is contained in:
2026-09-08 18:41:20 +00:00
parent f8a3e113ef
commit 287fc4afd7
12 changed files with 493 additions and 2 deletions

View File

@@ -1,3 +1,78 @@
# ansible-role-notarius # Ansible Role: Notarius
Ansible role to install the Notarius application. Installs and configures [Notarius](https://gitea.maximumdirect.net/eric/notarius)
from source on Ubuntu 26.04 (`x86_64` or `aarch64`). The role requires gathered
facts and uses privilege escalation only for dependency installation and
root-owned application state.
## Variables
```yaml
notarius_version: v0.6.0
notarius_repository_url: https://gitea.maximumdirect.net/eric/notarius.git
notarius_source_dir: /usr/local/src/notarius
notarius_binary_path: /usr/local/bin/notarius
notarius_manage_build_dependencies: true
notarius_go_snap_channel: 1.26/stable
notarius_go_binary: /snap/bin/go
notarius_config_path: /usr/local/etc/notarius/config.yml
notarius_config_version: 4
notarius_promptkit_profile_dir: null
notarius_promptkit_profile_file: null
notarius_promptkit_local_backend_endpoint: null
notarius_promptkit_local_backend_concurrency_limit: null
notarius_pipelines: null
notarius_concurrency_total_llm: null
notarius_concurrency_stage_workers_extract: null
notarius_output_directory: null
notarius_cache_chunk_plans_mode: null
notarius_cache_chunk_plans_directory: null
notarius_cache_checkpoints_enabled: null
notarius_cache_checkpoints_directory: null
notarius_debug_directory: null
```
When `notarius_manage_build_dependencies` is `false`, Git and the executable
selected by `notarius_go_binary` must already be available. Otherwise, the role
installs Git with APT and the classic Go Snap from `notarius_go_snap_channel`.
It checks out `notarius_version` authoritatively, builds `./cmd/notarius`
directly to `notarius_binary_path`, and rebuilds only when that checkout changes
or the binary is absent. The source tree is recursively owned by `root:root`;
the binary is `root:root` mode `0755`.
Configuration variables map directly to Notarius's versioned YAML fields.
Every optional value defaults to `null`, so it and any empty parent section are
omitted and Notarius retains ownership of its built-in defaults. The role always
emits `notarius_config_version` as `version` and writes the file as `root:root`
mode `0644`. `notarius_pipelines` is the native mapping supplied by the caller;
the role does not merge or rewrite it. For example, inventory can compose
fragments in the ordinary way:
```yaml
notarius_pipelines: "{{ notarius_pipeline_group_one | combine(notarius_pipeline_group_two) }}"
```
PromptKit profile values identify profile sources or a local backend endpoint;
they never contain credentials. Supply any credential environment variables
outside this role.
## Example
```yaml
- hosts: notarius_hosts
roles:
- role: ansible-role-notarius
```
## Validation
The repository-local integration suite installs its pinned collection, runs
syntax checking and production-profile lint, verifies the default release,
ownership, executable output, minimal configuration, native configuration
validation, and immediate idempotence. It mutates only the managed source,
binary, configuration, and a private temporary directory, then leaves the
default release and minimal configuration installed.
```sh
tests/integration
```

2
ansible.cfg Normal file
View File

@@ -0,0 +1,2 @@
[defaults]
roles_path = ..

View File

@@ -0,0 +1,4 @@
---
collections:
- name: community.general
version: 13.3.0

23
defaults/main.yml Normal file
View File

@@ -0,0 +1,23 @@
---
notarius_version: v0.6.0
notarius_repository_url: https://gitea.maximumdirect.net/eric/notarius.git
notarius_source_dir: /usr/local/src/notarius
notarius_binary_path: /usr/local/bin/notarius
notarius_manage_build_dependencies: true
notarius_go_snap_channel: 1.26/stable
notarius_go_binary: /snap/bin/go
notarius_config_path: /usr/local/etc/notarius/config.yml
notarius_config_version: 4
notarius_promptkit_profile_dir: null
notarius_promptkit_profile_file: null
notarius_promptkit_local_backend_endpoint: null
notarius_promptkit_local_backend_concurrency_limit: null
notarius_pipelines: null
notarius_concurrency_total_llm: null
notarius_concurrency_stage_workers_extract: null
notarius_output_directory: null
notarius_cache_chunk_plans_mode: null
notarius_cache_chunk_plans_directory: null
notarius_cache_checkpoints_enabled: null
notarius_cache_checkpoints_directory: null
notarius_debug_directory: null

71
meta/argument_specs.yml Normal file
View File

@@ -0,0 +1,71 @@
---
argument_specs:
main:
short_description: Install and configure Notarius from source
options:
notarius_version:
type: str
required: true
notarius_repository_url:
type: str
required: true
notarius_source_dir:
type: path
required: true
notarius_binary_path:
type: path
required: true
notarius_manage_build_dependencies:
type: bool
required: true
notarius_go_snap_channel:
type: str
required: true
notarius_go_binary:
type: path
required: true
notarius_config_path:
type: path
required: true
notarius_config_version:
type: int
required: true
notarius_promptkit_profile_dir:
type: str
required: false
notarius_promptkit_profile_file:
type: str
required: false
notarius_promptkit_local_backend_endpoint:
type: str
required: false
notarius_promptkit_local_backend_concurrency_limit:
type: int
required: false
notarius_pipelines:
type: dict
required: false
notarius_concurrency_total_llm:
type: int
required: false
notarius_concurrency_stage_workers_extract:
type: int
required: false
notarius_output_directory:
type: str
required: false
notarius_cache_chunk_plans_mode:
type: str
required: false
notarius_cache_chunk_plans_directory:
type: str
required: false
notarius_cache_checkpoints_enabled:
type: bool
required: false
notarius_cache_checkpoints_directory:
type: str
required: false
notarius_debug_directory:
type: str
required: false

18
meta/main.yml Normal file
View File

@@ -0,0 +1,18 @@
---
galaxy_info:
role_name: notarius
namespace: rakestraw
author: Eric Rakestraw
description: Install and configure Notarius from source
license: BSD-3-Clause
min_ansible_version: "2.18"
issue_tracker_url: https://gitea.maximumdirect.net/eric/ansible-role-notarius/issues
platforms:
- name: Ubuntu
versions:
- resolute
galaxy_tags:
- notarius
- transcript
- processing
dependencies: []

101
tasks/main.yml Normal file
View File

@@ -0,0 +1,101 @@
---
- name: Validate the supported platform
ansible.builtin.assert:
that:
- ansible_facts.distribution == "Ubuntu"
- ansible_facts.distribution_version == "26.04"
- ansible_facts.architecture in ["x86_64", "aarch64"]
fail_msg: Notarius supports Ubuntu 26.04 on x86_64 or aarch64.
- name: Install Git
become: true
ansible.builtin.apt:
name: git
state: present
update_cache: true
cache_valid_time: 3600
when: notarius_manage_build_dependencies
- name: Install Go
become: true
community.general.snap:
name: go
channel: "{{ notarius_go_snap_channel }}"
classic: true
state: present
when: notarius_manage_build_dependencies
- name: Create installation parent directories
become: true
ansible.builtin.file:
path: "{{ item }}"
state: directory
owner: root
group: root
mode: "0755"
loop:
- "{{ notarius_source_dir | dirname }}"
- "{{ notarius_binary_path | dirname }}"
- "{{ notarius_config_path | dirname }}"
- name: Check out Notarius source
become: true
ansible.builtin.git:
repo: "{{ notarius_repository_url }}"
dest: "{{ notarius_source_dir }}"
version: "{{ notarius_version }}"
force: true
register: notarius_checkout
- name: Inspect the installed binary
ansible.builtin.stat:
path: "{{ notarius_binary_path }}"
register: notarius_binary
- name: Build Notarius
become: true
ansible.builtin.command:
argv:
- "{{ notarius_go_binary }}"
- build
- -trimpath
- -ldflags
- "-X gitea.maximumdirect.net/eric/notarius/internal/buildinfo.Override={{ notarius_version }}"
- -o
- "{{ notarius_binary_path }}"
- ./cmd/notarius
chdir: "{{ notarius_source_dir }}"
environment:
CGO_ENABLED: "0"
GOTOOLCHAIN: local
GOWORK: "off"
changed_when: true
when: >-
notarius_checkout.changed or
not notarius_binary.stat.exists
- name: Converge installed metadata
become: true
ansible.builtin.file:
path: "{{ item.path }}"
state: "{{ item.state }}"
owner: root
group: root
mode: "{{ item.mode | default(omit) }}"
recurse: "{{ item.recurse | default(omit) }}"
loop:
- path: "{{ notarius_source_dir }}"
state: directory
recurse: true
- path: "{{ notarius_binary_path }}"
state: file
mode: "0755"
- name: Write Notarius configuration
become: true
ansible.builtin.template:
src: config.yml.j2
dest: "{{ notarius_config_path }}"
owner: root
group: root
mode: "0644"

61
templates/config.yml.j2 Normal file
View File

@@ -0,0 +1,61 @@
version: {{ notarius_config_version }}
{% if notarius_promptkit_profile_dir is not none or notarius_promptkit_profile_file is not none or notarius_promptkit_local_backend_endpoint is not none or notarius_promptkit_local_backend_concurrency_limit is not none %}
promptkit:
{% if notarius_promptkit_profile_dir is not none %}
profile_dir: {{ notarius_promptkit_profile_dir | to_json }}
{% endif %}
{% if notarius_promptkit_profile_file is not none %}
profile_file: {{ notarius_promptkit_profile_file | to_json }}
{% endif %}
{% if notarius_promptkit_local_backend_endpoint is not none or notarius_promptkit_local_backend_concurrency_limit is not none %}
local_backend:
{% if notarius_promptkit_local_backend_endpoint is not none %}
endpoint: {{ notarius_promptkit_local_backend_endpoint | to_json }}
{% endif %}
{% if notarius_promptkit_local_backend_concurrency_limit is not none %}
concurrency_limit: {{ notarius_promptkit_local_backend_concurrency_limit | to_json }}
{% endif %}
{% endif %}
{% endif %}
{% if notarius_pipelines is not none %}
pipelines: {{ notarius_pipelines | to_json }}
{% endif %}
{% if notarius_concurrency_total_llm is not none or notarius_concurrency_stage_workers_extract is not none %}
concurrency:
{% if notarius_concurrency_total_llm is not none %}
total_llm: {{ notarius_concurrency_total_llm | to_json }}
{% endif %}
{% if notarius_concurrency_stage_workers_extract is not none %}
stage_workers:
extract: {{ notarius_concurrency_stage_workers_extract | to_json }}
{% endif %}
{% endif %}
{% if notarius_output_directory is not none %}
output:
directory: {{ notarius_output_directory | to_json }}
{% endif %}
{% if notarius_cache_chunk_plans_mode is not none or notarius_cache_chunk_plans_directory is not none or notarius_cache_checkpoints_enabled is not none or notarius_cache_checkpoints_directory is not none %}
cache:
{% if notarius_cache_chunk_plans_mode is not none or notarius_cache_chunk_plans_directory is not none %}
chunk_plans:
{% if notarius_cache_chunk_plans_mode is not none %}
mode: {{ notarius_cache_chunk_plans_mode | to_json }}
{% endif %}
{% if notarius_cache_chunk_plans_directory is not none %}
directory: {{ notarius_cache_chunk_plans_directory | to_json }}
{% endif %}
{% endif %}
{% if notarius_cache_checkpoints_enabled is not none or notarius_cache_checkpoints_directory is not none %}
checkpoints:
{% if notarius_cache_checkpoints_enabled is not none %}
enabled: {{ notarius_cache_checkpoints_enabled | to_json }}
{% endif %}
{% if notarius_cache_checkpoints_directory is not none %}
directory: {{ notarius_cache_checkpoints_directory | to_json }}
{% endif %}
{% endif %}
{% endif %}
{% if notarius_debug_directory is not none %}
debug:
directory: {{ notarius_debug_directory | to_json }}
{% endif %}

6
tests/converge.yml Normal file
View File

@@ -0,0 +1,6 @@
---
- name: Converge Notarius role
hosts: localhost
gather_facts: true
roles:
- role: ansible-role-notarius

46
tests/integration Executable file
View File

@@ -0,0 +1,46 @@
#!/usr/bin/env bash
set -euo pipefail
repository_root=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)
workspace_venv="$repository_root/../.venv"
test_tmp=$(mktemp -d)
chmod 0700 "$test_tmp"
export ANSIBLE_COLLECTIONS_PATH="$test_tmp/collections"
export ANSIBLE_ROLES_PATH="$(dirname "$repository_root")"
inventory="$repository_root/tests/inventory"
converge="$repository_root/tests/converge.yml"
verify="$repository_root/tests/verify.yml"
ansible_playbook="$workspace_venv/bin/ansible-playbook"
default_commit=77ae132e5609916da40dcd4fcc749c000a63cbac
cleanup() {
exit_status=$?
trap - EXIT
"$ansible_playbook" -i "$inventory" "$converge" >/dev/null 2>&1 || true
rm -rf -- "$test_tmp"
exit "$exit_status"
}
trap cleanup EXIT
require_clean_recap() {
grep -Eq 'changed=0 .*failed=0' "$1"
}
cd "$repository_root"
"$workspace_venv/bin/ansible-galaxy" collection install \
-r collections/requirements.yml \
-p "$ANSIBLE_COLLECTIONS_PATH"
"$ansible_playbook" -i "$inventory" --syntax-check "$converge"
"$workspace_venv/bin/ansible-lint" "$converge" "$verify"
baseline_log="$test_tmp/baseline.log"
"$ansible_playbook" -i "$inventory" "$converge" | tee "$baseline_log"
"$ansible_playbook" -i "$inventory" \
-e "notarius_expected_version=v0.6.0" \
-e "notarius_expected_commit=$default_commit" \
"$verify"
repeat_log="$test_tmp/repeat.log"
"$ansible_playbook" -i "$inventory" "$converge" | tee "$repeat_log"
require_clean_recap "$repeat_log"

1
tests/inventory Normal file
View File

@@ -0,0 +1 @@
localhost ansible_connection=local

83
tests/verify.yml Normal file
View File

@@ -0,0 +1,83 @@
---
- name: Verify Notarius installation
hosts: localhost
gather_facts: false
tasks:
- name: Read the selected source commit
become: true
ansible.builtin.command:
argv:
- git
- -C
- /usr/local/src/notarius
- rev-parse
- HEAD
register: notarius_commit
changed_when: false
- name: Inspect source ownership
become: true
ansible.builtin.command:
argv:
- find
- /usr/local/src/notarius
- -not
- -user
- root
- -o
- -not
- -group
- root
register: notarius_source_ownership
changed_when: false
- name: Inspect binary metadata
become: true
ansible.builtin.stat:
path: /usr/local/bin/notarius
register: notarius_binary_metadata
- name: Inspect configuration metadata
become: true
ansible.builtin.stat:
path: /usr/local/etc/notarius/config.yml
register: notarius_config_metadata
- name: Read default configuration
become: true
ansible.builtin.slurp:
src: /usr/local/etc/notarius/config.yml
register: notarius_default_config
- name: Read the installed version
ansible.builtin.command:
argv:
- /usr/local/bin/notarius
- --version
register: notarius_version_output
changed_when: false
- name: Validate Notarius configuration
ansible.builtin.command:
argv:
- /usr/local/bin/notarius
- config
- validate
- --config
- /usr/local/etc/notarius/config.yml
changed_when: false
- name: Assert the installation contract
ansible.builtin.assert:
that:
- notarius_commit.stdout == notarius_expected_commit
- notarius_source_ownership.stdout == ""
- notarius_binary_metadata.stat.isreg
- notarius_binary_metadata.stat.pw_name == "root"
- notarius_binary_metadata.stat.gr_name == "root"
- notarius_binary_metadata.stat.mode == "0755"
- notarius_config_metadata.stat.pw_name == "root"
- notarius_config_metadata.stat.gr_name == "root"
- notarius_config_metadata.stat.mode == "0644"
- '(notarius_default_config.content | b64decode | from_yaml) == {"version": 4}'
- notarius_version_output.stdout == "notarius " ~ notarius_expected_version