Filtre actif, cliquez pour en enlever un tag :
Cliquez sur un tag pour affiner votre recherche :
Résultat de la recherche (59 notes) :
Journal du lundi 23 décembre 2024 à 19:39
J'ai commencé le Projet GH-271 - Installer Proxmox sur mon serveur NUC Intel i3-5010U, 8Go de Ram le 9 octobre.
Le 27 octobre, j'ai publié la note 2024-10-27_2109 qui contient une erreur qui m'a fait perdre 14h !
# virt-customize -a noble-server-cloudimg-amd64.img --install qemu-guest-agent --run-command 'systemctl enable qemu-guest-agent.service'
[ 0.0] Examining the guest ...
[ 4.5] Setting a random seed
virt-customize: warning: random seed could not be set for this type of
guest
[ 4.5] Setting the machine ID in /etc/machine-id
[ 4.5] Installing packages: qemu-guest-agent
[ 32.1] Running: systemctl enable qemu-guest-agent.service
[ 32.6] Finishing off
Je n'avais pas fait attention au message Setting the machine ID in /etc/machine-id
🙊.
Conséquence : le template Proxmox Ubuntu contenait un fichier /etc/machine-id
avec un id
.
Conséquence : toutes les Virtual machine que je créais sous Proxmox avaient la même valeur machine-id
.
J'ai découvert que l'option 61 "Client identifier" du protocole DHCP permet de passer un client id
au serveur DHCP qui sera utilisé à la place de l'adresse MAC.
Conséquence : le serveur DHCP assignait la même IP à ces Virtual machine.
J'ai pensé que le serveur DHCP de mon router BBox avait un problème. J'ai donc décidé d'installer Projet 15 - Installation et configuration de OpenWrt sur Xiaomi Mi Router 4A Gigabit pour avoir une meilleure maitrise du serveur DHCP.
Problème : j'ai fait face au même problème avec le serveur DHCP de OpenWrt.
Après quelques recherches, j'ai découvert que contrairement à virt-customize
la commande virt-sysprep
permet d'agir sur des images qui ont vocation à être clonées.
"Sysprep" stands for "system preparation" tool. The name comes from the Microsoft program sysprep.exe which is used to unconfigure Windows machines in preparation for cloning them.
Pour corriger le problème, j'ai remplacé cette ligne :
# virt-customize -a noble-server-cloudimg-amd64.img --install qemu-guest-agent --run-command 'systemctl enable qemu-guest-agent.service'
Par ces deux lignes :
# virt-sysprep -a noble-server-cloudimg-amd64.img --network --install qemu-guest-agent --run-command 'systemctl enable qemu-guest-agent.service'
# virt-sysprep --operation machine-id -a noble-server-cloudimg-amd64.img
La seconde commande permet de supprimer le fichier /etc/machine-id
, ce qui corrige le problème d'attribution d'IP par le serveur DHCP.
À noter que je ne comprends pas pourquoi il est nécessaire de lancer explicitement cette seconde commande, étant donné que la commande virt-sysprep
est destinée aux images de type "template". Le fichier /etc/machine-id
ne devrait jamais être créé, ou tout du moins, automatiquement supprimé à la fin de chaque utilisation de virt-sysprep.
Maintenant, l'instanciation de Virtual machine fonctionne bien, elles ont des IP différentes 🙂.
Prochaine étape du Projet GH-271 :
Je souhaite arrive à effectuer un déploiement d'une Virtual instance via cli de Terraform.
Journal du samedi 21 décembre 2024 à 16:10
Je viens d'améliorer l'implémentation du moteur de recherche de mon sklein-pkm-engine.
Voici un screencast de présentation du résultat :
Le commit de changement : https://github.com/stephane-klein/sklein-pkm-engine/commit/71210703fe626bd455b2ec7774167d9a637e4972
Je suis passé de :
query_string: {
query: queryString,
default_field: "content_html"
}
à ceci :
multi_match: {
query: queryString,
fields: ["title^2", "content_html"],
fuzziness: "AUTO",
type: "best_fields"
}
Les fonctionnalités de recherche d'Elasticsearch sont nombreuses. Pour les parcourir, je conseille ce point d'entrée de la documentation Search in Depth.
Même après avoir fini mon implémentation de la fonction recherche, je dois avouer que je tâtonne sur le sujet. Je suis loin de maitriser le sujet.
Au départ, après lecture de ce paragraphe :
If you don’t need to support a query syntax, consider using the
match
query. If you need the features of a query syntax, use thesimple_query_string
query, which is less strict.
J'ai fait un refactoring de query_string
vers simple_query_string
(lien vers la documentation).
Mon objectif était d'arriver à implémenter la fonctionnalité Query-Time Search-as-You-Type avec de la recherche floue (fuzzy).
J'ai commencé par essayer la syntax foobar~*
mais j'ai appris qu'il n'était pas possible d'utiliser ~
(fuzzy) en couplé avec *
😔 (documentation vers la syntax). Sans doute pour de bonnes raisons, liées à des problèmes de performance.
J'ai ensuite découpé ma requête en 3 conditions :
baseQuery.body.query.bool.must.push({
bool: {
should: [
{
simple_query_string: {
query: queryString,
fields: ["content_html"],
boost: 3
}
},
{
simple_query_string: {
query: queryString.split(' ').map(word => (word.length >= 3) ? `${word}*` : undefined).join(' ').trim(),
fields: ["content_html"],
boost: 1
}
},
{
simple_query_string: {
query: queryString.split(' ').map(
word => {
if (word.length >= 5) { return `${word}~2`; }
else if (word.length >= 3) { return `${word}~1`; }
else return undefined;
}
).join(' ').trim(),
fields: ["content_html"],
boost: 1
}
}
],
minimum_should_match: 1
}
}
Cette implémentation fonctionne, mais je rencontrais des problèmes de performance aléatoires que je n'ai pas pris le temps d'essayer de comprendre la cause.
À force de tâtonnement, j'ai fini par choisir la solution basée sur multi_match
(documentation de référence) :
multi_match: {
query: queryString,
fields: ["title^2", "content_html"],
fuzziness: "AUTO",
type: "best_fields"
}
Documentation de référence du paramètre fuzziness
: Fuzzy query.
Documentation de la valeur AUTO
: Common options - Fuzziness
Malheureusement, ici aussi, je ne peux pas utiliser fuzziness
avec phrase_prefix
:
The fuzziness parameter cannot be used with the phrase or phrase_prefix type.
En finissant cette note, je viens de découvrir cet exemple dans la documentation.
J'ai l'impression de comprendre qu'en utilisant le tokenizer ngram
je pourrais faire des Fuzzy Search sans utiliser l'option fuzziness
🤔.
J'ai commencé l'implémentation dans la branche ngram-tokenizer
mais je m'arrête là pour aujourd'hui. En tout, ce weekend, j'ai passé 4h30 sur ce sujet 😮.
J'espère tester cette implémentation d'ici à quelques jours.
Je souhaite aussi essayer prochainement de migrer de Elasticsearch vers OpenSearch.
Journal du samedi 21 décembre 2024 à 14:17
Je viens de corriger dans mon sklein-pkm-engine, un problème d'expérience utilisateur que m'avait remonté Alexandre sur la page détail d'une note.
Par exemple sur la note : https://notes.sklein.xyz/2024-12-19_1709/
Le lien sur le tag dev-kit
pointait vers https://notes.sklein.xyz/diaries/?tags=dev-kit
. Conséquence : les Evergreen Note n'étaient pas listés dans les résultats. Ce comportement était perturbant pour l'utilisateur.
J'ai modifié l'URL sur les tags pour les faire pointer vers https://notes.sklein.xyz/search/?tags=dev-kit
, page qui affiche tous types de notes.
Journal du samedi 07 décembre 2024 à 20:49
Je pense être arrivé à une solution plus ou moins satisfaisante pour le Projet 19 - "Documenter une méthode pour synchroniser un monorepo vers des multirepos qui fonctionne dans les deux sens".
Voici-ci, ci-dessous, les étapes de la démonstration qui sont détaillées dans le README.md
du repository poc-git-monorepo-multirepos-sync
.
- Je crée deux repositories :
frontend
etbackend
(multi repositories) ; - J'utilise le script tomono pour les intégrer dans un monorepo nommé
monorepo
; - J'ajoute deux fichiers à la racine de
monorepo
:README.md
et.mise.toml
; - J'effectue des changements dans le repository
frontend
, je commit ; - Je pull les changements du repository
frontend
versmonorepo
; - Dans
monorepo
, j'effectue des changements dans le dossierfrontend/
, je commit ; - J'utilise
cd frontend/; git format-patch --relative -1 HEAD
pour générer un patch qui contient les changements que j'ai effectués dans le dossierfrontend/
; - Je vais dans le repository
frontend
et j'applique les changements contenus dans ce patch avec la commandgit apply monpatch.patch
ou avecgit am monptach.patch
.
Pour le moment, j'ai privilégié l'option git patch, parce que je souhaite suivre la méthode la plus "manuelle" que j'ai pu trouver lorsque je dois intervenir sur les repositories upstream, parce que je ne veux prendre aucun risque de perturber mes collègues avec mon initiative de monorepo.
Le repository GitHub suivant contient le résultat final du monorepo : https://github.com/stephane-klein/poc-git-monorepo-multirepos-sync-result-example/.
Est-ce que je suis satisfait du résultat de cette démo ?
La réponse est oui, bien que je ne sois pas satisfait de quelques éléments.
Par exemple, les fichiers de frontend
présents dans ce commit ne sont pas dans le dossier frontend
.
J'aimerais que ces titres de commits contiennent un prefix [frontend] ...
et [backend]...
. Je pense que cela doit être possible à implémenter en modifiant le script tomono.
Est-ce que c'est pénible à utiliser ? Pour le moment, ma réponse est « je ne sais pas ».
Je vais tester cette méthode avec deux projets. Je pense écrire une note de bilan de cette expérience d'ici à quelques semaines.
Journal du mardi 03 décembre 2024 à 23:57
Suite de 2024-12-03_2213. J'ai réussi à implémenter le support Pandoc style markdown attributes dans sklein-pkm-engine.
Le package markdown-it-attrs
fonctionne parfaitement bien.
Par contre, le plugin markdown-attributes
semble ne pas fonctionner sur les dernières versions de Obsidian.
Journal du mardi 03 décembre 2024 à 22:13
Suite à 2024-11-13_2147, j'ai implémenté l'amélioration du rendu des "citations", voici un exemple :
Texte de la citation.
J'ai utilisé la librairie markdown-it-callouts
.
Par contre, l'implémentation actuelle contient un bug. Je souhaite appliquer ce style css uniquement au lien de la source de la citation :
Pour cela, j'aimerais pouvoir spécifier en markdown une classe source
sur le lien qui pointe vers la source de la citation.
J'ai trouvé markdown-it-attrs
qui me permettrait d'implémenter une syntax Pandoc-style markdown attributes :
> [!quote]
>
> Texte de la citation.
>
> [source](http://example.com){.source}
Le plugin Obsidian markdown-attributes
semble implémenter cette syntax.
Je souhaite tester si ce plugin fonctionne bien et si oui, je vais essayer d'intégrer markdown-it-attrs
dans sklein-pkm-engine.
Journal du jeudi 21 novembre 2024 à 17:36
Dans la note 2024-11-20_1102, je disais :
Prochaine étape du Projet 17 : Setup les iOS Requirements de Capacitor sur ce serveur Apple Silicon.
C'est chose faite 🙂.
Le repository poc-capacitor
contient maintenant un script ./scripts/deploy-ios-requirements.sh
qui permet d'exécuter ce script de provisioning sur le serveur Scaleway Apple Silicon distant : /provisioning/_ios.sh
.
Ensuite, j'ai détaillé les étapes pour :
- Uploader le projet sur le Scaleway Apple Silicon distant
- Démarrer l'émulation d'un iPhone 15
- Compiler et lancer l'application Capacitor dans l'émulateur iPhone 15
- Et visualiser l'émulateur via VNC
Tout cela est détaillé ici : https://github.com/stephane-klein/poc-capacitor/tree/f109fb23dc612f486fad0d55ba939b4679841d06?tab=readme-ov-file#launch-application-on-ios
Je teste l'offre Scaleway Apple Silicon
Dans le projet "Projet 17 - Créer un POC de création d'une app smartphone avec Capacitor" je disais :
- Essayer d'utiliser l'offre Apple Mac mini M1 de Scaleway pour builder l'app pour iOS
Voici mon retour d'expérience d'utilisation de l'offre Scaleway Apple Silicon.
Voici la liste des images MacOS disponibles :
$ scw apple-silicon os list
ID NAME LABEL IMAGE URL FAMILY IS BETA VERSION XCODE VERSION
59bf09f1-5584-469d-a0f6-55c8fee1ab81 macos-ventura-13.6 macOS Ventura 13.6 https://scw-apple-silicon.s3.fr-par.scw.cloud/scw-console/os/macos-ventura.png Ventura false 13.6 14
e08d1e5d-b4b9-402a-9f9a-97732d17e374 macos-sonoma-14.4 macOS Sonoma 14.4 https://scw-apple-silicon.s3.fr-par.scw.cloud/scw-console/os/macos-sonoma.png Sonoma false 14.4 15
7a8d85fb-781a-4212-8e47-240ec0c3d23f macos-sequoia-15.0 macOS Sequoia 15.0 https://scw-apple-silicon.s3.fr-par.scw.cloud/scw-console/os/macos-sequoia.png Sequoia true 15.0 16
Voici la liste des types de serveurs disponibles dans la zone fr-par-3
:
$ SCW_DEFAULT_ZONE="fr-par-3" scw apple-silicon server-type list
Name CPU Memory Disk Stock Minimum Lease Duration
M1-M Apple M1 (8 cores) 8.0 GB 256 GB high stock 1 days
Et la liste dans la zone fr-par-1
:
$ SCW_DEFAULT_ZONE="fr-par-1" scw apple-silicon server-type list
Name CPU Memory Disk Stock Minimum Lease Duration
M2-M Apple M2 (8 cores) 16 GB 256 GB high stock 1 days
M2-L Apple M2 Pro (10 cores) 16 GB 512 GB high stock 1 days
Je souhaite installer un serveur de type M1-M
à 0,11 € HT / heure, soit 2,64 € HT / jour, 80,3 € HT / mois.
Lors de ma première tentative, j'ai essayé de créer un serveur avec la commande suivante :
$ scw apple-silicon server create name=capacitor zone=fr-par-3 "$SCW_PROJECT_ID" M1-M 7a8d85fb-781a-4212-8e47-240ec0c3d23f
Invalid argument '46ad009f-xxxxxx': arg name must only contain lowercase letters, numbers or dashes
Suite à cette erreur, j'ai créé l'issue siuvante : Reduce"scw apple-silicon server create" helper message ambiguity.
$ scw apple-silicon server create name=capacitor project-id=${SCW_PROJECT_ID} type=M1-M os-id=7a8d85fb-781a-4212-8e47-240ec0c3d23f zone=fr-par-3
Mais l'OS n'était pas trouvé, je me suis rendu compte que cette image OS n'était pas disponible dans la zone fr-par-3
.
$ SCW_DEFAULT_ZONE="fr-par-3" scw apple-silicon os list
ID NAME LABEL IMAGE URL FAMILY IS BETA VERSION XCODE VERSION
59bf09f1-5584-469d-a0f6-55c8fee1ab81 macos-ventura-13.6 macOS Ventura 13.6 https://scw-apple-silicon.s3.fr-par.scw.cloud/scw-console/os/macos-ventura.png Ventura false 13.6 14
e08d1e5d-b4b9-402a-9f9a-97732d17e374 macos-sonoma-14.4 macOS Sonoma 14.4 https://scw-apple-silicon.s3.fr-par.scw.cloud/scw-console/os/macos-sonoma.png Sonoma false 14.4 15
Voici finalement la commande de création de serveur qui a fonctionné avec succès :
$ scw apple-silicon server create name=capacitor project-id=$SCW_PROJECT_ID type=M1-M os-id=e08d1e5d-b4b9-402a-9f9a-97732d17e374 zone=fr-par-3
ID bb34d8ef-6305-4104-801c-1cf1b6b0f99f
Type M1-M
Name capacitor
ProjectID 46ad009f-xxxx
OrganizationID 215d7434-xxxx
IP 51.xxx.xxx.xxx
VncURL vnc://m1:xxxx@51.xxx.xxx.121:5900
SSHUsername m1
SudoPassword xxxxxxx
Os ID e08d1e5d-b4b9-402a-9f9a-97732d17e374
Name macos-sonoma-14.4
Label macOS Sonoma 14.4
ImageURL https://scw-apple-silicon.s3.fr-par.scw.cloud/scw-console/os/macos-sonoma.png
Family Sonoma
IsBeta false
Version 14.4
XcodeVersion 15
CompatibleServerTypes:
[M1-M M2-M M2-L]
Status starting
CreatedAt now
UpdatedAt now
DeletableAt 23 hours from now
DeletionScheduled false
Zone fr-par-3
Voici le serveur créé :
$ scw apple-silicon server list
ID TYPE NAME PROJECT ID
bb34d8ef-6305-xxxxx M1-M capacitor 46ad009f-54bc-4125-xxxxxx
Le serveur est passé en ready
après environ 1min.
$ scw apple-silicon server get bb34d8ef-6305-xxxxxxx
...
CompatibleServerTypes:
[M1-M M2-M M2-L]
Status ready
...
DeletableAt 23 hours from now
DeletionScheduled false
...
Je peux me connecter directement en ssh au serveur :
$ ssh m1@xxx.xxx.xx.xxx
Last login: Wed Nov 20 16:22:10 2024
m1@bb34d8ef-6305-4104-801c-1cf1b6b0f99f ~ % uname -a
Darwin bb34d8ef-6305-4104-801c-1cf1b6b0f99f 23.4.0 Darwin Kernel Version 23.4.0: Fri Mar 15 00:12:41 PDT 2024; root:xnu-10063.101.17~1/RELEASE_ARM64_T8103 arm64
Je peux aussi me connecter au serveur via VNC (lien vers la documentation à ce sujet).
Installation des dépendances sous Fedora :
$ sudo dnf install -y remmina remmina-plugins-vnc
J'utilise le client VNC nommé Remmina.
$ remmina -c vnc://m1:xxxxx@51.xxxx.xxx.xxxx:5900
Les paramètres vnc
et le mot de passe de l'user m1
sont disponibles dans la sortie de :
$ scw apple-silicon server get bb34d8ef-6305-xxxxxxx -o json
{
"id": "bb34d8ef-6305-4104-xxxx-xxxxxxxxx",
...
"vnc_url": "vnc://m1:xxxx@xxx.xxx.xxx.xxx:5900",
"ssh_username": "m1",
"sudo_password": "bTgkdiVUs7yT",
...
}
Il est possible de coller le mot de passe via la fonctionnalité « Envoyer le contenu du presse-papiers comme une saisie au clavier » de Remmina :
Attention, la réinstallation d'un serveur Apple Silicon prend au moins 45min.
J'ai implémenté des scritps de déploiement d'un Apple Silicon dans le POC : poc-capacitor
.
Prochaine étape du Projet 17 : Setup les iOS Requirements de Capacitor sur ce serveur Apple Silicon.
Journal du mardi 19 novembre 2024 à 23:50
#iteration Projet 17 - Créer un POC de création d'une app smartphone avec Capacitor.
Dans la note 2024-11-19_1029, je disais :
Pour utiliser Capacitor, j'ai besoin d'installer certains éléments.
In order to develop Android applications using Capacitor, you will need two additional dependencies:
- Android Studio
- An Android SDK installation
Je me demande si Android Studio est optionnel ou non.
La réponse est non, Android Studio n'est pas nécessaire, ni pour compiler l'application, ni pour la lancer dans un émulateur Android. Android SDK est suffisant.
J'ai utilisé le plugin Mise https://github.com/Syquel/mise-android-sdk pour installer les "Android Requirements" de Capacitor. Les instructions détaillées pour Fedora sont listées dans le README.md du repository : https://github.com/stephane-klein/poc-capacitor/tree/4238e80f84a248fdb9e5bb86c10bea8b9f0fdade.
Installation de Android Studio sous Fedora
Dans le Projet 17 - Créer un POC de création d'une app smartphone avec Capacitor, il semble que j'ai besoin d'installer Android Studio.
J'ai exploré la méthode Asdf / Mise, mais j'ai rencontré des difficultés : 2024-11-19_1029 et 2024-11-19_1102.
J'ai ensuite constaté ici que RPM Fusion ne propose pas de package Android Studio. J'ai ensuite cherché sur Fedora COPR, mais j'ai trouvé uniquement de très vieux packages.
J'ai lu ici qu'Android Studio est disponible via Flatpak sur Flathub : https://flathub.org/apps/com.google.AndroidStudio. Je n'avais pas pensé à Flatpak 🙊.
Après réflexion, je trouve cela totalement logique que Android Studio soit distribué via Flatpak.
Voici le repository GitHub de ce package : https://github.com/flathub/com.google.AndroidStudio. Il semble être bien maintenu par Alessandro Scarozza « Senior Android Developer, Android Studio Flatpak Mantainer and old Debian Linux user ».
Le package contient la version 2024.2.1.11
d'Android Studio, j'ai vérifié, elle correspond bien à la dernière version disponible sur https://developer.android.com/studio.
Voici ce que donne l'installation :
$ flatpak install com.google.AndroidStudio
Looking for matches…
Remotes found with refs similar to ‘com.google.AndroidStudio’:
1) ‘flathub’ (system)
2) ‘flathub’ (user)
Which do you want to use (0 to abort)? [0-2]: 1
com.google.AndroidStudio permissions:
ipc network pulseaudio ssh-auth x11 devices multiarch file access [1]
dbus access [2]
[1] home
[2] com.canonical.AppMenu.Registrar, org.freedesktop.Notifications, org.freedesktop.secrets
ID Branch Op Remote Download
1. [✓] com.google.AndroidStudio.Locale stable i flathub 5,6 Ko / 57,2 Ko
2. [✓] com.google.AndroidStudio stable i flathub 1,3 Go / 1,3 Go
Installation complete.
Journal du mardi 19 novembre 2024 à 10:29
#iteration Projet 17 - Créer un POC de création d'une app smartphone avec Capacitor.
Pour utiliser Capacitor, j'ai besoin d'installer certains éléments.
In order to develop Android applications using Capacitor, you will need two additional dependencies:
- Android Studio
- An Android SDK installation
Je me demande si Android Studio est optionnel ou non.
J'aimerais installer ces deux services avec Mise.
J'ai trouvé des Asdf plugins pour Android SDK :
- https://github.com/Syquel/mise-android-sdk (créé le 2024-03-03)
- https://github.com/huffduff/asdf-android-sdk (créé le 2024-10-10)
- https://github.com/arcticShadow/asdf-android (créé le 2024-11-13)
#JeMeDemande quel plugin utiliser, quelles sont leurs différences.
Pour essayer d'avoir une réponse, j'ai posté les issues suivantes :
- What are the differences with other existing plugins?
- What are the differences with other existing plugins?
Alexandre m'a informé qu'il a utilisé avec succès le plugin https://github.com/Syquel/mise-android-sdk/, il a même créé une issue https://github.com/Syquel/mise-android-sdk/issues/10 qui a été traité 🙂.
La suite : 2024-11-19_1102.
Journal du mercredi 13 novembre 2024 à 21:47
Actuellement, dans sklein-pkm-engine, les "citations" sont affichées comme ceci :
Je souhaite modifier ce rendu pour réaliser quelque chose ressemblant à ceci :
Ma source d'inspiration est le blog de gwern.net.
gwern.net utilise la syntax de quote suivante (exemple) :
<div class="epigraph">
> Beware of bugs in the above code; I have only proved it correct, not tried it.
>
> [Donald Knuth](https://www-cs-faculty.stanford.edu/~knuth/faq.html)
</div>
Étant donné que j'édite notes.sklein.xyz avec Obsidian, je ne peux pas utiliser la même syntax.
En remplacement, je pense utiliser la syntax "Callouts", par exemple :
> [!quote]
>
> Beware of bugs in the above code; I have only proved it correct, not tried it.
>
> [Donald Knuth](https://www-cs-faculty.stanford.edu/~knuth/faq.html)
Qui donne le rendu suivant dans Obsidian :
#réflexion : j'ai l'intuition qu'à terme, une utilisation SilverBullet.mb à la place d'Obsidian m'offrirait bien plus de flexibilité.
Journal du dimanche 27 octobre 2024 à 21:09
Nouvelle #iteration du Projet GH-271 - Installer Proxmox sur mon serveur NUC Intel i3-5010U, 8Go de Ram.
J'ai eu des difficultés à trouver comment déployer avec Proxmox des Virtual instance basées sur Ubuntu Cloud Image.
J'ai trouvé réponse à mes questions dans cet article : "Perfect Proxmox Template with Cloud Image and Cloud Init".
Mais depuis, j'ai trouvé un meilleur tutoriel : "Linux VM Templates in Proxmox on EASY MODE using Prebuilt Cloud Init Images!".
Création d'un template Ubuntu LTS
J'ai exécuté les commandes suivantes en SSH sur mon serveur NUC i3 pour créer un template de VM Proxmox.
root@nuci3:~# apt update -y && apt install libguestfs-tools jq -y
root@nuci3:~# wget https://cloud-images.ubuntu.com/noble/current/noble-server-cloudimg-amd64.img
Ancienne commande qui contient une erreur à ne pas utilisé, plus d'information dans la note 2024-12-23_1939 :
root@nuci3:~# virt-customize -a noble-server-cloudimg-amd64.img --install qemu-guest-agent --run-command 'systemctl enable qemu-guest-agent.service'
root@nuci3:~# virt-sysprep -a noble-server-cloudimg-amd64.img --network --install qemu-guest-agent --run-command 'systemctl enable qemu-guest-agent.service'
root@nuci3:~# virt-sysprep --operation machine-id -a noble-server-cloudimg-amd64.img
root@nuci3:~# qm create 8000 --memory 2048 --core 2 --name ubuntu-cloud-template --net0 virtio,bridge=vmbr0
root@nuci3:~# qm disk import 8000 noble-server-cloudimg-amd64.img local-lvm
transferred 3.5 GiB of 3.5 GiB (100.00%)
transferred 3.5 GiB of 3.5 GiB (100.00%)
Successfully imported disk as 'unused0:local-lvm:vm-8000-disk-0'
root@nuci3:~# rm noble-server-cloudimg-amd64.img
root@nuci3:~# qm set 8000 --scsihw virtio-scsi-pci --scsi0 local-lvm:vm-8000-disk-0
update VM 8000: -scsi0 local-lvm:vm-8000-disk-0 -scsihw virtio-scsi-pci
root@nuci3:~# qm set 8000 --ide2 local-lvm:cloudinit
update VM 8000: -ide2 local:cloudinit
Formatting '/var/lib/vz/images/8000/vm-8000-cloudinit.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off preallocation=metadata compression_type=zlib size=4194304 lazy_refcounts=off refcount_bits=16
ide2: successfully created disk 'local:8000/vm-8000-cloudinit.qcow2,media=cdrom'
generating cloud-init ISO
(liste des paramètres cloud-init
)
root@nuci3:~# qm set 8000 --ipconfig0 "ip6=auto,ip=dhcp"
root@nuci3:~# qm set 8000 --sshkeys ~/.ssh/authorized_keys
root@nuci3:~# qm set 8000 --ciuser stephane
root@nuci3:~# qm set 8000 --cipassword password # optionnel, seulement en phase de debug
root@nuci3:~# qm set 8000 --boot c --bootdisk scsi0
update VM 8000: -boot c -bootdisk scsi0
root@nuci3:~# qm set 8000 --serial0 socket --vga serial0
update VM 8000: -serial0 socket -vga serial0
root@nuci3:~# qm set 8000 --agent enabled=1
root@nuci3:~# qm set 8000 --ciupgrade 0
root@nuci3:~# qm template 8000
Renamed "vm-8000-disk-0" to "base-8000-disk-0" in volume group "pve"
Logical volume pve/base-8000-disk-0 changed.
WARNING: Combining activation change with other commands is not advised.
Création d'une Virtual Instance
root@nuci3:~# qm clone 8000 100 --name server1
root@nuci3:~# qm start 100
root@nuci3:~# qm guest cmd 100 network-get-interfaces | jq -r '.[] | select(.name == "eth0") | .["ip-addresses"][0] | .["ip-address"]'
192.168.1.64
$ ssh stephane@192.168.1.64
The authenticity of host '192.168.1.64 (192.168.1.64)' can't be established.
ED25519 key fingerprint is SHA256:OJHcY3GHOsm3I4qcsYFc6V4qePNxVS4iAOBsDjeLM7o.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '192.168.1.64' (ED25519) to the list of known hosts.
Welcome to Ubuntu 24.04.1 LTS (GNU/Linux 6.8.0-45-generic x86_64)
...
Journal du dimanche 20 octobre 2024 à 22:50
Nouvelle #iteration du Projet 14 - Script de base d'installation d'un serveur Ubuntu LTS.
Il y a quelques jours, j'ai migré de vagrant-hostmanger vers vagrant-dns. J'ai ensuite souhaité mettre en œuvre Grizzly, mais j'ai rencontré un problème.
J'ai installé une version binaire statiquement liée de Grizzly à l'aide de Mise. Dans cette version, Go ne fait pas appel à la fonction getaddrinfo pour la résolution des noms d'hôte. Au lieu de cela, Go se limite à lire les informations de configuration DNS dans /etc/resolv.conf
(champ nameserver
) et les entrées de /etc/hosts
.
Cela signifie que les serveurs DNS gérés par systemd-resolved ne sont pas pris en compte 😭.
Pour régler ce problème, j'utilise en même temps vagrant-dns et Vagrant Host Manager : voici le commit.
J'active uniquement ici le paramètre config.hostmanager.manage_host = true
et je laisse vagrant-dns résoudre les hostnames à l'intérieur des machines virtuelles et des containers Docker.
Journal du vendredi 18 octobre 2024 à 19:15
Nouvelle #iteration de Projet 14.
Pour traiter ce problème, je souhaite essayer de remplacer Vagrant Host Manager par vagrant-dns.
-- from
Résultat : j'ai migré de Vagrant Host Manager vers vagrant-dns avec succès 🙂.
Voici le commit : lien vers le commit.
Voici quelques explications de la configuration Vagrantfile.
Les lignes suivantes permettent d'utiliser la seconde IP des machines virtuelles pour identifier les identifier (renseignés par le serveur DNS).
config.dns.ip = -> (vm, opts) do
ip = nil
vm.communicate.execute("hostname -I | cut -d ' ' -f 2") do |type, data|
ip = data.strip if type == :stdout
end
ip
end
La commande hostname
retourne les deux IP de la machine virtuelle :
vagrant@server1:~$ hostname -I
10.0.2.15 192.168.56.22
La commande hostname -I | cut -d ' ' -f 2
capture la seconde IP, ici 192.168.56.22
.
La configuration DNS qui retourne cette IP est consultable via :
$ vagrant dns -l
/server1.vagrant.test/ => 192.168.56.22
/server2.vagrant.test/ => 192.168.56.23
/grafana.vagrant.test/ => 192.168.56.23
/loki.vagrant.test/ => 192.168.56.23
vb.customize ["modifyvm", :id, "--natdnshostresolver1", "on"]
Cette ligne configure la machine virtuelle pour qu'elle utilise le serveur DNS de vagrant-dns.
Cela permet de résoudre les noms des autres machines virtuelles. Exemple :
vagrant@server1:~$ resolvectl query server2.vagrant.test
server2.vagrant.test: 192.168.56.23 -- link: eth0
-- Information acquired via protocol DNS in 12.3ms.
-- Data is authenticated: no; Data was acquired via local or encrypted transport: no
-- Data from: network
En mettant en place vagrant-dns sur ma workstation qui tourne sous Fedora, j'ai rencontré la difficulté suivante.
J'avais la configuration suivante installée :
$ cat /etc/systemd/resolved.conf.d/csd.conf
[Resolve]
DNS=10.57.40.1
Domains=~csd
Elle me permet de résoudre les hostnames des machines qui appartiennent à un réseau privé exposé via OpenVPN (voir cette note).
Voici ma configuration complète de systemd-resolved
:
$ systemd-analyze cat-config systemd/resolved.conf
# /etc/systemd/resolved.conf
...
[Resolve]
...
# /etc/systemd/resolved.conf.d/1-vagrant-dns.conf
# This file is generated by vagrant-dns
[Resolve]
DNS=127.0.0.1:5300
Domains=~test
# /etc/systemd/resolved.conf.d/csd.conf
[Resolve]
DNS=10.57.40.1
Domains=~csd
Quand je lançais resolvectl query server2.vagrant.test
pour la première fois après redémarrage de sudo systemctl restart systemd-resolved
, tout fonctionnait correctement :
$ resolvectl query server2.vagrant.test
server2.vagrant.test: 192.168.56.23
-- Information acquired via protocol DNS in 7.5073s.
-- Data is authenticated: no; Data was acquired via local or encrypted transport: no
-- Data from: network
Mais, la seconde fois, j'avais l'erreur suivante :
$ resolvectl query server2.vagrant.test
server2.vagrant.test: Name 'server2.vagrant.test' not found
Ce problème disparait si je supprime /etc/systemd/resolved.conf.d/csd.conf
.
Je n'ai pas compris pourquoi. D'après la section "Protocols and routing" de systemd-resolved, le serveur 10.57.40.1
est utilisé seulement pour les hostnames qui se terminent par .csd
.
J'ai activé les logs de systemd-resolved au niveau debug
avec
$ sudo resolvectl log-level debug
$ journalctl -u systemd-resolved -f
Voici le contenu des logs lors de la première exécution de resolvectl query server2.vagrant.test
: https://gist.github.com/stephane-klein/506a9fc7d740dc4892e88bfc590bee98.
Voici le contenu des logs lors de la seconde exécution de resolvectl query server2.vagrant.test
: https://gist.github.com/stephane-klein/956befc280ef9738bfe48cdf7f5ef930.
J'ai l'impression que la ligne 13 indique que le cache de systemd-resolved a été utilisé et qu'il n'a pas trouvé de réponse pour server2.vagrant.test
. Pourquoi ? Je ne sais pas.
Ligne 13 : NXDOMAIN cache hit for server2.vagrant.test IN A
Ensuite, je supprime /etc/systemd/resolved.conf.d/csd.conf
:
$ sudo rm /etc/systemd/resolved.conf.d/csd.conf
Je relance systemd-resolved et voici le contenu des logs lors de la seconde exécution de resolvectl query server2.vagrant.test
: https://gist.github.com/stephane-klein/9f87050524048ecf9766f9c97b789123#file-systemd-resolved-log-L11
Je constate que cette fois, la ligne 11 contient : Cache miss for server2.vagrant.test IN A
.
Pourquoi avec .csd
le cache retourne NXDOMAIN
et sans .csd
, le cache retourne Cache miss
et systemd-resolved continue son algorithme de résosultion du hostname ?
Je soupçonne systemd-resolved de stocker en cache la résolution de server2.vagrant.test
par le serveur DNS 10.57.40.1
. Si c'est le cas, je me demande pourquoi il fait cela alors qu'il est configuré pour les hostnames qui se terminent par .csd
🤔.
Autre problème rencontré, la latence de réponse :
$ resolvectl query server2.vagrant.test
server2.vagrant.test: 192.168.56.23
-- Information acquired via protocol DNS in 7.5073s.
-- Data is authenticated: no; Data was acquired via local or encrypted transport: no
-- Data from: network
La réponse est retournée en 7 secondes, ce qui ne me semble pas normal.
J'ai découvert que je n'ai plus aucune latence si je passe le paramètre DNSStubListener
à no
:
$ sudo cat <<EOF > /etc/systemd/resolved.conf.d/0-vagrant-dns.conf
[Resolve]
DNSStubListener=no
EOF
$ sudo systemctl restart systemd-resolved
$ resolvectl query server2.vagrant.test
server2.vagrant.test: 192.168.56.23
-- Information acquired via protocol DNS in 2.9ms.
-- Data is authenticated: no; Data was acquired via local or encrypted transport: no
-- Data from: network
Le temps de réponse passe de 7.5s
à 2.9ms
. Je n'ai pas compris la signification de ma modification.
Je récapitule, pour faire fonctionner correctement vagrant-dns sur ma workstation Fedora j'ai dû :
- supprimer
/etc/systemd/resolved.conf.d/csd.conf
- et paramétrer
DNSStubListener
àno
Journal du lundi 14 octobre 2024 à 11:23
J'ai commencé le projet Projet 14 - Script de base d'installation d'un serveur Ubuntu LTS.
Journal du mercredi 09 octobre 2024 à 23:52
#iteration Projet GH-271 - Installer Proxmox sur mon serveur NUC Intel i3-5010U, 8Go de Ram.
J'ai installé avec succès la version 8.2.2
de Proxmox sur mon Serveur NUC i3.
J'ai copié l'image ISO de Proxmox sur une clé USB.
J'ai branché un clavier et un moniteur sur mon Serveur NUC i3 et j'ai suivi la procédure d'installation sans rencontrer de difficulté.
Je peux me connecter au serveur via l'interface web de Proxmox ou directement via ssh.
Prochaine étape : déployer une Virtual instance Ubuntu LTS.
Journal du mercredi 02 octobre 2024 à 18:07
Nouvelle #iteration du Projet 11 - "Première version d'un moteur web PKM".
J'ai traité les tâches décrites dans ma dernière note.
- Comme me l'a signalé à plusieurs reprises Alexandre, je dois améliorer le rendu responsive sur smartphone. Jusqu'à présent, je n'ai pas encore consacré de temps à ce sujet.
- Je dois améliorer le script d'import des données dans Elasticsearch. Pour le moment, ici, je commence par supprimer toutes les données avant d'effectuer l'importation des données.
Problème : les pages ne sont plus accessibles pendant l'exécution de ce script.
J'ai enfin publié sklein-pkm-engine sur https://notes.sklein.xyz.
En mars 2024, j'écrivais :
Pour le moment, j'utilise Obsidian Quartz pour déployer https://notes.sklein.xyz.
Est-ce que j'en suis satisfait ? Pour le moment, la réponse est non, parce que je ne le maitrise pas assez.
J'ai une grande envie d'implémenter une version personnelle basée sur SvelteKit et Apache Age, mais j'essaie de ne pas tomber dans ce Yak!.
Début mai 2024, je suis tombé dans ce Yak!, j'y ai consacré 93 heures en tout, soit l'équivalent d'environ 15 jours de travail étalés sur 8 semaines.
J'ai enfin supprimé Obsidian Quartz
J'ai changé plusieurs fois de direction :
- j'ai exploré une implémentation basée sur Apache Age,
- ensuite pg_search,
- ensuite Typesense
- et pour finir, j'ai opté pour une implémentation basée sur Elasticsearch (voir détail dans Projet 13).
Je viens d'essayer de réaliser un screencast de présentation de la version actuelle de sklein-pkm-engine, mais le résultat de mon discours était vraiment trop déstructuré pour être publié. J'essaierai de publier un screencast prochainement.
Je viens de tenter de réaliser un screencast pour présenter la version actuelle de sklein-pkm-engine, mais mon discours était trop désorganisé pour être publié. Je souhaite enregistrer une nouvelle version prochainement.
Prochains objectifs concernant le projet sklein-pkm-engine :
- Traiter les dernières tâches que j'avais listées dans Projet 11 - "Première version d'un moteur web PKM" ;
- Dresser une liste des corrections de bug et des améliorations que je souhaite apporter à notes.sklein.xyz.
Journal du mardi 01 octobre 2024 à 11:55
Nouvelle #iteration du Projet 11 - "Première version d'un moteur web PKM".
Dans ma dernière itération du 31 août 2024, j'écrivais ceci :
Voici quelque erreur d'User Interface que je souhaite corriger.
Sur ce screenshot, les notes actuellement séparé par des
<hr />
ne sont pas facilement identifiable.
Depuis, j'ai travaillé dans la branche experimentation-ui
et pour le moment, j'ai le résultat suivant :
Je pense que les délimitations des notes sont maintenant mieux identifiables.
Problème User Interface que j'ai identifié : je pense que la présence d'un lien sur le titre de la note n'est pas facilement "découvrable".
Mon objectif est toujours le suivant :
Maintenant mon objectif est d'apporter le minimum de petite amélioration me permettant de remplacer l'instance notes.sklein.xyz propulsé actuellement par Obsidian Quartz par une version propulsé par
sklein-pkm-engine
.-- from
Voici la liste des choses que je dois implémenter pour atteindre cet objectif.
- Comme me l'a signalé à plusieurs reprises Alexandre, je dois améliorer le rendu responsive sur smartphone. Jusqu'à présent, je n'ai pas encore consacré de temps à ce sujet.
- Je dois améliorer le script d'import des données dans Elasticsearch. Pour le moment, ici, je commence par supprimer toutes les données avant d'effectuer l'importation des données.
Problème : les pages ne sont plus accessibles pendant l'exécution de ce script.
Je pense qu'après avoir traité ces deux tâches, je pourrais abandonner Obsidian Quartz et seulement ensuite implémenter toutes les idées pour améliorer mon Personal knowledge management "viewer".
Journal du mardi 24 septembre 2024 à 17:41
gibbon-replay n'enregistre pas les sessions de Safari sous MacOS et iOS.
En analysant le problème, j'ai découvert le message d'erreur suivant :
Beacon API cannot load ... Reached maximum amount of queued data of 64Kb for keepalive requests
Je n'ai trouvé la limitation de 64Kb ni dans https://www.w3.org/TR/beacon/, ni dans https://developer.mozilla.org/en-US/docs/Web/API/Navigator/sendBeacon.
Cela semble être une spécificité de Safari.
#JaiDécouvert que posthog-js utilise fflate pour compresser les données. La compression a été ajoutée en décembre 2020, dans cette Merge Request : Compress events using fflate (gzip-js).
Ce que je compte faire pour corriger le bug que j'ai sous Safari :
- Si les données à envoyer ont une taille supérieure à 50ko, alors utiliser
fetch
sinon utilisersendBeacon
; - Utiliser fflate pour compresser les données.
Journal du jeudi 29 août 2024 à 13:23
Voici les nouveautés depuis ma dernière itération du Projet 11 - "Première version d'un moteur web PKM".
Ce commit contient le résultat du travail du Projet 13, c'est-à-dire le refactoring de PostgreSQL vers Elasticsearch ainsi que la page /src/routes/search
qui permet à la fois d'effectuer une recherche sur le contenu des notes et un filtrage de type and
sur les tags.
Une démo est visible ici https://notes.develop.sklein.xyz/
Ma Developer eXperience avec Elasticsearch est excellente. J'ai trouvé toutes les fonctionnalités dont j'avais besoin.
Je pense que mon utilisation des Fleeting Note n'est pas la bonne. Je pense que les notes que je qualifie de Fleeting Note sont en réalité des Diary notes ou Journal notes.
J'ai donc décidé de :
- [x] Renommer partout
fleeting_note
enjournal_notes
Après implémentation, j'ai réalisé que j'ai fait l'erreur de mélanger l'implémentation de le page qui affiche la liste des notes antéchronologiques et la page de recherche.
Pour être efficace, le résultat de la page recherche doit être affiché en fonction du scoring de la recherche, alors que les pages listes de notes par date de publication.
J'ai donc décidé de :
- [x] Implémenter une page
/diaries/
(pour la cohérence des path en anglais, je préfère "diaries" à "journaux") qui affiche une liste de notes de type Diary notes ;- [x] Cette page doit permettre un filtrage par tags
- [x] Implémenter une page
/notes/
qui affiche une liste des notes qui ne sont pas de type Diary notes, comme des Evergreen Note, Hub note…- [x] Contrairement à la page liste des Diary notes, cette page de liste ne doit pas afficher le contenu des notes, mais seulement le titre des notes ;
- [x] Je propose de classer ces titres de notes par ordre alphabétique ;
- [x] Je propose aussi de séparer ces notes par lettre,
A
,B
… c'est-à-dire un index alphabétique. - [x] Cette page doit permettre un filtrage par tags
- [x] Refactoring la page
/search/
pour ordonner le résultat de la recherche par scoring.- [x] Cette page doit afficher le contenu des notes avec highligthing ;
- [x] Cette page doit permettre un filtrage sur les types de notes, pour le moment Diary notes et Evergreen Note.
- [x] Cette page doit permettre un filtrage par tags
Au moment où j'écris ces lignes, je ne sais pas encore comment je vais gérer les opérateurs or
, (
.
Pour le moment, le filtrage multi tags est effectué avec des and
.
Journal du jeudi 15 août 2024 à 16:00
#iteration Projet 11 - "Première version d'un moteur web PKM".
Le nombre de tags listé sur ce screenshot est limité par un flex-wrap: wrap
+ height: 2em
+ overflow: hidden
.
Problème : j'aimerais que le bouton "Afficher plus de tags…" soit affiché directement à droite du dernier tag (ici "Svelte").
Je souhaite limiter le nombre de tags affiché non pas via du css (overflow: hidden
), mais via une action Svelte.
J'aimerais pouvoir utiliser cette svelte/action
comme ceci :
<ul use:ItemOverflowLimiter={{itemClass: "tag"}}>
{#each data.tags as tag}
<li class="tag">
<a
href={`/search/?tags=${tag.name}`}
>{tag.name} ({tag.note_counts})</a>
</li>
{/each}
<li>Afficher plus de tags…</li>
</ul>
1 heure plus tard, j'ai réussi à atteindre mon objectif avec ce commit.
Voici le résulat 🙂 :
Voici le code de la fonction svelte/action
ItemOverflowLimiter.js :
export default function ItemOverflowLimiter(node, options) {
let destroyAllNextItems = false;
let itemsToDestroy = [];
// search width of items to keep
let widthItemsToKeep = 0;
for (let item of node.children) {
if (
(options?.itemClass) &&
(!item.classList.contains(options.itemClass))
) {
widthItemsToKeep += item.clientWidth;
}
}
for (let item of node.children) {
if (destroyAllNextItems) {
if (
(!options?.itemClass) ||
(item.classList.contains(options.itemClass))
) {
itemsToDestroy.push(item);
}
} else if (
(item.offsetTop > 0) ||
(item.offsetLeft + item.clientWidth > (node.clientWidth - widthItemsToKeep))
) {
itemsToDestroy.push(item);
destroyAllNextItems = true;
}
}
for (let item of itemsToDestroy) {
item.remove();
}
}
Je trouve les svelte/action
très agréable à utiliser.
Journal du jeudi 15 août 2024 à 10:48
Nouvelle #iteration de Projet 11 - "Première version d'un moteur web PKM".
En haut de cette page, j'aimerais afficher quelques tags.
En peu de la même manière que sur ce site :
Dans cette #iteration , j'affiche tous les tags, mais la liste est trop longue.
Sur ce screenshot, seules les deux premières lignes de tags sont affichées avec un fondu transparent sur la seconde ligne.
Je ne suis pas convaincu de la pertinence du fondu transparent.
Je pense que cela attire le regard d'une manière excessif sur un élément d'UI secondaire.
Je pense qu'il est préférable d'afficher une seule ligne 🤔.
Je pense ajouter à la fin d'un tags un élément UX inspiré par :
Journal du mardi 13 août 2024 à 21:32
#iteration du Projet GH-382 - Je cherche à convertir en SQL des query de filtre basé sur un système de "tags".
J'ai enfin analysé la Merge Request qui m'a été envoyé par un ami 🤗 : https://github.com/stephane-klein/postgres-tags-model-poc/pull/9
6 mois plus tard, j'ai fini l'implémentation de la première version du "Query string javascript parser" : https://github.com/stephane-klein/postgres-tags-model-poc/commit/f0f363b78c136e8e67a38f95b5c627d874537949
Pour la coloration syntaxique des fichiers Peggy sous Neovim, j'utilise avec succès https://github.com/TheGrandmother/peggy-vim : https://github.com/stephane-klein/dotfiles/commit/20cba4ba646a0793f66f9b19788920a4ff1f1838
Journal du jeudi 08 août 2024 à 17:22
Après 11h48 de travail, j'ai enfin réussi à achever mon Projet 8 - "CodeMirror, conceal, Svelte".
Consultez de détailler dans le README du repository : https://github.com/stephane-klein/svelte-codemirror-conceal-poc.
Journal du dimanche 28 juillet 2024 à 11:59
Nouvelle #iteration du Projet 11 - "Première version d'un moteur web PKM".
Voici ce que j'ai implémenté dans la sklein-pkm-engine
(lien vers la version du 28 juillet 2024, 12h00) :
- [x] Implémentation d'un script qui injecte des nanoid dans le frontmatter de toutes les notes ;
- [x] Implémentation d'un script qui injecte
type: fleeting_note
dans toutes les notes qui se trouvent dans le dossier/Notes éphémères/
; - [x] Implémentation d'un script qui injecte
type: evergreen_note
à toutes les notes sanstype
; - [x] Implémentation d'un script qui injecte
created_at: ISO 8601
sur les Fleeting Note ; - [x]
/{note_filename}/
(sans.md
) affiche une seule Fleeting Note ; - [x]
/
liste de toutes les Fleeting Note de la plus récente à la plus ancienne ; - [x] Afficher les Fleeting Note liées aux Evergreen Note en bas des Evergreen Note ;
- [x] Rendering des
WikiLink
; - [x] Rendering des
#tags
; - [x] Support des fichiers binaires (image…)
J'ai déployé cette projet sur https://notes.develop.sklein.xyz/.
Voici à quoi cela ressemble :
Prochaines itérations :
- [ ] Activer l'attribue
loading="lazy"
sur les images ; - [ ] Ajouter de la pagination sur
/
; - [ ] Rendering markdown :
- [ ] Rendering des simples liens;
- [ ] Rendering des codes sources.
- [ ]
/tags/{tag_name}/
; - [ ] Affichage des tags derrière l'heure : ;
- [ ] Permettre de remplacer les tages du type
JaiDécouvert
parJ'ai découvert
pour simplifier la lecture.
Journal du vendredi 19 juillet 2024 à 23:16
Pour la génération de nanoid du Projet 11, j'ai choisi les paramètres suivants :
const nanoid = customAlphabet('0123456789abcdefghijklmnopqrstuvwxyz', 12);
D'après les calculs effectués sur https://zelark.github.io/nano-id-cc/, à raison de 100 nouvelles notes par jour (ce qui est irréaliste), sur 352 années, le risque de doublon d'id est de 1%, ce qui est largement acceptable 😉.
Journal du mardi 16 juillet 2024 à 09:57
Suite de 2024-07-14_1211 en lien avec Projet 5 - "Importation d'un vault Obsidian vers Apache Age".
- Extraction des tags présents dans le corps des notes.
C'est fait 🙂 : Extract tags from note bodies to create and associate them with the note
- Implémentation d'une fonction qui transforme le corps markdown d'une note en HTML avec les bons liens HTML vers les tags et autres notes.
C'est fait 🙂 : Implementation of a markdown-to-html rendering function that takes tags and wikilinks into account
J’ai préparé une première ébauche, mais étant incertain de la manière dont je vais intégrer cette fonctionnalité avec pg_search ou Typesense, j’ai décidé de ne pas continuer à la développer pour le moment : Implementation of a function that transforms markdown content into plain text.
Journal du lundi 15 juillet 2024 à 15:25
Suite de 2024-07-14_1211 en lien avec Projet 5 - "Importation d'un vault Obsidian vers Apache Age".
Pour résoudre ce problème, j'ai décidé de :
- Créer un repository GitHub nommé
obsidian-vault-to-pg_search
.- Créer un repository GitHub nommé
obsidian-vault-to-typesense
.- Supprimer les intégrations pg_search et Typesense de
obsidian-vault-to-apache-age-poc
C'est fait 🙂.
Après cela, je souhaite implémenter dans
obsidian-vault-to-apache-age-poc
les fonctionnalités suivantes :
- Création des liaisons entre les notes basées sur les wikilink (
[[Internal links]]
).
C'est implémenté par ce commit 🙂.
Je ne suis pas satisfait de l'implémentation de cette partie et celle-ci.
Journal du dimanche 14 juillet 2024 à 12:11
Avec l'intégration de pg_search et Typesense, j'ai bien conscience de m'être un peu perdu dans Projet 5 - "Importation d'un vault Obsidian vers Apache Age".
Pour résoudre ce problème, j'ai décidé de :
- Créer un repository GitHub nommé
obsidian-vault-to-pg_search
. - Créer un repository GitHub nommé
obsidian-vault-to-typesense
. - Supprimer les intégrations pg_search et Typesense de
obsidian-vault-to-apache-age-poc
.
Après cela, je souhaite implémenter dans obsidian-vault-to-apache-age-poc
les fonctionnalités suivantes :
- Création des liaisons entre les notes basées sur les wikilink (
[[Internal links]]
). - Extraction des tags présents dans le corps des notes.
- Implémentation d'une fonction qui transforme le corps markdown d'une note en HTML avec les bons liens HTML vers les tags et autres notes.
- Implémentation d'une fonction qui transforme le corps markdown d'une note en texte brut, sans lien, destiné à être injecté dans un moteur de recherche comme pg_search ou Typesense.
Après avoir traité ces tâches, je souhaite travailler sur un moteur de rendu HTML basé sur SvelteKit, obsidian-vault-to-apache-age-poc
et sans doute obsidian-vault-to-typesense
.
Journal du dimanche 14 juillet 2024 à 10:26
Nouvelle #iteration du Projet 5 - "Importation d'un vault Obsidian vers Apache Age".
Dans 2024-07-10_0941 je disais :
je souhaite tester l'intégration de Typesense à
obsidian-vault-to-apache-age-poc
en complément de pg_search.
Voici un screencast du résulat de cette implémentation de InstantSearch connecté à Typesense :
Journal du mercredi 10 juillet 2024 à 09:41
Suite à 2024-07-09_0846 (Projet 5) et suite à la publication de poc-meilisearch-blog-sveltekit
en 2023, je souhaite tester l'intégration de Typesense à obsidian-vault-to-apache-age-poc
en complément de pg_search.
J'ai bien conscience que Typesense fait doublon avec pg_search, mais mon objectif dans ce projet est de comparer les résultats de Typesense avec ceux de pg_search.
J'espère que cet environnement de travail me permettra d'itérer afin de répondre à cette question.
Idéalement, j'aimerais uniquement utiliser pg_search afin de mettre en œuvre un seul serveur de base de données et de bénéficier de la mise à jour automatique de l'index du moteur de recherche :
A BM25 index must be created over a table before it can be searched. This index is strongly consistent, which means that new data is immediately searchable across all connections. Once an index is created, it automatically stays in sync with the underlying table as the data changes. (from)
Journal du mardi 09 juillet 2024 à 08:46
Dans le cadre de mon travail sur Projet 5 - "Importation d'un vault Obsidian vers Apache Age" et plus précisément, ma tentative d'utiliser pg_search pour y intégrer un moteur de recherche, j'ai creusé le sujet InstantSearch.
Typesense permet d'utiliser InstantSearch via un adaptateur :
At Typesense, we've built an adapter (opens new window) that lets you use the same Instantsearch widgets as is, but send the queries to Typesense instead. (from)
Ici j'ai découvert des alternatives à InstantSearch :
- typesense-minibar
- autocomplete (aussi créé par Algolia)
- docsearch (aussi créé par Algolia)
#JeMeDemande comment utiliser InstantSearch ou TypeSense-Minibar avec pg_search.
N'ayant pas trouvé de réponse, #JaiPublié How can I implement InstantSearch, Typesense-Minibar or Docsearch with pg_search?.
Journal du lundi 08 juillet 2024 à 09:38
#iteration sur le Projet 10 - "Mettre en oeuvre DotTXT AI".
#JeMeDemande quelles sont les projets alternatif à Outlines 🤔
J'ai trouvé :
- https://github.com/sgl-project/sglang (from)
- https://github.com/guidance-ai/guidance (from)
- https://github.com/eth-sri/lmql (from)
- https://python.langchain.com/v0.1/docs/modules/model_io/output_parsers/types/pydantic/ (from)
- https://github.com/ggerganov/llama.cpp/blob/master/grammars/README.md (from)
Journal du dimanche 07 juillet 2024 à 15:59
#iteration sur le Projet 10 - "Mettre en oeuvre DotTXT AI".
16:00
#JeLis Coding For Structured Generation with LLMs
For those new to the blog: structured generation using Outlines (and soon .txt's products!) (from)
Je comprends que https://github.com/outlines-dev/outlines est simplement le repository du futur produit dottxt.
Je pense comprendre que structured generation est le nom officiel de l'objectif de l'outil dottxt.
16:23
#JeMeDemande comment utiliser outlines avec Replicate.com 🤔.
16:31
#JeMeDemande comment utiliser outlines avec Replicate.com 🤔.
Je pense avoir ma réponse ici.
16:47
#JaiPosté How to use outlines with Replicate.com?
J'ai aussi posé la question sur https://replicate.com/support
Journal du samedi 06 juillet 2024 à 15:15
#iteration du Projet 5 - "Importation d'un vault Obsidian vers Apache Age" et plus précisément la suite de 2024-06-20_2211, 2024-06-23_1057 et 2024-06-23_2222.
Pour le projet obsidian-vault-to-apache-age-poc
je souhaite créer une image Docker qui intègre les extensions pg_search et Apache Age à une image PostgreSQL.
Pour réaliser cela, je vais me baser sur ce travail préliminaire https://github.com/stephane-klein/pg_search_docker.
#JaiDécidé de créer un repository GitHub nommé apache-age-docker
, qui contiendra un Dockerfile pour builder une image Docker PostgreSQL 16 qui intègre la release "Release v1.5.0 for PG16" de l'extension Postgres Apage Age.
Journal du samedi 06 juillet 2024 à 11:16
Je pense avoir terminé le projet Projet 7 - "Améliorer et mettre à jour le projet restic-pg_dump-docker".
Merci à Alexandre pour ses commits de GitHub Actions CI/CD et du support multi architectures publié sur Docker Hub : # stephaneklein/restic-pg_dump
.
Je suis assez satisfait du résultat. Le projet a été réalisé avec soin et j'ai tenté de le simplifier au maximum.
Il reste cependant une dernière possibilité de simplification à implémenter : Suggestion : Remplacer Supercronic par Cronie.
Bilan du temps passé sur le Projet 7 :
- 8 sessions de travail entre le 5 juin et le 6 juillet 2024 ;
- Pour un total de 10h16.
Journal du jeudi 04 juillet 2024 à 22:27
#JeLis la section Example: Decorations de CodeMirror qui je pense me sera très utile pour Projet 8.
#JaiDécouvert ici MatchDecorator
. Je pense devoir utiliser MatchDecorator
pour implémenter Projet 8.
#JaiDécouvert l'article [Learning CodeMirror] que #JeSouhaite lire.
L'implémentation dans SilverBullet.mb de la fonctionnalité décrite dans Projet 8 se trouve ici.
Journal du dimanche 23 juin 2024 à 22:22
#iteration du Projet 5 - "Importation d'un vault Obsidian vers Apache Age" et plus précisément la suite de 2024-06-20_2211 et 2024-06-23_1057.
#JaiCompris en lisant ceci que pg_search se nommait apparavant pg_bm25
.
#JaiDécouvert que Tantivy — lib sur laquelle est construit pg_search — et Apache Lucene utilisent l'algorithme de scoring nommé BM25.
Okapi BM25 est une méthode de pondération utilisée en recherche d'information. Elle est une application du modèle probabiliste de pertinence, proposé en 1976 par Robertson et Jones. (from)
Je suis impressionné qu'en 2024, l'algorithme qui je pense est le plus performant utilisé dans les moteurs de recherche ait été mis au point en 1976 😮.
#JaiDécouvert pgfaceting - Faceted query acceleration for PostgreSQL using roaring bitmaps .
J'ai finallement réussi à installer pg_search à l'image Docker postgres:16
: https://github.com/stephane-klein/pg_search_docker.
J'ai passé 3h pour réaliser cette image Docker, je trouve que c'est beaucoup trop 🫣.
Journal du dimanche 23 juin 2024 à 10:57
#iteration du Projet 5 - "Importation d'un vault Obsidian vers Apache Age" et plus précisément la suite de 2024-06-20_2211, #JeMeDemande comment créer une image Docker qui intègre l'extension pg_search ou autrement nommé ParadeDB.
Je lis ici :
#JePense que c'est un synonyme de pg_search mais je n'en suis pas du tout certain.
En regardant la documetation de ParadeDB, je lis :
J'en conclu que ParadeDB est un projet qui regroupe plusieurs extensions PostgreSQL : pg_search, pg_lakehouse
et pg_analytics
.
Pour le Projet 5, je suis intéressé seulement par pg_search.
#JeMeDemande si pg_search dépend de pg_vector mais je pense que ce n'est pas le cas.
#JeMeDemande comment créer une image Docker qui intègre l'extension pg_search ou autrement nommé ParadeDB.
J'ai commencé par essayer de créer cette image Docker en me basant sur ce Dockerfile mais j'ai trouvé cela pas pratique. Je constaté que j'avais trop de chose à modifier.
Suite à cela, je pense que je vais essayer d'installer pg_search avec PGXN.
Lien vers l'extension pg_search sur PGXN : https://pgxn.org/dist/pg_bm25/
Sur GitHub, je n'ai trouvé aucun exemple de Dockerfile
qui inclue pgxn install pg_bm25
.
J'ai posté https://github.com/paradedb/paradedb/issues/1019#issuecomment-2184933674.
I've seen this PGXN extension https://pgxn.org/dist/pg_bm25/
But for the moment I can't install it:
root@631f852e2bfa:/# pgxn install pg_bm25 INFO: best version: pg_bm25 9.9.9 INFO: saving /tmp/tmpvhb7eti5/pg_bm25-9.9.9.zip INFO: unpacking: /tmp/tmpvhb7eti5/pg_bm25-9.9.9.zip INFO: building extension ERROR: no Makefile found in the extension root
J'ai posté pgxn install pg_bm25 => ERROR: no Makefile found in the extension root #1287.
I think I may have found my mistake.
Should I not use
pgxn install
but should I usepgxn download
:root@28769237c982:~# pgxn download pg_bm25 INFO: best version: pg_bm25 9.9.9 INFO: saving /root/pg_bm25-9.9.9.zip
@philippemnoel Can you confirm my hypothesis?
J'ai l'impression que https://pgxn.org/dist/pg_bm25/ n'est buildé que pour PostgreSQL 15.
root@4c6674286839:/# unzip pg_bm25-9.9.9.zip
Archive: pg_bm25-9.9.9.zip
creating: pg_bm25-9.9.9/
creating: pg_bm25-9.9.9/usr/
creating: pg_bm25-9.9.9/usr/lib/
creating: pg_bm25-9.9.9/usr/lib/postgresql/
creating: pg_bm25-9.9.9/usr/lib/postgresql/15/
creating: pg_bm25-9.9.9/usr/lib/postgresql/15/lib/
inflating: pg_bm25-9.9.9/usr/lib/postgresql/15/lib/pg_bm25.so
creating: pg_bm25-9.9.9/usr/share/
creating: pg_bm25-9.9.9/usr/share/postgresql/
creating: pg_bm25-9.9.9/usr/share/postgresql/15/
creating: pg_bm25-9.9.9/usr/share/postgresql/15/extension/
inflating: pg_bm25-9.9.9/usr/share/postgresql/15/extension/pg_bm25.control
inflating: pg_bm25-9.9.9/usr/share/postgresql/15/extension/pg_bm25--9.9.9.sql
inflating: pg_bm25-9.9.9/META.json
Je pense que je dois changer de stratégie 🤔.
Je ne pensais pas rencontrer autant de difficultés pour installer cette extension 🤷♂️.
Ce matin, j'ai passé 1h30 sur ce sujet.
J'ai trouvé ce Dockerfile
https://github.com/kevinhu/pgsearch/blob/48c4fee0b645fddeb7825802e5d1a4a2beb9a99b/Dockerfile#L14
Je pense pouvoir installer un package Debian présent dans la page release : https://github.com/paradedb/paradedb/releases
Journal du jeudi 20 juin 2024 à 22:11
Nouvelle #iteration du Projet 5 - "Importation d'un vault Obsidian vers Apache Age".
Dans cette version du 20 juin j'ai implémenté :
- Importation des fichiers dans des nodes de type
notes
dans un graph. - Le contenu des notes dans une table
public.notes
- Les aliases dans la table
public.note_aliases
- Importation des tags et leurs liaisons vers les notes dans un graph.
Au stade où j'en suis, je suis encore loin d'être en capacité de juger si le moteur de graph — Age — me sera utile ou non pour réaliser des requêtes simplement 🤔.
Prochaine fonctionnalités que je souhaite implémenter dans ce projet :
- [ ] Recherche de type fuzzy search sur les
Note.title
,alias
etTag.name
basé sur la méthode Levenshtein du module fuzzystrmatch - [ ] Recherche plain text sur le contenu des Notes basé sur pg_search
Dans la liste des features de pg_search je lis :
- Autocomplete
- Fuzzy search
Je pense donc intégrer pg_search avant fuzzystrmatch. Peut-être que je n'aurais pas besoin d'utiliser fuzzystrmatch.
Journal du dimanche 16 juin 2024 à 17:08
Nouvelle #iteration du Projet 5 - "Importation d'un vault Obsidian vers Apache Age".
#JeMeDemande si la convention est de nommer les nodes au singulier ou au pluriel, par exemple Note
ou Notes
🤔.
D'après cette documentation, je comprends que la convention semble être le singulier.
Journal du samedi 08 juin 2024 à 17:08
Nouvelle #iteration sur Projet 7 - "Améliorer et mettre à jour le projet restic-pg_dump-docker".
Alors que je travaille sur cette partie du projet, je relis la documentation de pg_dumpall et je constate à nouveau que cette commande ne supporte pas les différents formats de sortie que propose pg_dump 😡.
C'est pénible… du coup, j'ai enfin pris le temps de chercher si il existe une solution alternative et #JaiDécouvert pg_back
:
pg_back is a dump tool for PostgreSQL. The goal is to dump all or some databases with globals at once in the format you want, because a simple call to pg_dumpall only dumps databases in the plain SQL format.
C'est parfait, c'est exactement ce que je cherche 👌.
Mais je découvre aussi les fonctionnalités suivantes :
- Pre-backup and post-backup hooks
- Purge based on age and number of dumps to keep
- Dump from a hot standby by pausing replication replay
- Encrypt and decrypt dumps and other files
- Upload and download dumps to S3, GCS, Azure or a remote host with SFTP
Conséquence : #JeMeDemande si j'ai encore besoin de restic dans Projet 7 🤔.
Je viens de lire ici :
In addition to the N previous backups, it would be nice to keep N' weekly backups and N'' monthly backups, to be able to look back into the far past.
C'est une fonctionnalité supporté par restic, donc pour le moment, je choisis de continuer à utiliser restic
.
Pour le moment, #JaiDécidé d'intégrer simplement pg_back
dans restic-pg_dump-docker
en remplacement de pg_dumpall
et de voir par la suite si je simplifie ce projet ou non.
Journal du vendredi 07 juin 2024 à 17:12
Nouvelle #iteration sur Projet 7 - "Améliorer et mettre à jour le projet restic-pg_dump-docker".
Hasard du calendrier, mon ami Alexandre travaille en ce moment sur un projet nommé restic-ftp-docker
.
Quelle différence avec restic-pg_dump-docker
?
Principale différence d'objectif entre ces deux projets :
restic-ftp-docker
sauvegarde via restic le contenu d'un dossier vers un espace FTP.restic-pg_dump-docker
sauvegarde via restic le contenu d'une base de données PostgreSQL. Le contenu de la base de données est exporté avec la commande standard pg_dump de PostgreSQL. La sauvegarde peut être envoyée vers tous les storages supportés par rclone.
#JaiDécidé de reprendre un maximum d'élément du projet restic-ftp-docker
dans restic-pg_dump-docker
.
#JeSouhaite proposer une Pull Request à restic-ftp-docker
pour étendre ce projet à tous les storages supporté par rclone et ne plus le limité au storage ftp
.
Journal du mercredi 22 mai 2024 à 10:33
Je viens de finir Projet 6 - "SvelteFlow playground", voici un screencast de démonstration du résultat :
J'ai passé 5h27 sur ce projet.
Code source de ce projet https://github.com/stephane-klein/svelteflow-playground
Ma plus grosse difficulté a été de trouver comment implémenter les containtes liaison.
Pour le moment, je doute que mon implémentation respecte les bonnes pratiques d'utilisation de la librairie. Je pense que je vais découvrir le "bon" usage — tel que imaginé par Moritz Klack — de la librarie au fur et à mesure de mon utilisation.
Journal du mardi 21 mai 2024 à 16:22
Nouvelle #iteration sur Projet 6 - "SvelteFlow playground".
17:00 : J'ai réussi à ajouter un CustomNode
(commit).
23:00 : Dans ce commit, j'ai réussi à définir des contraintes de liaisons. Il n'est plus possible de lier deux nodes du même type.
Journal du lundi 20 mai 2024 à 11:01
Nouvelle #iteration sur Projet 6 - "SvelteFlow playground".
Je me suis inspiré de l'exemple Drag and Drop pour implémenter ce commit, ce qui donne ceci :
11:19 : Prochaine étape, lire et comprendre Theming – Svelte Flow.
11:32 :
- J'ai trouvé ce projet https://github.com/theonlytechnohead/patchcanvas/ qui peut me servir de source d'inspiration.
- #JeMeDemande si je dois implémenter un composant de type
<Handle />
pour définir des contraintes de liaisons entre les nodes 🤔.
12:29 :
Journal du jeudi 16 mai 2024 à 09:44
Voici ma dernière itération du Projet -1 "CodeMirror, autocomplétion, Svelte".
Code source https://github.com/stephane-klein/svelte-codemirror-autocomplete-poc
Journal du vendredi 10 mai 2024 à 08:37
#JeMeDemande si le code de SilverBullet.mb pourrait m'inspirer dans mon travail sur Projet -1 "CodeMirror, autocomplétion, Svelte" 🤔.
J'ai l'impression que le code qui m'intéresse se trouve vers ici.
Je pense que CompletionTooltip
est la classe qui est responsable de l'affichage du "completion picker".
09:56 : J'ai réussi à afficher un "completion picker" minimaliste :
10:02 : Prochaines itérations :
- [ ] Essayer d'implémenter le chargement de la liste d'items de suggestion de manière dynamique. Je souhaite obtenir cette liste via une requête GET http, sur l'url
/get-suggestions/
. Cette fonctionnalité est souvent nommée « remote data fetch » (exemple ici). - [ ] Essayer d'implémenter un chargement dynamique d'items de manière progressif. Au lieu de charger toutes la listes des items, l'objectif et de les charger au fur et à mesure, par exemple en petit paquets de 100 items). L'objectif de cette tache ressemble à https://github.com/vtaits/react-select-async-paginate.
Vous êtes sur la première page | [ Page suivante (9) >> ]