Welcome the new Virtualmin Podman Plugin

Alright, Discourse SMTP can now be configured directly on its recipe deployment page in expand Email delivery → SMTP settings sub-section.

When Mail for domain is enabled, Virtualmin automatically fills the SMTP hostname, port, encryption, username, sender address, and, when available, the mailbox password. Replace any <USERNAME> or <PASSWORD> placeholder. You can also enter credentials from an external SMTP provider.

And, as you mentioned that before, after deployment, SMTP values can be changed under Manage Container Apps → Containers → Discourse web application container → Environment variables.

Also, note, that local Virtualmin SMTP routing from the Podman pod is handled automatically.

Lastly, you can test delivery in Discourse → Admin → Email settings → Server settings → Send test email.

Please let me know if it works for you this time.

app.yml belongs to the traditional discourse_docker launcher workflow. Our plugin runs the Discourse image directly with Podman, so there is no app.yml and equivalent DISCOURSE_* settings are container environment variables.

1 Like

Alas, after updating the podman plugin, I still see the same 24 vars I had before, whcih do not include the ones needed. Maybe I did something wrong.


Also, after server reboots, my containerized apps are down: all of my Podman containers were showing as “Missing” in Webmin because they weren’t starting back up on their own. Even though lingering was active and the containers were set to “unless-stopped”, they weren’t restarting because Debian and Ubuntu don’t always include podman-restart.service in the user systemd templates by default. We fixed it by creating a standard podman-restart.service unit inside /etc/systemd/user/ and running systemctl --global enable podman-restart.service, which immediately got all rootless containers starting automatically on boot across every domain user.

I don’t know how universal of a problem that might be. I think I’ve solved it for my server with AI assitance to set a global policy to restart all containers after reboot, but letting you know - especially if others run into the same issue.


That said, I’ve been slow to play with all of the available containers because I’ve spent time on these issues, but I’m still quite excited for this and will be playing around with more containers. :slight_smile: I will never stop saying thank you <3 :slight_smile: But not just this, but Virtualmin has brought back the joy in hosting that died years ago with cPanel stupidity. heh

Like which vars do you expect to see? To be clear, just updating the webmin-virtualmin-podman package won’t make any changes to your currently deployed containers. You would have to either delete and reinstall it or manually edit the container’s env vars as I explained in my previous comment.

Thanks, that’s right, and I’m aware of it. Still, I’m not sure what the best way to solve it would be. I’ll update this ticket with progress on this particular issue…

And I will always be thankful for your kind words and for using our product! Thank you!

Alright, going forward the containers will restart correctly whenever the system reboots. Appreciate you pointing this out!

If you’re using the development Virtualmin repo/branch, everything should just work out of the box.

1 Like

I don’t know why it took me so long to realize, but to add/edit the environmental variables, click on the container name in the list of containers. So I hope this helps anyone else who can’t figure this stuff out.

It’s incredibly easy… once you realize that’s where to go.

I’m happy to report that my SMTP settings are now working, and if ever I need to adjust a container’s vars, now I understand where and how to do that. :slight_smile:

I’m incredibly appreciative of your patience with me. :slight_smile:

2 Likes

Hi Ilia,

Sorry it took me a bit of time to run my first test, I had a lot going on.
Finally got to it, and here’s what I found.

I tested the Compose import with your phpBB example files first — worked perfectly, clean import, both services running as expected.

Then I tried importing my own wg-easy stack (WireGuard VPN, single service). As expected from the earlier discussion, the import rejected container_name, sysctls, and cap_add — I removed all three and the import succeeded fine, including a bind mount outside the domain home (/lib/modules, read-only) after enabling the two advanced overrides.

The problem: without NET_ADMIN and SYS_MODULE, WireGuard can’t create its network interface (RTNETLINK answers: Operation not permitted). The README mentions “Extra Linux capability controls” as a feature, so I expected to add these capabilities after import via the Edit Container page — but I don’t see any capability field there. I checked every section (port mappings, host volume mapping, environment variables, inspect metadata) and there’s nothing for capabilities.

Is this field just not exposed on the edit screen for imported containers, or is capability editing not implemented yet? Any workaround in the meantime (should I recreate manually with podman run and the right flags, keeping the same name/labels so the module still picks it up)?

Happy to share full logs/config if useful.

Thank you for your feedback! I really appreciate it!

“Extra capabilities” control is available in the “Privileged and host access” panel when enabled in the module configuration under “Podman Containers ⇾ Module Config: User interface settings ⇾ Visible panels on container create and edit pages”.

We wanted to keep it simpler from the start, long before I came up with adding recipes, so we only exposed basic controls by default.

Please let me know if that works for you.

Thanks for pointing me to the “hidden” configuration, capabilities are now editable and working. :folded_hands:

Went further with a first test (wg-easy - WireGuard) and hit a real blocker: it needs actual NET_ADMIN/iptables access, which only works in rootful mode. Switched the container to rootful, and the import then failed with:

netavark: error while applying dns entries: IO error: aardvark-dns failed to start
Error starting server failed to bind udp listener on 10.89.0.1:53: IO error: Address already in use (os error 98)

Turns out my server runs BIND for DNS zones (default/standard with Virtualmin), and it’s listening on all interfaces including every bridge Podman creates. In rootful mode, aardvark-dns also wants port 53 on its new bridge and loses the race. Digging around, this appears to be a known upstream Podman limitation (containers/podman#15452 among others). Podman’s own docs confirm there’s no way to run aardvark-dns on a non-standard port yet, and the fix is to bind the host DNS server to specific IPs instead of “any”.

To be clear, this only bit me on the one service that needed rootful (real network/iptables access). My earlier phpBB test import, fully rootless, worked without any DNS conflict at all. So this isn’t a “every import breaks” issue. It’s specific to services that need rootful mode for kernel-level networking, which I’d guess is a minority case (VPNs, reverse proxies doing their own iptables, that kind of thing).

Have you run into this with Virtualmin + BIND + rootful containers? Curious if there’s a known-good way to configure BIND’s listen-on around it, since I’d guess anyone running Virtualmin’s default DNS alongside a rootful import that needs its own network will hit the same wall.

Two more small things while I was in there:

1. False “unsaved changes” warning on save
Saving changes under Module Config → “Privileged and host access” and “Container list columns” (User interface settings) triggers the browser’s “leave page / changes won’t be saved” warning — but the save actually goes through fine. A bit confusing since it implies the save might have failed.

2. Raw HTML tags in Runtime mode selector
On “Import Compose Stack” → “Import Behavior”, the Runtime mode dropdown shows literal tags instead of rendering them: Domain user (<tt>rootful</tt>) instead of formatted “rootful”. Looks like the <tt> isn’t being stripped in that select element.

Happy to share screenshots or logs for any of these.

You’d just set BIND under “Servers → BIND DNS Server → Addresses and Topology” to listen only on explicit host IPs, excluding Podman bridge addresses. We should not modify global DNS automatically in any way, if that’s what you’re asking/suggesting.

Thanks! This is a known theme bug that should already be fixed in the latest development version. We will push a Webmin update soon to address this and other small issues.

Please install the latest development build and let me know if the issue is fixed for you.

I have a few questions relating to the podman & container manager support so hope this is OK to post here rather than open a new thread.

Firstly wanted to say thankyou to the Virtualmin team for making this happen, it’s my 1st time using podman but it’s something I recently became aware of and wanted to try and it works so well out of the box, the ‘recepies’ are simply superb being able to deploy a working app in literally 2/3 clicks is a game changer, so many thanks for the support and development.

My questions relate to guidance for updating the Podman builds & a few others:

How (could it be supported in a later build) do you best set the containers to restart automatically?

I tried the system.d approach, and the command states it is deprecated and to look for ‘quadlets’.

Please note this is for containers only; I don’t have any pods yet from the 2 recipes I have installed.

I understand that I can achieve the same via a cron job, but wonder if a future Virtualmin version will include support for this?

Also, what is the correct way to update Virtualmin Podman support at this time?

1 Like

Thanks for the kind words! :hand_with_index_finger_and_thumb_crossed:

Auto-restart after reboot

This is now supported natively, no cron or manual systemd units needed. Two pieces work together:

  1. Each container has a restart policy (set on the container’s create/edit form; the module default is unless-stopped, configurable under the module’s “Module Config → Container defaults”).
  2. Since 1.5.0 there’s a module config option “Start Podman containers after system reboot?” (enabled by default) which enables Podman’s own podman-restart.service — the system service for rootful containers and the global user service for rootless containers. On boot, that service starts every container whose restart policy calls for it (always / unless-stopped).

So for the containers you already have: make sure their restart policy is always or unless-stopped (edit the container and save/reinstall if it isn’t), and leave the “Start after reboot” option enabled. Nothing else is required. The deprecated podman generate systemd / quadlets approach isn’t necessary for this.

Updating the module

It’s a regular package from the OS repository, so it updates like everything else: through Virtualmin’s System Settings → Software Updates / Package Updates, or with apt upgrade / dnf upgrade on the server. When a new module version is released it will show up there.

1 Like

Dear Ilia,

Thanks again for the capability fix and the BIND guidance — both worked. Quick update on BIND for anyone else who hits this: the listen address needs to be the server’s actual local interface IP, not its public-facing IP if it’s behind NAT. It took me a moment to figure that out. Multiple protocol rows do work once the first is filled in.

Now, the actual blocker. After fixing BIND, the wg-easy import succeeded cleanly in rootful mode (no more DNS port conflict). I added NET_ADMIN and SYS_MODULE via the UI, confirmed they’re applied:

$ podman inspect ... --format '{{.HostConfig.CapAdd}}'
[CAP_NET_ADMIN CAP_SYS_MODULE]

But the container still fails every time it tries to bring up the WireGuard interface:

2026-08-18T19:59:57.146Z CMD $ wg-quick up wg0
[unhandledRejection] Error: Command failed: wg-quick up wg0
/usr/bin/wg-quick: line 86: exec: sudo: not found
code: 127

Traced it to this:

$ podman exec <container> id
uid=1003(opensourcesolutions) gid=1003(1003)

So in “rootful” mode, Podman itself runs as real root on the host, but the container process runs as the virtual server’s UID/GID rather than UID 0 inside the container namespace. The official wg-easy image’s wg-quick script checks the effective UID and calls sudo to escalate if it’s not 0 - but sudo isn’t installed in that Alpine-based image, so it fails hard, capabilities notwithstanding.

This isn’t specific to WireGuard and any image that assumes it’s running as UID 0 (checks $(id -u), calls sudo, or relies on root-only file ownership) will hit the same wall in this rootful mode, even with all the right capabilities granted.

Two questions:

  1. Is there a way to force the container to run as real UID 0 inside its namespace for a specific service, rather than the domain UID — maybe via “Extra run flags” (--user 0:0 or similar), without breaking the domain-isolation model rootful mode is designed for?

  2. If not, is this a known limitation of the rootful UID-mapping design, or worth flagging as an edge case for images built with a “must literally be root” assumption?

Happy to test whatever you’d suggest. Hopefully, this is the last piece needed to get wg-easy fully working under the plugin.

One more observation, unconfirmed — sharing in case it’s relevant:

While the wg-easy container was stuck in that restart loop (repeatedly failing on wg-quick up wg0 and presumably retrying per its restart policy), I noticed my SSH session to the server became noticeably slow/unstable. Once I stopped the Podman container and switched back to the Docker version, things went back to normal immediately.

I want to be careful here: I didn’t test this rigorously: no isolated reproduction, could easily have been an unrelated network hiccup on my end, and I only have one data point. But the timing correlation was strong enough that I thought it was worth mentioning, in case a container stuck in a tight crash-restart loop (repeatedly trying to bring up a network interface) could have some resource or network-stack impact on the host worth being aware of.

Not asking you to chase this specifically, just flagging it as a “maybe worth keeping in mind” alongside the main UID issue above.

Trying to install nextcloud:

Checking deployment requirements ..
.. done

Creating pod nextcloud ..
.. failed : error: OCI runtime error: error starting container 30e5ba4d809f7acae263eb9fb771749dada75eae34c47d0718b9b8b573aac7e2: writing file `/sys/fs/cgroup/cgroup.subtree_control`: Invalid argument
The failed deployment was rolled back. Its containers, pod, proxy configuration, and newly created persistent storage were removed. Downloaded images were kept in the image cache for future deployments

Steps to repro:

  1. Create top-level virtual server (with subdomain off domain working on server)
  2. Grab let’s encrypt certs
  3. Install container - changed admin user/pass (surely no impact)
  4. E R R O R :slight_smile:

Anyone else able to reproduce or tried installing nextcloud and it worked?