MYKOS / DOCUMENTATION · Dashboard · API

API usage

Documentation index

Contents

Base URLs and authentication

Use https://YOUR_HOST/mykos/api/v2 publicly. Uvicorn listens on http://127.0.0.1:8000 internally and its route paths start /api/v2; Apache strips the external /mykos prefix. The supported integration interface is API v2.

Create a read key using sudo /usr/local/sbin/mykos-api-keys create my-monitor read. Set it in your client's secret store. For an interactive shell, avoid placing the key literally in command history:

read -rs -p 'API key: ' MYKOS_KEY; echo
export MYKOS_KEY
BASE=https://mykos.example.com/mykos/api/v2
curl --fail-with-body -sS -H "X-MYKOS-API-Key: $MYKOS_KEY" "$BASE/overview"
unset MYKOS_KEY

The examples use an environment variable for readability; take care with process visibility on shared systems. TLS is required for credentials. An invalid supplied key returns 401 even if a browser session is otherwise valid. API keys are not accepted by legacy browser endpoints or the browser-session terminal WebSocket. An admin key can use the separate API terminal at /api/v2/terminal/{shop}.

API v2 operations require an X-MYKOS-API-Key header with a valid read or admin key. Browser cookies do not authorize API v2 requests. No login, cookie jar, or Origin header is required for API clients. Dashboard session routes retain their browser authentication and Origin checks.

Interactive reference

Open /mykos/api/v2/docs and enter your key in Swagger's Authorize control. The documentation and OpenAPI schema are public so the reference can load without a browser login or cookies; all operational endpoints still require a key. Swagger sends X-MYKOS-API-Key on Execute requests, using /mykos as the public proxy prefix. Swagger assets load from unpkg.com and require browser network access to that host.

curl --fail-with-body -sS "$BASE/openapi.json"

A generated offline schema is also available in openapi.json. Regenerate it when routes change; the running service remains authoritative.

Endpoint inventory

All paths below are relative to /mykos/api/v2. shop is exactly eight ASCII digits, including leading zeros. The read column includes both read and admin keys.

Method and path Permission Result / notes
GET /overview Read Host, counts, snapshot ages/freshness, joined nodes
GET /host Read Hostname, OS, kernel, uptime, backup storage, live metrics
GET /host/metrics Read CPU, logical CPU count, memory, swap, load averages, root disk, uptime and graph_totals (containers, vpns) counted from installed POS metadata files; null if unavailable/stale
GET /host/status Read Host row data: host contains hostname, status, OS/version/kernel, internal IP and collected VPN status; memory and uptime are top-level fields
GET /host/diagnostics/{action} Read Host logs (last 200 journal entries), top (processes), or ipsec status; fixed commands, no container execution
POST /host/reboot Admin JSON hostname must exactly match the server hostname; schedules a reboot in five seconds; interrupts all containers/users
WS /terminal/host Admin Interactive host root shell, or host VPN setup with ?action=add-vpn; host terminal_enabled setting must be enabled; API key in handshake header
GET /host/os Read Hostname, OS, kernel
GET /host/kernel Read Kernel string
GET /host/storage Read Backup storage free/used/total bytes and readable free value
GET /nodes Read count, fresh, nodes; optional filters below
GET /nodes/{shop} Read Full joined node
GET /nodes/{shop}/status Read Status, running flag, VPN state, start epoch/time, image, OS type/version
GET /nodes/{shop}/network Read eth1_ipv4, collected address list
GET /nodes/{shop}/resources Read CPU/memory display values from Podman
GET /nodes/{shop}/vpn Read VPN status, Libreswan counters/connections when available
GET /nodes/{shop}/details Read Container inspection details
GET /nodes/{shop}/ipsec Read Live ipsec status output
GET /nodes/{shop}/logs Read Last 200 Podman log lines; bounded output
GET /nodes/{shop}/processes Read Live podman top output
GET /nodes/{shop}/checkit Admin Runs /usr/bin/checkit inside the selected container
GET /containers Read Managed rootful container list
GET /images Read OS choices from running supported image containers; returns os and the local source image
GET /notes/{pane} mgreen session Private plain-text pane notes (mgreen session only), revision, and last-saved timestamp
PUT /notes/{pane} mgreen session Save notes with JSON text (up to 20,000 characters) and current revision; stale revisions return 409
GET /personal-notes mgreen session Read personal notes; separate from change requests and retained through updates
PUT /personal-notes mgreen session Save personal notes with text and revision; stale revisions return 409
GET /actions Read Supported administrative operations and permissions
GET /actions/stage/{shop}/check Admin Container existence, active job, RTI backup presence, host configuration readiness
GET /jobs/{shop} Admin Staging state and bounded output; idle if no recorded job
POST /actions/stage Admin Queue staging; JSON shop, os from /images, and optional restore boolean
POST /nodes/{shop}/stop Admin Stop the unique selected managed container
GET /backups Read Backup accounts, POS/OS, disk use, subscriber state and storage; optional refresh=true
GET /backups/{code} Read One backup account; optional refresh=true
POST /backups Admin Account creation/deletion, SSH key changes, subscriber updates and key retrieval
GET /backups/{code}/keys Admin Backed-up public and private RSA keys; response is not cached
GET /repos Read Repositories, disk use, modification times, Apache and sync state; optional refresh=true
GET /repos/{name} Read One repository; optional refresh=true
POST /repos Admin Delete, enable, disable or start repository sync
WS /terminal/{shop} Admin Interactive terminal; key in WebSocket handshake header, host terminal setting must be enabled
GET /openapi.json, GET /docs Public Machine/browser API reference; use Authorize for operations

GET /nodes filters: status=online|offline|unknown, vpn=up|down|unknown|not_configured, and running=true|false. include is all or a comma-separated selection of observation,details,extended,network,resources,vpn; base identity/status fields remain present. Status/vpn filters are exact string comparisons. Unknown filter values simply match nothing. Missing collected values can be null, empty objects, Unknown, or unknown depending on the field.

Container details include image (the image reference), os_type (distribution name), and os_version (distribution version). These fields are also available on joined nodes and /nodes/{shop}/status. The details collector reads the container's /etc/os-release, falling back to /usr/lib/os-release, including for stopped containers. Missing metadata displays as Unknown in the dashboard.

Read examples and response shapes

curl --fail-with-body -sS -H "X-MYKOS-API-Key: $MYKOS_KEY" \
  "$BASE/nodes?status=online&include=network,resources"
curl --fail-with-body -sS -H "X-MYKOS-API-Key: $MYKOS_KEY" \
  "$BASE/nodes/01234567/network"
curl --fail-with-body -sS -H "X-MYKOS-API-Key: $MYKOS_KEY" \
  "$BASE/nodes/01234567/logs"

Illustrative network result (addresses and node are examples, not production data):

{"shopcode":"01234567","eth1_ipv4":"192.0.2.10","addresses":[{"network":"podman","address":"10.88.0.2"}]}

Live diagnostic responses have this shape:

{"shop":"01234567","container":"01234567.host.example","output":"diagnostic text"}

/nodes returns {"count":0,"fresh":{"status":false,"details":false,"extended":false},"nodes":[]} on a fresh installation without collected nodes. A 200 response alone does not mean collectors are fresh. Inspect freshness and timestamps in /overview. Podman resource values are display strings, not uniformly normalized numeric metrics. Helper failures can produce Unknown backup storage in /host while the rest of the response works.

Administrative examples

Use an admin-scoped key and a staging shop approved for these operations. Staging creates a privileged container. For native Linux images, restore: true mounts available /backups/tfrsync-ID trees /usr2, /d, /etc, /home, and /usr/java directly read/write; guest writes change the original backup. The application adapter need not be enabled. VM images do not support this restore option.

Before the new instance starts, its private account files are reconciled with the backup IDs. Conflicting image account ownership and POSIX ACLs are adjusted only inside that instance; backup ownership and saved account files stay unchanged. The image root password is retained, missing customer password hashes produce locked accounts, and the old tfrsync-ID login account is omitted. The entire backup home tree is mounted, including any old backup-client home; its source is never deleted. Private per-instance bind mounts retain reconciled account files, hostname/hosts, machine ID, image fstab/crypttab and Podman interface ownership settings inside the complete /etc mount. Other saved customer configuration and service definitions are visible directly; files absent from the backup cannot be restored. The host backup account is untouched; use the existing Backups text menu to configure backup accounts afterward. Existing instances are not restored again on restart.

Root configuration can explicitly map receiver-owned files to customer identities: "backup_identity_overrides": {"01234567": {"users": {"appuser": 1011}, "groups": {"appgroup": 1012}}}. Only use IDs confirmed for that backup; mappings never change the backup files. An optional backup_root changes the host search root from /backups. Stopping affects the selected running POS instance.

curl --fail-with-body -sS -H "X-MYKOS-API-Key: $MYKOS_KEY" \
  "$BASE/actions/stage/01234567/check"
curl --fail-with-body -sS -X POST \
  -H "X-MYKOS-API-Key: $MYKOS_KEY" -H 'Content-Type: application/json' \
  --data '{"shop":"01234567","os":"rh9","restore":false}' "$BASE/actions/stage"
curl --fail-with-body -sS -H "X-MYKOS-API-Key: $MYKOS_KEY" "$BASE/jobs/01234567"
curl --fail-with-body -sS -X POST -H "X-MYKOS-API-Key: $MYKOS_KEY" \
  "$BASE/nodes/01234567/stop"

A staging submission returns HTTP 200 with a queued job, for example:

{"shop":"01234567","state":"queued","restore":false,"output":"","updated_at":1792690000}

Poll until state is done or failed; queued/running are nonterminal. The submission is not proof of completed staging. A lost/failed worker produces failed status when polled. Jobs are not automatically retried. Repeated start requests while a worker is active or a container exists are rejected. Stopping a successfully staged container keeps it present; removal/restart is an explicit operator task.

Host metrics, Backup, Repos and terminal integrations

API v2 now exposes the same data and operations as all dashboard panes. Use X-MYKOS-API-Key for each request; neither browser login nor Origin is required. /host/metrics returns the same raw readings used by the Host gauges and footer. CPU/memory/disk percentages are 0–100. Load averages are the raw 1/5/15-minute values; the gauge normalizes one-minute load by cpu_count. Uptime is seconds. When Apache uses a Certbot certificate, host.certificate_domain identifies the certified dashboard domain used for the Host pane heading. host.hostname continues to identify the actual server. Certificate metadata is collected on the host and does not add guest calls. Swap remains available in the API even though its gauge is hidden in the UI. Unavailable counters are null, rather than a fabricated zero.

curl --fail-with-body -sS -H "X-MYKOS-API-Key: $MYKOS_KEY" "$BASE/host/metrics"
curl --fail-with-body -sS -H "X-MYKOS-API-Key: $MYKOS_KEY" "$BASE/backups"
curl --fail-with-body -sS -H "X-MYKOS-API-Key: $MYKOS_KEY" "$BASE/repos?refresh=true"

Backup account responses include updated_at, the Unix modification timestamp of the newest backed-up RTI/Daisy tfrsync-summary.log, or null when unavailable. This is the dashboard’s Last updated value, not a guarantee of a successful backup.

Backup POST bodies share the dashboard's schema:

action Fields in addition to action
create code, SSH public key, optional boolean subscriber
key code, replacement public key
subscriber code, boolean subscriber
delete code, boolean remove_data (default false preserves data)
keys code; returns backed-up public/private client keys

The equivalent key read is GET /backups/{code}/keys. Key material is restricted to admin keys and uses Cache-Control: no-store. It is never included in listings. The account's currently authorized public key and the backed-up client's own RSA keys are different: key updates authorized access; keys reads the client backup.

Repository POST bodies use action: delete|enable|disable|sync and name. Deletion requires an existing repository name. Other actions use name: "all" (the default). Actions use the same helper validation and locks as the dashboard, and invalidate the shared listing cache. Enable/disable operates on all of Apache; disable can interrupt the API itself. Sync queues the same background systemd job; read /repos to monitor its state.

The terminal URL is wss://YOUR_HOST/mykos/api/v2/terminal/01234567. Supply an admin key in the X-MYKOS-API-Key handshake header, never the URL. Standard browser WebSocket objects cannot set that header; use a programmatic WebSocket client. The existing browser terminal remains on its separate session-authenticated route. Both use the same PTY helper, honor terminal_enabled, and reject invalid codes before opening the helper. Missing/invalid/read-scoped keys close with code 1008; an unavailable/disabled helper closes with 1011. Authorization is checked at the handshake; revoking a key does not terminate an already connected terminal. WebSocket routes are documented here and in /actions, since OpenAPI does not model the WebSocket transport.

For deployments using the explicit Apache WebSocket proxy rules, add these before the general /mykos/ HTTP proxy rule in the existing HTTPS VirtualHost:

ProxyPass /mykos/api/v2/terminal/ ws://127.0.0.1:8000/api/v2/terminal/
ProxyPassReverse /mykos/api/v2/terminal/ ws://127.0.0.1:8000/api/v2/terminal/

Validate with apachectl configtest before reloading Apache. The installer updates the example file but preserves the site's actual Apache configuration.

Legacy routes

The dashboard uses browser-session routes: POST /api/login with JSON username/password, POST /api/logout, GET /api/nodes, /api/nodes/{shop}/details, /api/web/current-user, /api/web/host-version, /api/web/host-uptime, /api/web/extended, /api/web/host-metrics, /api/terminal/permission, /api/admin/containers, and /api/admin/containers/{shop}/{logs|top|ipsec|checkit}. Checkit requires admin. The Host pane reads /api/web/host-metrics every ten seconds for aggregate CPU usage, memory and swap usage, 1/5/15-minute load averages, root filesystem usage, and host uptime. CPU usage is sampled over 100 ms; memory usage excludes available reclaimable memory. Unavailable counters return null.

Browser-only admin staging routes are /api/web/stage/{shop}/{check|status}, POST /api/web/stage, and POST /api/web/containers/{shop}/stop. The terminal WebSocket is /api/terminal/{shop} and requires an admin browser session plus matching Origin. Prefix all these paths with /mykos externally.

Legacy /api/monitor/summary, /api/monitor/nodes, /api/monitor/nodes/{shop}, /api/monitor/extended, and /api/monitor/extended/{shop} require Authorization: Bearer LEGACY_TOKEN; API v2 keys are not interchangeable with it. Do not build new integrations against these compatibility routes.

Common errors

Status Meaning / next action
400 Invalid eight-digit shopcode, invalid include fields, or bad route-level input
401 Missing/expired browser session or missing, invalid, or revoked API key
403 Admin privilege required, or missing/mismatched browser Origin
404 Shop absent from collected inventory, or details unavailable
422 JSON/query validation failed; inspect FastAPI's detail array
500 Helper rejected operation or a host command failed; inspect detail and unit journal
503 Helper socket unavailable/timeout/bad response, legacy token unavailable, or snapshot unavailable on a legacy route

The current helper bridge maps helper-side errors (including a container conflict or unconfigured image) to 500, not 409. Do not automatically retry a mutating request after a timeout; inspect its job/container state first. The helper limits diagnostic output and command duration; long operations belong to the staging job workflow.

Dashboard Backup and Repos panes

The dashboard orders its panes as Host, Backups, Repos, Containers. Header section links update the breadcrumb location. Container status includes the collected OS type and version; missing or stale details show OS unknown.

These browser-session endpoints sit outside API v2:

Method and path Permission Behavior
GET /api/web/mykos/backups Browser user Backup accounts, POS/OS, disk use, subscriber state and storage
GET /api/web/mykos/repos Browser user Repository directories, disk use, modification times, Apache and sync state
POST /api/web/mykos/backups Browser admin + Origin JSON action, eight-digit code, and action fields below
POST /api/web/mykos/repos Browser admin + Origin JSON action and optional name (default all)

Backup actions: create (SSH public key, subscriber), key (replacement public key), subscriber (boolean subscriber), delete (boolean remove_data), and keys (read the backed-up client's public/private RSA keys). Account creation uses useradd, the existing forced-command back/bin/tfrsync, and restricted SSH key permissions. Delete can retain backup data while removing the account and SSH access. Retained directories appear only when an OS backup account exists and must be resolved by an operator before reusing that code. View/get keys opens a private-key dialog and supports browser download; it does not copy keys into the server's /home/tfsupport/keys directory. Closing the dialog or logging out clears its displayed key material.

Repository storage may use a root-controlled symlink, such as /var/www/html -> /home/html, when its target and parent directories are trusted. Symlinks inside the repository root are excluded from listing and deletion.

Repo actions: delete requires an existing immediate directory name; enable, disable, and sync use name: "all". Enable/disable starts/stops all of Apache, matching the CLI menu, and may interrupt this UI and other sites. Sync starts mykos-repo-sync.service asynchronously using the toolkit's existing sync script; it installs dependencies and runs privileged mirror containers as that script specifies. Sync state is the systemd ActiveState (activating while the oneshot runs, inactive after exit, failed after a unit failure). Delete is rejected while sync is active. Service output is available via journalctl -u mykos-repo-sync.service.

Lists refresh every minute and are cached for up to 60 seconds. The Refresh button passes refresh=true to collect immediately. Disk usage collection is limited to 20 seconds per pane; unavailable size values display Unknown. No account, key, subscriber, repository, or service changes occur on page load. These operations use fixed privileged helper commands; interactive legacy menus are not executed by HTTP requests. Deployment must include the new helper module and sync unit and reload systemd before Sync can run.

The dashboard requires an OS selection when adding a container. The helper validates the selection against running supported OS images and records the source image in the queued job. Existing API clients that omit os use the configured stage_image fallback. No image is pulled from a registry. Backup creation accepts the ID and SSH public key directly in the pane.

Add a VPN from the container pane

For a running container with VPN status not_configured, administrators can use the blue plus in its VPN column. It opens the existing POS add_vpn prompts in the popup terminal. Enable terminal access in /etc/mykos/config.json. The prompts collect the remote name, public IP/hostname, IPv4 network (canonical CIDR, or a bare network address treated as /24), and a hidden PSK entry, then ask for confirmation and whether to push to Meraki. The entered PSK is written to its customer folder’s per-connection .secrets file with mode 0600; no preconfigured VPN_PSK is required. The host runs the fixed pos --add-vpn SHOP CONTAINER entry point, not an arbitrary host shell.

API clients use WS /api/v2/terminal/{shop}?action=add-vpn with an admin API key in the handshake header. The browser uses the authenticated, Origin-checked /api/terminal/{shop}?action=add-vpn route. Standard root container terminals retain the default action=shell.

Host responses include internal_ip, the host source IPv4 address selected by the route to 8.8.8.8, or null when unavailable. The dashboard footer shows this address; the header continues to show the hostname.

Supported OS image names are rh7, rh8, rh9, rh10, win10, wns2025, wns2022, wns2019, wns2016, win11, win8e, win7u, winxp, winme, win2k, win98, mac15, mac14, mac13, mac12. Only running images appear in the dropdown and /api/v2/images; each selection uses that image’s local image.

Persistent containers and live snapshots

The following key-authenticated v2 routes use the same backend jobs as the web buttons:

Route (under /mykos/api/v2) Scope Result
POST /nodes/{shop}/start Admin Start the existing persistent container and current disks
POST /nodes/{shop}/stop Admin Stop it while retaining writable storage, code and ports
POST /nodes/{shop}/snapshot Admin Capture live state; leave the source running
GET /snapshots Read List all saved snapshots, grouped by code in the UI
GET /nodes/{shop}/snapshots Read List one container's available snapshots
POST /nodes/{shop}/snapshots/{identifier}/restore Admin Replace the original container's disk/live state with the selection

POST responses return a queued job. Poll GET /jobs/{shop} until state is done or failed; the job's output contains the result JSON or failure detail. The helper permits one job per code. Restore interrupts that container and replaces current state; API callers must explicitly choose the original code and snapshot identifier. There is no cross-container restore. API authentication remains X-MYKOS-API-Key or Bearer key, without browser cookies or an Origin requirement.

Browser equivalents are GET /api/web/snapshots, GET /api/web/containers/{shop}/snapshots, and POST routes under /api/web/containers/{shop} ending in /start, /stop, /snapshot, or /snapshots/{identifier}/restore. Browser writes require an admin session and the configured Origin; list routes require a signed-in session. Private configuration, guest credentials and mounted source paths are excluded from snapshot list payloads.

Snapshot notes use pane name snapshots through the existing notes endpoints.

DELETE /mykos/api/v2/nodes/{shop}/snapshots/{identifier} permanently removes only that selected saved state (admin key required), through the same queued-job protocol. It does not stop, reboot or delete the live container. Other saved states remain. The browser equivalent is DELETE /mykos/api/web/containers/{shop}/snapshots/{identifier}, requiring an admin session and the configured Origin. Both restore and delete operate on the selected snapshot ID; list responses include its original os and created_at epoch time. The Snapshots table displays a full OS name and a Taken date/time for that selection.

Scheduled commands (admin API keys only)

PUT /mykos/api/v2/commands/{id} queues one command. The local mykos-command-collector.timer checks due work every 30 seconds. run_at is an ISO 8601 date/time with timezone; omit it to run on the next check. A busy target waits for its earlier job. Up to four different targets can run concurrently. A command may start later when a target is busy or the host is offline.

{
  "target": "01234567",
  "command": "Get-Date; Get-Service -Name Spooler",
  "run_at": "2026-10-25T14:30:00-05:00",
  "timeout_seconds": 300
}

Use an eight-digit container ID or host. Windows and Windows Server jobs run Windows PowerShell inside the guest, through QEMU Guest Agent. They never execute PowerShell text in the Linux Dockurr wrapper. Host and native RedHat/Linux jobs use Bash as root. macOS and VM-based Ubuntu scheduled commands are currently rejected. Native Linux requires /usr/bin/timeout in the guest.

Windows requires a working QEMU Guest Agent service with guest-exec enabled and the MYKOS private QGA channel. New Windows images created by this release include QGA=/dev/shm/mykos-qga.sock; install the signed QEMU Guest Agent from the VirtIO Windows driver distribution inside Windows and start its service before capturing the image. Older images/running instances are not automatically restarted or changed: without the channel/agent the job fails with an explicit prerequisite error. Adding a device to an older RAM capture requires a compatible recapture; do not edit its launch topology and restore the old capture. No public QGA port, guest password, SSH service, or WinRM listener is used.

Use a unique ID (1–64 ASCII letters/digits/underscores/hyphens, beginning with an alphanumeric). Repeating an identical PUT returns the existing record without rerunning it. A pending record may be rescheduled with a changed PUT; changing a claimed/completed/cancelled record returns 409. Use a new ID to run again.

Endpoint Behavior
GET /mykos/api/v2/commands Latest 100 records, excluding scripts/output
GET /mykos/api/v2/commands/{id} Full record, state, timestamps, exit code and bounded combined output
POST /mykos/api/v2/commands/{id}/cancel Cancel only a pending job; 409 once claimed

All endpoints require X-MYKOS-API-Key with admin scope; browser cookies and read keys cannot access them. The command limit is 16000 UTF-8 bytes and timeout is 1–3600 seconds. Output retains up to 64 KiB and reports truncation. Results and scripts are stored root-only under /var/lib/mykos/commands, retained across updates. Treat admin keys as root-equivalent credentials.

States are pending, starting, running, succeeded, failed, timed_out, cancelled, and interrupted. Dispatch is at most once: a worker lost during a reboot or service failure is marked interrupted and is not automatically retried. It may have executed some or all of the script; inspect the result before choosing a new ID. Timeouts kill the host process group or invoke guest timeout/taskkill; a disconnected Windows agent can prevent confirmation of termination. Detached processes or services deliberately started by a command can outlive the job.

Transport references: Dockur QGA configuration and QEMU guest execution protocol.

The authenticated GET /api/v2/images response includes images (startable OS choices) and builds (active unfinished images with os, name, and console_url). Builds expose the installation console but cannot be selected for starting a container until capture completes. The browser endpoint /api/web/stage-images returns the same data.

Delete a container and its private data

DELETE /api/v2/nodes/{shop} requires an admin API key and JSON {"confirmation":"01234567"} matching the path ID exactly. The browser equivalent is DELETE /api/web/containers/{shop}, with an administrator session and same-origin request. The trash action appears beside start, stop and snapshot in every OS pane. It asks you to type the ID. Stop still preserves the container and its data.

curl --fail-with-body -X DELETE "$BASE/nodes/01234567" \
  -H "X-MYKOS-API-Key: $MYKOS_API_KEY" -H 'Content-Type: application/json' \
  --data '{"confirmation":"01234567"}'

Deletion queues a per-ID worker; poll GET /jobs/{shop} for its result (the existing staging job status endpoint). It pins the selected Podman container identity, stops it if necessary, removes it without force-removing an image or volume, and removes its MYKOS-managed VM disk directory, private VPN directory, and per-ID lifecycle metadata. Writable native container layers are removed by Podman. It refuses unsafe/symlink cleanup paths and storage also mounted by another container. Unmanaged/external bind mounts, named volumes, rsync backups, OS images, and intentional snapshots are retained. retained_mounts lists untouched mounts.

Snapshots are retained as separate archives; deletion does not automatically recreate a container for restore. VM restore needs an existing compatible container with the same ID. The current native Linux CRIU restore requires its original container identity, so deleting that container prevents that restore method. The web confirmation warns when such native memory snapshots are present.

Explicit container-state purge

Administrator only: GET /api/v2/system/purge previews the host-wide reset and returns the exact confirmation phrase, PURGE hostname. Send that exact phrase as {"confirmation":"PURGE hostname"} to POST /api/v2/system/purge to queue it. Poll GET /api/v2/system/purge/status after the dashboard restarts. These routes require an admin API key. Browser equivalents live under /api/web/system/purge; browser execution additionally checks the request origin.

This is irreversible: it removes all rootful Podman containers and images, including non-MYKOS resources, pods, volumes, custom networks, build cache, VM disks, startup captures, intentional snapshots, recovery disks, per-ID VPN data, MYKOS build files, queued commands, runtime inventory, and pane notes. Active MYKOS lifecycle/command workers and recognized kickstart builders are cancelled. Rootless containers belonging to other Unix users are outside this scope.

MYKOS browser users/password hashes/roles, sessions and API key records remain. Rsync backup accounts/data, synced repos, application files, settings, docs and installer/RPM recovery packages remain. The operation refuses unsafe storage paths, storage overlapping preserved data, and nested host mounts. It does not remove application packages or run automatically during install/update.

Local text menu: POS Purge, or sudo /usr/local/sbin/mykos-prune purge. Preview without changes: sudo /usr/local/sbin/mykos-prune --dry-run. Status: sudo /usr/local/sbin/mykos-prune status. The interactive command requires typing the exact host confirmation, waits for the worker, and reports success/failure. Stop/start of MYKOS web/collector/socket services is temporary; only infrastructure that was active is resumed. Guest containers and cancelled jobs are never restarted by the purge.

Authenticated HTTPS desktop consoles

GET /console/{selection}/{path} under API v2 serves verified image/container console assets with an admin API key. WebSocket upgrades to /api/v2/console/{selection}/websockify require the same admin key header and are rechecked while connected. Human browser links use /mykos/console/{selection}/ with a current admin browser session; the WebSocket also checks the configured public Origin. Selection is a supported VM OS name for an image build, or an eight-digit container ID. Clients cannot supply a backend host or port. Upstream requests never receive MYKOS credentials.

Image/desktop metadata console_url now names the authenticated public proxy path. direct_console_url supplies the former LAN URL for diagnostics. Native RDP/VNC login_url values retain their LAN/VPN semantics.

Host Add VPN (WS /mykos/api/v2/terminal/host?action=add-vpn, admin key required) uses the same interactive workflow as container Add VPN: remote name, public address, IPv4 network without /24, hidden PSK entry, confirmation, optional Meraki push, and remote-peer instructions. Browser sessions use the equivalent authenticated host terminal action. The fixed workflow writes new host connection files and loads only the selected tunnel into host IPsec.

Host-side monitoring and RAM allocation

Periodic OS identity, container state, resource statistics and native network addresses now come from host Podman metadata and host iproute tools. Image OS identity is not a report of changes made by an in-guest OS upgrade. Native VPN results are sampled by the basic collector through the Libreswan control socket; details/extended reuse the same sample, rejecting samples older than 60 seconds or belonging to an earlier container start. VM wrappers are not queried for Linux VPN state or a pipework interface. Unsupported control protocols report unknown.

PUT /mykos/api/v2/nodes/{id}/memory/allocation (admin API key) accepts {"target_mib":2048,"confirmation":"12345678"} with confirmation matching the path ID. It queues a cold restart and returns a systemd unit name. Existing disks, OS images, snapshots and console/desktop ports are retained; the previous stopped wrapper is retained for recovery, explicitly stopped under unless-stopped policy. Running VMs also receive a quiesced reflink disk recovery copy; mismatched live storage paths are rejected before stopping. Windows instances use manual installation mode to prevent unattended reinstallation. Check its journal for completion and use GET /mykos/api/v2/nodes/{id}/memory to inspect configured_mib. The existing PUT .../memory is a guarded live balloon request. Both setters enforce the current 2048 MiB policy. Cold resizing is available for Windows, Ubuntu and macOS. Old 4096 MiB RAM captures cannot resume at 2048 MiB; existing instances are cold-booted and old captures/snapshots remain untouched.

Equivalent root CLI:

sudo /usr/local/share/mykos/pos/vm memory-configure 12345678 --target-mib 2048 --confirm 12345678

All new VM image builds use 2048 MiB RAM. The interactive menu displays the allocation; ./vm create OS --ram-mib 2048 makes it explicit. Captures and derived instances inherit this setting. Old images captured with larger allocations must be rebuilt at 2048 MiB before creating new instances. Windows 11 at 2048 MiB is below Microsoft's supported minimum; successful installation is not guaranteed.

The pagefile/swap target is 12 GiB. For Ubuntu, the public fixed download /mykos/image-setup/ubuntu.py contains no credentials. Download and run it with sudo python3 mykos-ubuntu-setup.py inside the installed Ubuntu VM, reboot and verify swapon --show before capture. The menu prints these steps and asks for confirmation. The script enables new swap before disabling recognized older installer swap files, preserves old files, backs up fstab and rejects unknown swap devices/symlinks. New supported Windows installations receive a fixed 12288 MiB pagefile provisioner through Dockur's OEM hook. Reboot and verify Win32_PageFileUsage before capture. Existing guests without a functioning agent need the same setup through their console; the host cannot infer their pagefile configuration. Legacy Windows without CIM/PowerShell is not automatically provisioned. macOS uses kernel-managed swap; a fixed total is unavailable in the stock guest. Its RAM allocation is still 2048 MiB.

Retained host performance history

GET /mykos/api/v2/host/history accepts a read/admin API key and returns up to 30 minutes of real host samples. Browser sessions use GET /mykos/api/web/host-history. An optional since query parameter is a nonnegative Unix timestamp in seconds; timestamps remain UTC Unix time. Responses include retention_seconds: 1800, sample_interval_seconds: 3, collected_at, and samples, ordered oldest first. Each sample contains collected_at, CPU percentage/count, load averages, memory/disk measurements, and cached graph_counts/graph_totals for containers and VPNs.

mykos-host-history.service collects without a browser open and performs no container commands. It reads host counters and the existing collector's cached status, storing a rolling SQLite history under /opt/mykos-web/data. A fresh latest sample is shared by the live metrics endpoints. Missing or stale container observations remain unknown. History survives browser/web-service reloads; old readings expire after 30 minutes. On initial deployment there is no synthetic historical data: the retained interval grows as samples are collected. The dashboard shows a trailing five-minute window with a history slider and Live control; horizontal/Shift-wheel scrolling also moves the selected window.

Update 81

Repository responses include latest_rpm, the filename (without directories), plus latest_rpm_path, the relative path of the most recently modified RPM. Snapshot responses include size_bytes, allocated disk bytes for that snapshot's private storage (sparse holes are excluded). Container detail responses include os_codename beside the unchanged numeric os_version.

DELETE /api/v2/images/{os_name}/build removes only a failed, unfinished image builder and its private disks. Send {"confirmation":"ubuntu22.04"} with the matching OS; administrator authorization is required. Published images and intentional snapshots are retained. The host terminal also accepts ?action=remove-vpn, with interactive selection and confirmation of a MYKOS host connection.

The terminal title bar uses pane name terminal for its notes. Opening or closing the notes dialog leaves the active terminal connection running.

Pane notes are disposable change requests and are cleared by each installation/update. User accounts, password hashes and API key digests are preserved.

Pane notes are private to the mgreen browser account. Both web and v2 notes endpoints require its authenticated session cookie; scope-only API keys cannot read or write these notes. PUT also requires the configured Origin header.

The orange Host notes icon opens personal notes. The equivalent web endpoints are GET/PUT /api/web/personal-notes. These use the separate personal_notes table and must never be included in automated change-request scans. Installation clears only disposable pane_notes; personal text remains private to mgreen and is preserved.

Prepared images stay visible to administrators in their OS panes. GET /api/v2/images also returns captured_images with image ID, size, version and removal state. DELETE /api/v2/images/{os_name} accepts an exact OS confirmation, queues guarded removal, and requires an administrator. GET /api/v2/images/{os_name}/delete reports removal progress. Other containers, saved instances, intentional snapshots, and active builds block removal. The generic base and its private startup capture are removed only after dependency checks; Podman image removal never uses force.

Container terminals now accept ?action=remove-vpn for native Linux and Ubuntu. The action opens the existing interactive connection selection and confirmation workflow. Native VPN setup advertises the actual Podman IPv4 address as a /32, which must match the router peer's private-subnet selector. IKE identities are independent of this traffic selector and remain unchanged.

Prepared-image catalog entries include size_bytes and created_at (Unix seconds, or null when unavailable). Production time comes from Podman's image creation metadata, without probing a guest. Admin image rows show both size and the production date/time in the browser's local timezone, including when removal is blocked by a dependency.

Shared VPN gateways and topology

The existing admin terminal VPN prompts select independent or shared mode. A shared gateway must use a newly managed full-tunnel-capable host/native Linux connection; legacy site-only configurations are rejected before routing changes. Independent configurations and shared-default profiles cannot be mixed in this release. Ubuntu-specific new VPN storage support is deferred.

Method/path under /mykos/api/v2 Permission Behavior
GET /vpn/gateways Read Configured profiles and cached full-tunnel/controller status; no credentials
PUT /nodes/{shop}/vpn/gateway Admin Select an existing managed native Linux VPN as shared gateway
PUT /host/vpn/gateway Admin Select an existing managed host VPN as shared gateway
DELETE /nodes/{shop}/vpn/gateway/{connection} Admin Remove only that guest gateway routing profile
DELETE /host/vpn/gateway/{connection} Admin Remove only that host gateway routing profile

PUT body is {"connection":"office","remote":"10.77.0.0/24","confirmation":"01234567"} for a guest gateway; host confirmation is "host". remote identifies the specific site subnet while the selected default CHILD_SA carries 0.0.0.0/0. The host connection name includes its mykos- prefix. Profile removal retains the underlying tunnel files; use the existing interactive remove-VPN workflow to remove the tunnel as well. Deleting a gateway container is refused until its shared profiles are removed.

Collected extended node data includes vpn_topology with guest, links, via_gateways and primary, plus network membership metadata. Connection links contain only name, peer, local/remote subnets and mode. Shared links include gateway ID (host for the host option), site subnet and cached full_tunnel_sa. Stale state is unconfirmed, not connected. host_internet_via_vpn indicates installed routing through a confirmed local full-tunnel SA, not a successful remote internet probe. All guest types can use a shared gateway. No new per-guest polling or PSK fields are introduced.

Separate browser terminal windows

GET /api/terminal/window/{shop} serves a standalone terminal page to an administrator with an active browser session. {shop} is an eight-digit ID or host; action=image-shell instead accepts a validated prepared-image OS name. Login buttons open separate windows in the same browser, sharing its existing MYKOS cookie. The URL carries only the target and display/action options, never a session token or password. If the browser blocks the window, the inline dialog remains available.

Each window has its own authenticated WS /api/terminal/{shop} connection. Closing one window does not close another container's shell. Existing direct-serial and base-image session limits still apply. Base-image shutdown protection and reset-on-close use the existing server-side lifecycle. Terminal notes retain their mgreen-only authorization and optimistic revision checks.

GET /api/terminal/permission?include_user=true adds the current username to the existing allowed result. Standalone terminals recheck it every five seconds and close their transport when the session expires, is revoked, or changes identity. They do not run dashboard collectors. These are browser-session endpoints; an API key alone does not open an interactive terminal.

Compact dashboard clock

GET /api/web/host-version retains the detailed server_time value and adds server_time_display, for example Oct 27 · 7:42 PM. Both come from the same server-local clock sample. The dashboard uses the compact value and keeps the full timestamp, including timezone, in the header clock tooltip.

Saved geographic metadata

GET /api/v2/geography accepts a read or admin API key and returns saved nodes and hosts location records plus the available non-secret system display fields. Node metadata can include shop_name, configured pos_type, and app_info. Coordinates that are absent remain absent; the UI omits those map points. Host location records are saved inventory metadata; current host health remains available from the host metrics endpoint. No guest execution or geolocation service request is needed to read this endpoint.

Shared customer notes and pane previews

Browser sessions can read and update shared notes for an eight-digit customer ID at GET/PUT /api/web/id-notes/{id}. Every signed-in user, including read-only dashboard users, can edit these customer notes. PUT requires the same-origin header and { "text": "...", "revision": 0 }; a stale revision returns 409 without replacing another user's changes. Responses include id, text, revision, updated_at and updated_by. Notes belong to the customer ID, not a particular login or container, and survive updates and container recreation. Private orange change-request notes remain separate and restricted to mgreen. API keys alone cannot edit customer notes.

GET /api/web/current-user includes preview_all_panes. Full-access administrators (including arch/owner identities as those roles are enabled) preview all OS panes with the footer leaf; other users preview EL and utility panes. Sample actions remain disabled. Preview visibility grants no additional backend privileges.

Monitoring interpretation and released scope

Use /mykos/api/v2/overview freshness flags and timestamps together with node status. A successful HTTP response or cached green VPN edge is not an end-to-end application health test. Resource values come from Podman; VM wrapper measurements and in-guest memory are different observations. Host history is retained from actual samples and may be missing/stale after a collector interruption.

Use separate least-privilege read keys for monitoring. An admin API key grants operations beyond observation and does not establish a browser session. Keep keys out of URLs, logs and shell history. Use the live allowlisted OpenAPI endpoint for route details. The current API does not implement the requested configurable host/guest and RTI/Dove application alert-field system. Native VPN/shared routes are detailed in VPN architecture and operations.