| SYSTEM INFORMATION | |
|---|---|
| OS type and version | AlmaLinux 10.2 |
| Webmin version | 2.660 |
| Virtualmin version | 8.2.0 GPL |
| Webserver version | Apache httpd 2.4.63 (AmaLinux) |
| Related packages | webmin-virtual-server-8.2.0-1.gpl.noarch; httpd; perl |
I hit what appears to be a restore preflight bug when migrating a virtual server from another Virtualmin host. Apologies if I have misunderstood.
The source virtual server administration user had UID 1008:
user1:x:1008:1006:...
On the destination server, UID 1008 was already allocated to an unrelated virtual server:
user2:x:1008:1005:...
The restore was run with UID/GID reallocation enabled:
virtualmin restore-domain \
--source /path/to/domain1.com.tar.gz \
--domain domain1.com \
--all-features \
--only-missing \
--reuid \
--default-ip \
--no-ip6 \
--test
but failed during preflight:
Checking for missing features ..
.. all features in backup are supported
Checking for errors in backup ..
.. this backup cannot be restored : A unix user with UID 1008 already exists
The same occurred with --skip-warnings and --fix.
The documented/default behaviour appears to be that UID/GID values should be reallocated unless --no-reuid is specified, so an existing numeric UID on the destination should not prevent the restore.
I traced this through the installed Virtualmin 8.2.0 code.
In restore-domain.pl, %opts is populated:
$opts{'reuid'} = $reuid;
$opts{'mail'}->{'reuser'} = $reuser;
$opts{'fix'} = $fix;
$opts{'repl'} = $replication;
but check_restore_errors() is called with:
@errs = &check_restore_errors($cont, $contdoms, $opts);
rather than:
@errs = &check_restore_errors($cont, $contdoms, \%opts);
The adjacent call similarly uses:
$opts->{'repl'}
rather than:
$opts{'repl'}
I changed those locally to:
@errs = &check_restore_errors($cont, $contdoms, \%opts);
and:
foreach my $w (&virtual_server_warnings(
$d, undef, $opts{'repl'})) {
However, that alone is not sufficient.
check_restore_errors() then calls:
my $cerr = &virtual_server_clashes(
$d, undef, undef, $opts->{'repl'});
The domain structure still contains the UID/GID from the backup.
virtual_server_clashes() calls check_unix_clash(), which contains:
if (!$field || $field eq 'uid') {
return &text('setup_eunixclash3', $d->{'uid'})
if ($d->{'uid'} &&
defined(getpwuid($d->{'uid'})));
}
and similarly for GID.
Thus restore preflight checks the old numeric UID/GID even though --reuid means those values will not be retained.
As a local workaround I changed check_restore_errors() so that, when reuid is enabled, it passes a shallow copy of the domain with uid and gid removed to virtual_server_clashes():
if ($d->{'missing'}) {
my $clashdom = $d;
if ($opts->{'reuid'}) {
$clashdom = { %$d };
delete($clashdom->{'uid'});
delete($clashdom->{'gid'});
}
my $cerr = &virtual_server_clashes(
$clashdom, undef, undef, $opts->{'repl'});
if ($cerr) {
push(@rv, {
'critical' => 1,
'desc' => $cerr,
'dom' => $d
});
}
}
This still checks username clashes, group-name clashes, database clashes and other feature clashes; it ignores only the backed-up numeric UID/GID when reallocation is enabled.
With both changes in place the dry run passed:
Checking for errors in backup ..
.. no errors found
The actual restore then completed successfully and Virtualmin performed the expected reallocation:
Re-allocating user and group IDs ..
.. allocated user ID is 1010 and group ID is 1007
So the backup itself was valid and the UID collision was harmless.
Suggested fixes:
-
In restore-domain.pl:
-@errs = &check_restore_errors($cont, $contdoms, $opts);
+@errs = &check_restore_errors($cont, $contdoms, %opts);-foreach my $w (&virtual_server_warnings($d, undef, $opts->{‘repl’})) {
+foreach my $w (&virtual_server_warnings($d, undef, $opts{‘repl’})) { -
During restore preflight, if reuid is enabled, do not include the source numeric UID/GID when performing virtual_server_clashes(), while retaining all other clash checks.
This seems preferable to pre-creating domain1.com or requiring source UID/GID values to be unique on the destination.
I can provide the exact diff against Virtualmin 8.2.0 if useful.