feat(oci): update and modify every application, and keep its address

- The backup taken before an update or a modification is made on another
  storage when it does not fit on the system disk; an operation without
  room says so before anything is stopped.
- Privileged containers, relaxed AppArmor or seccomp, process limits, the
  host monitors Glances and Netdata and single-file host mounts are
  rebuilt and recovered like any other application.
- HAOS One installs the docker-haos image: port 8123, host time zone,
  unprivileged, watchdog proposed by default; it is updated and modified
  with Home Assistant's own check on the rebuilt container.
- A container that reboots itself gets its DHCP client back.
- The installer takes the address of the container's own interface, and
  the notes of a suite or stack container show its LAN address.
- Seerr installs: its volume belongs to the image user and
  no-new-privileges goes through the include of the container.
- Removing an application deletes its seccomp profile.
This commit is contained in:
MacRimi
2026-10-08 17:14:36 +02:00
parent b629938cf1
commit f5ad4072b5
31 changed files with 1784 additions and 390 deletions
+20
View File
@@ -103,6 +103,24 @@ def persist_instances(deployment, services, primary_id=None):
oci_instances.publish_stack(oci_instances.ROOT, None, template, deployment, services)
def refresh_notes(services):
"""The notes of each container were written when it was created, before
it had its leg on the local network: write them again with the address
the application is reached at."""
from oci_description import render
from oci_native_stack import access_address as reachable_address
for service in services:
vmid = int(service['vmid'])
try:
record = oci_instances.read(oci_instances.ROOT, vmid)
running = 'running' in run('pct', 'status', vmid)
description = render(record['template'], '', record['installation_id'],
reachable_address(vmid, wait=20 if running else 0))
run('pct', 'set', vmid, '--description', description)
except (OSError, ValueError, KeyError, subprocess.SubprocessError) as error:
log(LOG, f'Notes of CT {vmid} not refreshed: {error}')
def run(*args, capture=True, timeout=180):
argv = list(map(str,args))
if capture:
@@ -811,6 +829,7 @@ def main():
fcntl.flock(lock,fcntl.LOCK_UN)
result = finish_independent_suite(services,subnet)
persist_instances(deployment, services)
refresh_notes(services)
result.update(completion_notes=list(deployment.get('completion_notes',[])), log=LOG)
print('PROXMENUX_RESULT='+base64.b64encode(json.dumps(result).encode()).decode(),flush=True)
return
@@ -852,6 +871,7 @@ def main():
msg_ok(translate('LAN address applied to the application URLs'))
result=results[primary['name']]
persist_instances(deployment, services, primary_id)
refresh_notes(services)
# The credentials of the main service come from its own installation.
result.update(vmid=primary_id,ip=lan,stack_vmids={s['name']:s['vmid'] for s in services},
urls=[{'label':'Web UI','url':public_url}],