Thursday, May 25, 2023

Migrating an openldap database to a new installation

If you are familiar with Openldap you may have become frustrated with the difficulty of migrating a database from one installation to a fresh instance of Openldap. There is an easy way to do this, using a combination of slapcat and slapadd. The only drawback is that it destroys the database at the destination. However, this is usually a new copy of Openldap, so it doesn't matter.

Ldap is a tree

It is important to realise that an ldap database is a tree. That is, there is only one node at the root, and every descendant node must have only one parent. When you install Openldap the tree consists of one node called "nodomain", which, if not destroyed, will likely conflict with anything you import. What you really want is for the root to consist of a "suffix" of your choice, such as, which ldap breaks down to dc=mycompany,dc=com.

Exporting your ldap tree

On your old Openldap installation you must first export the data. For this I recommend you use slapcat:

slapcat [-b suffix] -l output.ldif

You can specify a suffix, which will then export only that portion of the tree. This is useful when your old installation contains a sub-tree you want installed in standalone form on the new instance of Openldap. Or just omit it, and the entire tree will be exported to the file export.ldif.

Importing the exported tree to a new Openldap instance

slapadd is a simple utility that copies the exported database into an empty database. I provide here a script for doing this. Notice that it first deletes the old database (the one defining "nodomain" as the root) to avoid conflicts. To do this it must first stop the slapd service and restart it again afterwards.

If you install ldap-account-manager (in Debian/Ubuntu) you can see the tree it creates in Tools->Tree view, which should be identical to the one you exported.

Wednesday, May 24, 2023

Adding SSL/TLS certificates to Openldap on localhost using Ubuntu Linux 22.04.2

I wanted to install ssl/tls certificates on my openldap installation that I had running on localhost as a demo, but the information I found on the Web was mostly out of date. Another approach is to use letsencrypt, but that is for registered domain names and won't work with localhost, so I will be using self-signed certificates in this post.


You will need to have installed openldap and openssl. If you haven't then do so now:

sudo apt install openssl slapd

Create a certificate authority (CA) to sign your certificates

There is a script in openssl for doing this. Nowadays it is called I found it in /usr/lib/ssl/misc/, but it might be somewhere else on your machine. You can find it with:

sudo find / -name

Once you have the path to it, create a directory to hold the CA. I created one in /var/myca:

sudo mkdir -p /var/myca
cd /var/myca
Now invoke the script:

sudo /usr/lib/ssl/misc/ -newca

When it prompts for a certifcate filename just hit return. It will ask you some certificate type questions, including a passphrase. Give it something simple so you can remember it. (Remember this is just for testing. On production you'll need a secure passphrase.) It will create a directory called demoCA inside /var/myca.

Create a certificate for openldap using the CA

sudo   openssl req -new -nodes -keyout newreq.pem -out newreq.pem

Again, you have to answer all the tedious certificate questions. When it has finished you should have newreq.pem in the /var/myca directory. Now sign the request:

sudo /usr/lib/ssl/misc/ -sign

This creates newcert.pem

Copy the certificates and key to where openldap can find them

Create a directory to hold them for openldap. I chose /etc/openldap/certs. Create it if it is not there:

sudo mkdir -p /etc/openldap/certs

Now copy the certificates over:

cd /etc/openldap/certs
sudo cp /var/myca/demoCA/cacert.pem .
sudo mv /var/myca/newcert.pem servercrt.pem
sudo mv /var/myca/newreq.pem serverkey.pem
sudo chmod 600 serverkey.pem 
sudo chown openldap:openldap *
ls -l

This produces:

-rw-r--r-- 1 openldap openldap 4730 May 25 11:49 cacert.pem
-rw-r--r-- 1 openldap openldap 4751 May 25 11:50 servercrt.pem
-rw------- 1 openldap openldap 2843 May 25 10:22 serverkey.pem

Allow Openldap to read this directory

Nowadays Openldap is controlled by apparmor, which restricts which directories openldap, aka slapd, can access. So we have to tell it about this new directory of certificates we just created. In /etc/apparmor.d you should find a file called usr.sbin.slapd, which is divided into sections, one of which is called "# ldap files". After that are a couple of lines. Add this line in bold using your favourite editor to tell it about all the files in /etc/openldap/certs:

  # ldap files
  /etc/ldap/** kr,
  /etc/ldap/slapd.d/** rw,
  /etc/openldap/certs/* r,

Now restart slapd to get it to see the directory:

sudo systemctl restart slapd

Update the openldap config to point to the certificates and key

Create a file add_ssl.ldif using nano or vi, with this content:

dn: cn=config
changetype: modify
replace: olcTLSCACertificateFile
olcTLSCACertificateFile: /etc/openldap/certs/cacert.pem
replace: olcTLSCertificateKeyFile
olcTLSCertificateKeyFile: /etc/openldap/certs/serverkey.pem
replace: olcTLSCertificateFile
olcTLSCertificateFile: /etc/openldap/certs/servercrt.pem

Now load it:

sudo ldapmodify -Q -Y EXTERNAL -H ldapi:/// -f add_ssl.ldif -W

It will respond with:

[sudo] password for username: 
Enter LDAP Password: 
modifying entry "cn=config"

If it says:

ldap_modify: Other (e.g., implementation specific) error (80)

check in the last lines of syslog (tail /var/log/syslog) to see if apparmor is denying access. If so, check your steps in "Allow Openldap to read this directory" above.

Tell Openldap where the CA certificate is

Edit /etc/ldap/ldap.conf and set the variable TLS_CACERT to /etc/openldap/certs/cacert.pem, then restart slapd:

sudo systemctl restart slapd

Your Openldap installation should now be ready to use SSL!

Monday, February 13, 2023

Ubuntu 22.04.1 on Lenovo Thinkpad P14s (Ryzen R7 Pro 6850U)

I was a bit nervous about this as the Canonical site says that the latest version of Ubuntu may not run on the Thinkpad P14s:

Pre-installed in some regions with a custom Ubuntu image that takes advantage of the system’s hardware features and may include additional software. Standard images of Ubuntu may not work well, or at all.

Indeed, on booting up the laptop is indeed has a custom kernel 5.14.0-1047-oem and Ubuntu 20.04 (Focal Fossal). But I was determined to upgrade to 22.04. After upgrading the hard drive to 2TB PCIe 4.0 I noticed that in this model (21J5) there are NO slots for memory expansion. So you're stuck with the soldered 32GB it comes with. However, the installation went smoothly. I chose "Install 3rd party software for graphics and wifi". After installation I rebooted and tested wifi, sleep, suspend, closing the lid and connecting to a dock with two screens, keyboard and mouse. Also tested the function keys. All was fine. So I'd recommend this model for those of us who want a Linux laptop and don't want to pay the Microsoft tax.

Sunday, May 1, 2022

Ubuntu 22.04: Gdk-CRITICAL **... gdk_wayland_window_set_dbus_properties_libgtk_only: assertion 'GDK_IS_WAYLAND_WINDOW (window)' failed

I encountered this error when running the soffice commandline interface under Jammy Jellyfish (Ubuntu 22.04). Since there wasn't any window being generated I was puzzled. A little searching revealed that the library libgdk3.0-cil (CLI binding for GDK 3) was not installed, and so running:

sudo apt install libgdk3.0-cil

solved the problem.

Wednesday, March 23, 2022

Create a bootable .iso from a folder in Linux

If you have ever tried to modify a Linux installer you will know that you must mount the .iso file:

sudo mkdir /mnt/ubuntu
sudo mount -o loop ubuntu-xxx.iso /mnt/ubuntu

then copy it to another directory:

sudo cp -ra /mnt/ubuntu ~/ubuntu

because you can only mount it read-only. Then you can make your modifications to the files in the copied folder. In my case I provided a default value for the keyboard (US) to see if the installer would skip asking me for the setting. Then the bootable .iso must be recreated from the modified folder. But how to do it? I used xorriso:

sudo xorriso -as mkisofs \
   -J -R -V 'UNUNTU-20.04 [CUSTOM]' \
   -o ubuntu-20.04.custom.iso \
   -J -joliet-long -cache-inodes \
   -isohybrid-mbr isohdpfx.bin \
   -b isolinux/isolinux.bin \
   -c isolinux/ \
   -boot-load-size 4 -boot-info-table -no-emul-boot \
   -eltorito-alt-boot \
   -e boot/grub/efi.img \
   -no-emul-boot -isohybrid-gpt-basdat -isohybrid-apm-hfsplus \

Note the use of the file isohdpfx.bin. I couldn't locate this in the Ubuntu distribution so I just copied the first 432 bytes of the existing Ubuntu .iso installer and saved it using hexedit. Without this it will fail to mount and hence won't be bootable. Now make an installable USB out of the .iso using a tool like Startup Disk Creator or Balena Etcher and it will boot happily from it.

Monday, October 25, 2021

Puppeteer page waitForSelector and visible:true option won't process click

I had a problem in Puppeteer where an initially hidden menu has to be invoked by clicking on the menu icon. I used await page.waitForSelector(selector) and then called, where 'selector' is a css selector and page is my page object in Puppeteer. Nothing happened. I figured that as the page had just loaded the menu icon might have been in the DOM but not yet visible. So I tried adding the visible:true option: page.waitForSelector(selector,{visible:true}). Again nothing happened. Then I added a short delay before via page.waitForTimeout(2000) and it worked. But that's like a hack. I mean how long do you wait? So I figured that the menu icon is visible but the click-handler for it is not yet loaded, and waiting ensures that it usually is. But how to do it correctly? Then I tried this:

await page.waitForSelector(selector);
await page.$eval(selector, elem =>;

And it worked.

Wednesday, September 1, 2021

Cure for crashing iPhone

My iPhone kept crashing. If I left it on overnight it would invariably crash by morning and drain the battery in the process. I tried all the cures suggested on the Internet, including wiping the phone and reinstalling everything from scratch. That worked for a while then it started crashing again. I tried shutting it down overnight, but it still crashed the same. So then I tried shutting it down AND wrapping it in aluminium foil. And hey presto -- it woke up the next morning and the battery was fine. So this tells me that there is some communication going on between even a 'shut down' iPhone and the service provider, since radio waves can't penetrate alfoil. Also that there is some kind of broken connection that it tries to re-establish overnight that fails repeatedly until it runs out of power. Miraculously, the foil also stopped it crashing -- for a while. So those broken connections appear to be marked as 'stale' and it doesn't try to remake them, though eventually new ones appear. So if you have the same problem it can't hurt to try the same remedy that worked for me -- shutting it down overnight and wrapping it in alfoil. It's a lot easier than reinstalling the software.