Loading...

Blog

Dovecot setup voor e-mail archief

05-05-2025

In mijn zoektocht voor een alleen-archief-imap omgeving, was mijn eerste plan om een Debian of Ubuntu omgeving te gebruiken. Ik kwam er al snel achter dat er niet heel veel documentatie over de opzet te vinden was. Toen liep ik tegen een officiele docker implementatie.

De opzet van de container is echter wel wat simpeler dan de Debian of Ubuntu versie. Maar het lijkt er wel op dat alles erin zit wat nodig is. Inmiddels is versie 2.4.1 van de container te verkrijgen. Maar ja, hoe nu verder?

De basis setup van de container verwacht een wachtwoord via environment variabelen voor een gebruiker en de dovecot admin:

USER_PASSWORD=
DOVEADM_PASSWORD=

"Een wachtwoord voor één gebruiker?". Het blijkt dat de initiële setup zo gemaakt is dat hij elke gebruikersnaam accepteert en daarvoor een mailbox maakt, als dit wachtwoord wordt gebruikt. Op zich handig voor test omgevingen of zo, maar niet wat ik momenteel zoek. Ik wil voorlopig een basis opzet hebben, waarbij eventueel meerdere gebruikers aangemaakt kunnen worden. met een eigen wachtwoord. Dit wachtwoord en de opgeslagen mail moeten geëncrypt zijn. Hierbij ga ik alleen IMAP met SSL gebruiken. Voor het SSL certificaat wil ik letsencrypt gebruiken.

Ik heb via Dehydrated en Nginx een certificaat voor mijn domeinnaam aangemaakt. De container verwacht dat de certificaten als /etc/dovecot/ssl/tls.crt en /etc/dovecot/ssl/tls.key beschikbaar zijn. Voor de .crt gebruik ik fullchain.pem en voor de .key het privkey.pem certificaat. Deze worden via een volume mapping toegewezen.

De opgeslagen mail wil ik ook buiten de container opslaan. Standaard worden de mailboxen onder /srv/vmail aangemaakt.

services:
  dovecot:
    image: dovecot/dovecot:latest
    restart: always
    ports:
     - 0.0.0.0:993:31993
    volumes:
     - "${DOCKER_DATAPATH}/certs/fullchain.pem:/etc/dovecot/ssl/tls.crt:ro"
     - "${DOCKER_DATAPATH}/certs/privkey.pem:/etc/dovecot/ssl/tls.key:ro"
     - "${DOCKER_DATAPATH}/vmail:/srv/vmail"

Voor het totale plaatje zijn er nog 3 mappings nodig. Ik pas de basis configuratie niet aan van de container, maar voeg alleen toe. Voor de gebruikers wordt en een users bestand (passwd-file) gebruikt, dat een zowel de gebruiker als het wachtwoord bevat, maar ook een paar extra lege velden.

Voor de aanvullende configuratie wordt een 10-auth.conf bestand aangemaakt in de conf.d map. Bij het opstarten wordt elke .conf bestand in deze map meegenomen.

Aanvullend kan ik alvast verklappen dat certificaten voor het encrypten van de bestanden in de map /etc/dovecot/mail-crypt terecht gaan komen"

     - "${DOCKER_DATAPATH}/users:/etc/dovecot/users:ro"
     - "${DOCKER_DATAPATH}/10-auth.conf:/etc/dovecot/conf.d/10-auth.conf:ro"
     - "${DOCKER_DATAPATH}/dovecot-mail-crypt:/etc/dovecot/mail-crypt:ro"

Tijdens het testen heb ik Thunderbird gebruikt. Hierdoor liep ik al snel tegen een paar problemen aan. Het eerste probleem was, wanneer ik een mailtje in de mailbox sleepte, werd de verbinding verbroken met de melding dat er teveel ongeldige commando's verstuurd werden:

dovecot-1  | May 05 07:55:06 imap(myarchive)<21><t9Qz0F40vPW8Wgp1>: Info: Disconnected: Too many invalid IMAP commands. in=1677 out=2637 deleted=0 expunged=0 trashed=0 hdr_count=0 hdr_bytes=0 body_count=0 body_bytes=0 

Na een behoorlijke wat zoektijd, kwam ik in een github ticket tegen, dat een experimentele extentie het probleem zou kunnen zijn. Via mail_utf8_extensions=no kan deze worden uitgeschakeld en werkt Thunderbird in eens wel zoals verwacht.

Het tweede probleem had iets met de standaard mappen te maken. Na deze uit de Ubuntu configuratie over genomen te hebben (zie namespace inbox {...) werkte de mailbox in eens zoals verwacht.

Zo ben ik tot de volgende opzet van 10-auth.conf gekomen:

# Use for debugging
# mail_debug=yes
# auth_verbose=yes
# auth_debug=yes
# auth_debug_passwords=yes
# mail_debug=yes

# Fix for Thunderbird
mail_utf8_extensions=no

# Authorization
auth_verbose_passwords=plain
auth_mechanisms = plain login 
# removed: digest-md5 cram-md5

# Passdb configuration
passdb passwd-file {
  driver = passwd-file
  passwd_file_path = /etc/dovecot/users
}

# Userdb configuration
userdb passwd-file {
  driver = passwd-file
  passwd_file_path = /etc/dovecot/users
}

# Default folders
namespace inbox {
  inbox = yes
  mailbox Trash {
    special_use = \Trash
    auto = subscribe
  }

  # These mailboxes are widely used and could perhaps be created automatically:
  mailbox Drafts {
    special_use = \Drafts
  }
  mailbox Junk {
    special_use = \Junk
  }

  # For \Sent mailboxes there are two widely used names. We'll mark both of
  # them as \Sent. User typically deletes one of them if duplicates are created.
  mailbox Sent {
    special_use = \Sent
  }
  mailbox "Sent Messages" {
    special_use = \Sent
  }
}

# Encryption of mails
mail_plugins {
  mail_crypt = yes
}

crypt_global_public_key_file = /etc/dovecot/mail-crypt/ecpubkey.pem
crypt_global_private_key main {
  crypt_private_key_file = /etc/dovecot/mail-crypt/ecprivkey.pem
}

De certificaten voor het encrypten van de data moeten ook nog aangemaakt worden. Zorg ook dat de certificaten de juiste owner en rechten hebben binnen de container. De vmail gebruiker en groep hebben beide nummer 1000.

mkdir -p data/dovecot-mail-crypt
openssl ecparam -name prime256v1 -genkey | openssl pkey -out data/dovecot-mail-crypt/ecprivkey.pem
openssl pkey -in data/dovecot-mail-crypt/ecprivkey.pem -pubout -out data/dovecot-mail-crypt/ecpubkey.pem

chmod -Rf  600 data/dovecot-mail-crypt/*
chown -Rf 1000.1000 data/dovecot-mail-crypt

Om dit allemaal nou ook nog werkend te krijgen, moet er in ieder geval 1 gebruiker toegevoegd worden. Hiervoor kan de tool doveadm gebruikt worden. Misschien is het ook mogelijk om hiermee een gebruiker volledig toe te voegen aan het users bestand, maar zover heb ik niet gekeken. doveadm is in de container beschikbaar. Ik gebruik hier de encryptie SHA512-CRYPT om te zorgen dat het wachtwoord niet leesbaar is in de configuratie. Hier een voorbeeld:

docker compose exec dovecot doveadm pw -s SHA512-CRYPT
Enter new password: 
Retype new password: 
{SHA512-CRYPT}$6$RVEYzANS6v0a.kAB$.0lLSo2DaXwpi8E.iAClBoQu3GK36oWPCRp503ZlhDok3ixomdcMbiwURNScpxVlYHGD7UItfrlQz4tEMgaZ.

Deze laatste regel is het geëncrypte wachtwoord. Deze gaan we toevoegen aan het users bestand. Allereerst komt de gebruikersnaam in het bestand te staan. Hou er rekening mee dat deze in ieder geval geen : mag bevatten, omdat dit het scheidingsteken is tussen de velden. Deze wordt gevolgd door het wachtwoord. Het users bestandsformaat verwacht dan nog een aantal velden die we leeg gaan laten. Hierom voegen we :::::: toe aan de regel. Een voorbeeld is dan als volgt:

my-mail-user:{SHA512-CRYPT}$6$RVEYzANS6v0a.kAB$.0lLSo2DaXwpi8E.iAClBoQu3GK36oWPCRp503ZlhDok3ixomdcMbiwURNScpxVlYHGD7UItfrlQz4tEMgaZ.::::::

Belangrijk punt is dat dovecot herstart moet worden als dit bestand veranderd. Dit is een goed argument om een SQL server te gaan gebruiken hiervoor. Sqlite zou een prima oplossing kunnen zijn, maar dat is voor een andere keer. De container is zodanig kaal, dat ps of killall niet beschikbaar zijn. Een alternatief is dan ook om de container te herstarten. Maar dovecot heeft ook een herstart optie ingebouwd, wat het proces wat vloeiender maakt:

docker compose exec dovecot doveadm reload

Hierna zou je met elke IMAP applicatie moeten kunnen verbinden en mail naar deze mailbox moeten kunnen verplaatsen. Zorg wel voor een goede backup van de certificaten, anders zijn de e-mails niet meer te redden na een crash.

XTTS-v2 TTS Installation guide

26-04-2025

Online kwam ik een artikel tegen waarbij de auteur de stappen toont om XTTS-v2 te installeren. Wat me nogal vaak opvalt is dat dit soort blog posts verre van compleet zijn. Je zou bijna gaan denken dat het een vorm van clickbait is. Niet dat ik de auteur daarvan beschuldig hoor, integendeel. Hierbij dan ook mijn poging om het werkend te krijgen en wat meer diepgang te geven.

Ter info, ik gebruik in dit geval een Mac M1 machine. Onder Linux zullen de stap relatief hetzelfde zijn, vermoed ik.

In stap 1 wordt de repository van het project vanaf de git omgeving van huggingface gedownload.

git clone https://huggingface.co/coqui/XTTS-v2

De auteur gaat vervolgens de 'virtual environment' activeren, maar deze bestaat nog helemaal niet. Dus die gaan we aanmaken in de map van het project. Omdat ik in het verleden problemen ondervond met de hoogst geïnstalleerde versie van Python op mijn machine, kies ik ervoor om Python 3.10 te testen.

cd XTTS-v2/
python3.10 -m venv .
source ./bin/activate

Hierna zou de virtuale environment actief moeten zijn (bij mij verschijnt er (XTTS-v2) voor de command prompt. Waarom we dit doen? Op deze manier kunnen we het project scheiden van andere installaties op onze machine, zodat ze elkaar minder beïnvloeden.

De auteur wil vervolgens de requirements installeren. Dit kan je doen door alle benodigde pakketten in een bestandje te benoemen en dit met een commando te laten installeren. Hij heeft echter de volgorde verkeerd om staan. Dus we draaien het even om. We maken eerst het bestand requirements.txt aan. Ik heb een kleine wijziging erin gemaakt, wat veel vaker fout gaat bij dit soort blog posts en dat is het gebruik van PyTorch. Veelal wordt er verwezen naar een versie die niet meer bestaat. Op de PyTorch pagina is dezelfde versie wel te vinden, maar zonder de aanvulling op het versie nummer:

cat <<EOF > requirements.txt
absl-py==2.1.0
aiohappyeyeballs==2.4.3
aiohttp==3.11.2
aiosignal==1.3.1
annotated-types==0.7.0
anyascii==0.3.2
asttokens==2.4.1
attrs==24.2.0
audioread==3.0.1
babel==2.16.0
bangla==0.0.2
blinker==1.9.0
blis==0.7.11
bnnumerizer==0.0.2
bnunicodenormalizer==0.1.7
catalogue==2.0.10
certifi==2024.8.30
cffi==1.17.1
charset-normalizer==3.4.0
click==8.1.7
cloudpathlib==0.20.0
colorama==0.4.6
confection==0.1.5
contourpy==1.3.1
coqpit==0.0.17
cycler==0.12.1
cymem==2.0.8
Cython==3.0.11
dateparser==1.1.8
decorator==5.1.1
docopt==0.6.2
einops==0.8.0
encodec==0.1.1
executing==2.1.0
filelock==3.13.1
Flask==3.1.0
fonttools==4.55.0
frozenlist==1.5.0
fsspec==2024.2.0
g2pkk==0.1.2
grpcio==1.68.0
gruut==2.2.3
gruut-ipa==0.13.0
gruut_lang_de==2.0.1
gruut_lang_en==2.0.1
gruut_lang_es==2.0.1
gruut_lang_fr==2.0.2
hangul-romanize==0.1.0
huggingface-hub==0.26.2
idna==3.10
inflect==7.4.0
ipython==8.29.0
itsdangerous==2.2.0
jamo==0.4.1
jedi==0.19.2
jieba==0.42.1
Jinja2==3.1.3
joblib==1.4.2
jsonlines==1.2.0
kiwisolver==1.4.7
langcodes==3.4.1
language_data==1.2.0
lazy_loader==0.4
librosa==0.10.2.post1
llvmlite==0.43.0
marisa-trie==1.2.1
Markdown==3.7
markdown-it-py==3.0.0
MarkupSafe==2.1.5
matplotlib==3.9.2
matplotlib-inline==0.1.7
mdurl==0.1.2
more-itertools==10.5.0
mpmath==1.3.0
msgpack==1.1.0
multidict==6.1.0
murmurhash==1.0.10
networkx==2.8.8
nltk==3.9.1
num2words==0.5.13
numba==0.60.0
numpy==1.26.3
packaging==24.2
pandas==1.5.3
parso==0.8.4
pillow==10.2.0
platformdirs==4.3.6
pooch==1.8.2
preshed==3.0.9
prompt_toolkit==3.0.48
propcache==0.2.0
protobuf==5.28.3
psutil==6.1.0
pure_eval==0.2.3
pycparser==2.22
pydantic==2.9.2
pydantic_core==2.23.4
Pygments==2.18.0
pynndescent==0.5.13
pyparsing==3.2.0
pypinyin==0.53.0
pysbd==0.3.4
python-crfsuite==0.9.11
python-dateutil==2.9.0.post0
pytz==2024.2
PyYAML==6.0.2
regex==2024.11.6
requests==2.32.3
rich==13.9.4
safetensors==0.4.5
scikit-learn==1.5.2
scipy==1.14.1
shellingham==1.5.4
six==1.16.0
smart-open==7.0.5
soundfile==0.12.1
soxr==0.5.0.post1
spacy==3.7.5
spacy-legacy==3.0.12
spacy-loggers==1.0.5
srsly==2.4.8
stack-data==0.6.3
SudachiDict-core==20241021
SudachiPy==0.6.8
sympy==1.13.1
tensorboard==2.18.0
tensorboard-data-server==0.7.2
thinc==8.2.5
threadpoolctl==3.5.0
tokenizers==0.20.3
# Verwijderd vanwege versie problemen
# torch==2.5.1+cu124
# torchaudio==2.5.1+cu124
# torchvision==0.20.1+cu124
torch==2.5.1
torchaudio==2.5.1
torchvision==0.20.1
tqdm==4.67.0
trainer==0.0.36
traitlets==5.14.3
transformers==4.46.2
typeguard==4.4.1
typer==0.13.0
typing_extensions==4.12.2
tzdata==2024.2
tzlocal==5.2
umap-learn==0.5.7
Unidecode==1.3.8
urllib3==2.2.3
wasabi==1.1.3
wcwidth==0.2.13
weasel==0.4.1
Werkzeug==3.1.3
wrapt==1.16.0
yarl==1.17.1
EOF

Om deze vervolgens te gebruiken om de pakketten te installeren:

pip install -r requirements.txt

Als alles meezit wordt alles zonder meldingen geïnstalleerd. De oplossing van het versienummer werkt voor mij in ieder geval.

Vervolgens gaan we TTS installeren. De schrijver heeft het over dat deze installatie wel 40 minuten kan duren, maar 3 seconden later is hij klaar. Het is mij onduidelijk waarom hij dit schreef.

pip install TTS==0.22.0 --no-deps

In het vervolg wil hij PyTorch gaan installeren, maar dit is al gebeurd. Het lijkt wel of deze blog posts verkeerd om gepubliceerd is. En hierna houdt de post ook op. Wat hebben we nu bereikt? Nou, eigenlijk niet zoveel tot zo ver.

In de readme.md staat nog wat informatie van het project zelf. We nemen het eerste voorbeeld en passen hem een beetje aan. Aangezien het een variant is de voice cloning gebruikt, is er een audio sample nodig. Er staan een aantal voorbeelden in de samples map. Hiernaast is het voorbeeld wat verouderd. We passen het gpu=True aan naar tts.to("mps"). mps is de GPU acceleratie voor m1 processoren. Voor NVidea GPU's kan je cuda gebruiken.

cat <<EOF > test-1.py
from TTS.api import TTS
tts = TTS("tts_models/multilingual/multi-dataset/xtts_v2")
tts.to("mps")

# generate speech by cloning a voice using default settings
tts.tts_to_file(text="It took me quite a long time to develop a voice, and now that I have it I'm not going to be silent.",
                file_path="output.wav",
                speaker_wav="./samples/en_sample.wav",
                language="en")
EOF

python ./test-1.py 

Na uitvoer loop ik tegen het volgende probleem aan:

NotImplementedError: Output channels > 65536 not supported at the MPS device. As a temporary fix, you can set the environment variable `PYTORCH_ENABLE_MPS_FALLBACK=1` to use the CPU as a fallback for this op. WARNING: this will be slower than running natively on MPS.

En hier begint dan ook meteen de ellende. Ik zou willen proberen of een nieuwere PyTorch versie dit oplost, maar dat kan niet zomaar. Na het aanpassen naar de laatste versie (2.7.0) moet ook sympy>=1.13.3 worden geïnstalleerd, wat weer leid tot het volgende:

ERROR: pip's dependency resolver does not currently take into account all the packages that are installed. This behaviour is the source of the following dependency conflicts.
tts 0.22.0 requires numpy==1.22.0; python_version <= "3.10", but you have numpy 1.26.3 which is incompatible.

Na het weer terug zetten van de requirements, probeer ik het voorstel wat in het log voorbij komt:

export PYTORCH_ENABLE_MPS_FALLBACK=1; python test-1.py

Dit lijkt geen effect te hebben. Als alternatief kunnen we tts.to("cpu") in het script gebruiken. En dit werkt wel! Maar ja, wel een stuk trager dan we zouden willen natuurlijk. Na het aanpassen naar cpu werkt het voorbeeld en hebben we een output.wav bestand.

Inmiddels geloof ik wel dat Engels behoorlijk goed uitgesproken kan worden met TTS systemen, maar Nederlands is nog vaak een probleem. Om dit te testen pas ik het script aan met een Nederlandse tekst en gebruik hierbij de engelse sample.

from TTS.api import TTS
tts = TTS("tts_models/multilingual/multi-dataset/xtts_v2")
tts.to("cpu")

# generate speech by cloning a voice using default settings
tts.tts_to_file(text="Het is belangrijk dat het geluid duidelijk uitgesproken wordt, en daardoor verstaanbaar is.",
                file_path="output.wav",
                speaker_wav="./samples/en_sample.wav",
                language="nl")

En het resultaat is erg goed! Een test met de Spaanse stem (een mannelijke stem) werkt wel, maar is niet geweldig. Ook de Franse sample levert niet echt geweldig resultaat. Het is overigens wel verstaanbaar. Als test heb ik online een audio sample gezocht, en met wat uitproberen komen er behoorlijk goede resultaten uit.

De snelheid op deze manier is helaas wel een puntje. Interessant zou zijn om het op een CUDA compatible systeem te testen, of te onderzoeken of en hoe dit direct met PyTorch te doen is.

Update van piper naar laatste versie op macOS

06-04-2025
Installatie piper vanaf source

Firefox 130 experimele feature

08-09-2024
Nieuwe Firefox Labs feature doet stof opwaaien.

Readability implementatie in RSS reader

05-09-2024

Voor het lezen en tonen van RSS feeds, dacht ik dat het praktisch zou zijn om de inhoud van de link van de feed te tonen in een zogenaamde "readermode", zoals deze in veel browsers is ingebouwd. Na een kleine zoektocht lijkt het erop dat de reader mode van Safari gebaseerd is op de implementatie van Mozilla. En zo blijkt dat deze open-source is en op GitHub te vinden is: readability.

Dit klinkt natuurlijk als een interessante optie om te testen, maar ik gebruik .Net, en geen Node.js. Na wat zoekwerk kwam ik al snel meerdere implementaties tegen op nuget, waaronder SmartReader:

This library supports the .NET Standard 2.0. The core algorithm is a port of the Mozilla Readability library. The original library is stable and used in production inside Firefox. This way we can piggyback on the hard and well-tested work of Mozilla.

SmartReader also added some improvements on the original library, getting more and better metadata:

  • site name
  • an author and publication date
  • the language
  • the excerpt of the article
  • the featured image
  • a list of images found (it can optionally also download them and store as data URI)
  • an estimate of the time needed to read the article

Some of these fields are now present in the original library.

It also allows to perform custom operations before and after extracting the article.

Het inzetten van SmartReader is nogal simpel. Voeg de package toe aan je project en laat SmartReader de pagina ophalen en beoordelen:

var article = SmartReader.Reader.ParseArticle("https://arstechnica.com/information-technology/2017/02/humans-must-become-cyborgs-to-survive-says-elon-musk/");

if(article.IsReadable)
{
    Console.WriteLine($"Article title {article.Title}");
}

Er zijn nog diverse opties in te stellen, maar die sla ik voorlopig over. Voor het gebruik in mijn RSS reader, wil ik liever geen HTML hebben, maar Markdown tekst. Ik gebruik al langer de ReverseMarkdown packages, wat tot prima resultaten leid. Hier loop ik helaas wel tegen een probleem aan. Het blijkt dat de HTML soms veel tabs (of spaties) bevat, tussen een tekst node en een andere HTML node. Bijvoorbeeld een tekst gevolgd door een link. Maar ook een linefeed samen met tabs na een paragraph openings tag <p>. Hierbij worden de tabs niet verwijderd wat resulteert dat de markdown naar HTML deze tekst als <pre> formatteert.

Hierom is het verstandig om de HTML toch eerst nog wat op te schonen. AngleSharp is hier een prima oplossing voor. Ik heb ervoor gekozen om alle HTML element langs te lopen en de tekst in de textnode's op te ruimen:

public static void HtmlTextNodeTrim(INode node)
{
    if (node is IElement elementNode)
    {
        foreach (var childNode in elementNode.ChildNodes)
        {
            HtmlTextNodeTrim(childNode);
        }
    }
    else if (node is IText textNode)
    {
        var updatedText = 
            textNode.NodeValue = (textNode.Text ?? string.Empty).Trim() + " ";
    }
}

Tijdens het schrijven van dit artikel bedenk ik me wel dat dit problemen kan opleveren met een <pre> of <code> tag. Dit is voor latere zorg. Door dit te combineren met het herformatteren van de HTML zonder indenting, komt er HTML uit die prima door ReverseMarkdown kan worden omgezet:

using System.IO;
using AngleSharp;
using AngleSharp.Dom;
using AngleSharp.Html.Dom;
using AngleSharp.Html.Parser;

protected virtual string GetReadable(string url)
{
    try
    {
        var uri = new Uri(url);
        
        var article = Reader.ParseArticle(uri.ToString());
        if (!article.IsReadable)
            return null;
        
        // Get and sanitize HTML
        var html = HtmlSanitizeHelper.SanitizeHtml(article.Content);

        // Parse to markdown
        return ReadabilityHelper.HtmlToMarkdown(html);
    }
    catch (Exception ex)
    {
        // ... do some logging  
    }

    return null;
}

public class HtmlSanitizeHelper
{
    public static string SanitizeHtml(string html)
    {
        var parser = new HtmlParser();
        var document = parser.ParseDocument(html);

        HtmlTextNodeTrim(document.Body);
        
        return DocumentToHtml(document);
    }
    
    public static void HtmlTextNodeTrim(INode node)
    {
        if (node is IElement elementNode)
        {
            foreach (var childNode in elementNode.ChildNodes)
            {
                HtmlTextNodeTrim(childNode);
            }
        }
        else if (node is IText textNode)
        {
            var updatedText = 
                textNode.NodeValue = (textNode.Text ?? string.Empty).Trim() + " ";
        }
    }
    
    public static string DocumentToHtml(IHtmlDocument document)
    {
        using (var writer = new StringWriter())
        {
            document.ToHtml(writer);
            return writer.ToString();
        }
    }

    public static string HtmlToMarkdown(string html)
    {
        return new Converter(new Config()
        {
            UnknownTags = Config.UnknownTagsOption.Bypass,
            GithubFlavored = true,
            RemoveComments = true,
            SmartHrefHandling = true,
            TableWithoutHeaderRowHandling = Config.TableWithoutHeaderRowHandlingOption.Default
        }).Convert(html);
    }
}

MySql 8.4 in Docker

05-06-2024

Nog niet heel lang geleden is versie 8.4 van MySql uitgekomen. Hierin is een wijziging doorgevoerd m.b.t. de authenticatie. Voorheen kon met --default-authentication-plugin=mysql_native_password terug gevallen worden op de oudere (en vervallen) manier van de opslag van het wachtwoord. Na een update naar 8.4 start de server hierna niet meer op. Gelukkig hebben de ontwikkelaars hier een nog wel een optie voor toegevoegd.

Als vervanger kan nu --mysql-native-password=ON gebruik worden. Na aanpassen van de aanroep, werkt alles weer zoals vanouds:

services:
  db8:
    image: "mysql:8"
    command: --mysql-native-password=ON --max_connections=999 --max-allowed-packet=96M --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --skip-log-bin
    restart: always
    cap_add:
     - sys_nice
    volumes:
     - ${DOCKER_DATAPATH}/mysql8:/var/lib/mysql

Remote Desktop macOS

30-12-2023
macOS remote desktop is niet zo flexibel als RDP van Windows, maar een aantal (nieuwe) opties zijn zeker werkbaar

Lokale LLM's draaien met het gemak van containers

28-11-2023
Ollama biedt functionaliteit zoals Docker, maar dan voor Large Language Model.

.Net 8.0 en andere sdk's op macOS via brew

20-11-2023
Mogelijkheid om toch meerdere .Net SDK's met gebruik van Brew als package manager.

NuGet package versies via Directory.Packages.props

29-09-2023
Versimpelt nuget versie beheer via ManagePackageVersionsCentrally en Directory.Packages.props

Disk quota volume voor Docker

16-09-2023
Docker heeft momenteel out of the box geen mogelijkheid om een quota in te stellen op een volume. Dit kan via een tmpfs, maar deze is niet persistent bij herstart. Dit is op te lossen met een disk image.

Interessante en gratis AI tools

30-01-2023
Korte lijst van interessante en soms gratis AI tools

Bash template

09-01-2023
De originele template die ik ooit ergens gevonden heb om mijn bash scripts van een aantal standaard variabelen te voorziet, bleek niet om te kunnen gaan met spaties in de directory namen. De oplossing was eenvoudig toe te passen.

iPhone 2Fa zonder app

15-02-2022
Tot mijn verbazing is het mogelijk om 2Fa te gebruiken zonder extra app met macOS, IOS en IpadOS.

.NET Everywhere - Windows, Linux, and Beyond - Het einde van System.Drawing is in zicht

14-11-2021
Met de komst van .Net 6 zijn de eerste stappen genomen om System.Drawing uit te faseren. Zo is deze libary nu als "Windows Only" gemarkeerd. Gelukkig zijn er alternatieven om bestaande code simpel aan te passen en toekomst zeker te maken.

Reset mysql root password in docker container

09-11-2021
In veel gevallen start ik MySql in Docker zo op, dat er een random root wachtwoord wordt aangemaakt. Dit is prima, mits je of het wachtwoord uit de logfile haalt. In het geval dat je deze niet hebt, kan je mogelijk in de problemen komen.

.Net XUnit test herkend geen actions

23-10-2021
Asp.Net Core XUnit unittest project herkend geen actions

ZFS dataset niet aanwezig na stroomonderbreking

20-09-2021
Nadat de spanning van een bepaalde machine per ongeluk uitgevallen was, starte een aantal Docker services op deze machine niet meer op. Het blijkt al snel dat Docker niet gestart is, oftewel niet heeft kunnen opstarten.

Zfs snapshot als standaard gebruiker

11-08-2021
Voeg rechten toe aan een gewone gebruiker om snapshots te maken

Net 5.0 service op MacOS

19-06-2021
Uitvoeren van een achtergrond service via Launchd op MacOS, gemaakt in DotNet Core

Opstarten nginx met ontbrekende (Docker) host

22-02-2020
Herstarten nginx zonder foutmelding als reverse proxy host ontbreekt

DotNet Core achtergrond service onder Linux

28-12-2019
Systemd service onder linux met dotnet core

Uitbreiden swap

15-12-2019
Meer virtueel geheugen toewijzen aan linux server

Verplaatsen van docker storage lokatie

05-09-2019
Verplaats docker data storage naar andere partitie

Testen verplaatsen Docker volume van Mailcow naar ZFS pool

06-05-2019
Na de installatie van Mailcow via Docker op een Linux productie server, blijkt dat de opslag van de mail data in een Docker volume staat, waardoor de root partitie van de server langzaam volloopt. Mailcow biedt een beschrijving om dit aan te passen.