chore(ansible): centralize third-party Docker image versions

Add centralized image version variables in group_vars/all/vars.yml for
vulnerability tracking and controlled upgrades of third-party Docker
images (casdoor, flower, grafana-mcp, gitea-mcp, neo4j, memcached,
nginx, oauth2-proxy, rabbitmq, searxng).

Update vault.yml accordingly.
This commit is contained in:
2026-05-03 18:57:58 -04:00
parent 2be323f27e
commit 4ae6379613
11 changed files with 681 additions and 497 deletions

View File

@@ -4,10 +4,19 @@
Neo4j is a high-performance graph database providing native graph storage and processing. It enables efficient traversal of complex relationships and is used for knowledge graphs, recommendation engines, and connected data analysis. Deployed with the **APOC plugin** enabled for extended stored procedures and functions.
**Host:** ariel.incus
**Role:** graph_database
**Container Port:** 25554 (HTTP Browser), 7687 (Bolt)
**External Access:** Direct Bolt connection via `ariel.incus:7687`
Two dedicated Neo4j instances run in the Ouranos lab, one per tenant, because
Neo4j Community Edition is single-database and tenants cannot safely share
label space, vector indexes, or schema migrations:
| Host | Tenant | HTTP Browser | Bolt |
|------|--------|--------------|------|
| `ariel.incus` | Shared / general graph work (Neo4j MCP, exploration) | port 25554 | port 7687 |
| `umbriel.incus` | Mnemosyne (dedicated — `Library`/`Collection`/`Item`/`Chunk`/`Concept`) | port 25555 | port 7687 |
Both hosts run the same Ansible playbook (`neo4j/deploy.yml`) from the same
`docker-compose.yml.j2` template, differing only by port and vault password.
They run independent Docker Compose stacks with their own named volumes
(`neo4j_data`, `neo4j_logs`, `neo4j_plugins`) — no shared state.
## Architecture
@@ -22,32 +31,50 @@ Neo4j is a high-performance graph database providing native graph storage and pr
└────────────▶│ Neo4j Browser│
│ HTTP :25554 │
└──────────────┘
┌──────────────┐ ┌──────────────┐
│ Mnemosyne │─────▶│ Neo4j │
│ (puck) │ Bolt │ (Umbriel) │
└──────────────┘ └──────────────┘
┌──────────────┐
│ Neo4j Browser│
│ HTTP :25555 │
└──────────────┘
```
- **Neo4j Browser**: Web-based query interface on port 25554
- **Bolt Protocol**: Binary protocol on port 7687 for high-performance connections
- **Neo4j Browser (Ariel)**: Web-based query interface on port 25554
- **Neo4j Browser (Umbriel)**: Web-based query interface on port 25555
- **Bolt Protocol**: Binary protocol on port 7687 for high-performance connections (same port on both hosts — each container has its own network namespace)
- **APOC Plugin**: Extended procedures for import/export, graph algorithms, and utilities
- **Neo4j MCP Servers**: Connect via Bolt from Miranda for AI agent access
- **Neo4j MCP Servers**: Connect via Bolt from Miranda for AI agent access (Ariel only)
- **Mnemosyne**: Connects via Bolt to Umbriel; does not touch Ariel
## Terraform Resources
### Host Definition
### Host Definitions
The service runs on `ariel`, defined in `terraform/containers.tf`:
Both hosts are defined in `terraform/containers.tf`:
| Attribute | Value |
|-----------|-------|
| Image | noble |
| Role | graph_database |
| Security Nesting | true |
| AppArmor | unconfined |
| Description | Neo4j Host - Ethereal graph connections |
| Attribute | ariel | umbriel |
|-----------|-------|---------|
| Image | noble | noble |
| Role | graph_database | graph_database |
| Security Nesting | true | true |
| AppArmor | unconfined | unconfined |
| Description | Neo4j Host - Ethereal graph connections | Neo4j Host (Mnemosyne) - Dusky sprite keeping the memory graph |
### Proxy Devices
| Device Name | Listen | Connect |
|-------------|--------|---------|
| neo4j_ports | tcp:0.0.0.0:25554 | tcp:127.0.0.1:25554 |
| Host | Device Name | Listen | Connect |
|------|-------------|--------|---------|
| ariel | neo4j_ports | tcp:0.0.0.0:25554 | tcp:127.0.0.1:25554 |
| umbriel | neo4j_ports | tcp:0.0.0.0:25555 | tcp:127.0.0.1:25555 |
> Bolt (7687) is not in the Incus proxy device list for either host — it is
> reached directly over the internal `10.10.0.0/24` network by DNS name
> (`ariel.incus:7687`, `umbriel.incus:7687`).
### Dependencies
@@ -69,9 +96,10 @@ ansible-playbook neo4j/deploy.yml
| File | Purpose |
|------|---------|
| `neo4j/deploy.yml` | Main deployment playbook |
| `neo4j/deploy.yml` | Main deployment playbook (runs on both hosts via service detection) |
| `neo4j/docker-compose.yml.j2` | Docker Compose template |
| `alloy/ariel/config.alloy.j2` | Alloy log collection config |
| `alloy/ariel/config.alloy.j2` | Alloy log collection config — Ariel |
| `alloy/umbriel/config.alloy.j2` | Alloy log collection config — Umbriel |
### Deployment Steps
@@ -83,7 +111,28 @@ ansible-playbook neo4j/deploy.yml
## Configuration
### Host Variables (`host_vars/ariel.incus.yml`)
### Host Variables
Both hosts define the same variable set, differing only in port, syslog port,
and vault reference.
`host_vars/ariel.incus.yml`:
| Variable | Value |
|----------|-------|
| `neo4j_auth_password` | `{{ vault_neo4j_auth_password }}` |
| `neo4j_http_port` | `25554` |
| `neo4j_syslog_port` | `22011` |
`host_vars/umbriel.incus.yml`:
| Variable | Value |
|----------|-------|
| `neo4j_auth_password` | `{{ vault_mnemosyne_neo4j_auth_password }}` |
| `neo4j_http_port` | `25555` |
| `neo4j_syslog_port` | `22012` |
Shared variables on both hosts:
| Variable | Description | Default |
|----------|-------------|---------|
@@ -92,17 +141,15 @@ ansible-playbook neo4j/deploy.yml
| `neo4j_group` | System group | `neo4j` |
| `neo4j_directory` | Installation directory | `/srv/neo4j` |
| `neo4j_auth_user` | Database admin username | `neo4j` |
| `neo4j_auth_password` | Database admin password | `{{ vault_neo4j_auth_password }}` |
| `neo4j_http_port` | HTTP browser port | `25554` |
| `neo4j_bolt_port` | Bolt protocol port | `7687` |
| `neo4j_syslog_port` | Local syslog port for Alloy | `22011` |
| `neo4j_apoc_unrestricted` | APOC procedures allowed | `apoc.*` |
### Vault Variables (`group_vars/all/vault.yml`)
| Variable | Description |
|----------|-------------|
| `vault_neo4j_auth_password` | Neo4j admin password |
| `vault_neo4j_auth_password` | Neo4j admin password (Ariel) |
| `vault_mnemosyne_neo4j_auth_password` | Neo4j admin password (Umbriel — dedicated Mnemosyne instance) |
### APOC Plugin Configuration
@@ -128,19 +175,20 @@ The APOC (Awesome Procedures on Cypher) plugin is enabled with the following set
### Alloy Configuration
**File:** `ansible/alloy/ariel/config.alloy.j2`
**Files:** `ansible/alloy/ariel/config.alloy.j2`, `ansible/alloy/umbriel/config.alloy.j2`
Alloy on Ariel collects:
Alloy on each host collects:
- System logs (`/var/log/syslog`, `/var/log/auth.log`)
- Systemd journal
- Neo4j Docker container logs via syslog
- Neo4j Docker container logs via syslog (Ariel: tcp:127.0.0.1:22011; Umbriel: tcp:127.0.0.1:22012)
### Loki Logs
| Log Source | Labels |
|------------|--------|
| Neo4j container | `{job="neo4j", hostname="ariel.incus"}` |
| System logs | `{job="syslog", hostname="ariel.incus"}` |
| Neo4j container (Ariel) | `{job="neo4j", hostname="ariel.incus"}` |
| Neo4j container (Umbriel) | `{job="neo4j", hostname="umbriel.incus"}` |
| System logs | `{job="syslog", hostname="ariel.incus"}` / `{job="syslog", hostname="umbriel.incus"}` |
### Prometheus Metrics
@@ -153,7 +201,8 @@ Host-level metrics collected via Alloy's Unix exporter:
### Log Collection Flow
```
Neo4j Container → Syslog (tcp:127.0.0.1:22011) → Alloy → Loki (Prospero)
Neo4j Container (Ariel) → Syslog (tcp:127.0.0.1:22011) → Alloy → Loki (Prospero)
Neo4j Container (Umbriel) → Syslog (tcp:127.0.0.1:22012) → Alloy → Loki (Prospero)
```
## Operations