Problem: UCS@school Replica Join Fails: 96univention-samba4slavepdc.inst - The relative ID (SAMBA) is already in use

Problem

On a UCS@school Replica Node, the join script 96univention-samba4slavepdc.inst does not complete successfully.

The following output can be found in /var/log/univention/join.log:

RUNNING 96univention-samba4slavepdc.inst
2026-04-16 12:34:44.032879903+02:00 (in joinscript_init)
Object exists: cn=Builtin,dc=intern,dc=univention,dc=de
The relative ID (SAMBA) is already in use: 556.

EXITCODE=3
98da3c94-922c-4f32-b431-e5b31675777b
univention-join-hooks: looking for hook type "join/post-joinscripts" on ucs-primary.intern.univention.de
Found hooks:


Do 16. Apr 12:34:46 CEST 2026
univention-run-join-scripts finished

Root Cause

The issue is caused by a previous Active Directory (AD) takeover, where a German Microsoft AD environment was migrated into UCS LDAP using the ad-takeover application.

During this process, both German and English group names were imported, resulting in conflicting Relative IDs (RIDs).

The following log entry indicates the conflict:

Object exists: cn=Builtin,dc=intern,dc=univention,dc=de
The relative ID (SAMBA) is already in use: 556.

Further details are documented in the following bug report, which describes the same behavior:
https://forge.univention.org/bugzilla/show_bug.cgi?id=55911


Environment

root@ucs-primary:~/univention-support# univention-app info
UCS: 5.2-4 errata349
Installed: adtakeover=9.0 samba4=4.21 ucsschool=5.2v4

Investigation

To identify affected objects, perform an LDAP search for all entries below cn=Builtin:

univention-ldapsearch -LLL -b "cn=Builtin,$(ucr get ldap/base)" | less

A follow-up search for RID 556 confirms the issue described in the bug report:

dn: cn=Netzwerkkonfigurations-Operatoren,cn=Builtin,dc=intern,dc=univention,dc=de
gidNumber: 5062
sambaGroupType: 2
univentionGroupType: -2147483643
sambaSID: S-1-5-32-556
objectClass: posixGroup
objectClass: top
objectClass: univentionObject
objectClass: univentionGroup
objectClass: sambaGroupMapping
univentionObjectType: groups/group
cn: Netzwerkkonfigurations-Operatoren

Workaround

Until an official fix is released, the following workaround can be applied.
The workaround replaces the failing join script with a modified version that tolerates pre-existing objects.

1. Backup the existing join script

  • mv /usr/lib/univention-install/96univention-samba4slavepdc.inst /usr/lib/univention-install/96univention-samba4slavepdc.inst.bak

2. Create a new join script with the same name

  • touch /usr/lib/univention-install/96univention-samba4slavepdc.inst

3. Insert the following content into the new join script

#!/bin/bash
#
# Univention Samba4 Replica Directory Node PDC helper
#  join script
#
# SPDX-FileCopyrightText: 2013-2026 Univention GmbH
# SPDX-License-Identifier: AGPL-3.0-only

## joinscript api: bindpwdfile

VERSION=3
. /usr/share/univention-join/joinscripthelper.lib
joinscript_init

. /usr/share/univention-lib/all.sh
. /usr/share/univention-samba4/lib/all.sh

NAME="S4 SlavePDC"

eval "$(univention-config-registry shell)"

# This join script is a Workaround for Bug #30105:
# This code was copied from UCS 3.1-0 98univention-samba4-dns.inst

# samba4 allowed on this system?
if is_ucr_true samba4/disabled; then
    echo "WARNING: samba4 on this system is not allowed."
    echo "         The samba4 join stops here. To rerun the"
    echo "         join script, use "
    echo "         -> univention-run-join-scripts"
    exit 0
fi


is_school_slave ()
{
    local ldap_hostdn="$(ucr get ldap/hostdn)"
    univention-ldapsearch -LLL -b "$ldap_hostdn" "(&(univentionService=UCS@school)(univentionServerRole=slave))" dn | grep -qi "^dn:"
}
if ! is_school_slave; then
    # This join script should only run on a UCS@school Replica Directory Node
    # See bug 47234.
    echo "INFO: This system is not a UCS@school Replica Directory Node."
    joinscript_save_current_version
    exit 0
fi


## Check if Samba 4 setup is done
LDB_URI="tdb:///var/lib/samba/private/sam.ldb"
domaindn="DC=${kerberos_realm//./,DC=}" # that's what /usr/share/pyshared/samba/provision.py uses
if ! ldbsearch -H "$LDB_URI" -b "$domaindn" -s base dn 2>/dev/null| grep -qi ^"dn: $domaindn"; then
    echo "Samba4 backend database not available yet, exiting joinscript $(basename "$0")."
    exit 1
fi

_create_default_s4_groups ()
{
    udm container/cn create "$@" --set name=Builtin --ignore_exists || die

    udm groups/group create "$@" --set name="$(custom_groupname "Network Configuration Operators")" \
        --ignore_exists \
        --position "cn=Builtin,$ldap_base" \
        --set description="Members in this group can have some administrative privileges to manage configuration of networking features" \
        --set sambaGroupType="2" \
        --set adGroupType="-2147483643" \
        --set sambaRID="556" ||die

    udm groups/group create "$@" --set name="$(custom_groupname "Read-Only Domain Controllers")" \
        --ignore_exists \
        --position "cn=groups,$ldap_base" \
        --set description="Members of this group are Read-Only Domain Controllers in the domain" \
        --set sambaGroupType="2" \
        --set adGroupType="-2147483646" \
        --set sambaRID="521" ||die

    udm groups/group create "$@" --set name="$(custom_groupname "Remote Desktop Users")" \
        --ignore_exists \
        --position "cn=Builtin,$ldap_base" \
        --set description="Members in this group are granted the right to logon remotely" \
        --set sambaGroupType="2" \
        --set adGroupType="-2147483643" \
        --set sambaRID="555" ||die

    udm groups/group create "$@" --set name="$(custom_groupname "Distributed COM Users")" \
        --ignore_exists \
        --position "cn=Builtin,$ldap_base" \
        --set description="Members are allowed to launch, activate and use Distributed COM objects on this machine." \
        --set sambaGroupType="2" \
        --set adGroupType="-2147483643" \
        --set sambaRID="562" ||die

    udm groups/group create "$@" --set name="$(custom_groupname "Pre-Windows 2000 Compatible Access")" \
        --ignore_exists \
        --position "cn=Builtin,$ldap_base" \
        --set description="A backward compatibility group which allows read access on all users and groups in the domain" \
        --set sambaGroupType="2" \
        --set adGroupType="-2147483643" \
        --set sambaRID="554" ||die

    udm groups/group create "$@" --set name="$(custom_groupname "RAS and IAS Servers")" \
        --ignore_exists \
        --position "cn=groups,$ldap_base" \
        --set description="Servers in this group can access remote access properties of users" \
        --set sambaGroupType="2" \
        --set adGroupType="-2147483644" \
        --set sambaRID="553" ||die

    udm groups/group create "$@" --set name="$(custom_groupname "Enterprise Admins")" \
        --ignore_exists \
        --position "cn=groups,$ldap_base" \
        --append users="uid=$(custom_username Administrator),cn=users,$ldap_base" \
        --set description="Designated administrators of the enterprise" \
        --set sambaGroupType="2" \
        --set adGroupType="-2147483640" \
        --set sambaRID="519" ||die

    udm groups/group create "$@" --set name="$(custom_groupname "Account Operators")" \
        --ignore_exists \
        --position "cn=Builtin,$ldap_base" \
        --set description="Members can administer domain user and group accounts" \
        --set sambaGroupType="2" \
        --set adGroupType="-2147483643" \
        --set sambaRID="548" ||die

    udm groups/group create "$@" --set name="$(custom_groupname "Terminal Server License Servers")" \
        --ignore_exists \
        --position "cn=Builtin,$ldap_base" \
        --set description="Members of this group can update user accounts in Active Directory with information about license issuance, for the purpose of tracking and reporting TS Per User CAL usage" \
        --set sambaGroupType="2" \
        --set adGroupType="-2147483643" \
        --set sambaRID="561" ||die

    udm groups/group create "$@" --set name="$(custom_groupname "Domain Controllers")" \
        --ignore_exists \
        --position "cn=groups,$ldap_base" \
        --set description="All domain controllers in the domain" \
        --set sambaGroupType="2" \
        --set adGroupType="-2147483646" \
        --set sambaRID="516" ||die

    udm groups/group modify "$@" --dn "cn=$(custom_groupname "Domain Controllers"),cn=groups,$ldap_base" \
        --append hosts="$ldap_hostdn"

    udm groups/group create "$@" --set name="$(custom_groupname "Server Operators")" \
        --ignore_exists \
        --position "cn=Builtin,$ldap_base" \
        --set description="Members can administer domain servers" \
        --set sambaGroupType="2" \
        --set adGroupType="-2147483643" \
        --set sambaRID="549" ||die

    udm groups/group create "$@" --set name="$(custom_groupname "Cert Publishers")" \
        --ignore_exists \
        --position "cn=groups,$ldap_base" \
        --set description="Members of this group are permitted to publish certificates to the directory" \
        --set sambaGroupType="2" \
        --set adGroupType="-2147483644" \
        --set sambaRID="517" ||die

    udm groups/group create "$@" --set name="DnsUpdateProxy" \
        --ignore_exists \
        --position "cn=groups,$ldap_base" \
        --set description="DNS clients who are permitted to perform dynamic updates on behalf of some other clients (such as DHCP servers)." \
        --set sambaGroupType="2" \
        --set adGroupType="-2147483646" \
        --set sambaRID="1102" ||die

    udm groups/group create "$@" --set name="$(custom_groupname "Performance Monitor Users")" \
        --ignore_exists \
        --position "cn=Builtin,$ldap_base" \
        --set description="Members of this group can access performance counter data locally and remotely" \
        --set sambaGroupType="2" \
        --set adGroupType="-2147483643" \
        --set sambaRID="558" ||die

    udm groups/group create "$@" --set name="$(custom_groupname "Guests")" \
        --ignore_exists \
        --position "cn=Builtin,$ldap_base" \
        --append nestedGroup="cn=$(custom_groupname "Domain Guests"),cn=groups,$ldap_base" \
        --set description="Guests have the same access as members of the Users group by default, except for the Guest account which is further restricted" \
        --set sambaGroupType="2" \
        --set adGroupType="-2147483643" \
        --set sambaRID="546" ||die

    udm groups/group create "$@" --set name="$(custom_groupname "Certificate Service DCOM Access")" \
        --ignore_exists \
        --position "cn=Builtin,$ldap_base" \
        --set description="Members of this group are allowed to connect to Certification Authorities in the enterprise" \
        --set sambaGroupType="2" \
        --set adGroupType="-2147483643" \
        --set sambaRID="574" ||die

    udm groups/group create "$@" --set name="$(custom_groupname "Schema Admins")" \
        --ignore_exists \
        --position "cn=groups,$ldap_base" \
        --append users="uid=$(custom_username Administrator),cn=users,$ldap_base" \
        --set description="Designated administrators of the schema" \
        --set sambaGroupType="2" \
        --set adGroupType="-2147483640" \
        --set sambaRID="518" ||die

    udm groups/group create "$@" --set name="$(custom_groupname "Enterprise Read-Only Domain Controllers")" \
        --ignore_exists \
        --position "cn=groups,$ldap_base" \
        --set description="Members of this group are Read-Only Domain Controllers in the enterprise" \
        --set sambaGroupType="2" \
        --set adGroupType="-2147483640" \
        --set sambaRID="498" ||die

    udm groups/group create "$@" --set name="$(custom_groupname "Replicator")" \
        --ignore_exists \
        --position "cn=Builtin,$ldap_base" \
        --set description="Supports file replication in a domain" \
        --set sambaGroupType="2" \
        --set adGroupType="-2147483643" \
        --set sambaRID="552" ||die

    udm groups/group create "$@" --set name="$(custom_groupname "Domain Computers")" \
        --ignore_exists \
        --position "cn=groups,$ldap_base" \
        --set description="All workstations and servers joined to the domain" \
        --set sambaGroupType="2" \
        --set adGroupType="-2147483646" \
        --set sambaRID="515" ||die

    udm groups/group create "$@" --set name="DnsAdmins" \
        --ignore_exists \
        --position "cn=groups,$ldap_base" \
        --set description="DNS Administrators Group" \
        --set sambaGroupType="2" \
        --set adGroupType="-2147483644" \
        --set sambaRID="1101" ||die

    udm groups/group create "$@" --set name="$(custom_groupname "Windows Authorization Access Group")" \
        --ignore_exists \
        --position "cn=Builtin,$ldap_base" \
        --set description="Members of this group have access to the computed tokenGroupsGlobalAndUniversal attribute on User objects" \
        --set sambaGroupType="2" \
        --set adGroupType="-2147483643" \
        --set sambaRID="560" ||die

    udm groups/group create "$@" --set name="$(custom_groupname "Incoming Forest Trust Builders")" \
        --ignore_exists \
        --position "cn=Builtin,$ldap_base" \
        --set description="Members of this group can create incoming, one-way trusts to this forest" \
        --set sambaGroupType="2" \
        --set adGroupType="-2147483643" \
        --set sambaRID="557" ||die

    udm groups/group create "$@" --set name="$(custom_groupname "Event Log Readers")" \
        --ignore_exists \
        --position "cn=Builtin,$ldap_base" \
        --set description="Members of this group can read event logs from local machine" \
        --set sambaGroupType="2" \
        --set adGroupType="-2147483643" \
        --set sambaRID="573" ||die

    udm groups/group create "$@" --set name="$(custom_groupname "Group Policy Creator Owners")" \
        --ignore_exists \
        --position "cn=groups,$ldap_base" \
        --set description="Members in this group can modify group policy for the domain" \
        --set sambaGroupType="2" \
        --set adGroupType="-2147483646" \
        --set sambaRID="520" ||die

    udm groups/group create "$@" --set name="$(custom_groupname "Performance Log Users")" \
        --ignore_exists \
        --position "cn=Builtin,$ldap_base" \
        --set description="Members of this group may schedule logging of performance counters, enable trace providers, and collect event traces both locally and via remote access to this computer" \
        --set sambaGroupType="2" \
        --set adGroupType="-2147483643" \
        --set sambaRID="559" ||die

    udm groups/group create "$@" --set name="$(custom_groupname "Administrators")" \
        --ignore_exists \
        --position "cn=Builtin,$ldap_base" \
        --append users="uid=$(custom_username Administrator),cn=users,$ldap_base" \
        --append nestedGroup="cn=$(custom_groupname "Domain Admins"),cn=groups,$ldap_base" \
        --append nestedGroup="cn=$(custom_groupname "Enterprise Admins"),cn=groups,$ldap_base" \
        --set description="Administrators have complete and unrestricted access to the computer/domain" \
        --set sambaGroupType="2" \
        --set adGroupType="-2147483643" \
        --set sambaRID="544" ||die

    udm groups/group create "$@" --set name="$(custom_groupname "Allowed RODC Password Replication Group")" \
        --ignore_exists \
        --position "cn=groups,$ldap_base" \
        --set description="Members in this group can have their passwords replicated to all read-only domain controllers in the domain" \
        --set sambaGroupType="2" \
        --set adGroupType="-2147483644" \
        --set sambaRID="571" ||die

    udm groups/group create "$@" --set name="$(custom_groupname "Users")" \
        --ignore_exists \
        --position "cn=Builtin,$ldap_base" \
        --append nestedGroup="cn=$(custom_groupname "Domain Users"),cn=groups,$ldap_base" \
        --set description="Users are prevented from making accidental or intentional system-wide changes and can run most applications" \
        --set sambaGroupType="2" \
        --set adGroupType="-2147483643" \
        --set sambaRID="545" ||die

    udm groups/group create "$@" --set name="$(custom_groupname "Backup Operators")" \
        --ignore_exists \
        --position "cn=Builtin,$ldap_base" \
        --set description="Backup Operators can override security restrictions for the sole purpose of backing up or restoring files" \
        --set sambaGroupType="2" \
        --set adGroupType="-2147483643" \
        --set sambaRID="551" ||die

    udm groups/group create "$@" --set name="$(custom_groupname "IIS_IUSRS")" \
        --ignore_exists \
        --position "cn=Builtin,$ldap_base" \
        --set description="Built-in group used by Internet Information Services." \
        --set sambaGroupType="2" \
        --set adGroupType="-2147483643" \
        --set sambaRID="568" ||die

    udm groups/group create "$@" --set name="$(custom_groupname "Denied RODC Password Replication Group")" \
        --ignore_exists \
        --position "cn=groups,$ldap_base" \
        --append users="uid=krbtgt,cn=users,$ldap_base" \
        --append nestedGroup="cn=$(custom_groupname "Read-only Domain Controllers"),cn=groups,$ldap_base" \
        --append nestedGroup="cn=$(custom_groupname "Group Policy Creator Owners"),cn=groups,$ldap_base" \
        --append nestedGroup="cn=$(custom_groupname "Domain Admins"),cn=groups,$ldap_base" \
        --append nestedGroup="cn=$(custom_groupname "Cert Publishers"),cn=groups,$ldap_base" \
        --append nestedGroup="cn=$(custom_groupname "Enterprise Admins"),cn=groups,$ldap_base" \
        --append nestedGroup="cn=$(custom_groupname "Schema Admins"),cn=groups,$ldap_base" \
        --append nestedGroup="cn=$(custom_groupname "Domain Controllers"),cn=groups,$ldap_base" \
        --set description="Members in this group cannot have their passwords replicated to any read-only domain controllers in the domain" \
        --set sambaGroupType="2" \
        --set adGroupType="-2147483644" \
        --set sambaRID="572" ||die

    udm groups/group create "$@" --set name="$(custom_groupname "Cryptographic Operators")" \
        --ignore_exists \
        --position "cn=Builtin,$ldap_base" \
        --set description="Members are authorized to perform cryptographic operations." \
        --set sambaGroupType="2" \
        --set adGroupType="-2147483643" \
        --set sambaRID="569" ||die
}

_update_groups ()
{
    users_default_administrator=$(custom_username "Administrator")
    groups_default_domainadmins=$(custom_groupname "Domain Admins")
    groups_default_domainusers=$(custom_groupname "Domain Users")
    groups_default_domainguests=$(custom_groupname "Domain Guests")
    udm groups/group modify "$@" --dn "cn=$groups_default_domainguests,cn=groups,$ldap_base" --set description='All domain guests'
    udm groups/group modify "$@" --dn "cn=$groups_default_domainusers,cn=groups,$ldap_base" --set description='All domain users'
    udm groups/group modify "$@" --dn "cn=$groups_default_domainadmins,cn=groups,$ldap_base" --set description='Designated administrators of the domain'
    udm users/user modify "$@" --dn "uid=$users_default_administrator,cn=users,$ldap_base" --set description='Built-in account for administering the computer/domain'
    udm groups/group modify "$@" --dn "cn=$(custom_groupname "Group Policy Creator Owners"),cn=groups,$ldap_base" --append users="uid=$users_default_administrator,cn=users,$ldap_base"
}

_update_container ()
{
    udm container/cn create "$@" --ignore_exists --set name=System
    udm container/cn modify "$@" --dn "cn=System,$ldap_base" --set description='Builtin system settings'
    udm container/cn create "$@" --ignore_exists --set name='Managed Service Accounts' --set description='Default container for managed service accounts'
    udm container/cn create "$@" --ignore_exists --set name='PSPs' --position "cn=System,$ldap_base"
}


_create_default_s4_groups "$@"
_update_groups "$@"
_update_container "$@"

ucs_addServiceToLocalhost "${NAME}" "$@"

joinscript_save_current_version

exit 0

4. Make the script executable

  • chmod +x /usr/lib/univention-install/96univention-samba4slavepdc.inst

5. Re-run the join script

  • univention-run-join-scripts --run-scripts --force 96univention-samba4slavepdc.inst

Summary

This issue is caused by RID conflicts introduced during an AD takeover with mixed-language group names.
The workaround replaces the failing join script with a modified version that tolerates pre-existing objects.

This approach should only be used as a temporary solution until an official fix is provided.