empeira 0.1.0.pre.alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE +661 -0
- data/README.md +150 -0
- data/bin/empeira +18 -0
- data/config/defaults.yaml +229 -0
- data/docs/addons.md +331 -0
- data/docs/architecture.md +277 -0
- data/docs/configuration.md +1204 -0
- data/docs/development.md +472 -0
- data/docs/hiera-and-eyaml.md +361 -0
- data/docs/installation.md +280 -0
- data/docs/networking.md +362 -0
- data/docs/nodes.md +642 -0
- data/docs/proxy.md +136 -0
- data/docs/troubleshooting.md +361 -0
- data/lib/empeira/addons/environment.rb +82 -0
- data/lib/empeira/addons/error.rb +14 -0
- data/lib/empeira/addons/installation.rb +119 -0
- data/lib/empeira/addons/manifest.rb +112 -0
- data/lib/empeira/addons/service.rb +50 -0
- data/lib/empeira/addons/storage.rb +94 -0
- data/lib/empeira/agent/acquisition.rb +120 -0
- data/lib/empeira/agent/artifact.rb +41 -0
- data/lib/empeira/agent/authentication.rb +122 -0
- data/lib/empeira/agent/cache.rb +122 -0
- data/lib/empeira/agent/cache_storage.rb +82 -0
- data/lib/empeira/agent/download.rb +84 -0
- data/lib/empeira/agent/native_commands.rb +84 -0
- data/lib/empeira/agent/release_sources.rb +64 -0
- data/lib/empeira/agent/target.rb +66 -0
- data/lib/empeira/agent/versions.rb +29 -0
- data/lib/empeira/application.rb +86 -0
- data/lib/empeira/build.json +5 -0
- data/lib/empeira/build_info.rb +46 -0
- data/lib/empeira/cli/addons.rb +45 -0
- data/lib/empeira/cli/base.rb +73 -0
- data/lib/empeira/cli/completion.rb +42 -0
- data/lib/empeira/cli/config.rb +22 -0
- data/lib/empeira/cli/main.rb +114 -0
- data/lib/empeira/cli/node.rb +87 -0
- data/lib/empeira/cli/progress.rb +169 -0
- data/lib/empeira/cli/proxy.rb +36 -0
- data/lib/empeira/cli/update.rb +23 -0
- data/lib/empeira/completion/addons.rb +93 -0
- data/lib/empeira/completion/bash.rb +62 -0
- data/lib/empeira/completion/catalog.rb +170 -0
- data/lib/empeira/configuration/additional_services.rb +74 -0
- data/lib/empeira/configuration/addons.rb +85 -0
- data/lib/empeira/configuration/agent_schema.rb +163 -0
- data/lib/empeira/configuration/agent_values.rb +54 -0
- data/lib/empeira/configuration/bootstrap_guests.rb +42 -0
- data/lib/empeira/configuration/command_mocks.rb +65 -0
- data/lib/empeira/configuration/display.rb +20 -0
- data/lib/empeira/configuration/dns_rewrites.rb +58 -0
- data/lib/empeira/configuration/document.rb +67 -0
- data/lib/empeira/configuration/eyaml.rb +46 -0
- data/lib/empeira/configuration/hiera_modulepath.rb +40 -0
- data/lib/empeira/configuration/hiera_mount_schema.rb +62 -0
- data/lib/empeira/configuration/hiera_mounts.rb +83 -0
- data/lib/empeira/configuration/image_schema.rb +68 -0
- data/lib/empeira/configuration/loader.rb +70 -0
- data/lib/empeira/configuration/merge.rb +48 -0
- data/lib/empeira/configuration/network_redirects.rb +73 -0
- data/lib/empeira/configuration/node_images.rb +64 -0
- data/lib/empeira/configuration/schema.rb +215 -0
- data/lib/empeira/configuration/server_mounts.rb +106 -0
- data/lib/empeira/configuration/service_configuration.rb +40 -0
- data/lib/empeira/configuration/ssh_preferences.rb +83 -0
- data/lib/empeira/configuration/user.rb +46 -0
- data/lib/empeira/configuration/vm_interfaces.rb +147 -0
- data/lib/empeira/control_plane/additional_configurations.rb +106 -0
- data/lib/empeira/control_plane/browser.rb +73 -0
- data/lib/empeira/control_plane/controller.rb +763 -0
- data/lib/empeira/control_plane/discovery.rb +69 -0
- data/lib/empeira/control_plane/environment.rb +101 -0
- data/lib/empeira/control_plane/files.rb +263 -0
- data/lib/empeira/control_plane/health.rb +104 -0
- data/lib/empeira/control_plane/plan.rb +356 -0
- data/lib/empeira/control_plane/storage.rb +48 -0
- data/lib/empeira/errors.rb +9 -0
- data/lib/empeira/execution/console.rb +45 -0
- data/lib/empeira/execution/diagnostics.rb +210 -0
- data/lib/empeira/execution/launch_error.rb +14 -0
- data/lib/empeira/execution/result.rb +11 -0
- data/lib/empeira/execution/runner.rb +235 -0
- data/lib/empeira/execution/terminal.rb +35 -0
- data/lib/empeira/hostname_pattern.rb +14 -0
- data/lib/empeira/images/configuration.rb +44 -0
- data/lib/empeira/images/identity.rb +30 -0
- data/lib/empeira/images/recipe.rb +22 -0
- data/lib/empeira/images/reference.rb +43 -0
- data/lib/empeira/images/source.rb +19 -0
- data/lib/empeira/immutable.rb +19 -0
- data/lib/empeira/infrastructure/cleanup.rb +328 -0
- data/lib/empeira/infrastructure/definition.rb +59 -0
- data/lib/empeira/infrastructure/owned_files.rb +63 -0
- data/lib/empeira/infrastructure/recovery_inventory.rb +53 -0
- data/lib/empeira/infrastructure/service.rb +237 -0
- data/lib/empeira/infrastructure/status.rb +73 -0
- data/lib/empeira/infrastructure/store.rb +274 -0
- data/lib/empeira/modules/events.rb +67 -0
- data/lib/empeira/modules/git_safety.rb +60 -0
- data/lib/empeira/modules/host_git.rb +91 -0
- data/lib/empeira/modules/image.rb +27 -0
- data/lib/empeira/modules/installer.rb +67 -0
- data/lib/empeira/modules/request.rb +68 -0
- data/lib/empeira/modules/state.rb +87 -0
- data/lib/empeira/modules/storage.rb +35 -0
- data/lib/empeira/network/bootstrap_proxy.rb +157 -0
- data/lib/empeira/network/definition.rb +61 -0
- data/lib/empeira/network/direct_egress.rb +133 -0
- data/lib/empeira/network/egress.rb +27 -0
- data/lib/empeira/network/gateway.rb +79 -0
- data/lib/empeira/network/host_policy.rb +53 -0
- data/lib/empeira/network/naming.rb +28 -0
- data/lib/empeira/network/peer/adapter_image.rb +32 -0
- data/lib/empeira/network/peer/allocation.rb +45 -0
- data/lib/empeira/network/peer/attachment.rb +27 -0
- data/lib/empeira/network/peer/backend.rb +108 -0
- data/lib/empeira/network/peer/channel.rb +133 -0
- data/lib/empeira/network/peer/channel_server.rb +71 -0
- data/lib/empeira/network/peer/docker_adapter.rb +165 -0
- data/lib/empeira/network/peer/helper_security.rb +40 -0
- data/lib/empeira/network/peer/layout.rb +55 -0
- data/lib/empeira/network/peer/linux_podman.rb +114 -0
- data/lib/empeira/network/peer/podman_machine.rb +112 -0
- data/lib/empeira/network/policy.rb +39 -0
- data/lib/empeira/network/proxy_bindings.rb +52 -0
- data/lib/empeira/network/proxy_policy.rb +64 -0
- data/lib/empeira/network/redirects.rb +89 -0
- data/lib/empeira/network/resource.rb +50 -0
- data/lib/empeira/node/agent_installer.rb +31 -0
- data/lib/empeira/node/agent_package.rb +125 -0
- data/lib/empeira/node/agent_repository.rb +160 -0
- data/lib/empeira/node/apt_configuration.rb +85 -0
- data/lib/empeira/node/bootstrap.rb +17 -0
- data/lib/empeira/node/certificates.rb +98 -0
- data/lib/empeira/node/command_mock.rb +38 -0
- data/lib/empeira/node/command_mocks.rb +114 -0
- data/lib/empeira/node/container.rb +134 -0
- data/lib/empeira/node/container_agent_bootstrap.rb +43 -0
- data/lib/empeira/node/container_bootstrap.rb +52 -0
- data/lib/empeira/node/container_guest.rb +42 -0
- data/lib/empeira/node/container_lifecycle.rb +145 -0
- data/lib/empeira/node/container_preparation.rb +144 -0
- data/lib/empeira/node/container_state.rb +129 -0
- data/lib/empeira/node/definition.rb +20 -0
- data/lib/empeira/node/diagnostic_command.rb +19 -0
- data/lib/empeira/node/dnf_agent_repository.rb +202 -0
- data/lib/empeira/node/external_fact.rb +21 -0
- data/lib/empeira/node/image.rb +38 -0
- data/lib/empeira/node/interactive_tools.rb +33 -0
- data/lib/empeira/node/interface.rb +18 -0
- data/lib/empeira/node/inventory.rb +143 -0
- data/lib/empeira/node/package_bootstrap.rb +129 -0
- data/lib/empeira/node/package_proxy.rb +102 -0
- data/lib/empeira/node/package_sources.rb +19 -0
- data/lib/empeira/node/puppet_command.rb +12 -0
- data/lib/empeira/node/rpm_configuration.rb +62 -0
- data/lib/empeira/node/run_request.rb +52 -0
- data/lib/empeira/node/runtime_proxy.rb +86 -0
- data/lib/empeira/node/service.rb +72 -0
- data/lib/empeira/node/ssh_client.rb +25 -0
- data/lib/empeira/node/ssh_credentials.rb +78 -0
- data/lib/empeira/node/ssh_endpoint.rb +58 -0
- data/lib/empeira/node/ssh_identity.rb +37 -0
- data/lib/empeira/node/user_ssh.rb +60 -0
- data/lib/empeira/node/vm.rb +89 -0
- data/lib/empeira/node/vm_bootstrap.rb +53 -0
- data/lib/empeira/node/vm_lifecycle.rb +212 -0
- data/lib/empeira/node/vm_preflight.rb +37 -0
- data/lib/empeira/node/vm_preparation.rb +161 -0
- data/lib/empeira/node/vm_state.rb +161 -0
- data/lib/empeira/platform/facts.rb +66 -0
- data/lib/empeira/platform/kvm.rb +91 -0
- data/lib/empeira/platform/locations.rb +51 -0
- data/lib/empeira/platform/resolvers.rb +85 -0
- data/lib/empeira/platform/routes.rb +50 -0
- data/lib/empeira/progress.rb +70 -0
- data/lib/empeira/project_root.rb +47 -0
- data/lib/empeira/providers/lifecycle.rb +96 -0
- data/lib/empeira/providers/registry.rb +21 -0
- data/lib/empeira/providers/resource.rb +32 -0
- data/lib/empeira/providers.rb +55 -0
- data/lib/empeira/runtime/agent_helper.rb +34 -0
- data/lib/empeira/runtime/container.rb +184 -0
- data/lib/empeira/runtime/diagnostic_execution.rb +52 -0
- data/lib/empeira/runtime/docker.rb +87 -0
- data/lib/empeira/runtime/image_metadata.rb +83 -0
- data/lib/empeira/runtime/interface.rb +8 -0
- data/lib/empeira/runtime/mount_probe.rb +57 -0
- data/lib/empeira/runtime/podman.rb +122 -0
- data/lib/empeira/runtime/recipe_build.rb +103 -0
- data/lib/empeira/runtime/registry_diagnostics.rb +23 -0
- data/lib/empeira/runtime/service_arguments.rb +55 -0
- data/lib/empeira/runtime/service_images.rb +118 -0
- data/lib/empeira/runtime/service_inspection.rb +159 -0
- data/lib/empeira/runtime/services.rb +120 -0
- data/lib/empeira/runtime/update_helper.rb +97 -0
- data/lib/empeira/runtime/workspace_network.rb +69 -0
- data/lib/empeira/server/environment_configuration.rb +53 -0
- data/lib/empeira/server/http.rb +38 -0
- data/lib/empeira/server/puppetdb_runtime.rb +74 -0
- data/lib/empeira/server/relay_certificate.rb +76 -0
- data/lib/empeira/server/runtime.rb +90 -0
- data/lib/empeira/services/definition.rb +42 -0
- data/lib/empeira/updates/images.rb +104 -0
- data/lib/empeira/updates/modules.rb +45 -0
- data/lib/empeira/updates/service.rb +45 -0
- data/lib/empeira/version_requirement.rb +23 -0
- data/lib/empeira/vm/agent.rb +66 -0
- data/lib/empeira/vm/bootstrap_requirements.rb +69 -0
- data/lib/empeira/vm/certificate_runtime.rb +30 -0
- data/lib/empeira/vm/cloud_init.rb +171 -0
- data/lib/empeira/vm/disk.rb +136 -0
- data/lib/empeira/vm/guest.rb +123 -0
- data/lib/empeira/vm/guest_channel.rb +110 -0
- data/lib/empeira/vm/guest_network.rb +94 -0
- data/lib/empeira/vm/guest_output.rb +52 -0
- data/lib/empeira/vm/guest_shell.rb +79 -0
- data/lib/empeira/vm/guest_upload.rb +43 -0
- data/lib/empeira/vm/image_cache.rb +77 -0
- data/lib/empeira/vm/image_source.rb +91 -0
- data/lib/empeira/vm/interface.rb +8 -0
- data/lib/empeira/vm/interface_ownership.rb +124 -0
- data/lib/empeira/vm/interface_routes.rb +101 -0
- data/lib/empeira/vm/interfaces.rb +240 -0
- data/lib/empeira/vm/management.rb +73 -0
- data/lib/empeira/vm/prerequisites.rb +42 -0
- data/lib/empeira/vm/qemu.rb +83 -0
- data/lib/empeira/vm/qemu_runtime.rb +404 -0
- data/lib/empeira/vm/removal.rb +30 -0
- data/lib/empeira/vm/root_disk.rb +92 -0
- data/lib/empeira/vm/session_lock.rb +56 -0
- data/lib/empeira/vm/system_ssh.rb +29 -0
- data/lib/empeira/workspace.rb +42 -0
- data/lib/empeira.rb +209 -0
- data/resources/browser/relay.rb +22 -0
- data/resources/gateway/Containerfile +8 -0
- data/resources/gateway/bridge.rb +66 -0
- data/resources/gateway/configure.rb +323 -0
- data/resources/modules/Containerfile +15 -0
- data/resources/modules/Gemfile +5 -0
- data/resources/modules/Gemfile.lock +105 -0
- data/resources/modules/worker.rb +161 -0
- data/resources/network/adapter/Containerfile +13 -0
- data/resources/network/adapter/bridge_linux.go +51 -0
- data/resources/network/adapter/framing.go +45 -0
- data/resources/network/adapter/framing_test.go +53 -0
- data/resources/network/adapter/go.mod +3 -0
- data/resources/network/adapter/main_linux.go +273 -0
- data/resources/network/channel.rb +18 -0
- data/resources/network/ssh_connect.rb +32 -0
- data/resources/nodes/apt_sources.rb +66 -0
- data/resources/nodes/debian/Containerfile +10 -0
- data/resources/nodes/diagnostic_exec.rb +109 -0
- data/resources/nodes/interactive_tools.rb +139 -0
- data/resources/nodes/managed_file.rb +91 -0
- data/resources/nodes/management/guest_agent.py +415 -0
- data/resources/nodes/management/setup.sh +20 -0
- data/resources/nodes/management/shell_rc.sh +12 -0
- data/resources/nodes/management/system_account.sh +24 -0
- data/resources/nodes/management/system_home.sh +15 -0
- data/resources/nodes/rpm/Containerfile +10 -0
- data/resources/nodes/runtime_proxy.rb +244 -0
- data/resources/nodes/ssh/proxy.rb +16 -0
- data/resources/nodes/ssh/sshd_config +15 -0
- data/resources/nodes/ssh/start +6 -0
- data/resources/proxy/Containerfile +10 -0
- data/resources/relay/Containerfile +5 -0
- data/resources/relay/puppetdb.rb +81 -0
- data/resources/relay/server_environment.rb +10 -0
- data/resources/relay/server_start.sh +41 -0
- metadata +326 -0
data/docs/nodes.md
ADDED
|
@@ -0,0 +1,642 @@
|
|
|
1
|
+
# Nodes
|
|
2
|
+
|
|
3
|
+
Create nodes imperatively after `empeira up`; named nodes do not belong in
|
|
4
|
+
`.empeira.yaml`. `node run HOSTNAME` defaults to `container`; select `--provider vm` for a VM.
|
|
5
|
+
Existing-node commands use the provider recorded in workspace state.
|
|
6
|
+
|
|
7
|
+
```console
|
|
8
|
+
empeira node run host1 --provider container --os ubuntu --version 24.04
|
|
9
|
+
empeira node run vm1 --provider vm --memory 2048 --cpus 2
|
|
10
|
+
empeira node list
|
|
11
|
+
empeira node puppet host1
|
|
12
|
+
empeira node logs host1
|
|
13
|
+
empeira node exec host1 -- id
|
|
14
|
+
empeira node shell host1
|
|
15
|
+
empeira node console vm1
|
|
16
|
+
empeira node ssh host1
|
|
17
|
+
empeira node stop host1
|
|
18
|
+
empeira node start host1
|
|
19
|
+
empeira node destroy host1
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
The default node is Ubuntu 24.04, 1024 MiB, and two CPUs. External traffic requires
|
|
23
|
+
an explicit TCP egress rule or an allowlisted proxy policy. If the workspace proxy
|
|
24
|
+
is enabled, the node automatically gets
|
|
25
|
+
controlled HTTP/HTTPS access to destinations allowed by its proxy policy.
|
|
26
|
+
Hostname/certname is unique across both providers within a workspace. Names are
|
|
27
|
+
normalized to lowercase; service names are reserved. Another checkout may reuse
|
|
28
|
+
the same hostname. Before the first Puppet run, Empeira installs
|
|
29
|
+
`/etc/puppetlabs/facter/facts.d/empeira.yaml` with exactly one structured fact:
|
|
30
|
+
|
|
31
|
+
```yaml
|
|
32
|
+
empeira:
|
|
33
|
+
provider: container
|
|
34
|
+
hierarchy: empeira
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
VM nodes use `provider: vm`. Both providers verify this readable external fact before
|
|
38
|
+
enrollment; Facter's normal `facts.virtual` remains unchanged. The fixed
|
|
39
|
+
`hierarchy: empeira` selector enables [shared Hiera overrides](hiera-and-eyaml.md).
|
|
40
|
+
Existing provisioned nodes receive the updated fact on `up`, `node start` or
|
|
41
|
+
`node puppet`; unchanged fact revisions require no extra guest probe.
|
|
42
|
+
|
|
43
|
+
New nodes use their full inventory name as the kernel hostname, including multiple
|
|
44
|
+
domain components, with a maximum of 64 bytes. Containers already supply that name
|
|
45
|
+
to the runtime; new VMs persist it through cloud-init (`prefer_fqdn_over_hostname`),
|
|
46
|
+
`/etc/hostname` and `/etc/hosts`. A guest cloud-init fragment preserves the initialized
|
|
47
|
+
hostname on later boots, including after temporary seed configuration is removed.
|
|
48
|
+
`hostname` and `hostname -f` return the FQDN, while
|
|
49
|
+
Facter keeps its native short `networking.hostname`, domain and full
|
|
50
|
+
`networking.fqdn`. Puppet certname remains the inventory name. Only guest files are
|
|
51
|
+
configured; the physical host is never changed.
|
|
52
|
+
|
|
53
|
+
Existing VMs retain their hostname configuration: Puppet may already manage those
|
|
54
|
+
files, so `up` and `node start` do not overwrite them. Recreate an old VM to apply
|
|
55
|
+
the new FQDN initialization. Stop/start preserves the new configuration unless
|
|
56
|
+
Puppet or the guest administrator deliberately changes it.
|
|
57
|
+
|
|
58
|
+
Creation reserves identity atomically, including failed attempts.
|
|
59
|
+
`stop` preserves the disk and identity, `start` resumes them, and `destroy` permanently
|
|
60
|
+
removes the owned resource before releasing the name. Its public CA key fingerprint
|
|
61
|
+
is retained for verified cleanup before the next enrollment under that name.
|
|
62
|
+
Puppet exit codes 0 and 2 succeed. A failed catalog retains diagnostic state.
|
|
63
|
+
|
|
64
|
+
Puppet output uses ANSI colors when both stdout and stderr are terminals. Redirecting
|
|
65
|
+
either stream, setting `CI`, using `TERM=dumb`, or setting `NO_COLOR` disables Puppet
|
|
66
|
+
colors. Container and VM runs use the same policy. The progress display is suspended
|
|
67
|
+
while Puppet streams its output and resumes on a fresh line afterward.
|
|
68
|
+
|
|
69
|
+
`node list` reports observed runtime state and the last Puppet result without
|
|
70
|
+
waiting for guest readiness. `node puppet` verifies node ownership, completed
|
|
71
|
+
bootstrap and running state, then
|
|
72
|
+
streams the agent immediately. Container access also verifies workspace network
|
|
73
|
+
ownership and isolation, permitted attachments and SSH ports. It performs no
|
|
74
|
+
server-readiness check, infrastructure
|
|
75
|
+
reconciliation, guest configuration, command-mock update or VM disk inspection.
|
|
76
|
+
If the server is unavailable, the agent reports its native error and Empeira saves
|
|
77
|
+
the exit code. Apply configuration changes with `up` or resume with `node start`.
|
|
78
|
+
`node logs` streams runtime output for containers and the serial log for VMs.
|
|
79
|
+
Node deletion uses host/runtime mechanisms and requires no running guest or CA.
|
|
80
|
+
The retired public certificate fingerprint remains in workspace inventory; creating
|
|
81
|
+
the same hostname later cleans only its matching CA identity before enrollment.
|
|
82
|
+
Whole-workspace `destroy` removes the CA together with nodes.
|
|
83
|
+
|
|
84
|
+
## Environment cache and live code
|
|
85
|
+
|
|
86
|
+
Managed servers enforce native `[server] environment_timeout = 0` before startup
|
|
87
|
+
and verify the effective setting during `up`, independently of image environment
|
|
88
|
+
variable support. Existing workspaces adopt it on
|
|
89
|
+
their next `up`; run that once after updating from a version that enabled caching.
|
|
90
|
+
Each catalog request reloads live control code, modules and mounted Hiera data.
|
|
91
|
+
Empeira does not hash these trees,
|
|
92
|
+
persist content checkpoints or call the environment-cache admin API. Code edits
|
|
93
|
+
need neither `up` nor a server restart, including for agents invoked manually.
|
|
94
|
+
Empeira does not enable `use_cached_catalog`.
|
|
95
|
+
|
|
96
|
+
A repository's own `environment.conf` can override the server timeout; use zero
|
|
97
|
+
for immediate edits. Avoid concurrent edits during a catalog run. Existing files
|
|
98
|
+
and directories in projected environments stay live through read-only links.
|
|
99
|
+
New siblings under ancestors projected for nested Hiera mounts require `up` to
|
|
100
|
+
create their links. `node start` resumes the node without invoking Puppet; Puppet
|
|
101
|
+
services enabled by a catalog may run independently on startup.
|
|
102
|
+
|
|
103
|
+
## Distribution package sources
|
|
104
|
+
|
|
105
|
+
The reviewed Ubuntu container recipes retain the upstream distribution sources.
|
|
106
|
+
Ubuntu 24.04 uses `/etc/apt/sources.list.d/ubuntu.sources` (deb822); older images may
|
|
107
|
+
use `/etc/apt/sources.list`. VM Cloud-Init leaves the base image's APT configuration
|
|
108
|
+
untouched. It does not generate archive, security, ports, or internal repository
|
|
109
|
+
entries.
|
|
110
|
+
|
|
111
|
+
For either agent installation method, Empeira handles `bootstrap.packages` against
|
|
112
|
+
the base image's sources first. A disposable host-side helper resolves the selected
|
|
113
|
+
agent source using the target OS and architecture. The agent artifact is acquired
|
|
114
|
+
and normally reused from the shared user cache, then uploaded through the existing
|
|
115
|
+
container or VM transport and installed locally with APT/DNF. Agent repositories
|
|
116
|
+
and repository credentials never need to be installed on the node. Valid cached
|
|
117
|
+
artifacts are reused offline without HTTP authentication or login, including private
|
|
118
|
+
sources. Missing dependencies may still use the node's unchanged base repositories
|
|
119
|
+
through the short-lived bootstrap proxy, so installation can still need network access.
|
|
120
|
+
|
|
121
|
+
Empeira archives `/etc/apt` for Ubuntu or `/etc/yum.repos.d` and `/etc/dnf` for RPM
|
|
122
|
+
guests. Uploaded packages, temporary signing keys and proxy configuration are
|
|
123
|
+
removed, and the archive is restored and verified before bootstrap access is
|
|
124
|
+
removed, certificate enrollment completes and the first catalog runs. A failure
|
|
125
|
+
retains the incomplete node for diagnostics and prevents Puppet. Already
|
|
126
|
+
provisioned nodes are not bootstrapped again by `up` or `node start`. See
|
|
127
|
+
[agent sources and caching](configuration.md#agent-sources-and-shared-package-cache)
|
|
128
|
+
for generic sources, version resolution, optional verification and HTTP login.
|
|
129
|
+
|
|
130
|
+
Bootstrap command failures include the operation, native stdout/stderr, exit code
|
|
131
|
+
and timeout status with secrets redacted. Internal VM SSH confirms the guest exit
|
|
132
|
+
status separately from its transport status. Once the APT archive is restored and
|
|
133
|
+
compared successfully, a clearly transient SSH failure deleting that backup is
|
|
134
|
+
retried once, with a warning. Only the idempotent removal is repeated; packages and
|
|
135
|
+
restoration are not replayed. Native errors, missing completion status, command
|
|
136
|
+
timeouts and a second transport failure stop provisioning. Incomplete nodes are not automatically
|
|
137
|
+
resumed across commands; inspect the retained backup, then correct and recreate.
|
|
138
|
+
|
|
139
|
+
After restoration and before the first catalog, both node providers perform the same
|
|
140
|
+
read-only check for active Ubuntu/Debian distribution APT sources. Legacy `.list`
|
|
141
|
+
and deb822 `.sources` files are accepted. A missing/disabled source fails with an
|
|
142
|
+
actionable error and retains the node for inspection. No source is rewritten on
|
|
143
|
+
`up` or `node start`: repository ownership after bootstrap belongs to the tested
|
|
144
|
+
Puppet code. If a catalog purges unmanaged sources without declaring replacements,
|
|
145
|
+
the control repository must fix that classification. Check both source locations;
|
|
146
|
+
an empty `sources.list.d` alone does not prove that APT has no sources.
|
|
147
|
+
|
|
148
|
+
Source configuration does not grant egress. Managed VM agent installation uses the
|
|
149
|
+
temporary authenticated bootstrap proxy with reviewed base-distribution destinations.
|
|
150
|
+
Agent acquisition uses host/helper access, outside the isolated node network. After
|
|
151
|
+
bootstrap, normal access depends on the workspace proxy. Interactive `apt-get update`
|
|
152
|
+
or package resources need an enabled proxy and an explicit destination policy as described in
|
|
153
|
+
[networking](networking.md). Empeira never grants unrestricted Internet access to
|
|
154
|
+
repair package sources.
|
|
155
|
+
|
|
156
|
+
Normal APT/DNF proxy settings persist across restart and work for Puppet package
|
|
157
|
+
resources. Managed Puppet runs receive the current proxy environment directly,
|
|
158
|
+
without relying on login initialization. Login shells also load the owned
|
|
159
|
+
`/etc/profile.d/90-empeira-proxy.sh`. This file clears stale container environment
|
|
160
|
+
variables when proxy access is disabled; repository files are never replaced.
|
|
161
|
+
|
|
162
|
+
## Shell and SSH
|
|
163
|
+
|
|
164
|
+
After agent installation, Empeira detects the installed `puppet` and `facter`
|
|
165
|
+
directory and exposes it through `/etc/profile.d/90-empeira-tools.sh`. An owned
|
|
166
|
+
block in the existing global Bash initializer covers interactive non-login Bash.
|
|
167
|
+
Login SSH, serial-console logins and container shells share this configuration.
|
|
168
|
+
It preserves existing PATH entries, adds the directory once, and leaves
|
|
169
|
+
non-interactive PATH and personal startup files unchanged. Existing nodes receive
|
|
170
|
+
the setting on `up` and `node start`. Custom personal
|
|
171
|
+
startup files can still deliberately override their environment; they should
|
|
172
|
+
retain the distribution's global initialization. Modified owned fragments or
|
|
173
|
+
unsafe global paths stop reconciliation with a diagnosis.
|
|
174
|
+
|
|
175
|
+
| Provider | `node exec` | `node shell` | `node console` | `node ssh` |
|
|
176
|
+
| --- | --- | --- | --- | --- |
|
|
177
|
+
| Container | Native runtime execution as UID 0 | Native interactive root Bash | Not available | Real OpenSSH to the guest daemon |
|
|
178
|
+
| VM | Private VirtIO execution as UID 0 | Private VirtIO root PTY, Bash or POSIX sh | Direct QEMU serial console with guest login | Real OpenSSH to the guest daemon |
|
|
179
|
+
|
|
180
|
+
Direct access is useful for repair even when SSH, PAM, login profiles or network
|
|
181
|
+
configuration is broken. SSH exercises the login path that Puppet actually configures.
|
|
182
|
+
None of these commands starts a stopped node implicitly. Use `node start` first.
|
|
183
|
+
Both retain normal interactive output without a progress overlay.
|
|
184
|
+
|
|
185
|
+
For container nodes, the default SSH username is the local execution user's account
|
|
186
|
+
name (the Linux account on WSL2). Default keys, `ssh-agent` and normal OpenSSH
|
|
187
|
+
configuration remain available. Configure that user, its authorized keys and daemon
|
|
188
|
+
through Puppet or guest configuration.
|
|
189
|
+
|
|
190
|
+
For VM nodes, the default is the existing Cloud-Init account `empeira` and its
|
|
191
|
+
managed private key. Password and keyboard-interactive authentication are disabled;
|
|
192
|
+
the client selects the supplied identity without offering unrelated agent keys.
|
|
193
|
+
`--user`, `--identity` and `--port` independently override these defaults. The guest
|
|
194
|
+
system SSH port defaults to 22. Missing or unsafe
|
|
195
|
+
managed keys fail before connection, without generating a replacement. This access
|
|
196
|
+
also works for incomplete nodes once the VM and SSH daemon are running.
|
|
197
|
+
An authentication failure remains an SSH failure, with the client's output and
|
|
198
|
+
exit status. It never creates a login user, injects keys, or falls back to exec.
|
|
199
|
+
|
|
200
|
+
Optional personal defaults and hostname rules in `~/.empeira.yaml` apply to this
|
|
201
|
+
interactive command. Each field uses CLI override, last matching rule, global
|
|
202
|
+
preference, then provider default, in that order. Rules match full hostnames with
|
|
203
|
+
case-insensitive `*`/`?` globs; omitted fields preserve their existing value.
|
|
204
|
+
See [personal SSH configuration](configuration.md#optional-user-preferences) for
|
|
205
|
+
the schema and identity-file checks. VM management uses its private VirtIO channel
|
|
206
|
+
for bootstrap, enrollment and Puppet independently of these preferences.
|
|
207
|
+
SSH preferences do not affect `exec`, `shell` or `console`.
|
|
208
|
+
|
|
209
|
+
```console
|
|
210
|
+
empeira node ssh host1
|
|
211
|
+
empeira node ssh host1 --user deploy
|
|
212
|
+
empeira node ssh host1 --identity ~/.ssh/test_ed25519
|
|
213
|
+
empeira node ssh host1 --user deploy --identity ~/.ssh/test_ed25519
|
|
214
|
+
empeira node ssh host1 --port 2222
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
The three SSH overrides are independent. The logical hostname can select a `Host`
|
|
218
|
+
section in SSH configuration. Empeira fixes the host, port and transport to the owned
|
|
219
|
+
node, disables connection sharing and forwarding, and uses a private per-node
|
|
220
|
+
`known_hosts` file with `accept-new` checking. User settings cannot redirect the
|
|
221
|
+
connection through another proxy or jump host. Container logins retain the developer's
|
|
222
|
+
normal SSH agent behavior. Host-key changes fail until investigated; disposable host entries
|
|
223
|
+
are removed with the node and do not pollute `~/.ssh/known_hosts`.
|
|
224
|
+
|
|
225
|
+
Podman publishes SSH on a verified dynamic loopback port. Docker's internal bridge
|
|
226
|
+
does not activate published ports, so OpenSSH uses a runtime exec byte tunnel to
|
|
227
|
+
port 22 inside the ownership-checked container. This still carries real SSH traffic.
|
|
228
|
+
An explicit container guest port uses the same ownership-checked runtime tunnel,
|
|
229
|
+
without another host publication. VM SSH connects directly to the system daemon
|
|
230
|
+
on the owned peer IP and selected guest port (22 by default). Native rootless
|
|
231
|
+
Podman uses a capless peer client alongside its existing TAP; Docker uses its
|
|
232
|
+
existing adapter as an internal IP peer, and Podman machine uses its capless
|
|
233
|
+
staging adapter. No host route is added. No management command, authentication or
|
|
234
|
+
forwarding is needed.
|
|
235
|
+
Unavailable system SSH reports the native OpenSSH error without repair or fallback.
|
|
236
|
+
|
|
237
|
+
New VM records have `management_layout: 1`. Cloud-Init starts and enables
|
|
238
|
+
`empeira-management.service` before project scripts and package bootstrap.
|
|
239
|
+
The selected cloud image must already provide Python 3 (`/usr/bin/python3` or Rocky Linux's
|
|
240
|
+
`/usr/libexec/platform-python`); the adapter uses
|
|
241
|
+
only its standard library, so management needs no package download before it can
|
|
242
|
+
install the agent. The service runs with numeric UID/GID 0 and opens the dedicated
|
|
243
|
+
`org.empeira.management.0` VirtIO-Serial port. It has no SSH, PAM, sudo, password,
|
|
244
|
+
NSS login, authorized-key or network-port dependency. Puppet can set root shadow
|
|
245
|
+
to `!`, replace sudoers, remove regular users and groups, or restart/disable system
|
|
246
|
+
SSH without losing management. No root-password repair occurs after a catalog.
|
|
247
|
+
|
|
248
|
+
Before commands, the owned QEMU monitor verifies workspace, hostname and instance.
|
|
249
|
+
The host management socket lives in a private 0700 directory, is mode 0600, and
|
|
250
|
+
must match its recorded device/inode. The protocol also verifies the instance and
|
|
251
|
+
operation identity. Management has no host-published port, network NIC or SSH key.
|
|
252
|
+
Commands run in the normal guest filesystem with owned process groups. stdout and
|
|
253
|
+
stderr stream without truncation. Confirmed native exits (including 4, 6 and 255)
|
|
254
|
+
are distinct from transport failure; timeout and interruption terminate the owned
|
|
255
|
+
group. Guest commands do not inherit the service's `RUNTIME_DIRECTORY`, so
|
|
256
|
+
OpenVox retains its normal agent runtime directory. A failed catalog retains the
|
|
257
|
+
provisioned VM and can be retried.
|
|
258
|
+
|
|
259
|
+
Uploads stage in root-owned 0700 `/run/empeira-management`, verify SHA-256 and
|
|
260
|
+
atomically install the requested contents and mode. Staging is removed on success,
|
|
261
|
+
failure or disconnect. Management remains available across stop/start; the new
|
|
262
|
+
socket identity is recorded for each launch. It does not continuously poll idle
|
|
263
|
+
VMs or reconcile the whole guest before each Puppet run.
|
|
264
|
+
|
|
265
|
+
Cloud-Init creates the locked Linux system account `empeira` once for the default
|
|
266
|
+
interactive `node ssh` login, with `/bin/bash`, a dynamically allocated system UID
|
|
267
|
+
and private `/var/lib/empeira` home. Its public key goes into that home's
|
|
268
|
+
`.ssh/authorized_keys`. No sudo grant is added. Puppet owns subsequent account,
|
|
269
|
+
key, home and system-SSHD changes. Authentication failures never cause repairs.
|
|
270
|
+
|
|
271
|
+
If management is unavailable, Empeira preserves the overlay and reports unknown
|
|
272
|
+
guest completion without replaying installation. Use `node console` for the private
|
|
273
|
+
serial console and `node logs` for the serial log. In the console inspect
|
|
274
|
+
`journalctl -u empeira-management.service`, `cloud-init status --long`, the
|
|
275
|
+
VirtIO port, Python 3 and the unit. Console passwords apply only during initial
|
|
276
|
+
seed setup and remain under Puppet's control afterward. Removing Python, the
|
|
277
|
+
management unit, VirtIO support or the root filesystem can still interrupt this
|
|
278
|
+
privileged guest facility; there is no authentication fallback or automatic deletion.
|
|
279
|
+
|
|
280
|
+
Earlier management layouts fail before normal operation. Use the current
|
|
281
|
+
`node destroy` to remove the positively identified VM, then recreate it. Destroy
|
|
282
|
+
does not require a compatible guest management layout or working guest. `management_layout` and socket identity are internal inventory metadata,
|
|
283
|
+
not YAML options.
|
|
284
|
+
|
|
285
|
+
Packaged container images install and start OpenSSH, generating host keys at first
|
|
286
|
+
startup. They enable public-key login with `.ssh/authorized_keys`; password and
|
|
287
|
+
keyboard-interactive login are initially disabled. They do not provision developer
|
|
288
|
+
accounts or authorized keys. Puppet may manage the daemon and authentication policy.
|
|
289
|
+
Custom node images must provide the corresponding startup and package-manager contract.
|
|
290
|
+
|
|
291
|
+
Empeira uses the private privileged VirtIO channel internally to install the VM agent,
|
|
292
|
+
enroll certificates and run Puppet. User-facing SSH opens an ordinary interactive
|
|
293
|
+
login without the internal provisioning command or automatic sudo.
|
|
294
|
+
|
|
295
|
+
VM exec, shell, SSH and serial sessions release the workspace mutation lock after ownership and
|
|
296
|
+
running-state checks. Parallel sessions and read-only status remain available. A
|
|
297
|
+
shared instance guard prevents `node stop`, `node destroy` or restart from replacing
|
|
298
|
+
the VM while a session is attached; detach first and retry the conflicting operation.
|
|
299
|
+
Other nodes and workspace commands can proceed. Instance lock files stay stable;
|
|
300
|
+
their open descriptors are released on detach, disconnect, errors and signals.
|
|
301
|
+
|
|
302
|
+
## Root diagnostic commands and interactive shell
|
|
303
|
+
|
|
304
|
+
```console
|
|
305
|
+
empeira node exec host1 -- id
|
|
306
|
+
empeira node exec host1 --timeout 120 -- journalctl -u ssh.service -n 100 --no-pager
|
|
307
|
+
empeira node exec host1 -- sh -c 'echo hello && id'
|
|
308
|
+
empeira node shell host1
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
Everything after `--` is a literal guest argument vector. Shell operators are
|
|
312
|
+
interpreted only when you explicitly run a shell such as `sh -c`. stdout and stderr
|
|
313
|
+
stream separately without truncation or saved transcripts. The CLI returns the
|
|
314
|
+
confirmed guest exit status, including 255. Missing executables return 127. Transport
|
|
315
|
+
or unconfirmed cancellation failures report an error and retain the node; they are
|
|
316
|
+
never treated as confirmed guest exits.
|
|
317
|
+
|
|
318
|
+
Exec has no default timeout. `--timeout` accepts positive seconds up to 86400;
|
|
319
|
+
timeout returns 124 after controlled guest process-group cleanup. Ctrl+C cancels the
|
|
320
|
+
owned session and its process groups. Internal bootstrap and Puppet deadlines keep
|
|
321
|
+
their existing values. Container exec uses the agent's embedded Ruby interpreter
|
|
322
|
+
as a guest-only cancellation supervisor; a container without that interpreter cannot
|
|
323
|
+
confirm this diagnostic protocol and reports a transport failure. In process-init
|
|
324
|
+
containers SSHD is PID 1; stopping that daemon stops the whole container. Native
|
|
325
|
+
exec and shell require a running container. Podman systemd-init containers retain
|
|
326
|
+
root runtime access when the independent SSH service is stopped.
|
|
327
|
+
|
|
328
|
+
VM shell allocates a controlling PTY under numeric UID 0 and invokes Bash with `-i`,
|
|
329
|
+
or the existing POSIX `sh` if Bash is absent. It bypasses login authentication without
|
|
330
|
+
changing shadow, PAM, sudoers or SSHD. A Puppet-managed root shadow value `!` and a
|
|
331
|
+
stopped system SSH daemon do not prevent exec or shell. Both local input and output
|
|
332
|
+
must be terminals; otherwise shell fails clearly before opening a guest session.
|
|
333
|
+
Initial rows/columns and subsequent SIGWINCH resizes reach the guest PTY. ANSI,
|
|
334
|
+
completion, Ctrl+C/D/Z, foreground jobs and full-screen terminal applications use
|
|
335
|
+
normal guest terminal semantics. Shell output uses the PTY's merged stream.
|
|
336
|
+
|
|
337
|
+
Host raw mode exists only for the session and is restored after exit, errors and
|
|
338
|
+
handled termination signals. EOF or transport disconnect closes the PTY and kills
|
|
339
|
+
owned guest session groups. Failed cancellation is reported explicitly. Eight private
|
|
340
|
+
VirtIO slots permit independent concurrent sessions with pinned socket identities
|
|
341
|
+
and nonblocking slot locks; an exhausted pool fails clearly. Existing VMs require
|
|
342
|
+
explicit recreation to receive management layout 2. No network ports or SSH transport
|
|
343
|
+
are added, and no shell input is written to Empeira logs. Diagnostic shells disable
|
|
344
|
+
the default persistent history file; VM Bash startup preserves interactive configuration
|
|
345
|
+
and then makes `HISTFILE=/dev/null` read-only.
|
|
346
|
+
|
|
347
|
+
## Recovery destroy
|
|
348
|
+
|
|
349
|
+
`destroy` and `node destroy` ignore release requirements, current project configuration,
|
|
350
|
+
normal-operation inventory schemas and guest management versions. They use only
|
|
351
|
+
safely interpretable stored ownership plus observed native IDs/labels or the owned
|
|
352
|
+
QEMU monitor identity. Normal operations retain their compatibility gates. Destroy
|
|
353
|
+
never invokes guest commands, starts infrastructure, or requires a Puppetserver.
|
|
354
|
+
|
|
355
|
+
With a missing marker but an existing Git root, invoke destroy from that root.
|
|
356
|
+
If the repository itself has disappeared, supply its former absolute canonical Git
|
|
357
|
+
root path. Invoke these commands from any accessible working directory:
|
|
358
|
+
|
|
359
|
+
```console
|
|
360
|
+
empeira node destroy host1 --project-path /former/control-repo
|
|
361
|
+
empeira destroy --project-path /former/control-repo
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
Empeira derives the existing workspace identity from that path and the same user
|
|
365
|
+
home as before. The repository, marker and current configuration need not exist.
|
|
366
|
+
Use the same platform state location as the original workspace. Selection never
|
|
367
|
+
scans/adopts arbitrary containers by name, and native ownership checks still apply.
|
|
368
|
+
|
|
369
|
+
Already absent resources succeed. A deletion failure retains its node/resource
|
|
370
|
+
record and ownership evidence while other positively identified resources continue
|
|
371
|
+
to be removed. Remaining resources are listed and incomplete cleanup returns nonzero.
|
|
372
|
+
Foreign IDs/labels, unsafe paths, symlinks, unverifiable live QEMU processes and active
|
|
373
|
+
VM session guards block their corresponding deletions. Unknown resource groups remain
|
|
374
|
+
recorded for investigation. Node destroy preserves other nodes and shared services,
|
|
375
|
+
networks and volumes. Workspace destroy removes owned CA/database volumes and generated
|
|
376
|
+
files, preserving the stable mutation-lock inode, control code, modules and shared caches.
|
|
377
|
+
|
|
378
|
+
## VM console recovery
|
|
379
|
+
|
|
380
|
+
Each VM has a private Unix-domain serial socket created by its QEMU process.
|
|
381
|
+
`node console vm1` attaches to that existing endpoint without starting another QEMU.
|
|
382
|
+
Press Enter to obtain a prompt. **Ctrl-] detaches** and leaves the VM running.
|
|
383
|
+
The connection prints the detach instruction. With `vm.console.root_password: null`,
|
|
384
|
+
it also suggests `empeira node ssh vm1`; it does not assign a replacement password.
|
|
385
|
+
Local terminal mode is restored after detach, EOF or errors. Serial access carries
|
|
386
|
+
terminal bytes rather than SSH window-size negotiation; use `stty rows N cols N`
|
|
387
|
+
in the guest when a full-screen program needs different dimensions.
|
|
388
|
+
|
|
389
|
+
The initial recovery login is `root` with password `empeira`:
|
|
390
|
+
|
|
391
|
+
```yaml
|
|
392
|
+
vm:
|
|
393
|
+
console:
|
|
394
|
+
root_password: empeira
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
Set a different string for another initial password, or `null` to leave root password
|
|
398
|
+
configuration to the image/Puppet. The value applies once during cloud-init, only
|
|
399
|
+
to console recovery. It does not enable SSH password authentication. Puppet may
|
|
400
|
+
subsequently change or lock root, and Empeira does not restore this password on
|
|
401
|
+
`start`, `up`, or later Puppet runs. Keep real overrides outside version control.
|
|
402
|
+
|
|
403
|
+
Configuration display redacts the password. It is absent from node inventory,
|
|
404
|
+
image metadata and infrastructure fingerprints. Seed-generation files are private
|
|
405
|
+
and removed after ISO creation. After initial cloud-init, Empeira rewrites the
|
|
406
|
+
host seed without the password and removes guest cloud-init credential payloads.
|
|
407
|
+
The console socket is private to the local user, has a short macOS-compatible path,
|
|
408
|
+
and is separated by workspace and node identity. Node destruction removes it.
|
|
409
|
+
|
|
410
|
+
## VM images and bootstrap
|
|
411
|
+
|
|
412
|
+
Install the [VM prerequisites](installation.md#vm-prerequisites) before creating a
|
|
413
|
+
VM. Capability detection selects KVM or HVF; software emulation is never automatic.
|
|
414
|
+
Preflight checks commands, acceleration, image metadata, scripts, package destinations
|
|
415
|
+
and control-plane readiness before downloads or node reservation.
|
|
416
|
+
|
|
417
|
+
Ubuntu 22.04/24.04 cloud images and Rocky 8/9 GenericCloud images come directly from
|
|
418
|
+
[Ubuntu](https://cloud-images.ubuntu.com/releases/) and
|
|
419
|
+
[Rocky Linux](https://dl.rockylinux.org/pub/rocky/). Availability depends on architecture.
|
|
420
|
+
SHA-256 manifests are fetched over HTTPS and complete images verified before caching.
|
|
421
|
+
The immutable cache identity includes distribution, version, architecture, source,
|
|
422
|
+
revision and checksum. Each VM has a QCOW2 overlay pinned to its original base.
|
|
423
|
+
Destroying a node removes its overlay and seed, preserving the shared base cache.
|
|
424
|
+
|
|
425
|
+
`vm.disk` sets the virtual capacity of new VM overlays in GiB (default `30`, maximum
|
|
426
|
+
`2048`). A capacity smaller than the base image is rejected. The overlay is thin:
|
|
427
|
+
the host stores changed blocks, rather than reserving the entire virtual capacity.
|
|
428
|
+
Sizing is verified before the overlay is published and before QEMU starts.
|
|
429
|
+
Cloud-init grows the actual root partition and filesystem while preserving boot/EFI
|
|
430
|
+
partitions. Empeira verifies disk, partition and filesystem capacity after cloud-init
|
|
431
|
+
and before managed package installation; failed growth retains an incomplete VM for
|
|
432
|
+
diagnosis and prevents enrollment and Puppet. Check `df -h /` through `node ssh`.
|
|
433
|
+
The checks support both integer and decimal-string byte counts from supported
|
|
434
|
+
guest `lsblk` versions, with identical partition and filesystem growth requirements.
|
|
435
|
+
Changing `vm.disk` affects only subsequently created VMs; `up` and `node start`
|
|
436
|
+
preserve existing disks. Container nodes do not use this setting.
|
|
437
|
+
|
|
438
|
+
Cloud-init prepares identity, VirtIO management, the regular SSH login, DNS adapter, console recovery
|
|
439
|
+
and optional project scripts. Managed installation then installs the selected public
|
|
440
|
+
Puppet/OpenVox agent through separate bootstrap proxy access. Normal proxy rules are
|
|
441
|
+
not needed for standard installation. Bootstrap access ends
|
|
442
|
+
when installation completes or fails. See [proxy policy](proxy.md).
|
|
443
|
+
|
|
444
|
+
Incomplete bootstrap retains the VM for `node logs`, `node shell`, inspection and
|
|
445
|
+
explicit `node destroy`. An incomplete VM must be destroyed and recreated before
|
|
446
|
+
it can be started as a ready node. Preflight failures retain no new node.
|
|
447
|
+
|
|
448
|
+
## Additional VM interface lifecycle
|
|
449
|
+
|
|
450
|
+
Configure [additional VM interfaces](configuration.md#additional-vm-interfaces)
|
|
451
|
+
when a production manifest expects a named interface in ordinary networking facts.
|
|
452
|
+
After agent installation and bootstrap cleanup, Empeira creates and verifies the
|
|
453
|
+
matched dummy/VLAN devices before enrollment and the first catalog. Subsequent
|
|
454
|
+
`up` and `node start` reconcile devices and verify Facter; `node puppet` runs the
|
|
455
|
+
agent against the already configured guest.
|
|
456
|
+
Container provisioning and facts are unaffected.
|
|
457
|
+
|
|
458
|
+
`vm.disk` and `vm.interfaces` are independent settings and can be used together.
|
|
459
|
+
On a new VM, root disk growth is verified before package bootstrap, agent installation
|
|
460
|
+
and interface reconciliation. Failed growth retains an incomplete VM without creating
|
|
461
|
+
the additional interfaces or enrolling it. Updating interface rules on an existing VM
|
|
462
|
+
preserves its original disk capacity, even when `vm.disk` has changed.
|
|
463
|
+
|
|
464
|
+
`node start` restores ephemeral interfaces after a VM stop/start, and reconciles an
|
|
465
|
+
already running VM. `empeira up` applies edits to running, provisioned VMs without
|
|
466
|
+
recreating them or invoking Puppet. Stopped VMs take the current rules on their next
|
|
467
|
+
start; incomplete nodes remain blocked. Changing patterns, IPs, prefixes or VLAN
|
|
468
|
+
IDs updates only owned devices. A changed definition recreates that device, while
|
|
469
|
+
unchanged devices keep their Linux identity. Removed rules remove owned devices;
|
|
470
|
+
the parent is removed only after the last VLAN child. No guest network-manager
|
|
471
|
+
configuration or Puppet service configuration is installed. Direct/manual Puppet
|
|
472
|
+
and independently enabled Puppet services follow the existing access contract:
|
|
473
|
+
after a guest reboot, use `node start` or `up` before running them. Empeira guarantees
|
|
474
|
+
restoration before its own managed catalog requests.
|
|
475
|
+
|
|
476
|
+
Ownership combines the workspace and node identities, a random instance token in
|
|
477
|
+
the existing locked inventory, and a definition fingerprint. A derived locally
|
|
478
|
+
administered unicast MAC is assigned in the same netlink request as device creation;
|
|
479
|
+
Linux does not apply the alias at that stage. Empeira then sets and verifies the
|
|
480
|
+
full ownership alias. A missing alias is recoverable only when the recorded intent
|
|
481
|
+
and atomic MAC witness match; a conflicting alias or MAC is refused. Before
|
|
482
|
+
changing or removing a link, Empeira checks that marker, its type, VLAN ID, parent,
|
|
483
|
+
addresses and dependencies. Foreign devices, foreign child links, unexpected
|
|
484
|
+
addresses, renamed links and links attached to another network block reconciliation.
|
|
485
|
+
Names alone confer no ownership. Keep Puppet/network managers from managing these
|
|
486
|
+
test devices concurrently. The shared lab remains a cooperative environment.
|
|
487
|
+
|
|
488
|
+
Each new definition and the accepted previous definition are saved before mutation.
|
|
489
|
+
An SSH timeout or lost completion leaves this intent available for the next `up`,
|
|
490
|
+
`node start` or `node puppet`, which inspects the guest before continuing. Completed
|
|
491
|
+
deletions are observed before ownership is released. A failure during initial
|
|
492
|
+
provisioning retains an incomplete VM and prevents the first catalog; inspect it
|
|
493
|
+
through SSH/console, then destroy/recreate. A later reconcile failure blocks the
|
|
494
|
+
requested operation and keeps the provisioned VM available for repair and retry.
|
|
495
|
+
|
|
496
|
+
To inspect regular facts and Linux VLAN metadata:
|
|
497
|
+
|
|
498
|
+
```console
|
|
499
|
+
empeira node ssh web-one.example.test
|
|
500
|
+
sudo /opt/puppetlabs/bin/facter networking --json
|
|
501
|
+
ip -j -d link show ens192
|
|
502
|
+
ip -j address show ens192
|
|
503
|
+
```
|
|
504
|
+
|
|
505
|
+
Empeira verifies `networking.interfaces.DEVICE.bindings[0].address` and `netmask`
|
|
506
|
+
against the configured IPv4 CIDR. The ordinary Puppet expression works unchanged:
|
|
507
|
+
|
|
508
|
+
```puppet
|
|
509
|
+
$node_src_ip = $facts['networking']['interfaces'][$vlan]['bindings'][0]['address']
|
|
510
|
+
```
|
|
511
|
+
|
|
512
|
+
The [Facter networking contract](https://help.puppet.com/core/current/Content/PuppetCore/Markdown/core_facts.htm)
|
|
513
|
+
documents IPv4 `bindings`; a VLAN-ID fact is not assumed. VLAN ID and 802.1Q protocol
|
|
514
|
+
are checked separately in `ip -j -d link` output. The managed parent can also appear
|
|
515
|
+
in Facter, without an IPv4 binding. Linux dummy devices can have operational state
|
|
516
|
+
`UNKNOWN` while administratively `UP`; Empeira accepts `UP`/`UNKNOWN`, rejects `DOWN`,
|
|
517
|
+
and checks the exact address and device type.
|
|
518
|
+
|
|
519
|
+
## Node images and fidelity
|
|
520
|
+
|
|
521
|
+
| OS catalog key | Versions | Build source |
|
|
522
|
+
| --- | --- | --- |
|
|
523
|
+
| `ubuntu` | `22.04`, `24.04` | Docker Official Ubuntu images |
|
|
524
|
+
| `rocky` | `8`, `9` | Rocky Linux project images |
|
|
525
|
+
| `almalinux` | `8`, `9` | Docker Official AlmaLinux images |
|
|
526
|
+
| `oraclelinux` | `8` | Docker Official Oracle Linux image |
|
|
527
|
+
|
|
528
|
+
`images.nodes.OS.VERSION` defines the base repository/tag, packaged build recipe and
|
|
529
|
+
allowed `architectures` (`amd64`, `arm64`). The engine architecture is selected
|
|
530
|
+
and the resulting image architecture checked; emulation is never automatic. A
|
|
531
|
+
full `reference` overrides building and must provide the documented shell,
|
|
532
|
+
init mode and networking tools. Agent installation is controlled independently
|
|
533
|
+
by `agent.install` after the node starts.
|
|
534
|
+
|
|
535
|
+
The project-owned [node recipes](../resources/nodes) add SSH and diagnostic
|
|
536
|
+
tools but contain no agent package, source credential or Empeira PATH override.
|
|
537
|
+
The default bootstrap installs the agent version in [built-in defaults](../config/defaults.yaml) through a reviewed,
|
|
538
|
+
SHA-256-pinned release package and native signed APT/DNF repository. Custom
|
|
539
|
+
repository sources or direct verified `.deb`/`.rpm` packages can be configured
|
|
540
|
+
under `agent.install`; the selected server and PuppetDB images do not change.
|
|
541
|
+
Source configuration is restored and bootstrap access removed before certificate
|
|
542
|
+
enrollment and the first Puppet run. Container images remain in the selected
|
|
543
|
+
runtime cache; VM base images use the separate checksum-addressed cache. No
|
|
544
|
+
agent packages or images are bundled in Empeira releases.
|
|
545
|
+
|
|
546
|
+
Runtime tests report the selected OS, init mode and architecture. Systemd and HVF
|
|
547
|
+
need their own capable hosts; amd64 tests do not establish arm64 execution.
|
|
548
|
+
|
|
549
|
+
The Ubuntu base `docker.io/library/ubuntu` is the [official image maintained by
|
|
550
|
+
Canonical](https://hub.docker.com/_/ubuntu); `library` is Docker Hub's official-image
|
|
551
|
+
namespace. The minimal upstream image is extended with `sudo`, `locate` and
|
|
552
|
+
`updatedb` for catalogs that expect these commands before package management runs.
|
|
553
|
+
Ubuntu uses `plocate`; the RPM recipe uses `mlocate`. Puppet remains responsible for
|
|
554
|
+
application packages and sudo policy. No additional sudo grants are installed.
|
|
555
|
+
Run `updatedb` after filesystem changes before relying on `locate` results; process
|
|
556
|
+
mode does not run the distribution's timer or cron daemon. Existing nodes require
|
|
557
|
+
explicit destroy/recreate to receive changed recipe contents. VM images retain
|
|
558
|
+
their upstream package selection.
|
|
559
|
+
|
|
560
|
+
These tools come from the distribution's signed repositories, with package license
|
|
561
|
+
notices retained: [sudo](https://github.com/sudo-project/sudo/blob/main/LICENSE.md)
|
|
562
|
+
uses permissive licenses; [plocate](https://plocate.sesse.net/) and
|
|
563
|
+
[mlocate](https://git.almalinux.org/rpms/mlocate) use GPLv2 licenses. They run as
|
|
564
|
+
separate distribution programs and are not linked into Empeira's AGPL code.
|
|
565
|
+
Review distribution security updates when rebuilding. Cached images do not acquire
|
|
566
|
+
package updates automatically.
|
|
567
|
+
|
|
568
|
+
Default `process` mode uses the runtime's small init and a persistent sleeping process.
|
|
569
|
+
The images contain systemd, but it is not PID 1 in that mode. Explicit
|
|
570
|
+
`node_defaults.init: systemd` requires Podman with cgroup v2. Unsupported runtimes fail
|
|
571
|
+
instead of enabling privileged mode or mounting host cgroups. Systemd mode requires a separate cgroup-v2 integration host. Container catalogs requiring unavailable
|
|
572
|
+
kernel, boot or device functionality fail naturally. VM nodes provide higher
|
|
573
|
+
fidelity when host acceleration and the required QEMU tools are available. The
|
|
574
|
+
provider fact must not be used to hide container limitations.
|
|
575
|
+
|
|
576
|
+
Distribution contents retain their package licenses. Sources include
|
|
577
|
+
[Ubuntu](https://hub.docker.com/_/ubuntu),
|
|
578
|
+
[Rocky Linux](https://github.com/rocky-linux/sig-cloud-instance-images),
|
|
579
|
+
[AlmaLinux](https://github.com/AlmaLinux/docker-images), and
|
|
580
|
+
[Oracle Linux](https://github.com/oracle/container-images).
|
|
581
|
+
The public [OpenVox agent](https://github.com/OpenVoxProject/openvox) and optional
|
|
582
|
+
[Puppet agent](https://github.com/puppetlabs/puppet-agent) use open-source components,
|
|
583
|
+
including Apache-2.0 Puppet/OpenVox code. No RHEL or Puppet Enterprise artifact is used.
|
|
584
|
+
|
|
585
|
+
A configured image change marks existing nodes stale; it never replaces their writable
|
|
586
|
+
state automatically. Destroy/recreate them explicitly. Changing or replacing CoreDNS
|
|
587
|
+
with retained nodes is refused because their resolver bindings must remain valid.
|
|
588
|
+
|
|
589
|
+
## Configuration and stale resources
|
|
590
|
+
|
|
591
|
+
Workspace `mocks.commands` provides generic executable command stubs for Puppet
|
|
592
|
+
tests on both node providers. See [command mock configuration](configuration.md#command-mocks-on-test-nodes)
|
|
593
|
+
for echo and script-forwarding examples and mandatory exit-code selection.
|
|
594
|
+
|
|
595
|
+
Mocks are applied during initial node provisioning and during `node start`,
|
|
596
|
+
including an already running node. `empeira up` reconciles mocks on running nodes
|
|
597
|
+
without restarting them or running Puppet. Stopped nodes reconcile on their next
|
|
598
|
+
start. A configured mock replaces an existing file or symlink at its target and
|
|
599
|
+
is restored if another program overwrites it. Removed entries delete only
|
|
600
|
+
unchanged, ownership-verified stubs. Destroying a node removes its mocks with
|
|
601
|
+
the owned container or VM disk.
|
|
602
|
+
|
|
603
|
+
Managed container nodes must have the agent Ruby at
|
|
604
|
+
`/opt/puppetlabs/puppet/bin/ruby` after agent bootstrap and before mocks can
|
|
605
|
+
be reconciled. If this interpreter is missing, inspect the retained node and
|
|
606
|
+
its image. Both providers record `provisioned: false` until package cleanup,
|
|
607
|
+
bootstrap access removal, final network/configuration and certificate enrollment
|
|
608
|
+
have succeeded. Failed nodes remain `incomplete` and accessible through shell/logs,
|
|
609
|
+
but `node start`, `node puppet` and mock reconciliation are blocked. After diagnosis,
|
|
610
|
+
destroy and recreate the node. A failed first catalog can be retried once provisioning
|
|
611
|
+
is complete. `up` does not install the agent into an existing node.
|
|
612
|
+
|
|
613
|
+
Unsupported inventory schemas fail closed without automatic migration.
|
|
614
|
+
|
|
615
|
+
Existing-node commands still validate the full project configuration. Invalid
|
|
616
|
+
provisioning settings can block shell, SSH, logs or cleanup until corrected.
|
|
617
|
+
Ownership, inventory and version checks remain active on access operations.
|
|
618
|
+
A stale image does not cause automatic replacement. Preserve required data and
|
|
619
|
+
explicitly destroy/recreate a node when changing its image definition.
|
|
620
|
+
|
|
621
|
+
OpenSSH packages come from the selected distribution repositories. Their
|
|
622
|
+
[upstream license notices](https://github.com/openssh/openssh-portable/blob/master/LICENCE)
|
|
623
|
+
remain in the installed packages; the permissive OpenSSH licenses are compatible
|
|
624
|
+
with project-owned AGPL code. Consult [OpenSSH security advisories](https://www.openssh.com/security.html)
|
|
625
|
+
and distribution updates when refreshing images. `update images` checks native base-image manifest metadata and skips unchanged
|
|
626
|
+
recipes/resources/bases. Required builds use `--pull` and retain native cached
|
|
627
|
+
package-install layers; unchanged inputs do not reinstall packages. Updated bases or recipes cause dependent layers
|
|
628
|
+
to rebuild. The Ruby dependency audit does not audit OS packages.
|
|
629
|
+
|
|
630
|
+
A stopped VM resumes through visible retained-storage, network, QEMU-start and SSH
|
|
631
|
+
readiness milestones. It keeps its existing base/overlay and does not rerun Puppet
|
|
632
|
+
automatically. Container/VM creation and destroy retain their named workflow stages;
|
|
633
|
+
only module and image updates use homogeneous completed/total counts.
|
|
634
|
+
|
|
635
|
+
## Peer network lifetime
|
|
636
|
+
|
|
637
|
+
Container and VM nodes are direct IPv4 peers. Use their logical DNS names from
|
|
638
|
+
other nodes, additional services and Chromium; arbitrary TCP/UDP requires no port
|
|
639
|
+
publication. Stop/start preserves the instance's IP, MAC and DNS record. Destroy
|
|
640
|
+
releases the lease and removes the record and owned transport resources. Recreating
|
|
641
|
+
a name does not promise the previous IP or MAC. VM status includes network health:
|
|
642
|
+
`running`, `reserved` for a stopped instance, or `degraded` when its adapter is missing.
|