| SYSTEM INFORMATION | |
|---|---|
| OS type and version | Ubuntu Linux 22.04.5 |
| Webmin version | 2.670 |
| Virtualmin version | 8.3.0 Professional |
| Webserver version | 2.570 |
| Related packages | SUGGESTED |
Hi
There is a bug that make batch create sites and wordpress app install, it will install the first without problem but from site 2 and onward it fails in wordpress install.
i have placed a markdown bug report in the zip file and vil try to places alle the text ind here also…
Virtualmin_8.3.0_Batch_WordPress_Bug_Report.zip (6.1 KB)
# Bug report: Batch Create Servers fails to install WordPress on subsequent servers
**Product:** Virtualmin 8.3.0 Professional
**Incident date:** 6 November 2026
**Status:** Local workaround verified with two servers in one batch after a Webmin restart
**Suggested priority:** Functional defect affecting automated provisioning; misleading success reporting
## Summary
When using **Batch Create Servers → Creating virtual servers from pasted text**, with a server template configured to install WordPress automatically, the first virtual server receives a working WordPress installation. Subsequent servers are created, but their WordPress installation stops during PHP requirements checking:
```text
Checking PHP modules ..
Installing required PHP mysqlnd module ..
.. could not find domain’s php.ini file
.. failed to setup script requirements
```
The batch nevertheless finishes with **0 errors**. The domains exist, but the requested WordPress applications are missing.
Inspection of the installed code identified three calls inside `create_virtual_server` using `$d`, whereas the function receives and otherwise processes the current domain as `$dom`. Replacing those three references with `$dom`, then restarting Webmin, was followed by a successful two-server batch. Both WordPress front pages were subsequently opened successfully.
The successful test supports this correction, but the exact runtime contents and scope of the original `$d` variable were not instrumented. Please review the patch upstream and investigate error propagation separately.
## Environment
| Component | Observed value |
| — | — |
| OS | Ubuntu Linux 22.04.5 |
| Kernel / architecture | Linux 5.15.0-202-generic, x86_64 |
| Virtualmin | 8.3.0 Professional |
| Webmin | 2.670 |
| Usermin | 2.570 |
| Authentic theme | 26.70 |
| PHP | 8.5.12 |
| PHP execution mode | FCGI; reported by Virtualmin as `fcgid` |
| CGI execution mode | suEXEC |
| Web server | Apache, with `www-data` added to the domain group |
| WordPress installer version label | `wordpress version 7.1.4`, exactly as printed in the provisioning logs |
| Server type | Top-level virtual servers |
| Template | `Default Settings - Wordpress` |
| PHP configuration layout | Per-domain `~/etc/php8.5/php.ini` and FCGI wrapper |
| Provisioning method | Batch creation from pasted text |
All compared domains used the same template and plan. PHP 8.4 configuration files and wrappers also existed, but the selected version was PHP 8.5. Database server version and the exact pasted batch input were not captured for this report.
## Steps to reproduce
1. Use the environment above with a template configured to install WordPress automatically at `/wordpress/`.
2. Open **Batch Create Servers**.
3. Paste valid input for at least two new top-level virtual servers using the same template and plan.
4. Use valid passwords containing uppercase and lowercase letters and digits. Special characters are not required to trigger the failure.
5. Start batch creation.
6. Observe the app installation section for each server, rather than relying only on the final batch summary.
The exact batch-input rows are deliberately not reconstructed here because they were not retained in the supplied evidence. Credentials are omitted throughout.
## Expected behavior
- WordPress should install on every server whose prerequisites are satisfied.
- PHP module and configuration checks should use the current domain’s configuration.
- If a requested app fails to install, the final result should expose that failure clearly, even if creation of the underlying virtual server succeeded.
## Actual behavior before the verified workaround
| Batch | First server | Subsequent server(s) | Final summary |
| — | — | — | — |
| Initial observed batch | `esis-004.slotshaven.it`: WordPress installed | `esis-005.slotshaven.it`, `esis-006.slotshaven.it`: PHP requirements failed | `3 created, 0 errors` |
| Later observed batch | `esis-009.slotshaven.it`: WordPress installed | `esis-010.slotshaven.it`: same PHP requirements failure | `2 created, 0 errors` |
| After local edits and explicit Webmin restart | `esis-011.slotshaven.it`: WordPress installed | `esis-012.slotshaven.it`: WordPress installed | `2 created, 0 errors` |
The 009/010 failure was reported during the patching sequence. The edits were subsequently verified on disk, but whether that failing request loaded the changed code was not established. The first explicitly documented successful test followed `systemctl restart webmin`. No claim is made that a restart alone would fix the original unpatched code.
### Representative failure excerpt
```text
Creating virtual server esis-010.slotshaven.it ..
[Unix user, home, website, SSL, MySQL and Webmin setup completed]
Installing third-party web apps ..
Installing wordpress version 7.1.4 ..
Checking PHP modules ..
Installing required PHP mysqlnd module ..
.. could not find domain's php.ini file
.. failed to setup script requirements
.. done
[Webserver configuration and initial index page completed]
.. done
Batch creation complete: 2 created, 0 errors
```
Bracketed text summarizes omitted successful log lines; this is an abbreviated excerpt, not a byte-for-byte full log.
## Investigation and findings
### 1. Password handling was the initial suspicion, but does not explain this PHP failure
Initially, failures appeared related to passwords or special characters. Manual installation accepted a password containing uppercase and lowercase letters, digits and several symbols, including `#`, `*`, `(`, `$` and `¤`. Passwords containing only lowercase letters and digits were rejected by the manual initial-login validation; adding an uppercase letter was reported to satisfy that requirement.
Importantly, batch installation also failed with a password consisting only of mixed-case letters and digits, which worked manually. Therefore special characters were not necessary to reproduce the PHP requirements failure.
These observations do not establish that all password characters work in every batch/API context. They distinguish the observed manual validation behavior from the specific PHP error investigated here. No actual passwords are included.
### 2. Selected PHP settings were the same
Virtualmin reported PHP 8.5 and `fcgid` for domains 004, 005 and 006, using the same template and plan. Successful domain 004 had a reported PHP maximum execution time of 40 seconds; failed domains 005 and 006 had 30 seconds. No timeout appeared in the failure log, and this setting was not changed as the workaround.
### 3. PHP configuration files existed on all three domains
A filesystem check found both versions’ configuration files and wrappers on domains 004, 005 and 006:
```text
/home//fcgi-bin/php8.5.fcgi
/home//fcgi-bin/php8.4.fcgi
/home//etc/php8.5/php.ini
/home//etc/php8.4/php.ini
```
Thus, the files existed when inspected after batch completion. This alone would not prove their availability at the instant the installer ran.
### 4. PHP 8.5 FCGI wrappers were identical
```bash
#!/bin/bash
PHPRC=$PWD/../etc/php8.5
export PHPRC
umask 022
PHP_FCGI_MAX_REQUESTS=99999
export PHP_FCGI_MAX_REQUESTS
exec /bin/php-cgi8.5
```
### 5. Direct PHP tests successfully loaded the correct configuration and modules
The following read-only check was run as each domain owner:
```bash
for n in 004 005 006; do
echo "=== esis-$n ==="
sudo -u "esis-$n.slotshaven.it" \\
env PHPRC="/home/esis-$n.slotshaven.it/etc/php8.5" \\
/bin/php-cgi8.5 -i |
grep -E 'Loaded Configuration File|Scan this dir|Additional .ini|mysqlnd|mysqli|PDO drivers'
done
```
All three showed:
- Their own `/home//etc/php8.5/php.ini` loaded.
- Additional INI scanning under `/etc/php/8.5/cgi/conf.d`.
- `10-mysqlnd.ini` and `20-mysqli.ini` parsed.
- `mysqlnd` enabled, version 8.5.12.
- `mysqli` available.
- API extensions `mysqli,pdo_mysql`.
- PDO driver `mysql`.
This proves that the selected CGI binary could load the required modules with the supplied domain environment after creation. It does not reproduce every aspect of the installer or an actual Apache request.
### 6. Code path producing the error
Installed file: `/usr/share/webmin/virtual-server/virtual-server-lib-funcs.pl`
`create_virtual_server` began at line 8576 in the inspected installation:
```perl
sub create_virtual_server
{
my ($dom, $parentdom, $parentuser, $noscripts, $nopost,
$pass, $content) = @\_;
```
The template app-installation block used `$dom` for path validation, PHP version setup and dependency checking, but used `$d` for three other calls. No local `$d` definition was present in the inspected function prefix through that block.
The failing call at approximately line 8912 was:
```perl
if (!&setup_script_requirements($d, $script, $ver, $phpver, $opts, undef)) {
&$second_print($text{'setup_scriptreqs'});
next;
}
```
Inside `/usr/share/webmin/virtual-server/scripts-lib.pl`, the module check and configuration lookup were:
```perl
next if (&check_php_module($mphp, $phpver, $d) == 1);
# …
my $mode = &get_domain_php_mode($d);
my $inifile = $mode eq “mod_php” || $mode eq “fpm” ?
&get_global_php_ini($phpver, $mode) :
&get_domain_php_ini($d, $phpver);
if (!$inifile) {
\# Could not find php.ini
&$second_print($mode eq "mod_php" || $mode eq "fpm" ?
$text{'scripts_noini'} : $text{'scripts_noini2'});
if ($opt) { next; }
else { return 0; }
}
```
Here `$d` is the called function’s domain parameter; the concern is the argument supplied by `create_virtual_server`, not this parameter name itself.
`get_domain_php_ini` in `php-lib.pl` calls `list_domain_php_inis($d)`, selects the requested version or a fallback, and returns `undef` if none is found. This explains the visible error when the lookup does not resolve an INI file.
## Local workaround applied
Three domain arguments inside **only `create_virtual_server`** were changed. No global replacement of `$d` was performed.
```diff
-– virtual-server-lib-funcs.pl (before)
+++ virtual-server-lib-funcs.pl (local workaround)
@@
my $opts = { 'path' => &substitute_scriptname_template(
- $sinfo->{‘path’}, $d) };
+ $sinfo->{‘path’}, $dom) };
@@
- &setup_script_packages($script, $d, $ver);
+ &setup_script_packages($script, $dom, $ver);
@@
- if (!&setup_script_requirements($d, $script, $ver, $phpver, $opts, undef)) {
+ if (!&setup_script_requirements($dom, $script, $ver, $phpver, $opts, undef)) {
```
This is a minimal review diff; line numbers and context should be checked against the installed release before applying it.
### Application procedure used
1. A Python script isolated the `create_virtual_server` function, checked that each of the three original fragments occurred exactly once, and aborted on a mismatch.
2. A timestamped backup was created before writing the edited file.
3. The three substitutions above were saved.
4. The relevant file section was read back and all three `$dom` arguments were confirmed.
5. Webmin was explicitly restarted:
```bash
sudo systemctl restart webmin
```
The observed backup path was:
```text
/usr/share/webmin/virtual-server/virtual-server-lib-funcs.pl.bak-20261106-122104-527929
```
No PHP package installation, PHP mode change, INI copying or database configuration change was used as part of this successful workaround. A standalone Perl syntax check was not recorded; validation consisted of reading back the edits and performing the provisioning test below.
### Rollback for this installation
If necessary, the original file can be restored from the recorded backup and Webmin restarted:
```bash
sudo cp -p \
/usr/share/webmin/virtual-server/virtual-server-lib-funcs.pl.bak-20261106-122104-527929 \
/usr/share/webmin/virtual-server/virtual-server-lib-funcs.pl
sudo systemctl restart webmin
```
These rollback commands are specific to the backup recorded above. Rolling back would remove the local workaround. A future package update may also overwrite the edited file.
## Verification after workaround and restart
A fresh batch created domains 011 and 012 using the automatic WordPress installation workflow. Both reported:
```text
Installing wordpress version 7.1.4 ..
Configuring webserver PHP settings ..
.. done
Creating MySQL database _wp ..
.. done
.. done : WordPress installation completed.
```
The completed installation URLs were:
- https://esis-011.slotshaven.it/wordpress/
- https://esis-012.slotshaven.it/wordpress/
The administrator confirmed that both WordPress front pages could be opened.
**Verification boundary:** One two-server batch after the edits and explicit restart is documented as successful. Admin-login testing, a larger batch, other PHP modes/versions, other applications and all password-character combinations were not separately verified.
## Separate defect: misleading batch success reporting
The original failed batch displayed `3 created, 0 errors`, despite two explicit app-installation failures. A later failing batch displayed `2 created, 0 errors`, despite one such failure.
The underlying virtual servers were created successfully, so the count may represent server creation only. However, the workflow also requested automatic WordPress deployment, and the final summary did not communicate the incomplete provisioning.
The inspected caller prints `setup_scriptreqs` and executes `next` when requirements fail. This is a concrete point to review for error propagation, but the full aggregation path in the batch controller was not inspected, so this report does not claim a complete diagnosis of the counter implementation.
Suggested behavior: retain separate counts if needed, for example servers created, apps installed, and apps failed, and return a visible warning or failure status whenever requested application deployment is incomplete.
## Requested support / upstream action
1. Review the three `$d` arguments inside `create_virtual_server` in Virtualmin 8.3.0 Professional and confirm the correct domain object for each call.
2. Investigate why the first domain succeeds while subsequent domains fail, including any dynamically scoped or package-level `$d` state.
3. Confirm whether an official fix or supported package is available; the local workaround should not be relied on permanently across upgrades.
4. Fix or clarify final batch status reporting for failed template application installations.
5. Add a regression test creating at least two domains in one batch with a template-installed WordPress application under FCGId and per-domain PHP configuration.
6. Consider equivalent regression coverage for other template-installed applications and supported PHP modes.
## Historical reference
The official 8.3.0 release notes mention fixes for batch-created servers not applying template initial website content and for batch creation progress/status reporting. This incident still occurred on the reported 8.3.0 Professional installation. The release notes are context only; they do not establish that this is the same defect.
## Evidence and redaction notes
This report was compiled from administrator-supplied command output, source excerpts, provisioning logs and the administrator’s final browser verification. No remote access to the server was used. Passwords, personal descriptions, contact addresses and network addressing have been omitted. The example domain names and software versions are retained to correlate the before/after batches. Routine terminal mistakes during troubleshooting were excluded because they did not modify the patched file or explain the provisioning failure.