Replaces every native confirm() with a shared P.confirm() modal (a hung native dialog was found live to block the whole tab, including auto-refresh, and once even double-confirmed an unrelated deletion). Also fixes Edit Container silently resetting to Bridge/blanking the Static IP for any container on a custom network, and a context menu losing its anchor to a mid-read auto-refresh. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
281 lines
17 KiB
Markdown
281 lines
17 KiB
Markdown
# Changelog
|
|
|
|
All notable changes to this project will be documented in this file.
|
|
|
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html)
|
|
for the plugin version (independent of the bundled Podman/upstream package versions,
|
|
see [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md#52-build-strategie)).
|
|
|
|
## [Unreleased]
|
|
|
|
### Fixed
|
|
- Edit Container always reset the Network dropdown to "Bridge" and blanked
|
|
the Static IP field, even for a container actually on a custom/macvlan
|
|
network with a real IP — `HostConfig.NetworkMode` turns out to just say
|
|
"bridge" regardless of what a container is actually attached to via a
|
|
custom network (verified live: a running container on "Lan" reported
|
|
NetworkMode "bridge" while `NetworkSettings.Networks` only had a "Lan"
|
|
entry, no "bridge" one at all). The real network name now comes from
|
|
that one `NetworkSettings.Networks` key instead, except when it's
|
|
podman's own literal default bridge network (named "podman", not
|
|
"bridge") — found while investigating why Sonarr's real static IP never
|
|
showed up in its own Edit form.
|
|
- A row's context menu (opened from a container's name or its "⋮") kept
|
|
the ~2s auto-refresh running underneath it — found live: leaving the
|
|
menu open longer than that (reading it, or opening "Move to Folder"
|
|
after a pause) let a refresh replace the whole table's rows in the
|
|
background, so the menu's anchor button was no longer the one actually
|
|
on screen, and a submenu opened from it then positioned itself
|
|
wherever that stale anchor now was instead of anywhere sensible.
|
|
Auto-refresh now also pauses while any context menu is open, the same
|
|
way it already paused for an open modal.
|
|
|
|
### Added
|
|
- Create/Edit Container: "Run as user (optional)" overrides the image's
|
|
own default user (e.g. `99:100`) — found live migrating a real
|
|
container (Seerr) that Docker had run as `--user 99:100` to match its
|
|
bind-mounted appdata's ownership; without this field, podman fell back
|
|
to the image's own `USER node` (UID 1000), which couldn't write to
|
|
files/directories owned by `nobody:users`. Pre-fills from an existing
|
|
container's own `Config.User` when editing.
|
|
- Clicking a container's name in the Containers table now opens its row
|
|
menu (Details/Pause/Kill/Rename/Edit/Remove), matching how a folder's
|
|
member chips already worked — Details becomes just the first menu item
|
|
again, consistent everywhere a container is represented, rather than
|
|
only inside a folder.
|
|
- Create/Edit Container: volumes can now be marked read-only (a "RO"
|
|
checkbox per row), and a new "Device passthrough" field passes an
|
|
arbitrary host device (e.g. a USB serial adapter like `/dev/ttyACM0`)
|
|
through at the same path inside the container — the existing GPU
|
|
passthrough field is unchanged and stays the right choice for
|
|
`/dev/dri/*`. Both were verified live against podman's own API before
|
|
wiring them up (`RW:false` on the resulting mount, and the device
|
|
showing up as `PathOnHost`/`PathInContainer`). Device paths are
|
|
restricted to `/dev/...` (no `..`) — this goes straight into a podman
|
|
create request, not anywhere it could reach untrusted input otherwise.
|
|
Read-only also round-trips through templates now (dockerMan's own
|
|
`Mode="ro"` convention on a `Path` Config — found in the wild on a real
|
|
template that mounts `/mnt/user` read-only for a storage-stats
|
|
sidecar). Generic device passthrough is a container-only field for now,
|
|
not yet part of the template schema.
|
|
- Templates now carry a container's WebUI URL through save/export/import
|
|
too (`<WebUI>`, the same tag Unraid's own Docker templates already use
|
|
for this) — "Use template" now pre-fills the WebUI URL field, and this
|
|
applies to existing Community Applications/dockerMan templates on
|
|
import too, not just ones authored by this plugin.
|
|
- Templates: "Import from a URL" (e.g. a raw GitHub link to a Community
|
|
Applications template), fetched server-side rather than requiring
|
|
copy-paste. The fetch only allows plain http(s) to a hostname that
|
|
resolves exclusively to public addresses (checked before the request,
|
|
then pinned via curl's `CURLOPT_RESOLVE` so a DNS answer can't change
|
|
between that check and the actual connection), doesn't follow
|
|
redirects, and caps the response size — see
|
|
`template_fetch_url()` in `ajax/templates.php`.
|
|
- The Templates tab is now "Apps", with a Store/My Templates toggle.
|
|
Store browses/searches Community Applications' own public app feed
|
|
directly (the same catalog CA's own plugin is built on — see
|
|
`ca_feed_search()` in `ajax/templates.php`), paginated (24/page, with
|
|
Prev/Next) rather than a single capped-length list. Browsing (no search
|
|
term) defaults to Newest-first (by the feed's own FirstSeen timestamp —
|
|
when CA's feed first picked the template up), with a toggle to
|
|
alphabetical; an actual search is always alphabetical regardless of that
|
|
toggle — the only other candidate signal, the feed's own "downloads"
|
|
figure, turns out to just be the underlying Docker image's Docker Hub
|
|
pull count (found live: dozens of unrelated templates that all happen to
|
|
wrap the official nginx/postgres/redis images share the exact same,
|
|
enormous number), which would make search results look ranked by
|
|
relevance while really just favoring whichever match wraps the
|
|
most-pulled base image. "Install" fetches + imports an app the same way
|
|
pasting its template URL always did, then opens it straight in the
|
|
Create Container form, pre-filled — the same experience "Use" already
|
|
gives a saved template, since installing one also saves it as one. My
|
|
Templates is this plugin's own saved-template grid, unchanged, with
|
|
"Import Template" (paste XML / a URL / one of Unraid's own existing
|
|
local Docker templates) still a modal off of it.
|
|
- A shared in-app confirm dialog (`P.confirm()` in `app.js`) replaces
|
|
every browser-native `confirm()` across the whole plugin (containers,
|
|
templates, compose, images, volumes, networks, pods, settings). A
|
|
native `confirm()` blocks the entire tab until dismissed — including
|
|
this plugin's own auto-refresh — and found live to be an actual
|
|
liability: a hung dialog blocked further interaction outright, and in
|
|
one case a stray keypress meant to dismiss it ended up confirming a
|
|
second, unrelated deletion too.
|
|
|
|
### Fixed
|
|
- `podman-verify-packages.sh`/`podman-update-packages.sh` reported every
|
|
single package as "not installed" right after a genuinely successful
|
|
install (confirmed live on a real v0.1.5 install: `/var/log/packages/`
|
|
had the correct records the whole time). Root cause:
|
|
`/var/log/packages` is itself a symlink on Unraid
|
|
(`-> ../lib/pkgtools/packages`), and GNU `find`'s default `-P` mode
|
|
doesn't descend into a symlinked starting path at all without `-L` —
|
|
it just returns the symlink itself and nothing below it. Fixed via a
|
|
new shared `podman_find_installed_package_record()` helper in
|
|
`podman-common.sh`, which also fixes a second bug found while testing
|
|
the first fix: "podman"'s own glob also matched podman-compose's file
|
|
(a literal prefix collision), and `find`'s unsorted output let
|
|
podman-compose's record silently win podman's own check on the same
|
|
real host.
|
|
|
|
## [0.1.5] - 2026-07-13
|
|
|
|
### Added
|
|
- Containers panel: folders to group containers (name + optional icon
|
|
URL), purely cosmetic organizational metadata stored in the plugin's
|
|
own `folders.json` — podman itself has no such concept, same as
|
|
Unraid's own Docker page's folders. "+ New Folder", a "Move to Folder"
|
|
submenu on each container's row menu, and per-folder rename/delete
|
|
(deleting a folder only ungroups its containers, never touches them).
|
|
A folder with nothing assigned yet still shows up (so there's
|
|
somewhere to move a container into); one that's merely hidden by the
|
|
current search/filter does not. A folder's header always shows an
|
|
icon+name+status chip per member — collapsed or expanded, matching how
|
|
Unraid's own Docker page folders behave — rather than hiding everything
|
|
behind a bare count; clicking a chip opens the same row menu the "⋮"
|
|
button does (Details is now a menu item there too, alongside
|
|
Pause/Kill/Rename/Edit/Remove) rather than jumping straight to the
|
|
detail modal. "Move to Folder" only shows for a container that isn't
|
|
grouped yet — once it's in one, that item becomes a direct "Remove
|
|
from Folder" instead, since "move to a folder" reads as "add" and is
|
|
ambiguous/redundant once it's already in one. Containers can also
|
|
carry an icon URL (settable in the create/edit form, auto-filled when
|
|
creating from a template) shown in the table instead of the 2-letter
|
|
initials avatar.
|
|
- Containers can now carry a WebUI URL too (create/edit form, preserved
|
|
through Update/Update All the same way the icon URL is), shown as a
|
|
small open-in-new-tab button next to the name in the Containers table
|
|
when set. Both this and the icon are stored as the plugin's own
|
|
container labels (`podman-webui.weburl`/`.icon`), read straight off
|
|
the already-fetched container list — no extra per-container calls.
|
|
- Container detail modal: 5 new tabs (Resources, Logs, Console, Events,
|
|
Healthcheck), rounding it out from 6 to 11 of prompt.md's 12 requested
|
|
tabs (Volumes was left merged into the existing Mounts tab — same
|
|
underlying source/destination data, a separate tab would just repeat
|
|
it). Resources shows live CPU/memory alongside configured limits
|
|
(memory/swap/CPU/PIDs/block-I/O — a `0` in podman's own HostConfig
|
|
means "unlimited", not zero). Logs reuses the existing per-container
|
|
logs endpoint. Console opens a real ttyd/podman-exec session scoped to
|
|
the modal, cleaned up (killing the ttyd process server-side) on every
|
|
way of leaving — switching tabs, Close, backdrop click, or Escape —
|
|
not just on an explicit Disconnect, so peeking at a console doesn't
|
|
leak an orphaned ttyd process. Events and Healthcheck are both one-shot
|
|
historical queries (libpod's `/events?stream=false` for the last 7
|
|
days, and inspect's own `State.Health.Log`) rather than a live stream,
|
|
which stays out of scope (see dashboard.js's own note on why).
|
|
- A real toast notification system (success/warning/error/info, auto-
|
|
dismissing, stacked bottom-right, dismissible early) replacing every
|
|
`alert()` used for one-way feedback across Containers, Images, Volumes,
|
|
Networks, Pods, Templates, Compose, and Settings — confirmations stay
|
|
native `confirm()` (a decision, not a notice), and long command output
|
|
(`podman compose up/down`, previously also an `alert()`) now goes to
|
|
the existing scrolling log-modal instead, which fits it better than a
|
|
toast ever could.
|
|
- Dashboard reworked: a clean 6-tile row of plain counts (Running,
|
|
Stopped, Pods, Images, Volumes, Networks — colored green/red on
|
|
Running/Stopped so fleet health reads at a glance), a single "Resource
|
|
Usage" card with aligned CPU/Memory/Swap/Storage meter rows (bars shift
|
|
to warn/bad colors above 75%/90% instead of staying accent-colored at
|
|
any value), and an "Autostart Queue" table (reusing
|
|
`podman-autostart.sh`'s own per-container failure counters, so it shows
|
|
exactly what that script would decide, not a second tracked history).
|
|
Bar-and-percentage metrics were kept out of the plain-count tile grid
|
|
entirely after an earlier attempt at combining them (a tile spanning
|
|
multiple grid columns) left dead, empty cells in the layout.
|
|
- Dashboard and Containers now auto-refresh every ~2s (paused while the
|
|
tab is hidden or a modal is open) instead of requiring a manual
|
|
Refresh click to see current state.
|
|
- Settings: an "Add container" dropdown + button above the Autostart
|
|
order table — previously that table could only reorder/remove
|
|
containers already in the chain, with no way to add one in the first
|
|
place.
|
|
- Containers: "Update All" now also removes the old, now-unused image
|
|
version each updated container leaves behind (only when at least one
|
|
container actually updated), instead of leaving stale images to pile up
|
|
on disk after every update run.
|
|
|
|
### Fixed
|
|
- Dashboard memory usage was calculated from libpod's raw `memFree` (which
|
|
excludes reclaimable buffers/cache), showing usage far higher than
|
|
reality — e.g. 67% "used" where `free -h` reported 19%. Now reads
|
|
`/proc/meminfo`'s `MemAvailable` directly, matching what `free -h` and
|
|
most monitoring tools show.
|
|
- Dashboard CPU usage never changed — libpod's own `/info` computes
|
|
`cpuUtilization` once and never resamples it (confirmed live: three
|
|
calls seconds apart returned byte-identical numbers). Now computed from
|
|
`/proc/stat` deltas between successive requests, the same technique
|
|
`top`/`htop` use, which auto-refresh's ~2s cadence fits naturally.
|
|
- Context menus (a container's "⋮", a folder's "⋮") always dropped down
|
|
from the anchor at a fixed position — opened from a row near the
|
|
bottom of the viewport, the menu ran off-screen with its last items
|
|
unreachable. Now measures its own actual rendered size (which varies
|
|
with item count) after appending and flips above the anchor instead
|
|
when there isn't enough room below, clamped horizontally too.
|
|
- Expanding/collapsing a folder shifted every column (including the
|
|
header text) in the Containers table — its default `table-layout:
|
|
auto` sizes each column from the widest content among only the
|
|
currently-visible rows, so adding/removing a folder's rows changed
|
|
what counted as "widest" on every toggle. Columns now use explicit
|
|
fixed widths that don't depend on row content at all.
|
|
- The Name column's content (icon + name + WebUI button) was
|
|
misaligned with its own header, drifting further off with every row —
|
|
putting `display:flex` directly on the `<td>` (to keep the WebUI
|
|
button on the same line as the name) pulls that cell out of
|
|
table-cell layout entirely, so with `table-layout:fixed` it stopped
|
|
respecting the column width its `<th>` assigns. The flex layout now
|
|
lives on a `<div>` inside the `<td>` instead, so the `<td>` itself
|
|
stays a normal, fixed-width table cell.
|
|
|
|
## [0.1.3] - 2026-07-12
|
|
|
|
### Added
|
|
- Settings: a "Podman Service" card with live status plus Start/Stop/Restart,
|
|
each shown in a progress log modal — diagnosing and recovering a podman
|
|
that failed to start no longer needs SSH/terminal access at all.
|
|
- Settings: "Format a Disk for Podman Storage", for a single-disk system
|
|
with no cache pool. Only ever lists disks with no existing partition,
|
|
filesystem, or RAID/ZFS membership signature, and never the Unraid boot
|
|
flash — both excluded by multiple independent checks, not just one.
|
|
Formatted disks are remounted by UUID on every boot.
|
|
|
|
### Fixed
|
|
- `STORAGE_PATH` was never auto-created, even when its parent (a real,
|
|
already-mounted cache pool) existed — only failed if genuinely nothing
|
|
was mounted at all. Root cause of a real "cannot reach the Podman API
|
|
socket" report on a fresh install with a perfectly normal cache pool.
|
|
- Cache-busting for the WebUI's own JS/CSS never actually worked, at all,
|
|
the entire time — Unraid runs `.page` PHP through `eval()`, and
|
|
`__DIR__` inside `eval()`'d code resolves to the *eval() call site's*
|
|
directory, not the plugin's. Every "hard refresh" this project's own
|
|
docs/commits ever recommended only worked because Ctrl+Shift+R bypasses
|
|
the browser cache directly, independent of this (broken) mechanism.
|
|
- Settings' service status chip showed "Not running" immediately after a
|
|
successful Start, because the "is it running" check only recognized
|
|
`rc.podman status`'s own wording, not `start`/`stop`/`restart`'s.
|
|
- The Podman Service log showed `rc.podman`'s multi-line output as one
|
|
run-together paragraph (missing `white-space: pre-wrap` on the pane
|
|
itself, not just its per-line children).
|
|
|
|
## [0.1.1] - 2026-07-12
|
|
|
|
### Fixed
|
|
- `plugin/podman.plg`'s `<URL>`/`<MD5>` entity values were split across their
|
|
own lines (`<URL>\n&baseURL;/...\n</URL>`) — Unraid's plugin manager passes
|
|
that text straight into a `wget ... -O <name> <url>` shell command without
|
|
trimming it, so the leading newline broke the command in two: `wget` saw no
|
|
URL argument at all, and the URL text ran on the next line as its own
|
|
(failing) shell command. Every real Unraid plugin (verified against
|
|
`unassigned.devices.plg` on a live host) keeps `<URL>...</URL>` on one
|
|
line — found by running the plugin installer's own CLI (`scripts/plugin
|
|
install`) directly on a real Unraid host and reading its raw output,
|
|
rather than trusting the webGUI's summarized install log.
|
|
|
|
## [0.1.0] - 2026-07-12
|
|
|
|
### Added
|
|
- Initial repository scaffolding: directory structure, documentation skeleton,
|
|
CI workflow stubs, and community health files.
|
|
- Architecture documentation (`docs/ARCHITECTURE.md`).
|
|
|
|
[Unreleased]: https://github.com/OWNER/unraid-podman/compare/HEAD...HEAD
|