Skip to content

Foremanctl networks - #6

Open
pablomh wants to merge 6 commits into
masterfrom
foremanctl_networks
Open

Foremanctl networks#6
pablomh wants to merge 6 commits into
masterfrom
foremanctl_networks

Conversation

@pablomh

@pablomh pablomh commented Mar 4, 2026

Copy link
Copy Markdown
Owner

No description provided.

@pablomh
pablomh force-pushed the foremanctl_networks branch 30 times, most recently from c97c07a to e4a7982 Compare March 7, 2026 20:56
@pablomh
pablomh force-pushed the foremanctl_networks branch 24 times, most recently from a4dd9b8 to 535cc00 Compare March 8, 2026 21:15
pablomh and others added 6 commits March 31, 2026 10:15
After=foreman.target was added in 805217d to ensure systemctl stop
foreman.target blocks until all constituent services fully stop, preventing
a rapid stop+start race. However, every service is also WantedBy=foreman.target,
making After=foreman.target inherently circular: foreman.target cannot finish
starting until its Wants are satisfied, but those services cannot start until
foreman.target has started.

This caused both start and stop ordering cycles, which systemd resolved by
dropping jobs — leading to unclean postgresql shutdowns, stale postmaster.pid
files, and the very race condition the original fix was trying to prevent.

Remove After=foreman.target from all services. Stop ordering is preserved
through inter-service After= relationships: all application services are
After=redis.service postgresql.service (reversed: redis/postgresql stop after
all application services). PartOf=foreman.target ensures services stop when
foreman.target stops, and systemctl stop foreman.target waits for the full
PartOf-propagated transaction to complete.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Introduces the deploy_network role, which wraps
containers.podman.podman_network to create a named bridge network with
configurable properties: internal (no external routing), isolate (no
cross-network packet forwarding), IPv6, subnet, gateway, and DNS.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace host networking with four named Podman bridge networks:

- foreman-db (internal, isolated): PostgreSQL and its clients
- foreman-cache (internal, isolated): Redis and its clients
- foreman-app: application layer — Foreman, Candlepin, Pulp, httpd
- foreman-proxy-net: Foreman and the smart proxy

Services reach each other by container DNS name instead of localhost.
Per-service notes:

- postgresql: also accessible via a Unix socket bind-mounted at
  /var/run/postgresql, used by Ansible's community.postgresql modules
  during deployment so no TCP port needs to be published to the host.
- redis: publishes no ports; clients reach it by DNS name on
  foreman-cache.
- candlepin: Tomcat binds to 0.0.0.0 so that other containers on the
  bridge network can reach it via its DNS name.
- migration containers (foreman db:migrate, pulp migrations): attached
  to foreman-db when the database is internal; switched to foreman-app
  when the database is external, because foreman-db uses internal: true
  which removes the default gateway, making it impossible for containers
  on that network to reach an external database host.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The development setup runs the Foreman Rails process directly on the
host rather than in a container, so it cannot resolve container bridge
DNS names such as postgresql or candlepin. Keeping host networking for
all services in the devel environment means every service remains
reachable on localhost as before, without requiring per-service URL
overrides for the Rails process.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
foreman-certs generates certificates only for localhost and the server
FQDN. Now that Foreman connects to Candlepin via the bridge DNS name
"candlepin", TLS hostname validation fails against those certificates.
A dedicated certificate with SAN=candlepin, signed by the installer
CA, is generated using the openssl CLI (consistent with the rest of
the codebase).

The certificate validity is set to 7300 days (20 years), matching the
default used by puppet-certs (theforeman/puppet-certs manifests/init.pp
$expiration parameter). The signing step runs on every deployment to
ensure the certificate is always freshly dated, consistent with how
foreman-certs handles the other installer certificates.

The localhost certificate previously used by Candlepin's Tomcat is now
unused and removed:

- "localhost" dropped from certificates_hostnames — the certificates
  role no longer generates the cert.
- localhost_key / localhost_certificate removed from
  default_certificates.yml and installer_certificates.yml.

The healthcheck is updated to validate the new certificate instead of
skipping verification with --insecure. --resolve candlepin:23443:127.0.0.1
forces the connection to the loopback so it works in both bridge
networking (where other containers reach Candlepin by DNS name) and
host networking (where "candlepin" would not resolve via container DNS).

Tests are updated to route connectivity checks through the foreman
container (which shares the same bridge network as candlepin), to verify
against the new certificate, and to check candlepin_certificate expiry
instead of the now-removed localhost_certificate.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant