<?xml version="1.0"?>
<rss version="2.0">
   <channel>
      <title>Hugot Blog</title>
      <link>https://hugot.nl/blog.html</link>
      <description>Hugo's personal blog</description>
      <language>en-us</language>
      <pubDate>Wed, 03 Dec 2025 08:30:02 +0000</pubDate>
      <lastBuildDate>Wed, 03 Dec 2025 08:30:02 +0000</lastBuildDate>
      <docs>http://blogs.law.harvard.edu/tech/rss</docs>
      <generator>Hugo's Custom Bash Script</generator>
      <managingEditor>social@hugot.nl (Hugot)</managingEditor>
      <webMaster>infra@hugot.nl (Hugot Infra)</webMaster>
<item><title> [docs] Notities Over OpenLDAP </title><link>https://hugot.nl/posts/notes-on-openldap/index.html</link><description>&lt;h1&gt;[docs] Notities Over OpenLDAP&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;Dit zijn mijn notities over OpenLDAP. Deze notities dienen een dubbele functie: ze zijn een referentie voor mezelf bij het leren over OpenLDAP, EN ik hoop anderen er ook wat aan hebben in hun eigen leerproces. Houd er rekening mee dat ik werk vanuit het perspectief van een Software Engineer, niet een certified LDAPer, of hoe zoiets ook mag heten in het vakgebied ;).&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Ondanks het feit dat LDAP vaak gebruikt wordt voor authenticatie doeleinden, is het eigenijk gewoon een database die geoptimaliseerd is voor lezen. Bij het lezen van artikelen over LDAP voelt het vaak alsof je in een ongeloofelijk complexe wereld terecht bent gekomen waarin je met domeinspecifieke termen voor enterprise sysadmins om de oren wordt geslagen. Als je geen interesse hebt in active directory functionaliteiten binnen een traditioneel netwerk van linux systemen, dan hoef je je over een heleboel van deze termen niet zoveel zorgen te maken.&lt;/p&gt;

&lt;h2&gt;LDAP als database voor gebruikersaccounts&lt;/h2&gt;

&lt;p&gt;De rest van deze notities gaan over het gebruiken van LDAP als een database voor gebruikersaccounts, waar applicaties net als met een RDBMS verbinding mee kunnen maken voor de opslag en het ophalen van data. We behandelen onder andere het opzetten van OpenLDAP, het opzetten van replicatie tussen OpenLDAP instanties en het instellen van een applicatie, authelia, om van het cluster gebruik te maken.&lt;/p&gt;

&lt;h2&gt;LDAP Termen&lt;/h2&gt;

&lt;p&gt;Hieronder volgen een paar LDAP-specifieke termen.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;DN&lt;/strong&gt;: Distinguished Name&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CN&lt;/strong&gt;: Common Name&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;DC&lt;/strong&gt;: Domain Component&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;DIT&lt;/strong&gt;: Directory Information Tree&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Een &lt;strong&gt;Domain Component&lt;/strong&gt; is een component van een domein, meestal is dit een DNS domein van een organisatie of applicatie. De componenten van een DNS domein worden begrensd door een punt (.). Dus het domein example.com heeft de componenten &amp;ldquo;example&amp;rdquo; en &amp;ldquo;com&amp;rdquo;. Een &lt;strong&gt;Common Name&lt;/strong&gt; verschilt van een &lt;strong&gt;Domain Component&lt;/strong&gt; in de zin dat het een generale naam is die niet met domeinen te maken heeft. Een &lt;strong&gt;Distinguished Name&lt;/strong&gt; is de unieke naam van een ldap record, bestaande uit de opstapeling van Common Names, Domain Components en andere attributen waarop een record geselecteerd kunnen worden. Stel we willen de gebruiker met de uid &amp;ldquo;jan&amp;rdquo; opzoeken in een LDAP database van de organisatie example.com, dan is de &lt;strong&gt;Distinguished Name&lt;/strong&gt; dus &lt;code&gt;uid=jan,dc=example,dc=com&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;Opzetten OpenLDAP&lt;/h2&gt;

&lt;p&gt;Installeer openldap met het commando &lt;code&gt;apt install slapd ldap-utils&lt;/code&gt;. Configureer vervolgens de basis met het commando &lt;code&gt;dpkg-reconfigure slapd&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Configuratie basis tonen: &lt;code&gt;ldapsearch -Q -LLL -Y EXTERNAL -H ldapi:/// -b cn=config dn&lt;/code&gt; (alleen vanaf root gebruiker). Dit is een speciale ldap directory waarin de configuratie van de server zelf is vastgelegd en gewijzigd kan worden.&lt;/p&gt;

&lt;p&gt;Directory Information Tree (DIT) tonen: &lt;code&gt;ldapsearch -x -LLL -H ldapi:/// -b dc=example,dc=com dn&lt;/code&gt; (verander domein waar nodig). Dit is de hoofd directory van de ldap server.&lt;/p&gt;

&lt;h2&gt;Schema&amp;rsquo;s&lt;/h2&gt;

&lt;p&gt;Schema&amp;rsquo;s bepalen, net als mysql table definities, de types van de objecten die in een directory kunnen worden opgeslagen. Bij OpenLDAP worden standaard een aantal schema&amp;rsquo;s geleverd, maar deze zijn erg uitgebreid en complex, zeker voor gebruikersaccounts van een doorsnee website. Daarom gaan we ons eigen schema maken voor een gebruikerstype met alleen de attributen die we nodig hebben.&lt;/p&gt;
&lt;div class=&quot;code-sample&quot;&gt;&lt;pre&gt;objectclass ( 1.3.6.1.4.1.54392.5.1632.1&lt;/pre&gt;&lt;pre&gt;    NAME &amp;#39;com-example-Person&amp;#39;&lt;/pre&gt;&lt;pre&gt;    DESC &amp;#39;A person affiliated with example.com.&amp;#39;&lt;/pre&gt;&lt;pre&gt;    STRUCTURAL&lt;/pre&gt;&lt;pre&gt;    MUST ( uid $ userPassword $ displayName $ mail )&lt;/pre&gt;&lt;pre&gt;    )&lt;/pre&gt;&lt;pre&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;aside&gt;
**Private Enterprise Number / OID**
Het lange nummer aan het begin van de definitie van de objectclass is een OID. Hiervoor heb je een OID namespace nodig, die een &quot;Private Enterprise Number&quot; wordt genoemd en welke je aan kunt vragen via de IANA. PEN aanvragen worden door mensen beoordeeld en toegekend, dus het kan even duren voordat je aan de beurt bent. Het is een beetje een overgecompliceerd en bureaucratisch systeem waarvan de voordelen mij niet helemaal duidelijk zijn, maar het is nou eenmaal onderdeel van de RFC.

Als je geen zin hebt om te wachten op een toekenning van de IANA, dan is er deze website voor verkrijgen van OID zonder menselijke handeling: https://freeoid.pythonanywhere.com/ . Hier krijg je een sub-OID van een PEN die de IANA aan de maker van de website heeft toegekend.
&lt;/aside&gt;

&lt;h2&gt;Schema toevoegen&lt;/h2&gt;

&lt;p&gt;Om het nieuwe schema te gebruiken moeten we de configuratie van de LDAP server aanpassen. Bij oudere versies van OpenLDAP deed je dit door /etc/slapd.conf aan te passen, maar bij meer eigentijdse versies maak je hiervoor gebruik van de speciale configuratie directory binnen de LDAP server, cn=config genoemd.&lt;/p&gt;

&lt;p&gt;Deze directory wijzig je net zoals je andere LDAP directories zou wijzigen, namelijk door middel van een ldif (LDAP Data Interchange Format) bestand. Dit is een bestand met omschrijvingen van records die aan een LDAP directory moeten worden toegevoegd. Een beetje zoals een .sql bestand met INSERT queries. Om een ldif bestand te maken van ons schema kunnen we de volgende commando&amp;rsquo;s uitvoeren:&lt;/p&gt;
&lt;div class=&quot;code-sample&quot;&gt;&lt;pre&gt;tmpdir=&amp;#34;$(mktemp -d)&amp;#34;&lt;/pre&gt;&lt;pre&gt;&lt;/pre&gt;&lt;pre&gt;tee &amp;gt; schemas.conf &amp;lt;&amp;lt;EOF&lt;/pre&gt;&lt;pre&gt;include /etc/ldap/schema/core.schema&lt;/pre&gt;&lt;pre&gt;include /etc/ldap/schema/cosine.schema&lt;/pre&gt;&lt;pre&gt;include /etc/ldap/schema/inetorgperson.schema&lt;/pre&gt;&lt;pre&gt;include /etc/ldap/schema/openldap.schema&lt;/pre&gt;&lt;pre&gt;&lt;/pre&gt;&lt;pre&gt;include /pad/naar/ons/schema.schema (WIJZIGEN)&lt;/pre&gt;&lt;pre&gt;EOF&lt;/pre&gt;&lt;pre&gt;&lt;/pre&gt;&lt;pre&gt;slaptest -f ./schemas.conf -F &amp;#34;$tmpdir&amp;#34;&lt;/pre&gt;&lt;pre&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;aside&gt;
De include regels in het &quot;schemas.conf&quot; bestand dat hier gemaakt wordt laden datatypes in die met openldap meegeleverd worden. Als je andere/meer datatypes gebruikt dan in het voorbeeld, dan kan het zijn dat je andere bestanden moet includeren waar die types in gedefinieerd zijn.
&lt;/aside&gt;

&lt;p&gt;Dit commando maakt een representatie van een nieuwe cn=config directory in een mappenstructuur met ldif bestanden in een tijdelijke map. Bekijk de ldif bestanden van de geincludeerde schema&amp;rsquo;s zo:&lt;/p&gt;
&lt;div class=&quot;code-sample&quot;&gt;&lt;pre&gt;cd &amp;#34;$tmpdir/cn=config/cn=schema&amp;#34;&lt;/pre&gt;&lt;pre&gt;ls&lt;/pre&gt;&lt;pre&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Open het ldif bestand dat bij jouw schema hoort. Het heeft dezelfde naam als je aan het schema hebt gegeven, met een cn={x} prefix. Het zou ongeveer de volgende inhoud moeten hebben:&lt;/p&gt;
&lt;div class=&quot;code-sample&quot;&gt;&lt;pre&gt;# AUTO-GENERATED FILE - DO NOT EDIT!! Use ldapmodify.&lt;/pre&gt;&lt;pre&gt;# CRC32 eceebaf6&lt;/pre&gt;&lt;pre&gt;dn: cn={1}example-com&lt;/pre&gt;&lt;pre&gt;objectClass: olcSchemaConfig&lt;/pre&gt;&lt;pre&gt;cn: {1}example-com&lt;/pre&gt;&lt;pre&gt;olcObjectClasses: {0}( 1.3.6.1.4.1.54392.5.1632.1 NAME com-example-Person&amp;#39; DESC &lt;/pre&gt;&lt;pre&gt; &amp;#39;A person affiliated with example.com.&amp;#39; STRUCTURAL MUST ( uid $ userPassword $ displayName $ mail ) )&lt;/pre&gt;&lt;pre&gt;structuralObjectClass: olcSchemaConfig&lt;/pre&gt;&lt;pre&gt;entryUUID: 112d022e-5cd9-103d-8da4-6b43adf243c1&lt;/pre&gt;&lt;pre&gt;creatorsName: cn=config&lt;/pre&gt;&lt;pre&gt;createTimestamp: 20230322084122Z&lt;/pre&gt;&lt;pre&gt;entryCSN: 20230322084122.015156Z#000000#000#000000&lt;/pre&gt;&lt;pre&gt;modifiersName: cn=config&lt;/pre&gt;&lt;pre&gt;modifyTimestamp: 20230322084122Z&lt;/pre&gt;&lt;pre&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Wijzig dit zodat het er als volgt uitziet:&lt;/p&gt;
&lt;div class=&quot;code-sample&quot;&gt;&lt;pre&gt;dn: cn=example-com,cn=schema,cn=config&lt;/pre&gt;&lt;pre&gt;objectClass: olcSchemaConfig&lt;/pre&gt;&lt;pre&gt;cn: example-com&lt;/pre&gt;&lt;pre&gt;olcObjectClasses: {0}( 1.3.6.1.4.1.54392.5.1632.1 NAME com-example-Person&amp;#39; DESC &lt;/pre&gt;&lt;pre&gt; &amp;#39;A person affiliated with example.com.&amp;#39; STRUCTURAL MUST ( uid $ userPassword $ displayName $ mail ) )&lt;/pre&gt;&lt;pre&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Dit schema kun je nu aan je configuratie toevoegen door middal van het &lt;code&gt;ldapadd&lt;/code&gt; commando: &lt;code&gt;ldapadd -Q -Y EXTERNAL -H ldapi:/// -f /pad/naar/schema.ldif&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;Records (Gebruikers) Toevoegen&lt;/h2&gt;

&lt;p&gt;Voor het toevoegen van een gebruiker hebben we ook weer een ldif bestand nodig, dit keer voor het aanpassen van de feitelijke DIT van het root domein dat we hebben ingesteld bij de installatie van openldap.&lt;/p&gt;
&lt;div class=&quot;code-sample&quot;&gt;&lt;pre&gt;dn: uid=hugo,dc=example,dc=com&lt;/pre&gt;&lt;pre&gt;objectClass: com-example-Person&lt;/pre&gt;&lt;pre&gt;displayName: Hugo&lt;/pre&gt;&lt;pre&gt;userPassword: {SSHA}REDACTED&lt;/pre&gt;&lt;pre&gt;mail: hugo@example.com&lt;/pre&gt;&lt;pre&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Het &lt;code&gt;userPassword&lt;/code&gt; veld kun je genereren met het &lt;code&gt;slappasswd&lt;/code&gt; commando:&lt;/p&gt;
&lt;div class=&quot;code-sample&quot;&gt;&lt;pre&gt;slappasswd -h {SSHA} -s &amp;#34;$(read -rsp &amp;#39;Password: &amp;#39; password; echo &amp;#34;$password&amp;#34;)&amp;#34;&lt;/pre&gt;&lt;pre&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;ldif toepassen op database: &lt;code&gt;ldapadd -D cn=admin,dc=example,dc=com -W -x -H ldapi:/// -f ./adduser.ldif&lt;/code&gt;&lt;/p&gt;

&lt;aside&gt;ldapadd is een alias voor `ldapmodify -a`&lt;/aside&gt;

&lt;h2&gt;Records Wijzigen&lt;/h2&gt;
&lt;div class=&quot;code-sample&quot;&gt;&lt;pre&gt;dn: uid=hugo,dc=example,dc=com&lt;/pre&gt;&lt;pre&gt;replace: mail&lt;/pre&gt;&lt;pre&gt;mail: hugo-newmail@maildomain.example.com&lt;/pre&gt;&lt;pre&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;ldif met wijziging toepassen: &lt;code&gt;ldapmodify -D cn=admin,dc=example,dc=com -W -x -H ldapi:/// -f ./modifymail.ldif&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;Records Verwijderen&lt;/h2&gt;
&lt;div class=&quot;code-sample&quot;&gt;&lt;pre&gt;dn: uid=hugo,dc=example,dc=com&lt;/pre&gt;&lt;pre&gt;changetype: delete&lt;/pre&gt;&lt;pre&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Records (Gebruikers) Groeperen&lt;/h2&gt;

&lt;p&gt;Het groeperen van gebruikers kan met het groupOfNames datatype.&lt;/p&gt;
&lt;div class=&quot;code-sample&quot;&gt;&lt;pre&gt;dn: cn=superusers,dc=example,dc=com&lt;/pre&gt;&lt;pre&gt;objectClass: groupOfNames&lt;/pre&gt;&lt;pre&gt;cn: superusers&lt;/pre&gt;&lt;pre&gt;description: Administrators and people who found an exploit in our code.&lt;/pre&gt;&lt;pre&gt;member: uid=hugo,dc=example,dc=com&lt;/pre&gt;&lt;pre&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Gebruiker Toevoegen&lt;/h3&gt;
&lt;div class=&quot;code-sample&quot;&gt;&lt;pre&gt;dn: cn=superusers,dc=example,dc=com&lt;/pre&gt;&lt;pre&gt;changetype: modify&lt;/pre&gt;&lt;pre&gt;add: member&lt;/pre&gt;&lt;pre&gt;member: uid=hugo,dc=example,dc=com&lt;/pre&gt;&lt;pre&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Gebruiker Verwijderen&lt;/h3&gt;
&lt;div class=&quot;code-sample&quot;&gt;&lt;pre&gt;dn: cn=superusers,dc=example,dc=com&lt;/pre&gt;&lt;pre&gt;changetype: modify&lt;/pre&gt;&lt;pre&gt;delete: member&lt;/pre&gt;&lt;pre&gt;member: uid=hugo,dc=example,dc=com&lt;/pre&gt;&lt;pre&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Replicatie&lt;/h2&gt;

&lt;p&gt;Voor replicatie zie
&lt;a href=&quot;https://ubuntu.com/server/docs/service-ldap-replication&quot;&gt;deze&lt;/a&gt; pagina van de ubuntu documentatie. Er is verder ook documentatie op de openldap website.&lt;/p&gt;

&lt;h2&gt;SSL/TLS&lt;/h2&gt;

&lt;p&gt;Het instellen en gebruiken van TLS met openldap is dan misschien onnodig ingewikkeld, maar het is wel nodig voor de beveiligde verbinding van applicaties met de LDAP server.&lt;/p&gt;

&lt;p&gt;In het kort: je hebt een root CA nodig, er is genoeg documentatie over hoe deze te produceren met openssl. Verder heb je een cert en een private key nodig. Om hier vervolgens gebruik van te maken moeten we een aantal waardes in onze &lt;code&gt;cn=config&lt;/code&gt; directory aanpassen en een waarde aanpassen in het /etc/default/slapd configuratiebestand. Daarna &lt;strong&gt;is het nodig om slapd opnieuw op te starten&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;Aanpassingen cn=config&lt;/h3&gt;
&lt;div class=&quot;code-sample&quot;&gt;&lt;pre&gt;dn: cn=config&lt;/pre&gt;&lt;pre&gt;changetype: modify&lt;/pre&gt;&lt;pre&gt;add: olcTLSCertificateKeyFile&lt;/pre&gt;&lt;pre&gt;olcTLSCertificateKeyFile: /etc/ldap/ssl/privkey.pem&lt;/pre&gt;&lt;pre&gt;-&lt;/pre&gt;&lt;pre&gt;add: olcTLSCACertificateFile&lt;/pre&gt;&lt;pre&gt;olcTLSCACertificateFile: /etc/ldap/ssl/my-root.ca&lt;/pre&gt;&lt;pre&gt;-&lt;/pre&gt;&lt;pre&gt;add: olcTLSCertificateFile&lt;/pre&gt;&lt;pre&gt;olcTLSCertificateFile: /etc/ldap/ssl/pubkey.crt&lt;/pre&gt;&lt;pre&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Aanpassing /etc/default/slapd&lt;/h3&gt;

&lt;p&gt;Pas het bestand /etc/default/slapd de waarde van SLAPD_SERVICES aan zodat deze ldaps:/// includeert:&lt;/p&gt;
&lt;div class=&quot;code-sample&quot;&gt;&lt;pre&gt;SLAPD_SERVICES=&amp;#34;ldap:/// ldapi:/// ldaps:///&amp;#34;&lt;/pre&gt;&lt;pre&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Clients Gebruiken met TLS&lt;/h3&gt;

&lt;p&gt;Met StartTLS:&lt;/p&gt;
&lt;div class=&quot;code-sample&quot;&gt;&lt;pre&gt;LDAPTLS_REQCERT=allow ldapsearch -ZZ -x -LLL -H ldap://ldap.example.com -D cn=admin,dc=example,dc=com -W -b dc=example,dc=com&lt;/pre&gt;&lt;pre&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Of direct met TLS (via ldaps://):&lt;/p&gt;
&lt;div class=&quot;code-sample&quot;&gt;&lt;pre&gt;LDAPTLS_REQCERT=allow ldapsearch -x -LLL -H ldaps://ldap.example.com -D cn=admin,dc=example,dc=com -W -b dc=example,dc=com&lt;/pre&gt;&lt;pre&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Authenticatie&lt;/h2&gt;

&lt;p&gt;De bind-DN &lt;code&gt;cn=admin,dc=example,dc=com&lt;/code&gt; kan gebruikt worden voor alle mogelijke wijzigingen. Maar voor het gebruik van de ldap server met andere applicaties zoals authelia, is het toch wel fijn om apparte inlog gegevens aan te maken.&lt;/p&gt;

&lt;p&gt;Een bind-DN is eigenlijk niets anders dan een object in de directory tree. Alles dat het attribuut &lt;code&gt;userPassword&lt;/code&gt; heeft kan gebruikt worden als bind-DN. Je directory structuur kun je zo gek maken als je zelf wil.&lt;/p&gt;

&lt;p&gt;Welke rechten een willekeurige bind-DN over de directory tree krijgt, kan ingesteld worden via access regels in de cn=config database. In de &lt;a href=&quot;&quot;&gt;openldap documentatie&lt;/a&gt; en in &lt;code&gt;man slapd.access&lt;/code&gt; wordt het opstellen van deze regels uitgelegd. Het is sowieso wel aan te raden om andere access regels in te stellen dan de standaard, want zonder aanpassingen geeft openldap alles en iedereen zonder authenticatie lees-rechten.&lt;/p&gt;

&lt;h3&gt;Voorbeeld: &amp;ldquo;o=access&amp;rdquo;&lt;/h3&gt;

&lt;p&gt;Omdat OpenLDAP veel vrijheid biedt in de structuur van onze directory, en in manieren om rechten van bind-DNs vast te leggen, is het makkelijk om dingen ingewikkelder te maken dan nodig. Een strategie die ik in zulke situaties graag hanteer is kijken hoe andere software projecten het probleem oplossen. Een stuk software waar ik relatief veel ervaring mee heb is MYSQL of, preciezer, mariaDB. MariaDB slaat database gebruikers en hun rechten op in een tabel van de speciale &amp;ldquo;mysql&amp;rdquo; database. Dit voorbeeld is daardoor geinspireerd: we gaan een speciale &amp;ldquo;o=access&amp;rdquo; directory maken waarin bind-DNs en hun rechten worden vastgelegd. De structuur van onze volledige DIT gaat er als volgt uitzien:&lt;/p&gt;
&lt;div class=&quot;code-sample&quot;&gt;&lt;pre&gt;[ (root) dc=example,dc=com ]&lt;/pre&gt;&lt;pre&gt;  |&lt;/pre&gt;&lt;pre&gt;  |_ [ (organization) o=access,dc=example,dc=com ]&lt;/pre&gt;&lt;pre&gt;  |     |&lt;/pre&gt;&lt;pre&gt;  |     |_ [ (groupOfNames) cn=authentication,o=access,dc=example,dc=com ]&lt;/pre&gt;&lt;pre&gt;  |     |     |&lt;/pre&gt;&lt;pre&gt;  |     |     |_ +member: uid=authlia,o=access,dc=example,dc=com&lt;/pre&gt;&lt;pre&gt;  |     |     |_ +member: uid=registration,o=access,dc=example,dc=com&lt;/pre&gt;&lt;pre&gt;  |     |&lt;/pre&gt;&lt;pre&gt;  |     |_ [ (groupOfNames) cn=something-else,o=access,dc=example,dc=com ]&lt;/pre&gt;&lt;pre&gt;  |     |     |&lt;/pre&gt;&lt;pre&gt;  |     |     |_ +member: uid=registration,o=access,dc=example,dc=com&lt;/pre&gt;&lt;pre&gt;  |     |&lt;/pre&gt;&lt;pre&gt;  |     |_ [ (com-example-Person) uid=authelia,o=access,dc=example,dc=com ]&lt;/pre&gt;&lt;pre&gt;  |     |_ [ (com-example-Person) uid=registration,o=access,dc=example,dc=com ]&lt;/pre&gt;&lt;pre&gt;  |&lt;/pre&gt;&lt;pre&gt;  |&lt;/pre&gt;&lt;pre&gt;  |_ [ (organization) o=authentication,dc=example,dc=com ]&lt;/pre&gt;&lt;pre&gt;  |_ [ (organization) o=something-else,dc=example,dc=com ]&lt;/pre&gt;&lt;pre&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Zoals te zien, zal de o=access directory twee soorten objecten bevatten: &lt;code&gt;groupOfNames&lt;/code&gt; en &lt;code&gt;com-example-Person&lt;/code&gt;. Het &lt;code&gt;cn&lt;/code&gt; component van iedere groupOfNames heeft de naam van een andere &lt;code&gt;organization&lt;/code&gt; die naast &lt;code&gt;o=access&lt;/code&gt; in de DIT bestaat. Door gebruikers van het type &lt;code&gt;com-example-Person&lt;/code&gt; als lid van een dergelijke groep toe te voegen, zullen deze gebruikers gebruikt kunnen worden als bind-DNs voor de congruerende organizations. Kort gezegd: als de gebruiker &lt;code&gt;uid=authlia,o=access,dc=example,dc=com&lt;/code&gt; aan de groep &lt;code&gt;cn=authentication,o=access,dc=example,dc=com&lt;/code&gt; wordt toegevoegd, dan kan de DN van deze gebruiker vanaf dat moment gebruikt worden om toegang te krijgen tot &lt;code&gt;o=authentication,dc=example,dc=com&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Hiermee wordt het volgende bereikt:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Het is makkelijk om een bind-DN toegang te geven tot 1 of meerdere sub-organisaties in de DIT.&lt;/li&gt;
&lt;li&gt;Omdat alleen op het root-niveau van de DIT rechten worden beheerd, wordt onnodige complexiteit met rechten in meerdere lagen van sub-directories voorkomen.&lt;/li&gt;
&lt;li&gt;Net als een mariaDB database, is de ldap server met het gebruik van &lt;code&gt;organization&lt;/code&gt; directories in de root van onze DIT in feite een multi-tennant database geworden. Een &lt;code&gt;organization&lt;/code&gt; is in deze context als een &lt;code&gt;schema&lt;/code&gt; in een mariaDB/MySQL database. En database gebruikers en hun rechten kunnen per &lt;code&gt;organization&lt;/code&gt; worden bijgehouden.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;olcAccess in cn=config&lt;/h4&gt;

&lt;p&gt;Om het bovenstaande mogelijk te maken is wel wat configuratie magie nodig. De regels die gevolgd moeten worden voor het toewijzen van rechten aan een bind-DN bij connectie staan vastgelegd in &lt;code&gt;olcDatabase{1}mdb,cn=config&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;code-sample&quot;&gt;&lt;pre&gt;dn: olcDatabase={1}mdb,cn=config&lt;/pre&gt;&lt;pre&gt;changetype: modify&lt;/pre&gt;&lt;pre&gt;replace: olcAccess&lt;/pre&gt;&lt;pre&gt;olcAccess: to attrs=userPassword by anonymous auth&lt;/pre&gt;&lt;pre&gt;olcAccess: to dn.regex=&amp;#34;o=([^,]+),dc=example,dc=com$&amp;#34; by group/groupOfNames/member.expand=&amp;#34;cn=$1,o=access,dc=example,dc=com&amp;#34; manage&lt;/pre&gt;&lt;pre&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Authelia Configuratie&lt;/h2&gt;</description><pubDate></pubDate><guid isPermaLink="false"> [docs] Notities Over OpenLDAP Cg==</guid>
</item>
<item><title> How To Use Your Email Client For Physical Mail </title><link>https://hugot.nl/posts/use-your-mail-client-for-physical-mail/index.html</link><description>&lt;h1&gt;How To Use Your Email Client For Physical Mail&lt;/h1&gt;
&lt;p&gt;
 Whether it&#39;s to re-read a conversation, find a plane ticket I ordered or
 check when a meeting was planned, I often find myself looking up old
 emails. It&#39;s usually easy to do so because email clients are designed for
 the task: Many of them support full-text search and some even complement
 that with neat tagging and categorization systems. To be honest I have
 become completely dependent on those features for my day to day
 life. Having full-text search and some sort of categorization for email
 can be a huge time saver. When it comes to physical mail however, I still
 have to browse through stacks of paper to (hopefully) find what I&#39;m
 looking for. I figured that it&#39;d be nice to use my fancy email client to
 deal with physical mail as well, so I found a way to do just that. Turns
 out it&#39;s pretty simple!
&lt;/p&gt;

&lt;p&gt;
 The main objective here is to transform our physical mail into an email
 that can be received, indexed and read by our email client of choice. Now,
 one way to do that would be to type the contents of our mail into an email
 by hand, but &lt;i&gt;ain&#39;t nobody got time for that!&lt;/i&gt;. The (more appealing)
 alternative is to use a document scanner. I have a single purpose scanner
 unit from Canon that I hook up to my laptop for just this purpose.
&lt;/p&gt;

&lt;p&gt;
 It isn&#39;t as simple as just emailing a scanned document to ourselves
 though: email clients are smart, but they can&#39;t understand a word of text
 in our PDF or JPEG of a physical document. They need content to be in
 plain text form in order to provide us with some of their best features
 like full-text search. We&#39;ll have to somehow transform our scanned
 documents into plain text that we can include in our email. To do this, we
 can use tesseract. Tesseract is an optical character recognition (OCR)
 engine, meaning that it can recognize text in images and extract it for
 us. Installing it should be easy on Debian derivative distros like
 Ubuntu. My laptop is running Debian unstable so I just ran &lt;code class=&quot;nowrap&quot;&gt;apt
  install tesseract&lt;/code&gt; and started using it. Using it is as easy as
 upening up a terminal and typing &lt;code class=&quot;nowrap&quot;&gt;tesseract FILE.jpg
  OUTPUT&lt;/code&gt;. That command will save all the text that tesseract is able
 to recognize in the image FILE.jpg to a file called OUTPUT.txt.
&lt;/p&gt;

&lt;aside&gt;
 &lt;i&gt;
  Side note: I am Dutch, so most of my physical mail is in Dutch. To
  make tesseract better understand my mail I installed the
  tesseract-ocr-nld package using &lt;code&gt;apt install
   tesseract-ocr-nld&lt;/code&gt;. You can check what other language packs are
  available by using &lt;code&gt;apt search tesseract-ocr&lt;/code&gt;.
 &lt;/i&gt;
&lt;/aside&gt;

&lt;p&gt;
 All we have to do from there is copy-paste the contents of that file into
 an email and send it to ourselves! Depending on the formatting of the
 input document, the output may not always be pleasant to read. We can
 account for this by including the original document as an attachment to
 the email. That way we get the best of both worlds: we can use the search
 functionality of our email client to find the document, and then read it
 in its original form by opening the attachment.
&lt;/p&gt;

&lt;p&gt;
 This is all easy enough, but I&#39;m lazy. I didn&#39;t feel like opening up my
 email client and doing manual copy-pasting, so I decided to automate the
 process a little further. I have postfix setup on my system to relay to my
 mail server, so I can simply use the &lt;code&gt;mail&lt;/code&gt; command to send
 emails without a GUI mail client. I combined that with tesseract in a
 little bash script. The script iterates through all of its arguments and
 interprets them as filenames of scanned documents. It calls tesseract to
 extract text from them, concatenates the results, attaches the files to an
 email and sends it to my personal email address. Now all I have to do is
 run the script with filenames of some documents and my job is done. If
 anyone is interested in an actual program that does the same thing and
 doesn&#39;t require you to setup postfix, let me know! I might consider
 authoring one if it&#39;s useful to more people than just myself. The script
 I&#39;m currently using can be found &lt;a href=&quot;assets/scan-to-mailpile.bash.html&quot;&gt;here
  (pretty)&lt;/a&gt;  and &lt;a href=&quot;assets/scan-to-mailpile.bash&quot;&gt;here (raw)&lt;/a&gt;, but I
 don&#39;t recommend using it if you don&#39;t fully understand its contents, it&#39;s
 not a polished user experience 🤓.
&lt;/p&gt;

&lt;!-- Local Variables: --&gt;
&lt;!-- sgml-basic-offset: 1 --&gt;
&lt;!-- End: --&gt;</description><pubDate></pubDate><guid isPermaLink="false"> How To Use Your Email Client For Physical Mail Cg==</guid>
</item>
<item><title> Creating a Simple Static Blog </title><link>https://hugot.nl/posts/simple-static-blog/index.html</link><description>&lt;h1&gt;Creating a Simple Static Blog&lt;/h1&gt;

&lt;p&gt;
 I love personal websites. It&#39;s amazing that people can share content with the
 entire world just by writing some text and throwing it behind a web server. I
 wanted to know what that is like, so I set out to create a personal website of
 my own. As you can see I succeeded in doing so, but getting here wasn&#39;t as
 straight forward as I initially thought it would be. I thought that, being a
 programmer and knowing a thing or two about web servers, setting up my own
 website was going to be easy: How complicated can it be to throw some text
 behind a web server, right?! I was wrong. Throwing text behind a web server
 can be very complicated (and wasteful). But it doesn&#39;t have to be!
&lt;/p&gt;

&lt;h2&gt;The search for a CMS&lt;/h2&gt;
&lt;p&gt;
 The first thought that popped into my head when I got started was: &lt;em&gt;I need to
  find myself a CMS&lt;/em&gt;. I had a few requirements: my site should be
 self-hosted, be lightweight, have no JavaScript in it and it should look
 pretty. I also wanted to be able to write blog posts in markdown using my
 trusty text editor. The first CMSes that came to mind were WordPress, Ghost,
 Jekyll and Hugo. I don&#39;t want to get into too much detail, so I&#39;ll summarize
 my judgments here without any nuance: Wordpress is the devil, Ghost is great
 but too bulky and both Jekyll and Hugo required me to learn about theming and
 project structure which I deemed too much effort. I just wanted to write some
 text and throw it behind a web server, but all solutions I saw were sophisticated
 programs that were designed to &amp;quot;scale&amp;quot;, support &amp;quot;modern
 workflows&amp;quot; or be &amp;quot;easy to use with integrated WYSIWYG
 editors&amp;quot;. I didn&#39;t feel like exploring the idea further and gave up on
 having a website for a while.
&lt;/p&gt;

&lt;p&gt;
 Then, a few months back, I learned about writefreely. Writefreely is an open
 source web application from write.as that lets users create blogs that
 federate through the fediverse. I had just started to become acquainted with
 the fediverse and it seemed like a cool idea to me at the time, so me and a
 friend decided to set up our own instance. It wasn&#39;t too hard to set up and
 once it was running I only needed a couple of hours to add some custom
 style sheets. I finally had a fully functioning blog that satisfied all of my
 needs!
&lt;/p&gt;

&lt;p&gt;
 After that the holiday season came along and I turned my back on blogging for
 a while. When I checked on our instance three or four weeks later I was
 displeased to discover that spammers had created accounts on the instance and
 were posting spammy garbage. Sure, we could just close registrations. But this
 event reminded me that hosting any dynamic web application on the public
 internet is a big responsibility that involves keeping software up to date,
 monitoring and doing other configuration/maintenance work. Not to mention
 having to do regular database backups. I didn&#39;t feel like having to do any of
 that, I already have by hands full with self-hosting a bunch of other
 services. Once again I had found a complicated solution for a simple problem:
 I just wanted to throw some text behind a web server, remember? Why did I need to use a CMS
 again?
&lt;/p&gt;

&lt;p&gt;
 CMSes seem to offer solutions to a problem that I don&#39;t have: I don&#39;t mind
 writing plain html and I most certainly don&#39;t need a WISYWIG editor. I also
 don&#39;t need plugins, dynamic code for analytics, pretty yaml or toml
 configuration files, templates, extensive theming, admin panels, markdown,
 mailing lists, comment threads or any other common CMS features. I just want
 to throw some text behind a web server, so why not just write some HTML and do
 exactly that?
&lt;/p&gt;

&lt;h2&gt;A CMS in ~200 lines&lt;/h2&gt;
&lt;p&gt;
 It was decided: I was going to blog in plain HTML. Having figured out what I
 actually wanted, I went to work. The first order of business was creating a
 style sheet to make things look good. I made it my goal to use as little CSS
 as possible and I managed to limit myself to just these 23 lines:
&lt;/p&gt;

&lt;style type=&quot;text/css&quot;&gt;
 .code {
 color: #f6f3e8;
 background-color: #242424;
 }
 .builtin {
 color: #e5786d;
 }
 .css-property {
 color: #8ac6f2;
 font-weight: bold;
 }
 .css-selector {
 color: #cae682;
 }
 .custom {
 color: #000000;
 background-color: #f4ecd8;
 }
 .custom-1 {
 color: #ffffff;
 background-color: #5b4636;
 }
&lt;/style&gt;

&lt;div class=&quot;code&quot;&gt;
 &lt;pre&gt;
  &lt;span class=&quot;css-selector&quot;&gt;html &lt;/span&gt;{
    &lt;span class=&quot;css-property&quot;&gt;font-family&lt;/span&gt;: Helvetica, Arial, sans-serif;
    &lt;span class=&quot;css-property&quot;&gt;color&lt;/span&gt;: &lt;span class=&quot;custom-1&quot;&gt;#5b4636&lt;/span&gt;;
    &lt;span class=&quot;css-property&quot;&gt;background-color&lt;/span&gt;: &lt;span class=&quot;custom&quot;&gt;#f4ecd8&lt;/span&gt;;
  }

  &lt;span class=&quot;css-selector&quot;&gt;body &lt;/span&gt;{
    &lt;span class=&quot;css-property&quot;&gt;padding&lt;/span&gt;: 1em;
    &lt;span class=&quot;css-property&quot;&gt;margin&lt;/span&gt;: auto;
  }

  &lt;span class=&quot;builtin&quot;&gt;@media&lt;/span&gt; only all and (pointer: coarse), (pointer: none) {
    &lt;span class=&quot;css-selector&quot;&gt;body &lt;/span&gt;{
      &lt;span class=&quot;css-property&quot;&gt;font-size&lt;/span&gt;: 5.5vmin;
    }
  }

  &lt;span class=&quot;builtin&quot;&gt;@media&lt;/span&gt; only all and (pointer: fine) {
    &lt;span class=&quot;css-selector&quot;&gt;body &lt;/span&gt;{
      &lt;span class=&quot;css-property&quot;&gt;font-size&lt;/span&gt;: calc(16px + 0.6vmin);
      &lt;span class=&quot;css-property&quot;&gt;min-width&lt;/span&gt;: 500px;
      &lt;span class=&quot;css-property&quot;&gt;max-width&lt;/span&gt;: 50em;
    }
  }
 &lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
 This is all the CSS I need to have a responsive website that looks pretty (I
 stole the colors from firefox&#39;s reader mode btw). It&#39;s such a small amount
 that I don&#39;t mind copy-pasting it at the top of all new HTML pages that I add
 to my website. This might make it harder to change the styling later, but it
 has the added benefit that each page is a standalone document. So for
 example &lt;code&gt;wget PAGE_URL&lt;/code&gt;  will download a HTML page that looks
 exactly the same locally as it does on the web without having to download any
 extra assets.
&lt;/p&gt;

&lt;p&gt;
 The next challenge was creating and maintaining the article listing page and
 the RSS feed for the blog. I don&#39;t mind typing HTML pages, but typing out a
 page and an RSS feed containing excerpts/titles from other files gets old soon
 and I&#39;d be bound to forget updating its content every once in a while. This
 seemed like a perfect occasion to write a little bash script, so I did. You can
 find the script
 &lt;a href=&quot;assets/generate-blog.bash.html&quot;&gt;here&lt;/a&gt;. What it basically does is
 read in a file called posts.txt that has html filenames in it, separated by
 newlines. Using those filenames and the contents of the files it then generates
 a HTML page (called &lt;a href=&quot;../../blog.html&quot;&gt;blog.html&lt;/a&gt;) and an RSS feed
 (called &lt;a href=&quot;../../feed.xml&quot;&gt;feed.xml&lt;/a&gt;).
&lt;/p&gt;

&lt;p&gt;
 I keep all of this neatly stored under version control
 &lt;a href=&quot;https://git.snorba.art/hugo/website&quot;&gt;here&lt;/a&gt;, so deploying a new version
 is as easy as running &lt;code&gt;git pull&lt;/code&gt; on my web server. I can honestly say that
 this is the simplest, most user-friendly CMS that I have ever used, and it
 only took me several months to figure out that this is exactly what I needed 🤓.
&lt;/p&gt;

&lt;p&gt;
 So, to conclude this story: websites are just HTML. You don&#39;t need fancy
 programs or WYSIWYG editors to create a website. Just a text editor, a web
 server and some spare time.
&lt;/p&gt;

&lt;!-- Local Variables: --&gt;
&lt;!-- sgml-basic-offset: 1 --&gt;
&lt;!-- End: --&gt;</description><pubDate></pubDate><guid isPermaLink="false"> Creating a Simple Static Blog Cg==</guid>
</item>
<item><title> Introduction </title><link>https://hugot.nl/posts/introduction/index.html</link><description>&lt;h1&gt;Introduction&lt;/h1&gt;

&lt;p&gt;
 Hello, welcome to my blog! My name is Hugo. I am a 22 year old Software Engineering
 student from the Netherlands. Software development is a huge part of my life, I write a
 lot of (weird) programs to scratch my own itch and most software I create
 is &lt;a href=&quot;https://github.com/hugot&quot;&gt;open source&lt;/a&gt; by default. I also run a one-man
 company that provides some IT services on the side.
&lt;/p&gt;

&lt;p&gt;
 Between working on projects and studying I like to watch movies &amp;amp; series, listen to music
 &amp;amp; podcasts, ride my road bike and take hikes.
&lt;/p&gt;

&lt;h2&gt;What kind of blog is this?&lt;/h2&gt;
&lt;p&gt;
 Because I&#39;m quite new to this and I want to keep myself interested, I won&#39;t be
 limiting myself to a single topic. You can expect me to post about a variety of topics
 that may interest/annoy/excite me at any given moment.
&lt;/p&gt;

&lt;p&gt;May my posts be interesting and my posting schedule be consistent 🤓🖖&lt;/p&gt;

&lt;p&gt;I hope to see you around! - Hugo&lt;/p&gt;

&lt;!-- Local Variables: --&gt;
&lt;!-- sgml-basic-offset: 1 --&gt;
&lt;!-- End: --&gt;</description><pubDate></pubDate><guid isPermaLink="false"> Introduction Cg==</guid>
</item>
</channel>
</rss>
