Podman is a Virtualmin plugin for deploying and managing containerized applications, containers, and pods per virtual server. It combines Podman’s daemonless container runtime with Virtualmin’s domain ownership, permissions, reverse proxy configuration, audit logging, and command-line API.
Use an Application Recipe to deploy a complete supported application with
minimal configuration, or create standalone containers and multi-container
pods manually. The same operations are available through the virtualmin
command and authenticated remote API.
What the plugin manages
The plugin adds domain-aware management for:
- Application Recipes — deploy one of many curated applications with its containers, private database or cache services, persistent storage, generated secrets, and web, loopback, or direct-service connectivity
- Containers — create, edit, reinstall, start, stop, restart, delete, inspect, view logs, and open an interactive terminal when supported
- Pods — create, clone, start, stop, delete, inspect, view logs, and add member containers
- Images — search registries, inspect image metadata, pull images, list downloaded images, and remove images from a selected runtime store
- Networks — list, create, and remove Podman networks in a selected runtime context
- Reverse proxies — publish a container or pod below a virtual server’s website without configuring the web server manually
- Automation — use the
virtualminCLI locally or the authorized command subset throughremote.cgi
Virtualmin stores the configuration of module-managed containers and pods. Runtime discovery enriches those records with current state, IDs, health, uptime, networks, and resource usage. Recipe deployments use the same editable container and pod records as manually created resources.
Installation
The plugin is distributed through the standard Virtualmin Pro repositories. Repository access is configured automatically on licensed Virtualmin Pro systems.
Debian and derivatives
apt update
apt install webmin-virtualmin-podman podman skopeo
Enterprise Linux systems
dnf install webmin-virtualmin-podman podman skopeo
podman is required. skopeo is strongly recommended because the plugin uses
it for remote image inspection, architecture checks, and image-derived
defaults.
The Virtualmin Podman plugin is only available to Virtualmin Pro subscribers.
Enable the plugin
Installing the package does not automatically enable containers for every virtual server:
- Open System Settings ⇾ Features and Plugins.
- Enable the Podman containers plugin globally.
- Edit each virtual server that should use containers.
- Enable the Podman containers feature for that virtual server.
The feature can also be selected when creating a new virtual server after the plugin has been enabled globally.
Accessing the plugin
After installation and global enablement:
- Container Apps Manager appears in the main Virtualmin navigation for cross-domain administration.
- Manage Container Apps appears inside each virtual server where the feature is enabled.
- The per-domain page shows Available Recipes when no recipe is installed, or Installed Recipe when one is deployed, alongside Containers and Pods. The Containers and Pods tabs appear only when their respective direct-access policies permit them. Recipes remain available independently and can create their required containers and pods without exposing those lower-level management interfaces.
- Manage Downloaded Images is available to the master administrator from the global area.
Domain owners and resellers see the plugin only when access is enabled in module configuration and their Virtualmin ACL permits the target domain. Direct container and pod management have separate policies; each can be master-only, available to all permitted users, or disabled.
Runtime modes
Every managed container and pod belongs to one of two Podman runtime contexts. The mode affects runtime ownership, image and network visibility, cgroup capabilities, and which advanced options are available.
| Display name | CLI value | Host-side Podman process | Container user model |
|---|---|---|---|
| Image user | rootless | Runs as the virtual server’s Unix owner | Keeps the image’s configured user model |
| Domain user | rootful | Runs through the host-global rootful runtime | Runs as the virtual server UID and GID |
Image user (rootless) is the default and recommended mode for most
applications. It keeps Podman’s storage and runtime operations in the virtual
server owner’s Unix account.
Domain user (rootful) uses the host-global runtime but constrains the
container process to the virtual server UID and GID. It is useful when an
application must write files using the same host identity as the domain or
needs host features unavailable to the rootless runtime.
Rootful images and networks are host-global. Rootless images and networks belong to a Unix user, not directly to a Virtualmin domain, so several subservers using the same Unix owner can share the same rootless store.
The master administrator controls whether the runtime mode is:
- Selectable on create forms
- Shown as a fixed informational value
- Hidden while the configured default is applied
Existing objects keep their saved runtime mode even if the module default later changes. A container cannot be moved into or out of a pod by editing it; create a replacement in the required runtime context.
Rootless preparation
Before running rootless Podman, the plugin prepares the virtual server owner by ensuring:
- A persistent systemd user manager is enabled on systemd hosts
- The user’s runtime directory exists with the correct ownership
- Subordinate UID and GID ranges exist in
/etc/subuidand/etc/subgid podman system migrateruns when newly allocated subordinate IDs require it
If this setup fails, the operation stops and reports the preparation error. It does not fall back to running the requested rootless operation as root.
Getting started
For a supported application, the simplest deployment path is:
- Confirm that the virtual server has the Podman containers feature.
- Open Manage Container Apps for that virtual server.
- Select an application on the Available Recipes tab.
- Review its deployment name, database choice, initial login, and application details.
- Deploy the recipe and use the application URL or connection address shown on completion.
The recipe selects a known-compatible runtime mode and creates the necessary Podman networking and, for public web applications, reverse proxy configuration automatically.
For an application that is not in the catalog, open Containers and choose Install New Container, or create a pod first when several containers need shared networking and lifecycle. Review the suggested ports, mounts, environment, health check, runtime mode, and proxy settings before creating the resource.
Recipe, container, or pod?
- Use an Application Recipe when the application is in the catalog and its predefined web or service exposure fits the intended deployment.
- Use a standalone container when one image can operate independently with its own ports, mounts, restart policy, and proxy path.
- Use a pod when multiple containers should share a network namespace, published ports, bind mounts, or grouped lifecycle.
Published ports and proxy settings belong to the pod when a container is a pod member. Member containers retain their own image, command, environment, and container-specific mounts.
Application Recipes
Application recipes are curated, tested definitions for deploying complete self-hosted applications. A recipe can create a standalone container or a pod containing the application, database, cache, worker, and scheduler services it needs. Virtualmin also creates persistent storage, generates internal secrets, and publishes the application using the connection mode declared by the selected recipe variant.
Recipe connection modes are:
- Public web access — allocates a port on
127.0.0.1and publishes the application through the virtual server’s root reverse proxy, using HTTPS when its SSL website is enabled - Local host only — allocates a port on
127.0.0.1without creating a reverse proxy, for software that should be reached only from the host - Direct access — publishes declared TCP or UDP service ports on the host and reports the virtual server’s domain as the connection address; these master-only recipes may require host and upstream firewall changes
Public web recipes reserve / as the virtual server’s reverse proxy path. The
completion URL can include an application-specific landing path such as
/login, but the proxy owns the complete domain root. Create a dedicated
virtual server or subdomain for each public web recipe. A public web recipe
cannot be deployed while / is already used by another reverse proxy.
Recipe database choices use either application-managed storage or a database container; they do not depend on MariaDB or PostgreSQL being installed on the Virtualmin host. The phpMyAdmin recipe is the exception: it connects to a separately managed MySQL or MariaDB server and defaults to host.containers.internal.
Installing a recipe
- Create or select the virtual server that will host the application.
- Open Manage Container Apps ⇾ Available Recipes.
- Select an application from Available Recipes and choose Configure Selected Application.
- Review the deployment name. This name identifies its pod or containers and storage directory.
- Select a database variant when the application supports more than one.
- Set the initial username and password when the upstream image supports unattended account creation. A secure password is generated by default; some applications require a fixed username.
- Expand Application details to review container images, persistent storage, connection mode, and the automatically selected runtime mode.
- Deploy the application and wait for all readiness checks to complete.
Before changing runtime state, the plugin checks the domain, runtime and pod requirements, connection-specific proxy or port availability, deployment-name and storage collisions, and any disk, quota, or memory minimum declared by the recipe. For public web access, it also checks website support and, by default, prevents a recipe from replacing a Virtualmin web app already installed at the website root. It then creates dependencies in order, waits for database and cache services, starts the application, checks its published endpoint, completes any one-time initialization, and starts deferred worker or scheduler services before applying the reverse proxy when required.
The completion page displays the application URL or connection address, initial credentials when available, runtime resource names, and persistent-data path. Save generated credentials immediately. When File Manager is installed and authorized, the storage path links directly to that directory.
If deployment fails, Virtualmin reports the failing step and rolls back the new containers, pod, proxy configuration, and newly created storage. Downloaded images remain cached for later use. Any incomplete rollback is reported explicitly instead of being presented as a clean deployment.
Included applications
The current catalog includes the recipes listed below. The recipe ID is the
stable value accepted by --recipe in the command-line and remote APIs.
List of installable application recipes
| Application | Description | Categories | Recipe ID |
|---|---|---|---|
| Actual Budget | A privacy-focused personal finance and budgeting application with persistent account data. | Finance, Budgeting | actual-budget |
| Adminer | A lightweight database administration interface for MySQL, PostgreSQL, SQLite, SimpleDB and Elasticsearch. | Database, Administration | adminer |
| Apache Tomcat | An Apache Tomcat 11 server for deploying Java web applications with Java 21. | Development, Web Server | tomcat |
| Audiobookshelf | A personal audiobook and podcast server with persistent libraries, metadata and settings. | Media, Audiobooks | audiobookshelf |
| BookOrbit | A self-hosted library for ebooks, audiobooks, comics and PDFs, with built-in readers, device synchronization and a private PostgreSQL database. | Books, Media, Audiobooks | bookorbit |
| BookStack | A structured documentation and knowledge platform backed by a private MySQL database. | Documentation, Knowledge Base | bookstack |
| Caddy Static Site | A compact static website server with an editable web root and Caddyfile; Virtualmin remains the public TLS endpoint. | Web Server, Development | caddy-static |
| Calibre-Web | A browser interface for an ebook library with persistent books and a generated administrator password. | Media, Books | calibre-web |
| ChangeDetection.io | A website-change monitor with persistent watch history and notification settings. | Monitoring, Automation | changedetection |
| Chatwoot | A customer support inbox for live chat, email and messaging channels, with private PostgreSQL and Redis services plus a dedicated job worker. | Helpdesk, Chat, Business | chatwoot |
| ClassicPress | A community-led content management system based on the classic WordPress experience, with persistent files and a private MySQL database. | CMS, Blog | classicpress |
| Code Server | Visual Studio Code in the browser with password protection and a persistent workspace and settings. | Development, IDE | code-server |
| Collabora Online | A Collabora Online Development Edition document server for connecting Nextcloud and other WOPI-compatible applications. | Office, Collaboration, Documents | collabora |
| Directus | A data platform and headless CMS with built-in SQLite, persistent uploads and an initial administrator login. | CMS, Database, Development | directus |
| Discourse | A community discussion platform with PostgreSQL, Redis and a ready-to-use administrator account. Its standalone container image is currently marked experimental by Discourse. | Community, Forum | discourse |
| Django | An editable Django LTS application starter with PostgreSQL or SQLite, Gunicorn, static-file serving and an initial administrator. | Development, Web Server | django |
| Docmost | A collaborative documentation and wiki platform with PostgreSQL, Redis and persistent uploads. | Documentation, Collaboration | docmost |
| DokuWiki | A file-backed wiki with unattended setup, access controls and persistent pages, media, plugins and configuration. | Wiki, Documentation, Collaboration | dokuwiki |
| Dolibarr | An ERP and CRM suite for contacts, quotes, invoices, orders, inventory and accounting, backed by a private MariaDB database. | ERP, CRM, Business | dolibarr |
| Draw.io | A self-hosted browser editor for diagrams, flowcharts, network maps and technical drawings. | Design, Productivity | drawio |
| ejabberd | A federated XMPP messaging server with proxied web administration and direct client and server federation listeners. | Chat, XMPP, Federation | ejabberd |
| EspoCRM | A customer relationship management platform for sales, marketing and support, with a private MariaDB database and background job daemon. | CRM, Business | espocrm |
| Etherpad | A real-time collaborative document editor with MySQL and a protected administration area. | Collaboration, Documents | etherpad |
| Excalidraw | A collaborative-style browser whiteboard for diagrams; drawings remain in each user's browser unless exported. | Whiteboard, Collaboration | excalidraw |
| FastAPI | An editable FastAPI application starter with a persistent Python environment and Uvicorn server, served behind Virtualmin TLS. | Development, Web Server | fastapi |
| Firefly III | A personal finance manager with a private MariaDB database and persistent uploaded documents. | Finance, Budgeting | firefly-iii |
| Flask | An editable Flask application starter with a persistent Python environment and Gunicorn server, served behind Virtualmin TLS. | Development, Web Server | flask |
| FrankenPHP | A modern PHP application server with an editable web root and Caddyfile, served behind Virtualmin TLS. | Web Server, Development | frankenphp |
| FreeScout | A lightweight shared-inbox and helpdesk application with unattended setup, scheduled mail processing and a private MariaDB database. | Helpdesk, Email, Business | freescout |
| FreshRSS | A fast self-hosted RSS reader with automatic feed refresh and persistent extensions. | RSS, News | freshrss |
| Friendica | A decentralized social network with unattended setup, a private MariaDB database and a dedicated background-task service. | Social, Community, Federation | friendica |
| Ghost | A modern publishing platform for newsletters, blogs and independent media, backed by MySQL. | CMS, Blog, Publishing | ghost |
| Gitea | A lightweight Git hosting service with persistent repositories and MariaDB or PostgreSQL. | Development, Git | gitea |
| GLPI | An IT asset inventory and service desk platform with ticketing, software inventory and a private MySQL database. | Helpdesk, Inventory, Business | glpi |
| Go | An editable Go application starter with persistent module and build caches, compiled before serving behind Virtualmin TLS. | Development, Web Server | golang |
| Gotify | A lightweight real-time notification server with SQLite and an initial administrator login. | Notifications | gotify |
| Grafana | An observability platform with persistent data sources, users and interactive dashboards. | Monitoring, Analytics | grafana |
| Grafana OpenTelemetry LGTM | A development and testing stack combining Grafana, Loki, Mimir, Tempo, Pyroscope and an OpenTelemetry Collector. | Monitoring, Development, Analytics | grafana-otel-lgtm |
| Grav | A fast flat-file content management system with its administration plugin, unattended account creation and persistent site data. | CMS, Website | grav |
| Grocy | A household inventory, grocery, meal-planning and chores manager with persistent local data. | Home, Inventory, Productivity | grocy |
| HedgeDoc | A collaborative Markdown editor with PostgreSQL, persistent uploads and account registration enabled. | Markdown, Collaboration | hedgedoc |
| Homebox | A household inventory and organization application with SQLite; the first registered account owns the instance. | Home, Inventory | homebox |
| Homer | A lightweight, customizable dashboard for organizing links to services and applications. | Home, Utilities | homer |
| Immich | A photo and video backup library with machine-learning search, private PostgreSQL and Valkey services, and persistent originals. | Photos, Media, Backup | immich |
| InfluxDB | A time-series database with a web interface, query tools and a preconfigured organization and bucket. | Database, Analytics, Monitoring | influxdb |
| Invoice Ninja | An invoicing, payments and client portal platform with private MySQL and Redis services plus dedicated queue and scheduler processes. | Invoicing, Finance, Business | invoice-ninja |
| IT-Tools | A collection of browser-based developer, encoding, conversion and networking tools. | Development, Utilities | it-tools |
| Jellyfin | A personal media server with persistent configuration, cache and an empty library ready for uploads. | Media, Streaming | jellyfin |
| Joomla | A content management system with unattended setup, persistent website files and a private MariaDB or PostgreSQL database. | CMS, Website | joomla |
| Joplin Server | A private synchronization server for Joplin notes, notebooks and attachments, backed by PostgreSQL. | Notes, Sync, Productivity | joplin-server |
| Kanboard | A focused Kanban project manager with tasks, swimlanes, automation and a private PostgreSQL database. | Projects, Productivity, Business | kanboard |
| Karakeep | A bookmark and web-archive manager with full-text search, automated page capture, a private Meilisearch index and persistent content. | Bookmarks, Archive, Productivity | karakeep |
| Kavita | An ebook, comic and manga library server with persistent configuration and an empty content library. | Media, Books | kavita |
| Keycloak | An identity and access management server with PostgreSQL and selectable bootstrap administrator credentials. | Identity, Security | keycloak |
| Kimai | Professional time tracking, reporting and invoicing for freelancers, teams and agencies, backed by a private MySQL database. | Time Tracking, Business | kimai |
| Leantime | A project management and strategic planning workspace for teams, backed by a private MySQL database. | Projects, Productivity, Business | leantime |
| LimeSurvey | A survey and questionnaire platform with unattended administrator and database setup, persistent uploads and retained encryption configuration. | Survey, Forms, Research | limesurvey |
| linkding | A fast private bookmark manager with persistent SQLite data and an initial administrator login. | Bookmarks | linkding |
| Listmonk | A high-performance newsletter and mailing-list manager with subscriber lists, campaigns, templates and a private PostgreSQL database. | Email Marketing, Publishing | listmonk |
| Mailpit | A development SMTP server with a searchable web inbox, API and persistent message storage. | Development, Email | mailpit |
| Matomo | Privacy-focused web analytics with a private MariaDB database. | Analytics, Privacy | matomo |
| Mattermost | A team messaging and collaboration server with persistent files and a private PostgreSQL database, deployed without the optional Calls service. | Chat, Collaboration, Business | mattermost |
| Mautic | A marketing automation platform for contacts, campaigns, forms and email, with private MySQL storage and dedicated worker and scheduler services. | Marketing, Automation, Business | mautic |
| Mealie | A recipe manager and meal planner with persistent application data and built-in SQLite. | Food, Productivity | mealie |
| Memos | A lightweight private notes and knowledge service with persistent SQLite data and attachments. | Notes, Knowledge Base | memos |
| Metabase | A business intelligence and data visualization platform with a production PostgreSQL application database. | Analytics, Business Intelligence | metabase |
| Miniflux | A focused feed reader with a private PostgreSQL database and an initial administrator login. | RSS, News | miniflux |
| MongoDB with mongo-express | MongoDB with a private database and a password-protected browser administration interface. | Database, Administration | mongo-express |
| Moodle | A learning management system for courses, assignments and online education, with automated setup, scheduled tasks and persistent content. | Education, Learning, Collaboration | moodle |
| n8n | A visual workflow automation platform with built-in SQLite or PostgreSQL storage. | Automation | n8n |
| Navidrome | A lightweight music server with browser and Subsonic-compatible playback and an empty persistent library. | Media, Music | navidrome |
| Nextcloud | Private file sharing, synchronization and collaboration backed by MariaDB or PostgreSQL. | File Sharing, Collaboration, Productivity | nextcloud |
| NGINX Static Site | An unprivileged NGINX server for static websites and front-end assets, with an editable persistent web root behind Virtualmin TLS. | Web Server, Development | nginx-static |
| NocoDB | A no-code database and spreadsheet interface with persistent SQLite data; the first account becomes administrator. | Database, No-code | nocodb |
| Node-RED | A browser-based flow editor for connecting APIs, devices and online services, with persistent flows and authentication. | Automation, Development | node-red |
| Node.js | An editable Node.js LTS application starter with persistent source and dependency storage, served behind Virtualmin TLS. | Development, Web Server | nodejs |
| ntfy | A private push-notification server for phones, browsers and automation, with persistent messages, attachments and deny-by-default access control. | Notifications, Automation | ntfy |
| Odoo Community | An integrated business suite for CRM, sales, invoicing, accounting, inventory, projects and websites, backed by PostgreSQL. | ERP, CRM, Business | odoo |
| Open WebUI | A private AI chat interface for Ollama or OpenAI-compatible providers; the first registered account becomes administrator. | AI | open-webui |
| OpenSearch | A password-protected single-node OpenSearch 3 search and analytics service with persistent index data, deployable as a local REST service or a public OpenSearch Dashboards application. | Search, Database, Analytics | opensearch |
| PairDrop | A private browser-based local and Internet file transfer service inspired by AirDrop. | File Sharing | pairdrop |
| Paperless-ngx | A searchable document archive with PostgreSQL, Redis, OCR storage and an initial administrator login. | Documents, OCR | paperless-ngx |
| Penpot | A collaborative interface-design and prototyping platform with private PostgreSQL and Valkey services and a dedicated export service. | Design, Collaboration, Development | penpot |
| pgAdmin | A PostgreSQL administration interface with persistent connections, preferences and an initial login. | Database, Administration | pgadmin |
| PhotoPrism | A private photo and video library with search, albums, automatic organization and persistent originals. | Photos, Media, Gallery | photoprism |
| phpMyAdmin | A browser-based administration interface for a local or remote MySQL or MariaDB server. | Database, Administration | phpmyadmin |
| Piwigo | A photo gallery for organizing, publishing and sharing image collections, with unattended setup and persistent media. | Photos, Gallery, Media | piwigo |
| PLANKA | A Trello-style project board with PostgreSQL, persistent attachments and an initial administrator account. | Project Management | planka |
| Pocket ID | A compact OpenID Connect identity provider that authenticates users with passkeys and keeps its configuration in persistent storage. | Identity, Security | pocket-id |
| PrestaShop | An ecommerce platform for building and managing an online store, backed by a private MySQL database. | Commerce, E-commerce, Business | prestashop |
| PrivateBin | A privacy-preserving paste service whose server stores only encrypted content. | Privacy, Sharing | privatebin |
| Prometheus | A monitoring and alerting toolkit with an authenticated web interface, editable scrape configuration and persistent time-series data. | Monitoring, Analytics | prometheus |
| RabbitMQ | A message broker with persistent queues, an authenticated management interface and a direct AMQP listener. | Development, Messaging, Infrastructure | rabbitmq |
| Redmine | A mature project management and issue-tracking platform with projects, wikis, forums, time tracking and Gantt charts. | Project Management, Issue Tracking, Collaboration | redmine |
| Ruby | An editable Ruby web application starter with selectable Rack, Sinatra, Roda or Grape stacks, persistent gems and a Puma server. | Development, Web Server | ruby |
| RustDesk Server | A self-hosted RustDesk ID and relay server for remote desktop connections, with a persistent server identity and database. | Remote Access, Networking, Infrastructure | rustdesk |
| SearXNG | A privacy-respecting metasearch engine that searches multiple providers without profiling its users. | Search, Privacy | searxng |
| SFTPGo | A managed file-transfer server with SFTP, WebDAV, a web client and web administration. | File Sharing, Administration | sftpgo |
| Snipe-IT | An IT asset and license management platform with MariaDB and persistent uploaded files. | IT Management, Assets | snipe-it |
| Stirling PDF | A private browser-based PDF toolbox with authentication and persistent application settings. | PDF, Utilities | stirling-pdf |
| Tandoor Recipes | A recipe organizer, meal planner and shopping-list manager with a private PostgreSQL database and persistent uploaded media. | Recipes, Food, Productivity | tandoor |
| Trilium Notes | A hierarchical notes and personal knowledge-base application with persistent data. | Notes, Knowledge Base | trilium |
| Twenty CRM | A modern customer relationship management platform with private PostgreSQL and Redis services plus a dedicated background worker. | CRM, Business, Productivity | twenty |
| Umami | A simple privacy-focused web analytics platform backed by PostgreSQL. | Analytics, Privacy | umami |
| Uptime Kuma | A friendly uptime and service monitoring dashboard with persistent history and notifications. | Monitoring | uptime-kuma |
| Vaultwarden | A lightweight Bitwarden-compatible password vault with persistent encrypted data. | Security, Passwords | vaultwarden |
| Vikunja | A task and project management application with persistent SQLite data and file attachments. | Project Management, Productivity | vikunja |
| Wallos | A personal subscription and recurring-expense tracker with persistent SQLite data and service logos. | Finance, Subscriptions | wallos |
| Wiki.js | A modern wiki and knowledge platform backed by PostgreSQL. | Wiki, Knowledge Base | wikijs |
| WordPress | A popular publishing platform with a private MariaDB or MySQL database and persistent website files. | CMS, Blog | wordpress |
| YOURLS | A private URL shortener with MySQL and a selectable initial administrator login. | URL Shortener | yourls |
Managing an installed recipe
The Installed Recipe tab shows the live application URL or connection address and status, deployment name, selected database variant, initial username when recoverable, persistent storage, runtime mode, pod and containers, creation time, and an application version when the image exposes a reliable version label.
Use its controls to:
- Start a stopped deployment
- Stop a running deployment without removing configuration or data
- Delete Installed Recipe to permanently remove its pod or containers, reverse proxy when present, and persistent application data
Downloaded images are retained after deletion because the runtime cache can be shared with other deployments. Use Manage Downloaded Images separately if an unused image should also be removed.
Recipe-created pods and containers remain visible on the normal Pods and Containers tabs. They can be inspected, edited, reinstalled, cloned, and troubleshot like manually created resources, except that terminal actions are hidden when a recipe image does not provide an interactive shell. Use Delete Installed Recipe for complete application removal. Deleting resources manually can intentionally leave persistent data behind; deleting a recipe pod offers a separate application-data checkbox, selected by default.
Retained data reserves its deployment name. When redeploying that name, Virtualmin requires explicit confirmation before permanently deleting the old data and creating a clean application. It does not silently attach a new set of generated secrets to an old data directory.
Local recipes and overrides
Packaged definitions are individual JSON files in the module’s recipes/
directory. A system administrator can add new recipes or replace a packaged
definition by placing a file in:
/etc/webmin/virtualmin-podman/recipes/
The filename must match the recipe ID, such as my-application.json. A local
file with an existing ID replaces the packaged definition; a new ID appends a
catalog entry.
Recipe definitions are trusted administrative configuration and can declare container commands, environment, images, ports, mounts, connection mode, terminal availability, initialization steps, and generated secrets. The plugin therefore accepts only real JSON files in a real directory owned by the Webmin process user, rejects symbolic links and group- or world-writable paths, limits each file to 1 MiB, and validates the supported schema before loading it. Invalid entries are ignored and reported in the Webmin error log without preventing valid recipes from loading.
Managing containers
Creating a container
The create form begins with the required image and name, then exposes optional panels selected by the administrator.
Image and identity
- Search the configured registry or enter a complete reference such as
docker.io/library/wordpress:latest. - Give the container a unique, stable name and optional description.
- Choose an existing pod only when the pod and new container use the same runtime mode.
- Decide whether the image should be pulled before each installation.
The module checks the host architecture and can display registry metadata such as description, publisher, stars, pull count, update time, size, digest, and supported platforms.
Ports and reverse proxy
Port mappings support TCP and UDP in [host:]container[/protocol] form. When
the host port is omitted, the plugin allocates an available port beginning at
the configured base port.
Reverse proxying requires:
- A website-enabled virtual server
- At least one published TCP port
- A proxy path that does not conflict with another module-managed or Virtualmin proxy path
When several TCP ports are published, select the container port or mapping
index that should receive proxied traffic. The module can preserve or replace
the original HTTP Host header according to its global configuration.
For a container created inside a pod, configure published ports and the reverse proxy on the pod. Pod member containers do not publish their own host ports.
Volumes and environment
Bind mounts map a host source path to a container destination with rw or ro
mode. Environment variables use KEY=VALUE form.
For delegated users, host mount sources are restricted to the virtual server’s home directory. Sensitive system paths remain blocked unless the master administrator explicitly enables the corresponding advanced override.
Environment values are saved so a container can be recreated. List and audit output masks environment values by default; disclose them only when required and authorized.
Lifecycle and health checks
Container lifecycle controls include:
- Restart policy and maximum retries for
on-failure - Stop timeout and stop signal
- Pull-before-install policy
- Command and entrypoint overrides for master administrators
Virtualmin preserves the selected restart policy even when the installed Podman release needs a compatible runtime fallback for reliable startup after reboot. If Podman cannot update a restart policy in place, saving that change recreates the container from its saved configuration.
Health checks can define:
- Command
- Interval
- Timeout
- Start period
- Retry count
- Action when the container becomes unhealthy
Resource limits
Where supported by the selected mode and host, containers can use:
- Memory limit, swap, and reservation
- CPU shares, CPU count, and CPU or NUMA node pinning
- PID and shared-memory limits
- Block I/O weight
- Per-device bandwidth and IOPS throttling
- Ulimits
- The virtual server owner’s systemd user slice as the cgroup parent
The form reports the capabilities available for the selected runtime mode. Rootless controls depend on cgroup controllers delegated to the domain owner’s user service. Unsupported limits are rejected rather than silently ignored.
Explicit standalone-container limits do not apply to a container created as a pod member; configure shared limits on the pod instead.
Security and host access
Advanced controls include extra Linux capabilities, privileged mode,
no-new-privileges, read-only root filesystem, and host network, PID, or IPC
namespace access.
The master administrator can also allow mounts outside the domain home or
otherwise sensitive mount paths. Extra podman run flags are validated so
they cannot replace flags managed by the module.
These host-level and passthrough controls are not available to delegated domain owners through the remote API.
Editing and reinstalling
The edit page combines saved configuration with current runtime information. Depending on the change, saving either updates metadata or recreates the runtime container so its effective configuration remains synchronized with Virtualmin.
Use Reinstall to force recreation from the saved settings. Reinstallation can retain the saved image-pull policy or explicitly pull or skip pulling the image.
The CLI modify-container command overlays only the supplied scalar settings.
Repeatable collections—including ports, volumes, environment variables,
capabilities, device limits, ulimits, and extra flags—are replaced as complete
collections when supplied. Re-specify every entry to retain, or use the
matching --clear-* option to remove the collection.
Status, logs, console, and inspection
Container pages can show:
- Saved name, description, image, runtime mode, and proxy URL
- Runtime name and ID, status, health, creation time, and uptime
- Published ports, mounts, networks, and restart policy
- Optional CPU and memory usage
- Inspect summary, labels, command, environment, and raw inspect JSON
Logs can be read from the list or detail page. The configured default tail can be overridden from the CLI up to 10,000 lines.
The browser terminal requires Webmin’s xterm module, a running container, and
an image that provides an interactive shell. A recipe can mark terminal access
as unsupported; its container list then shows Not supported instead of a
console action. CLI exec-container can execute one command for automation or
open an interactive /bin/sh session when attached to a terminal.
Bulk operations
The web interface supports bulk start, stop, and delete operations. CLI
lifecycle commands accept repeated --container options or --all for the
selected domain. reinstall-container also supports repeated selectors and
--all.
Deletion removes the runtime container, saved module record, and associated reverse proxy mapping. Downloaded images and data in mounted host directories are kept.
Managing pods
Pods group containers around shared networking and lifecycle. A pod can own published ports, a reverse proxy path, common bind mounts, namespace sharing, and pod-level limits.
Creating a pod
The basic pod definition includes:
- Name and description
- Runtime mode
- Shared port mappings
- Optional reverse proxy path and target port
- Shared host bind mounts
Advanced options include:
- Infra container and user namespace mode
- Shared network, IPC, UTS, PID, and cgroup namespaces
- Restart policy, exit policy, stop timeout, and replace behavior
- CPU, memory, and shared-memory limits
- User-slice cgroup-parent policy
- SELinux relabel mode and ownership shifting for pod bind mounts
- Validated extra
podman pod createflags for master administrators
Pod networking
Supported network modes are:
- Bridge/default — use the runtime’s default network
- Custom — attach to a named Podman network
- Host — share the host network namespace; master-only
- None — create the pod without network connectivity
Depending on the selected network and host support, a pod can also specify:
- Static IPv4 or IPv6 address
- MAC address
- Network aliases
- DNS servers, search domains, and resolver options
- Extra hostname-to-address entries
no-hostsandno-resolvbehavior
Networks can be created and removed from the pod form without leaving the
workflow. Built-in networks such as podman, bridge, host, and none
cannot be deleted.
Adding member containers
Create a container normally and select the target pod. The runtime modes must match. The member container uses the pod’s networking, published ports, and proxy configuration, while retaining container-specific image, environment, command, and mounts.
The pod details page lists each member container and its current status. Open the linked container or use the Containers tab for its logs and terminal.
Lifecycle and cloning
Pods can be started, stopped, and deleted individually or in bulk. Deleting a pod also removes its runtime member containers and reverse proxy mapping. When a pod belongs to an application recipe, the confirmation page also offers to delete its persistent application data. This option is selected by default; clear it only when retaining the data for manual recovery.
Podman does not update an existing pod definition in place, so the plugin does not provide an edit-in-place workflow. Clone Pod creates a new pre-filled definition. You can change its name, ports, proxy path, mounts, networking, namespaces, or limits before creation.
CLI clone-pod also accepts create-pod options as overrides. It generates a
new name when one is not supplied and reallocates published host ports to
avoid collisions with the source pod.
Images and registries
Registry search and metadata
The create form searches the configured registry after enough characters have been entered. Search results are bounded by the module-configured limit and cached briefly to avoid repeated registry requests.
Defaults can be assembled from:
- Local
podman image inspect - Remote
skopeo inspect --config - Bundled
presets.json - Optional custom presets
These sources can suggest ports, bind-mount targets, environment variables, health checks, proxy settings, and image-specific notes. Suggestions remain editable and are validated like manually entered values.
Custom presets are stored in:
/etc/webmin/virtualmin-podman/presets.json
When custom preset mode is enabled, custom rules override matching bundled rules. An empty or invalid custom file falls back to bundled presets.
Downloaded images and runtime stores
The global downloaded-images page displays repositories, tags, IDs, digests, creation time, size, runtime context, and container usage.
Remember that rootful and rootless storage are separate:
rootfulselects the host-global image store.rootlessrequires a domain so the plugin can resolve its Unix owner.- A master image listing with a domain and no explicit mode can combine the visible rootless and rootful stores.
- Pull and delete operations always target one resolved store.
Removing an image normally fails while containers in that store use it.
Forced image deletion removes dependent runtime containers first and cleans up
matching module-managed records, so use --force only when that outcome is
intended.
Podman networks
Networks belong to a runtime context just like images:
- With a domain and no mode, network commands use the module’s configured runtime mode.
--runtime-mode rootlessrequires a domain.--runtime-mode rootfulselects the host-global network store and is the only mode allowed without a domain.
Network creation supports an optional subnet, gateway, IPv6, internal-only mode, and built-in DNS enable or disable setting. Network deletion refuses built-in runtime networks and reports when a network is still in use.
Image-store and network-store commands are intentionally master-only through the remote API because a store can be shared by multiple domains.
Global views
Container Apps Manager provides cross-domain Recipes, Containers, and, when enabled, Pods views for the master administrator. It helps identify application and resource ownership, last-known state, runtime mode, published ports, proxy paths, and the associated virtual server. Bulk actions are available without opening each virtual server separately.
The page renders from saved metadata and runtime snapshots, so opening it does not wait for every rootful and rootless Podman context. Refresh Runtime Status queries each distinct runtime context once, stores current container, pod, health, CPU, and memory information, and reports when the displayed snapshot was last refreshed.
Container and pod list columns are configurable. CPU and memory columns show the most recently refreshed values rather than triggering runtime queries on page load.
Module configuration
The configuration page is divided into six groups.
General settings
- Podman runtime command path
- Default runtime mode
- Runtime-mode selector display policy
- Original HTTP hostname forwarding for reverse proxies
- Domain-owner access
- Reseller access
- Default number of log lines
User interface settings
- Container list columns
- Pod list columns
- Visible container create and edit panels
- Visible pod create panels
Hiding a panel removes it from normal forms but does not weaken backend validation or grant delegated access to master-only options.
Registry and discovery
- Default image registry or custom registry prefix
- Maximum search result count
- Bundled-only or merged custom preset mode
Docker Hub provides the richest search and metadata integration. Other registries work best with explicit full image references when they do not provide an equivalent search API.
Recipe defaults
- Check for a Virtualmin web app installed at the website root before recipe deployment
This safety check is enabled by default. Disable it only when intentionally replacing the root website route with a container application.
Container defaults
- Container access policy
- Restart policy
- Base port for automatic host-port allocation
- User-slice cgroup-parent policy
- Extra capabilities
- Hardening options
- Host-access options
- Extra Podman run flags
Pod defaults
- Pod access policy
- Infra container and user namespace mode
- Shared namespaces and network mode
- Restart, exit, and stop-timeout policy
- User-slice, CPU, memory, and shared-memory settings
- SELinux relabel and ownership-shift behavior
- Extra Podman create flags
Default settings apply to newly created objects. Existing saved objects are not silently rewritten when a module default changes.
Command-line API
The plugin exposes application recipe, container, pod, image, and network
operations through commands discovered by Virtualmin’s virtualmin wrapper.
Local virtualmin subcommands run as root; domain owners and resellers use
the authenticated remote API instead of local shell access.
Display a command’s detailed help with:
virtualmin create-container --help
Inspect its machine-readable command metadata with:
virtualmin get-command --command create-container
Output and exit behavior
Listing commands support:
- Default human-readable table output
--multilinedetailed records--jsonor--xmlVirtualmin API envelopes--name-onlystable object names
list-containers can disclose saved environment values only when explicitly
requested with --show-env-values; values are masked otherwise.
Log and exec commands return their natural text streams. JSON and XML wrappers
place unstructured text in an output field. Registry search also uses the
Virtualmin response envelope; consumers should accept its result text from the
output field rather than assuming a list-style data array.
Successful commands exit with status 0. Validation, authorization, runtime, and required post-action failures return a non-zero status. Mutating commands run deferred Virtualmin post-actions before reporting success, so a failed web server or service reload also makes the command fail.
Application Recipe commands
| Command | Purpose | Owner/reseller remote API |
|---|---|---|
list-application-recipes | List available or installed recipes and live deployment details | Yes |
deploy-application-recipe | Deploy a recipe using its declared connection mode | Yes |
delete-application-recipe | Delete an installed recipe and its persistent data | Yes |
list-application-recipes supports --installed, --available, and
--recipe id filters. Its detailed and structured output includes catalog
availability, variants, images, connection mode, runtime mode, and installed
resource details.
deploy-application-recipe requires --recipe id. It also accepts an
optional deployment --name, --variant, supported initial-login overrides,
and the MySQL host and port for recipes such as phpMyAdmin. Omitted supported
passwords are generated securely and included in the deployment result.
Use --delete-existing-storage only to permanently clear retained data for
the requested deployment name before installation.
delete-application-recipe accepts --recipe, --name, or both. When one
selector could match more than one deployment, use both to identify the exact
installation. Deletion removes persistent application data but retains
downloaded images.
Container commands
| Command | Purpose | Owner/reseller remote API |
|---|---|---|
create-container | Create and deploy a container | Yes |
modify-container | Apply selected changes and recreate when required | Yes |
delete-container | Delete selected containers or all domain containers | Yes |
start-container | Start selected containers or all domain containers | Yes |
stop-container | Stop selected containers or all domain containers | Yes |
restart-container | Restart selected containers or all domain containers | Yes |
reinstall-container | Force recreation from saved settings | Yes |
list-containers | List and inspect domain containers | Yes |
get-container-logs | Print recent container logs | Yes |
exec-container | Execute a command or open an interactive shell | Yes |
Pod commands
| Command | Purpose | Owner/reseller remote API |
|---|---|---|
create-pod | Create a pod | Yes, when pod access is enabled |
clone-pod | Clone a pod with optional overrides | Yes, when pod access is enabled |
delete-pod | Delete selected pods or all domain pods | Yes, when pod access is enabled |
start-pod | Start selected pods or all domain pods | Yes, when pod access is enabled |
stop-pod | Stop selected pods or all domain pods | Yes, when pod access is enabled |
list-pods | List and inspect domain pods | Yes, when pod access is enabled |
get-pod-logs | Print recent pod logs | Yes, when pod access is enabled |
Image and network commands
| Command | Purpose | Owner/reseller remote API |
|---|---|---|
search-container-images | Search the configured registry | Yes |
list-container-images | List images in visible runtime stores | No; master-only |
pull-container-image | Download an image without creating a container | No; master-only |
delete-container-image | Delete images from one runtime store | No; master-only |
list-container-networks | List networks in one runtime store | No; master-only |
create-container-network | Create a Podman network | No; master-only |
delete-container-network | Delete a Podman network | No; master-only |
Domain owners and resellers can download images as part of managing their
containers. create-container downloads its configured image by default, and
reinstall-container --pull downloads it again when recreating that managed
container. The master-only commands above inspect or change Podman images and
networks directly, without creating or reinstalling a managed container.
Application recipe example
List recipe IDs that are currently available for a domain:
virtualmin list-application-recipes \
--domain blog.example.com \
--available \
--name-only
Deploy WordPress with MariaDB. This example lets Virtualmin generate the password rather than placing it in shell history:
virtualmin deploy-application-recipe \
--domain blog.example.com \
--recipe wordpress \
--login-username admin
The result includes the application URL or connection address, generated password, storage path, pod, and container names. Save the password, then inspect the installed deployment in JSON:
virtualmin list-application-recipes \
--domain blog.example.com \
--recipe wordpress \
--installed \
--json
To remove the complete deployment and its persistent data while keeping its downloaded images:
virtualmin delete-application-recipe \
--domain blog.example.com \
--recipe wordpress
Manual WordPress application example
The recipe above is the recommended WordPress workflow. The following manual
example shows how the same architecture can be assembled with lower-level pod
and container commands. It deploys WordPress and MariaDB as two containers in
one pod for a dedicated HTTPS-enabled blog.example.com virtual server. The
pod publishes WordPress and proxies the domain root to it; MariaDB remains
reachable only through the pod’s shared network namespace.
Run these commands as root and replace both example passwords with strong,
independently generated values. The host paths assume the virtual server’s
home is /home/blog; adjust them when the domain uses a different home
directory.
The commands explicitly select rootful mode because the MariaDB image changes ownership of its persistent bind-mounted data directory during initialization. On hosts where rootless containers cannot change ownership of bind mounts, using rootless mode here causes MariaDB to enter a restart loop.
Create the pod and let Virtualmin allocate the host-side port automatically:
virtualmin create-pod \
--domain blog.example.com \
--name wordpress \
--runtime-mode rootful \
--port :80/tcp \
--proxy \
--proxy-path /
Add MariaDB with persistent database storage:
virtualmin create-container \
--domain blog.example.com \
--name wordpress-db \
--pod wordpress \
--runtime-mode rootful \
--image docker.io/library/mariadb:11 \
--volume /home/blog/containers/wordpress/database:/var/lib/mysql:rw \
--env MARIADB_DATABASE=wordpress \
--env MARIADB_USER=wordpress \
--env MARIADB_PASSWORD=CHANGE_ME_DB_PASSWORD \
--env MARIADB_ROOT_PASSWORD=CHANGE_ME_ROOT_PASSWORD
Add the WordPress frontend. Because both containers share the pod’s network
namespace, WordPress reaches MariaDB on 127.0.0.1:3306:
virtualmin create-container \
--domain blog.example.com \
--name wordpress-web \
--pod wordpress \
--runtime-mode rootful \
--image docker.io/library/wordpress:latest \
--volume /home/blog/containers/wordpress/files:/var/www/html:rw \
--env WORDPRESS_DB_HOST=127.0.0.1:3306 \
--env WORDPRESS_DB_USER=wordpress \
--env WORDPRESS_DB_PASSWORD=CHANGE_ME_DB_PASSWORD \
--env WORDPRESS_DB_NAME=wordpress \
--env 'WORDPRESS_CONFIG_EXTRA=$_SERVER["HTTPS"] = "on"; define("WP_HOME", "https://blog.example.com"); define("WP_SITEURL", "https://blog.example.com");'
Open https://blog.example.com/ to complete the WordPress installer. The
WORDPRESS_CONFIG_EXTRA value keeps WordPress on HTTPS when the container is
behind Virtualmin’s root reverse proxy and sets the canonical URL to the
domain root.
The database and WordPress files live below the virtual server home rather than only in the containers’ writable layers. Back up both directories as one application and protect the database passwords like any other production credential.
Operating the WordPress example
Inspect the pod and its containers, read logs, and verify PHP inside the frontend:
virtualmin list-pods --domain blog.example.com --json
virtualmin list-containers --domain blog.example.com --json
virtualmin get-container-logs \
--domain blog.example.com \
--container wordpress-db \
--tail 100
virtualmin get-container-logs \
--domain blog.example.com \
--container wordpress-web \
--tail 100
virtualmin exec-container \
--domain blog.example.com \
--container wordpress-web \
--command "php -v"
Stop and start the application as one unit, or pull an updated WordPress image and recreate only the frontend from its saved configuration:
virtualmin stop-pod --domain blog.example.com --pod wordpress
virtualmin start-pod --domain blog.example.com --pod wordpress
virtualmin reinstall-container \
--domain blog.example.com \
--container wordpress-web \
--pull
Image and network examples
Search for an image in a domain’s configured registry:
virtualmin search-container-images \
--domain blog.example.com \
--query wordpress \
--limit 10
Work with the host-global rootful image store:
virtualmin pull-container-image \
--runtime-mode rootful \
--image docker.io/library/wordpress:latest
virtualmin list-container-images --runtime-mode rootful --json
Create and remove a network in a domain owner’s rootless store:
virtualmin create-container-network \
--domain example.com \
--runtime-mode rootless \
--name app-private \
--internal
virtualmin delete-container-network \
--domain example.com \
--runtime-mode rootless \
--name app-private
Explicit --runtime-mode selection is master-only. For rootful image and
network commands, the domain can be omitted because the target is the
host-global runtime store. Rootless mode always requires a domain.
Remote API
Virtualmin’s authenticated remote API exposes commands at:
https://host.example:10000/virtual-server/remote.cgi
Pass the command as program, command options as request parameters, and
json=1 or xml=1 for the desired response format.
curl --silent --show-error \
--user 'domain-owner:password' \
--get 'https://host.example:10000/virtual-server/remote.cgi' \
--data-urlencode 'program=list-containers' \
--data-urlencode 'domain=example.com' \
--data-urlencode 'json=1'
Deploy an application recipe through the same endpoint. Omitting the initial password lets Virtualmin generate it and return it in the command result:
curl --silent --show-error \
--user 'domain-owner:password' \
--get 'https://host.example:10000/virtual-server/remote.cgi' \
--data-urlencode 'program=deploy-application-recipe' \
--data-urlencode 'domain=blog.example.com' \
--data-urlencode 'recipe=wordpress' \
--data-urlencode 'login-username=admin' \
--data-urlencode 'json=1'
Use HTTPS and provide credentials through the caller’s secret-management facility rather than embedding passwords in scripts. Treat the response as sensitive when it contains generated credentials. Repeat a request parameter when the corresponding CLI option can be repeated.
Remote authorization
The master administrator can call every plugin command through remote.cgi.
Authenticated domain owners and resellers can call only the commands marked
Yes in the tables above, and only when all of these checks pass:
- Owner or reseller module access is enabled
- Container access is enabled for direct container, image, and network commands
- Pod access is enabled for direct pod commands
- The caller can edit the selected Virtualmin domain
- The domain is within the module’s allowed-domain ACL
- The command’s own object and runtime checks pass
Delegated calls cannot explicitly select --runtime-mode or request
master-only privilege, host namespace, host mount, command override, or raw
Podman flag settings. Pod host networking, host user namespaces, and replace
behavior are also master-only.
Cross-domain selectors are rejected even when an object with the requested name exists elsewhere.
A remote API request can return HTTP 200 while the command itself reports status: failure. Treat curl’s exit status as the transport result and always inspect the Virtualmin response status and error fields.
Audit logging
Mutating CLI and remote operations, plus exec-container attempts, are written
to Virtualmin’s command audit log. Environment values, initial-login
passwords, and command-like arguments—including exec commands, entrypoints,
health commands, and extra runtime flags—are redacted before logging.
Rootless exec and streaming operations switch to and verify the complete Unix identity, including supplementary groups, before starting Podman. A failed identity switch terminates the operation rather than continuing as root.
Permissions and safety model
The plugin enforces permissions at the UI, CLI, remote authorization, saved object, and runtime-context layers.
- A caller must be authorized for the selected virtual server before object lookup or runtime access.
- Rootless runtime commands execute as the resolved virtual server Unix owner.
- Runtime identity changes are checked before Podman is executed.
- Delegated users cannot select host-global runtime stores.
- Domain-owner mounts are confined to the domain home directory.
- Sensitive host paths are blocked unless explicitly allowed by the master.
- Privileged mode, host namespaces, extra capabilities, command overrides, and raw runtime flags are master-only controls.
- Reverse proxy paths are normalized and checked for collisions.
- Recipe storage and deletion paths are constrained below the selected virtual server’s home directory.
- Local recipe definitions are treated as trusted configuration and loaded only from process-owned, non-writable, non-symlinked paths after schema validation.
- Failed runtime queries are reported as errors rather than presented as empty lists.
- Required Virtualmin post-actions must complete before a mutation is reported as fully successful.
These controls reduce accidental cross-domain access, but container images and applications still require normal security review. Do not treat an untrusted image as safe merely because it runs inside a container.
Troubleshooting
The plugin does not appear for a domain
Check that:
- The plugin package is installed.
- Podman containers is enabled globally under Features and Plugins.
- The feature is enabled on the target virtual server.
- Owner or reseller access is enabled when using a delegated account.
- The account’s Virtualmin and module ACL includes the domain.
Podman command not found
Confirm that Podman is installed and that Podman runtime command in module configuration points to the executable. Run the configured command as root to verify that the binary starts.
Rootless initialization fails
Read the complete error shown by the plugin. Common causes include failure to
enable systemd linger, an unwritable /run/user/UID directory, subordinate ID
file permissions, or a failed podman system migrate operation.
The plugin reports the failed preparation step. Correct the host issue and retry; do not work around it by making a delegated command run as root.
A resource option is unavailable
Resource controls depend on the runtime mode, cgroup version, and controllers delegated to the virtual server owner’s user service. Select another supported limit, configure user-slice delegation, or use the rootful domain-user mode when appropriate.
An application recipe is unavailable
Read the reason shown below the recipe. Common causes include missing website
support for public web access, an incompatible runtime policy, insufficient
free quota, disk space, memory or swap, a required fixed port already being in
use, and an existing reverse proxy at /.
Public web recipes use the domain root and cannot share it with another recipe or proxy. Create a dedicated virtual server or subdomain instead of attempting to assign the recipe a subdirectory. Local-host and direct-service recipes do not create a root reverse proxy, although direct services may reserve fixed host ports and therefore allow only one deployment per physical server.
For public web recipes, deployment also stops by default when a Virtualmin web app is already installed at the website root. Uninstall that web app or create a dedicated virtual server. The master administrator can disable this check under Recipe defaults, but the container application’s root proxy will then take precedence over the existing root website.
A recipe deployment failed
Read the final deployment output. It identifies the failed container, readiness command, public port, HTTP check, or initialization step and states whether rollback completed. Downloaded images are intentionally retained and do not indicate that an application is still installed.
If rollback was incomplete, inspect the remaining pod or containers from the normal tabs and review their logs before deleting them. Do not assume that an empty recipe list means the runtime query succeeded when the page or command also reports a Podman error.
A recipe deployment name is still in use
Persistent data can remain after manually deleting a recipe’s pod or containers. Select that deployment name on the recipe form and explicitly choose to delete its retained data before installing a clean application, or use another name. Use Delete Installed Recipe for complete removal when the deployment is still listed.
A proxy cannot be enabled
Confirm that the virtual server has website support, the container or pod has a published TCP port, and the requested path does not conflict with another proxy. For a pod member, configure proxying on the pod rather than the member container.
An image or network appears to be missing
Confirm the runtime context. Rootless and rootful Podman stores are separate, and rootless stores are selected through the domain’s Unix owner. Use an explicit runtime mode as the master administrator when diagnosing store visibility.
A remote request has HTTP 200 but did not run
Inspect the JSON or XML status, error, and full_error fields. HTTP status
describes the CGI request; the response body describes command authorization,
validation, and runtime success.
Requirements and operational notes
- Virtualmin Pro with the Podman plugin installed and enabled
- Podman installed and reachable through the configured command path
skopeorecommended for remote metadata and architecture discovery- Webmin’s
xtermmodule for supported browser terminal access - Website support for virtual servers using reverse proxy paths
- Enough disk, quota, memory, and swap for the selected application recipe
- Host support for the selected rootless, networking, namespace, and cgroup features
Runtime behavior can vary with Podman, kernel, systemd, cgroup, and network backend versions. The plugin validates known capability boundaries and reports runtime failures, but the host must still provide the feature requested by the container or pod.