Skip to content

Commit 1835f65

Browse files
pablomhclaude
andcommitted
Document container networking architecture
Adds docs/deployment.md with a description of the four bridge networks introduced by this series, their properties (internal, isolate), which containers are attached to each, and the rationale for the port publishing decisions. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent f1dba59 commit 1835f65

1 file changed

Lines changed: 92 additions & 0 deletions

File tree

docs/deployment.md

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,3 +236,95 @@ As `foremanctl` is Ansible-based, this means that the ["control node"](https://d
236236
To simplify the "install `foremanctl`" step, our test infrastructure uses different systems for the "control node" (the system the source code is cloned to) and the "target node" (the VM created by our development tooling).
237237

238238
There is a desire to allow deployments where a single `foremanctl` control node manages multiple managed nodes, but no code exists yet for this.
239+
240+
## Container Networking
241+
242+
All containers are connected to one or more named Podman bridge networks instead of sharing the host network namespace, limiting lateral movement: a container can only reach the services it is explicitly connected to.
243+
244+
### Networks
245+
246+
#### `foreman-db`
247+
248+
**Properties:** `internal: true`, `isolate: true`
249+
250+
The database network. Only containers that need to read or write persistent data are attached.
251+
252+
- `internal: true` removes the default gateway, so no container on this network can initiate outbound internet connections. Database servers have no reason to reach the internet, and clients that need internet access (e.g. for content sync) are multi-homed and use a different network for that.
253+
- `isolate: true` prevents containers on this network from forwarding packets to containers on other bridge networks, closing off lateral movement paths between network segments.
254+
255+
| Container | Role |
256+
|-----------|------|
257+
| `postgresql` | Server — listens on port 5432 (internal DB only) |
258+
| `foreman` | Client |
259+
| `dynflow-sidekiq@*` | Client |
260+
| `foreman-recurring@*` | Client |
261+
| `candlepin` | Client (internal DB only) |
262+
| `pulp-api` | Client |
263+
| `pulp-content` | Client |
264+
| `pulp-worker@*` | Client |
265+
266+
Ansible's `community.postgresql.*` modules reach the database during deployment via a Unix socket: `/var/run/postgresql` is bind-mounted from the host into the container so the socket is accessible on the host without publishing a TCP port.
267+
268+
#### `foreman-cache`
269+
270+
**Properties:** `internal: true`, `isolate: true`
271+
272+
The cache network. Only containers that need to reach Redis are attached. The same rationale as `foreman-db` applies: cache servers have no business reaching the internet, and the `isolate` flag prevents bridge pivoting.
273+
274+
| Container | Role |
275+
|-----------|------|
276+
| `redis` | Server — listens on port 6379 |
277+
| `foreman` | Client — app cache and Dynflow queue |
278+
| `dynflow-sidekiq@*` | Client — job queue |
279+
| `foreman-recurring@*` | Client — job queue |
280+
| `pulp-api` | Client |
281+
| `pulp-content` | Client |
282+
| `pulp-worker@*` | Client |
283+
284+
Redis does not publish any port to the host: it is a purely internal service with no legitimate consumers outside the container network.
285+
286+
#### `foreman-app`
287+
288+
**Properties:** none (`internal: false`, `isolate: false`)
289+
290+
The application network. Containers that need to communicate with each other at the application layer, or that need outbound internet access (e.g. for content synchronisation), are attached here.
291+
292+
| Container | Role |
293+
|-----------|------|
294+
| `candlepin` | Server — Tomcat (23443) and Artemis STOMP broker (61613) |
295+
| `foreman` | Client to Candlepin; serves Foreman Proxy requests |
296+
| `dynflow-sidekiq@*` | Client |
297+
| `foreman-recurring@*` | Client |
298+
| `pulp-api` | Server — API (24817); needs internet for content sync |
299+
| `pulp-content` | Server — content (24816); needs internet for content sync |
300+
| `pulp-worker@*` | Worker — needs internet for content sync |
301+
302+
Candlepin does not publish any ports to the host: `foreman` reaches it directly over the bridge using its DNS name. `foreman`, `pulp-api`, and `pulp-content` publish their respective ports to `127.0.0.1` so that the `httpd` reverse proxy running on the host can reach them.
303+
304+
#### `foreman-proxy-net`
305+
306+
**Properties:** none (`internal: false`, `isolate: false`)
307+
308+
The proxy network, used exclusively for communication between Foreman and Foreman Proxy. Keeping this traffic on a dedicated network makes it straightforward to apply stricter controls in future without affecting the rest of the application.
309+
310+
| Container | Role |
311+
|-----------|------|
312+
| `foreman-proxy` | Server — listens on 0.0.0.0:8443 (external) |
313+
| `foreman` | Client |
314+
315+
`foreman-proxy` publishes port `0.0.0.0:8443` so that remote Foreman Proxies and clients can register and communicate with it from outside the host.
316+
317+
### Network membership summary
318+
319+
| Container | foreman-db | foreman-cache | foreman-app | foreman-proxy-net |
320+
|-----------|:----------:|:-------------:|:-----------:|:-----------------:|
321+
| `postgresql` || | | |
322+
| `redis` | || | |
323+
| `candlepin` | ✓ (internal DB) | || |
324+
| `foreman` |||||
325+
| `dynflow-sidekiq@*` |||| |
326+
| `foreman-recurring@*` |||| |
327+
| `foreman-proxy` | | | ||
328+
| `pulp-api` |||| |
329+
| `pulp-content` |||| |
330+
| `pulp-worker@*` |||| |

0 commit comments

Comments
 (0)