Contract rev 9 removes the instance CA, client certificates, the peer listener and the trust store fleet-wide. Internal traffic is plaintext HTTP on each service single :8080 listener, so there is no peer identity left to authorize: delete lib/pki, lib/federation, devboot, the per-service database role model and the /api/peers* and /api/instances surfaces, and drop the console Trusted services UI. Config delivery now rides a dedicated ES256 token from lib/configsign rather than mTLS, and the instance fingerprint is derived from a persisted random key and is informational only. main.go also wires the surfaces introduced by the later commits, which this change is what makes possible.
135 lines
5.3 KiB
Go
135 lines
5.3 KiB
Go
// Copyright (C) 2026 Dcntrlized
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU Affero General Public License as published
|
|
// by the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU Affero General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU Affero General Public License
|
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
package containers
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"strings"
|
|
|
|
"git.dcntrlized.org/Dcntrlized/Maestro/lib/docker"
|
|
"git.dcntrlized.org/Dcntrlized/Maestro/lib/logger"
|
|
libregistry "git.dcntrlized.org/Dcntrlized/Maestro/lib/registry"
|
|
"git.dcntrlized.org/Dcntrlized/Maestro/lib/types"
|
|
"github.com/docker/docker/api/types/container"
|
|
"github.com/docker/docker/api/types/filters"
|
|
"github.com/docker/docker/api/types/network"
|
|
)
|
|
|
|
const (
|
|
// DCNTRLIZEDNetwork is the external Docker network every dcntrlized service joins.
|
|
DCNTRLIZEDNetwork = "dcntrlized_net"
|
|
// DatabaseServiceName is the shared database service (image, container and DNS name).
|
|
DatabaseServiceName = "dcntrlized-db"
|
|
// AuthServiceName is the shared auth service (image, container and DNS name).
|
|
AuthServiceName = "dcntrlized-auth"
|
|
)
|
|
|
|
// EnsureDCNTRLIZEDNetwork creates the external dcntrlized_net network when it is
|
|
// missing. Every service compose file declares it as external, so it must exist
|
|
// before any compose project is started.
|
|
func EnsureDCNTRLIZEDNetwork(ctx context.Context, dc *docker.DockerClient) error {
|
|
if _, err := dc.NetworkInspect(ctx, DCNTRLIZEDNetwork, network.InspectOptions{}); err == nil {
|
|
return nil
|
|
}
|
|
if _, err := dc.NetworkCreate(ctx, DCNTRLIZEDNetwork, network.CreateOptions{}); err != nil {
|
|
return fmt.Errorf("failed to create network %s: %w", DCNTRLIZEDNetwork, err)
|
|
}
|
|
logger.Info("Created external Docker network %s", DCNTRLIZEDNetwork)
|
|
return nil
|
|
}
|
|
|
|
// EnsureDatabaseRunning ensures the shared database container is running. On a
|
|
// fresh host — when the database is not installed yet — it resolves the
|
|
// database from the registry and installs it automatically before starting it.
|
|
// The database is infrastructure, so this must never be invoked for the
|
|
// database service itself (StartContainer guards that).
|
|
func EnsureDatabaseRunning(ctx context.Context) error {
|
|
return ensureInfraRunning(ctx, DatabaseServiceName, "shared database")
|
|
}
|
|
|
|
// EnsureAuthRunning ensures the shared auth service container is running. The
|
|
// auth service is hidden infrastructure: every consumer proxies /auth/* to it
|
|
// and validates action tokens with its key, so it must be up before services
|
|
// that depend on it start. Like the database, it is installed automatically
|
|
// from the registry when it is missing.
|
|
func EnsureAuthRunning(ctx context.Context) error {
|
|
return ensureInfraRunning(ctx, AuthServiceName, "shared auth service")
|
|
}
|
|
|
|
// ensureInfraRunning makes sure a hidden infrastructure container (shared
|
|
// database, shared auth service) is running. When the service is not installed
|
|
// yet it resolves the registry item and installs it first, so a fresh host
|
|
// boots with its infrastructure without manual UI steps. Failures are returned
|
|
// to the caller, which treats them as non-fatal warnings.
|
|
func ensureInfraRunning(ctx context.Context, serviceName, label string) error {
|
|
dc, err := docker.NewDockerClient()
|
|
if err != nil {
|
|
return fmt.Errorf("failed to initialize docker client: %w", err)
|
|
}
|
|
defer dc.Close()
|
|
|
|
if err := EnsureDCNTRLIZEDNetwork(ctx, dc); err != nil {
|
|
return err
|
|
}
|
|
|
|
if infraRunning(ctx, dc, serviceName) {
|
|
return nil
|
|
}
|
|
if !IsInstalled(serviceName) {
|
|
logger.Info("%s %s not installed; installing from the registry...", label, serviceName)
|
|
item, err := libregistry.ItemByName(ctx, serviceName)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to resolve %s %s from the registry: %w", label, serviceName, err)
|
|
}
|
|
if err := InstallContainer(ctx, *item); err != nil {
|
|
return fmt.Errorf("failed to install %s %s: %w", label, serviceName, err)
|
|
}
|
|
}
|
|
|
|
logger.Info("Starting %s %s...", label, serviceName)
|
|
if err := StartContainer(ctx, types.RegistryContainer{Name: serviceName}); err != nil {
|
|
return fmt.Errorf("failed to start %s %s: %w", label, serviceName, err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// infraRunning reports whether the named infrastructure container is currently up.
|
|
func infraRunning(ctx context.Context, dc *docker.DockerClient, serviceName string) bool {
|
|
filter := filters.NewArgs()
|
|
filter.Add("label", "org.dcntrlized.service="+serviceName)
|
|
|
|
containers, err := dc.ContainerList(ctx, container.ListOptions{All: true, Filters: filter})
|
|
if err != nil {
|
|
logger.Warn("Failed to list %s containers: %v", serviceName, err)
|
|
return false
|
|
}
|
|
for _, c := range containers {
|
|
if c.State != "running" && c.State != "restarting" {
|
|
continue
|
|
}
|
|
// Only the canonical container (e.g. "dcntrlized-auth") counts as the
|
|
// shared infrastructure being up. Dev lookalikes (auth-debug) share the
|
|
// role label but must never satisfy the check.
|
|
for _, n := range c.Names {
|
|
if strings.TrimPrefix(n, "/") == serviceName {
|
|
return true
|
|
}
|
|
}
|
|
}
|
|
return false
|
|
}
|