Domain Join Ubuntu 22.04 - Failed (with updated Join Script)

Thank you for this clarification.

Indeed the speedport was the home router, i was connected when i took the screenshot.

How can i check if the UCS server is configured as DNS?
When log in into the UCS WebGUI → network → external name server I see my server provider’s DNS IP.

However, i also tried the IP Address of the UCS in the UDJA instead of the hostname as well. Therefore the DNS does not need to resolve the hostname or do i miss something? But that aint worked as well.
(I also tried to change the DNS on the client’s network manager to the UCS IP ) .

@pmhahn thank you for your help

How can i check if the UCS server is configured as DNS?

There are 2 DNS settings:

  1. Your UCS systems (Primary, Backup, Replica, Server) have one which is required for the UCS system to resolve external addresses like https://updates.software-univention.de/ er al. On top of that UCS adds data from its own zones, which other UCS systems need to communicate with each other.
  2. Your Ubuntu Clients have one: they should use the UCS systems to resolve IP addresses as only the UCS systems know of your domain; using an (external) DNS server here like your speedport home roter will lead to that resolution not working.

However, i also tried the IP Address of the UCS in the UDJA instead of the hostname as well. Therefore the DNS does not need to resolve the hostname or do i miss something?

Using names instead of plain IP addresses is important as SSL/TLS certificates work with names, not IP addresses (at least in UCS; theoretically you can add IP addresses to certificates, but no-one I know of does that.)
For the join process multiple connections to the Primary are initiated:

  1. an ssh connection to create the machine account on the Primary; that one works well with IP addresses, too.
  2. afterwards LDAP and Kerberos, which AFAIK require a name instead of IP addresses.

But that aint worked as well.

  1. check on the client that nmcli in the section DNS configuration reports your Primary to be used. That auto-detection should work.
  2. otherwise try sudo /usr/sbin/univention-domain-join-cli and specify --dc-ip IP --domain DOMAIN manually.

If 2. works but 1. still does not work, we can continue debugging from there. If you have the tool dig installed please check which of your servers is capable of resolving the SRV record:

dig -p 53 @127.0.0.53 _domaincontroller_master._tcp.codenauten.intranet. srv  # ❓
dig -p 53 @192.168.2.1 _domaincontroller_master._tcp.codenauten.intranet. srv  # ❌
dig -p 53 @IP.of.your.UCS _domaincontroller_master._tcp.codenauten.intranet. srv # ✅

The last one should work definitely, the middle one probably not, the first one is the most interesting one:
NetworkManager and systemd nowadays run a local DNS server on each host: This allows caching but is required to have a more flexible DNS configuration: Traditionally you had your /etc/resolv.conf file where you could name up to 3 DNS servers, all serving the same (public) data. With todays VPNs this is too inflexible as you want to delegate querying some domains to specific other servers and only use the “public” DNS servers for looking up the (public) rest.
What you basically need is to configure NetworkManager to “delegate” codenauten.intranet. to your UCS Primary. You can do this by creating a file like /etc/NetworkManager/dnsmasq.d/ucs.conf with content server=/codenauten.intranet/IP.of.your.UCS and doing a systemctl reload NetworkManager.service.

1 Like

Thank you very much!

With your explanations i started to understand the situation , at lest a bit.

  1. check on the client that nmcli in the section DNS configuration reports your Primary to be used. That auto-detection should work.

It is present in the nmcli.

DNS configuration:
        servers: 89.58.11.173
        domains: codenauten.intranet
        interface: wlp7s0

        servers: fe80::1
        domains: speedport.ip
        interface: wlp7s0

But the UDJA does not work
No DNS record for DC master could be found.

  1. otherwise try sudo /usr/sbin/univention-domain-join-cli and specify --dc-ip IP --domain DOMAIN manually.

It returns, that the UCS master name ucs-1234.codenauten.intranet could not be resolved.

dig -p 53 @127.0.0.53 _domaincontroller_master._tcp.codenauten.intranet. srv  # ❓
dig -p 53 @192.168.2.1 _domaincontroller_master._tcp.codenauten.intranet. srv  # ❌
dig -p 53 @IP.of.your.UCS _domaincontroller_master._tcp.codenauten.intranet. srv # ✅

Surprisingly all of these seem to work. They return a bunch of information’s, which includes my UCS IP and a part which say 1 server found.

I also created a file

/etc/NetworkManager/dnsmasq.d/ucs.con

with the according content and performed the reload, but still the same issue.

PS:
As you already clarified so much things for me, i like to ask you about the different names i came across in UCS.

  • I got domain.intranet
  • I got ucs-1234.domain.intranet
  • I got my external domain sub.domain.tld which has a DNS entry and therefore points to IP of my UCS

Iam a bit confused about all of them, therefore i try all of them whenever iam in despair.

That looks okay to me.

strange; see below for the next step to manually resolve that name to an IP address.

By default the output of dig is very verbose and includes many sections; of interest is only the “ANSWER SECTION” which should have a line like

_domaincontroller_master._tcp.codenauten.intranet. 10800 IN SRV 0 0 0 ucs-1234.codenauten.intranet.

You can reduce the output of dig by inserting a +short just after the command. Of interest here is only that there is such a SRV record and that “fully qualified host name” (FQHN) it points to.

Next would then be to resolve the host-name from the SRV record to an IP address by doing:

dig +short -p 53 @127.0.0.53 ucs-123.codenauten.intranet. any  # ❓
dig +short -p 53 @192.168.2.1 ucs-123.codenauten.intranet. any  # ❌
dig +short -p 53 @IP.of.your.UCS ucs-1234.codenauten.intranet. any # ✅

Again this should return A records for an IPv4 addresses and/or AAAA records for IPv6 addresses.

Nit: I did non check if this is required, but the file suffix should be .conf with an additional f at the end; I goofed up the styling in my previous reply; now fixed.

  • domain.intranet is your domain name: it’s a hierarchical name-space which allows you (and anybody in the world) to group your devices under a common name. If others are supposed to use that name it must be registered at a public registrar, but as long as you use the name only internally you can mostly use any name you like, but make sure to not shadow any public domain like univention.de or github.com.
  • ucs-123.domain.intranet is a FQHN of one of your devices , e.g. your UCS server. It splits into the host-name ucs-123 in the domain named domainname.intranet.
  • sub.domain.tld is yet another name for your UCS server: Any device can have multiple names, e.g. multiple internal and multiple public names. The host does not care if it has multiple names: internally it has a hostname and one or more IP addresses. How they resolve to names is managed by DNS and might also depend on the actual DNS server you ask:
    • Any public DNS server probably knows nothing about domain.intranet and will not be able to resolve a IP address from a private address range like 192.168.2.X to any name.
    • Only your UCS server will know about domain.intranet and will be able to resolve its name ucs-1234.domain.intranet to its IP address 192.168.2.X.

It is perfectly normal for a device to have multiple names, but you have to make sure to communicate the right name to third-parties: If you give them your internal name, it will not work for them.
You also have to do additional work for SSL/TLS certificates as they work with names:

  • for your internal domain domain.intranett UCS will create a custom Certtificate Authority (CA) to be able to create certificates on demand: They are required to setup encrypted LDAP and HTTPS connections for internal communication.
  • for any external domain (sub.domain.tld) you have to get a valid certificate on your own, either by using Let’s encrypt or by getting one from some other accepted CA. This certificate then can be configured for Apache and other public visible servers so that clients can validate them when accessing your server via its public names.
1 Like

Thank you very much once again.

I did all three of them (with my UCS number ofc)
The first two of them does return without any information
The last one returned IP.of.my.UCS

Just in case i also tried the older ones from your post before with the +short

dig +short -p 53 @127.0.0.53 _domaincontroller_master._tcp.codenauten.intranet. srv  # ❓
dig +short -p 53 @192.168.2.1 _domaincontroller_master._tcp.codenauten.intranet. srv  # ❌
dig +short -p 53 @IP.of.your.UCS _domaincontroller_master._tcp.codenauten.intranet. srv # ✅

The first and third command return:
0 0 0 ucs-1234.codenauten.intranet.

Second returns nothing

i already wondern about the .con ending.
I changed it to .conf and restarted the service.
I tried to use the GUI. Nope
I tried to use the CLI. Nope

  • So the domain.intranet is the one i need to use whenever Univention refers to “domain name”?
  • So this one is internal and needed whenever i like to build a bigger/complexer system with multiple Servers (f.e. a Backup server or another Storage server)?
  • Ok, so this one can be used by external user? For example for the nextcloud UCS app(sub.domain.tld/nextcloud). As this propangated by public DNS.
    • I did made a Lets Encrypt certificate at my domain provider. How do i need to integrate this into Apace/UCS in order to be accepted? (At this moment user get the message the page is unsafe [due to the UCS custom certificate], whenever they use either sub.domain.tld or ip)

PS: I really appreciate your support on this issue! :heart:

I goofed up again and missed some 4 in my command; please re-run this again with the fixed name ucs-1234:

dig +short -p 53 @127.0.0.53 ucs-1234.codenauten.intranet. any  # ❓
dig +short -p 53 @192.168.2.1 ucs-1234.codenauten.intranet. any  # ❌
dig +short -p 53 @IP.of.your.UCS ucs-1234.codenauten.intranet. any # ✅

The last one I expected, the first one is also good as this shows me that your locally running DNS service is able to resolve the SRV records. But this contradicts the message from the log-file from above:

2022-11-23 22:18:18,657 userinfo CRITICAL All nameservers failed to answer the query _domaincontroller_master._tcp.codenauten.intranet. IN SRV: Server 127.0.0.53 UDP port 53 answered SERVFAIL

Now I hope that the commands to resolve that name to IP addresses above work the same.

Can you please check the content of /etc/resolv.conf that is contains the line

nameserver 127.0.0.53

It probably is a symbolic link to /run/NetworkManager/resolv.conf which NM auto-generates.

Can you also please run this command:

getent ahosts ucs-1234.codenauten.intranet.

It should also be able to resolve the name into IP addresses. Sadly there are many implementations of the DNS resolution mechanism, which all use the same underlying DNS service, but they all differ in nuances and may return different results. So next also give this a try:

python3 -c 'from dns.resolver import Resolver;r=Resolver();print(r.query("_domaincontroller_master._tcp.codenauten.intranet.","SRV"))'
python3 -c 'from dns.resolver import Resolver;r=Resolver();print(r.query("ucs-1234.codenauten.intranet.","A"))'

You have to copy the filed to your server and configure Apache to use them. See Using your own SSL certificates

FYI: There’s also our Let’s encrypt App in our app-center which you could have used to generate those certificates.

1 Like

i already used the correct ucs-NUMBER.
I just write UCS-1234 instead of my real UCS number as i though that could be somewhat sensitive data like the servers ip which might not flow around public accessible posts.

So its still valid. The last one returns the UCS IP while the rest does not return any information

This just contains 3 lines.

nameserver 127.0.0.53
options edns0 trust-ad
search codenauten.intranet speedport.ip

The speedport is my local router.

Can you also please run this command:

getent ahosts ucs-1234.codenauten.intranet.

I useed this command (with and with out a dot at the end of the line).
I dont get any return message.

Both scripts start with a Deprecation Warning, then run for a short time and throw a dns.exceptiontimeout after 5.4 seconds.

I changed the command according to the Deprecated message from r.query to r.resolve

python3 -c 'from dns.resolver import Resolver;r=Resolver();print(r.resolve("_domaincontroller_master._tcp.codenauten.intranet.","SRV"))'

Still throws an Timeoutexception

python3 -c 'from dns.resolver import Resolver;r=Resolver();print(r.resolve("ucs-1234.codenauten.intranet.","A"))'

But this returns:

dns.resolver.NXDOMAIN: The DNS query name does not exists: ucs-1234.codenauten.intranet.

Thank you so much for your constant support on this!

This is bizarre:

  • dig +short -p 53 @127.0.0.53 _domaincontroller_master._tcp.codenauten.intranet. srv # ❓ works and returns 0 0 0 ucs-1234.codenauten.intranet as expected
  • dig +short -p 53 @127.0.0.53 ucs-1234.codenauten.intranet. any # ❓ does not, which should just resolve that name to an IP address.

Both should go via your local resolver to the same DNS server, which is able to answer those queries as has been proven by querying that server directly.

What currently confuses me is your nmcli output from above:

That mydomain.intranet does not match your later codenauten.intranet. Can you please re-check the output of nmcl.

Also please check /etc/NetworkManager/NetworkManager.conf if in section [main] there is any dns=… setting. Probably not which will tell NM to use either systemd-resolved if

/etc/resolv.conf is a symlink to /run/systemd/resolve/stub-resolv.conf, /run/systemd/resolve/resolv.conf, /lib/systemd/resolv.conf or /usr/lib/systemd/resolv.conf

or NMs own default, which would explain why that /etc/NetworkManager/dnsmasq.d/ucs.conf is not used.

  1. Please check grep -n -e ^\\[ -e ^dns /etc/NetworkManager/NetworkManager.conf
  2. Please check readlink -f /etc/resolv.conf
  3. Please check ps $(pgrep dnsmasq) for any running dnsmasq process (just to be sure it is not used)
  4. Please check ps $(pgrep systemd-resolved) for any running process (to make sure it is running)

As the command resolvectl did work for you I strongly guess that systemd-resolved is used in your case. I have to dig deeper myself first how that beast can be tamed.

1 Like

Iam sorry about this one. I wrote mydonmain.intranet as I liked to obfuscate the original domain name (wasn’t sure if they are somewhat sensitive)
It is indeed codenauten.intranet

No DNS setting here

  1. Returns
1:[main]
4:[ifupdown]
7:[device]
  1. Returns
/run/systemd/resolve/stub-resolv.conf

3&4: both returns two processes running. Ps and bash. However I wasn’t sure about that “for any running process” I just typed the line into the terminal.

:heart:

I tried this, but the system service does not want to restart apache2

An error occurred while connecting to the server, please try again later.

That happens only when pgrep does not find such processes and thus ps was called without any extra argument, in which case it only returns itself and the shell. Please re-run this command instead of 3: ps $(pgrep systemd-resolve) which should print one process (there a limit of 15 characters per “process name”, so the trialing d needs to be stripped.)

For systemd-resolved you have to

  1. create the directory sudo install -o root -g root -m 0755 -d /etc/systemd/resolved.conf.d
  2. Create a file like /etc/systemd/resolved.conf.d/ucs.conf with this content:
[Resolve]
# the IP of your DC Primary goes here:
DNS=192.168.2.X
# your UCS domain name goes here:
Domains=~codenauten.intranet
  1. Restart the daemon: sudo systemctl reload-or-restart systemd-resolved.service

resolvectl should then list the DC Primary with its IP and domain name.
Check again that dig +short _domaincontroller_master._tcp.codenauten.intranet. srv returns a record and dig +short ucs-1234.codenauten.intranet. any is able to resolve the name into an IP address.
Afterwards give univention-domain-join another try: Make sure to enter codenauten.intranet into the field “Domain name or IP address”. (specifying the IP address of your UCS Primary there should also work.)

1 Like

This returns one process the Command /lib/systemd/systemd-resolved

I did as described.
For the DNS in the conf file i used IP.of.your.UCS.
Thats the IP i can use to reach the UCS GUI.

However, it does not work so far but i guess we are a big step further.
The fail message changed:

“The domain join failed: For further informations look at /var/log/univention/domain-join-gui.log”

It seems like something about the LDAP goes bad.
Here is the log from today, i changed the occurrence of the actual server’s IP (which I put into the conf file) to IP.of.your.UCS.

2022-12-07 01:35:34,377 userinfo WARNING Warning: /etc/ldap/ldap.conf already exists.
2022-12-07 01:35:34,379 userinfo WARNING Warning: /etc/sssd/sssd.conf already exists.
2022-12-07 01:35:34,382 userinfo WARNING Warning: /etc/krb5.conf already exists.
2022-12-07 01:35:34,383 userinfo INFO Created a backup of all configuration files, that will be modified at '/var/univention-backup/20221207003534_domain-join'.
2022-12-07 01:35:35,222 userinfo INFO Getting the DN of the Administrator
2022-12-07 01:35:36,739 userinfo INFO Downloading the UCS root certificate to /etc/univention/ssl/ucsCA/CAcert.pem
2022-12-07 01:35:36,790 userinfo INFO Adding the UCS root certificate to the certificate store
2022-12-07 01:35:41,288 userinfo INFO Adding LDAP entry for this machine on the UCS DC
2022-12-07 01:35:42,189 userinfo CRITICAL Adding an LDAP object for this computer didn't work.
2022-12-07 01:35:42,190 userinfo CRITICAL Warning: Permanently added 'IP.of.your.UCS' (ED25519) to the list of known hosts.

2022-12-07 01:35:42,941 userinfo CRITICAL
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/univention_domain_join/join_steps/ldap_configurator.py", line 78, in modify_old_entry_or_add_machine_to_ldap
	udm_type, dn = get_machines_udm(dc_ip, admin_username, admin_pw, admin_dn)
  File "/usr/lib/python3/dist-packages/univention_domain_join/utils/ldap.py", line 77, in get_machines_udm
	raise LookupError(dc_ip)
LookupError: IP.of.your.UCS

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/sbin/univention-domain-join", line 458, in run
	distribution_joiner.join_domain()
  File "/usr/lib/python3/dist-packages/univention_domain_join/distributions/ubuntu.py", line 115, in join_domain
	LdapConfigurator().configure_ldap(self.dc_ip, self.ldap_server_name, self.admin_username, self.admin_pw, self.ldap_base, admin_dn)
  File "/usr/lib/python3/dist-packages/univention_domain_join/join_steps/ldap_configurator.py", line 72, in configure_ldap
	self.modify_old_entry_or_add_machine_to_ldap(password, dc_ip, admin_username, admin_pw, ldap_base, admin_dn)
  File "/usr/lib/python3/dist-packages/univention_domain_join/join_steps/ldap_configurator.py", line 81, in modify_old_entry_or_add_machine_to_ldap
	dn = self.add_machine_to_ldap(password, dc_ip, admin_username, admin_pw, ldap_base, admin_dn)
  File "/usr/lib/python3/dist-packages/univention_domain_join/join_steps/ldap_configurator.py", line 133, in add_machine_to_ldap
	raise LdapConfigutationException()
univention_domain_join.join_steps.ldap_configurator.LdapConfigutationException

I’ve got the feeling that we are about to close this case :mag_right:
A million thanks for your support :tada:

The corresponding function that raises the error seems to be this one.

@pmhahn do you got any idea what i could check?
If necessary i could try to get the source files, set breakpoints on the specific lines, and post the variable values.
Somehow the ssh process on the server seems to fail.

Sorry for the delay, but other tasks kept me busy.

The code tries to add a machine account by running udm on your Primary. Your logfile /var/log/univention/domain-join-gui.log or /var/log/univention/domain-join-cli.log should contain the error message, (which should also have been printed to your console if you are using the CLI version.)

If you want to debug this yourself put a breakpoint() before line 128 and print out the command which gets executed: p udm_command
You can then login to the Primary yourself and run it there; bear in mind that you replace the argument after --bindpwfile to point to some other file which contains your admin password.

1 Like

I totally understand if you need to take care of other tasks as well.
Iam very happy about any time you can spend to help me to get this done.
Its strange since its a complete fresh installation of ubuntu. I literally just installed ubuntu, downloaded the domain join script thats it.

Well, I used the gui to join and already posted the log file above at post number 16.
Thats how i came across these functions, but i dont get how to dig further.
executing the command from line 128 on primary wont do the trick? Otherwise the script wouldnt fail?
Do i oversee something?

UDJ builds a command to join your Ubuntu client to your domain, which is then executed on your Primary. This is done via ssh for which it needs the address of your Primary and your Administrator credentials to do the login. The later thing we have now solved, but the command the fails for some reason. I need to see that error message to figure out, what goes wrong and why that might happen in your environment.

The command with is executed is built in line 119-126 which is something like this:

/usr/sbin/udm computers/ubuntu create \
--binddn cn=Administrator,cn=users,dc=codenauten,dc=intranet \
--bindpwdfile /SOME/PATH \
--position cn=computers,dc=codenauten,dc=intranet \
--set name=HOSTNAME \
--set password=PASSWORD \
--set operatingSystem=Ubuntu \
--set operatingSystemVersion=22.04

It can fail for multiple reasons:

  • wrong admin credentials
  • missing UDM module
  • LDAP errors
  • type error
  • password policy complexity issue

The error message from that specific udm command hopefully will tell us the exact problem. Its output should be in the log files named above near the end if you search for Adding an LDAP object for this computer didn't work.
If you don’t find that message you could just login to your Primary itself and then execute the command there by hand, which should then show the same error. If you later on run UDJ again it should detect that the machine account already exists and should try to modify that already existing entry.

1 Like

Thank you so much for your constant support.

Which log file is needed? On the primary or the client?

The clients var/log/univention/domain-join-gui.log is posted above.

Does the primary has any log file for domain join fails

/var/log/univention/domain-join-gui.log or /var/log/univention/domain-join-cli.log from the client — the Ubuntu host where UDJ is executed.

Not for UDJ — for joining other UCS server roles /usr/share/univention-join/univention-server-join would log to ~Administrator/.univention-server-join.log.
For UDJ the failing command should be logged in the UDJ log files named above.

@pmhahn

this was the /var/log/univention/domain-join-gui.log file from the client as i used the GUI.

PS:

Just for the forum post to obfuscate my servers actual IP.
It is the same IP as in the DNS config file

Mastodon