Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions compose.coolify.agriculture.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ x-runtime: &runtime
depends_on:
audit-permissions: {condition: service_completed_successfully}

# Coolify matches a routed service against its exact compose key but resolves
# that key after rewriting "-" to "_", so a hyphenated name is stored where
# routing never reads it. Every service carrying solmara.lab.host therefore
# uses an underscore name.
services:
audit-permissions:
image: ${SOLMARA_AUTHORITY_PROVISIONER_IMAGE:?set the digest-pinned Solmara authority provisioner image}
Expand All @@ -25,23 +29,23 @@ services:
security_opt: [no-new-privileges:true]
volumes: [nagdi-relay-audit:/audit/nagdi-relay, nagdi-evidence-audit:/audit/nagdi-evidence]

nagdi-relay:
nagdi_relay:
<<: *runtime
image: ${REGISTRY_RELAY_IMAGE:?set the digest-pinned official Registry Stack Relay image}
command: [serve, --runtime, /etc/relay/nagdi/runtime.yaml]
environment: {SOLMARA_RELAY_AUDIT_KEY: "${NAGDI_RELAY_AUDIT_KEY:?required}", SOLMARA_RELAY_CURSOR_KEY: "${NAGDI_RELAY_CURSOR_KEY:?required}"}
volumes: [/data/solmara-authority-cells/nagdi-relay/runtime:/etc/relay/nagdi:ro, /data/solmara-authority-cells/nagdi-relay/source:/var/lib/relay/source:ro, nagdi-relay-audit:/var/lib/relay/audit]
labels: {solmara.lab.host: nagdi-relay-authority-cells.solmara.registrystack.org, solmara.rollout.slot: authority-cells, traefik.docker.network: "${COOLIFY_RESOURCE_UUID:?set by Coolify for every deployment}"}

nagdi-evidence:
nagdi_evidence:
<<: *runtime
image: ${SOLMARA_EVIDENCE_IMAGE:?set the digest-pinned official Registry Stack Evidence image}
command: [--runtime, /etc/registry-evidence/nagdi/runtime.yaml, serve]
volumes: [/data/solmara-authority-cells/nagdi-evidence/runtime:/etc/registry-evidence/nagdi:ro, /data/solmara-authority-cells/nagdi-evidence/secrets:/run/secrets/registry-evidence/nagdi:ro, /data/solmara-authority-cells/nagdi-evidence/transit:/run/registry-evidence/nagdi:ro, nagdi-evidence-audit:/var/lib/registry-evidence/nagdi/audit]
networks: {runtime: {ipv4_address: 172.29.5.26}}
depends_on:
audit-permissions: {condition: service_completed_successfully}
nagdi-relay: {condition: service_started}
nagdi_relay: {condition: service_started}
labels: {solmara.lab.host: "${SOLMARA_NAGDI_EVIDENCE_PUBLIC_HOST:-nagdi-evidence.solmara.registrystack.org}", solmara.rollout.slot: authority-cells, traefik.docker.network: "${COOLIFY_RESOURCE_UUID:?set by Coolify for every deployment}"}

volumes:
Expand Down
14 changes: 9 additions & 5 deletions compose.coolify.interior.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ x-runtime: &runtime
depends_on:
audit-permissions: {condition: service_completed_successfully}

# Coolify matches a routed service against its exact compose key but resolves
# that key after rewriting "-" to "_", so a hyphenated name is stored where
# routing never reads it. Every service carrying solmara.lab.host therefore
# uses an underscore name.
services:
audit-permissions:
image: ${SOLMARA_AUTHORITY_PROVISIONER_IMAGE:?set the digest-pinned Solmara authority provisioner image}
Expand All @@ -25,34 +29,34 @@ services:
security_opt: [no-new-privileges:true]
volumes: [cra-relay-audit:/audit/cra-relay, nia-relay-audit:/audit/nia-relay, cra-evidence-audit:/audit/cra-evidence, nia-evidence-audit:/audit/nia-evidence]

cra-relay:
cra_relay:
<<: *runtime
image: ${REGISTRY_RELAY_IMAGE:?set the digest-pinned official Registry Stack Relay image}
command: [serve, --runtime, /etc/relay/cra/runtime.yaml]
environment: {SOLMARA_RELAY_AUDIT_KEY: "${CRA_RELAY_AUDIT_KEY:?required}"}
volumes: [/data/solmara-authority-cells/cra-relay/runtime:/etc/relay/cra:ro, /data/solmara-authority-cells/cra-relay/source:/var/lib/relay/source:ro, cra-relay-audit:/var/lib/relay/audit]
labels: {solmara.lab.host: cra-relay-authority-cells.solmara.registrystack.org, solmara.rollout.slot: authority-cells, traefik.docker.network: "${COOLIFY_RESOURCE_UUID:?set by Coolify for every deployment}"}

nia-relay:
nia_relay:
<<: *runtime
image: ${REGISTRY_RELAY_IMAGE:?set the digest-pinned official Registry Stack Relay image}
command: [serve, --runtime, /etc/relay/nia/runtime.yaml]
environment: {SOLMARA_RELAY_AUDIT_KEY: "${NIA_RELAY_AUDIT_KEY:?required}"}
volumes: [/data/solmara-authority-cells/nia-relay/runtime:/etc/relay/nia:ro, /data/solmara-authority-cells/nia-relay/source:/var/lib/relay/source:ro, nia-relay-audit:/var/lib/relay/audit]
labels: {solmara.lab.host: nia-relay-authority-cells.solmara.registrystack.org, solmara.rollout.slot: authority-cells, traefik.docker.network: "${COOLIFY_RESOURCE_UUID:?set by Coolify for every deployment}"}

cra-evidence:
cra_evidence:
<<: *runtime
image: ${SOLMARA_EVIDENCE_IMAGE:?set the digest-pinned official Registry Stack Evidence image}
command: [--runtime, /etc/registry-evidence/cra/runtime.yaml, serve]
volumes: [/data/solmara-authority-cells/cra-evidence/runtime:/etc/registry-evidence/cra:ro, /data/solmara-authority-cells/cra-evidence/secrets:/run/secrets/registry-evidence/cra:ro, /data/solmara-authority-cells/cra-evidence/transit:/run/registry-evidence/cra:ro, /data/solmara-authority-cells/cra-evidence/extracts:/var/lib/registry-evidence/cra/extracts:ro, cra-evidence-audit:/var/lib/registry-evidence/cra/audit]
networks: {runtime: {ipv4_address: 172.29.2.21}}
depends_on:
audit-permissions: {condition: service_completed_successfully}
cra-relay: {condition: service_started}
cra_relay: {condition: service_started}
labels: {solmara.lab.host: "${SOLMARA_CRA_EVIDENCE_PUBLIC_HOST:-cra-evidence.solmara.registrystack.org}", solmara.rollout.slot: authority-cells, traefik.docker.network: "${COOLIFY_RESOURCE_UUID:?set by Coolify for every deployment}"}

nia-evidence:
nia_evidence:
<<: *runtime
image: ${SOLMARA_EVIDENCE_IMAGE:?set the digest-pinned official Registry Stack Evidence image}
command: [--runtime, /etc/registry-evidence/nia/runtime.yaml, serve]
Expand Down
10 changes: 7 additions & 3 deletions compose.coolify.labour-pensions.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ x-runtime: &runtime
depends_on:
audit-permissions: {condition: service_completed_successfully}

# Coolify matches a routed service against its exact compose key but resolves
# that key after rewriting "-" to "_", so a hyphenated name is stored where
# routing never reads it. Every service carrying solmara.lab.host therefore
# uses an underscore name.
services:
audit-permissions:
image: ${SOLMARA_AUTHORITY_PROVISIONER_IMAGE:?set the digest-pinned Solmara authority provisioner image}
Expand All @@ -25,23 +29,23 @@ services:
security_opt: [no-new-privileges:true]
volumes: [sipf-relay-audit:/audit/sipf-relay, sipf-evidence-audit:/audit/sipf-evidence]

sipf-relay:
sipf_relay:
<<: *runtime
image: ${REGISTRY_RELAY_IMAGE:?set the digest-pinned official Registry Stack Relay image}
command: [serve, --runtime, /etc/relay/sipf/runtime.yaml]
environment: {SOLMARA_RELAY_AUDIT_KEY: "${SIPF_RELAY_AUDIT_KEY:?required}", SOLMARA_RELAY_CURSOR_KEY: "${SIPF_RELAY_CURSOR_KEY:?required}"}
volumes: [/data/solmara-authority-cells/sipf-relay/runtime:/etc/relay/sipf:ro, /data/solmara-authority-cells/sipf-relay/source:/var/lib/relay/source:ro, sipf-relay-audit:/var/lib/relay/audit]
labels: {solmara.lab.host: sipf-relay-authority-cells.solmara.registrystack.org, solmara.rollout.slot: authority-cells, traefik.docker.network: "${COOLIFY_RESOURCE_UUID:?set by Coolify for every deployment}"}

sipf-evidence:
sipf_evidence:
<<: *runtime
image: ${SOLMARA_EVIDENCE_IMAGE:?set the digest-pinned official Registry Stack Evidence image}
command: [--runtime, /etc/registry-evidence/sipf/runtime.yaml, serve]
volumes: [/data/solmara-authority-cells/sipf-evidence/runtime:/etc/registry-evidence/sipf:ro, /data/solmara-authority-cells/sipf-evidence/secrets:/run/secrets/registry-evidence/sipf:ro, /data/solmara-authority-cells/sipf-evidence/transit:/run/registry-evidence/sipf:ro, sipf-evidence-audit:/var/lib/registry-evidence/sipf/audit]
networks: {runtime: {ipv4_address: 172.29.4.25}}
depends_on:
audit-permissions: {condition: service_completed_successfully}
sipf-relay: {condition: service_started}
sipf_relay: {condition: service_started}
labels: {solmara.lab.host: "${SOLMARA_SIPF_EVIDENCE_PUBLIC_HOST:-sipf-evidence.solmara.registrystack.org}", solmara.rollout.slot: authority-cells, traefik.docker.network: "${COOLIFY_RESOURCE_UUID:?set by Coolify for every deployment}"}

volumes:
Expand Down
12 changes: 8 additions & 4 deletions compose.coolify.social-development.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ x-runtime: &runtime
depends_on:
audit-permissions: {condition: service_completed_successfully}

# Coolify matches a routed service against its exact compose key but resolves
# that key after rewriting "-" to "_", so a hyphenated name is stored where
# routing never reads it. Every service carrying solmara.lab.host therefore
# uses an underscore name.
services:
audit-permissions:
image: ${SOLMARA_AUTHORITY_PROVISIONER_IMAGE:?set the digest-pinned Solmara authority provisioner image}
Expand All @@ -25,31 +29,31 @@ services:
security_opt: [no-new-privileges:true]
volumes: [mosd-relay-audit:/audit/mosd-relay, sro-evidence-audit:/audit/sro-evidence, mosd-evidence-audit:/audit/mosd-evidence]

mosd-relay:
mosd_relay:
<<: *runtime
image: ${REGISTRY_RELAY_IMAGE:?set the digest-pinned official Registry Stack Relay image}
command: [serve, --runtime, /etc/relay/mosd/runtime.yaml]
environment: {SOLMARA_RELAY_AUDIT_KEY: "${MOSD_RELAY_AUDIT_KEY:?required}"}
volumes: [/data/solmara-authority-cells/mosd-relay/runtime:/etc/relay/mosd:ro, /data/solmara-authority-cells/mosd-relay/source:/var/lib/relay/source:ro, mosd-relay-audit:/var/lib/relay/audit]
labels: {solmara.lab.host: mosd-programme-relay-authority-cells.solmara.registrystack.org, solmara.rollout.slot: authority-cells, traefik.docker.network: "${COOLIFY_RESOURCE_UUID:?set by Coolify for every deployment}"}

sro-evidence:
sro_evidence:
<<: *runtime
image: ${SOLMARA_EVIDENCE_IMAGE:?set the digest-pinned official Registry Stack Evidence image}
command: [--runtime, /etc/registry-evidence/sro/runtime.yaml, serve]
volumes: [/data/solmara-authority-cells/sro-evidence/runtime:/etc/registry-evidence/sro:ro, /data/solmara-authority-cells/sro-evidence/secrets:/run/secrets/registry-evidence/sro:ro, /data/solmara-authority-cells/sro-evidence/transit:/run/registry-evidence/sro:ro, /data/solmara-authority-cells/sro-evidence/extracts:/var/lib/registry-evidence/sro/extracts:ro, sro-evidence-audit:/var/lib/registry-evidence/sro/audit]
networks: {runtime: {ipv4_address: 172.29.3.23}}
labels: {solmara.lab.host: "${SOLMARA_SRO_EVIDENCE_PUBLIC_HOST:-sro-evidence.solmara.registrystack.org}", solmara.rollout.slot: authority-cells, traefik.docker.network: "${COOLIFY_RESOURCE_UUID:?set by Coolify for every deployment}"}

mosd-programme-evidence:
mosd_programme_evidence:
<<: *runtime
image: ${SOLMARA_EVIDENCE_IMAGE:?set the digest-pinned official Registry Stack Evidence image}
command: [--runtime, /etc/registry-evidence/mosd-programme/runtime.yaml, serve]
volumes: [/data/solmara-authority-cells/mosd-evidence/runtime:/etc/registry-evidence/mosd-programme:ro, /data/solmara-authority-cells/mosd-evidence/secrets:/run/secrets/registry-evidence/mosd-programme:ro, /data/solmara-authority-cells/mosd-evidence/transit:/run/registry-evidence/mosd-programme:ro, mosd-evidence-audit:/var/lib/registry-evidence/mosd-programme/audit]
networks: {runtime: {ipv4_address: 172.29.3.24}}
depends_on:
audit-permissions: {condition: service_completed_successfully}
mosd-relay: {condition: service_started}
mosd_relay: {condition: service_started}
labels: {solmara.lab.host: "${SOLMARA_MOSD_PROGRAMME_EVIDENCE_PUBLIC_HOST:-mosd-programme-evidence.solmara.registrystack.org}", solmara.rollout.slot: authority-cells, traefik.docker.network: "${COOLIFY_RESOURCE_UUID:?set by Coolify for every deployment}"}

volumes:
Expand Down
10 changes: 7 additions & 3 deletions compose.coolify.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ x-hosted-evidence-environment: &hosted-evidence
SOLMARA_SIPF_EVIDENCE_URL: ${SOLMARA_SIPF_EVIDENCE_PUBLIC_BASE_URL:-https://sipf-evidence.solmara.registrystack.org}
SOLMARA_NAGDI_EVIDENCE_URL: ${SOLMARA_NAGDI_EVIDENCE_PUBLIC_BASE_URL:-https://nagdi-evidence.solmara.registrystack.org}
CHILD_BENEFIT_FEDERATOR_TOKEN: ${CHILD_BENEFIT_FEDERATOR_TOKEN:?required}
# Coolify matches a routed service against its exact compose key but resolves
# that key after rewriting "-" to "_", so a hyphenated name is stored where
# routing never reads it. Every service carrying solmara.lab.host therefore
# uses an underscore name.
services:
audit-permissions:
image: ${SOLMARA_AUTHORITY_PROVISIONER_IMAGE:?set the digest-pinned Solmara authority provisioner image}
Expand Down Expand Up @@ -55,14 +59,14 @@ services:
security_opt: [no-new-privileges:true]
depends_on:
mint: {condition: service_started}
static-metadata:
static_metadata:
image: ${SOLMARA_STATIC_METADATA_IMAGE:?set a digest-pinned Solmara static metadata image}
# The image only layers the published metadata onto a stock Python base and
# sets no CMD of its own, so the server has to be named here.
command: ["python", "-m", "http.server", "8080", "--bind", "0.0.0.0", "--directory", "/srv/static"]
restart: unless-stopped
labels: {solmara.lab.host: "${SOLMARA_METADATA_PUBLIC_HOST:-metadata.solmara.registrystack.org}"}
scenario-runner:
scenario_runner:
image: ${SOLMARA_SCENARIO_RUNNER_IMAGE:?set a digest-pinned Solmara scenario runner image}
restart: unless-stopped
environment:
Expand All @@ -76,7 +80,7 @@ services:
depends_on:
mint-readiness: {condition: service_completed_successfully}
labels: {solmara.lab.host: "${SOLMARA_SCENARIO_RUNNER_PUBLIC_HOST:-scenarios.solmara.registrystack.org}"}
child-benefit-federator:
child_benefit_federator:
image: ${SOLMARA_SCENARIO_RUNNER_IMAGE:?set a digest-pinned Solmara scenario runner image}
command: ["python", "scenario-runner/child_benefit_federator.py"]
restart: unless-stopped
Expand Down
6 changes: 6 additions & 0 deletions docs/hosted-deployment.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,12 @@ which resolves to the Coolify-managed network the proxy is on. A routed service
that joins the ingress network alone has no choice to remove and carries no such
label.

Coolify accepts a routed service only under its exact Compose key but resolves
that key after rewriting `-` to `_`. A hyphenated routed service is therefore
recorded where routing never reads it and answers no public route. Every service
that carries `solmara.lab.host` uses an underscore name so both halves agree.
Volume keys, host paths, label values, and public hostnames are unaffected.

`compose.coolify.provision.yaml` is a dedicated operator-only application. It
runs only the one-shot target provisioners and is the sole writer of every
shared path except the seven Transit sockets.
Expand Down
43 changes: 30 additions & 13 deletions scripts/test_hosted_evidence_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,56 +14,56 @@
TEST_IMAGE = "example.invalid/solmara@sha256:" + "a" * 64

EVIDENCE_ROUTES = {
"cra-evidence": (
"cra_evidence": (
ROOT / "compose.coolify.interior.yaml",
"SOLMARA_CRA_EVIDENCE_PUBLIC_HOST",
"cra-evidence.solmara.registrystack.org",
),
"nia-evidence": (
"nia_evidence": (
ROOT / "compose.coolify.interior.yaml",
"SOLMARA_NIA_EVIDENCE_PUBLIC_HOST",
"nia-evidence.solmara.registrystack.org",
),
"sro-evidence": (
"sro_evidence": (
ROOT / "compose.coolify.social-development.yaml",
"SOLMARA_SRO_EVIDENCE_PUBLIC_HOST",
"sro-evidence.solmara.registrystack.org",
),
"mosd-programme-evidence": (
"mosd_programme_evidence": (
ROOT / "compose.coolify.social-development.yaml",
"SOLMARA_MOSD_PROGRAMME_EVIDENCE_PUBLIC_HOST",
"mosd-programme-evidence.solmara.registrystack.org",
),
"sipf-evidence": (
"sipf_evidence": (
ROOT / "compose.coolify.labour-pensions.yaml",
"SOLMARA_SIPF_EVIDENCE_PUBLIC_HOST",
"sipf-evidence.solmara.registrystack.org",
),
"nagdi-evidence": (
"nagdi_evidence": (
ROOT / "compose.coolify.agriculture.yaml",
"SOLMARA_NAGDI_EVIDENCE_PUBLIC_HOST",
"nagdi-evidence.solmara.registrystack.org",
),
}

RELAY_ROUTES = {
"cra-relay": (
"cra_relay": (
ROOT / "compose.coolify.interior.yaml",
"cra-relay-authority-cells.solmara.registrystack.org",
),
"nia-relay": (
"nia_relay": (
ROOT / "compose.coolify.interior.yaml",
"nia-relay-authority-cells.solmara.registrystack.org",
),
"mosd-relay": (
"mosd_relay": (
ROOT / "compose.coolify.social-development.yaml",
"mosd-programme-relay-authority-cells.solmara.registrystack.org",
),
"sipf-relay": (
"sipf_relay": (
ROOT / "compose.coolify.labour-pensions.yaml",
"sipf-relay-authority-cells.solmara.registrystack.org",
),
"nagdi-relay": (
"nagdi_relay": (
ROOT / "compose.coolify.agriculture.yaml",
"nagdi-relay-authority-cells.solmara.registrystack.org",
),
Expand Down Expand Up @@ -139,9 +139,11 @@ def test_canonical_evidence_defaults_render_across_apps(self) -> None:
)

def test_staging_evidence_hosts_render_without_changing_relay_routes(self) -> None:
# The compose key is not a hostname label, so the staging host comes
# from the canonical route rather than from the service name.
overrides = {
variable: f"{service}.staging.example.org"
for service, (_, variable, _) in EVIDENCE_ROUTES.items()
variable: f"{canonical_host.split('.', 1)[0]}.staging.example.org"
for _, variable, canonical_host in EVIDENCE_ROUTES.values()
}
rendered = {
path: render_compose(path, overrides)
Expand All @@ -162,5 +164,20 @@ def test_staging_evidence_hosts_render_without_changing_relay_routes(self) -> No
)


class RoutedServiceNameTests(unittest.TestCase):
def test_every_routed_service_carries_a_coolify_resolvable_name(self) -> None:
"""Coolify accepts a routed service only under its exact compose key but
resolves it after rewriting "-" to "_", so a hyphenated key is stored
where routing never reads it and the service answers no public route."""
for path in sorted(ROOT.glob("compose.coolify*.yaml")):
compose = yaml.safe_load(path.read_text(encoding="utf-8"))
for name, service in (compose.get("services") or {}).items():
labels = service.get("labels") or {}
if "solmara.lab.host" not in labels:
continue
with self.subTest(compose=path.name, service=name):
self.assertNotIn("-", name)


if __name__ == "__main__":
unittest.main()
4 changes: 2 additions & 2 deletions scripts/test_hosted_home_topology.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ def test_static_metadata_serves_the_published_directory(self) -> None:
# interpreter, so without an explicit command the container exits 0 at
# once and restarts forever instead of serving.
compose = yaml.safe_load(COMPOSE_PATH.read_text(encoding="utf-8"))
command = compose["services"]["static-metadata"].get("command")
command = compose["services"]["static_metadata"].get("command")

self.assertIsNotNone(command, "static-metadata must name its server command")
self.assertIsNotNone(command, "static_metadata must name its server command")
self.assertEqual(
command,
["python", "-m", "http.server", "8080", "--bind", "0.0.0.0", "--directory", "/srv/static"],
Expand Down
Loading
Loading