1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# SPDX-License-Identifier: PMPL-1.0-or-later
#
# Example selur-compose configuration — multi-service stack
#
# This is a concrete, fully-commented example showing a Rust API + Elixir
# worker + svalinn gateway deployment. Copy this file to compose.toml and
# customise for your project.
#
# Usage:
# cp compose.example.toml compose.toml
# # Edit service names, ports, images
# selur-compose up --detach
= "1.0"
# ============================================================================
# Services
# ============================================================================
# Rust API service — the primary HTTP/gRPC backend.
# Handles incoming requests, data storage, and core business logic.
[]
= "ghcr.io/hyperpolymath/myproject-api:latest.ctp"
# Map host port 8080 to container port 8080.
# Use ["[::]:8080:8080"] for explicit IPv6 binding.
= ["8080:8080"]
# Environment variables passed into the container at startup.
# These override defaults in the Containerfile ENV directives.
= {
RUST_LOG = "info", # Rust log level (trace, debug, info, warn, error)
= "[::]", # Listen on all interfaces (IPv4 + IPv6)
= "8080", # Internal container port
= "json", # Structured logging for selur/vordr
= "/data", # Persistent data directory (matches VOLUME)
}
# Bind-mount a named volume for persistent data.
# Format: "volume-name:/container/path"
= ["api-data:/data"]
# Restart policy: "always" ensures the service comes back after crashes.
# Other options: "no", "on-failure", "unless-stopped"
= "always"
# Health check: selur/Podman uses this to determine if the service is ready.
# The service must respond 2xx to this endpoint within the timeout.
= { = "curl -sf http://localhost:8080/health", = "30s", = "5s", = 3 }
# ---
# Elixir worker service — background processing, event handling, coordination.
# Runs as an OTP release with supervision trees for fault tolerance.
[]
= "ghcr.io/hyperpolymath/myproject-worker:latest.ctp"
# Separate port for the worker's admin/metrics endpoint.
= ["4000:4000"]
# The worker connects to the Rust API over the internal selur network.
# Service names resolve as hostnames within the compose network.
= {
API_URL = "http://rust-api:8080/api/v1", # Internal service discovery
= "prod", # Elixir release mode
= "json", # Match structured logging format
= "10", # DB connection pool size
}
# depends_on ensures the Rust API starts before the worker.
# Note: This only waits for the container to start, not for the health check.
# Use healthcheck + startup probes for true readiness gating.
= ["rust-api"]
= "always"
= { = "curl -sf http://localhost:4000/health", = "30s", = "5s", = 3 }
# ---
# Svalinn edge gateway — reverse proxy with policy enforcement.
# All external traffic enters through svalinn, which:
# 1. Terminates TLS (auto-provisioned certificates)
# 2. Validates JWT/OAuth2 authentication
# 3. Enforces rate limits from .gatekeeper.yaml
# 4. Routes requests to the appropriate backend service
# 5. Logs all write operations for audit
[]
= "ghcr.io/hyperpolymath/svalinn:latest.ctp"
# External-facing ports: HTTPS (443) and HTTP->HTTPS redirect (80).
= ["443:443", "80:80"]
= {
# Backend routing: svalinn proxies to internal services.
= "http://rust-api:8080",
= "http://elixir-worker:4000",
# Policy file: mounted from the svalinn-config volume.
= "/etc/svalinn/gatekeeper.yaml",
# Auto-provision TLS certificates (Let's Encrypt).
= "true",
}
# Mount .gatekeeper.yaml as read-only policy configuration.
= ["svalinn-config:/etc/svalinn:ro"]
# Svalinn starts last — it needs both backends to be running.
= ["rust-api", "elixir-worker"]
= "always"
= { = "curl -sf http://localhost:80/health", = "30s", = "5s", = 3 }
# ============================================================================
# Volumes
# ============================================================================
# Persistent storage for the Rust API (database files, indexes, WAL).
[]
= "local"
# Read-only policy configuration for svalinn gateway.
# Populate with: cp .gatekeeper.yaml /path/to/svalinn-config/gatekeeper.yaml
[]
= "local"
# ============================================================================
# Networks
# ============================================================================
# selur network: zero-copy IPC between services on the same host.
# When the selur driver is not installed, falls back to standard bridge
# networking (TCP over localhost). Performance is slightly lower but
# functionality is identical.
[]
= "selur"