Capture the catalogue's module.json files at mesh-catalog bb0fe93b for the moved catalogue tests (issue 1379)
Part 2 of 4 of go/testdata/beside; each kept as module.json.captured.
This commit is contained in:
+65
@@ -0,0 +1,65 @@
|
||||
{
|
||||
"module": "artifact-store-tools",
|
||||
"version": "1",
|
||||
"invokes": [
|
||||
"seat:mesh-controller.artifacts",
|
||||
"seat:mesh-controller.collect",
|
||||
"mesh-catalog.catalog_modules",
|
||||
"mesh-catalog.catalog_module"
|
||||
],
|
||||
"tools": [
|
||||
"artifact_store_repositories",
|
||||
"artifact_store_usage",
|
||||
"artifact_store_references",
|
||||
"artifact_store_collect"
|
||||
],
|
||||
"config": {
|
||||
"older-store-names": {
|
||||
"type": "string",
|
||||
"description": "The names the artifact store had before, as host names or host:port separated by spaces, or none when it had no other. artifact_store_references reads every definition under these as well as under the store's current name, so an image a definition pins under one is said to be named by a definition (novox/hq issue 323).",
|
||||
"pattern": "none|[A-Za-z0-9.:-]+( [A-Za-z0-9.:-]+)*",
|
||||
"default": "none"
|
||||
}
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"id": "state",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"place": ".",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "store-names",
|
||||
"type": "file",
|
||||
"path": "${dir:state}/store-names",
|
||||
"mode": "0600",
|
||||
"trusted": false,
|
||||
"template": "files/store-names"
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "tools-go",
|
||||
"kind": "bundle",
|
||||
"language": "go",
|
||||
"system": "arch",
|
||||
"from": "cmd/artifact-store-tools",
|
||||
"binary": "artifact-store-tools",
|
||||
"loads": [
|
||||
"artifact-store-tools"
|
||||
],
|
||||
"env": {
|
||||
"MESH_ARTIFACT_STORE_CONTAINER": "mesh-registry",
|
||||
"MESH_ARTIFACT_STORE_NAMES_FILE": "${dir:state}/store-names"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "files",
|
||||
"kind": "archive",
|
||||
"from": "files"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
+229
@@ -0,0 +1,229 @@
|
||||
{
|
||||
"module": "asus-zephyrus-g14",
|
||||
"version": "1",
|
||||
"moved": true,
|
||||
"templates": "templates",
|
||||
"capabilities": [
|
||||
"package-manager",
|
||||
"service-manager"
|
||||
],
|
||||
"requires": [
|
||||
"x11-display"
|
||||
],
|
||||
"emits": [
|
||||
"profile.switched"
|
||||
],
|
||||
"tools": [
|
||||
"zephyrus_brightness",
|
||||
"zephyrus_battery",
|
||||
"zephyrus_charge_limit",
|
||||
"zephyrus_gpu_mode",
|
||||
"zephyrus_profile",
|
||||
"zephyrus_thermals",
|
||||
"zephyrus_power_draw",
|
||||
"zephyrus_profile_policy",
|
||||
"zephyrus_fan_curves",
|
||||
"zephyrus_keys",
|
||||
"zephyrus_check"
|
||||
],
|
||||
"resources": [
|
||||
{
|
||||
"id": "asusctl",
|
||||
"type": "package",
|
||||
"package": "asusctl"
|
||||
},
|
||||
{
|
||||
"id": "playerctl",
|
||||
"type": "package",
|
||||
"package": "playerctl"
|
||||
},
|
||||
{
|
||||
"id": "asusd",
|
||||
"type": "service",
|
||||
"unit": "asusd.service",
|
||||
"state": "running"
|
||||
},
|
||||
{
|
||||
"id": "supergfxd",
|
||||
"type": "service",
|
||||
"unit": "supergfxd.service",
|
||||
"state": "running",
|
||||
"boot": "enabled"
|
||||
},
|
||||
{
|
||||
"id": "scripts",
|
||||
"type": "archive",
|
||||
"path": "/usr/local/lib/asus-zephyrus-g14",
|
||||
"artifact": "scripts",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "nvidia-options",
|
||||
"type": "file",
|
||||
"path": "/etc/modprobe.d/g14-nvidia-power.conf",
|
||||
"mode": "0644",
|
||||
"template": "templates/modprobe.d/g14-nvidia-power.conf"
|
||||
},
|
||||
{
|
||||
"id": "video-options",
|
||||
"type": "file",
|
||||
"path": "/etc/modprobe.d/video-brightness-switch.conf",
|
||||
"mode": "0644",
|
||||
"template": "templates/modprobe.d/video-brightness-switch.conf"
|
||||
},
|
||||
{
|
||||
"id": "suspend-drop-ins",
|
||||
"type": "directory",
|
||||
"path": "/etc/systemd/system/systemd-suspend.service.d",
|
||||
"mode": "0755",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "nvidia-on-suspend",
|
||||
"type": "file",
|
||||
"path": "/etc/systemd/system/systemd-suspend.service.d/asus-zephyrus-g14-nvidia.conf",
|
||||
"mode": "0644",
|
||||
"template": "templates/systemd/system/systemd-suspend.service.d/asus-zephyrus-g14-nvidia.conf"
|
||||
},
|
||||
{
|
||||
"id": "hibernate-drop-ins",
|
||||
"type": "directory",
|
||||
"path": "/etc/systemd/system/systemd-hibernate.service.d",
|
||||
"mode": "0755",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "nvidia-on-hibernate",
|
||||
"type": "file",
|
||||
"path": "/etc/systemd/system/systemd-hibernate.service.d/asus-zephyrus-g14-nvidia.conf",
|
||||
"mode": "0644",
|
||||
"template": "templates/systemd/system/systemd-hibernate.service.d/asus-zephyrus-g14-nvidia.conf"
|
||||
},
|
||||
{
|
||||
"id": "suspend-then-hibernate-drop-ins",
|
||||
"type": "directory",
|
||||
"path": "/etc/systemd/system/systemd-suspend-then-hibernate.service.d",
|
||||
"mode": "0755",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "nvidia-on-suspend-then-hibernate",
|
||||
"type": "file",
|
||||
"path": "/etc/systemd/system/systemd-suspend-then-hibernate.service.d/asus-zephyrus-g14-nvidia.conf",
|
||||
"mode": "0644",
|
||||
"template": "templates/systemd/system/systemd-suspend-then-hibernate.service.d/asus-zephyrus-g14-nvidia.conf"
|
||||
},
|
||||
{
|
||||
"id": "powerd-drop-ins",
|
||||
"type": "directory",
|
||||
"path": "/etc/systemd/system/nvidia-powerd.service.d",
|
||||
"mode": "0755",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "powerd-opt-in",
|
||||
"type": "file",
|
||||
"path": "/etc/systemd/system/nvidia-powerd.service.d/asus-zephyrus-g14.conf",
|
||||
"mode": "0644",
|
||||
"template": "templates/systemd/system/nvidia-powerd.service.d/asus-zephyrus-g14.conf"
|
||||
},
|
||||
{
|
||||
"id": "backlight-rule",
|
||||
"type": "file",
|
||||
"path": "/etc/udev/rules.d/90-backlight.rules",
|
||||
"mode": "0644",
|
||||
"template": "templates/udev/rules.d/90-backlight.rules"
|
||||
},
|
||||
{
|
||||
"id": "udev",
|
||||
"type": "service",
|
||||
"unit": "systemd-udevd.service",
|
||||
"reload-on": [
|
||||
"backlight-rule"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "upower-package",
|
||||
"type": "package",
|
||||
"package": "upower"
|
||||
},
|
||||
{
|
||||
"id": "upower-drop-ins",
|
||||
"type": "directory",
|
||||
"path": "/etc/UPower/UPower.conf.d",
|
||||
"mode": "0755",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "low-battery",
|
||||
"type": "file",
|
||||
"path": "/etc/UPower/UPower.conf.d/50-asus-zephyrus-g14.conf",
|
||||
"mode": "0644",
|
||||
"template": "templates/UPower/UPower.conf.d/50-asus-zephyrus-g14.conf"
|
||||
},
|
||||
{
|
||||
"id": "upower",
|
||||
"type": "service",
|
||||
"unit": "upower.service",
|
||||
"state": "running",
|
||||
"boot": "enabled",
|
||||
"restart-on": [
|
||||
"low-battery"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "xorg-drop-ins",
|
||||
"type": "directory",
|
||||
"path": "/etc/X11/xorg.conf.d",
|
||||
"mode": "0755",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "touchpad",
|
||||
"type": "file",
|
||||
"path": "/etc/X11/xorg.conf.d/30-asus-zephyrus-g14-touchpad.conf",
|
||||
"mode": "0644",
|
||||
"template": "templates/X11/xorg.conf.d/30-asus-zephyrus-g14-touchpad.conf"
|
||||
}
|
||||
],
|
||||
"items": [
|
||||
{
|
||||
"collection": "shell:after-wake:normal",
|
||||
"template": "templates/after-wake"
|
||||
},
|
||||
{
|
||||
"collection": "contribution:node-hotkeys:trigger",
|
||||
"template": "templates/hotkeys-triggers"
|
||||
},
|
||||
{
|
||||
"collection": "contribution:node-display-session:config",
|
||||
"name": "display-session",
|
||||
"template": "templates/display-session"
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "tools-go",
|
||||
"kind": "bundle",
|
||||
"language": "go",
|
||||
"system": "arch",
|
||||
"from": "cmd/zephyrus",
|
||||
"binary": "zephyrus",
|
||||
"loads": [
|
||||
"zephyrus"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "scripts",
|
||||
"kind": "archive",
|
||||
"from": "files"
|
||||
},
|
||||
{
|
||||
"name": "templates",
|
||||
"kind": "archive",
|
||||
"from": "templates"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
{
|
||||
"module": "audit-logger",
|
||||
"version": "1",
|
||||
"slug": "audit",
|
||||
"consumes": [
|
||||
"**"
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "code",
|
||||
"kind": "bundle",
|
||||
"language": "typescript",
|
||||
"entrypoints": [
|
||||
"index.js",
|
||||
"tools/index.js"
|
||||
],
|
||||
"loads": [
|
||||
"index.js",
|
||||
"tools/index.js"
|
||||
],
|
||||
"env": {
|
||||
"AUDIT_LOG": "${dir:trail}/audit.log",
|
||||
"AUDIT_SPOOL": "${dir:spool}"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"data": {
|
||||
"own": [
|
||||
{
|
||||
"id": "trail",
|
||||
"path": "${dir:trail}",
|
||||
"class": "valuable",
|
||||
"why": "the audit trail, written nowhere else"
|
||||
},
|
||||
{
|
||||
"id": "spool",
|
||||
"path": "${dir:spool}",
|
||||
"class": "valuable",
|
||||
"why": "events the trail could not take yet; after the bus gives one up, the only copy"
|
||||
}
|
||||
]
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"id": "state",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"place": ".",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "trail",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "spool",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"unknown": "program"
|
||||
}
|
||||
],
|
||||
"capabilities": [
|
||||
"container-runtime"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
{
|
||||
"module": "avahi",
|
||||
"version": "1",
|
||||
"capabilities": [
|
||||
"package-manager",
|
||||
"service-manager"
|
||||
],
|
||||
"tools": [
|
||||
"avahi_status",
|
||||
"avahi_browse",
|
||||
"avahi_resolve",
|
||||
"avahi_services"
|
||||
],
|
||||
"resources": [
|
||||
{
|
||||
"id": "package",
|
||||
"type": "package",
|
||||
"package": "avahi"
|
||||
},
|
||||
{
|
||||
"id": "daemon",
|
||||
"type": "service",
|
||||
"unit": "avahi-daemon.service",
|
||||
"state": "running",
|
||||
"boot": "enabled"
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "tools",
|
||||
"kind": "bundle",
|
||||
"language": "go",
|
||||
"system": "arch",
|
||||
"from": "cmd/avahi-tools",
|
||||
"binary": "avahi-tools",
|
||||
"loads": [
|
||||
"avahi-tools"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
{
|
||||
"module": "baserow",
|
||||
"version": "1",
|
||||
"capabilities": [
|
||||
"container-runtime"
|
||||
],
|
||||
"requires": [
|
||||
"postgres-database",
|
||||
"route"
|
||||
],
|
||||
"contributes": {
|
||||
"postgres-database": {
|
||||
"name": "baserow"
|
||||
},
|
||||
"route": {
|
||||
"label": "baserow",
|
||||
"endpoint": "web"
|
||||
}
|
||||
},
|
||||
"binds": {
|
||||
"postgres-database": "${dir:state}/database.json",
|
||||
"route": "${dir:state}/route.json"
|
||||
},
|
||||
"secrets": {
|
||||
"postgres-database": "${dir:state}/database.secret"
|
||||
},
|
||||
"own-secrets": {
|
||||
"admin": "${dir:state}/admin.secret"
|
||||
},
|
||||
"listens": [
|
||||
{
|
||||
"name": "web",
|
||||
"port": 80,
|
||||
"protocol": "tcp",
|
||||
"from": "mesh",
|
||||
"why": "the Baserow web UI and REST API, served by the image's own Caddy; a public name is the route's"
|
||||
}
|
||||
],
|
||||
"data": {
|
||||
"own": [
|
||||
{
|
||||
"id": "data",
|
||||
"path": "${dir:data}",
|
||||
"class": "valuable",
|
||||
"why": "uploaded files and media; the tables are in the database"
|
||||
}
|
||||
]
|
||||
},
|
||||
"config": {
|
||||
"host": {
|
||||
"type": "string",
|
||||
"description": "The Host header the module's tools send to Baserow, a host name; the file's default is the name the module's route was given.",
|
||||
"trusted": true,
|
||||
"default": "${bound:route:name}"
|
||||
},
|
||||
"email": {
|
||||
"type": "string",
|
||||
"description": "The email address of the Baserow account the module's tools sign in as; unset, the code falls back to its environment.",
|
||||
"trusted": true,
|
||||
"default": ""
|
||||
},
|
||||
"url": {
|
||||
"type": "string",
|
||||
"description": "The address the module's tools reach Baserow at, as a URL; unset, the code falls back to its environment, else this machine's Baserow on port 80.",
|
||||
"trusted": true,
|
||||
"default": ""
|
||||
}
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"id": "mesh-state",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"place": "mesh",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "state",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"place": ".",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "data",
|
||||
"type": "directory",
|
||||
"mode": "0755",
|
||||
"owner": "9999:9999",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "server-env",
|
||||
"type": "file",
|
||||
"path": "${dir:state}/server.env",
|
||||
"mode": "0600",
|
||||
"template": "files/server.env"
|
||||
},
|
||||
{
|
||||
"id": "net",
|
||||
"type": "network",
|
||||
"name": "baserow"
|
||||
},
|
||||
{
|
||||
"id": "server",
|
||||
"type": "container",
|
||||
"name": "baserow",
|
||||
"image": "baserow/baserow@sha256:263ea6c4b72c9eccabcd975ffe9fdebf23913a293a514bec6a3897a5e0a5a080",
|
||||
"health": {
|
||||
"kind": "runtime"
|
||||
},
|
||||
"network": "baserow",
|
||||
"env-file": [
|
||||
"${dir:state}/server.env"
|
||||
],
|
||||
"ports": [
|
||||
"80"
|
||||
],
|
||||
"volumes": [
|
||||
"${dir:data}:/baserow/data",
|
||||
"${dir:state}/database.secret:/run/secrets/database:ro"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "runtime-config",
|
||||
"type": "file",
|
||||
"path": "${dir:mesh-state}/config.json",
|
||||
"mode": "0600",
|
||||
"template": "files/config.json",
|
||||
"merge": "json",
|
||||
"takes-config": ["host", "email", "url"],
|
||||
"protected": ["password"]
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "tools",
|
||||
"kind": "bundle",
|
||||
"language": "typescript",
|
||||
"entrypoints": [
|
||||
"tools/index.js"
|
||||
],
|
||||
"loads": [
|
||||
"tools/index.js"
|
||||
],
|
||||
"env": {
|
||||
"MESH_BASEROW_URL": "http://127.0.0.1:${port:80}",
|
||||
"MESH_BASEROW_CONFIG_FILE": "${dir:mesh-state}/config.json"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "files",
|
||||
"kind": "archive",
|
||||
"from": "files"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,253 @@
|
||||
{
|
||||
"module": "betterbird",
|
||||
"version": "1",
|
||||
"upgrade": {
|
||||
"policy": "record",
|
||||
"why": "a new build may remove the community package betterbird-bin and replaces the installation in /opt/betterbird, which a running Betterbird has open: the switch on each node and every upgrade wait for the operator, who quits Betterbird first and then pushes (novox/hq ADR 0316 §4, §5)"
|
||||
},
|
||||
"requires": [
|
||||
"x11-display"
|
||||
],
|
||||
"invokes": [
|
||||
"seat:mesh-controller.settings",
|
||||
"seat:mesh-controller.nodes",
|
||||
"seat:mesh-controller.node",
|
||||
"betterbird.betterbird_derive"
|
||||
],
|
||||
"tools": [
|
||||
"betterbird_status",
|
||||
"betterbird_prefs",
|
||||
"betterbird_config",
|
||||
"betterbird_config_apply",
|
||||
"betterbird_user_js",
|
||||
"betterbird_log",
|
||||
"betterbird_restart",
|
||||
"betterbird_check",
|
||||
"betterbird_accounts",
|
||||
"betterbird_identities",
|
||||
"betterbird_calendars",
|
||||
"betterbird_address_books",
|
||||
"betterbird_filters",
|
||||
"betterbird_tags",
|
||||
"betterbird_derive",
|
||||
"betterbird_drift",
|
||||
"betterbird_reminder_test"
|
||||
],
|
||||
"config": {
|
||||
"prefs": {
|
||||
"type": "object",
|
||||
"description": "Betterbird's preferences the operator sets, by their own names (mailnews.*, calendar.* and the like), laid into prefs.json; an account's, a server's and a tag's are refused, as accounts, the four kinds and tags own them (novox/hq ADR 0329 §6).",
|
||||
"trusted": true,
|
||||
"default": {}
|
||||
},
|
||||
"accounts": {
|
||||
"type": "object",
|
||||
"description": "The mail accounts Betterbird is set up with, each by a name of the operator's: its address, its sender's name and its incoming and outgoing servers; no password, token or cookie (novox/hq ADR 0329 §2).",
|
||||
"trusted": true,
|
||||
"default": {}
|
||||
},
|
||||
"identities": {
|
||||
"type": "object",
|
||||
"description": "The identities beside an account's own, each by a name of the operator's: the address and name it sends as, its signature as a list of lines, and the profile's key to adopt on a node.",
|
||||
"trusted": true,
|
||||
"default": {}
|
||||
},
|
||||
"calendars": {
|
||||
"type": "object",
|
||||
"description": "The calendars Betterbird shows, each by a name of the operator's: where it is and how it is reached, and the profile's key to adopt on a node.",
|
||||
"trusted": true,
|
||||
"default": {}
|
||||
},
|
||||
"address-books": {
|
||||
"type": "object",
|
||||
"description": "The address books Betterbird uses, each by a name of the operator's: where it is and how it is reached, and the profile's key to adopt on a node.",
|
||||
"trusted": true,
|
||||
"default": {}
|
||||
},
|
||||
"filters": {
|
||||
"type": "object",
|
||||
"description": "The message filters of each account, by account: what each matches and what it does with the mail.",
|
||||
"trusted": true,
|
||||
"default": {}
|
||||
},
|
||||
"tags": {
|
||||
"type": "object",
|
||||
"description": "The tags Betterbird offers, each by its own key: its name, colour and order; trusted since issue 751, so a change to it is the operator's to approve.",
|
||||
"trusted": true,
|
||||
"default": {}
|
||||
}
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"id": "configuration-dir",
|
||||
"type": "directory",
|
||||
"path": "${machine:account-home}/.config/betterbird",
|
||||
"owner": "${machine:account}",
|
||||
"mode": "0755",
|
||||
"unknown": "move-out",
|
||||
"knows": ["accounts-record.json", "configuration-record.json", "kept/"]
|
||||
},
|
||||
{
|
||||
"id": "prefs",
|
||||
"type": "file",
|
||||
"path": "${machine:account-home}/.config/betterbird/prefs.json",
|
||||
"owner": "${machine:account}",
|
||||
"mode": "0644",
|
||||
"merge": "json",
|
||||
"takes-config": [
|
||||
"prefs"
|
||||
],
|
||||
"template": "files/prefs.json",
|
||||
"trusted": true
|
||||
},
|
||||
{
|
||||
"id": "accounts",
|
||||
"type": "file",
|
||||
"path": "${machine:account-home}/.config/betterbird/accounts.json",
|
||||
"owner": "${machine:account}",
|
||||
"mode": "0600",
|
||||
"merge": "json",
|
||||
"takes-config": [
|
||||
"accounts"
|
||||
],
|
||||
"template": "files/accounts.json",
|
||||
"trusted": true
|
||||
},
|
||||
{
|
||||
"id": "configuration",
|
||||
"type": "file",
|
||||
"path": "${machine:account-home}/.config/betterbird/configuration.json",
|
||||
"owner": "${machine:account}",
|
||||
"mode": "0600",
|
||||
"merge": "json",
|
||||
"takes-config": [
|
||||
"identities",
|
||||
"calendars",
|
||||
"address-books",
|
||||
"filters"
|
||||
],
|
||||
"template": "files/configuration.json",
|
||||
"trusted": true
|
||||
},
|
||||
{
|
||||
"id": "tags",
|
||||
"type": "file",
|
||||
"path": "${machine:account-home}/.config/betterbird/tags.json",
|
||||
"owner": "${machine:account}",
|
||||
"mode": "0644",
|
||||
"merge": "json",
|
||||
"takes-config": [
|
||||
"tags"
|
||||
],
|
||||
"template": "files/tags.json",
|
||||
"trusted": true
|
||||
},
|
||||
{
|
||||
"id": "community-package",
|
||||
"type": "package",
|
||||
"package": "betterbird-bin",
|
||||
"absent": true
|
||||
},
|
||||
{
|
||||
"id": "installation",
|
||||
"type": "archive",
|
||||
"path": "/opt/betterbird",
|
||||
"artifact": "archive",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "owl",
|
||||
"type": "archive",
|
||||
"path": "/opt/betterbird/owl",
|
||||
"artifact": "owl",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "policies",
|
||||
"type": "archive",
|
||||
"path": "/opt/betterbird/distribution",
|
||||
"artifact": "distribution",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "spelling",
|
||||
"type": "archive",
|
||||
"path": "/opt/betterbird/defaults/pref",
|
||||
"artifact": "defaults",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "preparation",
|
||||
"type": "archive",
|
||||
"path": "/usr/local/lib/mesh-betterbird",
|
||||
"artifact": "tools",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "start",
|
||||
"type": "file",
|
||||
"path": "/usr/local/bin/betterbird",
|
||||
"mode": "0755",
|
||||
"template": "files/betterbird"
|
||||
},
|
||||
{
|
||||
"id": "launcher",
|
||||
"type": "file",
|
||||
"path": "/usr/local/share/applications/eu.betterbird.Betterbird.desktop",
|
||||
"mode": "0644",
|
||||
"template": "files/eu.betterbird.Betterbird.desktop"
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "tools",
|
||||
"kind": "bundle",
|
||||
"language": "go",
|
||||
"system": "arch",
|
||||
"from": "cmd/betterbird-tools",
|
||||
"binary": "betterbird-tools",
|
||||
"loads": [
|
||||
"betterbird-tools"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "archive",
|
||||
"kind": "archive",
|
||||
"url": "https://www.betterbird.eu/downloads/LinuxArchive/betterbird-153.4.0esr-bb10.en-US.linux-x86_64.tar.xz",
|
||||
"sha256": "38dd24890a66b4cf9a45bc24e15192e00c26b929e1bb8df7974c16a4539129e2",
|
||||
"version": "153.4.0esr-bb10",
|
||||
"within": "betterbird",
|
||||
"names-on-purpose": {
|
||||
"www.betterbird.eu": "Betterbird's project publishes its Linux release there; the build seat fetches it once, by its pinned sha256 (novox/hq ADR 0316 §2)"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "owl",
|
||||
"kind": "archive",
|
||||
"url": "https://www.beonex.com/owl/owl.xpi",
|
||||
"sha256": "a54cc3d52113b34f97942ee19190947dee23561e2217f18db3d80ac023991221",
|
||||
"version": "1.5.6.1",
|
||||
"file": "owl.xpi",
|
||||
"names-on-purpose": {
|
||||
"www.beonex.com": "Owl's vendor publishes its xpi there; the build seat fetches it once, by its pinned sha256 (novox/hq ADR 0316 §6)"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "distribution",
|
||||
"kind": "archive",
|
||||
"from": "install/distribution"
|
||||
},
|
||||
{
|
||||
"name": "defaults",
|
||||
"kind": "archive",
|
||||
"from": "install/defaults-pref"
|
||||
},
|
||||
{
|
||||
"name": "files",
|
||||
"kind": "archive",
|
||||
"from": "files"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"module": "blueman",
|
||||
"version": "1",
|
||||
"capabilities": [
|
||||
"package-manager"
|
||||
],
|
||||
"requires": [
|
||||
"x11-display"
|
||||
],
|
||||
"tools": [
|
||||
"blueman_status",
|
||||
"blueman_restart",
|
||||
"blueman_check"
|
||||
],
|
||||
"resources": [
|
||||
{
|
||||
"id": "package",
|
||||
"type": "package",
|
||||
"package": "blueman"
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "tools",
|
||||
"kind": "bundle",
|
||||
"language": "go",
|
||||
"system": "arch",
|
||||
"from": "cmd/blueman-tools",
|
||||
"binary": "blueman-tools",
|
||||
"loads": [
|
||||
"blueman-tools"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
{
|
||||
"module": "bluetooth",
|
||||
"version": "1",
|
||||
"capabilities": [
|
||||
"package-manager",
|
||||
"service-manager"
|
||||
],
|
||||
"tools": [
|
||||
"bluetooth_controller",
|
||||
"bluetooth_power",
|
||||
"bluetooth_devices",
|
||||
"bluetooth_scan",
|
||||
"bluetooth_connect",
|
||||
"bluetooth_disconnect",
|
||||
"bluetooth_trust",
|
||||
"bluetooth_pair",
|
||||
"bluetooth_remove"
|
||||
],
|
||||
"resources": [
|
||||
{
|
||||
"id": "stack",
|
||||
"type": "package",
|
||||
"package": "bluez"
|
||||
},
|
||||
{
|
||||
"id": "utilities",
|
||||
"type": "package",
|
||||
"package": "bluez-utils"
|
||||
},
|
||||
{
|
||||
"id": "daemon",
|
||||
"type": "service",
|
||||
"unit": "bluetooth.service",
|
||||
"state": "running",
|
||||
"boot": "enabled"
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "tools",
|
||||
"kind": "bundle",
|
||||
"language": "go",
|
||||
"system": "arch",
|
||||
"from": "cmd/bluetooth-tools",
|
||||
"binary": "bluetooth-tools",
|
||||
"loads": [
|
||||
"bluetooth-tools"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
{
|
||||
"module": "ca-trust",
|
||||
"version": "1",
|
||||
"slug": "catrust",
|
||||
"capabilities": [
|
||||
"service-manager"
|
||||
],
|
||||
"requires": [
|
||||
"internal-acme-ca"
|
||||
],
|
||||
"seats": [
|
||||
{
|
||||
"name": "the-mesh-trust-anchor",
|
||||
"scope": "node"
|
||||
}
|
||||
],
|
||||
"claims": [
|
||||
{
|
||||
"name": "the-mesh-trust-anchor",
|
||||
"scope": "node"
|
||||
}
|
||||
],
|
||||
"resources": [
|
||||
{
|
||||
"id": "state",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"place": ".",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "anchor",
|
||||
"type": "file",
|
||||
"path": "${dir:state}/anchor",
|
||||
"mode": "0755",
|
||||
"template": "files/anchor"
|
||||
},
|
||||
{
|
||||
"id": "unit",
|
||||
"type": "file",
|
||||
"path": "/etc/systemd/system/mesh-ca-trust.service",
|
||||
"mode": "0644",
|
||||
"template": "files/mesh-ca-trust.service"
|
||||
},
|
||||
{
|
||||
"id": "trust",
|
||||
"type": "service",
|
||||
"unit": "mesh-ca-trust.service",
|
||||
"state": "running",
|
||||
"boot": "enabled",
|
||||
"restart-on": [
|
||||
"anchor",
|
||||
"unit"
|
||||
]
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "files",
|
||||
"kind": "archive",
|
||||
"from": "files"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,247 @@
|
||||
{
|
||||
"module": "claude-code",
|
||||
"version": "1",
|
||||
"moved": true,
|
||||
"slug": "agent",
|
||||
"capabilities": [
|
||||
"package-manager"
|
||||
],
|
||||
"requires": [
|
||||
"mcp-endpoint",
|
||||
{
|
||||
"name": "gitea-read",
|
||||
"optional": true
|
||||
}
|
||||
],
|
||||
"binds": {
|
||||
"mcp-endpoint": "${dir:state}/mcp-endpoint.json"
|
||||
},
|
||||
"secrets": {
|
||||
"gitea-read": "${dir:state}/gitea-read.secret"
|
||||
},
|
||||
"uses": [
|
||||
"operator-channel"
|
||||
],
|
||||
"state": [
|
||||
"servers",
|
||||
"holdings",
|
||||
"config",
|
||||
"proposals",
|
||||
"questions",
|
||||
"memory"
|
||||
],
|
||||
"reads": [
|
||||
"claude-licence-manager.bindings"
|
||||
],
|
||||
"tools": [
|
||||
"claude_code_status",
|
||||
"claude_code_render",
|
||||
"claude_code_guard",
|
||||
"claude_code_pull",
|
||||
"claude_code_grant",
|
||||
"claude_code_add_api_key",
|
||||
"claude_code_registrations",
|
||||
"claude_code_memory",
|
||||
"claude_code_mcp_list",
|
||||
"claude_code_mcp_register",
|
||||
"claude_code_mcp_unregister",
|
||||
"claude_code_skill_list",
|
||||
"claude_code_skill_register",
|
||||
"claude_code_skill_unregister",
|
||||
"claude_code_agent_list",
|
||||
"claude_code_agent_register",
|
||||
"claude_code_agent_unregister",
|
||||
"claude_code_command_list",
|
||||
"claude_code_command_register",
|
||||
"claude_code_command_unregister",
|
||||
"claude_code_hook_list",
|
||||
"claude_code_hook_register",
|
||||
"claude_code_hook_unregister",
|
||||
"claude_code_output_style_list",
|
||||
"claude_code_output_style_register",
|
||||
"claude_code_output_style_unregister",
|
||||
"claude_code_instructions_list",
|
||||
"claude_code_instructions_register",
|
||||
"claude_code_instructions_unregister",
|
||||
"claude_code_instructions_propose",
|
||||
"claude_code_proposals",
|
||||
"claude_code_ask",
|
||||
"claude_code_answer",
|
||||
"claude_code_settings_get",
|
||||
"claude_code_settings_set",
|
||||
"claude_code_settings_clear",
|
||||
"claude_code_permission_add",
|
||||
"claude_code_permission_remove",
|
||||
"claude_code_config_list",
|
||||
"claude_code_config_show",
|
||||
"claude_code_config_status",
|
||||
"claude_code_config_import",
|
||||
"claude_code_home_show",
|
||||
"claude_code_home_remove",
|
||||
"claude_code_home_removed",
|
||||
"claude_code_home_restore",
|
||||
"claude_code_judge",
|
||||
"claude_code_judged"
|
||||
],
|
||||
"data": {
|
||||
"own": [
|
||||
{
|
||||
"id": "agent-home",
|
||||
"path": "${dir:agent-home}",
|
||||
"class": "valuable",
|
||||
"why": "the operator's agent's own files: its memory, history and projects"
|
||||
}
|
||||
]
|
||||
},
|
||||
"config": {
|
||||
"role": {
|
||||
"type": "string",
|
||||
"description": "What this machine is for, in a sentence, written into the instructions every Claude Code session on it reads; empty says nothing.",
|
||||
"trusted": true,
|
||||
"default": ""
|
||||
},
|
||||
"mcp_servers": {
|
||||
"type": "object",
|
||||
"description": "The tool servers every session on this machine is given beside the mesh's own, by name, each as Claude Code's managed MCP configuration takes it; empty adds none.",
|
||||
"trusted": true,
|
||||
"default": {}
|
||||
},
|
||||
"managed_settings": {
|
||||
"type": "object",
|
||||
"description": "Keys of Claude Code's managed settings every session on this machine obeys, such as spinnerTipsEnabled, laid over the mesh's own; empty adds none. Falls back to agent-managed-settings, the mesh's or this node's.",
|
||||
"trusted": true,
|
||||
"predefined": "agent-managed-settings",
|
||||
"default": {}
|
||||
},
|
||||
"instructions": {
|
||||
"type": "object",
|
||||
"description": "The instructions every session on this machine reads, by name, each a text as one line or a list of its lines; empty adds none.",
|
||||
"trusted": true,
|
||||
"default": {}
|
||||
},
|
||||
"output_styles": {
|
||||
"type": "object",
|
||||
"description": "The output styles offered to every session on this machine, by name, each a text as one line or a list of its lines; empty adds none.",
|
||||
"trusted": true,
|
||||
"default": {}
|
||||
},
|
||||
"skills": {
|
||||
"type": "object",
|
||||
"description": "The skills offered to every session on this machine, by name, each its files by path, a text as one line or a list of its lines; a skill without its SKILL.md is left out; empty adds none.",
|
||||
"trusted": true,
|
||||
"default": {}
|
||||
},
|
||||
"commands": {
|
||||
"type": "object",
|
||||
"description": "The slash commands offered to every session on this machine, by name, each a text as one line or a list of its lines; empty adds none.",
|
||||
"trusted": true,
|
||||
"default": {}
|
||||
},
|
||||
"agents": {
|
||||
"type": "object",
|
||||
"description": "The agents offered to every session on this machine, by name, each a text as one line or a list of its lines; empty adds none.",
|
||||
"trusted": true,
|
||||
"default": {}
|
||||
}
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"id": "package",
|
||||
"type": "package",
|
||||
"package": "claude-code"
|
||||
},
|
||||
{
|
||||
"id": "managed",
|
||||
"type": "directory",
|
||||
"path": "/etc/claude-code",
|
||||
"mode": "0755",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "start",
|
||||
"type": "file",
|
||||
"path": "/usr/local/bin/claude-agent",
|
||||
"mode": "0755",
|
||||
"template": "files/claude-agent"
|
||||
},
|
||||
{
|
||||
"id": "agent-account-name",
|
||||
"type": "file",
|
||||
"path": "/etc/claude-code/agent-account",
|
||||
"mode": "0644",
|
||||
"template": "files/agent-account"
|
||||
},
|
||||
{
|
||||
"id": "agent-account",
|
||||
"type": "user",
|
||||
"name": "${machine:agent-account}",
|
||||
"home": "${machine:agent-home}",
|
||||
"root": "${machine:agent-root}"
|
||||
},
|
||||
{
|
||||
"id": "agent-home",
|
||||
"type": "directory",
|
||||
"path": "${machine:agent-home}/.claude",
|
||||
"mode": "0700",
|
||||
"owner": "${machine:agent-account}",
|
||||
"unknown": "module"
|
||||
},
|
||||
{
|
||||
"id": "state",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"owner": "${machine:account}",
|
||||
"place": ".",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "facts",
|
||||
"type": "file",
|
||||
"path": "${dir:state}/facts.json",
|
||||
"mode": "0600",
|
||||
"owner": "${machine:account}",
|
||||
"template": "files/facts.json"
|
||||
},
|
||||
{
|
||||
"id": "settings",
|
||||
"type": "file",
|
||||
"path": "${dir:state}/settings.json",
|
||||
"mode": "0600",
|
||||
"owner": "${machine:account}",
|
||||
"takes-config": ["role", "mcp_servers", "managed_settings", "instructions", "output_styles", "skills", "commands", "agents"],
|
||||
"merge": "json",
|
||||
"template": "files/settings.json"
|
||||
}
|
||||
],
|
||||
"items": [
|
||||
{
|
||||
"collection": "shell:zsh:normal",
|
||||
"template": "files/zsh-normal"
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "tools",
|
||||
"kind": "bundle",
|
||||
"language": "go",
|
||||
"system": "arch",
|
||||
"from": "cmd/claude-code",
|
||||
"binary": "claude-code",
|
||||
"loads": [
|
||||
"claude-code"
|
||||
],
|
||||
"env": {
|
||||
"MESH_CLAUDE_CODE_STATE": "${dir:state}",
|
||||
"MESH_CLAUDE_CODE_FACTS": "${dir:state}/facts.json",
|
||||
"MESH_CLAUDE_CODE_SETTINGS": "${dir:state}/settings.json"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "files",
|
||||
"kind": "archive",
|
||||
"from": "files"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
+184
@@ -0,0 +1,184 @@
|
||||
{
|
||||
"module": "claude-licence-manager",
|
||||
"version": "1",
|
||||
"slug": "licmgr",
|
||||
"requires": [
|
||||
"postgres-database",
|
||||
"secret"
|
||||
],
|
||||
"contributes": {
|
||||
"postgres-database": {
|
||||
"name": "claude_licences",
|
||||
"readable": [
|
||||
"audit",
|
||||
"binding"
|
||||
]
|
||||
}
|
||||
},
|
||||
"binds": {
|
||||
"postgres-database": "${dir:state}/database.json"
|
||||
},
|
||||
"secrets": {
|
||||
"postgres-database": "${dir:state}/database.secret",
|
||||
"secret": {
|
||||
"grant-key": "${dir:state}/grant.key"
|
||||
}
|
||||
},
|
||||
"seats": [
|
||||
{
|
||||
"name": "anthropic-licence-manager",
|
||||
"scope": "mesh",
|
||||
"serves": [
|
||||
"licences",
|
||||
"bindings",
|
||||
"bind",
|
||||
"switch",
|
||||
"release",
|
||||
"refresh",
|
||||
"usage",
|
||||
"adopt",
|
||||
"current",
|
||||
"public-key"
|
||||
]
|
||||
}
|
||||
],
|
||||
"claims": [
|
||||
{
|
||||
"name": "anthropic-licence-manager",
|
||||
"scope": "mesh",
|
||||
"serves": [
|
||||
"licences",
|
||||
"bindings",
|
||||
"bind",
|
||||
"switch",
|
||||
"release",
|
||||
"refresh",
|
||||
"usage",
|
||||
"adopt",
|
||||
"current",
|
||||
"public-key"
|
||||
]
|
||||
}
|
||||
],
|
||||
"emits": [
|
||||
"licence.adopted",
|
||||
"licence.refused",
|
||||
"licence.bound",
|
||||
"licence.switched",
|
||||
"licence.released",
|
||||
"licence.rotated",
|
||||
"licence.failing",
|
||||
"usage.read"
|
||||
],
|
||||
"state": [
|
||||
"bindings"
|
||||
],
|
||||
"reads": [
|
||||
"claude-code.holdings"
|
||||
],
|
||||
"config": {
|
||||
"cadence_minutes": {
|
||||
"type": "number",
|
||||
"description": "How old a licence's grant may grow before it is rotated, in minutes; 0 keeps 240.",
|
||||
"minimum": 0,
|
||||
"trusted": true,
|
||||
"default": 240
|
||||
},
|
||||
"floor_minutes": {
|
||||
"type": "number",
|
||||
"description": "How little time a grant may have left before it is refreshed in any case, in minutes; 0 keeps 60.",
|
||||
"minimum": 0,
|
||||
"trusted": true,
|
||||
"default": 60
|
||||
},
|
||||
"failures_to_notify": {
|
||||
"type": "number",
|
||||
"description": "How many refreshes of a licence fail in a row before the operator is told, a count; 0 keeps 3.",
|
||||
"minimum": 0,
|
||||
"trusted": true,
|
||||
"default": 3
|
||||
},
|
||||
"cooldown_hours": {
|
||||
"type": "number",
|
||||
"description": "How long after telling the operator about a licence nothing more is said about it, in hours; 0 keeps 24.",
|
||||
"minimum": 0,
|
||||
"trusted": true,
|
||||
"default": 24
|
||||
},
|
||||
"refresh_warn_days": {
|
||||
"type": "number",
|
||||
"description": "How long before a licence's refresh token itself expires the operator is warned, in days; 0 keeps 3.",
|
||||
"minimum": 0,
|
||||
"trusted": true,
|
||||
"default": 3
|
||||
}
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"id": "state",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"place": ".",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "database-url",
|
||||
"type": "file",
|
||||
"path": "${dir:state}/database.url",
|
||||
"mode": "0600",
|
||||
"template": "files/database.url"
|
||||
},
|
||||
{
|
||||
"id": "settings",
|
||||
"type": "file",
|
||||
"path": "${dir:state}/settings.json",
|
||||
"mode": "0600",
|
||||
"takes-config": ["cadence_minutes", "floor_minutes", "failures_to_notify", "cooldown_hours", "refresh_warn_days"],
|
||||
"merge": "json",
|
||||
"template": "files/settings.json"
|
||||
},
|
||||
{
|
||||
"id": "prepare",
|
||||
"type": "process",
|
||||
"name": "claude-licence-manager-prepare",
|
||||
"artifact": "code",
|
||||
"run": [
|
||||
"./claude-licence-manager",
|
||||
"prepare"
|
||||
],
|
||||
"run-once": true,
|
||||
"env": {
|
||||
"DATABASE_URL_FILE": "${dir:state}/database.url"
|
||||
},
|
||||
"restart-on": [
|
||||
"database-url"
|
||||
]
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "code",
|
||||
"kind": "bundle",
|
||||
"language": "go",
|
||||
"system": "arch",
|
||||
"from": "cmd/claude-licence-manager",
|
||||
"binary": "claude-licence-manager",
|
||||
"loads": [
|
||||
"claude-licence-manager"
|
||||
],
|
||||
"env": {
|
||||
"DATABASE_URL_FILE": "${dir:state}/database.url",
|
||||
"MESH_LICENCE_STATE": "${dir:state}",
|
||||
"MESH_LICENCE_KEY_FILE": "${dir:state}/grant.key",
|
||||
"MESH_LICENCE_SETTINGS": "${dir:state}/settings.json"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "files",
|
||||
"kind": "archive",
|
||||
"from": "files"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
{
|
||||
"module": "clipmenu",
|
||||
"version": "1",
|
||||
"moved": true,
|
||||
"capabilities": [
|
||||
"package-manager"
|
||||
],
|
||||
"requires": [
|
||||
"x11-display"
|
||||
],
|
||||
"claims": [
|
||||
{
|
||||
"name": "node-clipboard",
|
||||
"scope": "node",
|
||||
"serves": [
|
||||
"history",
|
||||
"copy"
|
||||
]
|
||||
}
|
||||
],
|
||||
"tools": [
|
||||
"clipmenu_paste",
|
||||
"clipmenu_clear",
|
||||
"clipmenu_delete"
|
||||
],
|
||||
"items": [
|
||||
{
|
||||
"collection": "environment",
|
||||
"name": "cm-selections",
|
||||
"attributes": {
|
||||
"kind": "variable",
|
||||
"name": "CM_SELECTIONS"
|
||||
},
|
||||
"template": "files/env-cm-selections"
|
||||
},
|
||||
{
|
||||
"collection": "environment",
|
||||
"name": "cm-max-clips",
|
||||
"attributes": {
|
||||
"kind": "variable",
|
||||
"name": "CM_MAX_CLIPS"
|
||||
},
|
||||
"template": "files/env-cm-max-clips"
|
||||
},
|
||||
{
|
||||
"collection": "environment",
|
||||
"name": "cm-histlength",
|
||||
"attributes": {
|
||||
"kind": "variable",
|
||||
"name": "CM_HISTLENGTH"
|
||||
},
|
||||
"template": "files/env-cm-histlength"
|
||||
},
|
||||
{
|
||||
"collection": "contribution:node-display-session:config",
|
||||
"name": "display-session",
|
||||
"template": "files/i3/50-clipmenu.conf"
|
||||
}
|
||||
],
|
||||
"resources": [
|
||||
{
|
||||
"id": "package",
|
||||
"type": "package",
|
||||
"package": "clipmenu"
|
||||
},
|
||||
{
|
||||
"id": "greenclip",
|
||||
"type": "package",
|
||||
"package": "rofi-greenclip",
|
||||
"absent": true
|
||||
},
|
||||
{
|
||||
"id": "text-only",
|
||||
"type": "file",
|
||||
"path": "/usr/local/lib/mesh-clipmenu/xsel",
|
||||
"mode": "0755",
|
||||
"template": "files/bin/xsel"
|
||||
},
|
||||
{
|
||||
"id": "daemon-dropins",
|
||||
"type": "directory",
|
||||
"path": "${machine:account-home}/.config/systemd/user/clipmenud.service.d",
|
||||
"owner": "${machine:account}",
|
||||
"mode": "0755",
|
||||
"unknown": "move-out"
|
||||
},
|
||||
{
|
||||
"id": "daemon-dropin",
|
||||
"type": "file",
|
||||
"path": "${machine:account-home}/.config/systemd/user/clipmenud.service.d/mesh.conf",
|
||||
"owner": "${machine:account}",
|
||||
"mode": "0644",
|
||||
"template": "files/systemd/clipmenud-mesh.conf"
|
||||
},
|
||||
{
|
||||
"id": "launcher",
|
||||
"type": "file",
|
||||
"path": "/usr/local/lib/mesh-clipmenu/clipmenud-session",
|
||||
"mode": "0755",
|
||||
"template": "files/bin/clipmenud-session"
|
||||
},
|
||||
{
|
||||
"id": "daemon",
|
||||
"type": "service",
|
||||
"unit": "clipmenud.service",
|
||||
"scope": "user",
|
||||
"user": "${machine:account}",
|
||||
"state": "running",
|
||||
"boot": "enabled",
|
||||
"health": {
|
||||
"kind": "unit"
|
||||
}
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "tools",
|
||||
"kind": "bundle",
|
||||
"language": "go",
|
||||
"system": "arch",
|
||||
"from": "cmd/clipmenu-tools",
|
||||
"binary": "clipmenu-tools",
|
||||
"loads": [
|
||||
"clipmenu-tools"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "files",
|
||||
"kind": "archive",
|
||||
"from": "files"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
{
|
||||
"module": "confluence",
|
||||
"version": "1",
|
||||
"slug": "confl",
|
||||
"own-secrets": {
|
||||
"token": "${dir:state}/token"
|
||||
},
|
||||
"config": {
|
||||
"atlassian-url": {
|
||||
"type": "string",
|
||||
"description": "The address of the operator's Atlassian site the confluence tools call, as a URL such as https://example.atlassian.net, laid into the file as ATLASSIAN_URL; unset, the code falls back to its environment and answers no calls until it is given.",
|
||||
"trusted": true,
|
||||
"default": ""
|
||||
},
|
||||
"atlassian-email": {
|
||||
"type": "string",
|
||||
"description": "The email address of the Atlassian account the confluence tools sign in as with its API token, laid into the file as ATLASSIAN_EMAIL; unset, the code falls back to its environment and answers no calls until it is given.",
|
||||
"trusted": true,
|
||||
"default": ""
|
||||
}
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"id": "state",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"place": ".",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "config",
|
||||
"type": "file",
|
||||
"path": "${dir:state}/config.json",
|
||||
"merge": "json",
|
||||
"template": "files/config.json",
|
||||
"mode": "0600",
|
||||
"takes-config": [
|
||||
{
|
||||
"key": "atlassian-url",
|
||||
"as": "ATLASSIAN_URL"
|
||||
},
|
||||
{
|
||||
"key": "atlassian-email",
|
||||
"as": "ATLASSIAN_EMAIL"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"capabilities": [
|
||||
"container-runtime"
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "tools",
|
||||
"kind": "bundle",
|
||||
"language": "typescript",
|
||||
"entrypoints": [
|
||||
"tools/index.js"
|
||||
],
|
||||
"loads": [
|
||||
"tools/index.js"
|
||||
],
|
||||
"env": {
|
||||
"MESH_CONFLUENCE_TOKEN_FILE": "${dir:state}/token",
|
||||
"MESH_CONFLUENCE_CONFIG_FILE": "${dir:state}/config.json"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "files",
|
||||
"kind": "archive",
|
||||
"from": "files"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
{
|
||||
"module": "cups",
|
||||
"version": "1",
|
||||
"capabilities": [
|
||||
"package-manager",
|
||||
"service-manager"
|
||||
],
|
||||
"tools": [
|
||||
"cups_printers",
|
||||
"cups_queue",
|
||||
"cups_cancel",
|
||||
"cups_print",
|
||||
"cups_default",
|
||||
"cups_resume",
|
||||
"cups_drivers"
|
||||
],
|
||||
"resources": [
|
||||
{
|
||||
"id": "package",
|
||||
"type": "package",
|
||||
"package": "cups"
|
||||
},
|
||||
{
|
||||
"id": "driverless",
|
||||
"type": "package",
|
||||
"package": "cups-filters"
|
||||
},
|
||||
{
|
||||
"id": "socket",
|
||||
"type": "service",
|
||||
"unit": "cups.socket",
|
||||
"state": "running",
|
||||
"boot": "enabled"
|
||||
},
|
||||
{
|
||||
"id": "scheduler",
|
||||
"type": "service",
|
||||
"unit": "cups.service",
|
||||
"state": "running",
|
||||
"boot": "enabled"
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "tools",
|
||||
"kind": "bundle",
|
||||
"language": "go",
|
||||
"system": "arch",
|
||||
"from": "cmd/cups-tools",
|
||||
"binary": "cups-tools",
|
||||
"loads": [
|
||||
"cups-tools"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
{
|
||||
"module": "dbus",
|
||||
"version": "1",
|
||||
"capabilities": [
|
||||
"package-manager",
|
||||
"service-manager"
|
||||
],
|
||||
"claims": [
|
||||
{
|
||||
"name": "node-message-bus",
|
||||
"scope": "node"
|
||||
}
|
||||
],
|
||||
"emits": [
|
||||
"bus.stalled",
|
||||
"bus.recovered",
|
||||
"bus.restarted",
|
||||
"service.appeared",
|
||||
"service.left",
|
||||
"policy.denied"
|
||||
],
|
||||
"tools": [
|
||||
"dbus_names",
|
||||
"dbus_introspect",
|
||||
"dbus_monitor",
|
||||
"dbus_check",
|
||||
"dbus_health"
|
||||
],
|
||||
"resources": [
|
||||
{
|
||||
"id": "dbus",
|
||||
"type": "package",
|
||||
"package": "dbus"
|
||||
},
|
||||
{
|
||||
"id": "broker",
|
||||
"type": "package",
|
||||
"package": "dbus-broker"
|
||||
},
|
||||
{
|
||||
"id": "broker-units",
|
||||
"type": "package",
|
||||
"package": "dbus-broker-units"
|
||||
},
|
||||
{
|
||||
"id": "system-bus",
|
||||
"type": "service",
|
||||
"unit": "dbus-broker.service",
|
||||
"state": "running"
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "tools-go",
|
||||
"kind": "bundle",
|
||||
"language": "go",
|
||||
"system": "arch",
|
||||
"from": "cmd/dbus-tools",
|
||||
"binary": "dbus-tools",
|
||||
"loads": [
|
||||
"dbus-tools"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
{
|
||||
"module": "desk-channel",
|
||||
"version": "1",
|
||||
"slug": "desk",
|
||||
"runs-as": "desk-channel",
|
||||
"claims": [
|
||||
{
|
||||
"name": "channel",
|
||||
"scope": "mesh",
|
||||
"kind": "desktop",
|
||||
"capabilities": [
|
||||
"deliver",
|
||||
"silent",
|
||||
"loud",
|
||||
"edit",
|
||||
"private",
|
||||
"choice",
|
||||
"exact-render"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "intake",
|
||||
"scope": "mesh",
|
||||
"kind": "desktop"
|
||||
}
|
||||
],
|
||||
"consumes": [
|
||||
"dunst.action-chosen",
|
||||
"dunst.started",
|
||||
"dunst.paused"
|
||||
],
|
||||
"invokes": [
|
||||
"seat:node-notifier.send"
|
||||
],
|
||||
"state": [
|
||||
{
|
||||
"name": "shown",
|
||||
"ttl-seconds": 2592000
|
||||
}
|
||||
],
|
||||
"own-secrets": {
|
||||
"broker": "${dir:state}/broker"
|
||||
},
|
||||
"secrets-owner": "desk-channel",
|
||||
"tools": [
|
||||
"desk_channel_status"
|
||||
],
|
||||
"config": {
|
||||
"desktop-machines": {
|
||||
"type": "list",
|
||||
"description": "The machines, by node name, whose desktop shows the operator's questions and notifications, in the order they are tried; empty shows them on none.",
|
||||
"trusted": true,
|
||||
"default": []
|
||||
}
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"id": "account",
|
||||
"type": "user",
|
||||
"name": "desk-channel",
|
||||
"shell": "/usr/bin/nologin",
|
||||
"home": "/var/lib/desk-channel"
|
||||
},
|
||||
{
|
||||
"id": "state",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"owner": "desk-channel",
|
||||
"place": ".",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "settings",
|
||||
"type": "file",
|
||||
"path": "${dir:state}/settings.json",
|
||||
"mode": "0600",
|
||||
"owner": "desk-channel",
|
||||
"takes-config": ["desktop-machines"],
|
||||
"merge": "json",
|
||||
"template": "files/settings.json"
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "tools",
|
||||
"kind": "bundle",
|
||||
"language": "go",
|
||||
"system": "arch",
|
||||
"from": "cmd/desk-channel",
|
||||
"binary": "desk-channel",
|
||||
"loads": [
|
||||
"desk-channel"
|
||||
],
|
||||
"env": {
|
||||
"MESH_DESK_SETTINGS": "${dir:state}/settings.json"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "files",
|
||||
"kind": "archive",
|
||||
"from": "files"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
{
|
||||
"module": "dev-tools",
|
||||
"version": "1",
|
||||
"capabilities": [
|
||||
"package-manager"
|
||||
],
|
||||
"resources": [
|
||||
{
|
||||
"id": "go",
|
||||
"type": "package",
|
||||
"package": "go"
|
||||
},
|
||||
{
|
||||
"id": "c-compiler",
|
||||
"type": "package",
|
||||
"package": "gcc"
|
||||
},
|
||||
{
|
||||
"id": "make",
|
||||
"type": "package",
|
||||
"package": "make"
|
||||
},
|
||||
{
|
||||
"id": "nodejs",
|
||||
"type": "package",
|
||||
"package": "nodejs"
|
||||
},
|
||||
{
|
||||
"id": "npm",
|
||||
"type": "package",
|
||||
"package": "npm"
|
||||
},
|
||||
{
|
||||
"id": "python",
|
||||
"type": "package",
|
||||
"package": "python"
|
||||
},
|
||||
{
|
||||
"id": "git",
|
||||
"type": "package",
|
||||
"package": "git"
|
||||
},
|
||||
{
|
||||
"id": "jq",
|
||||
"type": "package",
|
||||
"package": "jq"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"module": "disk-load",
|
||||
"version": "1",
|
||||
"tools": [
|
||||
"disk_load",
|
||||
"disk_top",
|
||||
"disk_filesystems",
|
||||
"disk_devices",
|
||||
"cpu_top"
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "tools-go",
|
||||
"kind": "bundle",
|
||||
"language": "go",
|
||||
"system": "arch",
|
||||
"from": "cmd/disk-load",
|
||||
"binary": "disk-load",
|
||||
"loads": [
|
||||
"disk-load"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
{
|
||||
"module": "distribution",
|
||||
"version": "1",
|
||||
"provides": [
|
||||
{
|
||||
"name": "artifact-store",
|
||||
"scope": "mesh"
|
||||
}
|
||||
],
|
||||
"claims": [
|
||||
{
|
||||
"name": "mesh-artifact-store",
|
||||
"scope": "mesh"
|
||||
}
|
||||
],
|
||||
"capabilities": [
|
||||
"container-runtime"
|
||||
],
|
||||
"own-secrets": {
|
||||
"broker": "/var/lib/mesh/registry/broker"
|
||||
},
|
||||
"serves": {
|
||||
"artifact-store": {
|
||||
"port": 5000
|
||||
}
|
||||
},
|
||||
"listens": [
|
||||
{
|
||||
"name": "registry",
|
||||
"port": 5000,
|
||||
"protocol": "tcp",
|
||||
"from": "mesh",
|
||||
"why": "every machine pulls images and artifacts from here"
|
||||
}
|
||||
],
|
||||
"data": {
|
||||
"own": [
|
||||
{
|
||||
"id": "registry",
|
||||
"path": "${dir:registry-data}",
|
||||
"class": "rebuildable",
|
||||
"backup": "none",
|
||||
"measure": "shallow",
|
||||
"why": "the artifact store: every image is built again from its source, and too large to copy every night (ADR 0214 left it out)"
|
||||
}
|
||||
]
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"id": "state",
|
||||
"type": "directory",
|
||||
"path": "/var/lib/mesh/registry",
|
||||
"mode": "0700",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "registry-data",
|
||||
"type": "directory",
|
||||
"path": "/var/lib/mesh-registry",
|
||||
"mode": "0700",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "store",
|
||||
"type": "container",
|
||||
"name": "mesh-registry",
|
||||
"image": "registry@sha256:a3d8aaa63ed8681a604f1dea0aa03f100d5895b6a58ace528858a7b332415373",
|
||||
"ports": [
|
||||
"5000:5000"
|
||||
],
|
||||
"volumes": [
|
||||
"/var/lib/mesh-registry:/var/lib/registry"
|
||||
],
|
||||
"env": {
|
||||
"REGISTRY_STORAGE_DELETE_ENABLED": "true"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "collect",
|
||||
"type": "container",
|
||||
"name": "mesh-registry-collect",
|
||||
"image": "registry@sha256:a3d8aaa63ed8681a604f1dea0aa03f100d5895b6a58ace528858a7b332415373",
|
||||
"volumes": [
|
||||
"/var/lib/mesh-registry:/var/lib/registry"
|
||||
],
|
||||
"args": [
|
||||
"garbage-collect",
|
||||
"/etc/docker/registry/config.yml"
|
||||
],
|
||||
"schedule": "30 3 * * *",
|
||||
"while-stopped": [
|
||||
"store"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"module": "dmenu",
|
||||
"version": "1",
|
||||
"capabilities": [
|
||||
"package-manager"
|
||||
],
|
||||
"tools": [
|
||||
"dmenu_menu",
|
||||
"dmenu_session"
|
||||
],
|
||||
"resources": [
|
||||
{
|
||||
"id": "package",
|
||||
"type": "package",
|
||||
"package": "dmenu"
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "tools",
|
||||
"kind": "bundle",
|
||||
"language": "go",
|
||||
"system": "arch",
|
||||
"from": "cmd/dmenu-tools",
|
||||
"binary": "dmenu-tools",
|
||||
"loads": [
|
||||
"dmenu-tools"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
{
|
||||
"module": "dnsmasq",
|
||||
"version": "1",
|
||||
"upgrade": {
|
||||
"policy": "record",
|
||||
"why": "the mesh's resolver: a build that breaks it can stop a machine resolving the bus, and then neither the gate's rollback nor a push reaches it (hq ADR 0236, issue 260)"
|
||||
},
|
||||
"provides": [
|
||||
{
|
||||
"name": "wildcard-resolution",
|
||||
"scope": "mesh",
|
||||
"identity": false
|
||||
}
|
||||
],
|
||||
"requires": [
|
||||
"mesh-addressing"
|
||||
],
|
||||
"emits": [
|
||||
"name.added",
|
||||
"name.removed",
|
||||
"restarted",
|
||||
"restart-judged"
|
||||
],
|
||||
"own-secrets": {
|
||||
"broker": "${dir:mesh-state}/broker"
|
||||
},
|
||||
"claims": [
|
||||
{
|
||||
"name": "mesh-dns-resolver",
|
||||
"scope": "mesh"
|
||||
}
|
||||
],
|
||||
"tools": [
|
||||
"dnsmasq_health",
|
||||
"dnsmasq_names",
|
||||
"dnsmasq_resolve"
|
||||
],
|
||||
"listens": [
|
||||
{
|
||||
"name": "dns-udp",
|
||||
"port": 53,
|
||||
"protocol": "udp",
|
||||
"from": "mesh",
|
||||
"why": "one of the mesh's resolvers (ADR 0194, 0223): every node's and every container's resolver, beside any other holder of the seat — the mesh's own names answered here, a module's zone forwarded to it, the rest forwarded upstream",
|
||||
"fixed": true
|
||||
},
|
||||
{
|
||||
"name": "dns-tcp",
|
||||
"port": 53,
|
||||
"protocol": "tcp",
|
||||
"from": "mesh",
|
||||
"why": "the same names over tcp, which a resolver answers on as well and is asked for whenever an answer will not fit in a datagram. Declared because the daemon serves it: a declaration that covers one of the two protocols its own service listens on leaves the other closed while everything reports success",
|
||||
"fixed": true
|
||||
}
|
||||
],
|
||||
"resources": [
|
||||
{
|
||||
"id": "mesh-state",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"place": "mesh",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "package",
|
||||
"type": "package",
|
||||
"package": "dnsmasq"
|
||||
},
|
||||
{
|
||||
"id": "config",
|
||||
"type": "file",
|
||||
"path": "/etc/dnsmasq.conf",
|
||||
"mode": "0644",
|
||||
"template": "files/dnsmasq.conf"
|
||||
},
|
||||
{
|
||||
"id": "drop-ins",
|
||||
"type": "directory",
|
||||
"path": "/etc/systemd/system/dnsmasq.service.d",
|
||||
"mode": "0755",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "wait-for-address",
|
||||
"type": "file",
|
||||
"path": "/etc/systemd/system/dnsmasq.service.d/mesh.conf",
|
||||
"mode": "0644",
|
||||
"template": "files/mesh.conf"
|
||||
},
|
||||
{
|
||||
"id": "service",
|
||||
"type": "service",
|
||||
"unit": "dnsmasq.service",
|
||||
"state": "running",
|
||||
"boot": "enabled",
|
||||
"restart-on": [
|
||||
"config",
|
||||
"wait-for-address",
|
||||
"dnsmasq.fact-node-zones",
|
||||
"dnsmasq.fact-zones"
|
||||
],
|
||||
"health": {
|
||||
"kind": "unit"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "watch-dir",
|
||||
"type": "directory",
|
||||
"path": "/var/lib/dnsmasq-watch",
|
||||
"mode": "0755",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "watch",
|
||||
"type": "process",
|
||||
"name": "dnsmasq-watch",
|
||||
"artifact": "tools",
|
||||
"run": [
|
||||
"./dnsmasq-tools",
|
||||
"watch"
|
||||
],
|
||||
"health": {
|
||||
"kind": "tool",
|
||||
"tool": "dnsmasq_health",
|
||||
"interval": "20s",
|
||||
"timeout": "10s",
|
||||
"looks": 2,
|
||||
"grace": "60s"
|
||||
}
|
||||
}
|
||||
],
|
||||
"facts": {
|
||||
"node-zones": {
|
||||
"path": "/etc/mesh-resolver/nodes.conf",
|
||||
"template": "# Generated by the mesh. Do not edit — this file is replaced whenever a machine\n# joins or leaves, and an edit would survive until then and vanish.\n\nlocal=/{{.Suffix}}/\n# A machine's own name is a host record as well as a wildcard: asked for an IPv6 address, the\n# resolver then says the name exists and has none, where the wildcard alone said there is no such\n# name — and a resolver that reads that as final (musl, so every Alpine container) failed to find\n# the machine at all (novox/hq issue 262).\n{{range .Machines}}address=/{{.FQDN}}/{{.Address}}\nhost-record={{.FQDN}},{{.Address}}\n{{end}}"
|
||||
},
|
||||
"zones": {
|
||||
"path": "/etc/mesh-resolver/zones.conf",
|
||||
"template": "# Generated by the mesh. Do not edit — this file is replaced whenever a module declares a zone or\n# its machine moves (novox/hq ADR 0199). One forwarding line per zone, to the module answering it.\n\n{{range .Zones}}server=/{{.Zone}}/{{.Address}}#{{.Port}}\n{{end}}"
|
||||
}
|
||||
},
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "tools",
|
||||
"kind": "bundle",
|
||||
"language": "go",
|
||||
"system": "arch",
|
||||
"from": "cmd/dnsmasq-tools",
|
||||
"binary": "dnsmasq-tools",
|
||||
"loads": [
|
||||
"dnsmasq-tools"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "files",
|
||||
"kind": "archive",
|
||||
"from": "files"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"module": "docker-compose",
|
||||
"version": "1",
|
||||
"capabilities": [
|
||||
"package-manager"
|
||||
],
|
||||
"tools": [
|
||||
"docker_compose_projects",
|
||||
"docker_compose_ps",
|
||||
"docker_compose_logs",
|
||||
"docker_compose_config",
|
||||
"docker_compose_up",
|
||||
"docker_compose_down",
|
||||
"docker_compose_restart",
|
||||
"docker_compose_pull",
|
||||
"docker_compose_job"
|
||||
],
|
||||
"resources": [
|
||||
{
|
||||
"id": "package",
|
||||
"type": "package",
|
||||
"package": "docker-compose"
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "tools",
|
||||
"kind": "bundle",
|
||||
"language": "go",
|
||||
"system": "arch",
|
||||
"from": "cmd/docker-compose-tools",
|
||||
"binary": "docker-compose-tools",
|
||||
"loads": [
|
||||
"docker-compose-tools"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,179 @@
|
||||
{
|
||||
"module": "docker",
|
||||
"version": "1",
|
||||
"capabilities": [
|
||||
"package-manager",
|
||||
"service-manager",
|
||||
"privileged"
|
||||
],
|
||||
"invokes": [
|
||||
"seat:mesh-controller.images"
|
||||
],
|
||||
"claims": [
|
||||
{
|
||||
"name": "node-container-runtime",
|
||||
"scope": "node"
|
||||
}
|
||||
],
|
||||
"tools": [
|
||||
"docker_list",
|
||||
"docker_inspect",
|
||||
"docker_resolv_conf",
|
||||
"docker_logs",
|
||||
"docker_secrets_in_logs",
|
||||
"docker_secrets_in_events",
|
||||
"docker_stats",
|
||||
"docker_start",
|
||||
"docker_stop",
|
||||
"docker_restart",
|
||||
"docker_top",
|
||||
"docker_images",
|
||||
"docker_prune",
|
||||
"docker_prune_images",
|
||||
"docker_disk_usage",
|
||||
"docker_networks",
|
||||
"docker_volumes",
|
||||
"docker_events",
|
||||
"docker_daemon_config",
|
||||
"docker_unlabelled",
|
||||
"docker_problems",
|
||||
"docker_ports"
|
||||
],
|
||||
"replaces": {
|
||||
"docker_resolv_conf": [
|
||||
"docker exec cat /etc/resolv.conf"
|
||||
]
|
||||
},
|
||||
"config": {
|
||||
"log-max-size": {
|
||||
"type": "string",
|
||||
"description": "The size each container's log is cut at, a whole number from 1 with k, m or g after it; the runtime keeps log-max-file of them, so 100m and 10 hold about 1 GB per container (novox/hq issue 452). The runtime reads it only at its next start, which the mesh never forces, and a container created before that keeps the options it was created with until it is created again.",
|
||||
"pattern": "[1-9][0-9]*[kmg]",
|
||||
"trusted": true,
|
||||
"default": "100m"
|
||||
},
|
||||
"log-max-file": {
|
||||
"type": "number",
|
||||
"description": "How many of a container's log files of log-max-size the runtime keeps, a count from 1 to 99, the oldest dropped first; taken at the runtime's next start and by containers created after it, like log-max-size (novox/hq issue 452).",
|
||||
"minimum": 1,
|
||||
"maximum": 99,
|
||||
"trusted": true,
|
||||
"default": 10
|
||||
}
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"id": "package",
|
||||
"type": "package",
|
||||
"package": "docker"
|
||||
},
|
||||
{
|
||||
"id": "buildx",
|
||||
"type": "package",
|
||||
"package": "docker-buildx"
|
||||
},
|
||||
{
|
||||
"id": "socket",
|
||||
"type": "service",
|
||||
"unit": "docker.socket",
|
||||
"state": "running",
|
||||
"boot": "enabled"
|
||||
},
|
||||
{
|
||||
"id": "state",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"place": "mesh",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "log-rotation",
|
||||
"type": "file",
|
||||
"path": "${dir:state}/log-rotation.conf",
|
||||
"mode": "0600",
|
||||
"trusted": true,
|
||||
"template": "files/log-rotation.conf"
|
||||
},
|
||||
{
|
||||
"id": "log-rotation-check",
|
||||
"type": "process",
|
||||
"name": "docker-log-rotation-check",
|
||||
"artifact": "tools",
|
||||
"run": [
|
||||
"./docker-tools",
|
||||
"check-log-rotation"
|
||||
],
|
||||
"run-once": true,
|
||||
"env": {
|
||||
"DOCKER_LOG_ROTATION": "${dir:state}/log-rotation.conf"
|
||||
},
|
||||
"restart-on": [
|
||||
"log-rotation"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "daemon",
|
||||
"type": "file",
|
||||
"path": "/etc/docker/daemon.json",
|
||||
"mode": "0644",
|
||||
"into": "json",
|
||||
"trusted": true,
|
||||
"template": "files/daemon.json"
|
||||
},
|
||||
{
|
||||
"id": "runtime",
|
||||
"type": "service",
|
||||
"unit": "docker.service",
|
||||
"state": "running",
|
||||
"boot": "enabled",
|
||||
"reload-on": [
|
||||
"daemon"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "prune-service",
|
||||
"type": "file",
|
||||
"path": "/etc/systemd/system/docker-prune.service",
|
||||
"mode": "0644",
|
||||
"template": "files/docker-prune.service"
|
||||
},
|
||||
{
|
||||
"id": "prune-timer",
|
||||
"type": "file",
|
||||
"path": "/etc/systemd/system/docker-prune.timer",
|
||||
"mode": "0644",
|
||||
"template": "files/docker-prune.timer"
|
||||
},
|
||||
{
|
||||
"id": "prune",
|
||||
"type": "service",
|
||||
"unit": "docker-prune.timer",
|
||||
"state": "running",
|
||||
"boot": "enabled",
|
||||
"restart-on": [
|
||||
"prune-service",
|
||||
"prune-timer"
|
||||
]
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "tools",
|
||||
"kind": "bundle",
|
||||
"language": "go",
|
||||
"system": "arch",
|
||||
"from": "cmd/docker-tools",
|
||||
"binary": "docker-tools",
|
||||
"loads": [
|
||||
"docker-tools"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "files",
|
||||
"kind": "archive",
|
||||
"from": "files"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
{
|
||||
"module": "dunst",
|
||||
"version": "1",
|
||||
"moved": true,
|
||||
"capabilities": [
|
||||
"package-manager"
|
||||
],
|
||||
"claims": [
|
||||
{
|
||||
"name": "node-notifier",
|
||||
"scope": "node",
|
||||
"serves": [
|
||||
"send",
|
||||
"history"
|
||||
]
|
||||
}
|
||||
],
|
||||
"tools": [
|
||||
"dunst_pause",
|
||||
"dunst_resume",
|
||||
"dunst_close_all",
|
||||
"dunst_rules",
|
||||
"dunst_count",
|
||||
"dunst_reload"
|
||||
],
|
||||
"config": {
|
||||
"font-size": {
|
||||
"type": "number",
|
||||
"description": "The size of a notification's text, in points of Inter: 10 reads well on a screen of about 100 DPI, and a denser screen needs a larger size.",
|
||||
"minimum": 6,
|
||||
"maximum": 72,
|
||||
"predefined": "font-size",
|
||||
"default": 10
|
||||
},
|
||||
"width": {
|
||||
"type": "number",
|
||||
"description": "The width of a notification, in pixels: 250 fits a title of about forty characters at 10 points, and a larger font needs a wider notification.",
|
||||
"minimum": 50,
|
||||
"maximum": 4000,
|
||||
"default": 250
|
||||
}
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"id": "package",
|
||||
"type": "package",
|
||||
"package": "dunst"
|
||||
},
|
||||
{
|
||||
"id": "client",
|
||||
"type": "package",
|
||||
"package": "libnotify"
|
||||
},
|
||||
{
|
||||
"id": "configuration-dir",
|
||||
"type": "directory",
|
||||
"path": "${machine:account-home}/.config/dunst",
|
||||
"owner": "${machine:account}",
|
||||
"mode": "0755",
|
||||
"unknown": "move-out"
|
||||
},
|
||||
{
|
||||
"id": "dropins",
|
||||
"type": "directory",
|
||||
"path": "${machine:account-home}/.config/dunst/dunstrc.d",
|
||||
"owner": "${machine:account}",
|
||||
"mode": "0755",
|
||||
"unknown": "move-out",
|
||||
"knows": ["50-slack.conf"]
|
||||
},
|
||||
{
|
||||
"id": "configuration",
|
||||
"trusted": false,
|
||||
"type": "file",
|
||||
"path": "${machine:account-home}/.config/dunst/dunstrc",
|
||||
"owner": "${machine:account}",
|
||||
"mode": "0644",
|
||||
"template": "files/dunstrc"
|
||||
},
|
||||
{
|
||||
"id": "notifier",
|
||||
"type": "service",
|
||||
"unit": "dunst.service",
|
||||
"scope": "user",
|
||||
"user": "${machine:account}",
|
||||
"reload-on": [
|
||||
"configuration"
|
||||
]
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "tools",
|
||||
"kind": "bundle",
|
||||
"language": "go",
|
||||
"system": "arch",
|
||||
"from": "cmd/dunst-tools",
|
||||
"binary": "dunst-tools",
|
||||
"loads": [
|
||||
"dunst-tools"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "files",
|
||||
"kind": "archive",
|
||||
"from": "files"
|
||||
}
|
||||
]
|
||||
},
|
||||
"emits": [
|
||||
"action-chosen",
|
||||
"started",
|
||||
"paused"
|
||||
],
|
||||
"items": [
|
||||
{
|
||||
"collection": "contribution:node-display-session:config",
|
||||
"name": "display-session",
|
||||
"template": "files/i3/50-dunst.conf"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,195 @@
|
||||
{
|
||||
"module": "fail2ban",
|
||||
"version": "1",
|
||||
"capabilities": [
|
||||
"firewall"
|
||||
],
|
||||
"claims": [
|
||||
{
|
||||
"name": "node-intrusion-prevention",
|
||||
"scope": "node",
|
||||
"serves": [
|
||||
"status",
|
||||
"banned",
|
||||
"ban",
|
||||
"unban"
|
||||
]
|
||||
}
|
||||
],
|
||||
"tools": [
|
||||
"fail2ban_settings",
|
||||
"fail2ban_health"
|
||||
],
|
||||
"jailing": {
|
||||
"into": "/etc/fail2ban/jail.d/mesh.conf",
|
||||
"filter-into": "/etc/fail2ban/filter.d"
|
||||
},
|
||||
"config": {
|
||||
"own-addresses": {
|
||||
"type": "list",
|
||||
"description": "The addresses and networks outside the mesh that are the operator's own, each an IP address or a CIDR network: every jail ignores them beside the private ranges, the ban verb refuses them, and a failure a jail counted from one is said as a warning; empty is none.",
|
||||
"trusted": true,
|
||||
"default": []
|
||||
}
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"id": "package",
|
||||
"type": "package",
|
||||
"package": "fail2ban"
|
||||
},
|
||||
{
|
||||
"id": "state-dir",
|
||||
"type": "directory",
|
||||
"path": "/var/lib/mesh-fail2ban",
|
||||
"mode": "0755",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "own-addresses-list",
|
||||
"type": "file",
|
||||
"path": "/var/lib/mesh-fail2ban/own-addresses",
|
||||
"mode": "0644",
|
||||
"create-once": true,
|
||||
"template": "files/own-addresses"
|
||||
},
|
||||
{
|
||||
"id": "jail-d",
|
||||
"type": "directory",
|
||||
"path": "/etc/fail2ban/jail.d",
|
||||
"mode": "0755",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "action-d",
|
||||
"type": "directory",
|
||||
"path": "/etc/fail2ban/action.d",
|
||||
"mode": "0755",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "filter-d",
|
||||
"type": "directory",
|
||||
"path": "/etc/fail2ban/filter.d",
|
||||
"mode": "0755",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "run-dir",
|
||||
"type": "directory",
|
||||
"path": "/var/run/fail2ban",
|
||||
"mode": "0755",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "jail-local",
|
||||
"type": "file",
|
||||
"path": "/etc/fail2ban/jail.local",
|
||||
"mode": "0644",
|
||||
"template": "files/jail.local"
|
||||
},
|
||||
{
|
||||
"id": "jail-sshd",
|
||||
"type": "file",
|
||||
"path": "/etc/fail2ban/jail.d/sshd.conf",
|
||||
"mode": "0644",
|
||||
"template": "files/sshd.conf"
|
||||
},
|
||||
{
|
||||
"id": "own-addresses",
|
||||
"type": "file",
|
||||
"path": "/etc/fail2ban/mesh-own-addresses.json",
|
||||
"mode": "0644",
|
||||
"merge": "json",
|
||||
"takes-config": [
|
||||
"own-addresses"
|
||||
],
|
||||
"trusted": true,
|
||||
"template": "files/mesh-own-addresses.json"
|
||||
},
|
||||
{
|
||||
"id": "watch",
|
||||
"type": "process",
|
||||
"name": "fail2ban-watch",
|
||||
"artifact": "tools",
|
||||
"run": [
|
||||
"./fail2ban-tools",
|
||||
"watch"
|
||||
],
|
||||
"health": {
|
||||
"kind": "tool",
|
||||
"tool": "fail2ban_health",
|
||||
"interval": "60s",
|
||||
"timeout": "10s",
|
||||
"looks": 2,
|
||||
"grace": "90s"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "log",
|
||||
"type": "file",
|
||||
"path": "/var/log/fail2ban.log",
|
||||
"mode": "0640",
|
||||
"create-once": true,
|
||||
"template": "files/own-addresses"
|
||||
},
|
||||
{
|
||||
"id": "jail-recidive",
|
||||
"type": "file",
|
||||
"path": "/etc/fail2ban/jail.d/recidive.conf",
|
||||
"mode": "0644",
|
||||
"template": "files/recidive.conf"
|
||||
},
|
||||
{
|
||||
"id": "action-dualchain",
|
||||
"type": "file",
|
||||
"path": "/etc/fail2ban/action.d/iptables-allports-dualchain.conf",
|
||||
"mode": "0644",
|
||||
"template": "files/iptables-allports-dualchain.conf"
|
||||
},
|
||||
{
|
||||
"id": "logrotate",
|
||||
"type": "file",
|
||||
"path": "/etc/logrotate.d/fail2ban",
|
||||
"mode": "0644",
|
||||
"template": "files/fail2ban"
|
||||
},
|
||||
{
|
||||
"id": "run",
|
||||
"type": "service",
|
||||
"unit": "fail2ban.service",
|
||||
"state": "running",
|
||||
"boot": "enabled",
|
||||
"restart-on": [
|
||||
"jail-local",
|
||||
"jail-sshd",
|
||||
"jail-recidive",
|
||||
"action-dualchain",
|
||||
"composed-jails"
|
||||
],
|
||||
"health": {
|
||||
"kind": "unit"
|
||||
}
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "tools",
|
||||
"kind": "bundle",
|
||||
"language": "go",
|
||||
"system": "arch",
|
||||
"from": "cmd/fail2ban-tools",
|
||||
"binary": "fail2ban-tools",
|
||||
"loads": [
|
||||
"fail2ban-tools"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "files",
|
||||
"kind": "archive",
|
||||
"from": "files"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
{
|
||||
"module": "feh",
|
||||
"version": "1",
|
||||
"moved": true,
|
||||
"capabilities": [
|
||||
"package-manager"
|
||||
],
|
||||
"requires": [
|
||||
"x11-display"
|
||||
],
|
||||
"tools": [
|
||||
"feh_set",
|
||||
"feh_current"
|
||||
],
|
||||
"items": [
|
||||
{
|
||||
"collection": "shell:xinitrc:normal",
|
||||
"name": "xinitrc-normal",
|
||||
"template": "files/xinitrc-normal"
|
||||
},
|
||||
{
|
||||
"collection": "contribution:node-display-session:config",
|
||||
"name": "display-session",
|
||||
"template": "files/i3/50-feh.conf"
|
||||
}
|
||||
],
|
||||
"resources": [
|
||||
{
|
||||
"id": "package",
|
||||
"type": "package",
|
||||
"package": "feh"
|
||||
},
|
||||
{
|
||||
"id": "wallpapers",
|
||||
"type": "archive",
|
||||
"path": "${machine:account-home}/.local/share/feh/wallpapers",
|
||||
"owner": "${machine:account}",
|
||||
"artifact": "wallpapers",
|
||||
"unknown": "move-out"
|
||||
},
|
||||
{
|
||||
"id": "fehbg",
|
||||
"type": "file",
|
||||
"path": "${machine:account-home}/.fehbg",
|
||||
"owner": "${machine:account}",
|
||||
"mode": "0755",
|
||||
"template": "files/fehbg"
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "wallpapers",
|
||||
"kind": "archive",
|
||||
"from": "wallpaper"
|
||||
},
|
||||
{
|
||||
"name": "tools",
|
||||
"kind": "bundle",
|
||||
"language": "go",
|
||||
"system": "arch",
|
||||
"from": "cmd/feh-tools",
|
||||
"binary": "feh-tools",
|
||||
"loads": [
|
||||
"feh-tools"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "files",
|
||||
"kind": "archive",
|
||||
"from": "files"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
{
|
||||
"module": "flatpak",
|
||||
"version": "1",
|
||||
"capabilities": [
|
||||
"package-manager"
|
||||
],
|
||||
"tools": [
|
||||
"flatpak_list",
|
||||
"flatpak_runtimes",
|
||||
"flatpak_remotes",
|
||||
"flatpak_updates",
|
||||
"flatpak_unused",
|
||||
"flatpak_disk_usage",
|
||||
"flatpak_install",
|
||||
"flatpak_remove",
|
||||
"flatpak_update",
|
||||
"flatpak_remove_unused",
|
||||
"flatpak_job"
|
||||
],
|
||||
"resources": [
|
||||
{
|
||||
"id": "package",
|
||||
"type": "package",
|
||||
"package": "flatpak"
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "tools",
|
||||
"kind": "bundle",
|
||||
"language": "go",
|
||||
"system": "arch",
|
||||
"from": "cmd/flatpak-tools",
|
||||
"binary": "flatpak-tools",
|
||||
"loads": [
|
||||
"flatpak-tools"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
{
|
||||
"module": "fonts",
|
||||
"version": "1",
|
||||
"capabilities": [
|
||||
"package-manager"
|
||||
],
|
||||
"tools": [
|
||||
"fonts_families",
|
||||
"fonts_match",
|
||||
"fonts_glyph",
|
||||
"fonts_sources",
|
||||
"fonts_config",
|
||||
"fonts_cache_rebuild"
|
||||
],
|
||||
"resources": [
|
||||
{
|
||||
"id": "monospace",
|
||||
"type": "package",
|
||||
"package": "ttf-jetbrains-mono-nerd"
|
||||
},
|
||||
{
|
||||
"id": "interface",
|
||||
"type": "package",
|
||||
"package": "inter-font"
|
||||
},
|
||||
{
|
||||
"id": "symbols",
|
||||
"type": "package",
|
||||
"package": "ttf-nerd-fonts-symbols"
|
||||
},
|
||||
{
|
||||
"id": "noto",
|
||||
"type": "package",
|
||||
"package": "noto-fonts"
|
||||
},
|
||||
{
|
||||
"id": "emoji",
|
||||
"type": "package",
|
||||
"package": "noto-fonts-emoji"
|
||||
},
|
||||
{
|
||||
"id": "defaults",
|
||||
"type": "file",
|
||||
"path": "${machine:account-home}/.config/fontconfig/conf.d/50-mesh-fonts.conf",
|
||||
"owner": "${machine:account}",
|
||||
"mode": "0644",
|
||||
"template": "files/50-mesh-fonts.conf"
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "tools",
|
||||
"kind": "bundle",
|
||||
"language": "go",
|
||||
"system": "arch",
|
||||
"from": "cmd/fonts-tools",
|
||||
"binary": "fonts-tools",
|
||||
"loads": [
|
||||
"fonts-tools"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "files",
|
||||
"kind": "archive",
|
||||
"from": "files"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
{
|
||||
"module": "forticlient",
|
||||
"version": "1",
|
||||
"upgrade": {
|
||||
"policy": "record",
|
||||
"why": "its adapter routes the company's domains on the machine a person works on: a build that breaks it cuts the person off from work names until a person pushes the next (hq ADR 0236, ADR 0247)"
|
||||
},
|
||||
"capabilities": [
|
||||
"service-manager"
|
||||
],
|
||||
"requires": [
|
||||
"x11-display",
|
||||
"split-dns"
|
||||
],
|
||||
"tools": [
|
||||
"forticlient_status",
|
||||
"forticlient_restart",
|
||||
"forticlient_check"
|
||||
],
|
||||
"resources": [
|
||||
{
|
||||
"id": "scheduler",
|
||||
"type": "service",
|
||||
"unit": "forticlient.service",
|
||||
"state": "running",
|
||||
"boot": "enabled"
|
||||
},
|
||||
{
|
||||
"id": "split-dns",
|
||||
"type": "process",
|
||||
"name": "forticlient-split-dns",
|
||||
"artifact": "tools",
|
||||
"run": [
|
||||
"./forticlient-tools",
|
||||
"split-dns"
|
||||
],
|
||||
"health": {
|
||||
"kind": "unit"
|
||||
}
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "tools",
|
||||
"kind": "bundle",
|
||||
"language": "go",
|
||||
"system": "arch",
|
||||
"from": "cmd/forticlient-tools",
|
||||
"binary": "forticlient-tools",
|
||||
"loads": [
|
||||
"forticlient-tools"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,545 @@
|
||||
{
|
||||
"module": "gitea",
|
||||
"version": "1",
|
||||
"moved": true,
|
||||
"requires": [
|
||||
"postgres-database",
|
||||
"route",
|
||||
"secret"
|
||||
],
|
||||
"contributes": {
|
||||
"postgres-database": {
|
||||
"name": "gitea"
|
||||
},
|
||||
"route": {
|
||||
"web": {
|
||||
"label": "git",
|
||||
"endpoint": "web"
|
||||
},
|
||||
"internal-api-refused": {
|
||||
"label": "git",
|
||||
"path": "/api/internal",
|
||||
"deny": true,
|
||||
"priority": 100000
|
||||
}
|
||||
}
|
||||
},
|
||||
"binds": {
|
||||
"postgres-database": "${dir:state}/database.json",
|
||||
"route": "${dir:state}/route.json"
|
||||
},
|
||||
"secrets": {
|
||||
"postgres-database": "${dir:state}/database.secret",
|
||||
"secret": {
|
||||
"internal-token": "${dir:state}/internal-token.secret",
|
||||
"admin": "${dir:state}/admin.secret"
|
||||
}
|
||||
},
|
||||
"capabilities": [
|
||||
"container-runtime"
|
||||
],
|
||||
"emits": [
|
||||
"repo.created",
|
||||
"issue.opened",
|
||||
"pull.merged",
|
||||
"pull.updated",
|
||||
"pull.closed",
|
||||
"forge.push",
|
||||
"forge.create",
|
||||
"forge.delete",
|
||||
"forge.fork",
|
||||
"forge.status",
|
||||
"forge.pull-request.opened",
|
||||
"forge.pull-request.reopened",
|
||||
"forge.pull-request.synchronized",
|
||||
"forge.pull-request.edited",
|
||||
"forge.pull-request.closed",
|
||||
"forge.pull-request.merged",
|
||||
"forge.pull-request.labeled",
|
||||
"forge.pull-request.unlabeled",
|
||||
"forge.pull-request.assigned",
|
||||
"forge.pull-request.unassigned",
|
||||
"forge.pull-request.reviewed",
|
||||
"forge.pull-request.review-requested",
|
||||
"forge.pull-request.commented",
|
||||
"forge.pull-request.changed",
|
||||
"forge.issue-comment.created",
|
||||
"forge.issue-comment.edited",
|
||||
"forge.issue-comment.deleted",
|
||||
"forge.issues.opened",
|
||||
"forge.issues.reopened",
|
||||
"forge.issues.closed",
|
||||
"forge.issues.edited",
|
||||
"forge.issues.labeled",
|
||||
"forge.issues.unlabeled",
|
||||
"forge.issues.assigned",
|
||||
"forge.issues.unassigned",
|
||||
"forge.issues.changed",
|
||||
"forge.release.published",
|
||||
"forge.release.updated",
|
||||
"forge.release.deleted",
|
||||
"forge.release.changed",
|
||||
"forge.repository.created",
|
||||
"forge.repository.deleted",
|
||||
"forge.repository.changed",
|
||||
"forge.wiki.changed",
|
||||
"forge.other"
|
||||
],
|
||||
"consumes": [
|
||||
"mesh-controller.checked",
|
||||
"node-build-agent.started"
|
||||
],
|
||||
"listens": [
|
||||
{
|
||||
"name": "web",
|
||||
"port": 3000,
|
||||
"protocol": "tcp",
|
||||
"from": "mesh",
|
||||
"why": "the forge, over http"
|
||||
},
|
||||
{
|
||||
"name": "ssh",
|
||||
"port": 22,
|
||||
"protocol": "tcp",
|
||||
"from": "mesh",
|
||||
"why": "git over ssh, gitea's own unmodified sshd. Published on the machine's own side at 222, the mesh's fixed public convention — not 22, which the machine's own daemon holds and a module does not take"
|
||||
},
|
||||
{
|
||||
"name": "forge-events",
|
||||
"port": 3047,
|
||||
"protocol": "tcp",
|
||||
"from": "machine",
|
||||
"why": "the forge's system webhook, every event signed with a secret the module keeps, from the forge's container on the docker bridge to the module's receiver at the bridge's gateway 172.17.0.1 (novox/hq issue 729)"
|
||||
}
|
||||
],
|
||||
"serves": {
|
||||
"npm-package-registry": {
|
||||
"scheme": "http",
|
||||
"port": 3000,
|
||||
"npm-path": "/api/packages/novox/npm/",
|
||||
"public-root": "https://${bound:route:name-web}/api/packages/novox/npm/"
|
||||
},
|
||||
"git": {
|
||||
"scheme": "http",
|
||||
"port": 3000
|
||||
}
|
||||
},
|
||||
"receives": {
|
||||
"npm-package-registry": "${dir:grants}/npm.json"
|
||||
},
|
||||
"grants": {
|
||||
"npm-package-registry": "${dir:grants}"
|
||||
},
|
||||
"claims": [
|
||||
{
|
||||
"name": "npm-package-registry",
|
||||
"scope": "mesh"
|
||||
},
|
||||
{
|
||||
"name": "git",
|
||||
"scope": "mesh"
|
||||
}
|
||||
],
|
||||
"data": {
|
||||
"own": [
|
||||
{
|
||||
"id": "data",
|
||||
"path": "${dir:data}",
|
||||
"class": "valuable",
|
||||
"why": "every repository, its issues and attachments, and the package registry"
|
||||
}
|
||||
],
|
||||
"consumers": {
|
||||
"npm-package-registry": {
|
||||
"class": "rebuildable",
|
||||
"in": "data",
|
||||
"why": "a consumer's packages are published again from its source"
|
||||
}
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"url": {
|
||||
"type": "string",
|
||||
"description": "The address the module's tools reach the forge at, as a URL; unset, the code falls back to its environment, else this machine's gitea on its port.",
|
||||
"trusted": true,
|
||||
"default": ""
|
||||
},
|
||||
"agent-read-teams": {
|
||||
"type": "object",
|
||||
"description": "The read teams of the agents' forge accounts (ADR 0365 clause 3): each team by name, {\"<team>\": {\"repos\": [\"<owner>/<repo>\", ...], \"members\": [\"<node>\", ...]}}. The forge gets a team agent-read-<team> that reads only, with exactly those repositories and the accounts agent-<node>; a team taken out of the value is emptied. Nothing else on the forge is touched; an agent account is in no team until it is listed here.",
|
||||
"trusted": true,
|
||||
"default": {}
|
||||
},
|
||||
"repositories": {
|
||||
"type": "object",
|
||||
"description": "The repositories of the organisation novox the mesh holds (ADR 0428): each by name, {\"<name>\": {\"private\": true, \"description\": \"...\"}}. One that does not exist is made by the module's setup login under its own account, its main protected and given a first commit (a README naming the description and a merge-check.sh), its rule narrowed to no push and the tools' merge requiring mesh/repo-check and mesh/merge-gate, and only then moved into the organisation; one that exists only has main's rule put right, its statuses kept. A repository taken out of the value is never touched.",
|
||||
"trusted": true,
|
||||
"default": {}
|
||||
}
|
||||
},
|
||||
"facts": {
|
||||
"forge-host": {
|
||||
"path": "/etc/gitea/forge-host",
|
||||
"template": "{{range .Machines}}{{if eq .Name $.Node}}{{.FQDN}}{{end}}{{end}}\n"
|
||||
}
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"id": "mesh-state",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"place": "mesh",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "runtime-state",
|
||||
"type": "directory",
|
||||
"path": "${dir:mesh-state}/state",
|
||||
"mode": "0700",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "forge-patches",
|
||||
"type": "directory",
|
||||
"path": "/var/lib/mesh/forge-patches",
|
||||
"mode": "0733",
|
||||
"owner": "${machine:account}",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "state",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"place": ".",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "grants",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "server-env",
|
||||
"type": "file",
|
||||
"path": "${dir:state}/server.env",
|
||||
"mode": "0600",
|
||||
"template": "files/server.env"
|
||||
},
|
||||
{
|
||||
"id": "data",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"owner": "1000:1000",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "server",
|
||||
"type": "container",
|
||||
"health": {
|
||||
"kind": "http",
|
||||
"endpoint": "web",
|
||||
"path": "/api/healthz",
|
||||
"status": 200,
|
||||
"needs": "postgres-database"
|
||||
},
|
||||
"name": "gitea",
|
||||
"image": "gitea/gitea@sha256:87a67ee09d3ae0d1df5fda5dcda3e2a1f9236a45b0a59025d6e00e46adc43bef",
|
||||
"env": {
|
||||
"DB_TYPE": "postgres",
|
||||
"USER_UID": "1000",
|
||||
"USER_GID": "1000"
|
||||
},
|
||||
"env-file": [
|
||||
"${dir:state}/server.env"
|
||||
],
|
||||
"ports": [
|
||||
"3000",
|
||||
"222:22"
|
||||
],
|
||||
"volumes": [
|
||||
"${dir:data}:/data"
|
||||
],
|
||||
"secrets-in-environment": "gitea honours GITEA__database__PASSWD__FILE and GITEA__security__INTERNAL_TOKEN__FILE; convertible, awaiting a bed that proves it",
|
||||
"logging": "journald"
|
||||
},
|
||||
{
|
||||
"id": "admin-bootstrap",
|
||||
"type": "container",
|
||||
"name": "mesh-gitea-admin",
|
||||
"image": "gitea/gitea@sha256:87a67ee09d3ae0d1df5fda5dcda3e2a1f9236a45b0a59025d6e00e46adc43bef",
|
||||
"run-once": true,
|
||||
"env": {
|
||||
"USER_UID": "1000",
|
||||
"USER_GID": "1000",
|
||||
"MESH_GITEA_ADMIN_USER": "mesh-admin"
|
||||
},
|
||||
"env-file": [
|
||||
"${dir:state}/server.env"
|
||||
],
|
||||
"volumes": [
|
||||
"${dir:data}:/data",
|
||||
"${dir:state}/admin.secret:/run/secrets/admin:ro"
|
||||
],
|
||||
"args": [
|
||||
"/bin/sh",
|
||||
"-c",
|
||||
"su-exec git gitea admin user create --admin --username \"$MESH_GITEA_ADMIN_USER\" --email mesh-admin@localhost --password \"$(cat /run/secrets/admin)\" --must-change-password=false || true"
|
||||
],
|
||||
"secrets-in-environment": "gitea honours GITEA__database__PASSWD__FILE and GITEA__security__INTERNAL_TOKEN__FILE; convertible, awaiting a bed that proves it"
|
||||
},
|
||||
{
|
||||
"id": "origins",
|
||||
"type": "file",
|
||||
"path": "${dir:mesh-state}/origins",
|
||||
"mode": "0644",
|
||||
"template": "files/origins"
|
||||
},
|
||||
{
|
||||
"id": "runtime-config",
|
||||
"type": "file",
|
||||
"path": "${dir:mesh-state}/config.json",
|
||||
"mode": "0600",
|
||||
"template": "files/config.json",
|
||||
"merge": "json",
|
||||
"takes-config": [
|
||||
"url"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "agent-teams-file",
|
||||
"type": "file",
|
||||
"path": "${dir:mesh-state}/agent-teams.json",
|
||||
"mode": "0600",
|
||||
"template": "files/agent-teams.json",
|
||||
"merge": "json",
|
||||
"takes-config": [
|
||||
"agent-read-teams"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "repositories-file",
|
||||
"type": "file",
|
||||
"path": "${dir:mesh-state}/repositories.json",
|
||||
"mode": "0600",
|
||||
"template": "files/repositories.json"
|
||||
},
|
||||
{
|
||||
"id": "consumers",
|
||||
"type": "file",
|
||||
"path": "${dir:state}/consumers.json",
|
||||
"mode": "0600",
|
||||
"template": "files/consumers.json"
|
||||
},
|
||||
{
|
||||
"id": "agent-teams",
|
||||
"type": "process",
|
||||
"name": "gitea-agent-teams",
|
||||
"artifact": "agent-teams",
|
||||
"run": [
|
||||
"./agent-teams"
|
||||
],
|
||||
"run-once": true,
|
||||
"env": {
|
||||
"MESH_GITEA_URL": "http://127.0.0.1:${port:3000}",
|
||||
"MESH_GITEA_ADMIN_USER": "mesh-admin",
|
||||
"MESH_GITEA_ADMIN_PASSWORD_FILE": "${dir:state}/admin.secret",
|
||||
"MESH_AGENT_TEAMS_FILE": "${dir:mesh-state}/agent-teams.json"
|
||||
},
|
||||
"restart-on": [
|
||||
"agent-teams-file"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "repositories",
|
||||
"type": "process",
|
||||
"name": "gitea-repositories",
|
||||
"artifact": "repositories",
|
||||
"run": [
|
||||
"./repositories",
|
||||
"sync"
|
||||
],
|
||||
"run-once": true,
|
||||
"env": {
|
||||
"MESH_GITEA_URL": "http://127.0.0.1:${port:3000}",
|
||||
"MESH_GITEA_ADMIN_USER": "mesh-admin",
|
||||
"MESH_GITEA_ADMIN_PASSWORD_FILE": "${dir:state}/admin.secret",
|
||||
"MESH_GITEA_TOOLS_USER": "mesh-tools",
|
||||
"MESH_REPOSITORIES_FILE": "${dir:mesh-state}/repositories.json",
|
||||
"MESH_REPOSITORIES_OUTCOME": "${dir:runtime-state}/repositories-outcome.json"
|
||||
},
|
||||
"restart-on": [
|
||||
"repositories-file"
|
||||
]
|
||||
}
|
||||
],
|
||||
"provides": [
|
||||
{
|
||||
"name": "npm-package-registry",
|
||||
"scope": "mesh",
|
||||
"identity": {
|
||||
"max": 40,
|
||||
"in": "a Gitea user name"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "git",
|
||||
"scope": "mesh"
|
||||
},
|
||||
{
|
||||
"name": "gitea-read",
|
||||
"scope": "mesh",
|
||||
"credential": {
|
||||
"issued-by": "software",
|
||||
"tool": "gitea_agent_token"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "forge-account",
|
||||
"scope": "mesh"
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "code",
|
||||
"kind": "bundle",
|
||||
"language": "typescript",
|
||||
"entrypoints": [
|
||||
"index.js",
|
||||
"tools/index.js",
|
||||
"provisioner/index.js"
|
||||
],
|
||||
"loads": [
|
||||
"index.js",
|
||||
"tools/index.js",
|
||||
"provisioner/index.js"
|
||||
],
|
||||
"env": {
|
||||
"MESH_GITEA_URL": "http://127.0.0.1:${port:3000}",
|
||||
"MESH_GITEA_CONFIG_FILE": "${dir:mesh-state}/config.json",
|
||||
"MESH_GITEA_ADMIN_USER": "mesh-admin",
|
||||
"MESH_GITEA_ADMIN_PASSWORD_FILE": "${dir:state}/admin.secret",
|
||||
"MESH_GITEA_TOOLS_USER": "mesh-tools",
|
||||
"MESH_GITEA_STATE_DIR": "${dir:runtime-state}",
|
||||
"MESH_RECEIVES": "${dir:grants}/npm.json",
|
||||
"MESH_GITEA_HOOK_URL": "http://172.17.0.1:3047",
|
||||
"MESH_GITEA_HOOK_PORT": "3047",
|
||||
"MESH_GITEA_HOOK_HOST": "172.17.0.1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "npm-registry",
|
||||
"kind": "bundle",
|
||||
"language": "go",
|
||||
"system": "arch",
|
||||
"from": "cmd/npm-registry",
|
||||
"binary": "npm-registry",
|
||||
"loads": [
|
||||
"npm-registry"
|
||||
],
|
||||
"env": {
|
||||
"MESH_GITEA_URL": "http://127.0.0.1:${port:3000}",
|
||||
"MESH_GITEA_ADMIN_USER": "mesh-admin",
|
||||
"MESH_GITEA_ADMIN_PASSWORD_FILE": "${dir:state}/admin.secret",
|
||||
"MESH_NPM_OWNER": "novox"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "forge",
|
||||
"kind": "bundle",
|
||||
"language": "go",
|
||||
"system": "arch",
|
||||
"from": "cmd/forge",
|
||||
"binary": "forge",
|
||||
"loads": [
|
||||
"forge"
|
||||
],
|
||||
"env": {
|
||||
"MESH_GITEA_URL": "http://127.0.0.1:${port:3000}",
|
||||
"MESH_GITEA_TOOLS_USER": "mesh-tools",
|
||||
"MESH_GITEA_TOKEN_FILE": "${dir:runtime-state}/token",
|
||||
"MESH_GITEA_PATCH_DIR": "${dir:forge-patches}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "files",
|
||||
"kind": "archive",
|
||||
"from": "files"
|
||||
},
|
||||
{
|
||||
"name": "agent-token",
|
||||
"kind": "bundle",
|
||||
"language": "go",
|
||||
"system": "arch",
|
||||
"from": "cmd/agent-token",
|
||||
"binary": "agent-token",
|
||||
"loads": [
|
||||
"agent-token"
|
||||
],
|
||||
"env": {
|
||||
"MESH_GITEA_URL": "http://127.0.0.1:${port:3000}",
|
||||
"MESH_GITEA_ADMIN_USER": "mesh-admin",
|
||||
"MESH_GITEA_ADMIN_PASSWORD_FILE": "${dir:state}/admin.secret",
|
||||
"MESH_GITEA_ORIGINS_FILE": "${dir:mesh-state}/origins"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "agent-teams",
|
||||
"kind": "bundle",
|
||||
"language": "go",
|
||||
"system": "arch",
|
||||
"from": "cmd/agent-teams",
|
||||
"binary": "agent-teams",
|
||||
"loads": [
|
||||
"agent-teams"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "repositories",
|
||||
"kind": "bundle",
|
||||
"language": "go",
|
||||
"system": "arch",
|
||||
"from": "cmd/repositories",
|
||||
"binary": "repositories",
|
||||
"loads": [
|
||||
"repositories"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "forge-account-provider",
|
||||
"kind": "bundle",
|
||||
"language": "go",
|
||||
"system": "arch",
|
||||
"from": "cmd/forge-account-provider",
|
||||
"binary": "forge-account-provider",
|
||||
"loads": [
|
||||
"forge-account-provider"
|
||||
],
|
||||
"env": {
|
||||
"MESH_GITEA_URL": "http://127.0.0.1:${port:3000}",
|
||||
"MESH_GITEA_ADMIN_USER": "mesh-admin",
|
||||
"MESH_GITEA_ADMIN_PASSWORD_FILE": "${dir:state}/admin.secret",
|
||||
"MESH_GITEA_ORIGINS_FILE": "${dir:mesh-state}/origins",
|
||||
"MESH_GITEA_SSH_PORT": "222",
|
||||
"MESH_FORGE_HOST_FILE": "/etc/gitea/forge-host"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"jails": [
|
||||
{
|
||||
"name": "gitea",
|
||||
"failregex": "^.*Failed authentication attempt for .* from <HOST>(?::\\d+)?\\s*$\n ^.*Invalid user .* from <HOST> port \\d+\\s*$\n ^.*User \\S+ from <HOST> not allowed because .*$",
|
||||
"jail": "backend = systemd\njournalmatch = CONTAINER_NAME=gitea\nport = http,https,222\nmaxretry = 3\nfindtime = 1d\nbantime = 1d"
|
||||
}
|
||||
],
|
||||
"state": [
|
||||
"bound",
|
||||
"announced"
|
||||
],
|
||||
"reads": [
|
||||
"mesh-controller.assignments",
|
||||
"ssh-client.keys"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
{
|
||||
"module": "gitlab",
|
||||
"version": "1",
|
||||
"own-secrets": {
|
||||
"token": "${dir:state}/token"
|
||||
},
|
||||
"config": {
|
||||
"gitlab-url": {
|
||||
"type": "string",
|
||||
"description": "The address of the GitLab instance the gitlab tools call, as a URL such as https://gitlab.com, laid into the file as GITLAB_URL; unset, the code falls back to its environment and answers no calls until it is given.",
|
||||
"trusted": true,
|
||||
"default": ""
|
||||
}
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"id": "state",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"place": ".",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "config",
|
||||
"type": "file",
|
||||
"path": "${dir:state}/config.json",
|
||||
"merge": "json",
|
||||
"template": "files/config.json",
|
||||
"mode": "0600",
|
||||
"takes-config": [
|
||||
{
|
||||
"key": "gitlab-url",
|
||||
"as": "GITLAB_URL"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"capabilities": [
|
||||
"container-runtime"
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "tools",
|
||||
"kind": "bundle",
|
||||
"language": "typescript",
|
||||
"entrypoints": [
|
||||
"tools/index.js"
|
||||
],
|
||||
"loads": [
|
||||
"tools/index.js"
|
||||
],
|
||||
"env": {
|
||||
"MESH_GITLAB_TOKEN_FILE": "${dir:state}/token",
|
||||
"MESH_GITLAB_CONFIG_FILE": "${dir:state}/config.json"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "files",
|
||||
"kind": "archive",
|
||||
"from": "files"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
{
|
||||
"module": "gnome-keyring",
|
||||
"version": "1",
|
||||
"moved": true,
|
||||
"capabilities": [
|
||||
"package-manager"
|
||||
],
|
||||
"claims": [
|
||||
{
|
||||
"name": "node-secret-service",
|
||||
"scope": "node"
|
||||
}
|
||||
],
|
||||
"tools": [
|
||||
"gnome_keyring_unlocked",
|
||||
"gnome_keyring_lock",
|
||||
"gnome_keyring_collections",
|
||||
"gnome_keyring_ssh_keys"
|
||||
],
|
||||
"items": [
|
||||
{
|
||||
"collection": "shell:xinitrc:first",
|
||||
"name": "xinitrc-first",
|
||||
"template": "files/xinitrc-first"
|
||||
}
|
||||
],
|
||||
"resources": [
|
||||
{
|
||||
"id": "package",
|
||||
"type": "package",
|
||||
"package": "gnome-keyring"
|
||||
},
|
||||
{
|
||||
"id": "library",
|
||||
"type": "package",
|
||||
"package": "libsecret"
|
||||
},
|
||||
{
|
||||
"id": "manager",
|
||||
"type": "package",
|
||||
"package": "seahorse"
|
||||
},
|
||||
{
|
||||
"id": "pam-login",
|
||||
"type": "file",
|
||||
"path": "/etc/pam.d/login",
|
||||
"mode": "0644",
|
||||
"into": "block",
|
||||
"at": "end",
|
||||
"template": "files/pam/login"
|
||||
},
|
||||
{
|
||||
"id": "pam-passwd",
|
||||
"type": "file",
|
||||
"path": "/etc/pam.d/passwd",
|
||||
"mode": "0644",
|
||||
"into": "block",
|
||||
"at": "end",
|
||||
"template": "files/pam/passwd"
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "tools",
|
||||
"kind": "bundle",
|
||||
"language": "go",
|
||||
"system": "arch",
|
||||
"from": "cmd/gnome-keyring-tools",
|
||||
"binary": "gnome-keyring-tools",
|
||||
"loads": [
|
||||
"gnome-keyring-tools"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "files",
|
||||
"kind": "archive",
|
||||
"from": "files"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,225 @@
|
||||
{
|
||||
"module": "grafana",
|
||||
"version": "1",
|
||||
"emits": [
|
||||
"alert.firing"
|
||||
],
|
||||
"own-secrets": {
|
||||
"admin": "${dir:mesh-state}/admin"
|
||||
},
|
||||
"capabilities": [
|
||||
"container-runtime"
|
||||
],
|
||||
"listens": [
|
||||
{
|
||||
"name": "web",
|
||||
"port": 3000,
|
||||
"protocol": "tcp",
|
||||
"from": "mesh",
|
||||
"why": "the dashboards. Also 3000 inside, like the forge - which is the mesh's port assignment earning its keep"
|
||||
}
|
||||
],
|
||||
"data": {
|
||||
"own": [
|
||||
{
|
||||
"id": "data",
|
||||
"path": "${dir:data}",
|
||||
"class": "valuable",
|
||||
"why": "dashboards, users and alert rules"
|
||||
}
|
||||
]
|
||||
},
|
||||
"config": {
|
||||
"user": {
|
||||
"type": "string",
|
||||
"description": "The Grafana account the module's tools sign in as with the vault's password; the file's default is admin.",
|
||||
"trusted": true,
|
||||
"default": "admin"
|
||||
},
|
||||
"url": {
|
||||
"type": "string",
|
||||
"description": "The address the module's tools reach Grafana at, as a URL; unset, the code falls back to its environment, else this machine's Grafana on its port.",
|
||||
"trusted": true,
|
||||
"default": ""
|
||||
}
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"id": "mesh-state",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"place": "mesh",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "state",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"place": ".",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "data",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"owner": "472:472",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "admin-secret",
|
||||
"type": "file",
|
||||
"path": "${dir:state}/admin.secret",
|
||||
"mode": "0400",
|
||||
"owner": "472:472",
|
||||
"template": "files/admin.secret"
|
||||
},
|
||||
{
|
||||
"id": "oidc-secret",
|
||||
"type": "file",
|
||||
"path": "${dir:state}/oidc-client.secret",
|
||||
"mode": "0400",
|
||||
"owner": "472:472",
|
||||
"template": "files/oidc-client.secret"
|
||||
},
|
||||
{
|
||||
"id": "oidc-env",
|
||||
"type": "file",
|
||||
"path": "${dir:state}/oidc.env",
|
||||
"mode": "0644",
|
||||
"template": "files/oidc.env"
|
||||
},
|
||||
{
|
||||
"id": "influxdb-datasources",
|
||||
"type": "directory",
|
||||
"path": "${dir:state}/datasources",
|
||||
"mode": "0755",
|
||||
"owner": "472:472",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "influxdb-credential",
|
||||
"type": "directory",
|
||||
"path": "${dir:state}/influxdb",
|
||||
"mode": "0700",
|
||||
"owner": "472:472",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "influxdb-secret",
|
||||
"type": "file",
|
||||
"path": "${dir:influxdb-credential}/influxdb-api",
|
||||
"mode": "0400",
|
||||
"owner": "472:472",
|
||||
"template": "files/influxdb-api",
|
||||
"only-when-bound": "influxdb-api"
|
||||
},
|
||||
{
|
||||
"id": "influxdb-datasource",
|
||||
"type": "file",
|
||||
"path": "${dir:influxdb-datasources}/mesh-influxdb.yaml",
|
||||
"mode": "0644",
|
||||
"template": "files/mesh-influxdb.yaml",
|
||||
"only-when-bound": "influxdb-api"
|
||||
},
|
||||
{
|
||||
"id": "server",
|
||||
"type": "container",
|
||||
"name": "grafana",
|
||||
"image": "grafana/grafana@sha256:ac461fb352abc50da10a51c7d02462e9c05488f11f53f14b3ad79a8145f638a0",
|
||||
"health": {
|
||||
"kind": "http",
|
||||
"endpoint": "web",
|
||||
"path": "/"
|
||||
},
|
||||
"ports": [
|
||||
"3000"
|
||||
],
|
||||
"volumes": [
|
||||
"${dir:data}:/var/lib/grafana",
|
||||
"${dir:state}/admin.secret:/run/secrets/admin:ro",
|
||||
"${dir:state}/oidc-client.secret:/run/secrets/oidc-client:ro",
|
||||
"${dir:influxdb-credential}:/run/secrets/influxdb:ro",
|
||||
"${dir:influxdb-datasources}:/etc/grafana/provisioning/datasources:ro"
|
||||
],
|
||||
"env": {
|
||||
"GF_SECURITY_ADMIN_PASSWORD__FILE": "/run/secrets/admin"
|
||||
},
|
||||
"env-file": [
|
||||
"${dir:state}/oidc.env"
|
||||
],
|
||||
"restart-on": [
|
||||
"oidc-env",
|
||||
"oidc-secret",
|
||||
"influxdb-datasource",
|
||||
"influxdb-secret"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "runtime-config",
|
||||
"type": "file",
|
||||
"path": "${dir:mesh-state}/config.json",
|
||||
"mode": "0600",
|
||||
"template": "files/config.json",
|
||||
"merge": "json",
|
||||
"takes-config": ["user", "url"],
|
||||
"protected": ["password", "token"]
|
||||
}
|
||||
],
|
||||
"requires": [
|
||||
"route",
|
||||
"oidc-client",
|
||||
{
|
||||
"name": "influxdb-api",
|
||||
"optional": true
|
||||
}
|
||||
],
|
||||
"contributes": {
|
||||
"route": {
|
||||
"label": "grafana",
|
||||
"endpoint": "web"
|
||||
},
|
||||
"oidc-client": {
|
||||
"label": "grafana",
|
||||
"endpoint": "web",
|
||||
"callback": "/login/generic_oauth"
|
||||
},
|
||||
"influxdb-api": {
|
||||
"access": "read"
|
||||
}
|
||||
},
|
||||
"binds": {
|
||||
"route": "${dir:state}/route.json",
|
||||
"oidc-client": "${dir:state}/oidc.json",
|
||||
"influxdb-api": "${dir:state}/influxdb.json"
|
||||
},
|
||||
"secrets": {
|
||||
"oidc-client": "${dir:mesh-state}/oidc-client",
|
||||
"influxdb-api": "${dir:mesh-state}/influxdb-api"
|
||||
},
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "code",
|
||||
"kind": "bundle",
|
||||
"language": "typescript",
|
||||
"entrypoints": [
|
||||
"index.js",
|
||||
"tools/index.js"
|
||||
],
|
||||
"loads": [
|
||||
"index.js",
|
||||
"tools/index.js"
|
||||
],
|
||||
"env": {
|
||||
"MESH_GRAFANA_URL": "http://127.0.0.1:${port:3000}",
|
||||
"MESH_GRAFANA_CONFIG_FILE": "${dir:mesh-state}/config.json"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "files",
|
||||
"kind": "archive",
|
||||
"from": "files"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
{
|
||||
"module": "hello-web",
|
||||
"slug": "hello",
|
||||
"version": "1",
|
||||
"capabilities": [
|
||||
"container-runtime"
|
||||
],
|
||||
"requires": [
|
||||
"route"
|
||||
],
|
||||
"contributes": {
|
||||
"route": {
|
||||
"label": "hello",
|
||||
"endpoint": "web"
|
||||
}
|
||||
},
|
||||
"binds": {
|
||||
"route": "${dir:state}/route.json"
|
||||
},
|
||||
"listens": [
|
||||
{
|
||||
"name": "web",
|
||||
"port": 8080,
|
||||
"protocol": "tcp",
|
||||
"from": "mesh",
|
||||
"why": "the demo web page; only the route-proxy reaches it, and the public name is a route grant"
|
||||
}
|
||||
],
|
||||
"resources": [
|
||||
{
|
||||
"id": "state",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"place": ".",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "page",
|
||||
"type": "file",
|
||||
"path": "${dir:state}/index.html",
|
||||
"mode": "0644",
|
||||
"template": "files/index.html"
|
||||
},
|
||||
{
|
||||
"id": "net",
|
||||
"type": "network",
|
||||
"name": "hello-web"
|
||||
},
|
||||
{
|
||||
"id": "server",
|
||||
"type": "container",
|
||||
"name": "hello-web",
|
||||
"network": "hello-web",
|
||||
"ports": [
|
||||
"8080"
|
||||
],
|
||||
"volumes": [
|
||||
"${dir:state}/index.html:/www/index.html:ro"
|
||||
],
|
||||
"args": [
|
||||
"sh",
|
||||
"-c",
|
||||
"while true; do { printf 'HTTP/1.1 200 OK\\r\\nContent-Type: text/plain\\r\\nConnection: close\\r\\n\\r\\n'; cat /www/index.html; } | nc -l -p 8080; done"
|
||||
],
|
||||
"artifact": "server"
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "server",
|
||||
"kind": "upstream",
|
||||
"from": "alpine@sha256:28bd5fe8b56d1bd048e5babf5b10710ebe0bae67db86916198a6eec434943f8b"
|
||||
},
|
||||
{
|
||||
"name": "files",
|
||||
"kind": "archive",
|
||||
"from": "files"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,209 @@
|
||||
{
|
||||
"module": "home-assistant",
|
||||
"version": "1",
|
||||
"slug": "hass",
|
||||
"capabilities": [
|
||||
"container-runtime"
|
||||
],
|
||||
"emits": [
|
||||
"state.changed"
|
||||
],
|
||||
"own-secrets": {
|
||||
"token": "${dir:mesh-state}/token"
|
||||
},
|
||||
"listens": [
|
||||
{
|
||||
"name": "web",
|
||||
"port": 8123,
|
||||
"protocol": "tcp",
|
||||
"from": "mesh",
|
||||
"why": "the dashboard, the API and the companion apps"
|
||||
},
|
||||
{
|
||||
"name": "sonos-events",
|
||||
"port": 1400,
|
||||
"protocol": "tcp",
|
||||
"from": "mesh",
|
||||
"why": "the Sonos integration's event callback: speakers push their state changes here"
|
||||
},
|
||||
{
|
||||
"name": "webrtc",
|
||||
"port": 18555,
|
||||
"protocol": "tcp",
|
||||
"from": "mesh",
|
||||
"why": "the bundled go2rtc's WebRTC port, which camera streams to a browser use"
|
||||
}
|
||||
],
|
||||
"data": {
|
||||
"own": [
|
||||
{
|
||||
"id": "config",
|
||||
"path": "${dir:config}",
|
||||
"class": "valuable",
|
||||
"active": "1d",
|
||||
"why": "the house's configuration, automations and history; written all the time"
|
||||
}
|
||||
]
|
||||
},
|
||||
"config": {
|
||||
"url": {
|
||||
"type": "string",
|
||||
"description": "The address the module's tools reach Home Assistant at, as a URL; unset, the code falls back to its environment, else this machine's Home Assistant on its port.",
|
||||
"trusted": true,
|
||||
"default": ""
|
||||
}
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"id": "mesh-state",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"place": "mesh",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "state",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"place": ".",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "config",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "written",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "server",
|
||||
"type": "container",
|
||||
"name": "home-assistant",
|
||||
"image": "ghcr.io/home-assistant/home-assistant@sha256:d8922685169707fd91e8b9729902d975f06157d005e422874d201e0261dda196",
|
||||
"network": "host",
|
||||
"env": {
|
||||
"TZ": "Etc/UTC"
|
||||
},
|
||||
"volumes": [
|
||||
"${dir:config}:/config"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "runtime-config",
|
||||
"type": "file",
|
||||
"path": "${dir:mesh-state}/config.json",
|
||||
"mode": "0600",
|
||||
"template": "files/config.json",
|
||||
"merge": "json",
|
||||
"takes-config": ["url"]
|
||||
},
|
||||
{
|
||||
"id": "provisions-env",
|
||||
"type": "file",
|
||||
"path": "${dir:state}/provisions.env",
|
||||
"mode": "0600",
|
||||
"template": "files/provisions.env"
|
||||
},
|
||||
{
|
||||
"id": "provisions",
|
||||
"type": "process",
|
||||
"name": "home-assistant-provisions",
|
||||
"artifact": "code",
|
||||
"run": [
|
||||
"node",
|
||||
"provisions/index.js"
|
||||
],
|
||||
"run-once": true,
|
||||
"env-file": [
|
||||
"${dir:state}/provisions.env"
|
||||
],
|
||||
"restart-on": [
|
||||
"provisions-env",
|
||||
"bound-mqtt-topic",
|
||||
"secret-mqtt-topic",
|
||||
"bound-sonarr-api",
|
||||
"secret-sonarr-api",
|
||||
"bound-radarr-api",
|
||||
"secret-radarr-api",
|
||||
"bound-lidarr-api",
|
||||
"secret-lidarr-api"
|
||||
]
|
||||
}
|
||||
],
|
||||
"requires": [
|
||||
{
|
||||
"name": "lidarr-api",
|
||||
"optional": true
|
||||
},
|
||||
{
|
||||
"name": "mqtt-topic",
|
||||
"optional": true
|
||||
},
|
||||
{
|
||||
"name": "radarr-api",
|
||||
"optional": true
|
||||
},
|
||||
"route",
|
||||
{
|
||||
"name": "sonarr-api",
|
||||
"optional": true
|
||||
}
|
||||
],
|
||||
"contributes": {
|
||||
"mqtt-topic": {
|
||||
"topics": [
|
||||
"#"
|
||||
]
|
||||
},
|
||||
"route": {
|
||||
"label": "home-assistant",
|
||||
"endpoint": "web"
|
||||
}
|
||||
},
|
||||
"binds": {
|
||||
"route": "${dir:state}/route.json",
|
||||
"mqtt-topic": "${dir:state}/mqtt-topic.json",
|
||||
"sonarr-api": "${dir:state}/sonarr-api.json",
|
||||
"radarr-api": "${dir:state}/radarr-api.json",
|
||||
"lidarr-api": "${dir:state}/lidarr-api.json"
|
||||
},
|
||||
"secrets": {
|
||||
"mqtt-topic": "${dir:state}/mqtt-topic.secret",
|
||||
"sonarr-api": "${dir:state}/sonarr-api.secret",
|
||||
"radarr-api": "${dir:state}/radarr-api.secret",
|
||||
"lidarr-api": "${dir:state}/lidarr-api.secret"
|
||||
},
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "code",
|
||||
"kind": "bundle",
|
||||
"language": "typescript",
|
||||
"entrypoints": [
|
||||
"index.js",
|
||||
"tools/index.js",
|
||||
"provisions/index.js"
|
||||
],
|
||||
"loads": [
|
||||
"index.js",
|
||||
"tools/index.js"
|
||||
],
|
||||
"env": {
|
||||
"MESH_HOMEASSISTANT_URL": "http://127.0.0.1:${port:8123}",
|
||||
"MESH_HOMEASSISTANT_TOKEN_FILE": "${dir:mesh-state}/token",
|
||||
"MESH_HOMEASSISTANT_CONFIG_FILE": "${dir:mesh-state}/config.json"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "files",
|
||||
"kind": "archive",
|
||||
"from": "files"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
{
|
||||
"module": "hostname",
|
||||
"version": "1",
|
||||
"claims": [
|
||||
{
|
||||
"name": "node-hostname",
|
||||
"scope": "node",
|
||||
"serves": [
|
||||
"entries",
|
||||
"add",
|
||||
"remove"
|
||||
]
|
||||
}
|
||||
],
|
||||
"config": {
|
||||
"hostname": {
|
||||
"type": "string",
|
||||
"description": "The machine's host name, written to /etc/hostname: the operator's name for this machine, with no default (novox/hq ADR 0112).",
|
||||
"trusted": true,
|
||||
"required": true
|
||||
}
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"id": "own",
|
||||
"type": "file",
|
||||
"path": "/etc/hosts",
|
||||
"mode": "0644",
|
||||
"into": "block",
|
||||
"at": "start",
|
||||
"template": "files/hosts"
|
||||
},
|
||||
{
|
||||
"id": "name",
|
||||
"type": "file",
|
||||
"path": "/etc/hostname",
|
||||
"mode": "0644",
|
||||
"template": "files/hostname"
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "tools",
|
||||
"kind": "bundle",
|
||||
"language": "go",
|
||||
"system": "arch",
|
||||
"from": "cmd/hostname-tools",
|
||||
"binary": "hostname-tools",
|
||||
"loads": [
|
||||
"hostname-tools"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "files",
|
||||
"kind": "archive",
|
||||
"from": "files"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
{
|
||||
"module": "i3",
|
||||
"version": "1",
|
||||
"moved": true,
|
||||
"capabilities": [
|
||||
"package-manager"
|
||||
],
|
||||
"requires": [
|
||||
"x11-display"
|
||||
],
|
||||
"claims": [
|
||||
{
|
||||
"name": "node-display-session",
|
||||
"scope": "node",
|
||||
"serves": [
|
||||
"reload",
|
||||
"workspaces",
|
||||
"windows"
|
||||
]
|
||||
}
|
||||
],
|
||||
"tools": [
|
||||
"i3_focus",
|
||||
"i3_move",
|
||||
"i3_layout_save",
|
||||
"i3_layout_restore",
|
||||
"i3_exec",
|
||||
"i3_kill",
|
||||
"i3_bindings",
|
||||
"i3_config_check",
|
||||
"i3_marks",
|
||||
"i3_scratchpad"
|
||||
],
|
||||
"items": [
|
||||
{
|
||||
"collection": "environment",
|
||||
"name": "xdg-current-desktop",
|
||||
"attributes": {
|
||||
"kind": "variable",
|
||||
"name": "XDG_CURRENT_DESKTOP"
|
||||
},
|
||||
"template": "files/env-xdg-current-desktop"
|
||||
},
|
||||
{
|
||||
"collection": "environment",
|
||||
"name": "xdg-session-desktop",
|
||||
"attributes": {
|
||||
"kind": "variable",
|
||||
"name": "XDG_SESSION_DESKTOP"
|
||||
},
|
||||
"template": "files/env-xdg-session-desktop"
|
||||
},
|
||||
{
|
||||
"collection": "shell:xinitrc:last",
|
||||
"name": "xinitrc-last",
|
||||
"template": "files/xinitrc-last"
|
||||
}
|
||||
],
|
||||
"resources": [
|
||||
{
|
||||
"id": "package",
|
||||
"type": "package",
|
||||
"package": "i3-wm"
|
||||
},
|
||||
{
|
||||
"id": "package-dex",
|
||||
"type": "package",
|
||||
"package": "dex"
|
||||
},
|
||||
{
|
||||
"id": "config-dir",
|
||||
"type": "directory",
|
||||
"path": "${machine:account-home}/.config/i3",
|
||||
"owner": "${machine:account}",
|
||||
"mode": "0755",
|
||||
"unknown": "move-out",
|
||||
"knows": ["scripts/"]
|
||||
},
|
||||
{
|
||||
"id": "drop-ins",
|
||||
"type": "directory",
|
||||
"path": "${machine:account-home}/.config/i3/config.d",
|
||||
"owner": "${machine:account}",
|
||||
"mode": "0755",
|
||||
"unknown": "move-out",
|
||||
"knows": ["10-asus.conf", "20-g14.conf"]
|
||||
},
|
||||
{
|
||||
"id": "config",
|
||||
"type": "file",
|
||||
"path": "${machine:account-home}/.config/i3/config",
|
||||
"owner": "${machine:account}",
|
||||
"mode": "0644",
|
||||
"template": "files/config"
|
||||
},
|
||||
{
|
||||
"id": "session",
|
||||
"type": "file",
|
||||
"path": "/etc/lemurs/wms/i3",
|
||||
"mode": "0755",
|
||||
"template": "files/wms/i3"
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "tools",
|
||||
"kind": "bundle",
|
||||
"language": "go",
|
||||
"system": "arch",
|
||||
"from": "cmd/i3-tools",
|
||||
"binary": "i3-tools",
|
||||
"loads": [
|
||||
"i3-tools"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "files",
|
||||
"kind": "archive",
|
||||
"from": "files"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
{
|
||||
"module": "i3status-rust",
|
||||
"version": "1",
|
||||
"moved": true,
|
||||
"capabilities": [
|
||||
"package-manager"
|
||||
],
|
||||
"requires": [
|
||||
"x11-display"
|
||||
],
|
||||
"claims": [
|
||||
{
|
||||
"name": "node-bar",
|
||||
"scope": "node"
|
||||
}
|
||||
],
|
||||
"tools": [
|
||||
"i3status_rust_reload",
|
||||
"i3status_rust_blocks",
|
||||
"i3status_rust_block_run",
|
||||
"i3status_rust_themes"
|
||||
],
|
||||
"items": [
|
||||
{
|
||||
"collection": "shell:xinitrc:normal",
|
||||
"name": "xinitrc-normal",
|
||||
"template": "files/xinitrc-normal"
|
||||
},
|
||||
{
|
||||
"collection": "contribution:node-display-session:config",
|
||||
"name": "display-session",
|
||||
"template": "files/i3/60-i3status-rust.conf"
|
||||
}
|
||||
],
|
||||
"resources": [
|
||||
{
|
||||
"id": "package",
|
||||
"type": "package",
|
||||
"package": "i3status-rust"
|
||||
},
|
||||
{
|
||||
"id": "configuration-dir",
|
||||
"type": "directory",
|
||||
"path": "${machine:account-home}/.config/i3status-rust",
|
||||
"owner": "${machine:account}",
|
||||
"mode": "0755",
|
||||
"unknown": "move-out"
|
||||
},
|
||||
{
|
||||
"id": "icons-dir",
|
||||
"type": "directory",
|
||||
"path": "${machine:account-home}/.config/i3status-rust/icons",
|
||||
"owner": "${machine:account}",
|
||||
"mode": "0755",
|
||||
"unknown": "move-out"
|
||||
},
|
||||
{
|
||||
"id": "top-bar",
|
||||
"type": "file",
|
||||
"path": "${machine:account-home}/.config/i3status-rust/top-bar.toml",
|
||||
"owner": "${machine:account}",
|
||||
"mode": "0644",
|
||||
"template": "files/top-bar.toml"
|
||||
},
|
||||
{
|
||||
"id": "bottom-bar",
|
||||
"type": "file",
|
||||
"path": "${machine:account-home}/.config/i3status-rust/bottom-bar.toml",
|
||||
"owner": "${machine:account}",
|
||||
"mode": "0644",
|
||||
"template": "files/bottom-bar.toml"
|
||||
},
|
||||
{
|
||||
"id": "icons",
|
||||
"type": "file",
|
||||
"path": "${machine:account-home}/.config/i3status-rust/icons/custom-icons.toml",
|
||||
"owner": "${machine:account}",
|
||||
"mode": "0644",
|
||||
"template": "files/icons/custom-icons.toml"
|
||||
},
|
||||
{
|
||||
"id": "updates",
|
||||
"type": "file",
|
||||
"path": "${machine:account-home}/.local/bin/i3status-updates",
|
||||
"owner": "${machine:account}",
|
||||
"mode": "0755",
|
||||
"template": "files/bin/i3status-updates"
|
||||
},
|
||||
{
|
||||
"id": "watchdog",
|
||||
"type": "file",
|
||||
"path": "${machine:account-home}/.local/bin/i3bar-watchdog",
|
||||
"owner": "${machine:account}",
|
||||
"mode": "0755",
|
||||
"template": "files/bin/i3bar-watchdog"
|
||||
},
|
||||
{
|
||||
"id": "value",
|
||||
"type": "file",
|
||||
"path": "${machine:account-home}/.local/bin/i3status-value",
|
||||
"owner": "${machine:account}",
|
||||
"mode": "0755",
|
||||
"template": "files/bin/i3status-value"
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "tools",
|
||||
"kind": "bundle",
|
||||
"language": "go",
|
||||
"system": "arch",
|
||||
"from": "cmd/i3status-rust-tools",
|
||||
"binary": "i3status-rust-tools",
|
||||
"loads": [
|
||||
"i3status-rust-tools"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "files",
|
||||
"kind": "archive",
|
||||
"from": "files"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
{
|
||||
"module": "icecast",
|
||||
"version": "1",
|
||||
"requires": [
|
||||
"route",
|
||||
"secret"
|
||||
],
|
||||
"contributes": {
|
||||
"route": {
|
||||
"label": "icecast",
|
||||
"endpoint": "stream"
|
||||
}
|
||||
},
|
||||
"binds": {
|
||||
"route": "${dir:state}/route.json"
|
||||
},
|
||||
"secrets": {
|
||||
"secret": {
|
||||
"source": "${dir:state}/source.secret",
|
||||
"admin": "${dir:state}/admin.secret",
|
||||
"relay": "${dir:state}/relay.secret"
|
||||
}
|
||||
},
|
||||
"capabilities": [
|
||||
"container-runtime"
|
||||
],
|
||||
"emits": [
|
||||
"stream.started",
|
||||
"stream.stopped"
|
||||
],
|
||||
"listens": [
|
||||
{
|
||||
"name": "stream",
|
||||
"port": 8000,
|
||||
"protocol": "tcp",
|
||||
"from": "mesh",
|
||||
"why": "streams in from sources (HTTP PUT) and out to listeners, plus the status and admin pages; a public name is its route"
|
||||
}
|
||||
],
|
||||
"data": {
|
||||
"own": [
|
||||
{
|
||||
"id": "logs",
|
||||
"path": "${dir:logs}",
|
||||
"class": "cache",
|
||||
"why": "the streaming server's logs"
|
||||
}
|
||||
]
|
||||
},
|
||||
"config": {
|
||||
"url": {
|
||||
"type": "string",
|
||||
"description": "The address the module's tools reach Icecast at, as a URL; unset, the code falls back to its environment, else this machine's Icecast on its port.",
|
||||
"trusted": true,
|
||||
"default": ""
|
||||
},
|
||||
"user": {
|
||||
"type": "string",
|
||||
"description": "The Icecast admin account the module's tools sign in as; unset, the code falls back to its environment, else admin.",
|
||||
"trusted": true,
|
||||
"default": ""
|
||||
}
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"id": "mesh-state",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"place": "mesh",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "state",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"place": ".",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "logs",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"owner": "100:101",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "server-conf",
|
||||
"type": "file",
|
||||
"path": "${dir:state}/icecast.xml",
|
||||
"mode": "0600",
|
||||
"template": "files/icecast.xml"
|
||||
},
|
||||
{
|
||||
"id": "net",
|
||||
"type": "network",
|
||||
"name": "icecast"
|
||||
},
|
||||
{
|
||||
"id": "server",
|
||||
"type": "container",
|
||||
"name": "icecast",
|
||||
"image": "infiniteproject/icecast@sha256:cd506cf3dfe31ce05fd37d7e672dbd1213e7255cc93d28ecf5a3b547af4e162c",
|
||||
"network": "icecast",
|
||||
"ports": [
|
||||
"8000"
|
||||
],
|
||||
"volumes": [
|
||||
"${dir:state}/icecast.xml:/etc/icecast.xml:ro",
|
||||
"${dir:logs}:/var/log/icecast"
|
||||
],
|
||||
"restart-on": [
|
||||
"server-conf"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "runtime-config",
|
||||
"type": "file",
|
||||
"path": "${dir:mesh-state}/config.json",
|
||||
"mode": "0600",
|
||||
"template": "files/config.json",
|
||||
"merge": "json",
|
||||
"takes-config": ["url", "user"]
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "code",
|
||||
"kind": "bundle",
|
||||
"language": "typescript",
|
||||
"entrypoints": [
|
||||
"index.js",
|
||||
"tools/index.js"
|
||||
],
|
||||
"loads": [
|
||||
"index.js",
|
||||
"tools/index.js"
|
||||
],
|
||||
"env": {
|
||||
"MESH_ICECAST_URL": "http://127.0.0.1:${port:8000}",
|
||||
"MESH_ICECAST_CONFIG_FILE": "${dir:mesh-state}/config.json",
|
||||
"MESH_ICECAST_ADMIN_PASSWORD_FILE": "${dir:state}/admin.secret"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "files",
|
||||
"kind": "archive",
|
||||
"from": "files"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,198 @@
|
||||
{
|
||||
"module": "influxdb",
|
||||
"version": "1",
|
||||
"provides": [
|
||||
{
|
||||
"name": "influxdb-api",
|
||||
"scope": "mesh",
|
||||
"identity": {
|
||||
"in": "an InfluxDB v1 authorization"
|
||||
}
|
||||
}
|
||||
],
|
||||
"capabilities": [
|
||||
"container-runtime"
|
||||
],
|
||||
"own-secrets": {
|
||||
"admin": "${dir:state}/admin.secret",
|
||||
"admin-token": "${dir:state}/admin-token.secret"
|
||||
},
|
||||
"listens": [
|
||||
{
|
||||
"name": "api",
|
||||
"port": 8086,
|
||||
"protocol": "tcp",
|
||||
"from": "mesh",
|
||||
"why": "queries, writes and the web UI, over http; consumers granted influxdb-api sign in with the mesh's credential, and a name is a route grant"
|
||||
}
|
||||
],
|
||||
"config": {
|
||||
"org": {
|
||||
"type": "string",
|
||||
"description": "The organisation influxdb-api names to its consumers and the module's tools write to; mesh is the one influxdb makes at its first start (server.env), and a machine whose server was set up with another sets its own (novox/hq issue 696, ADR 0348 clause 11).",
|
||||
"trusted": true,
|
||||
"default": "mesh"
|
||||
},
|
||||
"bucket": {
|
||||
"type": "string",
|
||||
"description": "The bucket influxdb-api names to its consumers and the module's tools write to; default is the one influxdb makes at its first start (server.env), and a machine whose server was set up with another sets its own (novox/hq issue 696, ADR 0348 clause 11).",
|
||||
"trusted": true,
|
||||
"default": "default"
|
||||
},
|
||||
"url": {
|
||||
"type": "string",
|
||||
"description": "The address the module's tools reach influxdb at, as a URL; empty is this machine's influxdb on its port.",
|
||||
"trusted": true,
|
||||
"default": ""
|
||||
}
|
||||
},
|
||||
"serves": {
|
||||
"influxdb-api": {
|
||||
"scheme": "http",
|
||||
"port": 8086,
|
||||
"org": "${config:org}",
|
||||
"bucket": "${config:bucket}"
|
||||
}
|
||||
},
|
||||
"receives": {
|
||||
"influxdb-api": "${dir:grants}/mesh.json"
|
||||
},
|
||||
"grants": {
|
||||
"influxdb-api": "${dir:grants}"
|
||||
},
|
||||
"data": {
|
||||
"own": [
|
||||
{
|
||||
"id": "data",
|
||||
"path": "${dir:data}",
|
||||
"class": "valuable",
|
||||
"why": "every consumer's time series"
|
||||
},
|
||||
{
|
||||
"id": "config",
|
||||
"path": "${dir:config}",
|
||||
"class": "valuable",
|
||||
"why": "the server's own configuration and its operator token, made at its first start"
|
||||
}
|
||||
],
|
||||
"consumers": {
|
||||
"influxdb-api": {
|
||||
"class": "valuable",
|
||||
"in": "data",
|
||||
"why": "a consumer's measurements are the only copy"
|
||||
}
|
||||
}
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"id": "mesh-state",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"place": "mesh",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "state",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"place": ".",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "data",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"owner": "1000:1000",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "config",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"owner": "1000:1000",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "grants",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "server-env",
|
||||
"type": "file",
|
||||
"path": "${dir:state}/server.env",
|
||||
"mode": "0600",
|
||||
"template": "files/server.env"
|
||||
},
|
||||
{
|
||||
"id": "server",
|
||||
"type": "container",
|
||||
"name": "influxdb",
|
||||
"image": "influxdb@sha256:f75e48af0598e8aec7986e991a848d19a119101a7d563a2e5db1dfaac9c45daa",
|
||||
"env-file": [
|
||||
"${dir:state}/server.env"
|
||||
],
|
||||
"ports": [
|
||||
"8086"
|
||||
],
|
||||
"volumes": [
|
||||
"${dir:data}:/var/lib/influxdb2",
|
||||
"${dir:config}:/etc/influxdb2",
|
||||
"${dir:state}/admin.secret:/run/secrets/admin:ro",
|
||||
"${dir:state}/admin-token.secret:/run/secrets/admin-token:ro"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "runtime-config",
|
||||
"type": "file",
|
||||
"path": "${dir:mesh-state}/config.json",
|
||||
"mode": "0600",
|
||||
"template": "files/config.json",
|
||||
"merge": "json",
|
||||
"takes-config": [
|
||||
"bucket",
|
||||
"org",
|
||||
"url"
|
||||
],
|
||||
"trusted": true
|
||||
}
|
||||
],
|
||||
"requires": [
|
||||
"route"
|
||||
],
|
||||
"contributes": {
|
||||
"route": {
|
||||
"label": "influxdb",
|
||||
"endpoint": "api"
|
||||
}
|
||||
},
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "code",
|
||||
"kind": "bundle",
|
||||
"language": "typescript",
|
||||
"entrypoints": [
|
||||
"tools/index.js",
|
||||
"provisioner/index.js"
|
||||
],
|
||||
"loads": [
|
||||
"tools/index.js",
|
||||
"provisioner/index.js"
|
||||
],
|
||||
"env": {
|
||||
"MESH_INFLUXDB_URL": "http://127.0.0.1:${port:8086}",
|
||||
"MESH_INFLUXDB_CONFIG_FILE": "${dir:mesh-state}/config.json",
|
||||
"MESH_INFLUXDB_TOKEN_FILE": "${dir:state}/admin-token.secret",
|
||||
"MESH_RECEIVES": "${dir:grants}/mesh.json"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "files",
|
||||
"kind": "archive",
|
||||
"from": "files"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
{
|
||||
"module": "invoicing",
|
||||
"version": "1",
|
||||
"slug": "invoice",
|
||||
"capabilities": [
|
||||
"container-runtime"
|
||||
],
|
||||
"requires": [
|
||||
"mongodb-database",
|
||||
"s3-bucket",
|
||||
"route"
|
||||
],
|
||||
"contributes": {
|
||||
"mongodb-database": {
|
||||
"name": "invoicing"
|
||||
},
|
||||
"route": {
|
||||
"site": {
|
||||
"label": "invoicing",
|
||||
"endpoint": "web"
|
||||
},
|
||||
"api": {
|
||||
"label": "invoicing-api",
|
||||
"endpoint": "api"
|
||||
}
|
||||
}
|
||||
},
|
||||
"binds": {
|
||||
"mongodb-database": "${dir:state}/database.json",
|
||||
"s3-bucket": "${dir:state}/store.json",
|
||||
"route": "${dir:state}/route.json"
|
||||
},
|
||||
"secrets": {
|
||||
"mongodb-database": "${dir:state}/database.secret",
|
||||
"s3-bucket": "${dir:state}/store.secret"
|
||||
},
|
||||
"listens": [
|
||||
{
|
||||
"name": "web",
|
||||
"port": 80,
|
||||
"protocol": "tcp",
|
||||
"from": "mesh",
|
||||
"why": "the invoicing web frontend; a public name is a route grant later"
|
||||
},
|
||||
{
|
||||
"name": "api",
|
||||
"port": 9000,
|
||||
"protocol": "tcp",
|
||||
"from": "mesh",
|
||||
"why": "the invoicing REST API the frontend and integrations call"
|
||||
}
|
||||
],
|
||||
"resources": [
|
||||
{
|
||||
"id": "mesh-state",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"place": "mesh",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "state",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"place": ".",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "api-env",
|
||||
"type": "file",
|
||||
"path": "${dir:state}/api.env",
|
||||
"mode": "0600",
|
||||
"template": "files/api.env"
|
||||
},
|
||||
{
|
||||
"id": "net",
|
||||
"type": "network",
|
||||
"name": "invoicing"
|
||||
},
|
||||
{
|
||||
"id": "app",
|
||||
"type": "container",
|
||||
"name": "invoicing-app",
|
||||
"image": "registry-api.novox.be/novox/invoicing-app@sha256:1e6ed40822f07169b24867cbfe8fc1ab3ef6a15ad642f3b3a2882a8e15c3dbec",
|
||||
"network": "invoicing",
|
||||
"env": {
|
||||
"UID": "2201",
|
||||
"GID": "2201"
|
||||
},
|
||||
"ports": [
|
||||
"80"
|
||||
],
|
||||
"names-on-purpose": {
|
||||
"registry-api.novox.be": "built outside the mesh, from the application's own repository, and pulled from the registry that built it; moves when that repository is a build source on the git seat (novox/hq ADR 0155, issue 122)"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "api",
|
||||
"type": "container",
|
||||
"name": "invoicing-api",
|
||||
"image": "registry-api.novox.be/novox/invoicing-api@sha256:efa6fba1fa9ba78849e94e958d33793a76654df0468e3012da9c02c54c265354",
|
||||
"network": "invoicing",
|
||||
"env": {
|
||||
"UID": "2201",
|
||||
"GID": "2201"
|
||||
},
|
||||
"env-file": [
|
||||
"${dir:state}/api.env"
|
||||
],
|
||||
"ports": [
|
||||
"9000"
|
||||
],
|
||||
"secrets-in-environment": "the application's own code reads MONGO_URL and MINIO_SECRET from the environment (invoicing-app server/src/config.js); converting is that repository's change",
|
||||
"names-on-purpose": {
|
||||
"registry-api.novox.be": "built outside the mesh, from the application's own repository, and pulled from the registry that built it; moves when that repository is a build source on the git seat (novox/hq ADR 0155, issue 122)"
|
||||
}
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "files",
|
||||
"kind": "archive",
|
||||
"from": "files"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
{
|
||||
"module": "jira",
|
||||
"version": "1",
|
||||
"own-secrets": {
|
||||
"token": "${dir:state}/token"
|
||||
},
|
||||
"config": {
|
||||
"atlassian-url": {
|
||||
"type": "string",
|
||||
"description": "The address of the operator's Atlassian site the jira tools call, as a URL such as https://example.atlassian.net, laid into the file as ATLASSIAN_URL; unset, the code falls back to its environment and answers no calls until it is given.",
|
||||
"trusted": true,
|
||||
"default": ""
|
||||
},
|
||||
"atlassian-email": {
|
||||
"type": "string",
|
||||
"description": "The email address of the Atlassian account the jira tools sign in as with its API token, laid into the file as ATLASSIAN_EMAIL; unset, the code falls back to its environment and answers no calls until it is given.",
|
||||
"trusted": true,
|
||||
"default": ""
|
||||
}
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"id": "state",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"place": ".",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "config",
|
||||
"type": "file",
|
||||
"path": "${dir:state}/config.json",
|
||||
"merge": "json",
|
||||
"template": "files/config.json",
|
||||
"mode": "0600",
|
||||
"takes-config": [
|
||||
{
|
||||
"key": "atlassian-url",
|
||||
"as": "ATLASSIAN_URL"
|
||||
},
|
||||
{
|
||||
"key": "atlassian-email",
|
||||
"as": "ATLASSIAN_EMAIL"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"capabilities": [
|
||||
"container-runtime"
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "tools",
|
||||
"kind": "bundle",
|
||||
"language": "typescript",
|
||||
"entrypoints": [
|
||||
"tools/index.js"
|
||||
],
|
||||
"loads": [
|
||||
"tools/index.js"
|
||||
],
|
||||
"env": {
|
||||
"MESH_JIRA_TOKEN_FILE": "${dir:state}/token",
|
||||
"MESH_JIRA_CONFIG_FILE": "${dir:state}/config.json"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "files",
|
||||
"kind": "archive",
|
||||
"from": "files"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
{
|
||||
"module": "kernel",
|
||||
"version": "1",
|
||||
"capabilities": [
|
||||
"service-manager"
|
||||
],
|
||||
"config": {
|
||||
"transparent-huge-pages": {
|
||||
"type": "string",
|
||||
"description": "madvise is the value the mesh chose for every node (novox/hq ADR 0381), not the always the distribution's kernel boots with; a machine that needs another value is given it as its own setting; madvise gives huge pages only to programs that ask for them, which stops a small write to a mapped file (the journal) dirtying and writing back a whole 2 MiB page on a machine whose disks are slow (novox/hq issue 746)",
|
||||
"trusted": true,
|
||||
"default": "madvise"
|
||||
}
|
||||
},
|
||||
"tools": [
|
||||
"kernel_huge_pages"
|
||||
],
|
||||
"resources": [
|
||||
{
|
||||
"id": "state",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"place": ".",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "huge-pages",
|
||||
"type": "file",
|
||||
"path": "${dir:state}/huge-pages",
|
||||
"mode": "0755",
|
||||
"trusted": true,
|
||||
"template": "files/huge-pages.sh"
|
||||
},
|
||||
{
|
||||
"id": "unit",
|
||||
"type": "file",
|
||||
"path": "/etc/systemd/system/mesh-kernel-huge-pages.service",
|
||||
"mode": "0644",
|
||||
"template": "files/mesh-kernel-huge-pages.service"
|
||||
},
|
||||
{
|
||||
"id": "apply",
|
||||
"type": "service",
|
||||
"unit": "mesh-kernel-huge-pages.service",
|
||||
"state": "running",
|
||||
"boot": "enabled",
|
||||
"restart-on": [
|
||||
"unit"
|
||||
],
|
||||
"reload-on": [
|
||||
"huge-pages"
|
||||
],
|
||||
"health": {
|
||||
"kind": "unit"
|
||||
}
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "tools",
|
||||
"kind": "bundle",
|
||||
"language": "go",
|
||||
"system": "arch",
|
||||
"from": "cmd/kernel-tools",
|
||||
"binary": "kernel-tools",
|
||||
"loads": [
|
||||
"kernel-tools"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "files",
|
||||
"kind": "archive",
|
||||
"from": "files"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,245 @@
|
||||
{
|
||||
"module": "keycloak",
|
||||
"version": "1",
|
||||
"moved": true,
|
||||
"upgrade": {
|
||||
"policy": "record",
|
||||
"why": "every person's sign-in to every site goes through it, and its new version migrates its database on start: a person takes each build, after a backup (hq ADR 0236)"
|
||||
},
|
||||
"provides": [
|
||||
{
|
||||
"name": "oidc-client",
|
||||
"scope": "mesh",
|
||||
"identity": {
|
||||
"max": 255,
|
||||
"in": "a Keycloak client id"
|
||||
}
|
||||
}
|
||||
],
|
||||
"requires": [
|
||||
"postgres-database",
|
||||
"route"
|
||||
],
|
||||
"contributes": {
|
||||
"postgres-database": {
|
||||
"name": "keycloak"
|
||||
},
|
||||
"route": {
|
||||
"label": "keycloak",
|
||||
"endpoint": "web"
|
||||
}
|
||||
},
|
||||
"binds": {
|
||||
"postgres-database": "${dir:state}/database.json",
|
||||
"route": "${dir:state}/route.json"
|
||||
},
|
||||
"secrets": {
|
||||
"postgres-database": "${dir:state}/database.secret"
|
||||
},
|
||||
"capabilities": [
|
||||
"container-runtime"
|
||||
],
|
||||
"emits": [
|
||||
"user.created",
|
||||
"user.deleted",
|
||||
"password.reset",
|
||||
"client.created",
|
||||
"client.retired",
|
||||
"group.created",
|
||||
"role.created",
|
||||
"admin.repaired",
|
||||
"admin.unrepaired"
|
||||
],
|
||||
"listens": [
|
||||
{
|
||||
"name": "web",
|
||||
"port": 8080,
|
||||
"protocol": "tcp",
|
||||
"from": "mesh",
|
||||
"why": "anything the mesh runs that authenticates a person"
|
||||
}
|
||||
],
|
||||
"serves": {
|
||||
"oidc-client": {
|
||||
"authorization-path": "/protocol/openid-connect/auth",
|
||||
"token-path": "/protocol/openid-connect/token",
|
||||
"userinfo-path": "/protocol/openid-connect/userinfo",
|
||||
"issuer": "${config:issuer}"
|
||||
}
|
||||
},
|
||||
"receives": {
|
||||
"oidc-client": "${dir:grants}/mesh.json"
|
||||
},
|
||||
"grants": {
|
||||
"oidc-client": "${dir:grants}"
|
||||
},
|
||||
"own-secrets": {
|
||||
"admin": "${dir:state}/admin.secret"
|
||||
},
|
||||
"data": {
|
||||
"consumers": {
|
||||
"oidc-client": {
|
||||
"class": "rebuildable",
|
||||
"in": "postgres-database",
|
||||
"why": "a consumer's client is made again from its declaration, with a new secret"
|
||||
}
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"url": {
|
||||
"type": "string",
|
||||
"description": "The address the module's provider reaches Keycloak's admin API at, as a URL; empty is this machine's Keycloak on its port.",
|
||||
"trusted": true,
|
||||
"default": ""
|
||||
},
|
||||
"user": {
|
||||
"type": "string",
|
||||
"description": "The Keycloak administrator the module's provider signs in as; empty is admin.",
|
||||
"trusted": true,
|
||||
"default": ""
|
||||
},
|
||||
"realm": {
|
||||
"type": "string",
|
||||
"description": "The realm the module's provider makes its consumers' clients in; empty is master.",
|
||||
"trusted": true,
|
||||
"default": ""
|
||||
},
|
||||
"issuer": {
|
||||
"type": "string",
|
||||
"description": "The issuer Keycloak's tokens name and oidc consumers are told, as the realm's URL, such as https://keycloak.example.org/realms/Example; the operator's, with no default (novox/hq ADR 0112, ADR 0155).",
|
||||
"trusted": true,
|
||||
"required": true
|
||||
}
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"id": "mesh-state",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"place": "mesh",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "state",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"place": ".",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "grants",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "consumers",
|
||||
"type": "file",
|
||||
"path": "${dir:state}/consumers.json",
|
||||
"mode": "0600",
|
||||
"template": "files/consumers.json"
|
||||
},
|
||||
{
|
||||
"id": "admin-env",
|
||||
"type": "file",
|
||||
"path": "${dir:state}/admin.env",
|
||||
"mode": "0600",
|
||||
"template": "files/admin.env"
|
||||
},
|
||||
{
|
||||
"id": "database-env",
|
||||
"type": "file",
|
||||
"path": "${dir:state}/database.env",
|
||||
"mode": "0600",
|
||||
"template": "files/database.env"
|
||||
},
|
||||
{
|
||||
"id": "net",
|
||||
"type": "network",
|
||||
"name": "keycloak"
|
||||
},
|
||||
{
|
||||
"id": "hostname",
|
||||
"type": "file",
|
||||
"path": "${dir:state}/hostname.env",
|
||||
"mode": "0644",
|
||||
"template": "files/hostname.env"
|
||||
},
|
||||
{
|
||||
"id": "server",
|
||||
"type": "container",
|
||||
"name": "keycloak",
|
||||
"image": "quay.io/keycloak/keycloak@sha256:ecd43971114b0c764f8a3288dddab73f98cb473daccc4feaffe4dc14adeaf866",
|
||||
"network": "keycloak",
|
||||
"args": [
|
||||
"start-dev"
|
||||
],
|
||||
"env": {
|
||||
"KC_DB": "postgres",
|
||||
"KC_HTTP_ENABLED": "true",
|
||||
"KC_HEALTH_ENABLED": "true",
|
||||
"KC_PROXY_HEADERS": "xforwarded"
|
||||
},
|
||||
"env-file": [
|
||||
"${dir:state}/admin.env",
|
||||
"${dir:state}/database.env",
|
||||
"${dir:state}/hostname.env"
|
||||
],
|
||||
"ports": [
|
||||
"8080"
|
||||
],
|
||||
"secrets-in-environment": "KC_DB_PASSWORD is convertible through a generated keycloak.conf (db-password=); KEYCLOAK_ADMIN_PASSWORD is env-only before Keycloak 26; not yet converted",
|
||||
"restart-on": [
|
||||
"hostname"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "runtime-config",
|
||||
"type": "file",
|
||||
"path": "${dir:mesh-state}/config.json",
|
||||
"mode": "0600",
|
||||
"template": "files/config.json",
|
||||
"merge": "json",
|
||||
"takes-config": [
|
||||
"url",
|
||||
"user",
|
||||
"realm",
|
||||
"issuer"
|
||||
]
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "code",
|
||||
"kind": "bundle",
|
||||
"language": "go",
|
||||
"system": "arch",
|
||||
"from": "cmd/keycloak-provider",
|
||||
"binary": "keycloak-provider",
|
||||
"loads": [
|
||||
"keycloak-provider"
|
||||
],
|
||||
"env": {
|
||||
"MESH_KEYCLOAK_URL": "http://127.0.0.1:${port:8080}",
|
||||
"MESH_KEYCLOAK_CONFIG_FILE": "${dir:mesh-state}/config.json",
|
||||
"MESH_KEYCLOAK_PASSWORD_FILE": "${dir:state}/admin.secret",
|
||||
"MESH_RECEIVES": "${dir:grants}/mesh.json",
|
||||
"MESH_KEYCLOAK_CONTAINER": "keycloak",
|
||||
"MESH_CONSUMERS_FILE": "${dir:state}/consumers.json"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "files",
|
||||
"kind": "archive",
|
||||
"from": "files"
|
||||
}
|
||||
]
|
||||
},
|
||||
"state": [
|
||||
"bound"
|
||||
],
|
||||
"reads": [
|
||||
"mesh-controller.assignments"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
{
|
||||
"module": "lab",
|
||||
"version": "1",
|
||||
"capabilities": [
|
||||
"container-runtime",
|
||||
"virtualisation"
|
||||
],
|
||||
"requires": [
|
||||
"npm-package-registry"
|
||||
],
|
||||
"contributes": {
|
||||
"npm-package-registry": {
|
||||
"access": "read"
|
||||
}
|
||||
},
|
||||
"binds": {
|
||||
"npm-package-registry": "${dir:state}/package-registry.json"
|
||||
},
|
||||
"secrets": {
|
||||
"npm-package-registry": "${dir:state}/package-registry.secret"
|
||||
},
|
||||
"data": {
|
||||
"own": [
|
||||
{
|
||||
"id": "work",
|
||||
"path": "${dir:work}",
|
||||
"class": "cache",
|
||||
"why": "the lab's runs, each thrown away"
|
||||
}
|
||||
]
|
||||
},
|
||||
"config": {
|
||||
"forge": {
|
||||
"type": "string",
|
||||
"description": "The forge the lab's machines take their packages from, as its address: the operator's, with no default (novox/hq ADR 0112).",
|
||||
"trusted": true,
|
||||
"required": true
|
||||
}
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"id": "state",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"place": ".",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "work",
|
||||
"type": "directory",
|
||||
"path": "/var/lib/mesh-lab-runs",
|
||||
"mode": "0700",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "runtime-env",
|
||||
"type": "file",
|
||||
"path": "${dir:state}/lab.env",
|
||||
"mode": "0600",
|
||||
"template": "files/lab.env"
|
||||
},
|
||||
{
|
||||
"id": "git",
|
||||
"type": "package",
|
||||
"package": "git"
|
||||
},
|
||||
{
|
||||
"id": "make",
|
||||
"type": "package",
|
||||
"package": "make"
|
||||
},
|
||||
{
|
||||
"id": "python",
|
||||
"type": "package",
|
||||
"package": "python"
|
||||
},
|
||||
{
|
||||
"id": "file",
|
||||
"type": "package",
|
||||
"package": "file"
|
||||
},
|
||||
{
|
||||
"id": "iproute2",
|
||||
"type": "package",
|
||||
"package": "iproute2"
|
||||
},
|
||||
{
|
||||
"id": "npm",
|
||||
"type": "package",
|
||||
"package": "npm"
|
||||
},
|
||||
{
|
||||
"id": "go",
|
||||
"type": "package",
|
||||
"package": "go"
|
||||
},
|
||||
{
|
||||
"id": "incus",
|
||||
"type": "package",
|
||||
"package": "incus"
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "code",
|
||||
"kind": "bundle",
|
||||
"language": "typescript",
|
||||
"entrypoints": [
|
||||
"tools/index.js"
|
||||
],
|
||||
"loads": [
|
||||
"tools/index.js"
|
||||
],
|
||||
"env": {
|
||||
"MESH_LAB_WORK": "${dir:work}",
|
||||
"MESH_LAB_ENV_FILE": "${dir:state}/lab.env",
|
||||
"MESH_LAB_FORGE_BINDING": "${dir:state}/package-registry.json",
|
||||
"MESH_LAB_FORGE_SECRET": "${dir:state}/package-registry.secret"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "files",
|
||||
"kind": "archive",
|
||||
"from": "files"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
{
|
||||
"module": "lemurs",
|
||||
"version": "1",
|
||||
"capabilities": [
|
||||
"package-manager",
|
||||
"service-manager",
|
||||
"seat"
|
||||
],
|
||||
"claims": [
|
||||
{
|
||||
"name": "node-login-manager",
|
||||
"scope": "node",
|
||||
"serves": [
|
||||
"sessions"
|
||||
]
|
||||
}
|
||||
],
|
||||
"tools": [
|
||||
"lemurs_default_session",
|
||||
"lemurs_logins"
|
||||
],
|
||||
"resources": [
|
||||
{
|
||||
"id": "package",
|
||||
"type": "package",
|
||||
"package": "lemurs"
|
||||
},
|
||||
{
|
||||
"id": "xserver",
|
||||
"type": "file",
|
||||
"path": "/etc/lemurs/xserver",
|
||||
"mode": "0755",
|
||||
"template": "files/xserver"
|
||||
},
|
||||
{
|
||||
"id": "config",
|
||||
"type": "file",
|
||||
"path": "/etc/lemurs/config.toml",
|
||||
"mode": "0644",
|
||||
"template": "files/config.toml"
|
||||
},
|
||||
{
|
||||
"id": "xsessions",
|
||||
"type": "directory",
|
||||
"path": "/etc/lemurs/xsessions",
|
||||
"mode": "0755",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "wayland-sessions",
|
||||
"type": "directory",
|
||||
"path": "/etc/lemurs/wayland-sessions",
|
||||
"mode": "0755",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "service",
|
||||
"type": "service",
|
||||
"unit": "lemurs.service",
|
||||
"state": "running",
|
||||
"boot": "enabled"
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "tools",
|
||||
"kind": "bundle",
|
||||
"language": "go",
|
||||
"system": "arch",
|
||||
"from": "cmd/lemurs-tools",
|
||||
"binary": "lemurs-tools",
|
||||
"loads": [
|
||||
"lemurs-tools"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "files",
|
||||
"kind": "archive",
|
||||
"from": "files"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
{
|
||||
"module": "letta",
|
||||
"version": "1",
|
||||
"capabilities": [
|
||||
"container-runtime"
|
||||
],
|
||||
"requires": [
|
||||
"postgres-database",
|
||||
"route"
|
||||
],
|
||||
"contributes": {
|
||||
"postgres-database": {
|
||||
"name": "letta",
|
||||
"extensions": [
|
||||
"vector"
|
||||
]
|
||||
},
|
||||
"route": {
|
||||
"label": "letta",
|
||||
"endpoint": "web"
|
||||
}
|
||||
},
|
||||
"binds": {
|
||||
"postgres-database": "${dir:state}/database.json",
|
||||
"route": "${dir:state}/route.json"
|
||||
},
|
||||
"secrets": {
|
||||
"postgres-database": "${dir:state}/database.secret"
|
||||
},
|
||||
"own-secrets": {
|
||||
"server-password": {
|
||||
"path": "${dir:state}/server-password.secret",
|
||||
"taken": "at-start"
|
||||
},
|
||||
"openai-api-key": {
|
||||
"path": "${dir:state}/openai-api-key.secret",
|
||||
"taken": "at-start",
|
||||
"issued-by": "outside"
|
||||
}
|
||||
},
|
||||
"listens": [
|
||||
{
|
||||
"name": "web",
|
||||
"port": 8283,
|
||||
"protocol": "tcp",
|
||||
"from": "mesh",
|
||||
"why": "the Letta agent server REST API and web UI, password-protected (--secure); a public name is the route's"
|
||||
}
|
||||
],
|
||||
"config": {
|
||||
"url": {
|
||||
"type": "string",
|
||||
"description": "The address the module's tools reach Letta at, as a URL; unset, the code falls back to its environment, else this machine's Letta on port 8283.",
|
||||
"trusted": true,
|
||||
"default": ""
|
||||
}
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"id": "mesh-state",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"place": "mesh",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "state",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"place": ".",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "server-env",
|
||||
"type": "file",
|
||||
"path": "${dir:state}/server.env",
|
||||
"mode": "0600",
|
||||
"template": "files/server.env"
|
||||
},
|
||||
{
|
||||
"id": "pgpass",
|
||||
"type": "file",
|
||||
"path": "${dir:state}/pgpass",
|
||||
"mode": "0600",
|
||||
"template": "files/pgpass"
|
||||
},
|
||||
{
|
||||
"id": "start",
|
||||
"type": "file",
|
||||
"path": "${dir:state}/start.sh",
|
||||
"mode": "0644",
|
||||
"template": "files/start.sh"
|
||||
},
|
||||
{
|
||||
"id": "net",
|
||||
"type": "network",
|
||||
"name": "letta"
|
||||
},
|
||||
{
|
||||
"id": "server",
|
||||
"type": "container",
|
||||
"name": "letta",
|
||||
"image": "letta/letta@sha256:bfd1e49ce45b9a208c941e832c1d1d194017ff210a3784b0ca6c323aed767a29",
|
||||
"network": "letta",
|
||||
"env-file": [
|
||||
"${dir:state}/server.env"
|
||||
],
|
||||
"ports": [
|
||||
"8283"
|
||||
],
|
||||
"volumes": [
|
||||
"${dir:state}/pgpass:/run/secrets/pgpass:ro",
|
||||
"${dir:state}/start.sh:/run/letta/start.sh:ro"
|
||||
],
|
||||
"args": [
|
||||
"sh",
|
||||
"/run/letta/start.sh"
|
||||
],
|
||||
"secrets-in-environment": "letta 0.6.x reads its settings from the environment only (pydantic settings, no secrets_dir or _FILE twin): LETTA_SERVER_PASSWORD and OPENAI_API_KEY have no file source. The database password is not here: LETTA_PG_URI, which letta prints at start, names no password, and libpq reads it from the mounted pgpass file (PGPASSFILE)"
|
||||
},
|
||||
{
|
||||
"id": "runtime-config",
|
||||
"type": "file",
|
||||
"path": "${dir:mesh-state}/config.json",
|
||||
"mode": "0600",
|
||||
"template": "files/config.json",
|
||||
"merge": "json",
|
||||
"takes-config": ["url"],
|
||||
"protected": ["password"]
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "tools",
|
||||
"kind": "bundle",
|
||||
"language": "typescript",
|
||||
"entrypoints": [
|
||||
"tools/index.js"
|
||||
],
|
||||
"loads": [
|
||||
"tools/index.js"
|
||||
],
|
||||
"env": {
|
||||
"MESH_LETTA_URL": "http://127.0.0.1:${port:8283}",
|
||||
"MESH_LETTA_CONFIG_FILE": "${dir:mesh-state}/config.json"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "files",
|
||||
"kind": "archive",
|
||||
"from": "files"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
{
|
||||
"module": "local-model-consumer",
|
||||
"version": "1",
|
||||
"slug": "local",
|
||||
"requires": [
|
||||
"model-access"
|
||||
],
|
||||
"binds": {
|
||||
"model-access": "${dir:state}/model.json"
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"id": "state",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"place": ".",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "config",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "openai-env",
|
||||
"type": "file",
|
||||
"path": "${dir:config}/openai.env",
|
||||
"mode": "0600",
|
||||
"template": "files/openai.env"
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "files",
|
||||
"kind": "archive",
|
||||
"from": "files"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
{
|
||||
"module": "localization",
|
||||
"version": "1",
|
||||
"capabilities": [
|
||||
"service-manager"
|
||||
],
|
||||
"tools": [
|
||||
"localization_get",
|
||||
"localization_time_zone",
|
||||
"localization_locales",
|
||||
"localization_keymaps"
|
||||
],
|
||||
"resources": [
|
||||
{
|
||||
"id": "locale",
|
||||
"type": "file",
|
||||
"path": "/etc/locale.conf",
|
||||
"mode": "0644",
|
||||
"template": "files/locale.conf"
|
||||
},
|
||||
{
|
||||
"id": "keymap",
|
||||
"type": "file",
|
||||
"path": "/etc/vconsole.conf",
|
||||
"mode": "0644",
|
||||
"template": "files/vconsole.conf"
|
||||
},
|
||||
{
|
||||
"id": "time-zone",
|
||||
"type": "process",
|
||||
"name": "localization-time-zone",
|
||||
"artifact": "tools",
|
||||
"run": [
|
||||
"./localization-tools",
|
||||
"set-time-zone",
|
||||
"Europe/Brussels"
|
||||
],
|
||||
"run-once": true
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "tools",
|
||||
"kind": "bundle",
|
||||
"language": "go",
|
||||
"system": "arch",
|
||||
"from": "cmd/localization-tools",
|
||||
"binary": "localization-tools",
|
||||
"loads": [
|
||||
"localization-tools"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "files",
|
||||
"kind": "archive",
|
||||
"from": "files"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
{
|
||||
"module": "logrotate",
|
||||
"version": "1",
|
||||
"capabilities": [
|
||||
"package-manager",
|
||||
"service-manager"
|
||||
],
|
||||
"tools": [
|
||||
"logrotate_status",
|
||||
"logrotate_configs",
|
||||
"logrotate_check",
|
||||
"logrotate_big_logs",
|
||||
"logrotate_force",
|
||||
"logrotate_journal_usage",
|
||||
"logrotate_journal_vacuum"
|
||||
],
|
||||
"resources": [
|
||||
{
|
||||
"id": "package",
|
||||
"type": "package",
|
||||
"package": "logrotate"
|
||||
},
|
||||
{
|
||||
"id": "config",
|
||||
"type": "file",
|
||||
"path": "/etc/logrotate.conf",
|
||||
"mode": "0644",
|
||||
"template": "files/logrotate.conf"
|
||||
},
|
||||
{
|
||||
"id": "timer",
|
||||
"type": "service",
|
||||
"unit": "logrotate.timer",
|
||||
"state": "running",
|
||||
"boot": "enabled"
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "tools",
|
||||
"kind": "bundle",
|
||||
"language": "go",
|
||||
"system": "arch",
|
||||
"from": "cmd/logrotate-tools",
|
||||
"binary": "logrotate-tools",
|
||||
"loads": [
|
||||
"logrotate-tools"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "files",
|
||||
"kind": "archive",
|
||||
"from": "files"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,772 @@
|
||||
{
|
||||
"module": "mailu",
|
||||
"version": "1",
|
||||
"upgrade": {
|
||||
"policy": "record",
|
||||
"why": "people's mail: any change to how its containers are declared recreates them together in one send, and the mail is down for everyone until they are up again — a person chooses the moment (hq ADR 0242, issue 295)"
|
||||
},
|
||||
"unhealthy": {
|
||||
"severity": "urgent",
|
||||
"why": "while mailu is broken, mail is refused or stuck for everyone with a mailbox here (hq ADR 0355, issue 687)"
|
||||
},
|
||||
"capabilities": [
|
||||
"container-runtime"
|
||||
],
|
||||
"requires": [
|
||||
"postgres-database",
|
||||
"route",
|
||||
"secret"
|
||||
],
|
||||
"contributes": {
|
||||
"postgres-database": {
|
||||
"name": "mailu"
|
||||
},
|
||||
"route": {
|
||||
"web": {
|
||||
"label": "mail",
|
||||
"endpoint": "web-tls",
|
||||
"scheme": "https",
|
||||
"insecure": true
|
||||
},
|
||||
"acme": {
|
||||
"label": "mail",
|
||||
"path": "/.well-known/acme-challenge",
|
||||
"endpoint": "web",
|
||||
"priority": 100
|
||||
},
|
||||
"autoconfig": {
|
||||
"label": "autoconfig",
|
||||
"endpoint": "autoconfig"
|
||||
},
|
||||
"autodiscover": {
|
||||
"label": "autodiscover",
|
||||
"endpoint": "autoconfig"
|
||||
},
|
||||
"automx": {
|
||||
"label": "automx",
|
||||
"endpoint": "autoconfig"
|
||||
}
|
||||
}
|
||||
},
|
||||
"binds": {
|
||||
"postgres-database": "${dir:state}/database.json",
|
||||
"route": "${dir:state}/route.json"
|
||||
},
|
||||
"secrets": {
|
||||
"postgres-database": "${dir:state}/database.secret",
|
||||
"secret": {
|
||||
"secret-key": "${dir:state}/secret-key.secret",
|
||||
"admin": "${dir:state}/admin.secret",
|
||||
"api-token": "${dir:state}/api-token.secret"
|
||||
}
|
||||
},
|
||||
"tools": [
|
||||
"mailu_list_users",
|
||||
"mailu_create_user",
|
||||
"mailu_change_password",
|
||||
"mailu_delete_user",
|
||||
"mailu_list_aliases",
|
||||
"mailu_create_alias",
|
||||
"mailu_delete_alias",
|
||||
"mailu_list_domains",
|
||||
"mailu_read_mail",
|
||||
"mailu_search_mail",
|
||||
"mailu_health"
|
||||
],
|
||||
"emits": [
|
||||
"user.created",
|
||||
"user.deleted",
|
||||
"alias.created",
|
||||
"alias.deleted"
|
||||
],
|
||||
"listens": [
|
||||
{
|
||||
"name": "smtp",
|
||||
"port": 25,
|
||||
"protocol": "tcp",
|
||||
"from": "anywhere",
|
||||
"why": "mail from other mail servers",
|
||||
"fixed": true
|
||||
},
|
||||
{
|
||||
"name": "pop3",
|
||||
"port": 110,
|
||||
"protocol": "tcp",
|
||||
"from": "anywhere",
|
||||
"why": "POP3, kept at parity with the predecessor; pruning legacy protocols is its own deliberate change",
|
||||
"fixed": true
|
||||
},
|
||||
{
|
||||
"name": "imap",
|
||||
"port": 143,
|
||||
"protocol": "tcp",
|
||||
"from": "anywhere",
|
||||
"why": "IMAP with STARTTLS, kept at parity",
|
||||
"fixed": true
|
||||
},
|
||||
{
|
||||
"name": "smtps",
|
||||
"port": 465,
|
||||
"protocol": "tcp",
|
||||
"from": "anywhere",
|
||||
"why": "submission over TLS",
|
||||
"fixed": true
|
||||
},
|
||||
{
|
||||
"name": "submission",
|
||||
"port": 587,
|
||||
"protocol": "tcp",
|
||||
"from": "anywhere",
|
||||
"why": "submission; also what the smtp provision serves consumers",
|
||||
"fixed": true
|
||||
},
|
||||
{
|
||||
"name": "imaps",
|
||||
"port": 993,
|
||||
"protocol": "tcp",
|
||||
"from": "anywhere",
|
||||
"why": "IMAP over TLS",
|
||||
"fixed": true
|
||||
},
|
||||
{
|
||||
"name": "pop3s",
|
||||
"port": 995,
|
||||
"protocol": "tcp",
|
||||
"from": "anywhere",
|
||||
"why": "POP3 over TLS, kept at parity",
|
||||
"fixed": true
|
||||
},
|
||||
{
|
||||
"name": "web",
|
||||
"port": 7080,
|
||||
"protocol": "tcp",
|
||||
"from": "mesh",
|
||||
"why": "the web front over http; only the ACME HTTP-01 passthrough is routed here — everything else 301s to https and would loop a proxy"
|
||||
},
|
||||
{
|
||||
"name": "web-tls",
|
||||
"port": 7443,
|
||||
"protocol": "tcp",
|
||||
"from": "mesh",
|
||||
"why": "the web front over its own TLS (admin, webmail, API); its public name is a route grant reaching it here"
|
||||
},
|
||||
{
|
||||
"name": "autoconfig",
|
||||
"port": 4243,
|
||||
"protocol": "tcp",
|
||||
"from": "mesh",
|
||||
"why": "automx: mail client autoconfiguration; the autoconfig, autodiscover and automx names are route grants reaching it here"
|
||||
},
|
||||
{
|
||||
"name": "admin-api",
|
||||
"port": 8080,
|
||||
"protocol": "tcp",
|
||||
"from": "machine",
|
||||
"why": "the admin API, which this module's own code reaches on loopback from the node's runtime now that it runs outside the mailu network"
|
||||
}
|
||||
],
|
||||
"data": {
|
||||
"own": [
|
||||
{
|
||||
"id": "mail",
|
||||
"path": "${dir:data-mail}",
|
||||
"class": "valuable",
|
||||
"why": "every mailbox"
|
||||
},
|
||||
{
|
||||
"id": "dkim",
|
||||
"path": "${dir:data-dkim}",
|
||||
"class": "valuable",
|
||||
"why": "the domain's signing keys; a new one means a new DNS record"
|
||||
},
|
||||
{
|
||||
"id": "data",
|
||||
"path": "${dir:data-data}",
|
||||
"class": "valuable",
|
||||
"why": "the server's own data"
|
||||
},
|
||||
{
|
||||
"id": "dav",
|
||||
"path": "${dir:data-dav}",
|
||||
"class": "valuable",
|
||||
"why": "calendars and contacts"
|
||||
},
|
||||
{
|
||||
"id": "webmail",
|
||||
"path": "${dir:data-webmail}",
|
||||
"class": "valuable",
|
||||
"why": "the webmail's own data: its users' settings and address books"
|
||||
},
|
||||
{
|
||||
"id": "queue",
|
||||
"path": "${dir:data-mailqueue}",
|
||||
"class": "valuable",
|
||||
"why": "mail accepted and not yet delivered, kept nowhere else"
|
||||
},
|
||||
{
|
||||
"id": "filter",
|
||||
"path": "${dir:data-filter}",
|
||||
"class": "rebuildable",
|
||||
"why": "the spam filter's learned statistics; it learns again"
|
||||
},
|
||||
{
|
||||
"id": "certs",
|
||||
"path": "${dir:data-certs}",
|
||||
"class": "rebuildable",
|
||||
"why": "certificates, issued again"
|
||||
},
|
||||
{
|
||||
"id": "automx",
|
||||
"path": "${dir:data-automx}",
|
||||
"class": "rebuildable",
|
||||
"why": "client autoconfiguration, written again"
|
||||
},
|
||||
{
|
||||
"id": "fetchmail",
|
||||
"path": "${dir:data-fetchmail}",
|
||||
"class": "rebuildable",
|
||||
"why": "which remote messages were fetched; lost, some are fetched twice"
|
||||
},
|
||||
{
|
||||
"id": "clamav",
|
||||
"path": "${dir:data-clamav}",
|
||||
"class": "cache",
|
||||
"why": "virus signatures, downloaded again"
|
||||
},
|
||||
{
|
||||
"id": "redis",
|
||||
"path": "${dir:data-redis}",
|
||||
"class": "cache",
|
||||
"why": "the filter's working set"
|
||||
}
|
||||
],
|
||||
"consumers": {
|
||||
"smtp": {
|
||||
"class": "valuable",
|
||||
"in": "mail",
|
||||
"why": "a consumer's mailbox holds the only copy of its mail"
|
||||
}
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"domain": {
|
||||
"type": "string",
|
||||
"description": "The mail domain Mailu serves, such as example.org: its first mail domain, the postmaster's and the one consumers send as; the operator's, with no default (novox/hq ADR 0112).",
|
||||
"trusted": true,
|
||||
"required": true
|
||||
},
|
||||
"proxy-address": {
|
||||
"type": "string",
|
||||
"description": "The address of the reverse proxy in front of Mailu, whose X-Real-IP header Mailu believes; the operator's, with no default.",
|
||||
"trusted": true,
|
||||
"required": true
|
||||
},
|
||||
"sitename": {
|
||||
"type": "string",
|
||||
"description": "The name Mailu's web pages show for the mail service; the operator's, with no default.",
|
||||
"trusted": true,
|
||||
"required": true
|
||||
},
|
||||
"website": {
|
||||
"type": "string",
|
||||
"description": "The address of the website Mailu's web pages link to, as a URL; the operator's, with no default.",
|
||||
"trusted": true,
|
||||
"required": true
|
||||
},
|
||||
"url": {
|
||||
"type": "string",
|
||||
"description": "The address the module's tools reach Mailu's API at, as a URL; empty leaves them to MESH_MAILU_URL.",
|
||||
"trusted": true,
|
||||
"default": ""
|
||||
},
|
||||
"container": {
|
||||
"type": "string",
|
||||
"description": "The name of the container holding Mailu's mailboxes, which the module's tools read mail in; empty is mailu-imap.",
|
||||
"trusted": true,
|
||||
"default": ""
|
||||
}
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"id": "mesh-state",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"place": "mesh",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "state",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"place": ".",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "grants",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "data-automx",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "config-env",
|
||||
"type": "file",
|
||||
"path": "${dir:state}/mailu.env",
|
||||
"mode": "0644",
|
||||
"template": "files/mailu.env"
|
||||
},
|
||||
{
|
||||
"id": "secret-env",
|
||||
"type": "file",
|
||||
"path": "${dir:state}/secret.env",
|
||||
"mode": "0600",
|
||||
"template": "files/secret.env"
|
||||
},
|
||||
{
|
||||
"id": "database-env",
|
||||
"type": "file",
|
||||
"path": "${dir:state}/database.env",
|
||||
"mode": "0600",
|
||||
"template": "files/database.env"
|
||||
},
|
||||
{
|
||||
"id": "admin-env",
|
||||
"type": "file",
|
||||
"path": "${dir:state}/admin.env",
|
||||
"mode": "0600",
|
||||
"template": "files/admin.env"
|
||||
},
|
||||
{
|
||||
"id": "data-certs",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "data-data",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "data-dkim",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "data-mail",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "data-mailqueue",
|
||||
"type": "directory",
|
||||
"mode": "0755",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "data-filter",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "data-clamav",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "data-redis",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "data-webmail",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "data-dav",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "data-fetchmail",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "data-overrides-nginx",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "data-overrides-dovecot",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "data-overrides-postfix",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "data-overrides-rspamd",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "data-overrides-roundcube",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "net",
|
||||
"type": "network",
|
||||
"name": "mailu"
|
||||
},
|
||||
{
|
||||
"id": "resolver",
|
||||
"type": "container",
|
||||
"name": "mailu-resolver",
|
||||
"image": "ghcr.io/mailu/unbound@sha256:2c037bc5c988b5c0ab7e1b6e6ffa762e14ba1e45c96281ac87f8b9be8eee8b6e",
|
||||
"health": {
|
||||
"kind": "runtime"
|
||||
},
|
||||
"network": "mailu",
|
||||
"env-file": [
|
||||
"${dir:state}/mailu.env",
|
||||
"${dir:state}/secret.env"
|
||||
],
|
||||
"secrets-in-environment": "mailu-admin honours SECRET_KEY_FILE, DB_PW_FILE and API_TOKEN_FILE (configuration.py) but INITIAL_ADMIN_PW is env-only (start.py); the remaining containers' need for SECRET_KEY is unverified",
|
||||
"ip": "192.168.203.254"
|
||||
},
|
||||
{
|
||||
"id": "redis",
|
||||
"type": "container",
|
||||
"name": "mailu-redis",
|
||||
"image": "redis@sha256:4bed291aa5efb9f0d77b76ff7d4ab71eee410962965d052552db1fb80576431d",
|
||||
"network": "mailu",
|
||||
"volumes": [
|
||||
"${dir:data-redis}:/data"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "admin",
|
||||
"type": "container",
|
||||
"name": "mailu-admin",
|
||||
"image": "ghcr.io/mailu/admin@sha256:6dbfdadc4a9590dcb7652357b505200115b689b74008653bbf369e4599a3be5a",
|
||||
"health": {
|
||||
"kind": "runtime"
|
||||
},
|
||||
"network": "mailu",
|
||||
"ports": [
|
||||
"8080"
|
||||
],
|
||||
"env-file": [
|
||||
"${dir:state}/mailu.env",
|
||||
"${dir:state}/secret.env",
|
||||
"${dir:state}/database.env",
|
||||
"${dir:state}/admin.env"
|
||||
],
|
||||
"volumes": [
|
||||
"${dir:data-data}:/data",
|
||||
"${dir:data-dkim}:/dkim"
|
||||
],
|
||||
"secrets-in-environment": "mailu-admin honours SECRET_KEY_FILE, DB_PW_FILE and API_TOKEN_FILE (configuration.py) but INITIAL_ADMIN_PW is env-only (start.py); the remaining containers' need for SECRET_KEY is unverified"
|
||||
},
|
||||
{
|
||||
"id": "imap",
|
||||
"type": "container",
|
||||
"name": "mailu-imap",
|
||||
"image": "ghcr.io/mailu/dovecot@sha256:7f0ed5db996fbdc00adc5c5e38a08492e04f7eb4a9fbd66a03aa9a28ddf23993",
|
||||
"health": {
|
||||
"kind": "runtime"
|
||||
},
|
||||
"network": "mailu",
|
||||
"env-file": [
|
||||
"${dir:state}/mailu.env"
|
||||
],
|
||||
"volumes": [
|
||||
"${dir:data-mail}:/mail",
|
||||
"${dir:data-overrides-dovecot}:/overrides:ro"
|
||||
],
|
||||
"dns": [
|
||||
"192.168.203.254"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "smtp",
|
||||
"type": "container",
|
||||
"name": "mailu-smtp",
|
||||
"image": "ghcr.io/mailu/postfix@sha256:e2e49f39e53b80eac9e7a2f18d9df11edeb4914fd62dbba89b3155e8e034f62e",
|
||||
"health": {
|
||||
"kind": "tool",
|
||||
"tool": "mailu_health",
|
||||
"interval": "60s",
|
||||
"timeout": "30s",
|
||||
"looks": 3,
|
||||
"grace": "120s"
|
||||
},
|
||||
"network": "mailu",
|
||||
"env-file": [
|
||||
"${dir:state}/mailu.env"
|
||||
],
|
||||
"volumes": [
|
||||
"${dir:data-mailqueue}:/queue",
|
||||
"${dir:data-overrides-postfix}:/overrides:ro"
|
||||
],
|
||||
"dns": [
|
||||
"192.168.203.254"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "antispam",
|
||||
"type": "container",
|
||||
"name": "mailu-antispam",
|
||||
"image": "ghcr.io/mailu/rspamd@sha256:ff3666d8a61f17d309c5c6f6bcf4d40470b82299ca706ac650301175bb1a079d",
|
||||
"health": {
|
||||
"kind": "runtime"
|
||||
},
|
||||
"network": "mailu",
|
||||
"env-file": [
|
||||
"${dir:state}/mailu.env"
|
||||
],
|
||||
"volumes": [
|
||||
"${dir:data-filter}:/var/lib/rspamd",
|
||||
"${dir:data-overrides-rspamd}:/etc/rspamd/override.d:ro"
|
||||
],
|
||||
"dns": [
|
||||
"192.168.203.254"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "antivirus",
|
||||
"type": "container",
|
||||
"name": "mailu-antivirus",
|
||||
"image": "clamav/clamav-debian@sha256:b12ef8fefddbba7d88de59bea8a32622f365339154adf02d38fd089112e6745a",
|
||||
"network": "mailu",
|
||||
"volumes": [
|
||||
"${dir:data-clamav}:/var/lib/clamav"
|
||||
],
|
||||
"dns": [
|
||||
"192.168.203.254"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "webmail",
|
||||
"type": "container",
|
||||
"name": "mailu-webmail",
|
||||
"image": "ghcr.io/mailu/webmail@sha256:bdbee44cdb05a4658f0e3b62cc448de55ca8f8aea172279fda594826144c04f6",
|
||||
"health": {
|
||||
"kind": "runtime"
|
||||
},
|
||||
"network": "mailu",
|
||||
"env-file": [
|
||||
"${dir:state}/mailu.env",
|
||||
"${dir:state}/secret.env"
|
||||
],
|
||||
"volumes": [
|
||||
"${dir:data-webmail}:/data",
|
||||
"${dir:data-overrides-roundcube}:/overrides:ro"
|
||||
],
|
||||
"secrets-in-environment": "mailu-admin honours SECRET_KEY_FILE, DB_PW_FILE and API_TOKEN_FILE (configuration.py) but INITIAL_ADMIN_PW is env-only (start.py); the remaining containers' need for SECRET_KEY is unverified",
|
||||
"dns": [
|
||||
"192.168.203.254"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "webdav",
|
||||
"type": "container",
|
||||
"name": "mailu-webdav",
|
||||
"image": "ghcr.io/mailu/radicale@sha256:690ed6edf189dfef100a5a8b37c195ebf5d9241ac5f23f2f44b8b7b75726e3de",
|
||||
"health": {
|
||||
"kind": "runtime"
|
||||
},
|
||||
"network": "mailu",
|
||||
"env-file": [
|
||||
"${dir:state}/mailu.env",
|
||||
"${dir:state}/secret.env"
|
||||
],
|
||||
"volumes": [
|
||||
"${dir:data-dav}:/data"
|
||||
],
|
||||
"secrets-in-environment": "mailu-admin honours SECRET_KEY_FILE, DB_PW_FILE and API_TOKEN_FILE (configuration.py) but INITIAL_ADMIN_PW is env-only (start.py); the remaining containers' need for SECRET_KEY is unverified",
|
||||
"dns": [
|
||||
"192.168.203.254"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "fetchmail",
|
||||
"type": "container",
|
||||
"name": "mailu-fetchmail",
|
||||
"image": "ghcr.io/mailu/fetchmail@sha256:f881c8412d3bbe73d638469b48321558d6403a9d45bfa043c1e52c752103d42d",
|
||||
"health": {
|
||||
"kind": "runtime"
|
||||
},
|
||||
"network": "mailu",
|
||||
"env-file": [
|
||||
"${dir:state}/mailu.env",
|
||||
"${dir:state}/secret.env"
|
||||
],
|
||||
"volumes": [
|
||||
"${dir:data-fetchmail}:/data"
|
||||
],
|
||||
"secrets-in-environment": "mailu-admin honours SECRET_KEY_FILE, DB_PW_FILE and API_TOKEN_FILE (configuration.py) but INITIAL_ADMIN_PW is env-only (start.py); the remaining containers' need for SECRET_KEY is unverified",
|
||||
"dns": [
|
||||
"192.168.203.254"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "front",
|
||||
"type": "container",
|
||||
"name": "mailu-front",
|
||||
"image": "ghcr.io/mailu/nginx@sha256:36f98897cd1bc9d27628bbb4e04bdf60147af2ec7507d6da77f002c4f256896d",
|
||||
"health": {
|
||||
"kind": "exec",
|
||||
"command": "curl -m3 -skfLo /dev/null http://127.0.0.1:10204/health && kill -0 $(cat /run/dovecot/master.pid) && python3 -c \"import smtplib; s = smtplib.SMTP('127.0.0.1', 25, timeout=5); s.ehlo('health'); s.quit()\" && openssl x509 -checkend 1209600 -noout -in /certs/letsencrypt/live/mailu/nginx-chain.pem",
|
||||
"interval": "60s",
|
||||
"timeout": "15s",
|
||||
"looks": 3,
|
||||
"grace": "120s"
|
||||
},
|
||||
"network": "mailu",
|
||||
"env-file": [
|
||||
"${dir:state}/mailu.env"
|
||||
],
|
||||
"ports": [
|
||||
"25",
|
||||
"110",
|
||||
"143",
|
||||
"465",
|
||||
"587",
|
||||
"993",
|
||||
"995",
|
||||
"7080:80",
|
||||
"7443:443"
|
||||
],
|
||||
"volumes": [
|
||||
"${dir:data-certs}:/certs",
|
||||
"${dir:data-overrides-nginx}:/overrides:ro"
|
||||
],
|
||||
"dns": [
|
||||
"192.168.203.254"
|
||||
],
|
||||
"logging": "journald"
|
||||
},
|
||||
{
|
||||
"id": "runtime-config",
|
||||
"type": "file",
|
||||
"path": "${dir:mesh-state}/config.json",
|
||||
"mode": "0600",
|
||||
"template": "files/config.json",
|
||||
"takes-config": ["domain", "proxy-address", "sitename", "website", "url", "container"],
|
||||
"merge": "json"
|
||||
},
|
||||
{
|
||||
"id": "automx",
|
||||
"type": "container",
|
||||
"name": "mailu-automx",
|
||||
"artifact": "automx",
|
||||
"network": "mailu",
|
||||
"env-file": [
|
||||
"${dir:state}/mailu.env"
|
||||
],
|
||||
"ports": [
|
||||
"4243"
|
||||
],
|
||||
"volumes": [
|
||||
"${dir:data-automx}:/data"
|
||||
]
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"on": [
|
||||
{
|
||||
"arg": "PYTHON_BASE",
|
||||
"image": "python@sha256:25f3cfeaceca14921366af4d1240b56457ef46273bdb508c7b0e8f469f6fd228"
|
||||
}
|
||||
],
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "code",
|
||||
"kind": "bundle",
|
||||
"language": "typescript",
|
||||
"entrypoints": [
|
||||
"index.js",
|
||||
"tools/index.js",
|
||||
"provisioner/index.js"
|
||||
],
|
||||
"loads": [
|
||||
"index.js",
|
||||
"tools/index.js",
|
||||
"provisioner/index.js"
|
||||
],
|
||||
"env": {
|
||||
"MESH_MAILU_URL": "http://127.0.0.1:${port:8080}/api/v1",
|
||||
"MESH_MAILU_API_KEY_FILE": "${dir:state}/api-token.secret",
|
||||
"MESH_MAILU_IMAP_CONTAINER": "mailu-imap",
|
||||
"MESH_MAILU_SMTP_CONTAINER": "mailu-smtp",
|
||||
"MESH_MAILU_CONFIG_FILE": "${dir:mesh-state}/config.json",
|
||||
"MESH_RECEIVES": "${dir:grants}/mesh.json"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "automx",
|
||||
"kind": "image",
|
||||
"from": "automx/Dockerfile"
|
||||
},
|
||||
{
|
||||
"name": "files",
|
||||
"kind": "archive",
|
||||
"from": "files"
|
||||
}
|
||||
]
|
||||
},
|
||||
"provides": [
|
||||
{
|
||||
"name": "smtp",
|
||||
"scope": "mesh",
|
||||
"identity": {
|
||||
"max": 64,
|
||||
"in": "a mailbox's local part"
|
||||
}
|
||||
}
|
||||
],
|
||||
"serves": {
|
||||
"smtp": {
|
||||
"port": 587,
|
||||
"domain": "${config:domain}"
|
||||
}
|
||||
},
|
||||
"receives": {
|
||||
"smtp": "${dir:grants}/mesh.json"
|
||||
},
|
||||
"grants": {
|
||||
"smtp": "${dir:grants}"
|
||||
},
|
||||
"jails": [
|
||||
{
|
||||
"name": "mailu-front",
|
||||
"failregex": "^.*(?:imap|pop3|submission|managesieve)-login: .*\\(auth failed, \\d+ attempts(?: in \\d+ secs)?\\):.*rip=<HOST>(?:,|$)\n ^.*client login failed: \"AUTH not supported\" while in http auth state, client: <HOST>, server: \\S+:25,",
|
||||
"jail": "backend = systemd\njournalmatch = CONTAINER_NAME=mailu-front\nport = smtp,submission,submissions,imap,imaps,pop3,pop3s\nmaxretry = 3\nfindtime = 1d\nbantime = 1d"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"module": "marrytts",
|
||||
"version": "1",
|
||||
"capabilities": [
|
||||
"container-runtime"
|
||||
],
|
||||
"listens": [
|
||||
{
|
||||
"name": "api",
|
||||
"port": 59125,
|
||||
"protocol": "tcp",
|
||||
"from": "mesh",
|
||||
"why": "the MaryTTS text-to-speech HTTP API and web interface"
|
||||
}
|
||||
],
|
||||
"resources": [
|
||||
{
|
||||
"id": "mesh-state",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"place": "mesh",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "server",
|
||||
"type": "container",
|
||||
"name": "marrytts",
|
||||
"image": "synesthesiam/marytts@sha256:45970ecb3e21a2981c66c60563a70cf00be8e95c02565e7d74b3a73dcec7db2c",
|
||||
"env": {
|
||||
"TZ": "Europe/Brussels"
|
||||
},
|
||||
"ports": [
|
||||
"59125"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,257 @@
|
||||
{
|
||||
"module": "matrix",
|
||||
"version": "1",
|
||||
"capabilities": [
|
||||
"container-runtime"
|
||||
],
|
||||
"listens": [
|
||||
{
|
||||
"name": "client",
|
||||
"port": 6167,
|
||||
"protocol": "tcp",
|
||||
"from": "mesh",
|
||||
"why": "Conduit's client-server and federation APIs over plain HTTP. Both arrive through the route on 443: Conduit answers /.well-known/matrix/server with <its name>:443, so other homeservers federate through the proxy and nothing needs the traditional 8448"
|
||||
},
|
||||
{
|
||||
"name": "web",
|
||||
"port": 80,
|
||||
"protocol": "tcp",
|
||||
"from": "mesh",
|
||||
"why": "Element Web, the static browser client, served by the image's nginx; reached through its route"
|
||||
}
|
||||
],
|
||||
"requires": [
|
||||
"route"
|
||||
],
|
||||
"contributes": {
|
||||
"route": {
|
||||
"homeserver": {
|
||||
"label": "matrix",
|
||||
"endpoint": "client"
|
||||
},
|
||||
"element": {
|
||||
"label": "element",
|
||||
"endpoint": "web"
|
||||
}
|
||||
}
|
||||
},
|
||||
"binds": {
|
||||
"route": "${dir:state}/route.json"
|
||||
},
|
||||
"data": {
|
||||
"own": [
|
||||
{
|
||||
"id": "db",
|
||||
"path": "${dir:db}",
|
||||
"class": "valuable",
|
||||
"why": "every room, message and account"
|
||||
}
|
||||
]
|
||||
},
|
||||
"config": {
|
||||
"default_server_name": {
|
||||
"type": "string",
|
||||
"description": "Element's default_server_name setting of config.json: the homeserver Element signs in to by default, by name; the file's default is the module's own route.",
|
||||
"trusted": true,
|
||||
"default": "${bound:route:name-homeserver}"
|
||||
},
|
||||
"default_server_config": {
|
||||
"type": "object",
|
||||
"description": "Element's default_server_config setting of config.json: the homeserver and identity server Element uses by default, by URL.",
|
||||
"trusted": true,
|
||||
"default": {
|
||||
"m.homeserver": {
|
||||
"base_url": "https://${bound:route:name-homeserver}"
|
||||
},
|
||||
"m.identity_server": {
|
||||
"base_url": "https://vector.im"
|
||||
}
|
||||
}
|
||||
},
|
||||
"brand": {
|
||||
"type": "string",
|
||||
"description": "Element's brand setting of config.json: the name Element shows itself as.",
|
||||
"trusted": true,
|
||||
"default": "Element"
|
||||
},
|
||||
"integrations_ui_url": {
|
||||
"type": "string",
|
||||
"description": "Element's integrations_ui_url setting of config.json: the integration manager's page, a URL.",
|
||||
"trusted": true,
|
||||
"default": "https://scalar.vector.im/"
|
||||
},
|
||||
"integrations_rest_url": {
|
||||
"type": "string",
|
||||
"description": "Element's integrations_rest_url setting of config.json: the integration manager's API, a URL.",
|
||||
"trusted": true,
|
||||
"default": "https://scalar.vector.im/api"
|
||||
},
|
||||
"integrations_widgets_urls": {
|
||||
"type": "list",
|
||||
"description": "Element's integrations_widgets_urls setting of config.json: the URLs whose widgets Element trusts as the integration manager's.",
|
||||
"trusted": true,
|
||||
"default": [
|
||||
"https://scalar.vector.im/_matrix/integrations/v1",
|
||||
"https://scalar.vector.im/api",
|
||||
"https://scalar-staging.vector.im/_matrix/integrations/v1",
|
||||
"https://scalar-staging.vector.im/api",
|
||||
"https://scalar-staging.riot.im/scalar/api"
|
||||
]
|
||||
},
|
||||
"bug_report_endpoint_url": {
|
||||
"type": "string",
|
||||
"description": "Element's bug_report_endpoint_url setting of config.json: where Element sends a bug report, a URL; its default here is empty, and the file's own value (Element's, naming outside servers) stays in the file and is never replaced unless this is set.",
|
||||
"trusted": true,
|
||||
"default": ""
|
||||
},
|
||||
"uisi_autorageshake_app": {
|
||||
"type": "string",
|
||||
"description": "Element's uisi_autorageshake_app setting of config.json: the app name Element files an automatic report of an undecryptable message under.",
|
||||
"trusted": true,
|
||||
"default": "element-auto-uisi"
|
||||
},
|
||||
"show_labs_settings": {
|
||||
"type": "boolean",
|
||||
"description": "Element's show_labs_settings setting of config.json: whether Element shows its Labs settings.",
|
||||
"trusted": true,
|
||||
"default": true
|
||||
},
|
||||
"room_directory": {
|
||||
"type": "object",
|
||||
"description": "Element's room_directory setting of config.json: the servers whose room directories Element offers; its default here is empty, and the file's own value (Element's, naming outside servers) stays in the file and is never replaced unless this is set.",
|
||||
"trusted": true,
|
||||
"default": {}
|
||||
},
|
||||
"enable_presence_by_hs_url": {
|
||||
"type": "object",
|
||||
"description": "Element's enable_presence_by_hs_url setting of config.json: whether Element shows presence, per homeserver URL.",
|
||||
"trusted": true,
|
||||
"default": {
|
||||
"https://matrix.org": false,
|
||||
"https://matrix-client.matrix.org": false
|
||||
}
|
||||
},
|
||||
"terms_and_conditions_links": {
|
||||
"type": "list",
|
||||
"description": "Element's terms_and_conditions_links setting of config.json: the links Element shows as its terms, each a URL and its text; its default here is empty, and the file's own value (Element's, naming outside servers) stays in the file and is never replaced unless this is set.",
|
||||
"trusted": true,
|
||||
"default": []
|
||||
},
|
||||
"features": {
|
||||
"type": "object",
|
||||
"description": "Element's features setting of config.json: Element's feature switches, each on or off.",
|
||||
"trusted": true,
|
||||
"default": {
|
||||
"feature_video_rooms": true,
|
||||
"feature_rust_crypto": true
|
||||
}
|
||||
},
|
||||
"element_call": {
|
||||
"type": "object",
|
||||
"description": "Element's element_call setting of config.json: where Element starts a call with Element Call, a URL.",
|
||||
"trusted": true,
|
||||
"default": {
|
||||
"url": "https://call.element.dev"
|
||||
}
|
||||
}
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"id": "state",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"place": ".",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "db",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "conduit-conf",
|
||||
"type": "file",
|
||||
"path": "${dir:state}/conduit.toml",
|
||||
"mode": "0644",
|
||||
"template": "files/conduit.toml",
|
||||
"names-on-purpose": {
|
||||
"matrix.org": "the federation's public key server, trusted by default; the world's, not this mesh's"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "element-conf",
|
||||
"type": "file",
|
||||
"path": "${dir:state}/element.json",
|
||||
"mode": "0644",
|
||||
"merge": "json",
|
||||
"takes-config": ["default_server_name", "default_server_config", "brand", "integrations_ui_url", "integrations_rest_url", "integrations_widgets_urls", "bug_report_endpoint_url", "uisi_autorageshake_app", "show_labs_settings", "room_directory", "enable_presence_by_hs_url", "terms_and_conditions_links", "features", "element_call"],
|
||||
"template": "files/element.json",
|
||||
"names-on-purpose": {
|
||||
"matrix.org": "the public room directory and the federation's largest homeserver; the world's",
|
||||
"matrix-client.matrix.org": "the same homeserver's client endpoint; the world's",
|
||||
"vector.im": "Element's public identity server; the world's",
|
||||
"scalar.vector.im": "Element's public integration manager; the world's",
|
||||
"scalar-staging.vector.im": "Element's staging integration manager, named by the upstream default config; the world's",
|
||||
"scalar-staging.riot.im": "the same, under its former name; the world's",
|
||||
"element.io": "Element's bug reports, privacy and cookie pages; the world's",
|
||||
"gitter.im": "a public room directory; the world's",
|
||||
"libera.chat": "a public room directory; the world's",
|
||||
"call.element.dev": "Element Call's public instance; the world's"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "net",
|
||||
"type": "network",
|
||||
"name": "matrix"
|
||||
},
|
||||
{
|
||||
"id": "homeserver",
|
||||
"type": "container",
|
||||
"name": "matrix",
|
||||
"image": "matrixconduit/matrix-conduit@sha256:b0d24248e94f944ca49f90f10c429e3d65f4472bdde25661ecea9840134fb133",
|
||||
"network": "matrix",
|
||||
"env": {
|
||||
"CONDUIT_CONFIG": "/etc/conduit/conduit.toml"
|
||||
},
|
||||
"ports": [
|
||||
"6167"
|
||||
],
|
||||
"volumes": [
|
||||
"${dir:db}:/var/lib/matrix-conduit",
|
||||
"${dir:state}/conduit.toml:/etc/conduit/conduit.toml:ro"
|
||||
],
|
||||
"restart-on": [
|
||||
"conduit-conf"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "element",
|
||||
"type": "container",
|
||||
"name": "element-web",
|
||||
"image": "vectorim/element-web@sha256:a8f415462ab8d2600a592ba1b92bea51efe5a4d10eb738aab9bed769f7099613",
|
||||
"health": {
|
||||
"kind": "runtime"
|
||||
},
|
||||
"network": "matrix",
|
||||
"ports": [
|
||||
"80"
|
||||
],
|
||||
"volumes": [
|
||||
"${dir:state}/element.json:/app/config.json:ro"
|
||||
],
|
||||
"restart-on": [
|
||||
"element-conf"
|
||||
]
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "files",
|
||||
"kind": "archive",
|
||||
"from": "files"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
+130
@@ -0,0 +1,130 @@
|
||||
{
|
||||
"module": "memory-pressure",
|
||||
"version": "1",
|
||||
"capabilities": [
|
||||
"package-manager",
|
||||
"service-manager"
|
||||
],
|
||||
"emits": [
|
||||
"pressure.high",
|
||||
"pressure.cleared"
|
||||
],
|
||||
"tools": [
|
||||
"memory_status",
|
||||
"memory_top",
|
||||
"memory_oom_history",
|
||||
"memory_zram",
|
||||
"memory_oomd",
|
||||
"memory_guard"
|
||||
],
|
||||
"resources": [
|
||||
{
|
||||
"id": "zram-generator",
|
||||
"type": "package",
|
||||
"package": "zram-generator"
|
||||
},
|
||||
{
|
||||
"id": "zram",
|
||||
"type": "file",
|
||||
"path": "/etc/systemd/zram-generator.conf",
|
||||
"mode": "0644",
|
||||
"template": "files/zram-generator.conf"
|
||||
},
|
||||
{
|
||||
"id": "sysctl-drop-ins",
|
||||
"type": "directory",
|
||||
"path": "/etc/sysctl.d",
|
||||
"mode": "0755",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "swap-tunables",
|
||||
"type": "file",
|
||||
"path": "/etc/sysctl.d/90-memory-pressure.conf",
|
||||
"mode": "0644",
|
||||
"template": "files/sysctl.conf"
|
||||
},
|
||||
{
|
||||
"id": "sysctl",
|
||||
"type": "service",
|
||||
"unit": "systemd-sysctl.service",
|
||||
"restart-on": [
|
||||
"swap-tunables"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "oomd-drop-ins",
|
||||
"type": "directory",
|
||||
"path": "/etc/systemd/oomd.conf.d",
|
||||
"mode": "0755",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "oomd-limits",
|
||||
"type": "file",
|
||||
"path": "/etc/systemd/oomd.conf.d/memory-pressure.conf",
|
||||
"mode": "0644",
|
||||
"template": "files/oomd.conf"
|
||||
},
|
||||
{
|
||||
"id": "root-slice-drop-ins",
|
||||
"type": "directory",
|
||||
"path": "/etc/systemd/system/-.slice.d",
|
||||
"mode": "0755",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "root-slice",
|
||||
"type": "file",
|
||||
"path": "/etc/systemd/system/-.slice.d/10-oomd.conf",
|
||||
"mode": "0644",
|
||||
"template": "files/root-slice.conf"
|
||||
},
|
||||
{
|
||||
"id": "user-manager-drop-ins",
|
||||
"type": "directory",
|
||||
"path": "/etc/systemd/system/user@.service.d",
|
||||
"mode": "0755",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "user-manager",
|
||||
"type": "file",
|
||||
"path": "/etc/systemd/system/user@.service.d/10-oomd.conf",
|
||||
"mode": "0644",
|
||||
"template": "files/user-manager.conf"
|
||||
},
|
||||
{
|
||||
"id": "oomd",
|
||||
"type": "service",
|
||||
"unit": "systemd-oomd.service",
|
||||
"state": "running",
|
||||
"boot": "enabled",
|
||||
"restart-on": [
|
||||
"oomd-limits",
|
||||
"root-slice",
|
||||
"user-manager"
|
||||
]
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "tools-go",
|
||||
"kind": "bundle",
|
||||
"language": "go",
|
||||
"system": "arch",
|
||||
"from": "cmd/memory-pressure",
|
||||
"binary": "memory-pressure",
|
||||
"loads": [
|
||||
"memory-pressure"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "files",
|
||||
"kind": "archive",
|
||||
"from": "files"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
{
|
||||
"module": "mesh-catalog",
|
||||
"slug": "catalog",
|
||||
"version": "1",
|
||||
"capabilities": [
|
||||
"container-runtime"
|
||||
],
|
||||
"claims": [
|
||||
{
|
||||
"name": "mesh-catalog",
|
||||
"scope": "mesh"
|
||||
}
|
||||
],
|
||||
"requires": [
|
||||
"postgres-database"
|
||||
],
|
||||
"contributes": {
|
||||
"postgres-database": {
|
||||
"name": "mesh_catalog"
|
||||
}
|
||||
},
|
||||
"binds": {
|
||||
"postgres-database": "${dir:state}/database.json"
|
||||
},
|
||||
"secrets": {
|
||||
"postgres-database": "${dir:state}/database.secret"
|
||||
},
|
||||
"consumes": [
|
||||
"node-build-agent.built",
|
||||
"mesh-build-machine.built",
|
||||
"mesh-controller.built-before"
|
||||
],
|
||||
"emits": [
|
||||
"registered",
|
||||
"upgraded",
|
||||
"rebuild-needed",
|
||||
"catching-up"
|
||||
],
|
||||
"resources": [
|
||||
{
|
||||
"id": "state",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"place": ".",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "database-url",
|
||||
"type": "file",
|
||||
"path": "${dir:state}/database.url",
|
||||
"mode": "0600",
|
||||
"template": "files/database.url"
|
||||
},
|
||||
{
|
||||
"id": "prepare",
|
||||
"type": "process",
|
||||
"name": "mesh-catalog-prepare",
|
||||
"artifact": "code",
|
||||
"run": [
|
||||
"node",
|
||||
"prepare/index.js"
|
||||
],
|
||||
"run-once": true,
|
||||
"env": {
|
||||
"DATABASE_URL_FILE": "${dir:state}/database.url"
|
||||
},
|
||||
"restart-on": [
|
||||
"database-url"
|
||||
]
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "code",
|
||||
"kind": "bundle",
|
||||
"language": "typescript",
|
||||
"entrypoints": [
|
||||
"index.js",
|
||||
"tools/index.js",
|
||||
"prepare/index.js"
|
||||
],
|
||||
"loads": [
|
||||
"index.js",
|
||||
"tools/index.js"
|
||||
],
|
||||
"env": {
|
||||
"DATABASE_URL_FILE": "${dir:state}/database.url"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "files",
|
||||
"kind": "archive",
|
||||
"from": "files"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"module": "mesh-cli",
|
||||
"version": "1",
|
||||
"moved": true,
|
||||
"resources": [
|
||||
{
|
||||
"id": "program",
|
||||
"type": "archive",
|
||||
"artifact": "program",
|
||||
"path": "/usr/local/bin",
|
||||
"unknown": "program"
|
||||
}
|
||||
],
|
||||
"items": [
|
||||
{
|
||||
"collection": "shell:zsh:normal",
|
||||
"template": "files/zsh-normal"
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "program",
|
||||
"kind": "bundle",
|
||||
"language": "go",
|
||||
"system": "arch",
|
||||
"from": "cmd/mesh-cli",
|
||||
"binary": "mesh-cli"
|
||||
},
|
||||
{
|
||||
"name": "files",
|
||||
"kind": "archive",
|
||||
"from": "files"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
{
|
||||
"module": "mesh-config",
|
||||
"version": "1",
|
||||
"runs-as": "mesh-config",
|
||||
"claims": [
|
||||
{
|
||||
"name": "mesh-config",
|
||||
"scope": "mesh",
|
||||
"serves": [
|
||||
"config"
|
||||
]
|
||||
}
|
||||
],
|
||||
"emits": [
|
||||
"config-changed"
|
||||
],
|
||||
"uses": [
|
||||
"operator-channel"
|
||||
],
|
||||
"invokes": [
|
||||
"seat:mesh-controller.hand-act",
|
||||
"seat:mesh-controller.warranted"
|
||||
],
|
||||
"reads": [
|
||||
"mesh-controller.assignments",
|
||||
"mesh-controller.declared-config",
|
||||
"mesh-controller.predefined"
|
||||
],
|
||||
"state": [
|
||||
"values",
|
||||
"resolved",
|
||||
"predefined",
|
||||
"proposals"
|
||||
],
|
||||
"logs": [
|
||||
"history"
|
||||
],
|
||||
"own-secrets": {
|
||||
"broker": "${dir:state}/broker"
|
||||
},
|
||||
"secrets-owner": "mesh-config",
|
||||
"resources": [
|
||||
{
|
||||
"id": "account",
|
||||
"type": "user",
|
||||
"name": "mesh-config",
|
||||
"shell": "/usr/bin/nologin",
|
||||
"home": "/var/lib/mesh-config"
|
||||
},
|
||||
{
|
||||
"id": "state",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"owner": "mesh-config",
|
||||
"place": ".",
|
||||
"unknown": "program"
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "tools",
|
||||
"kind": "bundle",
|
||||
"language": "go",
|
||||
"system": "arch",
|
||||
"from": "cmd/mesh-config",
|
||||
"binary": "mesh-config",
|
||||
"loads": [
|
||||
"mesh-config"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
+110
@@ -0,0 +1,110 @@
|
||||
{
|
||||
"module": "mesh-delivery-gate",
|
||||
"version": "1",
|
||||
"slug": "gate",
|
||||
"claims": [
|
||||
{
|
||||
"name": "mesh-delivery",
|
||||
"scope": "mesh",
|
||||
"serves": [
|
||||
"deliveries",
|
||||
"times",
|
||||
"show",
|
||||
"groups",
|
||||
"what-if",
|
||||
"checks",
|
||||
"table",
|
||||
"stalled",
|
||||
"recheck",
|
||||
"release",
|
||||
"stop",
|
||||
"close",
|
||||
"retire-history"
|
||||
]
|
||||
}
|
||||
],
|
||||
"consumes": [
|
||||
"gitea.pull.updated",
|
||||
"gitea.pull.merged",
|
||||
"gitea.pull.closed",
|
||||
"gitea.forge.status",
|
||||
"gitea.forge.pull-request.edited",
|
||||
"gitea.forge.pull-request.closed",
|
||||
"mesh-controller.checked",
|
||||
"mesh-controller.plan-moved",
|
||||
"mesh-delivery-forge-bridge.forge.**"
|
||||
],
|
||||
"emits": [
|
||||
"transition",
|
||||
"group",
|
||||
"merged"
|
||||
],
|
||||
"invokes": [
|
||||
"seat:mesh-controller.deliver",
|
||||
"seat:mesh-controller.delivery-stop",
|
||||
"seat:mesh-controller.delivery-backups-again",
|
||||
"seat:mesh-controller.delivery-walks",
|
||||
"seat:mesh-controller.delivery-check",
|
||||
"seat:mesh-controller.forget-checks",
|
||||
"seat:mesh-controller.plans",
|
||||
"gitea.gitea_commit_statuses",
|
||||
"gitea.gitea_contains",
|
||||
"gitea.gitea_open_pulls"
|
||||
],
|
||||
"state": [
|
||||
"deliveries",
|
||||
"groups",
|
||||
"pulls",
|
||||
{
|
||||
"name": "asks",
|
||||
"history": 5
|
||||
},
|
||||
{
|
||||
"name": "merges",
|
||||
"history": 10
|
||||
},
|
||||
{
|
||||
"name": "owed",
|
||||
"history": 5
|
||||
},
|
||||
{
|
||||
"name": "source",
|
||||
"history": 64
|
||||
}
|
||||
],
|
||||
"reads": [
|
||||
"mesh-delivery.deliveries",
|
||||
"mesh-delivery.groups",
|
||||
"mesh-delivery.pulls",
|
||||
"mesh-delivery-teller.answers",
|
||||
"mesh-controller.assignments",
|
||||
"node-engine.have"
|
||||
],
|
||||
"tools": [
|
||||
"delivery_status"
|
||||
],
|
||||
"resources": [
|
||||
{
|
||||
"id": "state",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"place": ".",
|
||||
"unknown": "program"
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "tools",
|
||||
"kind": "bundle",
|
||||
"language": "go",
|
||||
"system": "arch",
|
||||
"from": "cmd/mesh-delivery-gate",
|
||||
"binary": "mesh-delivery-gate",
|
||||
"loads": [
|
||||
"mesh-delivery-gate"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
{
|
||||
"module": "mesh-delivery",
|
||||
"version": "1",
|
||||
"slug": "deliver",
|
||||
"claims": [
|
||||
{
|
||||
"name": "mesh-delivery",
|
||||
"scope": "mesh",
|
||||
"serves": [
|
||||
"deliveries",
|
||||
"times",
|
||||
"show",
|
||||
"groups",
|
||||
"what-if",
|
||||
"checks",
|
||||
"table",
|
||||
"stalled",
|
||||
"recheck",
|
||||
"release",
|
||||
"stop",
|
||||
"close",
|
||||
"retire-history"
|
||||
]
|
||||
}
|
||||
],
|
||||
"consumes": [
|
||||
"gitea.pull.updated",
|
||||
"gitea.pull.merged",
|
||||
"gitea.pull.closed",
|
||||
"gitea.forge.status",
|
||||
"gitea.forge.pull-request.edited",
|
||||
"gitea.forge.pull-request.closed",
|
||||
"mesh-controller.checked",
|
||||
"mesh-controller.plan-moved"
|
||||
],
|
||||
"emits": [
|
||||
"transition",
|
||||
"group",
|
||||
"merged"
|
||||
],
|
||||
"invokes": [
|
||||
"seat:mesh-controller.delivery-plan",
|
||||
"seat:mesh-controller.delivery-check",
|
||||
"seat:mesh-controller.deliver",
|
||||
"seat:mesh-controller.delivery-backups-again",
|
||||
"seat:mesh-controller.delivery-stop",
|
||||
"seat:mesh-controller.delivery-walks",
|
||||
"seat:mesh-controller.forget-checks",
|
||||
"gitea.gitea_note_append",
|
||||
"gitea.gitea_delivery_view",
|
||||
"gitea.gitea_commit_status",
|
||||
"gitea.gitea_commit_statuses",
|
||||
"gitea.gitea_contains",
|
||||
"gitea.gitea_open_pulls",
|
||||
"gitea.gitea_merge_pull_request",
|
||||
"gitea.gitea_add_comment",
|
||||
"seat:operator-channel.notify"
|
||||
],
|
||||
"uses": [
|
||||
"operator-channel"
|
||||
],
|
||||
"state": [
|
||||
"deliveries",
|
||||
"groups",
|
||||
"asked",
|
||||
"pulls"
|
||||
],
|
||||
"tools": [
|
||||
"delivery_status"
|
||||
],
|
||||
"resources": [
|
||||
{
|
||||
"id": "state",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"place": ".",
|
||||
"unknown": "program"
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "tools",
|
||||
"kind": "bundle",
|
||||
"language": "go",
|
||||
"system": "arch",
|
||||
"from": "cmd/mesh-delivery",
|
||||
"binary": "mesh-delivery",
|
||||
"loads": [
|
||||
"mesh-delivery"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
{
|
||||
"module": "mesh-files",
|
||||
"version": "1",
|
||||
"claims": [
|
||||
{
|
||||
"name": "node-files",
|
||||
"scope": "node",
|
||||
"serves": [
|
||||
"stat",
|
||||
"readlink",
|
||||
"list",
|
||||
"read",
|
||||
"search",
|
||||
"account",
|
||||
"write",
|
||||
"copy",
|
||||
"move",
|
||||
"delete",
|
||||
"mkdir",
|
||||
"chmod",
|
||||
"chown",
|
||||
"trash",
|
||||
"restore"
|
||||
]
|
||||
}
|
||||
],
|
||||
"invokes": [
|
||||
"seat:operator-channel.tell"
|
||||
],
|
||||
"resources": [
|
||||
{
|
||||
"id": "state",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"place": ".",
|
||||
"unknown": "program"
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "tools",
|
||||
"kind": "bundle",
|
||||
"language": "go",
|
||||
"system": "arch",
|
||||
"from": "cmd/mesh-files",
|
||||
"binary": "mesh-files",
|
||||
"loads": [
|
||||
"mesh-files"
|
||||
],
|
||||
"env": {
|
||||
"MESH_FILES_STATE": "${dir:state}"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,330 @@
|
||||
{
|
||||
"module": "mesh-issues",
|
||||
"version": "1",
|
||||
"slug": "issues",
|
||||
"seats": [
|
||||
{
|
||||
"name": "issue-tracker",
|
||||
"scope": "mesh",
|
||||
"serves": [
|
||||
"open",
|
||||
"get",
|
||||
"list",
|
||||
"move",
|
||||
"note",
|
||||
"link",
|
||||
"import",
|
||||
"groom",
|
||||
"set",
|
||||
"tracking",
|
||||
"reserve",
|
||||
"fix-times"
|
||||
]
|
||||
}
|
||||
],
|
||||
"claims": [
|
||||
{
|
||||
"name": "issue-tracker",
|
||||
"scope": "mesh",
|
||||
"serves": [
|
||||
"open",
|
||||
"get",
|
||||
"list",
|
||||
"move",
|
||||
"note",
|
||||
"link",
|
||||
"import",
|
||||
"groom",
|
||||
"set",
|
||||
"tracking",
|
||||
"reserve",
|
||||
"fix-times"
|
||||
]
|
||||
}
|
||||
],
|
||||
"emits": [
|
||||
"opened",
|
||||
"moved",
|
||||
"noted",
|
||||
"linked",
|
||||
"imported",
|
||||
"set",
|
||||
"triaged",
|
||||
"ready",
|
||||
"ready-to-verify",
|
||||
"reserved"
|
||||
],
|
||||
"consumes": [
|
||||
"mesh-issues.opened",
|
||||
"mesh-issues.moved",
|
||||
"mesh-delivery.transition",
|
||||
"mesh-delivery-gate.transition"
|
||||
],
|
||||
"invokes": [
|
||||
"claude-code.claude_code_judge",
|
||||
"seat:mesh-delivery.checks",
|
||||
"seat:operator-channel.notify",
|
||||
"gitea.gitea_pull_reviews",
|
||||
"records.records_status",
|
||||
"records.records_list",
|
||||
"records.records_read",
|
||||
"mesh-knowledge.knowledge_highest"
|
||||
],
|
||||
"logs": [
|
||||
"changes"
|
||||
],
|
||||
"state": [
|
||||
{
|
||||
"name": "issues",
|
||||
"history": 2
|
||||
},
|
||||
"counters",
|
||||
"grooming",
|
||||
"reservations"
|
||||
],
|
||||
"config": {
|
||||
"first-number": {
|
||||
"type": "number",
|
||||
"description": "The number the first issue the tracker numbers gets, read once when its counter starts and never again; the import reads it as the boundary between the folders hq numbered and the tracker's issues.",
|
||||
"minimum": 1,
|
||||
"trusted": true,
|
||||
"default": 365
|
||||
},
|
||||
"owners": {
|
||||
"type": "list",
|
||||
"description": "The registered places an issue's located-in may name: a repository, or a repository and a folder in it separated by a space.",
|
||||
"trusted": true,
|
||||
"default": [
|
||||
"hq",
|
||||
"mesh-catalog",
|
||||
"mesh-catalog modules/adwaita",
|
||||
"mesh-catalog modules/artifact-store-tools",
|
||||
"mesh-catalog modules/asus-zephyrus-g14",
|
||||
"mesh-catalog modules/audit-logger",
|
||||
"mesh-catalog modules/avahi",
|
||||
"mesh-catalog modules/baserow",
|
||||
"mesh-catalog modules/betterbird",
|
||||
"mesh-catalog modules/blueman",
|
||||
"mesh-catalog modules/bluetooth",
|
||||
"mesh-catalog modules/ca-trust",
|
||||
"mesh-catalog modules/claude-code",
|
||||
"mesh-catalog modules/claude-licence-manager",
|
||||
"mesh-catalog modules/clipmenu",
|
||||
"mesh-catalog modules/confluence",
|
||||
"mesh-catalog modules/cups",
|
||||
"mesh-catalog modules/dbus",
|
||||
"mesh-catalog modules/desk-channel",
|
||||
"mesh-catalog modules/disk-load",
|
||||
"mesh-catalog modules/distribution",
|
||||
"mesh-catalog modules/dmenu",
|
||||
"mesh-catalog modules/dnsmasq",
|
||||
"mesh-catalog modules/docker",
|
||||
"mesh-catalog modules/docker-compose",
|
||||
"mesh-catalog modules/dunst",
|
||||
"mesh-catalog modules/fail2ban",
|
||||
"mesh-catalog modules/feh",
|
||||
"mesh-catalog modules/flatpak",
|
||||
"mesh-catalog modules/fonts",
|
||||
"mesh-catalog modules/forticlient",
|
||||
"mesh-catalog modules/gitea",
|
||||
"mesh-catalog modules/gitlab",
|
||||
"mesh-catalog modules/gnome-keyring",
|
||||
"mesh-catalog modules/grafana",
|
||||
"mesh-catalog modules/hello-web",
|
||||
"mesh-catalog modules/home-assistant",
|
||||
"mesh-catalog modules/hostname",
|
||||
"mesh-catalog modules/i3",
|
||||
"mesh-catalog modules/i3status-rust",
|
||||
"mesh-catalog modules/icecast",
|
||||
"mesh-catalog modules/influxdb",
|
||||
"mesh-catalog modules/invoicing",
|
||||
"mesh-catalog modules/jira",
|
||||
"mesh-catalog modules/keycloak",
|
||||
"mesh-catalog modules/lab",
|
||||
"mesh-catalog modules/lemurs",
|
||||
"mesh-catalog modules/letta",
|
||||
"mesh-catalog modules/local-model-consumer",
|
||||
"mesh-catalog modules/localization",
|
||||
"mesh-catalog modules/logrotate",
|
||||
"mesh-catalog modules/mailu",
|
||||
"mesh-catalog modules/marrytts",
|
||||
"mesh-catalog modules/matrix",
|
||||
"mesh-catalog modules/memory-pressure",
|
||||
"mesh-catalog modules/mesh-catalog",
|
||||
"mesh-catalog modules/mesh-cli",
|
||||
"mesh-catalog modules/mesh-delivery",
|
||||
"mesh-catalog modules/mesh-delivery-gate",
|
||||
"mesh-catalog modules/mesh-issues",
|
||||
"mesh-catalog modules/mesh-vault",
|
||||
"mesh-catalog modules/mesh-watcher",
|
||||
"mesh-catalog modules/messenger",
|
||||
"mesh-catalog modules/minio",
|
||||
"mesh-catalog modules/model-usage",
|
||||
"mesh-catalog modules/mongodb",
|
||||
"mesh-catalog modules/mosquitto",
|
||||
"mesh-catalog modules/mounts",
|
||||
"mesh-catalog modules/mssql",
|
||||
"mesh-catalog modules/n8n",
|
||||
"mesh-catalog modules/nats",
|
||||
"mesh-catalog modules/netcheck",
|
||||
"mesh-catalog modules/networkmanager",
|
||||
"mesh-catalog modules/nextcloud",
|
||||
"mesh-catalog modules/nextcloud-client",
|
||||
"mesh-catalog modules/nfs-server",
|
||||
"mesh-catalog modules/nftables",
|
||||
"mesh-catalog modules/nm-applet",
|
||||
"mesh-catalog modules/node-env",
|
||||
"mesh-catalog modules/nodered",
|
||||
"mesh-catalog modules/ollama",
|
||||
"mesh-catalog modules/only-office",
|
||||
"mesh-catalog modules/openai-consumer",
|
||||
"mesh-catalog modules/openrazer",
|
||||
"mesh-catalog modules/pacman",
|
||||
"mesh-catalog modules/photos-eef",
|
||||
"mesh-catalog modules/photos-filip",
|
||||
"mesh-catalog modules/picom",
|
||||
"mesh-catalog modules/polychromatic",
|
||||
"mesh-catalog modules/postgres",
|
||||
"mesh-catalog modules/power",
|
||||
"mesh-catalog modules/powerlevel10k",
|
||||
"mesh-catalog modules/records",
|
||||
"mesh-catalog modules/redis",
|
||||
"mesh-catalog modules/restic",
|
||||
"mesh-catalog modules/rofi",
|
||||
"mesh-catalog modules/route-adapter",
|
||||
"mesh-catalog modules/screen-lock",
|
||||
"mesh-catalog modules/searxng",
|
||||
"mesh-catalog modules/sensors",
|
||||
"mesh-catalog modules/showcase",
|
||||
"mesh-catalog modules/slack",
|
||||
"mesh-catalog modules/snapd",
|
||||
"mesh-catalog modules/ssh-client",
|
||||
"mesh-catalog modules/sshd",
|
||||
"mesh-catalog modules/step-ca",
|
||||
"mesh-catalog modules/sudo",
|
||||
"mesh-catalog modules/supabase",
|
||||
"mesh-catalog modules/systemd",
|
||||
"mesh-catalog modules/systemd-networkd",
|
||||
"mesh-catalog modules/systemd-resolved",
|
||||
"mesh-catalog modules/telegram",
|
||||
"mesh-catalog modules/time-sync",
|
||||
"mesh-catalog modules/triggerhappy",
|
||||
"mesh-catalog modules/umami",
|
||||
"mesh-catalog modules/unifi",
|
||||
"mesh-catalog modules/website",
|
||||
"mesh-catalog modules/xclip",
|
||||
"mesh-catalog modules/xdg",
|
||||
"mesh-catalog modules/xorg",
|
||||
"mesh-catalog modules/xterm",
|
||||
"mesh-catalog modules/zfs",
|
||||
"mesh-catalog modules/zsh",
|
||||
"mesh-catalog modules/zsh-autosuggestions",
|
||||
"mesh-catalog modules/zsh-syntax-highlighting",
|
||||
"mesh-controller",
|
||||
"mesh-controller modules/build-agent",
|
||||
"mesh-controller modules/route-proxy",
|
||||
"mesh-delivery",
|
||||
"mesh-host",
|
||||
"mesh-lab",
|
||||
"mesh-media-catalog",
|
||||
"mesh-sdk",
|
||||
"mesh-tools"
|
||||
]
|
||||
},
|
||||
"duplicate-check": {
|
||||
"type": "string",
|
||||
"description": "Whether a new issue is checked against the open ones for a duplicate: off stops it, anything else is on (novox/hq ADR 0278 §7).",
|
||||
"trusted": true,
|
||||
"default": "on"
|
||||
},
|
||||
"judge-model": {
|
||||
"type": "string",
|
||||
"description": "The model the duplicate check asks, by the agent's name for it, such as sonnet; empty is the tracker's own default.",
|
||||
"trusted": true,
|
||||
"default": "sonnet"
|
||||
},
|
||||
"forge-owner": {
|
||||
"type": "string",
|
||||
"description": "The owner on the forge of the repositories an issue's fixed-by names, for asking after a pull request's delivery (novox/hq ADR 0279 §3); empty asks no forge.",
|
||||
"trusted": true,
|
||||
"default": "novox"
|
||||
},
|
||||
"stuck-after": {
|
||||
"type": "string",
|
||||
"description": "How long a fix may be merged and not delivered before it is said stuck, as a duration such as 2h (novox/hq ADR 0281); empty is the tracker's own default.",
|
||||
"pattern": "|[0-9]+(\\.[0-9]+)?(ns|us|µs|ms|s|m|h)([0-9]+(\\.[0-9]+)?(ns|us|µs|ms|s|m|h))*",
|
||||
"trusted": true,
|
||||
"default": "2h"
|
||||
},
|
||||
"worker-stale-after": {
|
||||
"type": "string",
|
||||
"description": "How long an issue's worker stays current with nothing done on it, as a duration such as 24h (novox/hq ADR 0284 §4); empty is the tracker's own default.",
|
||||
"pattern": "|[0-9]+(\\.[0-9]+)?(ns|us|µs|ms|s|m|h)([0-9]+(\\.[0-9]+)?(ns|us|µs|ms|s|m|h))*",
|
||||
"trusted": true,
|
||||
"default": "24h"
|
||||
},
|
||||
"delivered-not-resolved-after": {
|
||||
"type": "string",
|
||||
"description": "How long an issue may stay in fixing once every fix it names is delivered before the operator is warned, as a duration such as 1h (novox/hq issue 483); empty is the tracker's own default.",
|
||||
"pattern": "|[0-9]+(\\.[0-9]+)?(ns|us|µs|ms|s|m|h)([0-9]+(\\.[0-9]+)?(ns|us|µs|ms|s|m|h))*",
|
||||
"trusted": true,
|
||||
"default": "1h"
|
||||
},
|
||||
"decision-floor": {
|
||||
"type": "number",
|
||||
"description": "The highest decision number already taken somewhere the tracker cannot read, such as an open branch of hq; the decision sequence's first number is one above it, read once when the counter starts (novox/hq issue 424).",
|
||||
"minimum": 0,
|
||||
"trusted": true,
|
||||
"default": 293
|
||||
},
|
||||
"research-floor": {
|
||||
"type": "number",
|
||||
"description": "The highest research number already taken somewhere the tracker cannot read; the research sequence's first number is one above it, read once when the counter starts (novox/hq issue 424).",
|
||||
"minimum": 0,
|
||||
"trusted": true,
|
||||
"default": 45
|
||||
}
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"id": "state",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"place": ".",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "settings",
|
||||
"trusted": true,
|
||||
"type": "file",
|
||||
"path": "${dir:state}/settings.json",
|
||||
"mode": "0600",
|
||||
"takes-config": ["first-number", "owners", "duplicate-check", "judge-model", "forge-owner", "stuck-after", "worker-stale-after", "delivered-not-resolved-after", "decision-floor", "research-floor"],
|
||||
"merge": "json",
|
||||
"template": "files/settings.json"
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "tools",
|
||||
"kind": "bundle",
|
||||
"language": "go",
|
||||
"system": "arch",
|
||||
"from": "cmd/mesh-issues",
|
||||
"binary": "mesh-issues",
|
||||
"loads": [
|
||||
"mesh-issues"
|
||||
],
|
||||
"env": {
|
||||
"MESH_ISSUES_SETTINGS": "${dir:state}/settings.json"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "files",
|
||||
"kind": "archive",
|
||||
"from": "files"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,218 @@
|
||||
{
|
||||
"module": "mesh-knowledge",
|
||||
"version": "1",
|
||||
"slug": "knowledge",
|
||||
"requires": [
|
||||
"postgres-database"
|
||||
],
|
||||
"contributes": {
|
||||
"postgres-database": {
|
||||
"name": "knowledge"
|
||||
}
|
||||
},
|
||||
"binds": {
|
||||
"postgres-database": "${dir:state}/database.json"
|
||||
},
|
||||
"secrets": {
|
||||
"postgres-database": "${dir:state}/database.secret"
|
||||
},
|
||||
"seats": [
|
||||
{
|
||||
"name": "knowledge-base",
|
||||
"scope": "mesh",
|
||||
"serves": [
|
||||
"ask",
|
||||
"get",
|
||||
"list",
|
||||
"findings",
|
||||
"holds",
|
||||
"links",
|
||||
"history",
|
||||
"reserve",
|
||||
"propose",
|
||||
"import",
|
||||
"return",
|
||||
"withdraw"
|
||||
]
|
||||
}
|
||||
],
|
||||
"claims": [
|
||||
{
|
||||
"name": "knowledge-base",
|
||||
"scope": "mesh",
|
||||
"serves": [
|
||||
"ask",
|
||||
"get",
|
||||
"list",
|
||||
"findings",
|
||||
"holds",
|
||||
"links",
|
||||
"history",
|
||||
"reserve",
|
||||
"propose",
|
||||
"import",
|
||||
"return",
|
||||
"withdraw"
|
||||
]
|
||||
}
|
||||
],
|
||||
"tools": [
|
||||
"knowledge_health",
|
||||
"knowledge_highest"
|
||||
],
|
||||
"emits": [
|
||||
"reserved",
|
||||
"proposed",
|
||||
"reviewed",
|
||||
"accepted",
|
||||
"changed",
|
||||
"imported",
|
||||
"drafted",
|
||||
"confirmed",
|
||||
"returned"
|
||||
],
|
||||
"uses": [
|
||||
"operator-channel"
|
||||
],
|
||||
"invokes": [
|
||||
"seat:issue-tracker.reserve",
|
||||
"claude-code.claude_code_judge",
|
||||
"claude-code.claude_code_judged",
|
||||
"records.records_status",
|
||||
"records.records_list",
|
||||
"records.records_read",
|
||||
"seat:operator-channel.notify"
|
||||
],
|
||||
"config": {
|
||||
"judge-model": {
|
||||
"type": "string",
|
||||
"description": "The model the knowledge base's drafting and confirming judgements ask, by the agent's name for it, such as sonnet; empty is sonnet.",
|
||||
"default": "sonnet"
|
||||
},
|
||||
"drafting": {
|
||||
"type": "string",
|
||||
"description": "Whether the knowledge base drafts and confirms clauses itself: off stops it, anything else is on.",
|
||||
"default": "on"
|
||||
},
|
||||
"reserved-for": {
|
||||
"type": "string",
|
||||
"description": "How long a reserved number waits for its proposal before it is withdrawn, as a duration such as 168h; empty is the knowledge base's own default.",
|
||||
"pattern": "|[0-9]+(\\.[0-9]+)?(ns|us|µs|ms|s|m|h)([0-9]+(\\.[0-9]+)?(ns|us|µs|ms|s|m|h))*",
|
||||
"default": "168h"
|
||||
}
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"id": "state",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"place": ".",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "database-url",
|
||||
"type": "file",
|
||||
"path": "${dir:state}/database.url",
|
||||
"mode": "0600",
|
||||
"template": "files/database.url"
|
||||
},
|
||||
{
|
||||
"id": "settings",
|
||||
"trusted": false,
|
||||
"type": "file",
|
||||
"path": "${dir:state}/settings.json",
|
||||
"mode": "0600",
|
||||
"takes-config": ["judge-model", "drafting", "reserved-for"],
|
||||
"merge": "json",
|
||||
"template": "files/settings.json"
|
||||
},
|
||||
{
|
||||
"id": "prepare",
|
||||
"type": "process",
|
||||
"name": "mesh-knowledge-prepare",
|
||||
"artifact": "tools",
|
||||
"run": [
|
||||
"./mesh-knowledge",
|
||||
"prepare"
|
||||
],
|
||||
"run-once": true,
|
||||
"env": {
|
||||
"DATABASE_URL_FILE": "${dir:state}/database.url"
|
||||
},
|
||||
"restart-on": [
|
||||
"database-url"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "keep",
|
||||
"type": "process",
|
||||
"name": "mesh-knowledge-keep",
|
||||
"artifact": "tools",
|
||||
"run": [
|
||||
"./mesh-knowledge",
|
||||
"keep"
|
||||
],
|
||||
"env": {
|
||||
"DATABASE_URL_FILE": "${dir:state}/database.url"
|
||||
},
|
||||
"restart-on": [
|
||||
"database-url"
|
||||
],
|
||||
"health": {
|
||||
"kind": "unit"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "watch",
|
||||
"type": "process",
|
||||
"name": "mesh-knowledge-watch",
|
||||
"artifact": "tools",
|
||||
"run": [
|
||||
"./mesh-knowledge",
|
||||
"watch"
|
||||
],
|
||||
"user": "${machine:account}",
|
||||
"env": {
|
||||
"DATABASE_URL_FILE": "${dir:state}/database.url",
|
||||
"MESH_KNOWLEDGE_STATUS": "${dir:state}/health.json"
|
||||
},
|
||||
"restart-on": [
|
||||
"database-url"
|
||||
],
|
||||
"health": {
|
||||
"kind": "tool",
|
||||
"tool": "knowledge_health",
|
||||
"needs": "postgres-database",
|
||||
"interval": "60s",
|
||||
"timeout": "10s",
|
||||
"looks": 2,
|
||||
"grace": "180s"
|
||||
}
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "tools",
|
||||
"kind": "bundle",
|
||||
"language": "go",
|
||||
"system": "arch",
|
||||
"from": "cmd/mesh-knowledge",
|
||||
"binary": "mesh-knowledge",
|
||||
"loads": [
|
||||
"mesh-knowledge"
|
||||
],
|
||||
"env": {
|
||||
"DATABASE_URL_FILE": "${dir:state}/database.url",
|
||||
"MESH_KNOWLEDGE_SETTINGS": "${dir:state}/settings.json",
|
||||
"MESH_KNOWLEDGE_STATUS": "${dir:state}/health.json"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "files",
|
||||
"kind": "archive",
|
||||
"from": "files"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
{
|
||||
"module": "mesh-mail-notifier",
|
||||
"version": "1",
|
||||
"runs-as": "mesh-mail-notifier",
|
||||
"claims": [
|
||||
{
|
||||
"name": "mail-notifier",
|
||||
"scope": "node",
|
||||
"serves": ["status"]
|
||||
}
|
||||
],
|
||||
"consumes": [
|
||||
"mesh-mail.mail.*.message.added"
|
||||
],
|
||||
"invokes": [
|
||||
"seat:node-notifier.send",
|
||||
"seat:mail-store.accounts"
|
||||
],
|
||||
"emits": [
|
||||
"shown"
|
||||
],
|
||||
"state": [
|
||||
{
|
||||
"name": "shown",
|
||||
"ttl-seconds": 2592000
|
||||
}
|
||||
],
|
||||
"tools": [
|
||||
"mail-notifier.status",
|
||||
"mail_notifier_health"
|
||||
],
|
||||
"own-secrets": {
|
||||
"broker": "${dir:state}/broker"
|
||||
},
|
||||
"secrets-owner": "mesh-mail-notifier",
|
||||
"resources": [
|
||||
{
|
||||
"id": "account",
|
||||
"type": "user",
|
||||
"name": "mesh-mail-notifier",
|
||||
"shell": "/usr/bin/nologin",
|
||||
"home": "/var/lib/mesh-mail-notifier"
|
||||
},
|
||||
{
|
||||
"id": "state",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"owner": "mesh-mail-notifier",
|
||||
"place": ".",
|
||||
"unknown": "program"
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "tools",
|
||||
"kind": "bundle",
|
||||
"language": "go",
|
||||
"system": "arch",
|
||||
"from": "cmd/mesh-mail-notifier",
|
||||
"binary": "mesh-mail-notifier",
|
||||
"loads": [
|
||||
"mesh-mail-notifier"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
{
|
||||
"module": "mesh-mail-web",
|
||||
"version": "1",
|
||||
"slug": "mail-web",
|
||||
"runs-as": "mesh-mail-web",
|
||||
"claims": [
|
||||
{
|
||||
"name": "mail-webclient",
|
||||
"scope": "mesh",
|
||||
"serves": ["open", "status"]
|
||||
}
|
||||
],
|
||||
"invokes": [
|
||||
"seat:mail-store.accounts",
|
||||
"seat:mail-store.search",
|
||||
"seat:mail-store.read",
|
||||
"seat:mail-store.send",
|
||||
"seat:mail-store.send-status"
|
||||
],
|
||||
"reads": ["mesh-mail.accounts"],
|
||||
"requires": ["route", "oidc-client"],
|
||||
"contributes": {
|
||||
"route": {
|
||||
"label": "mail",
|
||||
"endpoint": "web"
|
||||
},
|
||||
"oidc-client": {
|
||||
"label": "mail",
|
||||
"endpoint": "web",
|
||||
"callback": "/signed-in"
|
||||
}
|
||||
},
|
||||
"binds": {
|
||||
"route": "${dir:state}/route.json",
|
||||
"oidc-client": "${dir:state}/oidc-bound.json"
|
||||
},
|
||||
"secrets": {
|
||||
"oidc-client": "${dir:state}/oidc-bound.secret"
|
||||
},
|
||||
"listens": [
|
||||
{
|
||||
"name": "web",
|
||||
"port": 8099,
|
||||
"protocol": "tcp",
|
||||
"from": "mesh",
|
||||
"why": "the mail web client's pages, over http; only the route proxy reaches it, and the operator's own browser through the internal name (novox/hq ADR 0440 §2) — its public name, if any, is a route grant"
|
||||
}
|
||||
],
|
||||
"config": {
|
||||
"operators": {
|
||||
"type": "list",
|
||||
"description": "The Keycloak identities (the ID token's preferred_username) let to sign in; nobody by default (novox/hq ADR 0440 §3).",
|
||||
"trusted": true,
|
||||
"default": []
|
||||
}
|
||||
},
|
||||
"tools": [
|
||||
"mail-webclient.open",
|
||||
"mail-webclient.status",
|
||||
"mail_web_health"
|
||||
],
|
||||
"own-secrets": {
|
||||
"broker": "${dir:state}/broker"
|
||||
},
|
||||
"secrets-owner": "mesh-mail-web",
|
||||
"resources": [
|
||||
{
|
||||
"id": "account",
|
||||
"type": "user",
|
||||
"name": "mesh-mail-web",
|
||||
"shell": "/usr/bin/nologin",
|
||||
"home": "/var/lib/mesh-mail-web"
|
||||
},
|
||||
{
|
||||
"id": "state",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"owner": "mesh-mail-web",
|
||||
"place": ".",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "operators",
|
||||
"trusted": true,
|
||||
"type": "file",
|
||||
"path": "${dir:state}/operators.json",
|
||||
"mode": "0600",
|
||||
"owner": "mesh-mail-web",
|
||||
"merge": "json",
|
||||
"template": "files/operators.json",
|
||||
"takes-config": ["operators"]
|
||||
},
|
||||
{
|
||||
"id": "oidc-config",
|
||||
"type": "file",
|
||||
"path": "${dir:state}/oidc.json",
|
||||
"mode": "0600",
|
||||
"owner": "mesh-mail-web",
|
||||
"template": "files/oidc.json"
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "tools",
|
||||
"kind": "bundle",
|
||||
"language": "go",
|
||||
"system": "arch",
|
||||
"from": "cmd/mesh-mail-web",
|
||||
"binary": "mesh-mail-web",
|
||||
"loads": ["mesh-mail-web"],
|
||||
"env": {
|
||||
"MESH_MAIL_WEB_OPERATORS": "${dir:state}/operators.json",
|
||||
"MESH_MAIL_WEB_OIDC": "${dir:state}/oidc.json",
|
||||
"MESH_MAIL_WEB_LISTEN": "${port:8099}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "files",
|
||||
"kind": "archive",
|
||||
"from": "files"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,312 @@
|
||||
{
|
||||
"module": "mesh-mail",
|
||||
"version": "1",
|
||||
"slug": "mail",
|
||||
"seats": [
|
||||
{
|
||||
"name": "mail-store",
|
||||
"scope": "mesh",
|
||||
"serves": ["accounts", "search", "read", "send", "send-status"]
|
||||
},
|
||||
{
|
||||
"name": "mail-webclient",
|
||||
"scope": "mesh",
|
||||
"serves": ["open", "status"]
|
||||
},
|
||||
{
|
||||
"name": "mail-notifier",
|
||||
"scope": "node",
|
||||
"needs": ["node-notifier"],
|
||||
"serves": ["status"]
|
||||
}
|
||||
],
|
||||
"claims": [
|
||||
{
|
||||
"name": "mail-store",
|
||||
"scope": "mesh",
|
||||
"serves": ["accounts", "search", "read", "send", "send-status"]
|
||||
}
|
||||
],
|
||||
"requires": [
|
||||
"postgres-database",
|
||||
"s3-bucket"
|
||||
],
|
||||
"contributes": {
|
||||
"postgres-database": {
|
||||
"name": "mail"
|
||||
}
|
||||
},
|
||||
"binds": {
|
||||
"postgres-database": "${dir:state}/database.json",
|
||||
"s3-bucket": "${dir:state}/store-binding.json"
|
||||
},
|
||||
"secrets": {
|
||||
"postgres-database": "${dir:state}/database.secret",
|
||||
"s3-bucket": "${dir:state}/store.secret"
|
||||
},
|
||||
"own-secrets": {
|
||||
"mail-credential-*": {
|
||||
"path": "${dir:state}/mail-credential-*.secret",
|
||||
"issued-by": "outside",
|
||||
"prompt": "the password of the mail account {member}",
|
||||
"owner": "mesh-mail-send"
|
||||
},
|
||||
"broker-send": {
|
||||
"path": "${dir:state}/broker-send.secret",
|
||||
"owner": "mesh-mail-send"
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"accounts": {
|
||||
"type": "object",
|
||||
"description": "The mail accounts, each by a lower-case name that names it on the bus and its secret: its kind (imap), address, incoming and outgoing servers (host, port, security tls or starttls), and optionally the folders watched and the user it signs in as; no password, which is the own secret mail-credential-<account> (novox/hq ADR 0359 §5).",
|
||||
"trusted": true,
|
||||
"default": {}
|
||||
},
|
||||
"grants": {
|
||||
"type": "object",
|
||||
"description": "Per account, who may read its mail and who may send from it: a module's name (on every machine), <machine>.<module>, or person.<name>. Nobody by default; it restricts the stream MAIL and the tools mail_search, mail_read and mail_send alike (novox/hq ADR 0359 §4).",
|
||||
"trusted": true,
|
||||
"default": {}
|
||||
}
|
||||
},
|
||||
"tools": [
|
||||
"mail_accounts",
|
||||
"mail_search",
|
||||
"mail_read",
|
||||
"mail_health",
|
||||
"mail_send",
|
||||
"mail_send_status",
|
||||
"mail-store.accounts",
|
||||
"mail-store.search",
|
||||
"mail-store.read",
|
||||
"mail-store.send",
|
||||
"mail-store.send-status"
|
||||
],
|
||||
"uses": [
|
||||
"operator-channel"
|
||||
],
|
||||
"state": [
|
||||
"sends",
|
||||
"accounts",
|
||||
"mails"
|
||||
],
|
||||
"emits": [
|
||||
"mail.send.sent",
|
||||
"mail.send.failed"
|
||||
],
|
||||
"streams": [
|
||||
{
|
||||
"name": "mail",
|
||||
"events": [
|
||||
"mail.*.message.added",
|
||||
"mail.*.message.changed",
|
||||
"mail.*.message.removed"
|
||||
],
|
||||
"max-age-days": 7,
|
||||
"grant": {
|
||||
"config": "grants",
|
||||
"events": "mail.{key}.**"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "mail-sends",
|
||||
"events": [
|
||||
"mail.send.approved"
|
||||
],
|
||||
"max-age-days": 1,
|
||||
"max-mib": 64,
|
||||
"retention": "work-queue",
|
||||
"max-deliveries": 5,
|
||||
"duplicates": 24
|
||||
}
|
||||
],
|
||||
"resources": [
|
||||
{
|
||||
"id": "account",
|
||||
"type": "user",
|
||||
"name": "mesh-mail-send"
|
||||
},
|
||||
{
|
||||
"id": "state",
|
||||
"type": "directory",
|
||||
"mode": "0711",
|
||||
"place": ".",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "database-url",
|
||||
"type": "file",
|
||||
"path": "${dir:state}/database.url",
|
||||
"mode": "0600",
|
||||
"template": "files/database-url"
|
||||
},
|
||||
{
|
||||
"id": "store",
|
||||
"type": "file",
|
||||
"path": "${dir:state}/store.json",
|
||||
"mode": "0600",
|
||||
"template": "files/store.json"
|
||||
},
|
||||
{
|
||||
"id": "accounts",
|
||||
"trusted": true,
|
||||
"type": "file",
|
||||
"path": "${dir:state}/accounts.json",
|
||||
"mode": "0644",
|
||||
"merge": "json",
|
||||
"template": "files/accounts.json",
|
||||
"takes-config": [
|
||||
"accounts"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "grants",
|
||||
"trusted": true,
|
||||
"type": "file",
|
||||
"path": "${dir:state}/grants.json",
|
||||
"mode": "0600",
|
||||
"merge": "json",
|
||||
"template": "files/grants.json",
|
||||
"takes-config": [
|
||||
"grants"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "prepare",
|
||||
"type": "process",
|
||||
"name": "mesh-mail-prepare",
|
||||
"artifact": "tools",
|
||||
"run": [
|
||||
"./mesh-mail",
|
||||
"prepare"
|
||||
],
|
||||
"run-once": true,
|
||||
"env": {
|
||||
"DATABASE_URL_FILE": "${dir:state}/database.url"
|
||||
},
|
||||
"restart-on": [
|
||||
"database-url"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "keep",
|
||||
"type": "process",
|
||||
"name": "mesh-mail-keep",
|
||||
"artifact": "tools",
|
||||
"run": [
|
||||
"./mesh-mail",
|
||||
"keep"
|
||||
],
|
||||
"env": {
|
||||
"DATABASE_URL_FILE": "${dir:state}/database.url",
|
||||
"MESH_MAIL_ACCOUNTS": "${dir:state}/accounts.json",
|
||||
"MESH_MAIL_SECRETS": "${dir:state}",
|
||||
"MESH_MAIL_STORE": "${dir:state}/store.json"
|
||||
},
|
||||
"restart-on": [
|
||||
"database-url",
|
||||
"store",
|
||||
"accounts"
|
||||
],
|
||||
"health": {
|
||||
"kind": "unit"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "watch",
|
||||
"type": "process",
|
||||
"name": "mesh-mail-watch",
|
||||
"artifact": "tools",
|
||||
"run": [
|
||||
"./mesh-mail",
|
||||
"watch"
|
||||
],
|
||||
"user": "${machine:account}",
|
||||
"env": {
|
||||
"DATABASE_URL_FILE": "${dir:state}/database.url",
|
||||
"MESH_MAIL_ACCOUNTS": "${dir:state}/accounts.json",
|
||||
"MESH_MAIL_SECRETS": "${dir:state}",
|
||||
"MESH_MAIL_STATUS": "${dir:state}/health.json"
|
||||
},
|
||||
"restart-on": [
|
||||
"database-url",
|
||||
"accounts"
|
||||
],
|
||||
"health": {
|
||||
"kind": "tool",
|
||||
"tool": "mail_health",
|
||||
"needs": "postgres-database",
|
||||
"interval": "60s",
|
||||
"timeout": "10s",
|
||||
"looks": 2,
|
||||
"grace": "180s"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "send",
|
||||
"type": "process",
|
||||
"name": "mesh-mail-send",
|
||||
"artifact": "tools",
|
||||
"run": [
|
||||
"./mesh-mail",
|
||||
"send"
|
||||
],
|
||||
"user": "mesh-mail-send",
|
||||
"env": {
|
||||
"MESH_MAIL_ACCOUNTS": "${dir:state}/accounts.json",
|
||||
"MESH_MAIL_SECRETS": "${dir:state}"
|
||||
},
|
||||
"restart-on": [
|
||||
"accounts"
|
||||
],
|
||||
"bus": {
|
||||
"emits": [
|
||||
"mail.send.sent",
|
||||
"mail.send.failed"
|
||||
],
|
||||
"queues": [
|
||||
"mail-sends"
|
||||
],
|
||||
"state": [
|
||||
"sends"
|
||||
],
|
||||
"asks": true,
|
||||
"invokes": [
|
||||
"seat:operator-channel.tell"
|
||||
]
|
||||
},
|
||||
"health": {
|
||||
"kind": "unit"
|
||||
}
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "tools",
|
||||
"kind": "bundle",
|
||||
"language": "go",
|
||||
"system": "arch",
|
||||
"from": "cmd/mesh-mail",
|
||||
"binary": "mesh-mail",
|
||||
"loads": [
|
||||
"mesh-mail"
|
||||
],
|
||||
"env": {
|
||||
"DATABASE_URL_FILE": "${dir:state}/database.url",
|
||||
"MESH_MAIL_ACCOUNTS": "${dir:state}/accounts.json",
|
||||
"MESH_MAIL_GRANTS": "${dir:state}/grants.json",
|
||||
"MESH_MAIL_SECRETS": "${dir:state}",
|
||||
"MESH_MAIL_STORE": "${dir:state}/store.json",
|
||||
"MESH_MAIL_STATUS": "${dir:state}/health.json"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "files",
|
||||
"kind": "archive",
|
||||
"from": "files"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
{
|
||||
"module": "mesh-provisioner-client",
|
||||
"version": "1",
|
||||
"claims": [
|
||||
{
|
||||
"name": "node-provisioner",
|
||||
"scope": "node"
|
||||
}
|
||||
],
|
||||
"own-secrets": {
|
||||
"provisioner-broker": "${dir:state}/broker"
|
||||
},
|
||||
"secrets-owner": "mesh-provisioner-client",
|
||||
"resources": [
|
||||
{
|
||||
"id": "account",
|
||||
"type": "user",
|
||||
"name": "mesh-provisioner-client",
|
||||
"shell": "/usr/bin/nologin",
|
||||
"home": "/var/lib/mesh-provisioner-client"
|
||||
},
|
||||
{
|
||||
"id": "state",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"owner": "mesh-provisioner-client",
|
||||
"place": ".",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "client",
|
||||
"type": "process",
|
||||
"name": "mesh-provisioner-client",
|
||||
"artifact": "client",
|
||||
"run": [
|
||||
"./mesh-provisioner-client"
|
||||
],
|
||||
"env": {
|
||||
"MESH_PROVISIONER_CREDENTIAL": "${dir:state}/broker",
|
||||
"MESH_PROVISIONER_STATE": "${dir:state}"
|
||||
},
|
||||
"user": "mesh-provisioner-client",
|
||||
"health": {
|
||||
"kind": "unit"
|
||||
}
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "client",
|
||||
"kind": "bundle",
|
||||
"language": "go",
|
||||
"system": "arch",
|
||||
"from": "cmd/mesh-provisioner-client",
|
||||
"binary": "mesh-provisioner-client"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
{
|
||||
"module": "mesh-provisioner",
|
||||
"version": "1",
|
||||
"runs-as": "mesh-provisioner",
|
||||
"claims": [
|
||||
{
|
||||
"name": "mesh-provisioner",
|
||||
"scope": "mesh",
|
||||
"serves": [
|
||||
"provisioning"
|
||||
]
|
||||
}
|
||||
],
|
||||
"state": [
|
||||
"registry",
|
||||
"needs",
|
||||
"applied",
|
||||
"collect"
|
||||
],
|
||||
"own-secrets": {
|
||||
"broker": "${dir:state}/broker"
|
||||
},
|
||||
"secrets-owner": "mesh-provisioner",
|
||||
"resources": [
|
||||
{
|
||||
"id": "account",
|
||||
"type": "user",
|
||||
"name": "mesh-provisioner",
|
||||
"shell": "/usr/bin/nologin",
|
||||
"home": "/var/lib/mesh-provisioner"
|
||||
},
|
||||
{
|
||||
"id": "state",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"owner": "mesh-provisioner",
|
||||
"place": ".",
|
||||
"unknown": "program"
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "tools",
|
||||
"kind": "bundle",
|
||||
"language": "go",
|
||||
"system": "arch",
|
||||
"from": "cmd/mesh-provisioner",
|
||||
"binary": "mesh-provisioner",
|
||||
"loads": [
|
||||
"mesh-provisioner"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
{
|
||||
"module": "mesh-reads",
|
||||
"version": "1",
|
||||
"runs-as": "mesh-reads",
|
||||
"claims": [
|
||||
{
|
||||
"name": "node-reads",
|
||||
"scope": "node",
|
||||
"serves": [
|
||||
"stat",
|
||||
"readlink",
|
||||
"list",
|
||||
"read",
|
||||
"search",
|
||||
"account"
|
||||
]
|
||||
}
|
||||
],
|
||||
"own-secrets": {
|
||||
"broker": "${dir:state}/broker"
|
||||
},
|
||||
"secrets-owner": "mesh-reads",
|
||||
"resources": [
|
||||
{
|
||||
"id": "account",
|
||||
"type": "user",
|
||||
"name": "mesh-reads",
|
||||
"shell": "/usr/bin/nologin",
|
||||
"home": "/var/lib/mesh-reads"
|
||||
},
|
||||
{
|
||||
"id": "state",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"owner": "mesh-reads",
|
||||
"place": ".",
|
||||
"unknown": "program"
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "tools",
|
||||
"kind": "bundle",
|
||||
"language": "go",
|
||||
"system": "arch",
|
||||
"from": "cmd/mesh-reads",
|
||||
"binary": "mesh-reads",
|
||||
"loads": [
|
||||
"mesh-reads"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
{
|
||||
"module": "mesh-vault",
|
||||
"version": "1",
|
||||
"runs-as": "mesh-vault",
|
||||
"provides": [
|
||||
{
|
||||
"name": "secret",
|
||||
"scope": "mesh",
|
||||
"identity": {
|
||||
"in": "a vault entry"
|
||||
}
|
||||
}
|
||||
],
|
||||
"emits": [
|
||||
"provisioned",
|
||||
"rotated",
|
||||
"secret-changed"
|
||||
],
|
||||
"reads": [
|
||||
"mesh-controller.assignments"
|
||||
],
|
||||
"receives": {
|
||||
"secret": "${dir:grants}/mesh.json"
|
||||
},
|
||||
"grants": {
|
||||
"secret": "${dir:grants}"
|
||||
},
|
||||
"keeps": "/var/lib/mesh-vault/root",
|
||||
"data": {
|
||||
"own": [
|
||||
{
|
||||
"id": "state",
|
||||
"path": "${dir:state}",
|
||||
"class": "valuable",
|
||||
"why": "the vault's own keys"
|
||||
},
|
||||
{
|
||||
"id": "ledger",
|
||||
"path": "${dir:ledger}",
|
||||
"class": "valuable",
|
||||
"why": "every secret the vault keeps"
|
||||
},
|
||||
{
|
||||
"id": "root",
|
||||
"path": "${dir:root}",
|
||||
"class": "valuable",
|
||||
"why": "the vault's root material"
|
||||
},
|
||||
{
|
||||
"id": "store",
|
||||
"path": "${dir:store}",
|
||||
"class": "valuable",
|
||||
"why": "every secret the vault holds, sealed to its own key and to the operator key"
|
||||
}
|
||||
],
|
||||
"consumers": {
|
||||
"secret": {
|
||||
"class": "valuable",
|
||||
"in": "ledger",
|
||||
"why": "a secret given to a consumer is kept nowhere else in the clear"
|
||||
}
|
||||
}
|
||||
},
|
||||
"own-secrets": {
|
||||
"broker": "${dir:state}/broker"
|
||||
},
|
||||
"secrets-owner": "mesh-vault",
|
||||
"runtime-health": {
|
||||
"kind": "tool",
|
||||
"tool": "vault_health",
|
||||
"interval": "60s",
|
||||
"timeout": "10s",
|
||||
"looks": 2,
|
||||
"grace": "60s"
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"id": "account",
|
||||
"type": "user",
|
||||
"name": "mesh-vault",
|
||||
"shell": "/usr/bin/nologin",
|
||||
"home": "/var/lib/mesh-vault"
|
||||
},
|
||||
{
|
||||
"id": "state",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"owner": "mesh-vault",
|
||||
"place": ".",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "grants",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"owner": "mesh-vault",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "ledger",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"owner": "mesh-vault",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "root",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"owner": "mesh-vault",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "store",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"owner": "mesh-vault",
|
||||
"unknown": "program"
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "code",
|
||||
"kind": "bundle",
|
||||
"language": "go",
|
||||
"system": "arch",
|
||||
"from": "cmd/mesh-vault",
|
||||
"binary": "mesh-vault",
|
||||
"loads": [
|
||||
"mesh-vault"
|
||||
],
|
||||
"env": {
|
||||
"MESH_RECEIVES": "${dir:grants}/mesh.json",
|
||||
"MESH_VAULT_LEDGER": "${dir:ledger}",
|
||||
"MESH_VAULT_ROOT": "${dir:root}",
|
||||
"MESH_VAULT_STORE": "${dir:store}",
|
||||
"MESH_VAULT_STATE": "${dir:state}"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"tools": [
|
||||
"secret_export",
|
||||
"secret_holders",
|
||||
"secret_verify",
|
||||
"secret_handed",
|
||||
"secret_asks",
|
||||
"secret_vault_export",
|
||||
"provisioner_retirement",
|
||||
"provisioner_retire_approve",
|
||||
"provisioner_retire_reject",
|
||||
"provisioner_delete",
|
||||
"vault_status",
|
||||
"vault_health"
|
||||
],
|
||||
"claims": [
|
||||
{
|
||||
"name": "mesh-vault",
|
||||
"scope": "mesh",
|
||||
"serves": [
|
||||
"get",
|
||||
"accept",
|
||||
"secret-ask",
|
||||
"issued",
|
||||
"rotate",
|
||||
"move-in",
|
||||
"node-key",
|
||||
"move-asks"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
{
|
||||
"module": "mesh-watcher",
|
||||
"version": "1",
|
||||
"slug": "watch",
|
||||
"consumes": [
|
||||
"mesh-controller.doctor-heartbeat"
|
||||
],
|
||||
"invokes": [
|
||||
"mesh-watcher.watcher_ping",
|
||||
"seat:mesh-controller.seats"
|
||||
],
|
||||
"own-secrets": {
|
||||
"telegram-token": "${dir:state}/telegram-token"
|
||||
},
|
||||
"tools": [
|
||||
"watcher_status",
|
||||
"watcher_last_heard",
|
||||
"watcher_test",
|
||||
"watcher_ping"
|
||||
],
|
||||
"config": {
|
||||
"telegram-chat-id": {
|
||||
"type": "string",
|
||||
"description": "The Telegram chat the watcher reports to: the chat's id, a number, or @name of a channel; empty reports to none.",
|
||||
"trusted": true,
|
||||
"default": ""
|
||||
}
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"id": "state",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"place": ".",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "settings",
|
||||
"type": "file",
|
||||
"path": "${dir:state}/settings.json",
|
||||
"mode": "0600",
|
||||
"takes-config": ["telegram-chat-id"],
|
||||
"merge": "json",
|
||||
"template": "files/settings.json"
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "tools",
|
||||
"kind": "bundle",
|
||||
"language": "go",
|
||||
"system": "arch",
|
||||
"from": "cmd/mesh-watcher",
|
||||
"binary": "mesh-watcher",
|
||||
"loads": [
|
||||
"mesh-watcher"
|
||||
],
|
||||
"env": {
|
||||
"MESH_WATCHER_SETTINGS": "${dir:state}/settings.json",
|
||||
"MESH_WATCHER_TELEGRAM_TOKEN_FILE": "${dir:state}/telegram-token"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "files",
|
||||
"kind": "archive",
|
||||
"from": "files"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,188 @@
|
||||
{
|
||||
"module": "messenger",
|
||||
"version": "1",
|
||||
"slug": "msgr",
|
||||
"runs-as": "messenger",
|
||||
"seats": [
|
||||
{
|
||||
"name": "operator-channel",
|
||||
"scope": "mesh",
|
||||
"serves": [
|
||||
"open",
|
||||
"history",
|
||||
"notify",
|
||||
"tell",
|
||||
"asks"
|
||||
],
|
||||
"accepts": [
|
||||
"ask",
|
||||
"cancel",
|
||||
"condition"
|
||||
],
|
||||
"emits": [
|
||||
"decided"
|
||||
],
|
||||
"by-caller": [
|
||||
"ask",
|
||||
"cancel",
|
||||
"condition",
|
||||
"decided"
|
||||
],
|
||||
"records": [
|
||||
"asks"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "channel",
|
||||
"scope": "mesh",
|
||||
"kinded": true,
|
||||
"accepts": [
|
||||
"show",
|
||||
"edit",
|
||||
"send"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "intake",
|
||||
"scope": "mesh",
|
||||
"kinded": true,
|
||||
"emits": [
|
||||
"choice",
|
||||
"link",
|
||||
"failed",
|
||||
"standing"
|
||||
],
|
||||
"proofs": [
|
||||
"code"
|
||||
]
|
||||
}
|
||||
],
|
||||
"claims": [
|
||||
{
|
||||
"name": "operator-channel",
|
||||
"scope": "mesh",
|
||||
"serves": [
|
||||
"open",
|
||||
"history",
|
||||
"notify",
|
||||
"tell",
|
||||
"asks"
|
||||
]
|
||||
}
|
||||
],
|
||||
"uses": [
|
||||
"channel"
|
||||
],
|
||||
"consumes": [
|
||||
"mesh-controller.condition-raised",
|
||||
"mesh-controller.condition-changed",
|
||||
"mesh-controller.condition-cleared",
|
||||
"mesh-controller.plan-moved",
|
||||
"intake.choice",
|
||||
"intake.link",
|
||||
"intake.failed",
|
||||
"intake.standing"
|
||||
],
|
||||
"emits": [
|
||||
"refused"
|
||||
],
|
||||
"invokes": [
|
||||
"seat:mesh-controller.conditions",
|
||||
"seat:mesh-controller.root-free",
|
||||
"seat:issue-tracker.tracking"
|
||||
],
|
||||
"state": [
|
||||
"open",
|
||||
"sent",
|
||||
{
|
||||
"name": "asks",
|
||||
"ttl-seconds": 2592000
|
||||
},
|
||||
"identities",
|
||||
"walks"
|
||||
],
|
||||
"own-secrets": {
|
||||
"broker": "${dir:state}/broker"
|
||||
},
|
||||
"secrets-owner": "messenger",
|
||||
"tools": [
|
||||
"messenger_status",
|
||||
"messenger_recent",
|
||||
"messenger_test",
|
||||
"messenger_preview",
|
||||
"messenger_check",
|
||||
"messenger_identities",
|
||||
"messenger_unlink"
|
||||
],
|
||||
"config": {
|
||||
"time-zone": {
|
||||
"type": "string",
|
||||
"description": "The time zone every time a message says is said in, an IANA name such as Europe/Brussels; empty is this machine's own zone.",
|
||||
"trusted": true,
|
||||
"default": ""
|
||||
},
|
||||
"desktop-machines": {
|
||||
"type": "list",
|
||||
"description": "The machines whose desktop showed the operator's messages, by node name. Nothing in this module reads it since the desk channel took the desktop over; it is taken so the file stays as a layer that still sets it makes it, until that layer drops it.",
|
||||
"trusted": true,
|
||||
"default": []
|
||||
},
|
||||
"only-what-needs-me": {
|
||||
"type": "list",
|
||||
"description": "The kinds of channel set to say only what needs the operator: a walk that delivered with nothing held and nothing open is not told there (ADR 0308 §4); empty is none.",
|
||||
"trusted": true,
|
||||
"default": []
|
||||
}
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"id": "account",
|
||||
"type": "user",
|
||||
"name": "messenger",
|
||||
"shell": "/usr/bin/nologin",
|
||||
"home": "/var/lib/messenger"
|
||||
},
|
||||
{
|
||||
"id": "state",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"place": ".",
|
||||
"owner": "messenger",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "settings",
|
||||
"type": "file",
|
||||
"path": "${dir:state}/settings.json",
|
||||
"mode": "0600",
|
||||
"takes-config": ["time-zone", "desktop-machines", "only-what-needs-me"],
|
||||
"merge": "json",
|
||||
"template": "files/settings.json",
|
||||
"owner": "messenger"
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "tools",
|
||||
"kind": "bundle",
|
||||
"language": "go",
|
||||
"system": "arch",
|
||||
"from": "cmd/messenger",
|
||||
"binary": "messenger",
|
||||
"loads": [
|
||||
"messenger"
|
||||
],
|
||||
"env": {
|
||||
"MESH_MESSENGER_SETTINGS": "${dir:state}/settings.json",
|
||||
"MESH_MESSENGER_STATE": "${dir:state}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "files",
|
||||
"kind": "archive",
|
||||
"from": "files"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,188 @@
|
||||
{
|
||||
"module": "minio",
|
||||
"version": "1",
|
||||
"upgrade": {
|
||||
"policy": "record",
|
||||
"why": "holds the photos themselves (irreplaceable, kept by photos) for its consumers: a person takes each build, after a backup (hq ADR 0236)"
|
||||
},
|
||||
"provides": [
|
||||
{
|
||||
"name": "s3-bucket",
|
||||
"scope": "mesh",
|
||||
"identity": {
|
||||
"max": 20,
|
||||
"in": "an S3 access key"
|
||||
}
|
||||
}
|
||||
],
|
||||
"requires": [
|
||||
"route"
|
||||
],
|
||||
"contributes": {
|
||||
"route": {
|
||||
"api": {
|
||||
"label": "files-api",
|
||||
"endpoint": "s3"
|
||||
},
|
||||
"console": {
|
||||
"label": "files",
|
||||
"endpoint": "console"
|
||||
}
|
||||
}
|
||||
},
|
||||
"capabilities": [
|
||||
"container-runtime"
|
||||
],
|
||||
"emits": [
|
||||
"bucket.created",
|
||||
"bucket.removed"
|
||||
],
|
||||
"listens": [
|
||||
{
|
||||
"name": "s3",
|
||||
"port": 9000,
|
||||
"protocol": "tcp",
|
||||
"from": "mesh",
|
||||
"why": "the S3 endpoint"
|
||||
},
|
||||
{
|
||||
"name": "console",
|
||||
"port": 9001,
|
||||
"protocol": "tcp",
|
||||
"from": "mesh",
|
||||
"why": "the admin console"
|
||||
}
|
||||
],
|
||||
"serves": {
|
||||
"s3-bucket": {
|
||||
"scheme": "http",
|
||||
"region": "eu-west",
|
||||
"port": 9000,
|
||||
"bucket": "${consumer:as:dns}"
|
||||
}
|
||||
},
|
||||
"receives": {
|
||||
"s3-bucket": "${dir:grants}/mesh.json"
|
||||
},
|
||||
"grants": {
|
||||
"s3-bucket": "${dir:grants}"
|
||||
},
|
||||
"own-secrets": {
|
||||
"root": "${dir:state}/root.secret"
|
||||
},
|
||||
"data": {
|
||||
"own": [
|
||||
{
|
||||
"id": "data",
|
||||
"path": "${dir:data}",
|
||||
"class": "valuable",
|
||||
"why": "every consumer's bucket and its objects"
|
||||
}
|
||||
],
|
||||
"consumers": {
|
||||
"s3-bucket": {
|
||||
"class": "valuable",
|
||||
"in": "data",
|
||||
"why": "a consumer's objects are the only copy of what it stored; a consumer that keeps something irreplaceable here says so (kept-by)"
|
||||
}
|
||||
}
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"id": "state",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"place": ".",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "grants",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "root-env",
|
||||
"type": "file",
|
||||
"path": "${dir:state}/root.env",
|
||||
"mode": "0600",
|
||||
"template": "files/root.env"
|
||||
},
|
||||
{
|
||||
"id": "data",
|
||||
"type": "directory",
|
||||
"path": "/var/lib/minio-store",
|
||||
"mode": "0700",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "net",
|
||||
"type": "network",
|
||||
"name": "minio-net"
|
||||
},
|
||||
{
|
||||
"id": "server",
|
||||
"type": "container",
|
||||
"name": "minio",
|
||||
"image": "docker.io/pgsty/minio@sha256:b6bfe7239bfc83fb90d31612d9704d86039dd714f7904b3f1ad68f211e602372",
|
||||
"network": "minio-net",
|
||||
"args": [
|
||||
"server",
|
||||
"/data",
|
||||
"--console-address",
|
||||
":9001"
|
||||
],
|
||||
"env-file": [
|
||||
"${dir:state}/root.env"
|
||||
],
|
||||
"ports": [
|
||||
"9000",
|
||||
"9001"
|
||||
],
|
||||
"volumes": [
|
||||
"/var/lib/minio-store:/data",
|
||||
"${dir:state}/root.secret:/run/secrets/root:ro"
|
||||
],
|
||||
"env": {
|
||||
"MINIO_ROOT_PASSWORD_FILE": "/run/secrets/root",
|
||||
"MINIO_REGION": "eu-west"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "client",
|
||||
"type": "package",
|
||||
"package": "minio-client"
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "code",
|
||||
"kind": "bundle",
|
||||
"language": "typescript",
|
||||
"entrypoints": [
|
||||
"tools/index.js",
|
||||
"provisioner/index.js"
|
||||
],
|
||||
"loads": [
|
||||
"tools/index.js",
|
||||
"provisioner/index.js"
|
||||
],
|
||||
"env": {
|
||||
"MESH_MINIO_ENDPOINT": "http://127.0.0.1:${port:9000}",
|
||||
"MESH_MINIO_ROOT_USER": "meshroot",
|
||||
"MESH_MINIO_ROOT_PASSWORD_FILE": "${dir:state}/root.secret",
|
||||
"MESH_MINIO_REGION": "eu-west",
|
||||
"MESH_MINIO_MC_BIN": "mcli",
|
||||
"MESH_MINIO_MC_CONFIG": "${dir:state}/mc",
|
||||
"MESH_RECEIVES": "${dir:grants}/mesh.json"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "files",
|
||||
"kind": "archive",
|
||||
"from": "files"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
{
|
||||
"module": "model-usage",
|
||||
"version": "1",
|
||||
"slug": "usage",
|
||||
"capabilities": [
|
||||
"container-runtime"
|
||||
],
|
||||
"requires": [
|
||||
"postgres-database"
|
||||
],
|
||||
"contributes": {
|
||||
"postgres-database": {
|
||||
"name": "model_usage"
|
||||
}
|
||||
},
|
||||
"binds": {
|
||||
"postgres-database": "${dir:state}/database.json"
|
||||
},
|
||||
"secrets": {
|
||||
"postgres-database": "${dir:state}/database.secret"
|
||||
},
|
||||
"consumes": [
|
||||
"*.usage.*"
|
||||
],
|
||||
"data": {
|
||||
"own": [
|
||||
{
|
||||
"id": "state",
|
||||
"path": "${dir:state}",
|
||||
"class": "cache",
|
||||
"why": "the mesh's own files for it; its records are in its database"
|
||||
},
|
||||
{
|
||||
"id": "spool",
|
||||
"path": "${dir:spool}",
|
||||
"class": "valuable",
|
||||
"why": "usage events the store could not take yet; after the bus gives one up, the only copy"
|
||||
}
|
||||
]
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"id": "state",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"place": ".",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "database-url",
|
||||
"type": "file",
|
||||
"path": "${dir:state}/database.url",
|
||||
"mode": "0600",
|
||||
"template": "files/database.url"
|
||||
},
|
||||
{
|
||||
"id": "spool",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "prepare",
|
||||
"type": "process",
|
||||
"name": "model-usage-prepare",
|
||||
"artifact": "code",
|
||||
"run": [
|
||||
"node",
|
||||
"prepare/index.js"
|
||||
],
|
||||
"run-once": true,
|
||||
"env": {
|
||||
"DATABASE_URL_FILE": "${dir:state}/database.url"
|
||||
},
|
||||
"restart-on": [
|
||||
"database-url"
|
||||
]
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "code",
|
||||
"kind": "bundle",
|
||||
"language": "typescript",
|
||||
"entrypoints": [
|
||||
"index.js",
|
||||
"tools/index.js",
|
||||
"prepare/index.js"
|
||||
],
|
||||
"loads": [
|
||||
"index.js",
|
||||
"tools/index.js"
|
||||
],
|
||||
"env": {
|
||||
"DATABASE_URL_FILE": "${dir:state}/database.url",
|
||||
"USAGE_SPOOL": "${dir:spool}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "files",
|
||||
"kind": "archive",
|
||||
"from": "files"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
{
|
||||
"module": "mongodb",
|
||||
"version": "1",
|
||||
"upgrade": {
|
||||
"policy": "record",
|
||||
"why": "a provider whose restart drops every consumer on its machine, and which holds the photos' albums (irreplaceable, kept by photos): a person takes each build, after a backup (hq ADR 0236)"
|
||||
},
|
||||
"provides": [
|
||||
{
|
||||
"name": "mongodb-database",
|
||||
"scope": "mesh",
|
||||
"identity": {
|
||||
"max": 63,
|
||||
"in": "a MongoDB database name"
|
||||
}
|
||||
}
|
||||
],
|
||||
"capabilities": [
|
||||
"container-runtime"
|
||||
],
|
||||
"emits": [
|
||||
"database.provisioned",
|
||||
"database.deprovisioned"
|
||||
],
|
||||
"consumes": [
|
||||
"mongodb.database.provisioned",
|
||||
"mongodb.database.deprovisioned"
|
||||
],
|
||||
"listens": [
|
||||
{
|
||||
"name": "database",
|
||||
"port": 27017,
|
||||
"protocol": "tcp",
|
||||
"from": "mesh",
|
||||
"why": "modules on any machine that were granted a database"
|
||||
}
|
||||
],
|
||||
"serves": {
|
||||
"mongodb-database": {
|
||||
"port": 27017
|
||||
}
|
||||
},
|
||||
"receives": {
|
||||
"mongodb-database": "${dir:grants}/mesh.json"
|
||||
},
|
||||
"grants": {
|
||||
"mongodb-database": "${dir:grants}"
|
||||
},
|
||||
"own-secrets": {
|
||||
"root": "${dir:state}/root.secret"
|
||||
},
|
||||
"data": {
|
||||
"own": [
|
||||
{
|
||||
"id": "data",
|
||||
"path": "${dir:data}",
|
||||
"class": "valuable",
|
||||
"backup": {
|
||||
"dump": "docker exec mongodb-server sh -c 'printf \"password: %s\\n\" \"$(cat /run/secrets/root)\" > /tmp/.backup.yaml && mongodump --quiet --config /tmp/.backup.yaml --username root --authenticationDatabase admin --archive; s=$?; rm -f /tmp/.backup.yaml; exit $s' > ${dir:dumps}/all.archive.partial && mv ${dir:dumps}/all.archive.partial ${dir:dumps}/all.archive",
|
||||
"into": "dumps"
|
||||
},
|
||||
"why": "every consumer's database; copied by the dump, not as live files"
|
||||
},
|
||||
{
|
||||
"id": "dumps",
|
||||
"path": "${dir:dumps}",
|
||||
"class": "rebuildable",
|
||||
"why": "last night's dump, made again every night"
|
||||
}
|
||||
],
|
||||
"consumers": {
|
||||
"mongodb-database": {
|
||||
"class": "valuable",
|
||||
"in": "data",
|
||||
"why": "a consumer's documents are the only copy of what it wrote; a consumer that keeps something irreplaceable here says so (kept-by)"
|
||||
}
|
||||
}
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"id": "state",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"place": ".",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "grants",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "data",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "dumps",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "net",
|
||||
"type": "network",
|
||||
"name": "mongodb"
|
||||
},
|
||||
{
|
||||
"id": "server-root",
|
||||
"type": "file",
|
||||
"path": "${dir:state}/server-root.secret",
|
||||
"mode": "0400",
|
||||
"owner": "999:999",
|
||||
"template": "files/server-root.secret"
|
||||
},
|
||||
{
|
||||
"id": "server",
|
||||
"type": "container",
|
||||
"name": "mongodb-server",
|
||||
"image": "mongo@sha256:e3fa459b4f4b72f3257c67a23c145e250b8b5700f033860392c68539b998bbe3",
|
||||
"health": {
|
||||
"kind": "tcp",
|
||||
"endpoint": "database"
|
||||
},
|
||||
"network": "mongodb",
|
||||
"env": {
|
||||
"MONGO_INITDB_ROOT_USERNAME": "root",
|
||||
"MONGO_INITDB_ROOT_PASSWORD_FILE": "/run/secrets/root"
|
||||
},
|
||||
"ports": [
|
||||
"27017"
|
||||
],
|
||||
"volumes": [
|
||||
"${dir:data}:/data/db",
|
||||
"${dir:state}/server-root.secret:/run/secrets/root:ro"
|
||||
]
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "code",
|
||||
"kind": "bundle",
|
||||
"language": "typescript",
|
||||
"entrypoints": [
|
||||
"index.js",
|
||||
"tools/index.js",
|
||||
"provisioner/index.js"
|
||||
],
|
||||
"loads": [
|
||||
"index.js",
|
||||
"tools/index.js",
|
||||
"provisioner/index.js"
|
||||
],
|
||||
"env": {
|
||||
"MESH_PROVISION_MONGODB": "mongodb://root@127.0.0.1:${port:27017}/admin?authSource=admin",
|
||||
"MESH_PROVISION_PASSWORD_FILE": "${dir:state}/root.secret",
|
||||
"MESH_RECEIVES": "${dir:grants}/mesh.json"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "files",
|
||||
"kind": "archive",
|
||||
"from": "files"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,194 @@
|
||||
{
|
||||
"module": "mosquitto",
|
||||
"version": "1",
|
||||
"slug": "mosq",
|
||||
"provides": [
|
||||
{
|
||||
"name": "mqtt-topic",
|
||||
"scope": "mesh",
|
||||
"identity": {
|
||||
"in": "a Mosquitto client and topic prefix"
|
||||
}
|
||||
}
|
||||
],
|
||||
"capabilities": [
|
||||
"container-runtime"
|
||||
],
|
||||
"emits": [
|
||||
"topic.provisioned",
|
||||
"topic.deprovisioned"
|
||||
],
|
||||
"consumes": [
|
||||
"mosquitto.topic.provisioned",
|
||||
"mosquitto.topic.deprovisioned"
|
||||
],
|
||||
"serves": {
|
||||
"mqtt-topic": {
|
||||
"scheme": "mqtt",
|
||||
"port": 1883
|
||||
}
|
||||
},
|
||||
"receives": {
|
||||
"mqtt-topic": "${dir:grants}/mesh.json"
|
||||
},
|
||||
"grants": {
|
||||
"mqtt-topic": "${dir:grants}"
|
||||
},
|
||||
"own-secrets": {
|
||||
"admin": {
|
||||
"path": "${dir:mesh-state}/admin",
|
||||
"taken": "at-start"
|
||||
}
|
||||
},
|
||||
"listens": [
|
||||
{
|
||||
"name": "mqtt",
|
||||
"port": 1883,
|
||||
"protocol": "tcp",
|
||||
"from": "mesh",
|
||||
"why": "modules on any machine that were granted a topic namespace"
|
||||
},
|
||||
{
|
||||
"name": "mqtt-websockets",
|
||||
"port": 8081,
|
||||
"protocol": "tcp",
|
||||
"from": "mesh",
|
||||
"why": "the same broker over MQTT-on-WebSockets, for browser clients"
|
||||
}
|
||||
],
|
||||
"data": {
|
||||
"own": [
|
||||
{
|
||||
"id": "data",
|
||||
"path": "${dir:data}",
|
||||
"class": "rebuildable",
|
||||
"why": "retained messages and sessions; devices publish them again"
|
||||
}
|
||||
],
|
||||
"consumers": {
|
||||
"mqtt-topic": {
|
||||
"class": "rebuildable",
|
||||
"in": "data",
|
||||
"why": "retained messages are published again by the devices"
|
||||
}
|
||||
}
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"id": "mesh-state",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"place": "mesh",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "state",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"place": ".",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "grants",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "data",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"owner": "1883:1883",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "server-conf",
|
||||
"type": "file",
|
||||
"path": "${dir:state}/mosquitto.conf",
|
||||
"mode": "0600",
|
||||
"owner": "1883:1883",
|
||||
"template": "files/mosquitto.conf"
|
||||
},
|
||||
{
|
||||
"id": "net",
|
||||
"type": "network",
|
||||
"name": "mosquitto"
|
||||
},
|
||||
{
|
||||
"id": "bootstrap-env",
|
||||
"type": "file",
|
||||
"path": "${dir:state}/bootstrap.env",
|
||||
"mode": "0600",
|
||||
"template": "files/bootstrap.env"
|
||||
},
|
||||
{
|
||||
"id": "bootstrap",
|
||||
"type": "process",
|
||||
"name": "mosquitto-bootstrap",
|
||||
"artifact": "code",
|
||||
"run": [
|
||||
"node",
|
||||
"bootstrap/index.js"
|
||||
],
|
||||
"run-once": true,
|
||||
"env-file": [
|
||||
"${dir:state}/bootstrap.env"
|
||||
],
|
||||
"restart-on": [
|
||||
"bootstrap-env",
|
||||
"needs-admin"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "server",
|
||||
"type": "container",
|
||||
"name": "mosquitto",
|
||||
"image": "eclipse-mosquitto@sha256:38c0da4f2ef84284d47b3b3eeea1cb3bdeabe81ee10caf0cd5c5ff61ee3ea408",
|
||||
"health": {
|
||||
"kind": "tcp",
|
||||
"endpoint": "mqtt"
|
||||
},
|
||||
"network": "mosquitto",
|
||||
"ports": [
|
||||
"1883",
|
||||
"8081"
|
||||
],
|
||||
"volumes": [
|
||||
"${dir:data}:/mosquitto/data",
|
||||
"${dir:state}/mosquitto.conf:/mosquitto/config/mosquitto.conf:ro"
|
||||
]
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "code",
|
||||
"kind": "bundle",
|
||||
"language": "typescript",
|
||||
"entrypoints": [
|
||||
"index.js",
|
||||
"tools/index.js",
|
||||
"provisioner/index.js",
|
||||
"bootstrap/index.js"
|
||||
],
|
||||
"loads": [
|
||||
"index.js",
|
||||
"tools/index.js",
|
||||
"provisioner/index.js"
|
||||
],
|
||||
"env": {
|
||||
"MESH_RECEIVES": "${dir:grants}/mesh.json",
|
||||
"MESH_PROVISION_MQTT": "127.0.0.1:${port:1883}",
|
||||
"MESH_PROVISION_ADMIN_USER": "mesh-admin",
|
||||
"MESH_PROVISION_PASSWORD_FILE": "${dir:mesh-state}/admin",
|
||||
"MESH_MQTT_CTRL_CONTAINER": "mosquitto"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "files",
|
||||
"kind": "archive",
|
||||
"from": "files"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
{
|
||||
"module": "mounts",
|
||||
"version": "1",
|
||||
"requires": [
|
||||
"nfs-share"
|
||||
],
|
||||
"reads": [
|
||||
"nfs-server.exports"
|
||||
],
|
||||
"invokes": [
|
||||
"seat:mesh-controller.data"
|
||||
],
|
||||
"capabilities": [
|
||||
"package-manager",
|
||||
"service-manager"
|
||||
],
|
||||
"claims": [
|
||||
{
|
||||
"name": "node-mounts",
|
||||
"scope": "node",
|
||||
"serves": [
|
||||
"list",
|
||||
"test",
|
||||
"mount",
|
||||
"unmount",
|
||||
"adopt"
|
||||
]
|
||||
}
|
||||
],
|
||||
"tools": [
|
||||
"mounts_list",
|
||||
"mounts_exports",
|
||||
"mounts_health"
|
||||
],
|
||||
"state": [
|
||||
{
|
||||
"name": "shares",
|
||||
"per-machine": true
|
||||
}
|
||||
],
|
||||
"config": {
|
||||
"shares": {
|
||||
"type": "string",
|
||||
"description": "The shares of another machine this machine mounts: space-separated name=mountpoint, each optionally :ro, or none (novox/hq ADR 0263 rule 5).",
|
||||
"trusted": true,
|
||||
"default": "none"
|
||||
},
|
||||
"sources": {
|
||||
"type": "string",
|
||||
"description": "The occasional sources this machine mounts: space-separated name=smb://[<user>@]<host>/<share>@<mountpoint> or name=disk:<uuid>@<mountpoint>, each optionally :ro, or none (novox/hq ADR 0263 rule 6); an SMB source's username is in its entry, its password the secret smb-password-<name> (novox/hq ADR 0283).",
|
||||
"trusted": true,
|
||||
"default": "none"
|
||||
}
|
||||
},
|
||||
"own-secrets": {
|
||||
"smb-password-*": {
|
||||
"path": "${dir:state}/smb-password-*.secret",
|
||||
"issued-by": "outside"
|
||||
}
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"id": "nfs-utils",
|
||||
"type": "package",
|
||||
"package": "nfs-utils"
|
||||
},
|
||||
{
|
||||
"id": "cifs-utils",
|
||||
"type": "package",
|
||||
"package": "cifs-utils"
|
||||
},
|
||||
{
|
||||
"id": "state",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"place": ".",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "config-dir",
|
||||
"type": "directory",
|
||||
"path": "/etc/mesh-mounts",
|
||||
"mode": "0755",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "config",
|
||||
"type": "file",
|
||||
"path": "/etc/mesh-mounts/mounts.conf",
|
||||
"mode": "0644",
|
||||
"template": "files/mounts.conf"
|
||||
},
|
||||
{
|
||||
"id": "bus-dir-parent",
|
||||
"type": "directory",
|
||||
"path": "/var/lib/mesh-mounts",
|
||||
"mode": "0755",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "bus-dir",
|
||||
"type": "directory",
|
||||
"path": "/var/lib/mesh-mounts/from-bus",
|
||||
"mode": "0755",
|
||||
"owner": "${machine:account}",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "apply",
|
||||
"type": "process",
|
||||
"name": "mesh-mounts-apply",
|
||||
"artifact": "tools-go",
|
||||
"run": [
|
||||
"./mounts",
|
||||
"apply"
|
||||
],
|
||||
"health": {
|
||||
"kind": "unit"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "watch",
|
||||
"type": "process",
|
||||
"name": "mesh-mounts-watch",
|
||||
"artifact": "tools-go",
|
||||
"run": [
|
||||
"./mounts",
|
||||
"watch"
|
||||
],
|
||||
"health": {
|
||||
"kind": "tool",
|
||||
"tool": "mounts_health",
|
||||
"interval": "60s",
|
||||
"timeout": "10s",
|
||||
"looks": 2,
|
||||
"grace": "90s"
|
||||
}
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "tools-go",
|
||||
"kind": "bundle",
|
||||
"language": "go",
|
||||
"system": "arch",
|
||||
"from": "cmd/mounts",
|
||||
"binary": "mounts",
|
||||
"loads": [
|
||||
"mounts"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "files",
|
||||
"kind": "archive",
|
||||
"from": "files"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,174 @@
|
||||
{
|
||||
"module": "mssql",
|
||||
"version": "1",
|
||||
"upgrade": {
|
||||
"policy": "record",
|
||||
"why": "a provider whose restart drops every consumer on its machine, and whose new version may upgrade its databases in place: a person takes each build, after a backup (hq ADR 0236)"
|
||||
},
|
||||
"provides": [
|
||||
{
|
||||
"name": "mssql-database",
|
||||
"scope": "mesh",
|
||||
"identity": {
|
||||
"max": 128,
|
||||
"in": "a SQL Server login and database name"
|
||||
}
|
||||
}
|
||||
],
|
||||
"capabilities": [
|
||||
"container-runtime"
|
||||
],
|
||||
"emits": [
|
||||
"database.provisioned",
|
||||
"database.deprovisioned"
|
||||
],
|
||||
"consumes": [
|
||||
"mssql.database.provisioned",
|
||||
"mssql.database.deprovisioned"
|
||||
],
|
||||
"listens": [
|
||||
{
|
||||
"name": "database",
|
||||
"port": 1433,
|
||||
"protocol": "tcp",
|
||||
"from": "mesh",
|
||||
"why": "modules on any machine that were granted a database, and the people who were given its address; the machine port is the assignment's to pin"
|
||||
}
|
||||
],
|
||||
"serves": {
|
||||
"mssql-database": {}
|
||||
},
|
||||
"receives": {
|
||||
"mssql-database": "${dir:grants}/mesh.json"
|
||||
},
|
||||
"grants": {
|
||||
"mssql-database": "${dir:grants}"
|
||||
},
|
||||
"own-secrets": {
|
||||
"sa": "${dir:state}/sa.secret",
|
||||
"reader": "${dir:state}/reader.secret"
|
||||
},
|
||||
"data": {
|
||||
"own": [
|
||||
{
|
||||
"id": "data",
|
||||
"path": "${dir:data}",
|
||||
"class": "valuable",
|
||||
"backup": {
|
||||
"dump": "{ cat ${dir:state}/sa.secret; echo; cat ${dir:state}/backup.sql; } | docker exec -i mssql sh -c 'read -r p; SQLCMDPASSWORD=\"$p\" exec /opt/mssql-tools18/bin/sqlcmd -C -b -S localhost -U sa -i /dev/stdin'",
|
||||
"into": "dumps"
|
||||
},
|
||||
"why": "every consumer's database; copied by the dump, not as live files"
|
||||
},
|
||||
{
|
||||
"id": "dumps",
|
||||
"path": "${dir:dumps}",
|
||||
"class": "rebuildable",
|
||||
"why": "last night's dump, made again every night"
|
||||
}
|
||||
],
|
||||
"consumers": {
|
||||
"mssql-database": {
|
||||
"class": "valuable",
|
||||
"in": "data",
|
||||
"why": "a consumer's rows are the only copy of what it wrote"
|
||||
}
|
||||
}
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"id": "state",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"place": ".",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "grants",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "sa-env",
|
||||
"type": "file",
|
||||
"path": "${dir:state}/sa.env",
|
||||
"mode": "0600",
|
||||
"template": "files/sa.env"
|
||||
},
|
||||
{
|
||||
"id": "data",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"owner": "10001:0",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "dumps",
|
||||
"type": "directory",
|
||||
"path": "${dir:data}/backup",
|
||||
"mode": "0700",
|
||||
"owner": "10001:0",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "net",
|
||||
"type": "network",
|
||||
"name": "mssql"
|
||||
},
|
||||
{
|
||||
"id": "server",
|
||||
"type": "container",
|
||||
"name": "mssql",
|
||||
"image": "mcr.microsoft.com/mssql/server@sha256:4402d880dd4c34bfa7d8705e56a86cd6c88da80a1f6bbbe741f999e76264a090",
|
||||
"network": "mssql",
|
||||
"env-file": [
|
||||
"${dir:state}/sa.env"
|
||||
],
|
||||
"ports": [
|
||||
"1433"
|
||||
],
|
||||
"volumes": [
|
||||
"${dir:data}:/var/opt/mssql"
|
||||
],
|
||||
"secrets-in-environment": "the image documents only MSSQL_SA_PASSWORD, no _FILE and no configuration field; not convertible without a wrapper entrypoint"
|
||||
},
|
||||
{
|
||||
"id": "backup-sql",
|
||||
"type": "file",
|
||||
"path": "${dir:state}/backup.sql",
|
||||
"mode": "0600",
|
||||
"template": "files/backup.sql"
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "code",
|
||||
"kind": "bundle",
|
||||
"language": "typescript",
|
||||
"entrypoints": [
|
||||
"index.js",
|
||||
"tools/index.js",
|
||||
"provisioner/index.js"
|
||||
],
|
||||
"loads": [
|
||||
"index.js",
|
||||
"tools/index.js",
|
||||
"provisioner/index.js"
|
||||
],
|
||||
"env": {
|
||||
"MESH_PROVISION_MSSQL": "mssql://sa@127.0.0.1:${port:1433}/master",
|
||||
"MESH_PROVISION_PASSWORD_FILE": "${dir:state}/sa.secret",
|
||||
"MESH_RECEIVES": "${dir:grants}/mesh.json",
|
||||
"MESH_MSSQL_READER_PASSWORD_FILE": "${dir:state}/reader.secret"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "files",
|
||||
"kind": "archive",
|
||||
"from": "files"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
{
|
||||
"module": "n8n",
|
||||
"version": "1",
|
||||
"capabilities": [
|
||||
"container-runtime"
|
||||
],
|
||||
"requires": [
|
||||
"postgres-database",
|
||||
"route"
|
||||
],
|
||||
"contributes": {
|
||||
"postgres-database": {
|
||||
"name": "n8n"
|
||||
},
|
||||
"route": {
|
||||
"label": "n8n",
|
||||
"endpoint": "web"
|
||||
}
|
||||
},
|
||||
"binds": {
|
||||
"postgres-database": "${dir:state}/database.json",
|
||||
"route": "${dir:state}/route.json"
|
||||
},
|
||||
"secrets": {
|
||||
"postgres-database": "${dir:state}/database.secret"
|
||||
},
|
||||
"accesses": [
|
||||
{
|
||||
"id": "media",
|
||||
"mode": "read-write"
|
||||
}
|
||||
],
|
||||
"listens": [
|
||||
{
|
||||
"name": "web",
|
||||
"port": 5678,
|
||||
"protocol": "tcp",
|
||||
"from": "mesh",
|
||||
"why": "the n8n editor, its REST API and the webhook endpoints workflows are triggered through; a public name is the route's"
|
||||
}
|
||||
],
|
||||
"data": {
|
||||
"own": [
|
||||
{
|
||||
"id": "data",
|
||||
"path": "${dir:data}",
|
||||
"class": "valuable",
|
||||
"why": "the instance's encryption key, settings and binary data; workflows are in the database"
|
||||
},
|
||||
{
|
||||
"id": "cache",
|
||||
"path": "${dir:cache}",
|
||||
"class": "cache",
|
||||
"why": "scratch space"
|
||||
}
|
||||
]
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"id": "state",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"place": ".",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "data",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"owner": "1000:1000",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "cache",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"owner": "999:999",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "database-secret",
|
||||
"type": "file",
|
||||
"path": "${dir:state}/n8n-database.secret",
|
||||
"mode": "0400",
|
||||
"owner": "1000:1000",
|
||||
"template": "files/n8n-database.secret"
|
||||
},
|
||||
{
|
||||
"id": "server-env",
|
||||
"type": "file",
|
||||
"path": "${dir:state}/server.env",
|
||||
"mode": "0600",
|
||||
"template": "files/server.env"
|
||||
},
|
||||
{
|
||||
"id": "net",
|
||||
"type": "network",
|
||||
"name": "n8n"
|
||||
},
|
||||
{
|
||||
"id": "server",
|
||||
"type": "container",
|
||||
"health": {
|
||||
"kind": "http",
|
||||
"endpoint": "web",
|
||||
"path": "/healthz/readiness",
|
||||
"status": 200,
|
||||
"needs": "postgres-database"
|
||||
},
|
||||
"name": "n8n",
|
||||
"artifact": "server",
|
||||
"network": "n8n",
|
||||
"env-file": [
|
||||
"${dir:state}/server.env"
|
||||
],
|
||||
"ports": [
|
||||
"5678"
|
||||
],
|
||||
"volumes": [
|
||||
"${dir:data}:/home/node/.n8n",
|
||||
"${dir:state}/n8n-database.secret:/run/secrets/database:ro",
|
||||
"${access:media}:/media-library"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "cache-server",
|
||||
"type": "container",
|
||||
"name": "n8n-redis",
|
||||
"image": "redis@sha256:8a1efc5f479551822b47424ccae982026b633f28818eab0387348120a61e10e2",
|
||||
"network": "n8n",
|
||||
"args": [
|
||||
"redis-server",
|
||||
"--appendonly",
|
||||
"yes"
|
||||
],
|
||||
"volumes": [
|
||||
"${dir:cache}:/data"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "browser",
|
||||
"type": "container",
|
||||
"name": "n8n-selenium",
|
||||
"image": "selenium/standalone-chrome@sha256:9ae1c78e9b2ca9fe4b22e57873b5ee34aeb8e814e3122293eef4c3abe4c5f448",
|
||||
"network": "n8n",
|
||||
"env": {
|
||||
"SE_ENABLE_TRACING": "false",
|
||||
"SE_NODE_MAX_SESSIONS": "5",
|
||||
"SE_NODE_OVERRIDE_MAX_SESSIONS": "true"
|
||||
}
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"on": [
|
||||
{
|
||||
"arg": "N8N_BASE",
|
||||
"image": "n8nio/n8n@sha256:4846eb2f4b874ab04cde7fc1e249d2ddaec66e9aea64439beb2972cfea88e3c0"
|
||||
}
|
||||
],
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "server",
|
||||
"kind": "image",
|
||||
"from": "Dockerfile"
|
||||
},
|
||||
{
|
||||
"name": "files",
|
||||
"kind": "archive",
|
||||
"from": "files"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,171 @@
|
||||
{
|
||||
"module": "nats",
|
||||
"version": "1",
|
||||
"upgrade": {
|
||||
"policy": "record",
|
||||
"why": "the bus: replaced only as a planned step a person starts (`bus upgrade`), its streams snapshotted first and checked after (hq ADR 0236); the controller holds this whatever is said here"
|
||||
},
|
||||
"provides": [
|
||||
{
|
||||
"name": "mesh-bus",
|
||||
"scope": "mesh"
|
||||
}
|
||||
],
|
||||
"claims": [
|
||||
{
|
||||
"name": "mesh-broker",
|
||||
"scope": "mesh"
|
||||
}
|
||||
],
|
||||
"bus-users": "/var/lib/nats-module/conf/accounts.conf",
|
||||
"own-secrets": {
|
||||
"broker": "${dir:mesh-state}/broker"
|
||||
},
|
||||
"capabilities": [
|
||||
"container-runtime"
|
||||
],
|
||||
"emits": [],
|
||||
"consumes": [],
|
||||
"listens": [
|
||||
{
|
||||
"name": "bus",
|
||||
"port": 4222,
|
||||
"protocol": "tcp",
|
||||
"from": "mesh",
|
||||
"why": "the mesh bus — every link the mesh has, over TLS, reached across the overlay"
|
||||
}
|
||||
],
|
||||
"tools": [
|
||||
"nats_server",
|
||||
"nats_connections",
|
||||
"nats_closed_connections",
|
||||
"nats_subscriptions",
|
||||
"nats_streams",
|
||||
"nats_backlog",
|
||||
"nats_buckets",
|
||||
"nats_users",
|
||||
"nats_user_can"
|
||||
],
|
||||
"guards": [
|
||||
8222
|
||||
],
|
||||
"data": {
|
||||
"own": [
|
||||
{
|
||||
"id": "jetstream",
|
||||
"path": "${dir:jetstream-data}",
|
||||
"class": "valuable",
|
||||
"active": "1d",
|
||||
"backup": {
|
||||
"dump": "docker exec -i mesh-broker-nats mesh-nats-snapshot snapshot < ${dir:mesh-state}/broker > ${dir:snapshots}/bus.tar.partial && mv ${dir:snapshots}/bus.tar.partial ${dir:snapshots}/bus.tar || { rm -f ${dir:snapshots}/bus.tar.partial; exit 1; }",
|
||||
"into": "snapshots"
|
||||
},
|
||||
"why": "the bus's streams and key-value buckets: the hand-act log, conditions, every module's state; written all the time, so copied by the server's own snapshot of each stream (novox/hq ADR 0235), never as live files"
|
||||
},
|
||||
{
|
||||
"id": "snapshots",
|
||||
"path": "${dir:snapshots}",
|
||||
"class": "rebuildable",
|
||||
"why": "last night's snapshot of every stream with its manifest, made again every night"
|
||||
}
|
||||
]
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"id": "jetstream-data",
|
||||
"type": "directory",
|
||||
"path": "/var/lib/mesh-broker-nats",
|
||||
"mode": "0700",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "conf-dir",
|
||||
"type": "directory",
|
||||
"path": "/var/lib/nats-module/conf",
|
||||
"mode": "0700",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "snapshots",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "mesh-state",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"place": "mesh",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "server-conf",
|
||||
"type": "file",
|
||||
"path": "/var/lib/nats-module/conf/nats.conf",
|
||||
"template": "files/nats.conf",
|
||||
"mode": "0644"
|
||||
},
|
||||
{
|
||||
"id": "server",
|
||||
"type": "container",
|
||||
"name": "mesh-broker-nats",
|
||||
"ports": [
|
||||
"4222:4222",
|
||||
"127.0.0.1:8222:8222"
|
||||
],
|
||||
"volumes": [
|
||||
"/var/lib/mesh-broker-nats:/data",
|
||||
"/var/lib/nats-module/conf:/etc/nats:ro",
|
||||
"${access:tls}:/tls:ro"
|
||||
],
|
||||
"artifact": "server"
|
||||
}
|
||||
],
|
||||
"accesses": [
|
||||
{
|
||||
"id": "tls",
|
||||
"path": "/var/lib/mesh-broker-tls",
|
||||
"mode": "read"
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"on": [
|
||||
{
|
||||
"arg": "NATS_BASE",
|
||||
"image": "nats@sha256:e4bf19f15fd3218814a4e3c9e0064e1334bd8aa20d5984b9f1a0afd084f8cc00"
|
||||
},
|
||||
{
|
||||
"arg": "GO_BASE",
|
||||
"image": "golang@sha256:8ac98ca534ac3f51e1f420a1dd2c15e74c75cfa0f23f3ad27eb5d7236c349a0c"
|
||||
}
|
||||
],
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "server",
|
||||
"kind": "image",
|
||||
"from": "Dockerfile"
|
||||
},
|
||||
{
|
||||
"name": "tools",
|
||||
"kind": "bundle",
|
||||
"language": "go",
|
||||
"system": "arch",
|
||||
"from": "cmd/nats-tools",
|
||||
"binary": "nats-tools",
|
||||
"loads": [
|
||||
"nats-tools"
|
||||
],
|
||||
"env": {
|
||||
"MESH_NATS_MONITOR": "http://127.0.0.1:8222",
|
||||
"MESH_NATS_CONTAINER": "mesh-broker-nats",
|
||||
"MESH_NATS_USERS_FILE": "/etc/nats/accounts.conf"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "files",
|
||||
"kind": "archive",
|
||||
"from": "files"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
{
|
||||
"module": "netcheck",
|
||||
"version": "1",
|
||||
"emits": [
|
||||
"tunnel.endpoint-changed",
|
||||
"tunnel.handshake-stale",
|
||||
"tunnel.handshake-fresh"
|
||||
],
|
||||
"tools": [
|
||||
"netcheck_tunnel",
|
||||
"netcheck_tcp",
|
||||
"netcheck_dns",
|
||||
"netcheck_http",
|
||||
"netcheck_listening"
|
||||
],
|
||||
"replaces": {
|
||||
"netcheck_listening": [
|
||||
"ss -lunt",
|
||||
"ss -ltn",
|
||||
"netstat -lnt"
|
||||
],
|
||||
"netcheck_dns": [
|
||||
"dig",
|
||||
"nslookup"
|
||||
],
|
||||
"netcheck_tunnel": [
|
||||
"wg show",
|
||||
"wg show mesh0 dump"
|
||||
]
|
||||
},
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "tools-go",
|
||||
"kind": "bundle",
|
||||
"language": "go",
|
||||
"system": "arch",
|
||||
"from": "cmd/netcheck",
|
||||
"binary": "netcheck",
|
||||
"loads": [
|
||||
"netcheck"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "tools-typescript",
|
||||
"kind": "bundle",
|
||||
"language": "typescript",
|
||||
"entrypoints": [
|
||||
"tools/index.js"
|
||||
],
|
||||
"loads": [
|
||||
"tools/index.js"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
{
|
||||
"module": "networkmanager",
|
||||
"version": "1",
|
||||
"upgrade": {
|
||||
"policy": "record",
|
||||
"why": "the machine's network: a build that breaks it can cut the machine off from the bus, and then neither the gate's rollback nor a push reaches it (hq ADR 0236)"
|
||||
},
|
||||
"slug": "nm",
|
||||
"requires": [
|
||||
"wildcard-resolution"
|
||||
],
|
||||
"capabilities": [
|
||||
"package-manager",
|
||||
"service-manager",
|
||||
"uplink-networkmanager"
|
||||
],
|
||||
"claims": [
|
||||
{
|
||||
"name": "node-uplink",
|
||||
"scope": "node"
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "tools",
|
||||
"kind": "bundle",
|
||||
"language": "go",
|
||||
"system": "arch",
|
||||
"from": "cmd/uplink-tools",
|
||||
"binary": "uplink-tools",
|
||||
"loads": [
|
||||
"uplink-tools"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "files",
|
||||
"kind": "archive",
|
||||
"from": "files"
|
||||
}
|
||||
]
|
||||
},
|
||||
"facts": {
|
||||
"resolvers": {
|
||||
"path": "/etc/resolv.conf",
|
||||
"template": "# Managed by the mesh, and written by the module holding this machine's uplink:\n# the program that manages the machine's network would otherwise rewrite this\n# file on every change of network, so its holder is the one that writes it\n# (novox/hq ADR 0117, ADR 0223). Replaced on every push; edit nothing here.\n#\n# Every resolver of the mesh, by address, and nothing else (novox/hq ADR 0223) \u2014\n# this machine's own first when it holds one, then the others by name. Each\n# answers the mesh's names from the same roster and forwards every other name, so\n# whichever answers first gives the one answer. There is no public resolver here:\n# a C library that asks every listed server at once and takes the first reply \u2014\n# musl, so every Alpine container \u2014 took a public resolver's \"no such name\" for\n# a mesh name and failed. A machine that reaches none of these has no names until\n# it does. Containers copy these lines from their machine.\n{{range index .Holders \"mesh-dns-resolver\"}}nameserver {{.Address}}\n{{end}}options timeout:1 attempts:2 edns0\n"
|
||||
}
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"id": "package",
|
||||
"type": "package",
|
||||
"package": "networkmanager"
|
||||
},
|
||||
{
|
||||
"id": "config",
|
||||
"type": "file",
|
||||
"path": "/etc/NetworkManager/conf.d/50-mesh.conf",
|
||||
"mode": "0644",
|
||||
"template": "files/50-mesh.conf"
|
||||
},
|
||||
{
|
||||
"id": "service",
|
||||
"type": "service",
|
||||
"unit": "NetworkManager.service",
|
||||
"reload-on": [
|
||||
"config"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"module": "nextcloud-client",
|
||||
"version": "1",
|
||||
"capabilities": [
|
||||
"package-manager"
|
||||
],
|
||||
"requires": [
|
||||
"x11-display"
|
||||
],
|
||||
"tools": [
|
||||
"nextcloud_status",
|
||||
"nextcloud_log",
|
||||
"nextcloud_restart",
|
||||
"nextcloud_check"
|
||||
],
|
||||
"resources": [
|
||||
{
|
||||
"id": "package",
|
||||
"type": "package",
|
||||
"package": "nextcloud-client"
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "tools",
|
||||
"kind": "bundle",
|
||||
"language": "go",
|
||||
"system": "arch",
|
||||
"from": "cmd/nextcloud-client-tools",
|
||||
"binary": "nextcloud-client-tools",
|
||||
"loads": [
|
||||
"nextcloud-client-tools"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,168 @@
|
||||
{
|
||||
"module": "nextcloud",
|
||||
"version": "1",
|
||||
"slug": "ncloud",
|
||||
"requires": [
|
||||
"postgres-database",
|
||||
"s3-bucket",
|
||||
"route"
|
||||
],
|
||||
"contributes": {
|
||||
"postgres-database": {
|
||||
"name": "nextcloud"
|
||||
},
|
||||
"route": {
|
||||
"label": "drive",
|
||||
"endpoint": "web"
|
||||
}
|
||||
},
|
||||
"binds": {
|
||||
"postgres-database": "${dir:state}/database.json",
|
||||
"s3-bucket": "${dir:state}/store.json",
|
||||
"route": "${dir:state}/route.json"
|
||||
},
|
||||
"secrets": {
|
||||
"postgres-database": "${dir:state}/database.secret",
|
||||
"s3-bucket": "${dir:state}/store.secret"
|
||||
},
|
||||
"emits": [
|
||||
"user.created",
|
||||
"share.created"
|
||||
],
|
||||
"own-secrets": {
|
||||
"admin": "${dir:state}/admin.secret"
|
||||
},
|
||||
"capabilities": [
|
||||
"container-runtime"
|
||||
],
|
||||
"listens": [
|
||||
{
|
||||
"name": "web",
|
||||
"port": 80,
|
||||
"protocol": "tcp",
|
||||
"from": "mesh",
|
||||
"why": "files and sync, over http; a public name is a route grant later"
|
||||
}
|
||||
],
|
||||
"data": {
|
||||
"own": [
|
||||
{
|
||||
"id": "html",
|
||||
"path": "${dir:html}",
|
||||
"class": "valuable",
|
||||
"why": "the instance's configuration, its secret and installed apps; the files are in the object store"
|
||||
}
|
||||
]
|
||||
},
|
||||
"config": {
|
||||
"container": {
|
||||
"type": "string",
|
||||
"description": "The name of the container the module's tools run Nextcloud's occ in; empty is nextcloud.",
|
||||
"trusted": true,
|
||||
"default": ""
|
||||
},
|
||||
"url": {
|
||||
"type": "string",
|
||||
"description": "The address the module's tools reach Nextcloud's sharing API at, as a URL; empty is this machine's Nextcloud on its port.",
|
||||
"trusted": true,
|
||||
"default": ""
|
||||
},
|
||||
"user": {
|
||||
"type": "string",
|
||||
"description": "The Nextcloud account the module's tools act as; empty is admin.",
|
||||
"trusted": true,
|
||||
"default": ""
|
||||
}
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"id": "mesh-state",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"place": "mesh",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "state",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"place": ".",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "server-env",
|
||||
"type": "file",
|
||||
"path": "${dir:state}/server.env",
|
||||
"mode": "0600",
|
||||
"template": "files/server.env"
|
||||
},
|
||||
{
|
||||
"id": "html",
|
||||
"type": "directory",
|
||||
"mode": "0750",
|
||||
"owner": "33:33",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "server",
|
||||
"type": "container",
|
||||
"health": {
|
||||
"kind": "http",
|
||||
"endpoint": "web",
|
||||
"path": "/status.php",
|
||||
"status": 200,
|
||||
"body": "\"installed\":true",
|
||||
"needs": "postgres-database"
|
||||
},
|
||||
"name": "nextcloud",
|
||||
"image": "nextcloud@sha256:fb966733647ea03f0446b0c22eac9733c8eb616d37b960caca9d4c3010e14a08",
|
||||
"env-file": [
|
||||
"${dir:state}/server.env"
|
||||
],
|
||||
"ports": [
|
||||
"80"
|
||||
],
|
||||
"volumes": [
|
||||
"${dir:html}:/var/www/html"
|
||||
],
|
||||
"secrets-in-environment": "the image honours POSTGRES_PASSWORD_FILE and NEXTCLOUD_ADMIN_PASSWORD_FILE (entrypoint file_env); OBJECTSTORE_S3_SECRET has none and needs a generated config fragment; convertible, awaiting a bed"
|
||||
},
|
||||
{
|
||||
"id": "runtime-config",
|
||||
"type": "file",
|
||||
"path": "${dir:mesh-state}/config.json",
|
||||
"mode": "0600",
|
||||
"template": "files/config.json",
|
||||
"takes-config": ["container", "url", "user"],
|
||||
"merge": "json"
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "code",
|
||||
"kind": "bundle",
|
||||
"language": "typescript",
|
||||
"entrypoints": [
|
||||
"index.js",
|
||||
"tools/index.js"
|
||||
],
|
||||
"loads": [
|
||||
"index.js",
|
||||
"tools/index.js"
|
||||
],
|
||||
"env": {
|
||||
"MESH_NEXTCLOUD_URL": "http://127.0.0.1:${port:80}",
|
||||
"MESH_NEXTCLOUD_CONFIG_FILE": "${dir:mesh-state}/config.json",
|
||||
"MESH_NEXTCLOUD_ADMIN_USER": "mesh-admin",
|
||||
"MESH_NEXTCLOUD_ADMIN_PASSWORD_FILE": "${dir:state}/admin.secret"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "files",
|
||||
"kind": "archive",
|
||||
"from": "files"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,191 @@
|
||||
{
|
||||
"module": "nfs-server",
|
||||
"version": "1",
|
||||
"upgrade": {
|
||||
"policy": "record",
|
||||
"why": "the folders other machines mount: a build that breaks the exports leaves every client's mount hanging or refused, and the gate on this one machine does not see the clients (hq ADR 0236, ADR 0263)"
|
||||
},
|
||||
"capabilities": [
|
||||
"package-manager",
|
||||
"service-manager"
|
||||
],
|
||||
"provides": [
|
||||
{
|
||||
"name": "nfs-share",
|
||||
"scope": "mesh",
|
||||
"identity": false
|
||||
}
|
||||
],
|
||||
"data": {
|
||||
"consumers": {
|
||||
"nfs-share": {
|
||||
"class": "none",
|
||||
"why": "the shared folders are the operator's data (hq ADR 0051): what a client writes lands in them, and they are protected where the operator declares them, never by this module, which keeps nothing of a consumer's"
|
||||
}
|
||||
}
|
||||
},
|
||||
"claims": [
|
||||
{
|
||||
"name": "node-nfs-server",
|
||||
"scope": "node",
|
||||
"serves": [
|
||||
"exports",
|
||||
"clients",
|
||||
"test",
|
||||
"reload",
|
||||
"adopt"
|
||||
]
|
||||
}
|
||||
],
|
||||
"state": [
|
||||
{
|
||||
"name": "exports",
|
||||
"ttl-seconds": 120,
|
||||
"per-machine": true
|
||||
}
|
||||
],
|
||||
"reads": [
|
||||
"mounts.shares"
|
||||
],
|
||||
"invokes": [
|
||||
"seat:mesh-controller.seats",
|
||||
"seat:mesh-controller.data"
|
||||
],
|
||||
"config": {
|
||||
"shares": {
|
||||
"type": "string",
|
||||
"description": "The folders this machine exports, as space-separated name=path; the operator's, with no default (novox/hq ADR 0263).",
|
||||
"trusted": true,
|
||||
"required": true
|
||||
},
|
||||
"grants": {
|
||||
"type": "string",
|
||||
"description": "Which nodes may mount which share, and how: share=node:rw|ro[,node:rw|ro], entries separated by spaces, or none to export to no node whatever a node wants (novox/hq ADR 0263).",
|
||||
"trusted": true,
|
||||
"default": "none"
|
||||
}
|
||||
},
|
||||
"facts": {
|
||||
"machines": {
|
||||
"path": "/etc/nfs-server/machines",
|
||||
"template": "# Written by the mesh (module nfs-server, novox/hq ADR 0263): every machine of the mesh and its private\n# address, from which the module takes a node's address. Replaced on every push.\n{{range .Machines}}{{.Name}} {{.Address}}\n{{end}}"
|
||||
}
|
||||
},
|
||||
"tools": [
|
||||
"nfs_health"
|
||||
],
|
||||
"listens": [
|
||||
{
|
||||
"name": "nfs",
|
||||
"port": 2049,
|
||||
"protocol": "tcp",
|
||||
"from": "mesh",
|
||||
"fixed": true,
|
||||
"why": "the shares, to the mesh's machines only (hq ADR 0263): NFS version 4 alone, which needs no other port, and never the home network, where a device that is not a node could claim any user id"
|
||||
}
|
||||
],
|
||||
"resources": [
|
||||
{
|
||||
"id": "package",
|
||||
"type": "package",
|
||||
"package": "nfs-utils"
|
||||
},
|
||||
{
|
||||
"id": "nfs-conf",
|
||||
"type": "file",
|
||||
"path": "/etc/nfs.conf.d/50-mesh.conf",
|
||||
"mode": "0644",
|
||||
"template": "files/50-mesh.conf"
|
||||
},
|
||||
{
|
||||
"id": "run-dir",
|
||||
"type": "directory",
|
||||
"path": "/run/nfs-server",
|
||||
"mode": "0755",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "server",
|
||||
"type": "service",
|
||||
"unit": "nfs-server.service",
|
||||
"state": "running",
|
||||
"boot": "enabled",
|
||||
"restart-on": [
|
||||
"nfs-conf"
|
||||
],
|
||||
"health": {
|
||||
"kind": "unit"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "wants-dir-parent",
|
||||
"type": "directory",
|
||||
"path": "/var/lib/nfs-server",
|
||||
"mode": "0755",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "wants-dir",
|
||||
"type": "directory",
|
||||
"path": "/var/lib/nfs-server/from-bus",
|
||||
"mode": "0755",
|
||||
"owner": "${machine:account}",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "exports",
|
||||
"type": "process",
|
||||
"name": "nfs-server-exports",
|
||||
"artifact": "tools",
|
||||
"run": [
|
||||
"./nfs-server",
|
||||
"exports"
|
||||
],
|
||||
"restart-on": [
|
||||
"config"
|
||||
],
|
||||
"health": {
|
||||
"kind": "tool",
|
||||
"tool": "nfs_health",
|
||||
"interval": "60s",
|
||||
"timeout": "10s",
|
||||
"looks": 2,
|
||||
"grace": "90s"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "config-dir",
|
||||
"type": "directory",
|
||||
"path": "/etc/nfs-server",
|
||||
"mode": "0755",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "config",
|
||||
"type": "file",
|
||||
"path": "/etc/nfs-server/shares.conf",
|
||||
"mode": "0644",
|
||||
"template": "files/shares.conf"
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "tools",
|
||||
"kind": "bundle",
|
||||
"language": "go",
|
||||
"system": "arch",
|
||||
"from": "cmd/nfs-server",
|
||||
"binary": "nfs-server",
|
||||
"loads": [
|
||||
"nfs-server"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "files",
|
||||
"kind": "archive",
|
||||
"from": "files"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
{
|
||||
"module": "nftables",
|
||||
"version": "1",
|
||||
"upgrade": {
|
||||
"policy": "record",
|
||||
"why": "the machine's packet filter: a build that breaks it can cut the machine off from the bus, and then neither the gate's rollback nor a push reaches it (hq ADR 0236)"
|
||||
},
|
||||
"capabilities": [
|
||||
"firewall"
|
||||
],
|
||||
"claims": [
|
||||
{
|
||||
"name": "node-packet-filter",
|
||||
"scope": "node",
|
||||
"serves": [
|
||||
"rules",
|
||||
"reload",
|
||||
"remove"
|
||||
]
|
||||
}
|
||||
],
|
||||
"filtering": {
|
||||
"into": "/etc/nftables.conf"
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"id": "package",
|
||||
"type": "package",
|
||||
"package": "nftables"
|
||||
},
|
||||
{
|
||||
"id": "legacy-tools",
|
||||
"type": "package",
|
||||
"package": "iptables"
|
||||
},
|
||||
{
|
||||
"id": "unit",
|
||||
"type": "file",
|
||||
"path": "/etc/systemd/system/mesh-filter.service",
|
||||
"template": "files/mesh-filter.service",
|
||||
"mode": "0644"
|
||||
},
|
||||
{
|
||||
"id": "stock-unit-stop",
|
||||
"type": "file",
|
||||
"path": "/etc/systemd/system/nftables.service.d/mesh.conf",
|
||||
"template": "files/mesh.conf",
|
||||
"mode": "0644"
|
||||
},
|
||||
{
|
||||
"id": "load",
|
||||
"type": "service",
|
||||
"unit": "mesh-filter.service",
|
||||
"state": "running",
|
||||
"boot": "enabled",
|
||||
"restart-on": [
|
||||
"unit",
|
||||
"stock-unit-stop"
|
||||
],
|
||||
"reload-on": [
|
||||
"filtering"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "front-end",
|
||||
"type": "package",
|
||||
"package": "ufw",
|
||||
"absent": true
|
||||
}
|
||||
],
|
||||
"tools": [
|
||||
"firewall_rules"
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "tools",
|
||||
"kind": "bundle",
|
||||
"language": "typescript",
|
||||
"entrypoints": [
|
||||
"tools/index.js"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "files",
|
||||
"kind": "archive",
|
||||
"from": "files"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"module": "nm-applet",
|
||||
"version": "1",
|
||||
"capabilities": [
|
||||
"package-manager"
|
||||
],
|
||||
"requires": [
|
||||
"x11-display"
|
||||
],
|
||||
"tools": [
|
||||
"nm_applet_status",
|
||||
"nm_applet_restart",
|
||||
"nm_applet_check"
|
||||
],
|
||||
"resources": [
|
||||
{
|
||||
"id": "package",
|
||||
"type": "package",
|
||||
"package": "network-manager-applet"
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "tools",
|
||||
"kind": "bundle",
|
||||
"language": "go",
|
||||
"system": "arch",
|
||||
"from": "cmd/nm-applet-tools",
|
||||
"binary": "nm-applet-tools",
|
||||
"loads": [
|
||||
"nm-applet-tools"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
{
|
||||
"module": "node-env",
|
||||
"version": "1",
|
||||
"moved": true,
|
||||
"claims": [
|
||||
{
|
||||
"name": "node-environment",
|
||||
"scope": "node"
|
||||
}
|
||||
],
|
||||
"resources": [
|
||||
{
|
||||
"id": "mesh-config-dir",
|
||||
"type": "directory",
|
||||
"path": "${machine:account-home}/.config/mesh",
|
||||
"owner": "${machine:account}",
|
||||
"mode": "0755",
|
||||
"unknown": "move-out",
|
||||
"knows": ["forge.credentials"]
|
||||
},
|
||||
{
|
||||
"id": "environment-d",
|
||||
"type": "directory",
|
||||
"path": "${machine:account-home}/.config/environment.d",
|
||||
"owner": "${machine:account}",
|
||||
"mode": "0755",
|
||||
"unknown": "move-out"
|
||||
},
|
||||
{
|
||||
"id": "posix",
|
||||
"type": "file",
|
||||
"path": "${machine:account-home}/.config/mesh/environment.sh",
|
||||
"owner": "${machine:account}",
|
||||
"mode": "0644",
|
||||
"template": "files/environment.sh"
|
||||
},
|
||||
{
|
||||
"id": "systemd",
|
||||
"type": "file",
|
||||
"path": "${machine:account-home}/.config/environment.d/50-mesh.conf",
|
||||
"owner": "${machine:account}",
|
||||
"mode": "0644",
|
||||
"template": "files/50-mesh.conf"
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "files",
|
||||
"kind": "archive",
|
||||
"from": "files"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,297 @@
|
||||
{
|
||||
"module": "nodered",
|
||||
"version": "1",
|
||||
"emits": [
|
||||
"flows.deployed"
|
||||
],
|
||||
"own-secrets": {
|
||||
"admin": {
|
||||
"path": "${dir:mesh-state}/admin",
|
||||
"taken": "at-start"
|
||||
},
|
||||
"api-token": {
|
||||
"path": "${dir:mesh-state}/api-token",
|
||||
"taken": "at-start"
|
||||
}
|
||||
},
|
||||
"capabilities": [
|
||||
"container-runtime"
|
||||
],
|
||||
"listens": [
|
||||
{
|
||||
"name": "web",
|
||||
"port": 1880,
|
||||
"protocol": "tcp",
|
||||
"from": "mesh",
|
||||
"why": "the flow editor and the endpoints flows expose"
|
||||
}
|
||||
],
|
||||
"data": {
|
||||
"own": [
|
||||
{
|
||||
"id": "data",
|
||||
"path": "${dir:data}",
|
||||
"class": "valuable",
|
||||
"why": "flows and their credentials"
|
||||
}
|
||||
]
|
||||
},
|
||||
"config": {
|
||||
"flow-file": {
|
||||
"type": "string",
|
||||
"description": "Node-RED's flowFile setting: the file in the user directory the flows are kept in.",
|
||||
"trusted": true,
|
||||
"default": "flows.json"
|
||||
},
|
||||
"flow-file-pretty": {
|
||||
"type": "boolean",
|
||||
"description": "Node-RED's flowFilePretty setting: whether the flows file is written indented.",
|
||||
"trusted": true,
|
||||
"default": true
|
||||
},
|
||||
"diagnostics": {
|
||||
"type": "object",
|
||||
"description": "Node-RED's diagnostics setting: whether its diagnostics report is on, and shown in the editor.",
|
||||
"trusted": true,
|
||||
"default": {
|
||||
"enabled": true,
|
||||
"ui": true
|
||||
}
|
||||
},
|
||||
"runtime-state": {
|
||||
"type": "object",
|
||||
"description": "Node-RED's runtimeState setting: whether flows may be started and stopped from the editor.",
|
||||
"trusted": true,
|
||||
"default": {
|
||||
"enabled": false,
|
||||
"ui": false
|
||||
}
|
||||
},
|
||||
"logging": {
|
||||
"type": "object",
|
||||
"description": "Node-RED's logging setting: the console log's level, and whether metrics and audit events are logged.",
|
||||
"trusted": true,
|
||||
"default": {
|
||||
"console": {
|
||||
"level": "info",
|
||||
"metrics": false,
|
||||
"audit": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"export-global-context-keys": {
|
||||
"type": "boolean",
|
||||
"description": "Node-RED's exportGlobalContextKeys setting: whether a function node may list the global context's keys.",
|
||||
"trusted": true,
|
||||
"default": false
|
||||
},
|
||||
"external-modules": {
|
||||
"type": "object",
|
||||
"description": "Node-RED's externalModules setting: which modules the editor may install, and from where.",
|
||||
"trusted": true,
|
||||
"default": {}
|
||||
},
|
||||
"editor-theme": {
|
||||
"type": "object",
|
||||
"description": "Node-RED's editorTheme setting: the editor's look and features, projects among them.",
|
||||
"trusted": true,
|
||||
"default": {
|
||||
"projects": {
|
||||
"enabled": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"function-external-modules": {
|
||||
"type": "boolean",
|
||||
"description": "Node-RED's functionExternalModules setting: whether a function node may load modules of its own.",
|
||||
"trusted": true,
|
||||
"default": true
|
||||
},
|
||||
"debug-max-length": {
|
||||
"type": "number",
|
||||
"description": "Node-RED's debugMaxLength setting: the most characters a debug message shows, a count.",
|
||||
"trusted": true,
|
||||
"default": 1000
|
||||
},
|
||||
"mqtt-reconnect-time": {
|
||||
"type": "number",
|
||||
"description": "Node-RED's mqttReconnectTime setting: how long an MQTT node waits before reconnecting, in milliseconds.",
|
||||
"trusted": true,
|
||||
"default": 15000
|
||||
},
|
||||
"serial-reconnect-time": {
|
||||
"type": "number",
|
||||
"description": "Node-RED's serialReconnectTime setting: how long a serial node waits before reconnecting, in milliseconds.",
|
||||
"trusted": true,
|
||||
"default": 15000
|
||||
},
|
||||
"mqtt": {
|
||||
"type": "object",
|
||||
"description": "The broker nodes the module's MQTT step keeps pointed at the mesh's broker, as {\"brokers\": [their ids]}; empty, none.",
|
||||
"trusted": true,
|
||||
"default": {}
|
||||
},
|
||||
"time-zone": {
|
||||
"type": "string",
|
||||
"description": "The time zone the flows schedule and format in, an IANA name such as Europe/Brussels; unset, the container's UTC.",
|
||||
"trusted": true,
|
||||
"default": ""
|
||||
}
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"id": "mesh-state",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"place": "mesh",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "state",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"place": ".",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "data",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"owner": "1000:1000",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "written",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "settings-code",
|
||||
"type": "file",
|
||||
"path": "${dir:state}/settings.js",
|
||||
"mode": "0600",
|
||||
"owner": "1000:1000",
|
||||
"template": "files/settings.js"
|
||||
},
|
||||
{
|
||||
"id": "settings",
|
||||
"type": "file",
|
||||
"path": "${dir:state}/settings.json",
|
||||
"mode": "0600",
|
||||
"owner": "1000:1000",
|
||||
"merge": "json",
|
||||
"takes-config": [{"key": "flow-file", "as": "flowFile"}, {"key": "flow-file-pretty", "as": "flowFilePretty"}, "diagnostics", {"key": "runtime-state", "as": "runtimeState"}, "logging", {"key": "export-global-context-keys", "as": "exportGlobalContextKeys"}, {"key": "external-modules", "as": "externalModules"}, {"key": "editor-theme", "as": "editorTheme"}, {"key": "function-external-modules", "as": "functionExternalModules"}, {"key": "debug-max-length", "as": "debugMaxLength"}, {"key": "mqtt-reconnect-time", "as": "mqttReconnectTime"}, {"key": "serial-reconnect-time", "as": "serialReconnectTime"}, "mqtt", {"key": "time-zone", "as": "timeZone"}],
|
||||
"template": "files/settings.json"
|
||||
},
|
||||
{
|
||||
"id": "server",
|
||||
"type": "container",
|
||||
"name": "nodered",
|
||||
"image": "nodered/node-red@sha256:a649dd711d55490151a2c39a8e48ad0c44325488fbc0e66315f2d2e19e5e1ace",
|
||||
"health": {
|
||||
"kind": "runtime"
|
||||
},
|
||||
"env": {
|
||||
"TZ": "Etc/UTC"
|
||||
},
|
||||
"ports": [
|
||||
"1880"
|
||||
],
|
||||
"args": [
|
||||
"--settings",
|
||||
"/data/settings.js"
|
||||
],
|
||||
"volumes": [
|
||||
"${dir:data}:/data",
|
||||
"${dir:state}/settings.js:/data/settings.js:ro",
|
||||
"${dir:state}/settings.json:/data/settings.json:ro"
|
||||
],
|
||||
"restart-on": [
|
||||
"settings-code",
|
||||
"settings"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "runtime-config",
|
||||
"type": "file",
|
||||
"path": "${dir:mesh-state}/config.json",
|
||||
"mode": "0600",
|
||||
"template": "files/config.json"
|
||||
},
|
||||
{
|
||||
"id": "mqtt-env",
|
||||
"type": "file",
|
||||
"path": "${dir:state}/mqtt.env",
|
||||
"mode": "0600",
|
||||
"template": "files/mqtt.env"
|
||||
},
|
||||
{
|
||||
"id": "mqtt",
|
||||
"type": "process",
|
||||
"name": "nodered-mqtt",
|
||||
"artifact": "code",
|
||||
"run": [
|
||||
"node",
|
||||
"mqtt/index.js"
|
||||
],
|
||||
"run-once": true,
|
||||
"env-file": [
|
||||
"${dir:state}/mqtt.env"
|
||||
],
|
||||
"restart-on": [
|
||||
"mqtt-env",
|
||||
"bound-mqtt-topic",
|
||||
"secret-mqtt-topic",
|
||||
"settings"
|
||||
]
|
||||
}
|
||||
],
|
||||
"requires": [
|
||||
"mqtt-topic",
|
||||
"route"
|
||||
],
|
||||
"contributes": {
|
||||
"mqtt-topic": {
|
||||
"topics": [
|
||||
"#"
|
||||
]
|
||||
},
|
||||
"route": {
|
||||
"label": "nodered",
|
||||
"endpoint": "web"
|
||||
}
|
||||
},
|
||||
"binds": {
|
||||
"route": "${dir:state}/route.json",
|
||||
"mqtt-topic": "${dir:state}/mqtt-topic.json"
|
||||
},
|
||||
"secrets": {
|
||||
"mqtt-topic": "${dir:state}/mqtt-topic.secret"
|
||||
},
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "code",
|
||||
"kind": "bundle",
|
||||
"language": "typescript",
|
||||
"entrypoints": [
|
||||
"tools/index.js",
|
||||
"mqtt/index.js"
|
||||
],
|
||||
"loads": [
|
||||
"tools/index.js"
|
||||
],
|
||||
"env": {
|
||||
"MESH_NODERED_URL": "http://127.0.0.1:${port:1880}",
|
||||
"MESH_NODERED_CONFIG_FILE": "${dir:mesh-state}/config.json"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "files",
|
||||
"kind": "archive",
|
||||
"from": "files"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
{
|
||||
"module": "ollama",
|
||||
"version": "1",
|
||||
"capabilities": [
|
||||
"container-runtime"
|
||||
],
|
||||
"provides": [
|
||||
{
|
||||
"name": "model-access",
|
||||
"scope": "node"
|
||||
}
|
||||
],
|
||||
"listens": [
|
||||
{
|
||||
"name": "api",
|
||||
"port": 11434,
|
||||
"protocol": "tcp",
|
||||
"from": "machine",
|
||||
"why": "consumers on this machine reaching the local model server's OpenAI-compatible API"
|
||||
}
|
||||
],
|
||||
"serves": {
|
||||
"model-access": {
|
||||
"port": 11434,
|
||||
"model": "llama3.2"
|
||||
}
|
||||
},
|
||||
"data": {
|
||||
"own": [
|
||||
{
|
||||
"id": "models",
|
||||
"path": "${dir:state}",
|
||||
"class": "rebuildable",
|
||||
"backup": "none",
|
||||
"measure": "shallow",
|
||||
"why": "models, downloaded again, and too large to copy every night"
|
||||
}
|
||||
]
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"id": "state",
|
||||
"type": "directory",
|
||||
"path": "/services/ollama",
|
||||
"mode": "0700",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "server",
|
||||
"type": "container",
|
||||
"name": "ollama",
|
||||
"image": "ollama/ollama@sha256:32931b46719f673c05fdbaa81ccb26da18ea4a1c57590a754874ab28ba269eb2",
|
||||
"network": "host",
|
||||
"env": {
|
||||
"OLLAMA_HOST": "0.0.0.0:11434"
|
||||
},
|
||||
"volumes": [
|
||||
"/services/ollama:/root/.ollama"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
{
|
||||
"module": "only-office",
|
||||
"version": "1",
|
||||
"slug": "office",
|
||||
"capabilities": [
|
||||
"container-runtime"
|
||||
],
|
||||
"requires": [
|
||||
"route"
|
||||
],
|
||||
"contributes": {
|
||||
"route": {
|
||||
"label": "office",
|
||||
"endpoint": "web"
|
||||
}
|
||||
},
|
||||
"binds": {
|
||||
"route": "${dir:state}/route.json"
|
||||
},
|
||||
"own-secrets": {
|
||||
"jwt": "${dir:state}/jwt.secret"
|
||||
},
|
||||
"listens": [
|
||||
{
|
||||
"name": "web",
|
||||
"port": 9070,
|
||||
"protocol": "tcp",
|
||||
"from": "mesh",
|
||||
"why": "the document server over http; its public name is a route grant, and route-proxy reaches it on this published port"
|
||||
}
|
||||
],
|
||||
"data": {
|
||||
"own": [
|
||||
{
|
||||
"id": "data",
|
||||
"path": "${dir:data}",
|
||||
"class": "rebuildable",
|
||||
"why": "documents being edited; the documents themselves are the file store's"
|
||||
},
|
||||
{
|
||||
"id": "lib",
|
||||
"path": "${dir:lib}",
|
||||
"class": "rebuildable",
|
||||
"why": "the document server's working files"
|
||||
},
|
||||
{
|
||||
"id": "db",
|
||||
"path": "${dir:db}",
|
||||
"class": "rebuildable",
|
||||
"why": "the document server's own database of editing sessions"
|
||||
},
|
||||
{
|
||||
"id": "fonts",
|
||||
"path": "${dir:fonts}",
|
||||
"class": "rebuildable",
|
||||
"why": "fonts, installed again"
|
||||
},
|
||||
{
|
||||
"id": "logs",
|
||||
"path": "${dir:logs}",
|
||||
"class": "cache",
|
||||
"why": "logs"
|
||||
},
|
||||
{
|
||||
"id": "rabbitmq",
|
||||
"path": "${dir:rabbitmq}",
|
||||
"class": "cache",
|
||||
"why": "its queue's working set"
|
||||
},
|
||||
{
|
||||
"id": "redis",
|
||||
"path": "${dir:redis}",
|
||||
"class": "cache",
|
||||
"why": "its cache"
|
||||
}
|
||||
]
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"id": "state",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"place": ".",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "server-env",
|
||||
"type": "file",
|
||||
"path": "${dir:state}/server.env",
|
||||
"mode": "0600",
|
||||
"template": "files/server.env"
|
||||
},
|
||||
{
|
||||
"id": "logs",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "data",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "lib",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "db",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "rabbitmq",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "redis",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "fonts",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "net",
|
||||
"type": "network",
|
||||
"name": "only-office"
|
||||
},
|
||||
{
|
||||
"id": "server",
|
||||
"type": "container",
|
||||
"name": "only-office",
|
||||
"image": "onlyoffice/documentserver@sha256:3ab6ebc7c605e5a32b7ae3ff19daed4925090245acc8100ce2230bd766c88212",
|
||||
"network": "only-office",
|
||||
"env-file": [
|
||||
"${dir:state}/server.env"
|
||||
],
|
||||
"ports": [
|
||||
"9070:80"
|
||||
],
|
||||
"volumes": [
|
||||
"${dir:logs}:/var/log/onlyoffice",
|
||||
"${dir:data}:/var/www/onlyoffice/Data",
|
||||
"${dir:lib}:/var/lib/onlyoffice",
|
||||
"${dir:db}:/var/lib/postgresql",
|
||||
"${dir:rabbitmq}:/var/lib/rabbitmq",
|
||||
"${dir:redis}:/var/lib/redis",
|
||||
"${dir:fonts}:/usr/share/fonts/truetype/custom"
|
||||
],
|
||||
"secrets-in-environment": "run-document-server.sh regenerates JWT_SECRET from the environment on every start and overwrites local.json; not convertible"
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "files",
|
||||
"kind": "archive",
|
||||
"from": "files"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
{
|
||||
"module": "openai-consumer",
|
||||
"version": "1",
|
||||
"slug": "openai",
|
||||
"capabilities": [
|
||||
"container-runtime"
|
||||
],
|
||||
"requires": [
|
||||
"model-access"
|
||||
],
|
||||
"binds": {
|
||||
"model-access": "${dir:state}/model.json"
|
||||
},
|
||||
"secrets": {
|
||||
"model-access": "${dir:state}/api-key"
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"id": "state",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"place": ".",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "config",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "apply",
|
||||
"type": "process",
|
||||
"name": "openai-consumer-apply",
|
||||
"artifact": "code",
|
||||
"run": [
|
||||
"node",
|
||||
"apply/index.js"
|
||||
],
|
||||
"schedule": "*/5 * * * *",
|
||||
"env": {
|
||||
"MESH_MODEL_ACCESS_SECRET_FILE": "${dir:state}/api-key",
|
||||
"MESH_MODEL_ACCESS_BIND_FILE": "${dir:state}/model.json",
|
||||
"MESH_OPENAI_ENV_FILE": "${dir:state}/config/openai.env",
|
||||
"MESH_OPENAI_CREDENTIALS_FILE": "${dir:state}/config/auth.json"
|
||||
}
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "code",
|
||||
"kind": "bundle",
|
||||
"language": "typescript",
|
||||
"entrypoints": [
|
||||
"apply/index.js"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
{
|
||||
"module": "openrazer",
|
||||
"version": "1",
|
||||
"capabilities": [
|
||||
"package-manager"
|
||||
],
|
||||
"tools": [
|
||||
"openrazer_status",
|
||||
"openrazer_restart",
|
||||
"openrazer_check"
|
||||
],
|
||||
"resources": [
|
||||
{
|
||||
"id": "driver",
|
||||
"type": "package",
|
||||
"package": "openrazer-driver-dkms"
|
||||
},
|
||||
{
|
||||
"id": "daemon",
|
||||
"type": "package",
|
||||
"package": "openrazer-daemon"
|
||||
},
|
||||
{
|
||||
"id": "library",
|
||||
"type": "package",
|
||||
"package": "python-openrazer"
|
||||
},
|
||||
{
|
||||
"id": "account",
|
||||
"type": "user",
|
||||
"name": "${machine:account}",
|
||||
"groups": [
|
||||
"openrazer"
|
||||
]
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "tools",
|
||||
"kind": "bundle",
|
||||
"language": "go",
|
||||
"system": "arch",
|
||||
"from": "cmd/openrazer-tools",
|
||||
"binary": "openrazer-tools",
|
||||
"loads": [
|
||||
"openrazer-tools"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
{
|
||||
"module": "pacman",
|
||||
"version": "1",
|
||||
"capabilities": [
|
||||
"package-manager",
|
||||
"service-manager"
|
||||
],
|
||||
"claims": [
|
||||
{
|
||||
"name": "node-package-manager",
|
||||
"scope": "node"
|
||||
}
|
||||
],
|
||||
"tools": [
|
||||
"pacman_search",
|
||||
"pacman_info",
|
||||
"pacman_installed",
|
||||
"pacman_owns",
|
||||
"pacman_files",
|
||||
"pacman_updates",
|
||||
"pacman_upgrade",
|
||||
"pacman_orphans",
|
||||
"pacman_remove_orphans",
|
||||
"pacman_cache",
|
||||
"pacman_history",
|
||||
"pacman_mirrors",
|
||||
"pacman_foreign",
|
||||
"pacman_news",
|
||||
"pacman_config"
|
||||
],
|
||||
"resources": [
|
||||
{
|
||||
"id": "package",
|
||||
"type": "package",
|
||||
"package": "pacman"
|
||||
},
|
||||
{
|
||||
"id": "config",
|
||||
"type": "file",
|
||||
"path": "/etc/pacman.conf",
|
||||
"mode": "0644",
|
||||
"template": "files/pacman.conf"
|
||||
},
|
||||
{
|
||||
"id": "contrib",
|
||||
"type": "package",
|
||||
"package": "pacman-contrib"
|
||||
},
|
||||
{
|
||||
"id": "reflector",
|
||||
"type": "package",
|
||||
"package": "reflector"
|
||||
},
|
||||
{
|
||||
"id": "mirrors",
|
||||
"type": "file",
|
||||
"path": "/etc/xdg/reflector/reflector.conf",
|
||||
"mode": "0644",
|
||||
"template": "files/reflector.conf"
|
||||
},
|
||||
{
|
||||
"id": "mirror-refresh",
|
||||
"type": "service",
|
||||
"unit": "reflector.timer",
|
||||
"state": "running",
|
||||
"boot": "enabled"
|
||||
},
|
||||
{
|
||||
"id": "cache-cleaning",
|
||||
"type": "service",
|
||||
"unit": "paccache.timer",
|
||||
"state": "running",
|
||||
"boot": "enabled"
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "tools",
|
||||
"kind": "bundle",
|
||||
"language": "go",
|
||||
"system": "arch",
|
||||
"from": "cmd/pacman-tools",
|
||||
"binary": "pacman-tools",
|
||||
"loads": [
|
||||
"pacman-tools"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "files",
|
||||
"kind": "archive",
|
||||
"from": "files"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
{
|
||||
"module": "photos-eef",
|
||||
"version": "1",
|
||||
"slug": "eef",
|
||||
"capabilities": [
|
||||
"container-runtime"
|
||||
],
|
||||
"requires": [
|
||||
"route"
|
||||
],
|
||||
"contributes": {
|
||||
"route": {
|
||||
"label": "eef",
|
||||
"endpoint": "web"
|
||||
}
|
||||
},
|
||||
"binds": {
|
||||
"route": "${dir:state}/route.json"
|
||||
},
|
||||
"listens": [
|
||||
{
|
||||
"name": "web",
|
||||
"port": 4012,
|
||||
"protocol": "tcp",
|
||||
"from": "mesh",
|
||||
"why": "the eef photos client site over http; its public name is a route grant, and route-proxy reaches it on this published port"
|
||||
}
|
||||
],
|
||||
"resources": [
|
||||
{
|
||||
"id": "state",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"place": ".",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "net",
|
||||
"type": "network",
|
||||
"name": "photos-eef"
|
||||
},
|
||||
{
|
||||
"id": "client",
|
||||
"type": "container",
|
||||
"name": "photos-eef",
|
||||
"image": "registry-api.novox.be/novox/photos-client@sha256:f87d63ee7bfb44c9f9748b99be6ba6dc0daf955a1d463699e9e7e3009693c0ab",
|
||||
"network": "photos-eef",
|
||||
"ports": [
|
||||
"4012:80"
|
||||
],
|
||||
"names-on-purpose": {
|
||||
"registry-api.novox.be": "built outside the mesh, from the application's own repository, and pulled from the registry that built it; moves when that repository is a build source on the git seat (novox/hq ADR 0155, issue 122)"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
{
|
||||
"module": "photos-filip",
|
||||
"version": "1",
|
||||
"slug": "filip",
|
||||
"capabilities": [
|
||||
"container-runtime"
|
||||
],
|
||||
"requires": [
|
||||
"route"
|
||||
],
|
||||
"contributes": {
|
||||
"route": {
|
||||
"label": "filip",
|
||||
"endpoint": "web"
|
||||
}
|
||||
},
|
||||
"binds": {
|
||||
"route": "${dir:state}/route.json"
|
||||
},
|
||||
"listens": [
|
||||
{
|
||||
"name": "web",
|
||||
"port": 4013,
|
||||
"protocol": "tcp",
|
||||
"from": "mesh",
|
||||
"why": "the filip photos client site over http; its public name is a route grant, and route-proxy reaches it on this published port"
|
||||
}
|
||||
],
|
||||
"resources": [
|
||||
{
|
||||
"id": "state",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"place": ".",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "net",
|
||||
"type": "network",
|
||||
"name": "photos-filip"
|
||||
},
|
||||
{
|
||||
"id": "client",
|
||||
"type": "container",
|
||||
"name": "photos-filip",
|
||||
"image": "registry-api.novox.be/novox/photos-client@sha256:f87d63ee7bfb44c9f9748b99be6ba6dc0daf955a1d463699e9e7e3009693c0ab",
|
||||
"network": "photos-filip",
|
||||
"ports": [
|
||||
"4013:80"
|
||||
],
|
||||
"names-on-purpose": {
|
||||
"registry-api.novox.be": "built outside the mesh, from the application's own repository, and pulled from the registry that built it; moves when that repository is a build source on the git seat (novox/hq ADR 0155, issue 122)"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
{
|
||||
"module": "picom",
|
||||
"version": "1",
|
||||
"capabilities": [
|
||||
"package-manager"
|
||||
],
|
||||
"requires": [
|
||||
"x11-display"
|
||||
],
|
||||
"claims": [
|
||||
{
|
||||
"name": "node-compositor",
|
||||
"scope": "node"
|
||||
}
|
||||
],
|
||||
"config": {
|
||||
"backend": {
|
||||
"type": "string",
|
||||
"description": "How picom draws: glx with the graphics card, which has served every machine so far, or xrender on the CPU where glx leaves a window unpainted or stale on the machine's driver (novox/hq research 037, issue 345); xr_glx_hybrid and egl are picom's other backends.",
|
||||
"enum": [
|
||||
"glx",
|
||||
"xrender",
|
||||
"xr_glx_hybrid",
|
||||
"egl"
|
||||
],
|
||||
"trusted": true,
|
||||
"default": "glx"
|
||||
},
|
||||
"use-damage": {
|
||||
"type": "boolean",
|
||||
"description": "Whether picom repaints only what changed (true, picom's own default) or the whole screen each frame (false), which costs work and cures a window left stale or unpainted on some drivers (novox/hq issue 345).",
|
||||
"trusted": true,
|
||||
"default": true
|
||||
}
|
||||
},
|
||||
"tools": [
|
||||
"picom_restart",
|
||||
"picom_rules",
|
||||
"picom_window_opacity",
|
||||
"picom_toggle"
|
||||
],
|
||||
"resources": [
|
||||
{
|
||||
"id": "package",
|
||||
"type": "package",
|
||||
"package": "picom"
|
||||
},
|
||||
{
|
||||
"id": "window-properties",
|
||||
"type": "package",
|
||||
"package": "xorg-xprop"
|
||||
},
|
||||
{
|
||||
"id": "configuration-dir",
|
||||
"type": "directory",
|
||||
"path": "${machine:account-home}/.config/picom",
|
||||
"owner": "${machine:account}",
|
||||
"mode": "0755",
|
||||
"unknown": "move-out"
|
||||
},
|
||||
{
|
||||
"id": "configuration",
|
||||
"type": "file",
|
||||
"path": "${machine:account-home}/.config/picom/picom.conf",
|
||||
"owner": "${machine:account}",
|
||||
"mode": "0644",
|
||||
"template": "files/picom.conf"
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "tools",
|
||||
"kind": "bundle",
|
||||
"language": "go",
|
||||
"system": "arch",
|
||||
"from": "cmd/picom-tools",
|
||||
"binary": "picom-tools",
|
||||
"loads": [
|
||||
"picom-tools"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "files",
|
||||
"kind": "archive",
|
||||
"from": "files"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"module": "polychromatic",
|
||||
"version": "1",
|
||||
"moved": true,
|
||||
"requires": [
|
||||
"x11-display"
|
||||
],
|
||||
"tools": [
|
||||
"polychromatic_status",
|
||||
"polychromatic_restart",
|
||||
"polychromatic_check"
|
||||
],
|
||||
"items": [
|
||||
{
|
||||
"collection": "contribution:node-display-session:config",
|
||||
"name": "display-session",
|
||||
"template": "files/display-session"
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "tools",
|
||||
"kind": "bundle",
|
||||
"language": "go",
|
||||
"system": "arch",
|
||||
"from": "cmd/polychromatic-tools",
|
||||
"binary": "polychromatic-tools",
|
||||
"loads": [
|
||||
"polychromatic-tools"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "files",
|
||||
"kind": "archive",
|
||||
"from": "files"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,191 @@
|
||||
{
|
||||
"module": "postgres",
|
||||
"version": "1",
|
||||
"moved": true,
|
||||
"upgrade": {
|
||||
"policy": "record",
|
||||
"why": "a provider whose restart drops every consumer on its machine, and whose new major version changes its data's format: a person takes each build, after a backup (hq ADR 0236)"
|
||||
},
|
||||
"provides": [
|
||||
{
|
||||
"name": "postgres-database",
|
||||
"scope": "mesh",
|
||||
"identity": {
|
||||
"max": 63,
|
||||
"in": "a PostgreSQL role and database name"
|
||||
}
|
||||
}
|
||||
],
|
||||
"claims": [
|
||||
{
|
||||
"name": "mesh-store",
|
||||
"scope": "mesh",
|
||||
"serves": [
|
||||
"databases",
|
||||
"query"
|
||||
]
|
||||
}
|
||||
],
|
||||
"capabilities": [
|
||||
"container-runtime"
|
||||
],
|
||||
"emits": [
|
||||
"database.provisioned",
|
||||
"database.deprovisioned"
|
||||
],
|
||||
"consumes": [
|
||||
"postgres.database.provisioned",
|
||||
"postgres.database.deprovisioned"
|
||||
],
|
||||
"listens": [
|
||||
{
|
||||
"name": "database",
|
||||
"port": 5432,
|
||||
"protocol": "tcp",
|
||||
"from": "mesh",
|
||||
"why": "modules on any machine that were granted a database"
|
||||
}
|
||||
],
|
||||
"guards": [
|
||||
5432
|
||||
],
|
||||
"serves": {
|
||||
"postgres-database": {
|
||||
"port": 5432
|
||||
}
|
||||
},
|
||||
"receives": {
|
||||
"postgres-database": "${dir:grants}/mesh.json"
|
||||
},
|
||||
"grants": {
|
||||
"postgres-database": "${dir:grants}"
|
||||
},
|
||||
"own-secrets": {
|
||||
"superuser": "${dir:state}/superuser.secret",
|
||||
"reader": "${dir:state}/reader.secret"
|
||||
},
|
||||
"data": {
|
||||
"own": [
|
||||
{
|
||||
"id": "store",
|
||||
"path": "${dir:store-data}",
|
||||
"class": "valuable",
|
||||
"backup": {
|
||||
"dump": "docker exec -u postgres postgres sh -c 'cd /var/lib/postgresql/data/dumps && for db in $(psql -Atc \"select datname from pg_database where oid >= 16384 order by 1\"); do pg_dump -Fc -f \"$db.dump.partial\" \"$db\" && mv \"$db.dump.partial\" \"$db.dump\" || exit 1; done'",
|
||||
"into": "dumps"
|
||||
},
|
||||
"why": "every consumer's database; copied by the dump below, since a running store's files are not a consistent copy"
|
||||
},
|
||||
{
|
||||
"id": "dumps",
|
||||
"path": "${dir:dumps}",
|
||||
"class": "rebuildable",
|
||||
"why": "last night's dump of the store, made again every night"
|
||||
}
|
||||
],
|
||||
"consumers": {
|
||||
"postgres-database": {
|
||||
"class": "valuable",
|
||||
"in": "store",
|
||||
"why": "a consumer's rows are the only copy of what it wrote"
|
||||
}
|
||||
}
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"id": "state",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"place": ".",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "grants",
|
||||
"type": "directory",
|
||||
"mode": "0700",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "consumers",
|
||||
"type": "file",
|
||||
"path": "${dir:state}/consumers.json",
|
||||
"mode": "0600",
|
||||
"template": "files/consumers.json"
|
||||
},
|
||||
{
|
||||
"id": "store-data",
|
||||
"type": "directory",
|
||||
"path": "/var/lib/mesh-store",
|
||||
"mode": "0700",
|
||||
"owner": "999:70",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "dumps",
|
||||
"type": "directory",
|
||||
"path": "${dir:store-data}/dumps",
|
||||
"mode": "0700",
|
||||
"owner": "999:70",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "server",
|
||||
"type": "container",
|
||||
"name": "postgres",
|
||||
"image": "pgvector/pgvector@sha256:cf134a767f474095eeba57e0117be8e568e011a63f33fbf252f14c9b760f8e6f",
|
||||
"health": {
|
||||
"kind": "tcp",
|
||||
"endpoint": "database"
|
||||
},
|
||||
"env": {
|
||||
"POSTGRES_PASSWORD_FILE": "/run/secrets/superuser",
|
||||
"PGDATA": "/var/lib/postgresql/data/pgdata"
|
||||
},
|
||||
"ports": [
|
||||
"5432:5432"
|
||||
],
|
||||
"volumes": [
|
||||
"/var/lib/mesh-store:/var/lib/postgresql/data",
|
||||
"${dir:state}/superuser.secret:/run/secrets/superuser:ro"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "client",
|
||||
"type": "package",
|
||||
"package": "postgresql-libs"
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "code",
|
||||
"kind": "bundle",
|
||||
"language": "go",
|
||||
"system": "arch",
|
||||
"from": "cmd/postgres-provider",
|
||||
"binary": "postgres-provider",
|
||||
"loads": [
|
||||
"postgres-provider"
|
||||
],
|
||||
"env": {
|
||||
"MESH_PROVISION_POSTGRES": "postgres://postgres@127.0.0.1:${port:5432}/postgres?sslmode=disable",
|
||||
"MESH_PROVISION_PASSWORD_FILE": "${dir:state}/superuser.secret",
|
||||
"MESH_RECEIVES": "${dir:grants}/mesh.json",
|
||||
"MESH_POSTGRES_READER_PASSWORD_FILE": "${dir:state}/reader.secret",
|
||||
"MESH_CONSUMERS_FILE": "${dir:state}/consumers.json"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "files",
|
||||
"kind": "archive",
|
||||
"from": "files"
|
||||
}
|
||||
]
|
||||
},
|
||||
"state": [
|
||||
"bound"
|
||||
],
|
||||
"reads": [
|
||||
"mesh-controller.assignments"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,408 @@
|
||||
{
|
||||
"module": "power",
|
||||
"version": "1",
|
||||
"moved": true,
|
||||
"templates": "templates",
|
||||
"capabilities": [
|
||||
"package-manager",
|
||||
"service-manager"
|
||||
],
|
||||
"claims": [
|
||||
{
|
||||
"name": "node-power",
|
||||
"scope": "node"
|
||||
}
|
||||
],
|
||||
"emits": [
|
||||
"booted",
|
||||
"sleeping",
|
||||
"woke",
|
||||
"shutting-down",
|
||||
"on-mains",
|
||||
"on-battery",
|
||||
"battery-low"
|
||||
],
|
||||
"state": [
|
||||
{
|
||||
"name": "draw",
|
||||
"ttl-seconds": 30,
|
||||
"per-machine": true
|
||||
}
|
||||
],
|
||||
"tools": [
|
||||
"power_state",
|
||||
"power_hooks",
|
||||
"power_history",
|
||||
"power_run",
|
||||
"power_check"
|
||||
],
|
||||
"config": {
|
||||
"handle-power-key": {
|
||||
"type": "string",
|
||||
"description": "What logind does when the power key is pressed: one of logind's actions, such as suspend, ignore or poweroff (logind.conf(5)); the operator's choice for this machine, with no default.",
|
||||
"enum": [
|
||||
"ignore",
|
||||
"poweroff",
|
||||
"reboot",
|
||||
"halt",
|
||||
"kexec",
|
||||
"suspend",
|
||||
"hibernate",
|
||||
"hybrid-sleep",
|
||||
"suspend-then-hibernate",
|
||||
"lock",
|
||||
"factory-reset",
|
||||
"sleep"
|
||||
],
|
||||
"trusted": true,
|
||||
"required": true
|
||||
},
|
||||
"handle-lid-switch": {
|
||||
"type": "string",
|
||||
"description": "What logind does when the lid is closed on battery: one of logind's actions, such as suspend, ignore or poweroff (logind.conf(5)); the operator's choice for this machine, with no default.",
|
||||
"enum": [
|
||||
"ignore",
|
||||
"poweroff",
|
||||
"reboot",
|
||||
"halt",
|
||||
"kexec",
|
||||
"suspend",
|
||||
"hibernate",
|
||||
"hybrid-sleep",
|
||||
"suspend-then-hibernate",
|
||||
"lock",
|
||||
"factory-reset",
|
||||
"sleep"
|
||||
],
|
||||
"trusted": true,
|
||||
"required": true
|
||||
},
|
||||
"handle-lid-switch-external-power": {
|
||||
"type": "string",
|
||||
"description": "What logind does when the lid is closed on external power: one of logind's actions, such as suspend, ignore or poweroff (logind.conf(5)); the operator's choice for this machine, with no default.",
|
||||
"enum": [
|
||||
"ignore",
|
||||
"poweroff",
|
||||
"reboot",
|
||||
"halt",
|
||||
"kexec",
|
||||
"suspend",
|
||||
"hibernate",
|
||||
"hybrid-sleep",
|
||||
"suspend-then-hibernate",
|
||||
"lock",
|
||||
"factory-reset",
|
||||
"sleep"
|
||||
],
|
||||
"trusted": true,
|
||||
"required": true
|
||||
},
|
||||
"handle-lid-switch-docked": {
|
||||
"type": "string",
|
||||
"description": "What logind does when the lid is closed while docked or with another screen attached: one of logind's actions, such as suspend, ignore or poweroff (logind.conf(5)); the operator's choice for this machine, with no default.",
|
||||
"enum": [
|
||||
"ignore",
|
||||
"poweroff",
|
||||
"reboot",
|
||||
"halt",
|
||||
"kexec",
|
||||
"suspend",
|
||||
"hibernate",
|
||||
"hybrid-sleep",
|
||||
"suspend-then-hibernate",
|
||||
"lock",
|
||||
"factory-reset",
|
||||
"sleep"
|
||||
],
|
||||
"trusted": true,
|
||||
"required": true
|
||||
}
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"id": "polkit",
|
||||
"type": "package",
|
||||
"package": "polkit"
|
||||
},
|
||||
{
|
||||
"id": "scripts",
|
||||
"type": "archive",
|
||||
"path": "/usr/local/lib/mesh-power",
|
||||
"artifact": "scripts",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "config-dir",
|
||||
"type": "directory",
|
||||
"path": "/etc/mesh-power",
|
||||
"mode": "0755",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "moments-dir",
|
||||
"type": "directory",
|
||||
"path": "/etc/mesh-power/moments",
|
||||
"mode": "0755",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "moment-after-boot",
|
||||
"type": "file",
|
||||
"path": "/etc/mesh-power/moments/after-boot",
|
||||
"mode": "0644",
|
||||
"template": "templates/mesh-power/moments/after-boot"
|
||||
},
|
||||
{
|
||||
"id": "moment-before-sleep",
|
||||
"type": "file",
|
||||
"path": "/etc/mesh-power/moments/before-sleep",
|
||||
"mode": "0644",
|
||||
"template": "templates/mesh-power/moments/before-sleep"
|
||||
},
|
||||
{
|
||||
"id": "moment-after-wake",
|
||||
"type": "file",
|
||||
"path": "/etc/mesh-power/moments/after-wake",
|
||||
"mode": "0644",
|
||||
"template": "templates/mesh-power/moments/after-wake"
|
||||
},
|
||||
{
|
||||
"id": "moment-before-shutdown",
|
||||
"type": "file",
|
||||
"path": "/etc/mesh-power/moments/before-shutdown",
|
||||
"mode": "0644",
|
||||
"template": "templates/mesh-power/moments/before-shutdown"
|
||||
},
|
||||
{
|
||||
"id": "moment-on-mains",
|
||||
"type": "file",
|
||||
"path": "/etc/mesh-power/moments/on-mains",
|
||||
"mode": "0644",
|
||||
"template": "templates/mesh-power/moments/on-mains"
|
||||
},
|
||||
{
|
||||
"id": "moment-on-battery",
|
||||
"type": "file",
|
||||
"path": "/etc/mesh-power/moments/on-battery",
|
||||
"mode": "0644",
|
||||
"template": "templates/mesh-power/moments/on-battery"
|
||||
},
|
||||
{
|
||||
"id": "logind-drop-ins",
|
||||
"type": "directory",
|
||||
"path": "/etc/systemd/logind.conf.d",
|
||||
"mode": "0755",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "logind-power",
|
||||
"type": "file",
|
||||
"path": "/etc/systemd/logind.conf.d/power.conf",
|
||||
"mode": "0644",
|
||||
"template": "templates/systemd/logind.conf.d/power.conf"
|
||||
},
|
||||
{
|
||||
"id": "logind",
|
||||
"type": "service",
|
||||
"unit": "systemd-logind.service",
|
||||
"reload-on": [
|
||||
"logind-power"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "after-boot-unit",
|
||||
"type": "file",
|
||||
"path": "/etc/systemd/system/mesh-power-after-boot.service",
|
||||
"mode": "0644",
|
||||
"template": "templates/systemd/system/mesh-power-after-boot.service"
|
||||
},
|
||||
{
|
||||
"id": "before-shutdown-unit",
|
||||
"type": "file",
|
||||
"path": "/etc/systemd/system/mesh-power-before-shutdown.service",
|
||||
"mode": "0644",
|
||||
"template": "templates/systemd/system/mesh-power-before-shutdown.service"
|
||||
},
|
||||
{
|
||||
"id": "before-sleep-unit",
|
||||
"type": "file",
|
||||
"path": "/etc/systemd/system/mesh-power-before-sleep.service",
|
||||
"mode": "0644",
|
||||
"template": "templates/systemd/system/mesh-power-before-sleep.service"
|
||||
},
|
||||
{
|
||||
"id": "after-wake-unit",
|
||||
"type": "file",
|
||||
"path": "/etc/systemd/system/mesh-power-after-wake.service",
|
||||
"mode": "0644",
|
||||
"template": "templates/systemd/system/mesh-power-after-wake.service"
|
||||
},
|
||||
{
|
||||
"id": "supply-unit",
|
||||
"type": "file",
|
||||
"path": "/etc/systemd/system/mesh-power-supply.service",
|
||||
"mode": "0644",
|
||||
"template": "templates/systemd/system/mesh-power-supply.service"
|
||||
},
|
||||
{
|
||||
"id": "sleep-drop-ins",
|
||||
"type": "directory",
|
||||
"path": "/etc/systemd/system/sleep.target.d",
|
||||
"mode": "0755",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "sleep-wants",
|
||||
"type": "file",
|
||||
"path": "/etc/systemd/system/sleep.target.d/mesh-power.conf",
|
||||
"mode": "0644",
|
||||
"template": "templates/systemd/system/sleep.target.d/mesh-power.conf"
|
||||
},
|
||||
{
|
||||
"id": "suspend-drop-ins",
|
||||
"type": "directory",
|
||||
"path": "/etc/systemd/system/suspend.target.d",
|
||||
"mode": "0755",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "suspend-wants",
|
||||
"type": "file",
|
||||
"path": "/etc/systemd/system/suspend.target.d/mesh-power.conf",
|
||||
"mode": "0644",
|
||||
"template": "templates/systemd/system/suspend.target.d/mesh-power.conf"
|
||||
},
|
||||
{
|
||||
"id": "hibernate-drop-ins",
|
||||
"type": "directory",
|
||||
"path": "/etc/systemd/system/hibernate.target.d",
|
||||
"mode": "0755",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "hibernate-wants",
|
||||
"type": "file",
|
||||
"path": "/etc/systemd/system/hibernate.target.d/mesh-power.conf",
|
||||
"mode": "0644",
|
||||
"template": "templates/systemd/system/hibernate.target.d/mesh-power.conf"
|
||||
},
|
||||
{
|
||||
"id": "hybrid-sleep-drop-ins",
|
||||
"type": "directory",
|
||||
"path": "/etc/systemd/system/hybrid-sleep.target.d",
|
||||
"mode": "0755",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "hybrid-sleep-wants",
|
||||
"type": "file",
|
||||
"path": "/etc/systemd/system/hybrid-sleep.target.d/mesh-power.conf",
|
||||
"mode": "0644",
|
||||
"template": "templates/systemd/system/hybrid-sleep.target.d/mesh-power.conf"
|
||||
},
|
||||
{
|
||||
"id": "suspend-then-hibernate-drop-ins",
|
||||
"type": "directory",
|
||||
"path": "/etc/systemd/system/suspend-then-hibernate.target.d",
|
||||
"mode": "0755",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "suspend-then-hibernate-wants",
|
||||
"type": "file",
|
||||
"path": "/etc/systemd/system/suspend-then-hibernate.target.d/mesh-power.conf",
|
||||
"mode": "0644",
|
||||
"template": "templates/systemd/system/suspend-then-hibernate.target.d/mesh-power.conf"
|
||||
},
|
||||
{
|
||||
"id": "udev-rule",
|
||||
"type": "file",
|
||||
"path": "/etc/udev/rules.d/90-mesh-power.rules",
|
||||
"mode": "0644",
|
||||
"template": "templates/udev/rules.d/90-mesh-power.rules"
|
||||
},
|
||||
{
|
||||
"id": "after-boot",
|
||||
"type": "service",
|
||||
"unit": "mesh-power-after-boot.service",
|
||||
"state": "running",
|
||||
"boot": "enabled"
|
||||
},
|
||||
{
|
||||
"id": "before-shutdown",
|
||||
"type": "service",
|
||||
"unit": "mesh-power-before-shutdown.service",
|
||||
"state": "running",
|
||||
"boot": "enabled"
|
||||
},
|
||||
{
|
||||
"id": "draw-dir",
|
||||
"type": "directory",
|
||||
"path": "/run/mesh-power",
|
||||
"mode": "0755",
|
||||
"unknown": "program"
|
||||
},
|
||||
{
|
||||
"id": "draw",
|
||||
"type": "process",
|
||||
"name": "mesh-power-draw",
|
||||
"artifact": "tools-go",
|
||||
"run": [
|
||||
"./power",
|
||||
"draw"
|
||||
],
|
||||
"health": {
|
||||
"kind": "unit"
|
||||
}
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "tools-go",
|
||||
"kind": "bundle",
|
||||
"language": "go",
|
||||
"system": "arch",
|
||||
"from": "cmd/power",
|
||||
"binary": "power",
|
||||
"loads": [
|
||||
"power"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "scripts",
|
||||
"kind": "archive",
|
||||
"from": "files"
|
||||
},
|
||||
{
|
||||
"name": "templates",
|
||||
"kind": "archive",
|
||||
"from": "templates"
|
||||
}
|
||||
]
|
||||
},
|
||||
"items": [
|
||||
{
|
||||
"collection": "contribution:node-bar:block",
|
||||
"name": "battery",
|
||||
"if-capability": "battery",
|
||||
"attributes": {
|
||||
"bar": "bottom",
|
||||
"place": "status",
|
||||
"order": "40"
|
||||
},
|
||||
"template": "templates/bar-battery"
|
||||
},
|
||||
{
|
||||
"collection": "contribution:node-bar:block",
|
||||
"name": "power-draw",
|
||||
"if-capability": "power-meter",
|
||||
"attributes": {
|
||||
"bar": "bottom",
|
||||
"place": "status",
|
||||
"order": "45"
|
||||
},
|
||||
"template": "templates/bar-power-draw"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
{
|
||||
"module": "powerlevel10k",
|
||||
"version": "1",
|
||||
"moved": true,
|
||||
"resources": [
|
||||
{
|
||||
"id": "theme",
|
||||
"type": "archive",
|
||||
"path": "${machine:account-home}/.local/share/powerlevel10k",
|
||||
"owner": "${machine:account}",
|
||||
"artifact": "theme",
|
||||
"unknown": "move-out",
|
||||
"knows": ["powerlevel9k.zsh-theme.zwc", "powerlevel10k.zsh-theme.zwc", "internal/p10k.zsh.zwc", "internal/icons.zsh.zwc", "internal/configure.zsh.zwc", "internal/worker.zsh.zwc", "internal/parser.zsh.zwc", "gitstatus/gitstatus.plugin.zsh.zwc", "gitstatus/install.zwc"]
|
||||
},
|
||||
{
|
||||
"id": "configuration",
|
||||
"type": "archive",
|
||||
"path": "${machine:account-home}/.config/powerlevel10k",
|
||||
"owner": "${machine:account}",
|
||||
"artifact": "configuration",
|
||||
"unknown": "move-out"
|
||||
}
|
||||
],
|
||||
"items": [
|
||||
{
|
||||
"collection": "shell:zsh:normal",
|
||||
"template": "files/zsh-normal"
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "theme",
|
||||
"kind": "archive",
|
||||
"from": "theme"
|
||||
},
|
||||
{
|
||||
"name": "configuration",
|
||||
"kind": "archive",
|
||||
"from": "config"
|
||||
},
|
||||
{
|
||||
"name": "files",
|
||||
"kind": "archive",
|
||||
"from": "files"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user