Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
108 commits
Select commit Hold shift + click to select a range
f6836a6
feat(engine): report signed cloud node heartbeats
Agata-Proxima Nov 10, 2026
f60bfdf
docs(engine): add customer Docker enrollment path
Agata-Proxima Nov 10, 2026
1b44e2a
feat(engine): add customer-managed compose deployment
Agata-Proxima Nov 10, 2026
30d7f02
ci(engine): publish multi-arch customer container on version tags
Agata-Proxima Nov 10, 2026
8113d24
fix(engine): make customer compose build from downloaded source
Agata-Proxima Nov 10, 2026
2b8e418
docs(engine): link customer one-command installation
Agata-Proxima Nov 10, 2026
d00e522
docs(engine): document signed Fleet heartbeat behavior
Agata-Proxima Nov 10, 2026
88c5b87
test(engine): cover signed heartbeat payload integrity
Agata-Proxima Nov 10, 2026
1517909
fix(engine): encode heartbeat canonical fields correctly
Agata-Proxima Nov 10, 2026
b0ddf0a
fix(engine): use newline separators in heartbeat signature
Agata-Proxima Nov 10, 2026
7001f09
fix(engine): correct heartbeat bootstrap scope and regression tests
Agata-Proxima Nov 10, 2026
899abf0
test(engine): align heartbeat tests with fixed-length bootstrap valid…
Agata-Proxima Nov 10, 2026
3f3b586
feat(engine): support versioned image rollouts for customer executor
Agata-Proxima Nov 10, 2026
7ad88dc
ci(engine): publish semver and raw release image tags
Agata-Proxima Nov 10, 2026
be82e63
fix(engine): allow initial local build before first published image
Agata-Proxima Nov 10, 2026
7b81b9b
feat(engine): add customer-managed deployment executor
Agata-Proxima Nov 10, 2026
ad8adc7
docs(engine): document customer deployment executor installation
Agata-Proxima Nov 10, 2026
be81bf1
docs(engine): link customer deployment executor
Agata-Proxima Nov 10, 2026
ec15afd
ci(engine): syntax-check customer deployment executor
Agata-Proxima Nov 10, 2026
d3175b7
docs(engine): cross-link customer deployment executor
Agata-Proxima Nov 10, 2026
9d1b0be
feat(engine): read one-time enrollment token from Compose secret
Agata-Proxima Nov 10, 2026
35dae08
feat(engine): support tenant signing key Compose secret files
Agata-Proxima Nov 10, 2026
51aa592
feat(engine): mount node and tenant credentials as Compose secrets
Agata-Proxima Nov 10, 2026
5a0fbd1
docs(engine): align customer setup with Compose secret downloads
Agata-Proxima Nov 10, 2026
6693325
docs(engine): document tenant signing secret file configuration
Agata-Proxima Nov 10, 2026
e078c9a
docs(engine): recommend mounted tenant signing key secret files
Agata-Proxima Nov 10, 2026
26bd029
ci(engine): validate customer Compose secrets and required configuration
Agata-Proxima Nov 10, 2026
4534f05
fix(engine): align executor timeout with Control Plane rollout delivery
Agata-Proxima Nov 10, 2026
17a119c
docs(engine): document deployment webhook response timeout
Agata-Proxima Nov 10, 2026
e3f17da
feat(engine): support one signed executor for multiple customer nodes
Agata-Proxima Nov 10, 2026
0be9dc9
fix(engine): persist per-node deployment executor state correctly
Agata-Proxima Nov 10, 2026
c467384
docs(engine): document same-host multi-node executor target map
Agata-Proxima Nov 10, 2026
792afcb
fix(engine): report rejected release and unsupported state as failed …
Agata-Proxima Nov 10, 2026
c325d5e
docs(engine): add multi-node executor target map template
Agata-Proxima Nov 10, 2026
be3b3f8
docs(engine): link multi-node target map template
Agata-Proxima Nov 10, 2026
a37e41a
fix(engine): only mark running releases as rollback-safe versions
Agata-Proxima Nov 10, 2026
82fe51c
feat(engine): provide systemd service template for customer executor
Agata-Proxima Nov 10, 2026
aac0489
docs(engine): add Linux systemd executor installation procedure
Agata-Proxima Nov 10, 2026
024f388
docs(engine): document secret file ownership for non-root container
Agata-Proxima Nov 10, 2026
efe1199
docs(engine): document guided executor provisioning in Cloud
Agata-Proxima Nov 10, 2026
5ce0a72
docs(engine): disclose executor API key privilege and rotation
Agata-Proxima Nov 10, 2026
9dfb6d2
fix(engine): bind deployment executor to loopback behind HTTPS proxy
Agata-Proxima Nov 10, 2026
c2f164a
docs(engine): add HTTPS reverse proxy example for executor
Agata-Proxima Nov 10, 2026
d7c291c
docs(engine): document loopback listener and Caddy HTTPS proxy
Agata-Proxima Nov 10, 2026
e9a645d
fix(engine): run executor from the same Engine repository checkout
Agata-Proxima Nov 10, 2026
c3db972
docs(engine): align executor install paths with one repository checkout
Agata-Proxima Nov 10, 2026
c254c8c
docs(engine): align service identity and secret permissions with Engi…
Agata-Proxima Nov 10, 2026
c1501ef
docs(engine): make executor service account setup fail safely on UID …
Agata-Proxima Nov 10, 2026
af941f1
fix(engine): satisfy Clippy for tenant secret length validation
Agata-Proxima Nov 10, 2026
0306b10
feat(onboarding): add guided Windows customer Engine installer
Agata-Proxima Nov 10, 2026
09cdb4f
feat(onboarding): add guided Linux customer Engine installer
Agata-Proxima Nov 10, 2026
d5892dd
docs(onboarding): add customer node install steps for Windows and Linux
Agata-Proxima Nov 10, 2026
c9c9ff9
ci(onboarding): validate customer installer scripts
Agata-Proxima Nov 10, 2026
2e829be
feat(deployments): add guided Linux executor service installer
Agata-Proxima Nov 10, 2026
f28a185
docs(deployments): document guided Linux executor service installer
Agata-Proxima Nov 10, 2026
3d328ba
ci(deployments): validate executor service installer syntax
Agata-Proxima Nov 10, 2026
9d6e723
docs(readme): surface guided Windows and Linux customer install
Agata-Proxima Nov 10, 2026
832fe9e
fix(deployments): allow longer customer image pulls during rollout
Agata-Proxima Nov 10, 2026
4a1ac1b
fix(deployments): apply selected release image while keeping Engine s…
Agata-Proxima Nov 10, 2026
29c1c04
docs(engine): clarify stopped release application semantics
Agata-Proxima Nov 10, 2026
0e58b22
Harden Windows customer installer health checks
Agata-Proxima Nov 10, 2026
6330180
Add Windows installer smoke test
Agata-Proxima Nov 10, 2026
dbcdafa
Add Windows installer CI validation
Agata-Proxima Nov 10, 2026
47bcb09
Document Windows and Linux customer installation in README
Agata-Proxima Nov 10, 2026
17ca805
Add Windows and Linux registered-node quickstart
Agata-Proxima Nov 10, 2026
350e89b
Index Windows and Linux customer installation resources
Agata-Proxima Nov 10, 2026
17fe987
Fix Windows installer smoke-test command mock
Agata-Proxima Nov 10, 2026
4b2b9c4
Document Windows and Linux node installer commands
Agata-Proxima Nov 10, 2026
ad3bc3f
Correct Windows customer node health verification
Agata-Proxima Nov 10, 2026
bda8669
Clarify Windows Engine and executor installation boundaries
Agata-Proxima Nov 10, 2026
1e7a97b
Correct Windows node health verification command
Agata-Proxima Nov 10, 2026
dfa0767
Scope Windows installer prerequisites to supported Docker Desktop hosts
Agata-Proxima Nov 10, 2026
8749f2d
Scope Windows installer prerequisites to supported Docker Desktop hosts
Agata-Proxima Nov 10, 2026
f6b3d0b
Fix Windows CI Docker mock scope
Agata-Proxima Nov 10, 2026
5e43a25
Use stable main-branch customer installer download links
Agata-Proxima Nov 11, 2026
1847ac0
Use stable main-branch customer installer download links
Agata-Proxima Nov 11, 2026
6a50b87
Load organization-scoped tenant key from enrolled node identity
Agata-Proxima Nov 11, 2026
0ae8344
Use the organization-scoped tenant key delivered in node identity
Agata-Proxima Nov 11, 2026
3ca282a
Make Windows customer installer create its environment and enrollment…
Agata-Proxima Nov 11, 2026
c8f74b7
Make Linux customer installer create its environment and enrollment s…
Agata-Proxima Nov 11, 2026
7d3fb73
Keep the Windows installer compatible with Windows PowerShell 5.1
Agata-Proxima Nov 11, 2026
81d8b5e
Write enrollment token without a UTF-8 BOM
Agata-Proxima Nov 11, 2026
26fd60c
Validate customer Compose with only the enrollment secret and generat…
Agata-Proxima Nov 11, 2026
c55cd5b
Exercise Windows installer environment and one-time secret generation
Agata-Proxima Nov 11, 2026
50500cb
Rewrite customer node install guide around secure automatic key delivery
Agata-Proxima Nov 11, 2026
e379a56
Document organization-scoped tenant key persistence and credential ha…
Agata-Proxima Nov 11, 2026
60c9b1f
Simplify Windows and Linux registered-node quickstart
Agata-Proxima Nov 11, 2026
09566c7
Correct customer installer and tenant-key security instructions
Agata-Proxima Nov 11, 2026
73ac63b
Bootstrap node identity before loading Engine security configuration
Agata-Proxima Nov 11, 2026
3aa9754
Add Linux installer smoke test for generated customer setup files
Agata-Proxima Nov 11, 2026
2983c8a
Run Linux installer generation and health-check smoke test in CI
Agata-Proxima Nov 11, 2026
16c7828
Refresh organization-scoped tenant key for existing node identities
Agata-Proxima Nov 11, 2026
0a1dc3b
Document automatic identity-key refresh for existing Engine nodes
Agata-Proxima Nov 11, 2026
cefa843
Scope secure identity file write imports to Unix builds
Agata-Proxima Nov 11, 2026
3bd7fb1
Add Linux daemon checks and immediate container failure diagnostics
Agata-Proxima Nov 11, 2026
9aaca24
Mock Linux Docker daemon information in installer smoke test
Agata-Proxima Nov 11, 2026
93f83e2
Persist the explicit node heartbeat URL in customer environment
Agata-Proxima Nov 11, 2026
6819865
Persist the explicit node heartbeat URL in customer environment
Agata-Proxima Nov 11, 2026
adbd3c4
Verify Windows installer persists the heartbeat endpoint
Agata-Proxima Nov 11, 2026
3b05278
Verify Linux installer persists the heartbeat endpoint
Agata-Proxima Nov 11, 2026
ef3f337
Point issue reporting to the Proxima Engine repository
Agata-Proxima Nov 11, 2026
a1a533a
feat(engine): accept legacy tenant tokens during key migration
Agata-Proxima Nov 11, 2026
77ce4cd
feat(engine): configure previous tenant signing key for safe rotation
Agata-Proxima Nov 11, 2026
ce7b634
feat(engine): preserve legacy token verification during node identity…
Agata-Proxima Nov 11, 2026
9ddb7bc
test(engine): cover legacy token verification during key rotation
Agata-Proxima Nov 11, 2026
118d323
fix(engine): accept previous signing key as string configuration
Agata-Proxima Nov 11, 2026
278081f
test(engine): update TLS config fixture for key rotation
Agata-Proxima Nov 11, 2026
cab8667
test(engine): align previous-key tests with string config
Agata-Proxima Nov 11, 2026
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
41 changes: 41 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,26 @@ jobs:
uses: Swatinem/rust-cache@v2
- name: Test public Engine CLI
run: python3 -m unittest discover -s tests_cli -v
- name: Validate customer deployment executor syntax
run: node --check deployment-executor/receiver.mjs
- name: Validate customer installer scripts
run: |
bash -n install-customer.sh
bash -n install-deployment-executor.sh
bash tests/linux-installer-smoke.sh
pwsh -NoProfile -Command '$tokens = $null; $errors = $null; [System.Management.Automation.Language.Parser]::ParseFile((Resolve-Path "install-customer.ps1"), [ref]$tokens, [ref]$errors) > $null; if ($errors.Count -gt 0) { $errors | ForEach-Object { Write-Error $_ }; exit 1 }'
- name: Validate customer Compose installation contract
run: |
mkdir -p secrets
printf 'test-enrollment-token' > secrets/node_enrollment_token
cat > .env <<'EOF'
PROXIMA_NODE_ID=00000000-0000-4000-8000-000000000001
PROXIMA_NODE_ENROLLMENT_URL=https://api.agataproxima.com/api/v1/nodes/enroll
PROXIMA_UPSTREAM_ADDR=127.0.0.1:5432
PROXIMA_LISTEN_ADDR=0.0.0.0:6432
PROXIMA_ENVIRONMENT=production
EOF
docker compose -f compose.customer.yaml config --quiet
- name: Run engine tests
run: cargo test -p proxima-engine
- name: Build release engine
Expand All @@ -52,3 +72,24 @@ jobs:
run: docker build -t proxima-engine:ci .
- name: Verify PgBouncer tenant-pool isolation
run: bash scripts/test-pgbouncer-pooling.sh


windows-installer:
name: Windows customer installer
runs-on: windows-latest
steps:
- name: Check out source
uses: actions/checkout@v4
- name: Parse Windows installer
shell: pwsh
run: |
$tokens = $null
$errors = $null
[System.Management.Automation.Language.Parser]::ParseFile((Resolve-Path "install-customer.ps1"), [ref]$tokens, [ref]$errors) > $null
if ($errors.Count -gt 0) {
$errors | ForEach-Object { Write-Error $_ }
exit 1
}
- name: Execute Windows installer smoke test with Docker host simulation
shell: pwsh
run: ./tests/windows-installer-smoke.ps1
46 changes: 46 additions & 0 deletions .github/workflows/publish-container.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
name: Publish Engine container

on:
push:
tags:
- "v*"

permissions:
contents: read
packages: write

jobs:
publish:
name: Build and publish customer Engine image
runs-on: ubuntu-latest
steps:
- name: Check out source
uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Generate release image tags
id: meta
uses: docker/metadata-action@v5
with:
images: ghcr.io/proxima-engine/proxima-engine
tags: |
type=semver,pattern={{version}}
type=raw,value={{tag}}
type=raw,value=latest
- name: Build and publish multi-architecture Engine
uses: docker/build-push-action@v6
with:
context: .
file: ./Dockerfile
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
93 changes: 90 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<a href="https://www.linkedin.com/company/agata-proxima/">LinkedIn</a>
</p>

**Start:** [What is Agata Proxima?](#what-is-agata-proxima) · [Launch evaluation](docs/LAUNCH.md) · [Quickstart](docs/QUICKSTART.md) · [Local developer mode](docs/LOCAL_DEVELOPMENT.md) · [Engine CLI](docs/CLI.md) · [Documentation index](docs/README.md)
**Start:** [What is Agata Proxima?](#what-is-agata-proxima) · [Customer Docker install](docs/NODE_ENROLLMENT.md#2-one-command-docker-installation-hosted-cloud) · [Guided customer install (Windows/Linux)](docs/CUSTOMER_DEPLOYMENT_EXECUTOR.md#install-the-engine-customer-node) · [Deployment executor](docs/CUSTOMER_DEPLOYMENT_EXECUTOR.md) · [Launch evaluation](docs/LAUNCH.md) · [Quickstart](docs/QUICKSTART.md) · [Local developer mode](docs/LOCAL_DEVELOPMENT.md) · [Engine CLI](docs/CLI.md) · [Documentation index](docs/README.md)

**Technical guides:** [Architecture](docs/ARCHITECTURE.md) · [Tenant isolation](docs/TENANT_ISOLATION.md) · [Driver integrations](docs/INTEGRATIONS.md) · [API and metrics](docs/API.md) · [Security](docs/SECURITY.md) · [Deployment](docs/DEPLOYMENT.md) · [Verification](docs/VERIFICATION.md)

Expand Down Expand Up @@ -128,7 +128,8 @@ See [Tenant isolation](docs/TENANT_ISOLATION.md), [Verification](docs/VERIFICATI
| [Tenant isolation](docs/TENANT_ISOLATION.md) | PostgreSQL roles, RLS policies, signed context, and test results |
| [Driver integrations](docs/INTEGRATIONS.md) | psql, Node.js, Python, and Rust connection examples |
| [API reference](docs/API.md) | PostgreSQL endpoint, health/status routes, and Prometheus metrics |
| [Node enrollment](docs/NODE_ENROLLMENT.md) | Engine-side node identity and enrollment contract |
| [Node enrollment](docs/NODE_ENROLLMENT.md) | Customer Docker installation, one-time enrollment, signed heartbeat, and identity persistence |
| [Customer deployment executor](docs/CUSTOMER_DEPLOYMENT_EXECUTOR.md) | Install and operate the customer-managed, signed Docker Compose deployment executor |
| [Deployment](docs/DEPLOYMENT.md) | Container build, TLS, networking, persistence, and deployment configuration |
| [Operations](docs/OPERATIONS.md) | Health checks, logs, monitoring, recovery, and troubleshooting |
| [Engineering case study](docs/ENGINEERING_CASE_STUDY.md) | Executed tenant-isolation, RLS, PgBouncer, concurrency, authentication, and recovery results |
Expand Down Expand Up @@ -158,6 +159,92 @@ The Proxima Engine source and covered documentation are distributed under the [M

## Contribute

Use [GitHub Issues](https://github.com/Agata-Proxima/proxima-engine/issues) for reproducible Engine bugs and feature requests. Read [Contributing](CONTRIBUTING.md) before submitting a pull request. For vulnerabilities, use the private reporting process in [SECURITY.md](SECURITY.md).
Use [GitHub Issues](https://github.com/Proxima-Engine/proxima-engine/issues) for reproducible Engine bugs and feature requests. Read [Contributing](CONTRIBUTING.md) before submitting a pull request. For vulnerabilities, use the private reporting process in [SECURITY.md](SECURITY.md).

<p align="center">Built by Agata Proxima · <a href="https://agataproxima.com">agataproxima.com</a> · <a href="https://github.com/Agata-Proxima">GitHub organization</a></p>

## Install a registered Engine node on Windows or Linux

The customer-node installer supports Windows 10/11 hosts running Docker Desktop with the WSL 2 backend, Linux containers, and Docker Compose v2. Windows users have a dedicated PowerShell installer; Linux users have a Bash installer. Both install the same Proxima Engine container and use the same signed enrollment and heartbeat protocol.

### Windows downloads

1. Download the [Proxima Engine source ZIP](https://github.com/Proxima-Engine/proxima-engine/archive/refs/heads/main.zip) and extract it.
2. In Agata Proxima Cloud → Nodes, copy the Windows PowerShell setup commands shown with the node's one-time enrollment token.
3. Keep the included [Windows PowerShell installer](https://raw.githubusercontent.com/Proxima-Engine/proxima-engine/main/install-customer.ps1) and [customer Compose file](https://raw.githubusercontent.com/Proxima-Engine/proxima-engine/main/compose.customer.yaml) together in the extracted repository folder.
4. Paste the copied setup commands into the same PowerShell session. The installer generates `.env` and `secrets/node_enrollment_token`; it prompts for the PostgreSQL upstream address if it is not set. No tenant signing key download is required.

### Windows prerequisites

- Windows 10/11 with Docker Desktop configured to use the WSL 2 backend and Linux containers.
- Docker daemon running before installation.
- The Windows setup commands copied from the registered node in Node Management.
- Network access from the Engine container to the configured PostgreSQL upstream and Agata Proxima HTTPS enrollment/heartbeat endpoints.

The Engine is distributed as a Linux container. On Windows, Docker Desktop runs that container through its Linux/WSL 2 backend; this is the supported Windows installation path. The PowerShell installer is a Windows host installer, not an MSI and not a native Windows service binary.

### Run the Windows installer

Open PowerShell in the extracted folder. If the machine's execution policy blocks a locally downloaded script, allow it for this PowerShell process only:

```powershell
Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass
.\install-customer.ps1
```

The installer performs these checks and actions in order:

1. Generates the node environment file and one-time enrollment-token secret from the copied setup commands.
2. Prompts for the PostgreSQL upstream host and port when it is not already configured.
3. Confirms the Docker CLI and a running Docker daemon.
4. Confirms that Docker is using Linux containers and Docker Compose v2 is available.
5. Validates the customer Compose configuration.
6. Builds and starts the Engine container.
7. Waits up to 120 seconds for the container's Docker health check to report `healthy`.
8. Prints container status and the local PostgreSQL proxy endpoint.

A successful installation prints **Proxima Engine is healthy**. Then open Agata Proxima → Nodes/Fleet and confirm the registered node reports healthy after its signed heartbeat arrives. During first enrollment, the Control Plane returns the node heartbeat key and an organization-scoped tenant verification key over HTTPS. The Engine stores both in its protected identity file in a named Docker volume. The Control Plane master signing secret is never sent to customer nodes. After the node is healthy, replace the contents of `secrets/node_enrollment_token` with `enrollment-complete`; keep the file in place for subsequent Compose starts.

### Verify and operate on Windows

```powershell
docker compose -f compose.customer.yaml ps
docker compose -f compose.customer.yaml logs --tail 100 engine
$containerId = docker compose -f compose.customer.yaml ps -q engine
docker inspect --format '{{.State.Health.Status}}' $containerId
```

The final command prints the container health state. To verify SQL connectivity, connect your application or a PostgreSQL client to `127.0.0.1:6432` using the database credentials configured for your upstream PostgreSQL service.

Restart and stop the registered node:

```powershell
docker compose -f compose.customer.yaml restart engine
docker compose -f compose.customer.yaml down
```

Start it again without rebuilding:

```powershell
docker compose -f compose.customer.yaml up -d
```

### Linux installation

Linux customers copy the Linux shell setup commands from Agata Proxima → Nodes and paste them into a shell in the extracted repository folder. The Bash installer creates the environment and enrollment-token secret automatically:

```bash
chmod +x ./install-customer.sh
./install-customer.sh
```

For the Linux deployment-executor service installer and its security requirements, see [Customer-managed deployment executor](CUSTOMER_DEPLOYMENT_EXECUTOR.md).

### Network and security requirements

- The Engine listens on TCP 6432 and binds to host loopback by default. Keep this binding when the application runs on the same host.
- If the application runs in another container, attach it to the configured Compose network and use the Engine service name and port. For a different host, use a private network/VPN, a deliberate private bind address, and a restrictive firewall rule.
- The configured PostgreSQL upstream address is resolved from inside the Engine container. `localhost` refers to the container itself, not the Windows host. Use a reachable database hostname or the appropriate Docker Desktop host gateway address.
- Never expose PostgreSQL proxy port 6432, the status interface, or metrics publicly.
- Never commit, email, or paste `.env`, enrollment tokens, node identity files, operator API keys, or webhook secrets.
- The Control Plane master tenant-signing secret stays in the Control Plane. A customer Engine receives only its own organization's derived verification key during HTTPS enrollment; the Engine stores it in the protected identity file.
46 changes: 46 additions & 0 deletions compose.customer.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
services:
engine:
image: ghcr.io/proxima-engine/proxima-engine:${PROXIMA_ENGINE_VERSION:-latest}
build:
context: .
dockerfile: Dockerfile
restart: unless-stopped
environment:
PROXIMA_NODE_ID: ${PROXIMA_NODE_ID:?Set PROXIMA_NODE_ID in .env}
PROXIMA_NODE_IDENTITY_PATH: /var/lib/proxima/node-identity.json
PROXIMA_NODE_ENROLLMENT_URL: ${PROXIMA_NODE_ENROLLMENT_URL:-https://api.agataproxima.com/api/v1/nodes/enroll}
PROXIMA_NODE_HEARTBEAT_URL: ${PROXIMA_NODE_HEARTBEAT_URL:-https://api.agataproxima.com/api/v1/nodes/heartbeat}
PROXIMA_NODE_ENROLLMENT_TOKEN_FILE: /run/secrets/node_enrollment_token
PROXIMA_ENVIRONMENT: ${PROXIMA_ENVIRONMENT:-production}
PROXIMA_LISTEN_ADDR: ${PROXIMA_LISTEN_ADDR:-0.0.0.0:6432}
PROXIMA_UPSTREAM_ADDR: ${PROXIMA_UPSTREAM_ADDR:?Set PROXIMA_UPSTREAM_ADDR in .env}
PROXIMA_DASHBOARD_ENABLED: "false"
PROXIMA_METRICS_LISTEN_ADDR: 127.0.0.1:9090
ports:
- "${PROXIMA_BIND_ADDRESS:-127.0.0.1}:6432:6432"
secrets:
- node_enrollment_token
volumes:
- proxima-node-data:/var/lib/proxima
healthcheck:
test: ["CMD", "curl", "-fsS", "http://127.0.0.1:9090/healthz"]
interval: 15s
timeout: 5s
retries: 5
start_period: 20s
security_opt:
- no-new-privileges:true
read_only: true
tmpfs:
- /tmp:size=16m,noexec,nosuid

secrets:
node_enrollment_token:
file: ./secrets/node_enrollment_token

networks:
default:
name: ${PROXIMA_DOCKER_NETWORK:-proxima-engine-network}

volumes:
proxima-node-data:
33 changes: 27 additions & 6 deletions crates/proxima-engine/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ pub struct Config {
pub listen_addr: SocketAddr,
pub upstream_addr: String,
pub tenant_signing_key: Option<String>,
pub tenant_signing_key_previous: Option<String>,
pub tenant_role_prefix: String,
pub upstream_connect_timeout: Duration,
pub max_connections: usize,
Expand Down Expand Up @@ -78,17 +79,33 @@ impl Config {
));
}

let tenant_signing_key = match env::var("PROXIMA_TENANT_SIGNING_KEY") {
Ok(value) if value.trim().is_empty() => None,
Ok(value) if value.len() < 32 => {
// A node identity loaded during bootstrap sets the organization key in
// the environment. It must take precedence over any legacy key file.
let tenant_signing_key_value = match env::var("PROXIMA_TENANT_SIGNING_KEY") {
Ok(value) => Some(value),
Err(_) => match env::var("PROXIMA_TENANT_SIGNING_KEY_FILE") {
Ok(path) => Some(std::fs::read_to_string(path)?.trim().to_owned()),
Err(_) => None,
},
};
let tenant_signing_key = match tenant_signing_key_value {
Some(value) if value.trim().is_empty() => None,
Some(value) if value.len() < 32 => {
return Err(io::Error::new(
io::ErrorKind::InvalidInput,
"PROXIMA_TENANT_SIGNING_KEY must be at least 32 bytes",
"PROXIMA_TENANT_SIGNING_KEY or its secret file must contain at least 32 bytes",
))
}
Ok(value) => Some(value),
Err(_) => None,
Some(value) => Some(value),
None => None,
};
let tenant_signing_key_previous = non_empty_env("PROXIMA_TENANT_SIGNING_KEY_PREVIOUS");
if tenant_signing_key_previous.as_ref().is_some_and(|key| key.len() < 32) {
return Err(io::Error::new(
io::ErrorKind::InvalidInput,
"PROXIMA_TENANT_SIGNING_KEY_PREVIOUS must contain at least 32 bytes",
));
}

let upstream_connect_timeout_ms = env::var("PROXIMA_UPSTREAM_CONNECT_TIMEOUT_MS")
.unwrap_or_else(|_| "10000".to_string())
Expand Down Expand Up @@ -175,6 +192,7 @@ impl Config {
listen_addr,
upstream_addr,
tenant_signing_key,
tenant_signing_key_previous,
tenant_role_prefix,
upstream_connect_timeout: Duration::from_millis(upstream_connect_timeout_ms),
max_connections,
Expand Down Expand Up @@ -241,6 +259,8 @@ mod tests {
"PROXIMA_LISTEN_ADDR",
"PROXIMA_UPSTREAM_ADDR",
"PROXIMA_TENANT_SIGNING_KEY",
"PROXIMA_TENANT_SIGNING_KEY_FILE",
"PROXIMA_TENANT_SIGNING_KEY_PREVIOUS",
"PROXIMA_UPSTREAM_CONNECT_TIMEOUT_MS",
"PROXIMA_MAX_CONNECTIONS",
"PROXIMA_TLS_CERT_FILE",
Expand All @@ -261,6 +281,7 @@ mod tests {
assert_eq!(config.listen_addr, "127.0.0.1:6432".parse().unwrap());
assert_eq!(config.upstream_addr, "127.0.0.1:5432");
assert_eq!(config.tenant_signing_key, None);
assert_eq!(config.tenant_signing_key_previous, None);
assert_eq!(config.tenant_role_prefix, "proxima_tenant_");
assert_eq!(config.upstream_connect_timeout, Duration::from_secs(10));
assert_eq!(config.max_connections, 1024);
Expand Down
Loading
Loading