Collimo 0.1.0

This commit is contained in:
Collimo release committed 2026-10-22 10:28:55 -07:00
1 parent 078ce1a589
commit d31f29d767
10 files changed
+633 -198

No files matched your search

+65 -29
View File
@@ -1,7 +1,7 @@
# Single compose file for both paths.
#
# Ferrule runs from its published image, a built binary: no source reaches
# the Docker host. FERRULE_VERSION picks the release and is required.
# Collimo runs from its published image, a built binary: no source reaches
# the Docker host. COLLIMO_VERSION picks the release.
# docker-compose.build.yml, added beside this file, builds from source
# instead, for development.
#
@@ -18,16 +18,18 @@
services:
telemetry:
# The published image, at the release FERRULE_VERSION names: 0.9.0, or
# qa for what is under test. Required, so a stack never drifts onto a
# version nobody chose, and never latest. FERRULE_IMAGE is the registry
# path, one line to change when it moves. Its own container names keep
# it apart from an earlier stack of this project on the same host.
image: ${FERRULE_IMAGE:-ghcr.io/ferrulehq/ferrule}:${FERRULE_VERSION:?set FERRULE_VERSION to the release to run, such as 0.9.0}
# The published image, at the release COLLIMO_VERSION names: 0.9.0, or
# qa for what is under test, and never latest. COLLIMO_IMAGE is the
# registry path, one line to change when it moves. Its own container
# names keep it apart from an earlier stack of this project on the same
# host.
# Each release writes its own version and registry in as the defaults,
# so a blank stack runs it.
image: ${COLLIMO_IMAGE:-ghcr.io/collimohq/collimo}:${COLLIMO_VERSION:-0.1.0}
# Ask the registry on every deploy. A fixed release costs one quick
# request; qa moves, and this is how a redeploy picks it up.
pull_policy: always
container_name: ferrule
container_name: collimo
restart: unless-stopped
environment:
# false turns off Network, Protect, WAN and the probe, for a stack that
@@ -39,6 +41,7 @@ services:
UNIFI_USERNAME: ${UNIFI_USERNAME:-}
UNIFI_PASSWORD: ${UNIFI_PASSWORD:-}
UNIFI_SITE: ${UNIFI_SITE:-default}
PORT_SLEEPS: ${PORT_SLEEPS:-}
# Protect on separate hardware (a UNVR) needs its own host and its own
# credentials — the gateway's do not work on it. Leave these unset when
# one console runs both applications.
@@ -69,7 +72,7 @@ services:
# The outage archive. Fixed path because it is a named volume, not a
# host path — Portainer stacks cannot resolve relative host paths, and a
# named volume needs none.
LEDGER_PATH: /var/lib/ferrule/ledger.jsonl
LEDGER_PATH: /var/lib/collimo/ledger.jsonl
LEDGER_RETENTION: ${LEDGER_RETENTION:-8760h}
# Demarcation probe. Unset PROBE_TARGETS leaves it off. Point
@@ -100,6 +103,11 @@ services:
SOURCE_8: ${SOURCE_8:-}
SOURCE_8_SECRET: ${SOURCE_8_SECRET:-}
# Up-checks: ping, HTTP or a TCP port for anything with an address,
# entries separated by ; such as
# CHECKS=ping 192.168.1.20 name=printer; http https://nas.lab:5001 name=nas
CHECKS: ${CHECKS:-}
# Sign-in. Off until ADMIN_PASSWORD (free) or OIDC_* / LDAP_* (paid)
# are set. See PORTAINER.md.
ADMIN_USERNAME: ${ADMIN_USERNAME:-admin}
@@ -127,7 +135,15 @@ services:
# The license key, when there is one. Without it every install runs a
# 30-day trial of the paid features, then carries on as Community.
FERRULE_LICENSE: ${FERRULE_LICENSE:-}
COLLIMO_LICENSE: ${COLLIMO_LICENSE:-}
# Several sites, for an MSP (ADR-0044): a collector at each client
# site reports to one hub, calling out only. Unset is one site on its
# own.
COLLIMO_ROLE: ${COLLIMO_ROLE:-standalone}
HUB_URL: ${HUB_URL:-}
HUB_ENROL: ${HUB_ENROL:-}
HUB_LINK: ${HUB_LINK:-normal}
# Notification channels. Each is off until its variables are set; any
# number can be on. Slack, Teams, PagerDuty and the webhook are paid.
@@ -135,6 +151,10 @@ services:
# force; see PORTAINER.md for what each variable means.
GOTIFY_URL: ${GOTIFY_URL:-}
GOTIFY_TOKEN: ${GOTIFY_TOKEN:-}
# With the bundled Gotify and no token, Collimo makes a shared
# collimo-alerts account and its own app, using the admin password.
GOTIFY_ALERTS_PASSWORD: ${GOTIFY_ALERTS_PASSWORD:-}
GOTIFY_ADMIN_PASSWORD: ${GOTIFY_ADMIN_PASSWORD:-}
NTFY_URL: ${NTFY_URL:-}
NTFY_TOKEN: ${NTFY_TOKEN:-}
PUSHOVER_TOKEN: ${PUSHOVER_TOKEN:-}
@@ -147,6 +167,8 @@ services:
SMTP_PASSWORD: ${SMTP_PASSWORD:-}
SMTP_FROM: ${SMTP_FROM:-}
SMTP_TO: ${SMTP_TO:-}
# open or all when SMTP_TO is a help desk's mailbox: one ticket per alert
SMTP_TICKETS: ${SMTP_TICKETS:-}
SLACK_WEBHOOK_URL: ${SLACK_WEBHOOK_URL:-}
TEAMS_WEBHOOK_URL: ${TEAMS_WEBHOOK_URL:-}
PAGERDUTY_ROUTING_KEY: ${PAGERDUTY_ROUTING_KEY:-}
@@ -189,10 +211,24 @@ services:
INVENTORY_AT: ${INVENTORY_AT:-02:30}
# Days of inventory history: a year by default; 2557 keeps seven years.
INVENTORY_KEEP: ${INVENTORY_KEEP:-365}
# Capacity planning (paid): forecast thresholds in %, runway alert
# days, allocation limits, and hosts kept spare per cluster.
CAPACITY_THRESHOLDS: ${CAPACITY_THRESHOLDS:-cpu=80,mem=80,disk=85,pool=85}
CAPACITY_RUNWAY: ${CAPACITY_RUNWAY:-warn=90,bad=30}
CAPACITY_RATIOS: ${CAPACITY_RATIOS:-vcpu=4,vmem=1,disk=1.5}
CAPACITY_VM_SIZE: ${CAPACITY_VM_SIZE:-vcpu=4,mem=16,disk=100}
CAPACITY_HA: ${CAPACITY_HA:-}
# The monthly capacity summary: who gets it, whose name is on it, and
# the host "What to buy" plans in (empty: each cluster's largest).
CAPACITY_SUMMARY_TO: ${CAPACITY_SUMMARY_TO:-}
CAPACITY_SUMMARY_BY: ${CAPACITY_SUMMARY_BY:-}
CAPACITY_HOST: ${CAPACITY_HOST:-}
# Rated endurance per drive model, for disk wear: CT1000P310SSD8=220
CAPACITY_DISK_TBW: ${CAPACITY_DISK_TBW:-}
# A copy of every inventory in PostgreSQL, for Grafana and Power BI
# (paid). For the stack's own, add "postgres" to COMPOSE_PROFILES and
# set INVENTORY_DB_PASSWORD; for one you run, set INVENTORY_DB_URL. The
# reader password makes a read-only ferrule_reader role for reports.
# reader password makes a read-only collimo_reader role for reports.
INVENTORY_DB_URL: ${INVENTORY_DB_URL:-}
INVENTORY_DB_PASSWORD: ${INVENTORY_DB_PASSWORD:-}
INVENTORY_DB_READER_PASSWORD: ${INVENTORY_DB_READER_PASSWORD:-}
@@ -202,7 +238,7 @@ services:
# that mounts an NFS or SMB share (docker-compose.backup-nfs.yml,
# docker-compose.backup-smb.yml); BACKUP_S3_* is object storage, paid.
# See PORTAINER.md.
BACKUP_NAME: ${BACKUP_NAME:-ferrule}
BACKUP_NAME: ${BACKUP_NAME:-collimo}
BACKUP_KEY: ${BACKUP_KEY:-}
BACKUP_AT: ${BACKUP_AT:-03:30}
BACKUP_HISTORY: ${BACKUP_HISTORY:-true}
@@ -213,7 +249,7 @@ services:
BACKUP_S3_ENDPOINT: ${BACKUP_S3_ENDPOINT:-}
BACKUP_S3_REGION: ${BACKUP_S3_REGION:-us-east-1}
BACKUP_S3_BUCKET: ${BACKUP_S3_BUCKET:-}
BACKUP_S3_PREFIX: ${BACKUP_S3_PREFIX:-ferrule}
BACKUP_S3_PREFIX: ${BACKUP_S3_PREFIX:-collimo}
BACKUP_S3_ACCESS_KEY: ${BACKUP_S3_ACCESS_KEY:-}
BACKUP_S3_SECRET_KEY: ${BACKUP_S3_SECRET_KEY:-}
DASHBOARD_URL: ${DASHBOARD_URL:-}
@@ -230,8 +266,8 @@ services:
# Stack environment can start from what is set. Never a secret.
COMPOSE_PROFILES: ${COMPOSE_PROFILES:-}
WEB_PORT: ${WEB_PORT:-8090}
FERRULE_IMAGE: ${FERRULE_IMAGE:-ghcr.io/ferrulehq/ferrule}
FERRULE_VERSION: ${FERRULE_VERSION:-}
COLLIMO_IMAGE: ${COLLIMO_IMAGE:-ghcr.io/collimohq/collimo}
COLLIMO_VERSION: ${COLLIMO_VERSION:-}
RETENTION: ${RETENTION:-13w}
GOTIFY_ADMIN_USER: ${GOTIFY_ADMIN_USER:-admin}
GOTIFY_PORT: ${GOTIFY_PORT:-8091}
@@ -249,7 +285,7 @@ services:
# resolve. The root filesystem stays read-only; this is the one writable
# mount, and it is what makes the outage archive outlive the controller
# 21-hour window.
- ledger-data:/var/lib/ferrule
- ledger-data:/var/lib/collimo
sysctls:
# Lets the container open an unprivileged ICMP datagram socket for the
# demarcation probe, with cap_drop: ALL still in force. The range must
@@ -260,7 +296,7 @@ services:
- victoria-metrics
healthcheck:
# The image is scratch — no shell, no curl. The binary probes itself.
test: ["CMD", "/ferrule", "-healthcheck"]
test: ["CMD", "/collimo", "-healthcheck"]
interval: 30s
timeout: 5s
retries: 3
@@ -281,7 +317,7 @@ services:
victoria-metrics:
# Pin to a release tag once you have one you are happy with.
image: victoriametrics/victoria-metrics:latest
container_name: ferrule-victoria-metrics
container_name: collimo-victoria-metrics
restart: unless-stopped
command:
- "-storageDataPath=/victoria-metrics-data"
@@ -318,7 +354,7 @@ services:
gotify:
profiles: ["gotify"]
image: gotify/server:latest
container_name: ferrule-gotify
container_name: collimo-gotify
restart: unless-stopped
environment:
GOTIFY_DEFAULTUSER_NAME: ${GOTIFY_ADMIN_USER:-admin}
@@ -339,7 +375,7 @@ services:
igotify:
profiles: ["igotify"]
image: ghcr.io/androidseb25/igotify-notification-assist:latest
container_name: ferrule-igotify
container_name: collimo-igotify
hostname: igotify
restart: unless-stopped
pull_policy: always
@@ -360,23 +396,23 @@ services:
# ---- Optional: PostgreSQL, for the inventory's database copy ----------
#
# Starts only with "postgres" in COMPOSE_PROFILES. Set
# INVENTORY_DB_PASSWORD and the collector finds it at ferrule-postgres on
# INVENTORY_DB_PASSWORD and the collector finds it at collimo-postgres on
# its own; nothing else to set. It holds a copy: the inventory files on
# ledger-data stay the master and travel with the backups, and the copy is
# rebuilt from them, so this volume needs no backup of its own.
#
# Grafana and Power BI connect with their own PostgreSQL connectors, as
# ferrule_reader with INVENTORY_DB_READER_PASSWORD, never as the writer.
# collimo_reader with INVENTORY_DB_READER_PASSWORD, never as the writer.
# The port listens on the Docker host's loopback only; set
# INVENTORY_DB_BIND=0.0.0.0 for a reporting tool on another machine.
postgres:
profiles: ["postgres"]
image: postgres:18-alpine
container_name: ferrule-postgres
container_name: collimo-postgres
restart: unless-stopped
environment:
POSTGRES_USER: ferrule
POSTGRES_DB: ferrule
POSTGRES_USER: collimo
POSTGRES_DB: collimo
# The image refuses to start without one, so a missing password shows
# here rather than as an open database.
POSTGRES_PASSWORD: ${INVENTORY_DB_PASSWORD:-}
@@ -387,7 +423,7 @@ services:
ports:
- "${INVENTORY_DB_BIND:-127.0.0.1}:${INVENTORY_DB_PORT:-5432}:5432"
# Postgres sets POSTGRES_PASSWORD only when its volume is first made, so
# changing INVENTORY_DB_PASSWORD later left Ferrule refused. The first
# changing INVENTORY_DB_PASSWORD later left Collimo refused. The first
# check in each container sets the password from the environment, over
# the container's own socket, which needs none, and marks /tmp so it is
# done once: a redeploy with a new password is a new container with an
@@ -396,7 +432,7 @@ services:
# password reaches SQL as a psql variable, so no quote in it can break
# the statement.
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ferrule -d ferrule && { [ -f /tmp/ferrule-password-set ] || { echo \"ALTER ROLE ferrule PASSWORD :'pw';\" | psql -U ferrule -d ferrule -q -v ON_ERROR_STOP=1 -v pw=\"$$POSTGRES_PASSWORD\" >/dev/null && touch /tmp/ferrule-password-set; }; }"]
test: ["CMD-SHELL", "pg_isready -U collimo -d collimo && { [ -f /tmp/collimo-password-set ] || { echo \"ALTER ROLE collimo PASSWORD :'pw';\" | psql -U collimo -d collimo -q -v ON_ERROR_STOP=1 -v pw=\"$$POSTGRES_PASSWORD\" >/dev/null && touch /tmp/collimo-password-set; }; }"]
interval: 30s
timeout: 5s
retries: 3
@@ -411,7 +447,7 @@ services:
apprise:
profiles: ["apprise"]
image: caronc/apprise:latest
container_name: ferrule-apprise
container_name: collimo-apprise
hostname: apprise
restart: unless-stopped
pull_policy: always