<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="../assets/xml/rss.xsl" media="all"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Linux Sin Humo (Publicaciones sobre howto)</title><link>https://sergiobelkin.com/</link><description></description><atom:link href="https://sergiobelkin.com/categories/cat_howto.xml" rel="self" type="application/rss+xml"></atom:link><language>es</language><copyright>Contents © 2026 &lt;a href="mailto:sebelk@gmail.com"&gt;sebelk&lt;/a&gt; 
&lt;a rel="license" href="https://creativecommons.org/licenses/by-nc-sa/4.0/"&gt;
&lt;img alt="Creative Commons License BY-NC-SA"
style="border-width:0; margin-bottom:12px;"
src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png"&gt;&lt;/a&gt;
</copyright><lastBuildDate>Tue, 21 Apr 2026 00:01:46 GMT</lastBuildDate><generator>Nikola (getnikola.com)</generator><docs>http://blogs.law.harvard.edu/tech/rss</docs><item><title>Gestión de Contraseñas Usando Contenedores Podman (Update 2025)</title><link>https://sergiobelkin.com/posts/gestion-de-contrasenas-usando-contenedores-podman-update-2025/</link><dc:creator>sebelk</dc:creator><description>&lt;figure&gt;&lt;img src="https://sergiobelkin.com/images/podman-pass-2025.png"&gt;&lt;/figure&gt; &lt;p&gt;En 2023, &lt;a href="https://sergiobelkin.com/posts/gestion-de-contrasenas-usando-contenedores-podman/"&gt;publiqué un post&lt;/a&gt; sobre cómo usar &lt;strong&gt;&lt;code&gt;pass&lt;/code&gt;&lt;/strong&gt; con un contenedor Git administrado por Podman. Esa guía fue muy útil como demo inicial, pero desde entonces cambiaron algunas cosas: nuevas versiones de Podman, la aparición de &lt;strong&gt;Quadlet&lt;/strong&gt;, la deprecación de &lt;code&gt;podman generate systemd&lt;/code&gt;, y la conveniencia de usar imágenes más estables.&lt;/p&gt;
&lt;p&gt;Este post es una &lt;strong&gt;actualización 2025&lt;/strong&gt; del artículo original, incorporando:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Imagen base &lt;strong&gt;UBI9 minimal&lt;/strong&gt; (más liviana y con soporte extendido). Esta imagen, desarrollada por Red Hat, es de tamaño relativamente pequeño, usa una versión reduccida de dnf, llamada &lt;em&gt;microdnf&lt;/em&gt; con soporte de módulos y usa software de repositorios - también - de Red Hat.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rootless limpio&lt;/strong&gt; con &lt;code&gt;UserNS=keep-id&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Quadlet&lt;/strong&gt; para integrar con &lt;code&gt;systemd --user&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Volúmenes persistentes&lt;/strong&gt; para no perder datos ni claves al actualizar la imagen.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Endurecimiento SSH&lt;/strong&gt; (solo claves públicas, nada de contraseñas).&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3 id="1-construccion-de-la-imagen"&gt;1. Construcción de la imagen&lt;/h3&gt;
&lt;p&gt;Dockerfile (&lt;code&gt;Dockerfile&lt;/code&gt;):&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;registry.access.redhat.com/ubi9/ubi-minimal&lt;/span&gt;

&lt;span class="k"&gt;RUN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;microdnf&lt;span class="w"&gt; &lt;/span&gt;-y&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;openssh-server&lt;span class="w"&gt; &lt;/span&gt;git&lt;span class="w"&gt; &lt;/span&gt;shadow-utils&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;microdnf&lt;span class="w"&gt; &lt;/span&gt;clean&lt;span class="w"&gt; &lt;/span&gt;all&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;useradd&lt;span class="w"&gt; &lt;/span&gt;-ms&lt;span class="w"&gt; &lt;/span&gt;/bin/bash&lt;span class="w"&gt; &lt;/span&gt;git&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;chsh&lt;span class="w"&gt; &lt;/span&gt;-s&lt;span class="w"&gt; &lt;/span&gt;/usr/bin/git-shell&lt;span class="w"&gt; &lt;/span&gt;git

&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;2222&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"/usr/sbin/sshd"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"-D"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"-e"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Construcción:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;podman&lt;span class="w"&gt; &lt;/span&gt;build&lt;span class="w"&gt; &lt;/span&gt;-t&lt;span class="w"&gt; &lt;/span&gt;localhost/passteiner-ubi9:1&lt;span class="w"&gt; &lt;/span&gt;.
&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h3 id="2-crear-volumenes-persistentes"&gt;2. Crear volúmenes persistentes&lt;/h3&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;podman&lt;span class="w"&gt; &lt;/span&gt;volume&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;git-home
podman&lt;span class="w"&gt; &lt;/span&gt;volume&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;ssh-etc

&lt;span class="nv"&gt;VHOME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;podman&lt;span class="w"&gt; &lt;/span&gt;volume&lt;span class="w"&gt; &lt;/span&gt;inspect&lt;span class="w"&gt; &lt;/span&gt;-f&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'{{.Mountpoint}}'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;git-home&lt;span class="k"&gt;)&lt;/span&gt;
mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$VHOME&lt;/span&gt;&lt;span class="s2"&gt;/.ssh"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$VHOME&lt;/span&gt;&lt;span class="s2"&gt;/.password-store"&lt;/span&gt;
cp&lt;span class="w"&gt; &lt;/span&gt;~/.ssh/id_ed25519.pub&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$VHOME&lt;/span&gt;&lt;span class="s2"&gt;/.ssh/authorized_keys"&lt;/span&gt;
chmod&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;700&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$VHOME&lt;/span&gt;&lt;span class="s2"&gt;/.ssh"&lt;/span&gt;
chmod&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;600&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$VHOME&lt;/span&gt;&lt;span class="s2"&gt;/.ssh/authorized_keys"&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Repositorio bare:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;podman&lt;span class="w"&gt; &lt;/span&gt;unshare&lt;span class="w"&gt; &lt;/span&gt;chown&lt;span class="w"&gt; &lt;/span&gt;-R&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1000&lt;/span&gt;:1000&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$VHOME&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
podman&lt;span class="w"&gt; &lt;/span&gt;run&lt;span class="w"&gt; &lt;/span&gt;--rm&lt;span class="w"&gt; &lt;/span&gt;-v&lt;span class="w"&gt; &lt;/span&gt;git-home:/home/git&lt;span class="w"&gt; &lt;/span&gt;localhost/passteiner-ubi9:1&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;git&lt;span class="w"&gt; &lt;/span&gt;init&lt;span class="w"&gt; &lt;/span&gt;--bare&lt;span class="w"&gt; &lt;/span&gt;/home/git/.password-store
&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h3 id="3-quadlet-systemd-integration"&gt;3. Quadlet (systemd integration)&lt;/h3&gt;
&lt;p&gt;Archivo &lt;code&gt;~/.config/containers/systemd/pass_git.container&lt;/code&gt;:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="k"&gt;[Unit]&lt;/span&gt;
&lt;span class="na"&gt;Description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;pass git over SSH (podman quadlet)&lt;/span&gt;
&lt;span class="na"&gt;Wants&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;network-online.target&lt;/span&gt;
&lt;span class="na"&gt;After&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;network-online.target&lt;/span&gt;

&lt;span class="k"&gt;[Container]&lt;/span&gt;
&lt;span class="na"&gt;Image&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;containers-storage:localhost/passteiner-ubi9:1&lt;/span&gt;
&lt;span class="na"&gt;Pull&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;never&lt;/span&gt;

&lt;span class="na"&gt;ContainerName&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;pass_git&lt;/span&gt;
&lt;span class="na"&gt;Network&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;pasta&lt;/span&gt;
&lt;span class="na"&gt;PublishPort&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;60003:2222&lt;/span&gt;

&lt;span class="na"&gt;Volume&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;git-home:/home/git:Z,U&lt;/span&gt;
&lt;span class="na"&gt;Volume&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;ssh-etc:/etc/ssh:Z&lt;/span&gt;

&lt;span class="na"&gt;UserNS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;keep-id&lt;/span&gt;
&lt;span class="na"&gt;LogDriver&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;journald&lt;/span&gt;
&lt;span class="na"&gt;Exec&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/usr/sbin/sshd -D -e -p 2222 -o PidFile=/tmp/sshd.pid&lt;/span&gt;

&lt;span class="k"&gt;[Service]&lt;/span&gt;
&lt;span class="na"&gt;Restart&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;on-failure&lt;/span&gt;

&lt;span class="k"&gt;[Install]&lt;/span&gt;
&lt;span class="na"&gt;WantedBy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;default.target&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Activación:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;systemctl&lt;span class="w"&gt; &lt;/span&gt;--user&lt;span class="w"&gt; &lt;/span&gt;daemon-reload
systemctl&lt;span class="w"&gt; &lt;/span&gt;--user&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;enable&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--now&lt;span class="w"&gt; &lt;/span&gt;pass_git.service
&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h3 id="4-probar-conexion-ssh"&gt;4. Probar conexión SSH&lt;/h3&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;ssh&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;60003&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;git@&amp;lt;IP_DEL_HOST&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-o&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;PreferredAuthentications&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;publickey&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-o&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;PasswordAuthentication&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;no&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="s1"&gt;'git --version &amp;amp;&amp;amp; echo OK'&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Debe autenticar con tu clave pública y responder &lt;code&gt;git version ...&lt;/code&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="5-probar-pass-con-git"&gt;5. Probar pass con git&lt;/h3&gt;
&lt;p&gt;Inicializar &lt;code&gt;pass&lt;/code&gt; en tu host y configurar el remoto:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="nb"&gt;export&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;PASSWORD_STORE_DIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;~/.local/share/pass
pass&lt;span class="w"&gt; &lt;/span&gt;init&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"tu_clave_gpg"&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$PASSWORD_STORE_DIR&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
git&lt;span class="w"&gt; &lt;/span&gt;remote&lt;span class="w"&gt; &lt;/span&gt;add&lt;span class="w"&gt; &lt;/span&gt;origin&lt;span class="w"&gt; &lt;/span&gt;ssh://git@&amp;lt;IP_DEL_HOST&amp;gt;:60003/home/git/.password-store
git&lt;span class="w"&gt; &lt;/span&gt;push&lt;span class="w"&gt; &lt;/span&gt;origin&lt;span class="w"&gt; &lt;/span&gt;master
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Y luego:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;pass&lt;span class="w"&gt; &lt;/span&gt;git&lt;span class="w"&gt; &lt;/span&gt;push
pass&lt;span class="w"&gt; &lt;/span&gt;git&lt;span class="w"&gt; &lt;/span&gt;pull
&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h3 id="diferencias-clave-respecto-al-articulo-original"&gt;Diferencias clave respecto al artículo original&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Imagen&lt;/strong&gt;: antes Fedora, ahora UBI9 minimal (más estable, soporte hasta 2032).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Systemd&lt;/strong&gt;: antes &lt;code&gt;podman generate systemd&lt;/code&gt;, ahora &lt;strong&gt;Quadlet&lt;/strong&gt; (futuro estándar, más limpio).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rootless&lt;/strong&gt;: antes root dentro del contenedor, ahora &lt;code&gt;UserNS=keep-id&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Volúmenes&lt;/strong&gt;: ahora explícitos (&lt;code&gt;git-home&lt;/code&gt;, &lt;code&gt;ssh-etc&lt;/code&gt;), evitando pérdidas de datos.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Seguridad SSH&lt;/strong&gt;: solo claves, sin password, &lt;code&gt;PidFile&lt;/code&gt; movido a &lt;code&gt;/tmp&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3 id="conclusion"&gt;Conclusión&lt;/h3&gt;
&lt;p&gt;Este enfoque actualizado:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Evita perder el repositorio y las claves al recrear el contenedor.&lt;/li&gt;
&lt;li&gt;Asegura compatibilidad a futuro con Podman + systemd.&lt;/li&gt;
&lt;li&gt;Se apoya en una base más segura (UBI9 minimal).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;👉 Si ya usás el setup original, podés migrar en pocas horas y quedarte tranquilo de que tu &lt;strong&gt;gestor de contraseñas &lt;code&gt;pass&lt;/code&gt;&lt;/strong&gt; seguirá funcionando a largo plazo.&lt;/p&gt;</description><category>contenedores</category><category>seguridad</category><guid>https://sergiobelkin.com/posts/gestion-de-contrasenas-usando-contenedores-podman-update-2025/</guid><pubDate>Mon, 25 Aug 2025 22:27:46 GMT</pubDate></item><item><title>Comparación de systemd-run con nuhup, tmux y screen</title><link>https://sergiobelkin.com/posts/systemd-run-vs-nohup-vs-tmuxscreen/</link><dc:creator>sebelk</dc:creator><description>&lt;p&gt;&lt;img alt="systemd-run" class="img-izquierda-responsiva" src="https://sergiobelkin.com/images/systemd-run.webp"&gt;
&lt;br&gt;
Si estamos conectados por ssh y sufrimos una desconexión mientras ejecutamos un comandos, puede representar un problema, desde la interrupción del proceso o la pérdida del acceso a la salida estándar/error del mismo. Existen comandos como nohup que de alguna manera nos ayudan a mitigar esas situaciones, tales como nohup, o multiplexores de terminal como screen y tmux.&lt;/p&gt;
&lt;p&gt;Al usar systemd, contamos con una herramienta tan sencilla como poderosa: el comando &lt;code&gt;systemd-run&lt;/code&gt; que permite ejecutar un comando muy sencillo como el siguiente en un servicio. O para ser más exactos en una &lt;strong&gt;service unit&lt;/strong&gt;:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;systemd-run&lt;span class="w"&gt; &lt;/span&gt;--user&lt;span class="w"&gt; &lt;/span&gt;ping&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;8&lt;/span&gt;.8.8.8
&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id="comparacion-con-nohup-tmuxscreen"&gt;Comparación con nohup, tmux/screen&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Característica&lt;/th&gt;
&lt;th&gt;&lt;code&gt;systemd-run&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;nohup&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;tmux&lt;/code&gt; / &lt;code&gt;screen&lt;/code&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Supervisión del estado&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Sí, vía &lt;code&gt;systemctl status&lt;/code&gt; y &lt;code&gt;journalctl&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;No, se debe usar &lt;code&gt;ps&lt;/code&gt; o &lt;code&gt;pgrep&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Parcial, requiere inspección manual de la sesión&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Control del ciclo de vida&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Completo: iniciar, detener, reiniciar con políticas de reinicio&lt;/td&gt;
&lt;td&gt;Nulo: solo iniciar, sin reinicio automático&lt;/td&gt;
&lt;td&gt;Manual: requiere interacción del usuario&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Manejo de logs&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Centralizado en journal, con metadata y timestamps&lt;/td&gt;
&lt;td&gt;Básico: redirige a &lt;code&gt;nohup.out&lt;/code&gt; sin rotación&lt;/td&gt;
&lt;td&gt;Opcional: solo si se configura logging explícitamente&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Integración con el sistema&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Alta: como unidad de systemd, con cgroup, slices, y logs centralizados&lt;/td&gt;
&lt;td&gt;Nula: proceso genérico del usuario&lt;/td&gt;
&lt;td&gt;Baja: proceso de usuario sin integración con systemd&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Persistencia tras logout&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Alta: configurable vía &lt;code&gt;lingering&lt;/code&gt; o como unidad del sistema&lt;/td&gt;
&lt;td&gt;Limitada: depende de configuración de &lt;code&gt;logind&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Alta (tradicional), pero afectada por &lt;code&gt;KillUserProcesses&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Persistencia tras reinicio&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Posible mediante conversión a unidad persistente o uso de &lt;code&gt;systemd-timer&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;No, se requiere cron, scripts externos&lt;/td&gt;
&lt;td&gt;No, sesión se pierde tras reboot&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Políticas de recursos/aislamiento&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Completa: límites CPU, memoria, I/O, namespaces, privilegios, etc.&lt;/td&gt;
&lt;td&gt;Nula: se requiere uso externo de &lt;code&gt;ulimit&lt;/code&gt; o &lt;code&gt;nice&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Nula: requiere herramientas externas&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Facilidad de uso interactivo&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Baja: orientado a ejecución no interactiva&lt;/td&gt;
&lt;td&gt;Nula: no interactivo&lt;/td&gt;
&lt;td&gt;Alta: diseñado para interacción, múltiples ventanas/sesiones&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Ideal para&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Tareas ad-hoc, servicios temporales, pruebas controladas&lt;/td&gt;
&lt;td&gt;Procesos simples que deben continuar tras logout&lt;/td&gt;
&lt;td&gt;Tareas interactivas largas o sesiones remotas persistentes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="mas-ejemplos"&gt;Más Ejemplos&lt;/h3&gt;
&lt;h4 id="ansible"&gt;Ansible&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;Advertencia&lt;/strong&gt;: Los siguiente comandos no son para copiar y pegar sin analizarlos, deben ser ajustados al entorno en los cuales se los desea utiizar. El propósito principal es mostrar la potencia práctica de la herramienta &lt;code&gt;systemd-run&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Objetivo&lt;/strong&gt;: Ejecutar playbooks críticos en entornos controlados, como servicios temporales autoreiniciables.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;systemd-run&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;Restart&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;on-failure&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;PrivateTmp&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;yes&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;Description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"Provisionar servidores"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;SuccessExitStatus&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\ &lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;RestartSec&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\ &lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;TimeoutStopSec&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;30&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="se"&gt;\ &lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--unit&lt;span class="o"&gt;=&lt;/span&gt;ansible-run&lt;span class="w"&gt; &lt;/span&gt;ansible-playbook&lt;span class="w"&gt; &lt;/span&gt;site.yml&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;inventory/prod
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Ventajas&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Crea un entorno temporal (&lt;code&gt;/tmp&lt;/code&gt; aislado).&lt;/li&gt;
&lt;li&gt;Si falla, se reinicia automáticamente.&lt;/li&gt;
&lt;li&gt;El log de toda la ejecución queda en &lt;code&gt;journal&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="mysqldump"&gt;mysqldump&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;Objetivo&lt;/strong&gt;: Realizar dumps de bases de datos con límites de memoria y sin cargar el sistema.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;systemd-run&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;MemoryMax&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;750M&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;MemorySwapMax&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;150M&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;Nice&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;Description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"Backup de MySQL sin afectar el sistema"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--unit&lt;span class="o"&gt;=&lt;/span&gt;mysql-dump&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;bash&lt;span class="w"&gt; &lt;/span&gt;-c&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'mysqldump --all-databases &amp;gt; /tmp/backup.sql'&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Ventajas&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Protege al sistema de un uso excesivo de memoria&lt;/li&gt;
&lt;li&gt;Baja prioridad de batch (&lt;code&gt;Nice=10&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Log y control vía systemd.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="azure-cli"&gt;Azure CLI&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;Objetivo&lt;/strong&gt;: Apagar/desasignar todas las VMs del grupo "GrupoDesarrollo" en segundo plano&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;systemd-run&lt;span class="w"&gt; &lt;/span&gt;--unit&lt;span class="o"&gt;=&lt;/span&gt;apagar_vms&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;--service-type&lt;span class="o"&gt;=&lt;/span&gt;oneshot&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;WorkingDirectory&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/tmp&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;bash&lt;span class="w"&gt; &lt;/span&gt;-c&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'az login --identity &amp;amp;&amp;amp; az vm list -g GrupoDesarrollo --query "[].id" -o tsv | xargs -r az vm deallocate --ids'&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Ventajas&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Ejecución desacoplada de la terminal.&lt;/li&gt;
&lt;li&gt;Se puede usar &lt;code&gt;journalctl&lt;/code&gt; para auditar el comando.&lt;/li&gt;
&lt;li&gt;Control sobre el entorno de ejecución&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="conclusion"&gt;Conclusión&lt;/h3&gt;
&lt;p&gt;El comando &lt;code&gt;systemd-run&lt;/code&gt; es una alternativa más robusta que otros comandos legacy o multiplexores de terminal, ya que permite, no solamente desacoplar el proceso de la terminal sino también poder gestionarlo perfectamente dentro de systend.&lt;/p&gt;
&lt;h3 id="fuentes-y-mas-recursos"&gt;Fuentes y más recursos&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://www.freedesktop.org/software/systemd/man/latest/systemd-run.html"&gt;Manpage de &lt;code&gt;systemd-run&lt;/code&gt;&lt;/a&gt;&lt;br&gt;
  Documentación oficial de &lt;code&gt;systemd-run&lt;/code&gt;, incluyendo parámetros como &lt;code&gt;--unit&lt;/code&gt;, &lt;code&gt;--service-type&lt;/code&gt;, y ejemplos útiles.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://www.freedesktop.org/software/systemd/man/latest/systemd.service.html"&gt;Manpage de &lt;code&gt;systemd.service&lt;/code&gt;&lt;/a&gt;&lt;br&gt;
  Referencia esencial sobre unidades de servicio, incluyendo tipos (&lt;code&gt;oneshot&lt;/code&gt;, &lt;code&gt;simple&lt;/code&gt;) y propiedades como &lt;code&gt;Restart=&lt;/code&gt;, &lt;code&gt;WorkingDirectory=&lt;/code&gt;, etc.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://learn.microsoft.com/en-us/cli/azure/authenticate-azure-cli#sign-in-using-a-managed-identity"&gt;Autenticación con identidad administrada en Azure CLI&lt;/a&gt;&lt;br&gt;
  Cómo usar &lt;code&gt;az login --identity&lt;/code&gt; de forma segura, sin almacenar credenciales.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://unix.stackexchange.com/questions/420594/why-process-killed-with-nohup"&gt;Respuesta que recomienda &lt;code&gt;systemd-run&lt;/code&gt; cuando &lt;code&gt;nohup&lt;/code&gt; falla&lt;/a&gt;&lt;br&gt;
  Explica por qué procesos protegidos con &lt;code&gt;nohup&lt;/code&gt; pueden morir y propone &lt;code&gt;systemd-run --scope --user&lt;/code&gt; como solución más fiable.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://docs.fedoraproject.org/en-US/quick-docs/understanding-and-administering-systemd/index.html"&gt;Explicación de tipos de unidades systemd (Fedora Project)&lt;/a&gt;&lt;br&gt;
  Introducción accesible al funcionamiento de systemd.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;</description><category>systemd</category><guid>https://sergiobelkin.com/posts/systemd-run-vs-nohup-vs-tmuxscreen/</guid><pubDate>Tue, 24 Jun 2025 22:07:30 GMT</pubDate></item><item><title>Cómo migrar de vim-plug a lazy.nvim</title><link>https://sergiobelkin.com/posts/como-migrar-de-vim-plug-a-lazynvim/</link><dc:creator>sebelk</dc:creator><description>&lt;h3 id="introduccion"&gt;Introducción&lt;/h3&gt;
&lt;p&gt;Ya vimos &lt;a href="https://sergiobelkin.com/posts/como-convertir-tu-configuracion-de-initvim-a-initlua/"&gt;como convertir una una configuración en Vim script a Lua&lt;/a&gt;. Ese tipo de configuración es más flexible y reutilizaable. Ahora vamos por el paso final que es migrar de vim-plug a &lt;strong&gt;lazy.nvim&lt;/strong&gt;.&lt;/p&gt;
&lt;h3 id="que-es-lazynvim"&gt;¿Qué es lazy.nvim?&lt;/h3&gt;
&lt;p&gt;Es un gestor de plugins escrito en Lua que sabe sacar provecho de la arquitectura moderna de Neovim.&lt;/p&gt;
&lt;h3 id="que-ventajas-y-funcionalidades-tiene-lazynvim"&gt;¿Qué ventajas y funcionalidades tiene lazy.nvim?&lt;/h3&gt;
&lt;p&gt;El gestor lazy.nvim se destaca por su rendimiento, usabilidad/UX y el modo de gestionar de plugins.&lt;/p&gt;
&lt;p&gt;En la siguiente tabla vemos como se destaca en cuento a &lt;strong&gt;Rendimiento&lt;/strong&gt;:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Funcionalidad/Ventaja&lt;/th&gt;
&lt;th&gt;¿Qué significa?&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Inicio ultra rápido&lt;/td&gt;
&lt;td&gt;Arranca en segundos porque los módulos se precompilan y se cachean automáticamente.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Instalaciones livianas&lt;/td&gt;
&lt;td&gt;Clona sólo lo esencial de los repos, ahorrando ancho de banda y espacio.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Plugins sin bloqueo del editor&lt;/td&gt;
&lt;td&gt;Tareas pesadas se ejecutan en segundo plano, manteniendo Neovim fluido.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Análisis de rendimiento&lt;/td&gt;
&lt;td&gt;Herramientas para medir tiempos de carga y optimizar tu configuración.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Carga bajo demanda (lazy-loading)&lt;/td&gt;
&lt;td&gt;Plugins se cargan solo cuando se necesitan, reduciendo carga inicial y memoria.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h5 id="que-y-donde-cachea-lazynvim"&gt;📝 ¿Qué y dónde cachea lazy.nvim?&lt;/h5&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Directorio&lt;/th&gt;
&lt;th&gt;Uso específico por &lt;code&gt;lazy.nvim&lt;/code&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;~/.cache/nvim/luac/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Cache de bytecode Lua&lt;/strong&gt;. Compila tu configuración en Lua a &lt;code&gt;.luac&lt;/code&gt;, para que Neovim no tenga que interpretarla cada vez.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;~/.local/share/nvim/lazy/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Instalación real de los plugins&lt;/strong&gt;. Los plugins ya descargados no necesitan revalidarse ni reinstalarse.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;~/.local/state/nvim/lazy/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Cache de estado&lt;/strong&gt;: versiones exactas de los plugins, commits, fechas, hashes. Así &lt;code&gt;lazy.nvim&lt;/code&gt; sabe si algo cambió.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="por-que-migrar-de-vim-plug"&gt;¿Por qué migrar de vim-plug?&lt;/h3&gt;
&lt;h4 id="los-numeros-duros"&gt;Los números duros&lt;/h4&gt;
&lt;p&gt;&lt;img alt="Tabla Comparativa de Repositorios lazy.vim vs vim-plug" src="https://sergiobelkin.com/images/Comparativa_lazy-plug.webp"&gt;&lt;/p&gt;
&lt;p&gt;La tabla de arriba muestra que&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Si bien ambos son repositoorios populares, &lt;strong&gt;vim-plug&lt;/strong&gt; (que es un proyecto más longevo) supera a &lt;strong&gt;lazy.nvim&lt;/strong&gt; en este aspecto.&lt;/li&gt;
&lt;li&gt;Ambos proyectos están activos.&lt;/li&gt;
&lt;li&gt;El repo &lt;strong&gt;lazy.nvim&lt;/strong&gt; tiene más colaboradores.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;En este aspecto salen bastante empatados.&lt;/p&gt;
&lt;h4 id="aspectos-ventajosos-desde-el-punto-de-vista-tecnico"&gt;Aspectos ventajosos desde el punto de vista técnico&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Para sysadmins: Rendimiento y carga mínima: se puede configurar de manera natural los plugins que realmente necesitás en tu entorno (por ejemplo, se pueden configurar plugins para que solamente se carguen al usar ssh) y una configuración más clara: todo en Lua, más fácil de mantener con backups dotfiles/scripts.&lt;/li&gt;
&lt;li&gt;Para desarrolladores: Carga por filetype y herramientas específicas y mayor control sobre dependencias y versiones.&lt;/li&gt;
&lt;/ul&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Funcionalidad&lt;/th&gt;
&lt;th&gt;vim-plug&lt;/th&gt;
&lt;th&gt;lazy.nvim&lt;/th&gt;
&lt;th&gt;Nota / Matiz&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Gestión de plugins (install/update)&lt;/td&gt;
&lt;td&gt;Sí&lt;/td&gt;
&lt;td&gt;Sí&lt;/td&gt;
&lt;td&gt;Ambos permiten instalar, actualizar y remover plugins fácilmente&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lazy loading de plugins&lt;/td&gt;
&lt;td&gt;Sí (manual, limitado)&lt;/td&gt;
&lt;td&gt;Sí (declarativo y avanzado)&lt;/td&gt;
&lt;td&gt;vim-plug requiere configuración manual con &lt;code&gt;on&lt;/code&gt;, &lt;code&gt;for&lt;/code&gt;, &lt;code&gt;cmd&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cache de estado (lockfiles, hashes)&lt;/td&gt;
&lt;td&gt;Parcial (&lt;code&gt;:PlugSnapshot&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;Sí (&lt;code&gt;lazy-lock.json&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;vim-plug permite snapshot, pero no lo gestiona ni lo aplica automáticamente&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cache de bytecode Lua (.luac)&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Sí&lt;/td&gt;
&lt;td&gt;lazy.nvim compila módulos Lua para acelerar el arranque&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Arranque optimizado&lt;/td&gt;
&lt;td&gt;Parcial (con lazy manual)&lt;/td&gt;
&lt;td&gt;Sí (caching + carga bajo demanda)&lt;/td&gt;
&lt;td&gt;lazy.nvim acelera usando cache + lazy loading automático&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Integración con configuración Lua&lt;/td&gt;
&lt;td&gt;No (Vimscript-first)&lt;/td&gt;
&lt;td&gt;Sí (nativo en Lua)&lt;/td&gt;
&lt;td&gt;vim-plug puede usarse con hacks en Lua, pero no está diseñado para eso&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="conceptos-fundamentales-para-usar-lazy"&gt;Conceptos fundamentales para usar lazy&lt;/h3&gt;
&lt;hr&gt;
&lt;h4 id="1-comentarios"&gt;1. Comentarios&lt;/h4&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="c1"&gt;-- Esto es un comentario&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;h4 id="2-variables"&gt;2. Variables&lt;/h4&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="kd"&gt;local&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;nombre&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Neovim"&lt;/span&gt;
&lt;span class="kd"&gt;local&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;numero&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;h4 id="3-tablas-como-diccionarios-o-listas"&gt;3. &lt;strong&gt;Tablas (como diccionarios o listas)&lt;/strong&gt;&lt;/h4&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="kd"&gt;local&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;opciones&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;number&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;relativenumber&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;h4 id="4-funciones"&gt;4. &lt;strong&gt;Funciones&lt;/strong&gt;&lt;/h4&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="kd"&gt;local&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;saludar&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Hola desde Lua"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kr"&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;h4 id="5-requiriendo-otros-archivos-modularizacion"&gt;5. &lt;strong&gt;Requiriendo otros archivos (modularización)&lt;/strong&gt;&lt;/h4&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="nb"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"usuario.options"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"usuario.plugins.lazy"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h3 id="ejemplo-concreto-de-migracion"&gt;Ejemplo concreto de migración&lt;/h3&gt;
&lt;p&gt;Usamos como punto de partida el archivo &lt;code&gt;~/.config/nvim/plugins.vim&lt;/code&gt; del &lt;a href="https://sergiobelkin.com/posts/como-convertir-tu-configuracion-de-initvim-a-initlua/"&gt;post anterior&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Camino a lazy.nvim" class="img-izquierda-responsiva" src="https://sergiobelkin.com/images/path-to-lazy.webp"&gt;&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="c"&gt;"Plugins (Plug)&lt;/span&gt;
&lt;span class="k"&gt;call&lt;/span&gt; plug#begin&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'~/.vim/plugged'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

Plug &lt;span class="s1"&gt;'itchyny/lightline.vim'&lt;/span&gt;
Plug &lt;span class="s1"&gt;'nyngwang/NeoTerm.lua'&lt;/span&gt;
Plug &lt;span class="s1"&gt;'NLKNguyen/papercolor-theme'&lt;/span&gt;

&lt;span class="k"&gt;call&lt;/span&gt; plug#&lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;lua&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&amp;lt;&lt;/span&gt; EOF                                                       
require&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"neo-term"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;.setup {
  exclude_filetypes &lt;span class="p"&gt;=&lt;/span&gt; { &lt;span class="s2"&gt;"oil"&lt;/span&gt; }
}                          
EOF

&lt;span class="nb"&gt;nnoremap&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;F4&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; :NeoTermToggle&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;CR&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
tnoremap &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;F4&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;C&lt;span class="p"&gt;-&lt;/span&gt;\&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;C&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="k"&gt;n&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;:NeoTermToggle&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;CR&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
tnoremap &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;Esc&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;C&lt;span class="p"&gt;-&lt;/span&gt;\&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;C&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="k"&gt;n&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;:NeoTermEnterNormal&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;CR&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;h4 id="clonar-el-repo"&gt;Clonar el repo&lt;/h4&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;git&lt;span class="w"&gt; &lt;/span&gt;clone&lt;span class="w"&gt; &lt;/span&gt;https://github.com/folke/lazy.nvim.git&lt;span class="w"&gt; &lt;/span&gt;~/.local/share/nvim/lazy/lazy.nvim
&lt;/pre&gt;&lt;/div&gt;

&lt;h4 id="prepara-el-entorno"&gt;Prepara el entorno&lt;/h4&gt;
&lt;p&gt;Creamos un directorio para la configuración de los plugins y otro para la configuración de lazy.nvim:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;~/.config/nvim/lua/lplugins&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Aquí estarán los archivos de configuración de los plugins&lt;/span&gt;
mkdir&lt;span class="w"&gt; &lt;/span&gt;~/.config/nvim/lua/config/
&lt;/pre&gt;&lt;/div&gt;

&lt;h4 id="configuracion-inicial"&gt;Configuración inicial&lt;/h4&gt;
&lt;p&gt;Partimos de este archivo:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="c1"&gt;-- Cargamos módulos&lt;/span&gt;

&lt;span class="kd"&gt;local&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;commands&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'utils.commands'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;local&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;extracommands&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'utils.extracommands'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;local&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;keymaps&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'keymaps'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;local&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;opciones&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'opciones'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;-- Mantenemos por ahora la configuración de plugins en Vim script&lt;/span&gt;
&lt;span class="nv"&gt;vim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'source ~/.config/nvim/plugins.vim'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Y hacemos las siguientes modificaciones:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="c1"&gt;-- Cargamos módulos&lt;/span&gt;

&lt;span class="kd"&gt;local&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;commands&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'utils.commands'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;local&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;extracommands&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'utils.extracommands'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;local&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;keymaps&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'keymaps'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;local&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;opciones&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'opciones'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;-- Mantenemos por ahora la configuración de plugins en Vim script&lt;/span&gt;
&lt;span class="c1"&gt;-- vim.cmd('source ~/.config/nvim/plugins.vim')&lt;/span&gt;
&lt;span class="c1"&gt;-- require("config.lazy")&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;¿Qué hicimos? Deshabilitar vim-plug y &lt;strong&gt;por ahora&lt;/strong&gt; dejar comentada la línea que llamará al archivo &lt;code&gt;~/.config/nvim/lua/config/lazy.lua&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Luego en dicho archivo pondremos lo siguiente:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="c1"&gt;-- Bootstrap lazy.nvim&lt;/span&gt;
&lt;span class="kd"&gt;local&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;lazypath&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;vim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stdpath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/lazy/lazy.nvim"&lt;/span&gt;
&lt;span class="kr"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;not&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;vim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;uv&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;or&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;vim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;fs_stat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;lazypath&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;then&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kd"&gt;local&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;lazyrepo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://github.com/folke/lazy.nvim.git"&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kd"&gt;local&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;out&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;vim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;system&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"git"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"clone"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"--filter=blob:none"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"--branch=stable"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;lazyrepo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;lazypath&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kr"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;vim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;shell_error&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;~=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;then&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;vim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;nvim_echo&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Failed to clone lazy.nvim:&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ErrorMsg"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;out&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"WarningMsg"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;Press any key to exit..."&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;vim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getchar&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;os.exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kr"&gt;end&lt;/span&gt;
&lt;span class="kr"&gt;end&lt;/span&gt;
&lt;span class="nv"&gt;vim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;opt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;rtp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nf"&gt;prepend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;lazypath&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;-- Make sure to setup `mapleader` and `maplocalleader` before&lt;/span&gt;
&lt;span class="c1"&gt;-- loading lazy.nvim so that mappings are correct.&lt;/span&gt;
&lt;span class="c1"&gt;-- This is also a good place to setup other settings (vim.opt)&lt;/span&gt;
&lt;span class="nv"&gt;vim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;g&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;mapleader&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;" "&lt;/span&gt;
&lt;span class="nv"&gt;vim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;g&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;maplocalleader&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="c1"&gt;-- Setup lazy.nvim&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"lazy"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;spec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;-- import your plugins&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"lplugins"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;-- Configure any other settings here. See the documentation for more details.&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;-- colorscheme that will be used when installing plugins.&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;install&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;colorscheme&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"habamax"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;-- automatically check for plugin updates&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;checker&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;enabled&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;h5 id="explicacion"&gt;Explicación&lt;/h5&gt;
&lt;h6 id="requirelazysetup"&gt;require("lazy").setup({ ... })&lt;/h6&gt;
&lt;p&gt;Es la función principal que inicia y configura los plugins en lazy.nvim.&lt;/p&gt;
&lt;h6 class=".." id="spec"&gt;spec =&lt;/h6&gt;
&lt;p&gt;Es el campo que indica &lt;strong&gt;la especificación de los plugins&lt;/strong&gt;. Es el lugar para definir qué plugins cargar.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="nv"&gt;spec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"lplugins.ui"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;Cada &lt;code&gt;{ import = "..." }&lt;/code&gt; carga los plugins definidos en otros archivos lua.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;En este caso, usamoos una configuración modular:&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;~/.config/nvim/lua/lplugins/ui.lua&lt;/code&gt; tendrá la especificación del plugin &lt;strong&gt;papercolor-theme&lt;/strong&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;~/.config/nvim/lua/lplugins/terminal.lua&lt;/code&gt; tendrá las especificaciones de los plugins &lt;strong&gt;lightline&lt;/strong&gt; y &lt;strong&gt;Neoterm&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h6 id="install-colorscheme-habamax"&gt;install = { colorscheme = { "habamax" } }&lt;/h6&gt;
&lt;p&gt;Establece un esquema de colores que se aplicará automáticamente en la interfaz del gestor de plugins.&lt;/p&gt;
&lt;h6 enabled id="checker"&gt;checker =&lt;/h6&gt;
&lt;p&gt;Activa el &lt;strong&gt;verificador automático de actualizaciones&lt;/strong&gt;. Cabe aclarar que esta configuración no los &lt;strong&gt;no los actualiza automáticamente&lt;/strong&gt;, pero te avisa para que los actualices mediante el comando en modo ex (&lt;code&gt;:Lazy update&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;En la configuración de partida teníamos solamente 3 plugins, pero decidimos dividirlos en dos categorías, a medida que vamos instalando más plugins podemos crear más archivos lua para clasificarlos.&lt;/p&gt;
&lt;h4 id="especificaciones-de-plugins"&gt;Especificaciones de plugins&lt;/h4&gt;
&lt;p&gt;Todos los archivos donde clasificás plugins deben tener la keyword return para que cada uno de ellos debe devuelva una tabla Lua con los plugins que querés que lazy.nvim cargue desde esos archivos.&lt;/p&gt;
&lt;p&gt;La siguiente es una plantilla de archivo en la cual se especifican plugins:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="kr"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s2"&gt;"autor/repositorio"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;--  Reemplazá con el nombre del autor y nombre del repositorio&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;-- lazy = false,         --  true para carga diferida, false para cargar al inicio&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;-- priority = 1000,      --  Opcional. Útil para temas de colores&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;-- event = nil,          --  Reemplazá con evento si usás lazy = true (ej: "BufReadPre")&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;-- cmd = nil,            --  Reemplazá si querés cargar al ejecutar un comando&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;-- dependencies = {},    --  Lista de plugins que este necesita (si aplica)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;-- config = function()&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;-- Poné acá la configuración del plugin&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;-- end&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Para echar un poco de 💡 a esta cuestión de los campos:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Campo&lt;/th&gt;
&lt;th&gt;¿Obligatorio?&lt;/th&gt;
&lt;th&gt;¿Qué hace?&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;"autor/repositorio"&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Sí&lt;/td&gt;
&lt;td&gt;Identifica el plugin (por ejemplo &lt;code&gt;"NLKNguyen/papercolor-theme"&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;config = function()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;No, pero común&lt;/td&gt;
&lt;td&gt;Configura el plugin al cargarlo&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;lazy = true/false&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Opcional&lt;/td&gt;
&lt;td&gt;Define si se carga de forma diferida o al inicio&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;priority = número&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Opcional&lt;/td&gt;
&lt;td&gt;Da prioridad de carga (útil para temas de colores)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;event = "InsertEnter"&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Opcional&lt;/td&gt;
&lt;td&gt;Carga el plugin al ocurrir cierto evento&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;cmd = "Comando"&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Opcional&lt;/td&gt;
&lt;td&gt;Carga el plugin cuando se ejecuta un comando&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;dependencies = {}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Opcional&lt;/td&gt;
&lt;td&gt;Especifica otros plugins requeridos&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Vamos a los &lt;strong&gt;ejemplos concretos 💪&lt;/strong&gt;&lt;/p&gt;
&lt;h5 id="archivo-uilua"&gt;Archivo ui.lua&lt;/h5&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="kr"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s2"&gt;"NLKNguyen/papercolor-theme"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;priority&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;-- para que se cargue antes que otros&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;lazy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="c1"&gt;-- para que se cargue en el arranque&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;config&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;                                                                                                                                       &lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nv"&gt;vim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"colorscheme PaperColor"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kr"&gt;end&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Esto significa:&lt;/p&gt;
&lt;p&gt;» Devuelvo una lista (tabla) con un solo plugin. Este plugin es NLKNguyen/papercolor-theme y quiero que se cargue al inicio, con prioridad alta, y que cuando se cargue, aplique el esquema de colores PaperColor.&lt;/p&gt;
&lt;h5 id="archivo-terminallua"&gt;Archivo terminal.lua&lt;/h5&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="kr"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;-- Plugin 1: lightline.vim&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s2"&gt;"itchyny/lightline.vim"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;config&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nv"&gt;vim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;g&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;lightline&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;colorscheme&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'solarized'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;-- &amp;lt;- podés cambiar por "jellybeans","OldHope", "wombat", "PaperColor", etc.&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kr"&gt;end&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;-- Separador de items en la lista&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;-- Plugin 2: NeoTerm.lua&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s2"&gt;"nyngwang/NeoTerm.lua"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;config&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nb"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"neo-term"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nv"&gt;setup&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;exclude_filetypes&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"oil"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;-- evita que se use en buffers del tipo "oil"&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;-- Atajos de teclado:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nv"&gt;vim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;keymap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"n"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;F4&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;":NeoTermToggle&amp;lt;CR&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;silent&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="c1"&gt;-- F4 en modo normal: alterna el terminal&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nv"&gt;vim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;keymap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"t"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;F4&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;C-&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;&amp;gt;&amp;lt;C-n&amp;gt;:NeoTermToggle&amp;lt;CR&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;silent&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="c1"&gt;-- F4 en modo terminal: lo mismo&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nv"&gt;vim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;keymap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"t"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;Esc&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;C-&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;&amp;gt;&amp;lt;C-n&amp;gt;:NeoTermEnterNormal&amp;lt;CR&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;silent&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;-- Esc en terminal: pasa a modo normal&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kr"&gt;end&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;-- Separador final, no es obligatorio pero conveniente&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Este archivo configura dos plugins:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;lightline.vim&lt;/strong&gt;: para una línea de estado personalizada.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;NeoTerm.lua&lt;/strong&gt;: para trabajar con terminales flotantes o integrados, y define atajos con &lt;strong&gt;F4&lt;/strong&gt; y &lt;strong&gt;Esc&lt;/strong&gt; para manejarlos fácilmente.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="habilitar-lazynvim"&gt;Habilitar lazy.nvim&lt;/h4&gt;
&lt;p&gt;Ya estamos casi listos, solamente falta quitar el comentario en el archivo &lt;code&gt;~/.config/nvim/init.lua&lt;/code&gt;:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="nb"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"config.lazy"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Eso es todo, la próxima vez, al entrar al editor, &lt;strong&gt;lazy.nvim&lt;/strong&gt; se encargará de instalar los plugins especificados.&lt;/p&gt;
&lt;p&gt;Es importante ejecutar el comando &lt;code&gt;:checkhealth lazy&lt;/code&gt; el cual hará un diagnóstico de la instalación y configuración:&lt;/p&gt;
&lt;p&gt;&lt;img alt="checkhealth" src="https://sergiobelkin.com/images/checkhealthlazy.webp"&gt;&lt;/p&gt;
&lt;h3 id="sacandole-provecho-a-lazynvim"&gt;Sacándole provecho a lazy.nvim&lt;/h3&gt;
&lt;p&gt;Vamos a instalar el plugin &lt;a href="https://github.com/folke/which-key.nvim"&gt;which-key&lt;/a&gt; el cual sirve para mostrar de una manera amigable los atajos de teclado configurados.&lt;/p&gt;
&lt;p&gt;Editamos el archivo de configuración &lt;code&gt;~/.config/nvim/lua/lplugins/ui.lua&lt;/code&gt;siguiendo la plantilla mencionada anteriormente:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="kr"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s2"&gt;"NLKNguyen/papercolor-theme"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;priority&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;-- para que se cargue antes que otros&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;lazy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="c1"&gt;-- para que se cargue en el arranque&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;config&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;                                                                                                                                       &lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nv"&gt;vim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"colorscheme PaperColor"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kr"&gt;end&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;                  &lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;                      &lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;                         &lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="s2"&gt;"folke/which-key.nvim"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;event&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"VeryLazy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;opts&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{},&lt;/span&gt;&lt;span class="w"&gt;              &lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;keys&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;leader&amp;gt;ff"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;cmd&amp;gt;edit ~/.config/nvim/init.lua&amp;lt;cr&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;desc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Edit init.lua"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;leader&amp;gt;fr"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;cmd&amp;gt;e #&amp;lt;cr&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;desc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Open recent file"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;leader&amp;gt;tt"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;cmd&amp;gt;terminal&amp;lt;cr&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;desc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Open terminal"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;leader&amp;gt;?"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"which-key"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;show&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;global&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;end&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;desc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Buffer Local Keymaps"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;leader&amp;gt;q"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;cmd&amp;gt;q&amp;lt;cr&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;desc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Quit"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;leader&amp;gt;w"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;cmd&amp;gt;w&amp;lt;cr&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;desc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Save"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;-- Grupos visibles (aunque no hacen nada por sí mismos)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;leader&amp;gt;f"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"+file"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;leader&amp;gt;t"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"+terminal"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Este plugin sirve para que al teclar:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;kbd&gt;Espacio&lt;/kbd&gt;&lt;kbd&gt;f&lt;/kbd&gt;&lt;kbd&gt;f&lt;/kbd&gt;  Abrirá el archivo &lt;code&gt;/.config/nvim/init.lua&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;kbd&gt;Espacio&lt;/kbd&gt;&lt;kbd&gt;f&lt;/kbd&gt;&lt;kbd&gt;r&lt;/kbd&gt;  Abrirá el archivo más reciente.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;... y así con cada uno de los atajos definidos, pero además veremos una ayuda en pantalla.&lt;/p&gt;
&lt;p&gt;Vamos a verlo en acción:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Ejemplo usando which-key" src="https://sergiobelkin.com/images/ejemplo-wk.webp"&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;1&lt;/code&gt; Al presionar &lt;code&gt;y&lt;/code&gt; ....&lt;/li&gt;
&lt;li&gt;&lt;code&gt;2&lt;/code&gt; Muestra que es &lt;strong&gt;Yank&lt;/strong&gt; que en el contexto de Vi/Vim/Neovim es copiar...&lt;/li&gt;
&lt;li&gt;&lt;code&gt;3&lt;/code&gt; Aparecen automágicamente las teclas que pueden acompañar a este comando 💪 &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Y listo.... el resto es cuestión de usar la UI de Lazy, y familiarizarse con sus subcomandos en modo Ex.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Lazy UI" src="https://sergiobelkin.com/images/LazyUI.webp"&gt;&lt;/p&gt;
&lt;h3 id="conclusion"&gt;Conclusión&lt;/h3&gt;
&lt;p&gt;&lt;img alt="Old but even new and fresh" class="img-izquierda-responsiva" src="https://sergiobelkin.com/images/oldButNEW.webp"&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;vim-plug&lt;/code&gt;&lt;/strong&gt; sigue siendo una opción robusta y popular, especialmente para usuarios de Vim clásico o entornos donde se necesita algo probado y ampliamente documentado.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Sin embargo, &lt;strong&gt;&lt;code&gt;lazy.nvim&lt;/code&gt;&lt;/strong&gt; es una solución moderna y centrada en &lt;em&gt;Neovim&lt;/em&gt;, con alta participación comunitaria y buena agilidad en el mantenimiento. Ideal para setups nuevos o si des#eas aprovechar la asincronía y mejoras de Lua en Neovim.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Siempre que puedas&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Consultá el &lt;code&gt;README&lt;/code&gt; oficial&lt;/li&gt;
&lt;li&gt;Buscá ejemplos en GitHub o Dotfiles de otros usuarios&lt;/li&gt;
&lt;li&gt;Explorá el código fuente si sabés Lua&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Estos tres artículos no han servidor para comenzar a usar Neovim, modernizar la configuración y utilizar un gestor de plugins nativo en Lua.
wSiempre que agregues un plugin, revisa su README y especifica las dependencias manualmente si no estás seguro. Lazy puede resolver muchas automáticamente, pero declararlas te da más control y claridad.&lt;/p&gt;
&lt;p&gt;Detrás de la fachada antigua, Neovim es un editor que adaptó su arquitectura a los nuevos tiempos.&lt;/p&gt;
&lt;p&gt;¡Felicitaciones si llegaste hasta acá?&lt;/p&gt;
&lt;h3 id="fuentes-y-mas-recursos"&gt;Fuentes y más recursos&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://lazy.folke.io/usage"&gt;¿Cómo es el proceso de arranque de Neovim?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://lazy.folke.io/usage"&gt;¿Cómo funciona y se usa Lazy.mvim&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kaustubhpatange.medium.com/how-neovim-helped-improve-my-productivity-4214dd099340"&gt;How Neovim helped improve my productivity - Kaustubh Patange - Medium&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description><category>vi/vim/neovim</category><guid>https://sergiobelkin.com/posts/como-migrar-de-vim-plug-a-lazynvim/</guid><pubDate>Sun, 01 Jun 2025 22:50:42 GMT</pubDate></item><item><title>¿Cómo convertir tu configuración de init.vim a init.lua?</title><link>https://sergiobelkin.com/posts/como-convertir-tu-configuracion-de-initvim-a-initlua/</link><dc:creator>sebelk</dc:creator><description>&lt;h3 id="requisitos"&gt;Requisitos&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Curiosidad&lt;/strong&gt;. Es la condición más importante para leer este post. Si la tendrás, con algo de esfuerzo sumado a algo de tiempo podrás aprender Vim, Neovim, etcº.&lt;/li&gt;
&lt;li&gt;Conocimientos básicos o intermedios de Vim y haber leído el &lt;a href="https://sergiobelkin.com/posts/una-introduccion-pragmatica-al-uso-de-plugins-en-neovim/"&gt;post anterior&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Conocimientos básicos de &lt;a href="https://github.com/junegunn/vim-plug"&gt;vim-plug&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="repaso-de-conceptos-importantes"&gt;Repaso de conceptos importantes&lt;/h3&gt;
&lt;p&gt;En el &lt;a href="https://sergiobelkin.com/posts/una-introduccion-pragmatica-al-uso-de-plugins-en-neovim/"&gt;post anterior&lt;/a&gt; vimos como un usuario de Vim puede comenzar a Neovim. En el presente artículo haremos la transición de &lt;strong&gt;Vim script&lt;/strong&gt;  a &lt;strong&gt;Lua&lt;/strong&gt;. Ok, booting the post 😄 ...&lt;/p&gt;
&lt;p&gt;&lt;img alt="De Vim script a Lua" class="img-izquierda-responsiva" src="https://sergiobelkin.com/images/bridge_with_Vim_script_Lua_web.webp"&gt;&lt;/p&gt;
&lt;p&gt;Recordemos que Vim usa &lt;strong&gt;Vim script&lt;/strong&gt; (aka VimL) como lenguaje de scripting nativo. Es un lenguaje específico que permite personalizar y extender su funcionalidad. Existe en dos formas: el Vim script tradicional (también llamado "legacy script") y Vim9script (introducido en Vim 9.0), que ofrece mejor rendimiento y una sintaxis más moderna. Sin embargo &lt;em&gt;Vim9script ni siquiera se usa de manera predeterminada en Vim 9.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Lua&lt;/strong&gt;, en cambio, es un lenguaje de programación ligero, de alto nivel y multiparadigma, diseñado principalmente para ser incorporado en aplicaciones. Se destaca por su simplicidad, eficiencia y portabilidad. &lt;strong&gt;Neovim&lt;/strong&gt; incorporó Lua como lenguaje de scripting alternativo, lo que ha ganado popularidad debido a su mejor rendimiento y facilidad de uso comparado con Vim script tradicional.&lt;/p&gt;
&lt;p&gt;Cabe remarcar  que &lt;strong&gt;Neovim usa una implementación de Lua llamada LuaJIT&lt;/strong&gt;. LuaJIT es capaz de compilar código Lua a código máquina nativo durante la ejecución, lo que resulta en un rendimiento significativamente superior al intérprete estándar de Lua. LuaJIT es ampliamente reconocido por su alta velocidad, siendo en muchos casos comparable al rendimiento de lenguajes compilados como C. En el contexto de Neovim, LuaJIT permite que los scripts escritos en Lua se ejecuten con un rendimiento muy superior la de Lua estándar.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Diferencia de idiosincrasia:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Vim script:&lt;/strong&gt; scripting lineal, global y directo. Bueno para pequeños ajustes, pero difícil de escalar.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Lua (Neovim):&lt;/strong&gt; lenguaje estructurado, orientado a modularizar, reusar y escalar. Favorece el uso de variables locales, tablas y funciones que mejoran el mantenimiento de la configuración.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Entonces:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Neovim usa LuaJIT para ejecutar configuraciones en Lua de forma rápida.&lt;/li&gt;
&lt;li&gt;Casi todas las instalaciones modernas de Neovim usan LuaJIT por defecto.&lt;/li&gt;
&lt;li&gt;Esto significa que los scripts y configuraciones Lua en Neovim corren a velocidades cercanas al código nativo.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Ventaja clave:&lt;/strong&gt;
Permite que Neovim con Lua sea mucho más rápido que Vim script o incluso &lt;strong&gt;Vim9script&lt;/strong&gt; en muchos casos.&lt;/p&gt;
&lt;h3 id="3-conceptos-esenciales-lo-minimo-que-siempre-debes-recordar"&gt;3 conceptos esenciales — lo mínimo que siempre debés recordar&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Concepto&lt;/th&gt;
&lt;th&gt;Por qué es esencial&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Tablas (&lt;code&gt;table&lt;/code&gt;)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Todo en Lua usa tablas&lt;/strong&gt;. Opciones (&lt;code&gt;vim.o&lt;/code&gt;, &lt;code&gt;vim.opt&lt;/code&gt;), autocmds, comandos, mappings y configuraciones de plugins.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Variables locales (&lt;code&gt;local&lt;/code&gt;)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Permiten organizar el código, evitar errores y mejorar el rendimiento. Imprescindible para no contaminar el entorno global.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;API de Neovim (&lt;code&gt;vim.api.*&lt;/code&gt;)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Es la manera oficial y flexible de interactuar con Neovim: crear comandos, autocmds, mappings y manipular el editor desde Lua.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Si entendés estos 3 conceptos, podés crear y mantener cualquier configuración básica y muchas avanzadas.&lt;/strong&gt;&lt;/p&gt;
&lt;h4 id="que-es-una-tabla-y-que-no-en-la-configuracion-de-neovim-lua"&gt;¿Qué es una tabla y qué no en la configuración de Neovim (Lua)&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;Tablas 🆗:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;vim.g&lt;/li&gt;
&lt;li&gt;vim.opt / vim.o&lt;/li&gt;
&lt;li&gt;vim.tbl_keys(...)&lt;/li&gt;
&lt;li&gt;Configuraciones de plugins&lt;/li&gt;
&lt;li&gt;Listas/patrones&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;No son tablas ⚠ :&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Funciones&lt;/li&gt;
&lt;li&gt;Comandos ejecutados&lt;/li&gt;
&lt;li&gt;Strings, números, booleanos&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="el-podio-de-las-tablas-madres-mas-importantes-en-neovim"&gt;El podio de las tablas madres más importantes en Neovim&lt;/h3&gt;
&lt;p&gt;Estas son las tres tablas raíz (madre) más importantes del entorno Lua en Neovim:&lt;/p&gt;
&lt;h4 id="vim"&gt;🏅  vim&lt;/h4&gt;
&lt;p&gt;Es la tabla principal y núcleo del entorno Lua en Neovim. Contiene todo lo necesario para interactuar con el editor:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Subtablas como &lt;code&gt;vim.api&lt;/code&gt;, &lt;code&gt;vim.cmd&lt;/code&gt;, &lt;code&gt;vim.opt&lt;/code&gt;, &lt;code&gt;vim.g&lt;/code&gt;, &lt;code&gt;vim.fn&lt;/code&gt;, etc.&lt;/li&gt;
&lt;li&gt;Siempre disponible sin necesidad de importar.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="_g"&gt;🥈 _G&lt;/h4&gt;
&lt;p&gt;Es la tabla global del lenguaje Lua. Desde aquí podés definir funciones o variables globales accesibles desde cualquier parte de tu configuración:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;_G.mi_funcion = function() ... end&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;También contiene &lt;code&gt;vim&lt;/code&gt; como una de sus claves.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="package-de-lua"&gt;🥉 package (de Lua)&lt;/h4&gt;
&lt;p&gt;Maneja los módulos cargados por &lt;code&gt;require&lt;/code&gt;. Es crucial para modularizar tu configuración:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;package.loaded&lt;/code&gt; permite ver y recargar módulos.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Nota&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Tablas como &lt;code&gt;vim.api&lt;/code&gt;, &lt;code&gt;vim.opt&lt;/code&gt;, &lt;code&gt;vim.g&lt;/code&gt; son importantes, pero &lt;strong&gt;no son madres&lt;/strong&gt;: viven dentro de &lt;code&gt;vim&lt;/code&gt;. Lo mismo aplica para &lt;code&gt;math&lt;/code&gt;, &lt;code&gt;string&lt;/code&gt;, &lt;code&gt;table&lt;/code&gt;, etc., que viven en &lt;code&gt;_G&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;→ Estas 3 (&lt;code&gt;vim&lt;/code&gt;, &lt;code&gt;_G&lt;/code&gt;, &lt;code&gt;package&lt;/code&gt;) forman la base del entorno ejecutable de cualquier configuración Neovim moderna en Lua.&lt;/p&gt;
&lt;h3 id="subtablas-mas-importantes"&gt;Subtablas más importantes&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tabla&lt;/th&gt;
&lt;th&gt;Contiene&lt;/th&gt;
&lt;th&gt;Ejemplo equivalente en Vim script&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;vim.o&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Opciones globales&lt;/td&gt;
&lt;td&gt;&lt;code&gt;set tabstop=4&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;vim.opt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Opciones globales que contienen listas&lt;/td&gt;
&lt;td&gt;&lt;code&gt;set nf+=alpha&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;vim.cmd&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Comandos que se ejecutan en modo ex&lt;/td&gt;
&lt;td&gt;&lt;code&gt;colorscheme PaperColor&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;vim.g&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Variables Globales&lt;/td&gt;
&lt;td&gt;&lt;code&gt;let g:loaded_perl_provider =&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;vim.keymap.set&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Asignación de atajos de teclado a una función o combinación de teclas&lt;/td&gt;
&lt;td&gt;&lt;code&gt;vim.keymap.set('n', 'ñ', ':wq&amp;lt;CR&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;vim.api.nvim_create_user_command&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Creación de comandos personalizados&lt;/td&gt;
&lt;td&gt;&lt;code&gt;command Nbuild execute 'w | Silent nikola build&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="diccionario-cruzado-vim-script-lua"&gt;Diccionario cruzado Vim script / Lua&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Concepto&lt;/th&gt;
&lt;th&gt;Vim script&lt;/th&gt;
&lt;th&gt;Lua&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Variable global&lt;/td&gt;
&lt;td&gt;&lt;code&gt;let g:mi_var = 10&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;vim.g.mi_var = 10&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Variable local&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;(no hay una manera clara)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;local var = 10&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lista&lt;/td&gt;
&lt;td&gt;&lt;code&gt;let lista = [1,2,3]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;lista = {1, 2, 3}&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Diccionario&lt;/td&gt;
&lt;td&gt;&lt;code&gt;let dict = {'a':1}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;dict = {a = 1}&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Función&lt;/td&gt;
&lt;td&gt;&lt;code&gt;function! Hola() ... end&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;function hola() ... end&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Función anónima&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;no hay&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;function() ... end&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Autocomando&lt;/td&gt;
&lt;td&gt;&lt;code&gt;autocmd BufWrite ...&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;vim.api.nvim_create_autocmd&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mapping&lt;/td&gt;
&lt;td&gt;&lt;code&gt;nnoremap&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;vim.keymap.set&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Comando&lt;/td&gt;
&lt;td&gt;&lt;code&gt;command ...&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;vim.api.nvim_create_user_command&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="comparativa-de-conceptos-clave-vim-script-vs-lua"&gt;Comparativa de conceptos clave: Vim script vs Lua&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Concepto&lt;/th&gt;
&lt;th&gt;Vim script&lt;/th&gt;
&lt;th&gt;Lua (Neovim)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Variables y configuración&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Variables globales (&lt;code&gt;let g:var&lt;/code&gt;), &lt;code&gt;set&lt;/code&gt; para opciones&lt;/td&gt;
&lt;td&gt;Tablas (&lt;code&gt;vim.g&lt;/code&gt;, &lt;code&gt;vim.o&lt;/code&gt;, &lt;code&gt;vim.opt&lt;/code&gt;) y variables locales (&lt;code&gt;local&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Automatización / lógica&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Funciones (&lt;code&gt;function!&lt;/code&gt;), comandos (&lt;code&gt;command&lt;/code&gt;), autocmds&lt;/td&gt;
&lt;td&gt;Funciones anónimas y definidas, &lt;code&gt;vim.api.*&lt;/code&gt;, autocmds con &lt;code&gt;vim.api.nvim_create_autocmd&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Extensibilidad y estructura&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Scripts planos, difícil modularizar&lt;/td&gt;
&lt;td&gt;Modularización con &lt;code&gt;require&lt;/code&gt;, &lt;code&gt;package.loaded&lt;/code&gt;, uso de archivos Lua por secciones&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="ejemplo-de-migracion-vim-script-lua"&gt;Ejemplo de migración Vim script → Lua&lt;/h3&gt;
&lt;p&gt;Bueno, con la  teoría suficiente, ✋✋ a la obra 😉. Supongamos que tenemos esta configuración de archivo init.vim:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="k"&gt;set&lt;/span&gt; &lt;span class="nb"&gt;tabstop&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;
&lt;span class="k"&gt;set&lt;/span&gt; &lt;span class="nb"&gt;nf&lt;/span&gt;&lt;span class="p"&gt;+=&lt;/span&gt;alpha

&lt;span class="nb"&gt;nnoremap&lt;/span&gt; ñ :&lt;span class="k"&gt;wq&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;CR&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

command &lt;span class="p"&gt;-&lt;/span&gt;nargs&lt;span class="p"&gt;=+&lt;/span&gt; Silent execute &lt;span class="s1"&gt;'silent !&amp;lt;args&amp;gt;'&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="k"&gt;redraw&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;
command Nbuild execute &lt;span class="s1"&gt;'w | Silent nikola build'&lt;/span&gt;

&lt;span class="k"&gt;filetype&lt;/span&gt; plugin &lt;span class="k"&gt;on&lt;/span&gt;
runtime plugins.&lt;span class="k"&gt;vim&lt;/span&gt;
&lt;span class="k"&gt;colorscheme&lt;/span&gt; PaperColor
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Es un archivo pequeño, pero que sirve de punto de partida para moverse a una configuración en Lua.&lt;/p&gt;
&lt;h4 id="crear-el-entorno-para-neovim"&gt;Crear el entorno para Neovim&lt;/h4&gt;
&lt;p&gt;&lt;img alt="El sistema modular de Neovim" class="img-izquierda-responsiva" src="https://sergiobelkin.com/images/ElsistemamodulardeNeovim.webp"&gt;&lt;/p&gt;
&lt;p&gt;Como vimos en el post anterior, mi recomendación es comenzar con un archivo &lt;code&gt;init.vim&lt;/code&gt;. Una vez que ya estamos usando Neovim podemos realizar la migración &lt;code&gt;init.lua&lt;/code&gt;. Sin embargo, tenemos que crear los directorios para que Neovim guarde su configuración. Lo único que dejaremos por ahora en Vim script es la configuración de plugins con &lt;strong&gt;vim-plug&lt;/strong&gt;. Por lo tanto ejecutamos:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;~/.config/nvim/lua/utils
mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;~/.local/share/nvim/site/autoload
&lt;span class="c1"&gt;# Suponiendo que usabas un archivo para  &lt;/span&gt;
mv&lt;span class="w"&gt; &lt;/span&gt;~/.vim/autoload/plug.vim&lt;span class="w"&gt;  &lt;/span&gt;~/.local/share/nvim/site/autoload
&lt;/pre&gt;&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;El directorio ~/.config/nvim es obligatorio.&lt;/li&gt;
&lt;li&gt;El directorio ~/.config/nvim/lua &lt;em&gt;no&lt;/em&gt; es obligatorio, pero es muy útil para modularizar la configuración de Neovim.&lt;/li&gt;
&lt;li&gt;Los nombres dados de los archivos y directorios dentroo de &lt;code&gt;~/.config/nvim/lua&lt;/code&gt; son totalmente arbitrarios.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;En Neovim tendremos una estructura más modular. Si bien, podemos, tener, todo en &lt;code&gt;init.lua&lt;/code&gt;, vamos a aprovecharnos de esta configuración que es mucho más flexible.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Archivo ~/.config/nvim/init.lua&lt;/strong&gt;&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="c1"&gt;-- Cargamos nuestros módulos&lt;/span&gt;

&lt;span class="kd"&gt;local&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;commands&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'utils.commands'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;local&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;extracommands&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'utils.extracommands'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;local&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;keymaps&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'keymaps'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;local&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;opciones&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'opciones'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="c1"&gt;-- Mantenemos por ahora la configuración de plugins en Vim script&lt;/span&gt;
&lt;span class="nv"&gt;vim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'source ~/.config/nvim/plugins.vim'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Archivo ~/.config/nvim/keymaps.lua&lt;/strong&gt;&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="c1"&gt;-- Alias&lt;/span&gt;
&lt;span class="kd"&gt;local&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;map&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;vim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;keymap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;set&lt;/span&gt;&lt;span class="w"&gt;                                                                         &lt;/span&gt;
&lt;span class="c1"&gt;-- maps&lt;/span&gt;
&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'n'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'ñ'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;':wq&amp;lt;CR&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Archivo ~/.config/nvim/lua/opciones.lua&lt;/strong&gt;&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="c1"&gt;-- Alias&lt;/span&gt;
&lt;span class="kd"&gt;local&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;vo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;vim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;o&lt;/span&gt;
&lt;span class="kd"&gt;local&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;vop&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;vim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;opt&lt;/span&gt;

&lt;span class="c1"&gt;-- Opciones&lt;/span&gt;
&lt;span class="nv"&gt;vo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;tabstop&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;
&lt;span class="nv"&gt;vop&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;nf&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'alpha'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Archivo ~/.config/nvim/lua/utils/commands.lua&lt;/strong&gt;&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="c1"&gt;-- Crea una tabla vacía para guardar funciones&lt;/span&gt;

&lt;span class="kd"&gt;local&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;M&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="kr"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;M&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create_command&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;command_or_function&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nb"&gt;pcall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;vim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;nvim_del_user_command&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;vim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;nvim_create_user_command&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;command_or_function&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;opts&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;or&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt;
&lt;span class="kr"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;-- Alias&lt;/span&gt;
&lt;span class="kd"&gt;local&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;com&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;M&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;create_command&lt;/span&gt;

&lt;span class="nf"&gt;com&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Silent'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;vim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'silent !'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;table.concat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;fargs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;' '&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;vim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'redraw!'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kr"&gt;end&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;nargs&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'+'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="nf"&gt;com&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Nbuild'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;vim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'w'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;vim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'silent nikola build'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kr"&gt;end&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt;


&lt;span class="kr"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;M&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Archivo ~/.config/nvim/lua/utils/extracommands.lua&lt;/strong&gt;&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="c1"&gt;-- Alias&lt;/span&gt;
&lt;span class="kd"&gt;local&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;vcmd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;vim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;cmd&lt;/span&gt;

&lt;span class="c1"&gt;-- Extra commands&lt;/span&gt;
&lt;span class="nf"&gt;vcmd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'filetype plugin on'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;-- Esta configuración es innecesaria ya está en init.lua&lt;/span&gt;
&lt;span class="c1"&gt;-- vcmd('runtime plugins.vim')&lt;/span&gt;
&lt;span class="nf"&gt;vcmd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'colorscheme PaperColor'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Archivo ~/.config/nvim/plugins.vim&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Este es el único archivo que lo dejamos en Vim script (con código Lua embebido incluido):&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="c"&gt;"Plugins (Plug)&lt;/span&gt;
&lt;span class="k"&gt;call&lt;/span&gt; plug#begin&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'~/.vim/plugged'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

Plug &lt;span class="s1"&gt;'itchyny/lightline.vim'&lt;/span&gt;
Plug &lt;span class="s1"&gt;'nyngwang/NeoTerm.lua'&lt;/span&gt;
Plug &lt;span class="s1"&gt;'NLKNguyen/papercolor-theme'&lt;/span&gt;

&lt;span class="k"&gt;call&lt;/span&gt; plug#&lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;lua&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&amp;lt;&lt;/span&gt; EOF                                                       
require&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"neo-term"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;.setup {
  exclude_filetypes &lt;span class="p"&gt;=&lt;/span&gt; { &lt;span class="s2"&gt;"oil"&lt;/span&gt; }
}                          
EOF

&lt;span class="nb"&gt;nnoremap&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;F4&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; :NeoTermToggle&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;CR&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
tnoremap &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;F4&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;C&lt;span class="p"&gt;-&lt;/span&gt;\&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;C&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="k"&gt;n&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;:NeoTermToggle&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;CR&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
tnoremap &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;Esc&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;C&lt;span class="p"&gt;-&lt;/span&gt;\&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;C&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="k"&gt;n&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;:NeoTermEnterNormal&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;CR&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Y Listo...&lt;/p&gt;
&lt;h4 id="explicacion"&gt;Explicación&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;¿Por qué definimos alias en los 3 archivos de módulos?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Los alias son básicamente variables. Los definimos porque este es un ejemplo de tipo "esqueleto" de configuración. Cuando comiences a agregar, más opciones, atajos de teclado y comandos personalizados, no querrás etipear tanto 😉.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;¿Para qué agregamos la función &lt;code&gt;create_command&lt;/code&gt;?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;En Lua cuando usás la API de Neovim, si querés redefinir una función de un comando personalizado, tenés que borrarlo y volver definirlo, sino da error. Esto es para evitar sobreescrituras accidentales. Por eso creamos la función &lt;code&gt;create_command&lt;/code&gt; para que cuando redefinamos un comando lo hagamos de manera explícita.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Usa &lt;code&gt;pcall&lt;/code&gt; para borrar el comando personalizado y si no existe no da error. &lt;/li&gt;
&lt;li&gt;Vuelve a recrearlo con la nueva definición.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;¿Acaso el comando Nbuild hace lo mismo en Vim script que en Lua? Vamos a analizarlo.&lt;/p&gt;
&lt;h5 id="1-brevedad-vs-mantenibilidad"&gt;1. &lt;strong&gt;Brevedad vs mantenibilidad&lt;/strong&gt;&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;VimL:&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;vim
  command -nargs=+ Silent execute 'silent !&amp;lt;args&amp;gt;' | redraw!
  command Nbuild execute 'w | Silent nikola build'&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Es breve, directo y funciona. Pero:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Es poco &lt;strong&gt;expresivo&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;No permite &lt;strong&gt;manejar errores&lt;/strong&gt; fácilmente&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;No escala bien con lógica compleja&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Lua:&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;lua
  com('Silent', function(opts)
    vim.cmd('silent !' .. table.concat(opts.fargs, ' '))
    vim.cmd('redraw!')
  end, { nargs = '+' })&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Es más verboso, sí, pero:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;La función puede ser más compleja si se necesita&lt;/li&gt;
&lt;li&gt;Es &lt;strong&gt;programable&lt;/strong&gt; y &lt;strong&gt;reutilizable&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Puede integrarse con condicionales, bucles, o lógica externa&lt;/li&gt;
&lt;/ul&gt;
&lt;h5 id="2-control-de-errores-y-depuracion"&gt;2. &lt;strong&gt;Control de errores y depuración&lt;/strong&gt;&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;En VimL: si un comando falla, tenés poco margen para capturar y manejar el error.&lt;/li&gt;
&lt;li&gt;En Lua: podés usar &lt;code&gt;pcall&lt;/code&gt;, &lt;code&gt;vim.notify&lt;/code&gt;, &lt;code&gt;vim.fn.systemlist&lt;/code&gt;, y &lt;strong&gt;construir mensajes personalizados o fallback&lt;/strong&gt; si algo sale mal.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="kd"&gt;local&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;_&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;pcall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kr"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;vim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'silent !nikola build'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kr"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kr"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;not&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;ok&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;then&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;vim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;notify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Error al ejecutar nikola build'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;vim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;levels&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;ERROR&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kr"&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;h5 id="3-modularizacion"&gt;3. &lt;strong&gt;Modularización&lt;/strong&gt;&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;En Lua podés agrupar comandos en módulos, con &lt;code&gt;require(...)&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;En VimL tenés que recurrir a &lt;code&gt;runtime&lt;/code&gt;, &lt;code&gt;source&lt;/code&gt;, y no hay namespaces claros.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="kd"&gt;local&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;commands&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'utils.commands'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;commands&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create_command&lt;/span&gt;&lt;span class="p"&gt;(...)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Esto &lt;strong&gt;facilita dividir la configuración en archivos lógicos&lt;/strong&gt;, más fácil de leer, mantener y compartir.&lt;/p&gt;
&lt;h5 id="4-compatibilidad-futura-y-ecosistema-neovim"&gt;4. &lt;strong&gt;Compatibilidad futura y ecosistema Neovim&lt;/strong&gt;&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;Neovim ha declarado que Lua es su &lt;strong&gt;lenguaje de configuración nativo moderno&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;La mayoría de los &lt;strong&gt;plugins modernos están escritos en Lua&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;VimL sigue siendo soportado, pero está &lt;strong&gt;siendo superado funcionalmente&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h5 id="5-legibilidad-a-largo-plazo"&gt;5. &lt;strong&gt;Legibilidad a largo plazo&lt;/strong&gt;&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Aunque VimL sea más corto, en un entorno de colaboración o con configuraciones grandes, Lua:&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Es más &lt;strong&gt;explícito&lt;/strong&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;Permite &lt;strong&gt;documentar&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;La API de Neovim en Lua permite &lt;strong&gt;un uso más explícito y predecible de tipos de datos&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Es más &lt;strong&gt;fácil de extender&lt;/strong&gt; con lógica externa.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="conclusion"&gt;Conclusión&lt;/h3&gt;
&lt;p&gt;Si sabés migrar opciones, mappings, comandos y cargar plugins → podés convertir el 80% o más de tu &lt;code&gt;init.vim&lt;/code&gt; (equivalente el viejo &lt;code&gt;.vimrc&lt;/code&gt;) a &lt;code&gt;init.lua&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Migrar tu configuración de Neovim de Vim script a Lua no solo representa una mejora técnica inmediata, sino también una oportunidad para afilar tu pensamiento en términos de estructura, modularidad y optimización.&lt;/p&gt;
&lt;p&gt;Lua te invita a organizar tu configuración como un sistema flexible y componible, donde cada parte puede ser reutilizada, testeada y afinada con precisión. Este tipo de enfoque —más declarativo, más explícito— entrena tu mente en formas modernas de entender y construir software.&lt;/p&gt;
&lt;p&gt;A medida que domines la integración de herramientas, el manejo eficiente de datos y la automatización de tareas dentro de Neovim, estarás cultivando hábitos que trascienden tu editor: aprenderás a diseñar entornos complejos donde múltiples componentes cooperan de forma orquestada.&lt;/p&gt;
&lt;p&gt;Esa forma de pensar, de buscar la mejora continua y construir sistemas cada vez más elegantes y potentes, es lo que hoy distingue a los profesionales más relevantes del ecosistema tecnológico.&lt;/p&gt;
&lt;h3 id="apendice-los-10-conceptos-fundamentales-de-lua-resumen"&gt;Apéndice : Los 10 conceptos fundamentales de Lua (resumen)&lt;/h3&gt;
&lt;p&gt;Si querés profundizar, te propongo 7 conceptos extra para profundizar en el uso de Lua en Neovim:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Concepto&lt;/th&gt;
&lt;th&gt;Descripción breve&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Tablas (&lt;code&gt;table&lt;/code&gt;)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Estructuras clave-valor o listas. Base de toda la configuración.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Variables locales (&lt;code&gt;local&lt;/code&gt;)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Para mantener el código limpio y evitar contaminación global.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Funciones anónimas&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Permiten definir acciones sin nombre, usadas en mappings, autocmds y comandos.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;API de Neovim (&lt;code&gt;vim.api.*&lt;/code&gt;)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Puente entre Lua y Neovim: crear comandos, mappings, autocmds.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;vim.opt&lt;/code&gt; vs &lt;code&gt;vim.o&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Para configurar opciones. &lt;code&gt;vim.o&lt;/code&gt; para valores simples, &lt;code&gt;vim.opt&lt;/code&gt; para manipular listas.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;require&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Para cargar módulos externos y dividir la configuración.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Paréntesis en llamadas&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Obligatorio usar &lt;code&gt;()&lt;/code&gt; al llamar funciones.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Referencias&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Asignar una tabla a otra variable sin copiarla (ejemplo: &lt;code&gt;local vg = vim.g&lt;/code&gt;).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;\_G (global)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Tabla especial que contiene las variables y funciones globales accesibles en toda la configuración.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;package.loaded&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Permite ver o manipular qué módulos están cargados, útil para recargar configuraciones dinámicamente.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="fuentes-y-mas-recursos"&gt;Fuentes y más Recursos&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://neovim.io/doc/user/lua.html"&gt;Lua en Neovim&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://luascripts.com/neovim-lua"&gt;Mastering Neovim Lua: Quick Tips for Effortless Coding&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/NeogitOrg/neogit"&gt;An interactive and powerful Git interface for Neovim, inspired by Magit&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/tolomeo/a-pragmatic-approach-to-migrating-from-vscode-to-neovim-4fae"&gt;A pragmatic approach to migrating from VSCode to Neovim&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://toxigon.com/how-to-use-neovim-in-linux"&gt;Mastering Neovim on Linux: A Step-by-Step Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://sergiobelkin.com/posts/como-convertir-tu-configuracion-de-initvim-a-initlua/NeoVim%20Is%20Better,%20But%20Why%20Developers%20Aren't%20Switching%20To%20It?"&gt;NeoVim Is Better, But Why Developers Aren't Switching To It?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://markaicode.com/neovim-10-setup-ai-plugins-lsp/"&gt;NeoVim 10.0 Setup for 2025: AI Plugins and LSP Configuration&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description><category>vi/vim/neovim</category><guid>https://sergiobelkin.com/posts/como-convertir-tu-configuracion-de-initvim-a-initlua/</guid><pubDate>Thu, 15 May 2025 19:01:18 GMT</pubDate></item><item><title>Cómo Hacer Túneles SSH</title><link>https://sergiobelkin.com/posts/tuneles-ssh/</link><dc:creator>sebelk</dc:creator><description>&lt;p&gt;Una de las funcionalidades extraordinarias que posee openssh es la de encapsular el tráfico inseguro a puertos TCP. A continuación vemos algunos ejemplos útiles de cuándo y cómo utilizarlos.&lt;/p&gt;
&lt;p&gt;&lt;a class="image-reference" href="https://sergiobelkin.com/images/aaron-burden-gmy25xvSkq8-unsplash.jpg"&gt;&lt;img src="https://sergiobelkin.com/images/aaron-burden-gmy25xvSkq8-unsplash.thumbnail.jpg" alt="Túneles"&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;&lt;a style='background-color:black;color:white;text-decoration:none;padding:4px 6px;font-family:-apple-system, BlinkMacSystemFont, "San Francisco", "Helvetica Neue", Helvetica, Ubuntu, Roboto, Noto, "Segoe UI", Arial, sans-serif;font-size:12px;font-weight:bold;line-height:1.2;display:inline-block;border-radius:3px' href="https://unsplash.com/@aaronburden?utm_medium=referral&amp;amp;utm_campaign=photographer-credit&amp;amp;utm_content=creditBadge" target="_blank" rel="noopener noreferrer" title="Download free do whatever you want high-resolution photos from Aaron Burden"&gt;&lt;span style="display:inline-block;padding:2px 3px"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" style="height:12px;width:auto;position:relative;vertical-align:middle;top:-2px;fill:white" viewbox="0 0 32 32"&gt;&lt;title&gt;unsplash-logo&lt;/title&gt;&lt;path d="M10 9V0h12v9H10zm12 5h10v18H0V14h10v9h12v-9z"&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/span&gt;&lt;span style="display:inline-block;padding:2px 3px"&gt;Aaron Burden&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Algunas suposiciones:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;openssh-server.example.com&lt;/code&gt;: Es el host que posee el servicio ssh y el servicio sin cifrar&lt;/li&gt;
&lt;li&gt;&lt;code&gt;otrohost.example.com&lt;/code&gt;: Es un host que posee un servidor web sin TLS pero que carece de ssh.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;192.0.2.1/24&lt;/code&gt;: Es la dirección IP del cliente ssh.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;filtrado.example.com&lt;/code&gt;: Es un host que tiene el puerto del servicio al que queremos acceder pero se encuentra filtrado para el exterior.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;casa.example.com&lt;/code&gt;: Es un host remoto respecto a un servidor ssh accesible desde la red de &lt;code&gt;filtrado.example.com&lt;/code&gt;. Este host está en un lugar en el cual podemos trabajar cómodamente 😊 por fuera de la infraestructura de &lt;code&gt;filtrado.example.com&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="caso-1-redireccionado-desde-un-puerto-local-a-un-puerto-remoto-para-segurizar-un-servicio-sin-cifrar"&gt;Caso 1: Redireccionado desde un puerto local a un puerto remoto para segurizar un servicio sin cifrar&lt;/h4&gt;
&lt;blockquote&gt;
&lt;p&gt;Queremos segurizar el acceso a un servidor web sin TLS.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;code&gt;ssh -N -f  -L 10001:localhost:80 openssh-server.example.com&lt;/code&gt; &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;80&lt;/code&gt;: Es el puerto que tiene el servicio sin cifrar&lt;/li&gt;
&lt;li&gt;&lt;code&gt;localhost&lt;/code&gt;: Es la dirección en el host servicio-remoto.example.com que escucha en el puerto 80.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;10001&lt;/code&gt;: Es el puerto local al cual tendremos que conectarnos para obtener el servicio web.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-N&lt;/code&gt; No ejecuta comandos en el lado remoto.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-f&lt;/code&gt; El proceso va al segundo plazo antes de la ejecución de comandos.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;El url que habrá que poner en el navegador es http://localhost:10001&lt;/strong&gt;&lt;/p&gt;
&lt;h4 id="caso-2-redireccionado-desde-un-puerto-local-a-un-puerto-remoto-permitiendo-el-acceso-al-tunel-usuarios-de-la-misma-red-local-para-segurizar-un-servicio-sin-cifrar"&gt;Caso 2: Redireccionado desde un puerto local a un puerto remoto permitiendo el acceso al túnel usuarios de la misma red local para Segurizar un servicio sin cifrar&lt;/h4&gt;
&lt;blockquote&gt;
&lt;p&gt;Queremos permitir que otros hosts de la red puedan acceder nuestro servicio encapsulado.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;code&gt;ssh -g -N -f -L 10001:localhost:80 openssh-server.example.com&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;-g&lt;/code&gt; Permite acceder a otros hosts de la red 192.0.2.0/24 acceder a el url &lt;strong&gt;http://192.0.2.1:10001/&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="caso-3-redireccionado-desde-un-puerto-local-a-un-puerto-remoto-usando-otro-servidor-ssh-para-acceder-a-un-servicio-sin-tls-ni-ssh"&gt;Caso 3: Redireccionado desde un puerto local a un puerto remoto usando otro servidor ssh para acceder a un servicio sin TLS ni ssh&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;ssh  -N -f -L 10001:otrohost.example.com:80 openssh-server.example.com&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Aquí la url será &lt;strong&gt;http://localhost:10001&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="caso-4-crear-un-tunel-en-direccion-inversa-para-acceder-a-un-puerto-ssh-filtrado-utilizacion-de-un-tunel-remoto"&gt;Caso 4: Crear un túnel en dirección inversa para acceder a un puerto SSH filtrado (utilización de un túnel remoto)&lt;/h4&gt;
&lt;p&gt;En este caso, queremos acceder al puerto SSH de &lt;code&gt;filtrado.example.com&lt;/code&gt;, que no es accesible desde internet. Utilizamos &lt;code&gt;casa.example.com&lt;/code&gt; con acceso SSH temporal para redirigir el puerto SSH de &lt;code&gt;filtrado.example.com&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;El comando debe ejecutarse en &lt;strong&gt;&lt;code&gt;filtrado.example.com&lt;/code&gt;&lt;/strong&gt;:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;ssh&lt;span class="w"&gt;  &lt;/span&gt;-N&lt;span class="w"&gt; &lt;/span&gt;-f&lt;span class="w"&gt; &lt;/span&gt;-R&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;9000&lt;/span&gt;:localhost:22&lt;span class="w"&gt; &lt;/span&gt;casa.example.com
&lt;/pre&gt;&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;22&lt;/code&gt;&lt;/strong&gt;: Es el puerto SSH de &lt;code&gt;filtrado.example.com&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;9000&lt;/code&gt;&lt;/strong&gt;: Es el puerto redirigido en &lt;code&gt;casa.example.com&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Para conectarse al puerto SSH de &lt;code&gt;filtrado.example.com&lt;/code&gt; desde &lt;code&gt;casa.example.com&lt;/code&gt;:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;ssh&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;9000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;localhost
&lt;/pre&gt;&lt;/div&gt;

&lt;h4 id="caso-5-redireccionamiento-remoto-para-permitir-acceso-compartido-a-un-puerto-filtrado"&gt;Caso 5: Redireccionamiento remoto para permitir acceso compartido a un puerto filtrado&lt;/h4&gt;
&lt;p&gt;En este caso, queremos redirigir el puerto SSH de un servidor filtrado (&lt;code&gt;filtrado.example.com&lt;/code&gt;) hacia un servidor intermedio (&lt;code&gt;casa.example.com&lt;/code&gt;) y permitir que otros hosts que están en la misma red local puedan acceder al túnel.&lt;/p&gt;
&lt;p&gt;Comando para configurar el túnel:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;ssh&lt;span class="w"&gt;  &lt;/span&gt;-N&lt;span class="w"&gt; &lt;/span&gt;-f&lt;span class="w"&gt; &lt;/span&gt;-R&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.0.0.0:9000:localhost:22&lt;span class="w"&gt; &lt;/span&gt;casa.example.com
&lt;/pre&gt;&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;0.0.0.0:9000&lt;/code&gt;&lt;/strong&gt;: Permite que el puerto redirigido esté accesible en todas las interfaces de red de &lt;code&gt;casa.example.com&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;localhost:22&lt;/code&gt;&lt;/strong&gt;: Redirige el tráfico al puerto SSH de &lt;code&gt;filtrado.example.com&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Para conectarse al túnel desde cualquier host con acceso a &lt;code&gt;casa.example.com&lt;/code&gt;:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;ssh&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;9000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;casa.example.com
&lt;/pre&gt;&lt;/div&gt;

&lt;h5 id="requisito-en-casaexamplecom"&gt;Requisito en casa.example.com&lt;/h5&gt;
&lt;p&gt;Habilitar &lt;code&gt;GatewayPorts&lt;/code&gt; en &lt;code&gt;/etc/ssh/sshd_config&lt;/code&gt;:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;GatewayPorts&lt;span class="w"&gt; &lt;/span&gt;clientspecified
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Con esta configuración si el cliente no especifica explícitamente 0.0.0.0 al crear el túnel, los puertos siguen siendo locales por defecto.&lt;/p&gt;
&lt;p&gt;Reinicia el servicio SSH:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;systemctl&lt;span class="w"&gt; &lt;/span&gt;restart&lt;span class="w"&gt; &lt;/span&gt;sshd
&lt;/pre&gt;&lt;/div&gt;

&lt;h5 id="notas-de-seguridad"&gt;Notas de Seguridad&lt;/h5&gt;
&lt;p&gt;Si el servidor &lt;code&gt;casa.example.com&lt;/code&gt; tiene una IP pública, usar firewalls para limitar el acceso al puerto &lt;code&gt;9000&lt;/code&gt; y restringirlo solo a las máquinas necesarias. Para mayor seguridad, se puede especificar una interfaz específica en lugar de &lt;code&gt;0.0.0.0&lt;/code&gt;.&lt;/p&gt;
&lt;h5 id="troubleshooting"&gt;Troubleshooting&lt;/h5&gt;
&lt;p&gt;En todas las casos usar la opción &lt;code&gt;-v&lt;/code&gt; para obtener realizar debugging. Recordar que dicha opcioń se puede usar múltiples veces para aumentar el detalle.&lt;/p&gt;</description><category>ssh</category><guid>https://sergiobelkin.com/posts/tuneles-ssh/</guid><pubDate>Mon, 18 Nov 2024 00:00:03 GMT</pubDate></item><item><title>Como instalar Zabbix 7.x usando contenedores podman</title><link>https://sergiobelkin.com/posts/como-instalar-zabbix-7x-usando-contenedores-podman/</link><dc:creator>sebelk</dc:creator><description>&lt;div style="float: left; margin-right: 10px; width: 200px; max-width: 100%;"&gt;
&lt;a class="image-reference" href="https://sergiobelkin.com/images/zabbix-podman.webp"&gt;&lt;img src="https://sergiobelkin.com/images/zabbix-podman.thumbnail.webp" alt="Namespaces en Linux"&gt;&lt;/a&gt; 
&lt;/div&gt;

&lt;p&gt;Zabbix es una potente herramienta de monitoreo. Recientemente salió la versión 7.0 la cual incorporó funcionalidades importantes, como son los items de browser que usan webdrivers. A continuación veremos como implementar Zabbix 7.x usando podman.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;La guía siguiente supone que:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Ya generaste o adquiriste los certificados ssl.&lt;/li&gt;
&lt;li&gt;Tenés los conocimientos fundamentales sobre Linux (usamos RHEL8).&lt;/li&gt;
&lt;li&gt;Poseés conocimientos básicos de troubleshooting en contenedores y entendiendo que este "HowTo" es un punto al que deberás adaptar a tu entorno y necesidades. No es consultoría 😀.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="1-crear-el-pod-con-puertos-correctos"&gt;1. Crear el Pod con Puertos Correctos&lt;/h3&gt;
&lt;p&gt;Primero, crear el pod con el puerto 443 en el host mapeado al puerto 8443 en el contenedor de NGINX. También asignar el puerto 10051 para Zabbix Server.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;podman&lt;span class="w"&gt; &lt;/span&gt;pod&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;--name&lt;span class="w"&gt; &lt;/span&gt;zabbix&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;443&lt;/span&gt;:8443&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10051&lt;/span&gt;:10051
&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h3 id="2-desplegar-el-contenedor-mysql"&gt;2. Desplegar el Contenedor MySQL&lt;/h3&gt;
&lt;p&gt;Iniciar el contenedor &lt;code&gt;mysql-server&lt;/code&gt; dentro del pod, configurando las variables de entorno necesarias para la base de datos de Zabbix:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;mysql&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;podman&lt;span class="w"&gt; &lt;/span&gt;run&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;--name&lt;span class="w"&gt; &lt;/span&gt;mysql-server&lt;span class="w"&gt; &lt;/span&gt;--pod&lt;span class="o"&gt;=&lt;/span&gt;zabbix&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;-v&lt;span class="w"&gt; &lt;/span&gt;./mysql:/var/lib/mysql:Z&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;-e&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;MYSQL_DATABASE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"zabbix"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;-e&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;MYSQL_USER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"zabbix"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;-e&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;MYSQL_PASSWORD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"zabbix_pwd"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;-e&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;MYSQL_ROOT_PASSWORD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"root_pwd"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;docker.io/library/mysql:8.0
&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h3 id="3-configurar-log_bin_trust_function_creators-en-mysql"&gt;3. Configurar log_bin_trust_function_creators en MySQL&lt;/h3&gt;
&lt;p&gt;Para evitar problemas con permisos de creación de funciones, habilita esta configuración en el servidor MySQL:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Darle tiempo a que MySQL esté listo&lt;/strong&gt;:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="k"&gt;until&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;podman&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;mysql-server&lt;span class="w"&gt; &lt;/span&gt;mysqladmin&lt;span class="w"&gt; &lt;/span&gt;ping&lt;span class="w"&gt; &lt;/span&gt;-u&lt;span class="w"&gt; &lt;/span&gt;root&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="s1"&gt;'root_pwd'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--silent&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;do&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Esperando a que MySQL esté listo..."&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;sleep&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Ejecutar la configuración&lt;/strong&gt;:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;podman&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;mysql-server&lt;span class="w"&gt; &lt;/span&gt;mysql&lt;span class="w"&gt; &lt;/span&gt;-u&lt;span class="w"&gt; &lt;/span&gt;root&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="s1"&gt;'root_pwd'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-e&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"SET GLOBAL log_bin_trust_function_creators = 1;"&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h3 id="4-desplegar-el-contenedor-zabbix-server"&gt;4. Desplegar el Contenedor Zabbix Server&lt;/h3&gt;
&lt;p&gt;Iniciar el contenedor &lt;code&gt;zabbix-server-mysql&lt;/code&gt; en el pod, conectándolo a MySQL y asegurándote de que se conecte al Java Gateway:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;podman&lt;span class="w"&gt; &lt;/span&gt;run&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;--name&lt;span class="w"&gt; &lt;/span&gt;zabbix-server-mysql&lt;span class="w"&gt; &lt;/span&gt;--pod&lt;span class="o"&gt;=&lt;/span&gt;zabbix&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;-e&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;DB_SERVER_HOST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"127.0.0.1"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;-e&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;MYSQL_USER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"zabbix"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;-e&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;MYSQL_PASSWORD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"zabbix_pwd"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;-e&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;MYSQL_DATABASE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"zabbix"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;-e&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;ZBX_JAVAGATEWAY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"127.0.0.1"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;docker.io/zabbix/zabbix-server-mysql:alpine-latest
&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h3 id="5-verificar-la-creacion-de-tablas-en-la-base-de-datos"&gt;5. Verificar la Creación de Tablas en la Base de Datos&lt;/h3&gt;
&lt;p&gt;Confirmar que &lt;code&gt;zabbix-server-mysql&lt;/code&gt; crea correctamente las tablas en la base de datos:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;podman&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;mysql-server&lt;span class="w"&gt; &lt;/span&gt;mysql&lt;span class="w"&gt; &lt;/span&gt;-u&lt;span class="w"&gt; &lt;/span&gt;root&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="s1"&gt;'root_pwd'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-e&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"USE zabbix; SHOW TABLES;"&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h3 id="6-desplegar-el-contenedor-zabbix-java-gateway"&gt;6. Desplegar el Contenedor Zabbix Java Gateway&lt;/h3&gt;
&lt;p&gt;Iniciar el contenedor &lt;code&gt;zabbix-java-gateway&lt;/code&gt;, asegurándote de que esté en el pod &lt;code&gt;zabbix&lt;/code&gt;:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;podman&lt;span class="w"&gt; &lt;/span&gt;run&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;--name&lt;span class="w"&gt; &lt;/span&gt;zabbix-java-gateway&lt;span class="w"&gt; &lt;/span&gt;--pod&lt;span class="o"&gt;=&lt;/span&gt;zabbix&lt;span class="w"&gt; &lt;/span&gt;docker.io/zabbix/zabbix-java-gateway:alpine-latest
&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id="7-desplegar-el-contenedor-nginx-con-certificados-ssl-y-configuracion"&gt;7. Desplegar el Contenedor NGINX con Certificados SSL y Configuración&lt;/h3&gt;
&lt;p&gt;Ejecutar el contenedor de Zabbix Web NGINX MySQL (&lt;code&gt;zabbix-web-mysql-ssl&lt;/code&gt;), montando los certificados y el archivo de configuración &lt;code&gt;zabbix-ssl.conf&lt;/code&gt; correctamente:&lt;/p&gt;
&lt;p&gt;El archivo de configuración &lt;code&gt;zabbix-web-mysql-ssl&lt;/code&gt; puede ser algo así:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;server&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;listen&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;8443&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;ssl&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;server_name&lt;span class="w"&gt; &lt;/span&gt;_&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;ssl_certificate&lt;span class="w"&gt; &lt;/span&gt;/etc/ssl/nginx/fullchain.pem&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;ssl_certificate_key&lt;span class="w"&gt; &lt;/span&gt;/etc/ssl/nginx/privkey.pem&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;root&lt;span class="w"&gt; &lt;/span&gt;/usr/share/zabbix&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;index&lt;span class="w"&gt; &lt;/span&gt;index.php&lt;span class="w"&gt; &lt;/span&gt;index.html&lt;span class="w"&gt; &lt;/span&gt;index.htm&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;location&lt;span class="w"&gt; &lt;/span&gt;/&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;try_files&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$uri&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$uri&lt;/span&gt;/&lt;span class="w"&gt; &lt;/span&gt;/index.php?&lt;span class="nv"&gt;$args&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;location&lt;span class="w"&gt; &lt;/span&gt;~&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;php$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;include&lt;span class="w"&gt; &lt;/span&gt;fastcgi_params&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;fastcgi_pass&lt;span class="w"&gt; &lt;/span&gt;unix:/tmp/php-fpm.sock&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;fastcgi_index&lt;span class="w"&gt; &lt;/span&gt;index.php&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;fastcgi_param&lt;span class="w"&gt; &lt;/span&gt;SCRIPT_FILENAME&lt;span class="w"&gt; &lt;/span&gt;/usr/share/zabbix&lt;span class="nv"&gt;$fastcgi_script_name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;error_log&lt;span class="w"&gt; &lt;/span&gt;/tmp/zabbix_ssl_error.log&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;access_log&lt;span class="w"&gt; &lt;/span&gt;/tmp/zabbix_ssl_access.log&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;podman&lt;span class="w"&gt; &lt;/span&gt;run&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;--name&lt;span class="w"&gt; &lt;/span&gt;zabbix-web-mysql-ssl&lt;span class="w"&gt; &lt;/span&gt;--pod&lt;span class="o"&gt;=&lt;/span&gt;zabbix&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;-v&lt;span class="w"&gt; &lt;/span&gt;./certs/fullchain.pem:/etc/ssl/nginx/fullchain.pem:ro&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;-v&lt;span class="w"&gt; &lt;/span&gt;./certs/privkey.pem:/etc/ssl/nginx/privkey.pem:ro&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;-v&lt;span class="w"&gt; &lt;/span&gt;./zabbix-ssl.conf:/etc/nginx/http.d/zabbix-ssl.conf:ro&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;-e&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;ZBX_SERVER_HOST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"127.0.0.1"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;-e&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;DB_SERVER_HOST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"127.0.0.1"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;-e&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;MYSQL_DATABASE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"zabbix"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;-e&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;MYSQL_USER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"zabbix"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;-e&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;MYSQL_PASSWORD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"zabbix_pwd"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;docker.io/zabbix/zabbix-web-nginx-mysql:alpine-latest
&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id="8-verificacion-final"&gt;8. Verificación Final&lt;/h3&gt;
&lt;p&gt;Hacer una solicitud a la interfaz de Zabbix para confirmar que todo esté funcionando y que la configuración SSL esté activa:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;curl&lt;span class="w"&gt; &lt;/span&gt;-v&lt;span class="w"&gt;  &lt;/span&gt;https://sebelk.lab
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Deberías ver una respuesta HTTP 200 desde NGINX, indicando que Zabbix está activo y funcionando con SSL.&lt;/p&gt;
&lt;h3 id="9-instalacion-del-agente"&gt;9. Instalación del agente&lt;/h3&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;podman&lt;span class="w"&gt; &lt;/span&gt;run&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;--name&lt;span class="w"&gt; &lt;/span&gt;zabbix-agent&lt;span class="w"&gt; &lt;/span&gt;--pod&lt;span class="o"&gt;=&lt;/span&gt;zabbix&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;-e&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;ZBX_SERVER_HOST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"127.0.0.1"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;-e&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;ZBX_SERVER_PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"10051"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;-e&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;ZBX_HOSTNAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"ZabbixServerAgent"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;docker.io/zabbix/zabbix-agent2:alpine-latest
&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id="10-deshabilitar-variable-en-mysql"&gt;10. Deshabilitar variable en MySQL&lt;/h3&gt;
&lt;p&gt;La variable que habilitamos antes no es imprescindible, de modo que se puede desactivar:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;podman&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;mysql-server&lt;span class="w"&gt; &lt;/span&gt;mysql&lt;span class="w"&gt; &lt;/span&gt;-u&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;root&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="s1"&gt;'root_pwd'&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;-e&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"SET GLOBAL log_bin_trust_function_creators = 0;"&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id="todo-listo"&gt;Todo listo&lt;/h3&gt;
&lt;p&gt;¡Listo! Trabajo terminado 😉 &lt;/p&gt;
&lt;p&gt;&lt;a class="image-reference" href="https://sergiobelkin.com/images/zabbix-final.png"&gt;&lt;img src="https://sergiobelkin.com/images/zabbix-final.thumbnail.png" alt="Zabbix Implementado usando podman"&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;¿Qué te pareció la guía? Podés usar la sección de &lt;strong&gt;Comentarios&lt;/strong&gt;.&lt;/p&gt;</description><category>contenedores</category><guid>https://sergiobelkin.com/posts/como-instalar-zabbix-7x-usando-contenedores-podman/</guid><pubDate>Sun, 10 Nov 2024 20:20:45 GMT</pubDate></item><item><title>Gestión de Contraseñas Usando Contenedores Podman</title><link>https://sergiobelkin.com/posts/gestion-de-contrasenas-usando-contenedores-podman/</link><dc:creator>sebelk</dc:creator><description>&lt;p&gt;Podemos administrar nuestros datos personales también con estándares profesionales. En este contexto, vamos a explorar cómo llevar la gestión de contraseñas usando utilizando herramientas viejas y confiables como &lt;strong&gt;pass&lt;/strong&gt;, &lt;strong&gt;gpg&lt;/strong&gt;, &lt;strong&gt;git&lt;/strong&gt; combinada con  la potente solución de contenedores &lt;strong&gt;Podman&lt;/strong&gt;. Será una experiencia desafiante.&lt;/p&gt;
&lt;p&gt;&lt;a class="image-reference" href="https://sergiobelkin.com/images/rc-xyz-nft-gallery-r8VbpgMS6Uc-unsplash.jpg"&gt;&lt;img src="https://sergiobelkin.com/images/rc-xyz-nft-gallery-r8VbpgMS6Uc-unsplash.thumbnail.jpg" alt="Claves"&gt;&lt;/a&gt; &lt;/p&gt;
&lt;h3 id="almacenamiento-de-contrasenas-elevado"&gt;Almacenamiento de Contraseñas Elevado&lt;/h3&gt;
&lt;p&gt;Para gestionar nuestras passwords usaremos &lt;strong&gt;pass&lt;/strong&gt;. La herramienta pass no estra cosa que un potente script de bash de algo más de 720 líneas de wrapper principalemente para gpg y git.&lt;/p&gt;
&lt;p&gt;Ahora, lo realmente interesante: configuraremos un repositorio dentro de un contenedor &lt;strong&gt;Podman&lt;/strong&gt;. Este repositorio, administrado con &lt;strong&gt;git&lt;/strong&gt;, puede ser compartido de manera segura y efectiva en todos tus dispositivos.&lt;/p&gt;
&lt;h3 id="acceso-simplificado-desde-cualquier-lugar"&gt;Acceso Simplificado desde Cualquier Lugar&lt;/h3&gt;
&lt;p&gt;La accesibilidad es clave en tu entorno profesional. Ya sea trabajando en sistemas Windows o Linux, puedes aprovechar &lt;a href="https://qtpass.org/"&gt;QtPass&lt;/a&gt;, una interfaz gráfica para &lt;strong&gt;pass&lt;/strong&gt;. Para usuarios de iPhone, &lt;strong&gt;passforios&lt;/strong&gt; es una excelente opción, mientras que los dispositivos Android pueden beneficiarse de &lt;a href="https://github.com/android-password-store/Android-Password-Store#readme"&gt;Password-Store&lt;/a&gt;, disponible en &lt;a href="https://play.google.com/store/apps/details?id=dev.msfjarvis.aps"&gt;Google Play Store&lt;/a&gt; y &lt;a href="https://f-droid.org/packages/dev.msfjarvis.aps/"&gt;F-Droid&lt;/a&gt; para mantener tus contraseñas siempre sincronizadas.&lt;/p&gt;
&lt;p&gt;&lt;a class="image-reference" href="https://sergiobelkin.com/images/podman-pass.png"&gt;&lt;img src="https://sergiobelkin.com/images/podman-pass.thumbnail.png" title="Hacer clic para ampliar la imagen" alt="Esquema de podman con pass"&gt;&lt;/a&gt; &lt;/p&gt;
&lt;h3 id="caracteristicas-clave-para-profesionales"&gt;Características Clave para Profesionales&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Control Total:&lt;/strong&gt; Somos nosotros quienes gestionan nuestros repositorios. Los datos sensibles están en tus dispositivos, evitando intermediarios y asegurando la confidencialidad.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Portabilidad Sin Esfuerzo&lt;/strong&gt;: Se puede cambiar de dispositivos o realiza copias de seguridad con facilidad. Tu repositorio te seguirá sin problemas.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Seguridad de Alto Nivel&lt;/strong&gt;:  tus credenciales seguras con estándares de confiabilidad, integridad y disponibilidad.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Compartir con Confianza&lt;/strong&gt;: Podrás compartirlo fácilmente en círculos de confianza. &lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="configuracion-inicial-y-uso-avanzado"&gt;Configuración Inicial y Uso Avanzado&lt;/h3&gt;
&lt;p&gt;En esta primera fase, te guiaremos a través de la configuración de tu repositorio en un contenedor &lt;strong&gt;Podman&lt;/strong&gt; y las opciones para interactuar con él desde distintos dispositivos.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;mark&gt;Nota 1:&lt;/mark&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;El enfoque primordial es establecer un almacén personal de contraseñas. Además de utilizarlo en tus dispositivos, podrás extender su uso a usuarios de confianza. Aunque podría requerirse alguna asistencia técnica inicial para la configuración, las acciones esenciales son "actualizar desde el repositorio (pull)" y "enviar cambios al repositorio (push)".&lt;/p&gt;
&lt;p&gt;Esta idea es adaptable a ambientes profesionales con para grupos reducidos de usuarios en una red corporativa, donde cada miembro tiene su copia del repositorio principal. El repositorio podría estar incluso en algún contenedor que esté disponible 24x7. Esto facilita la consulta, creación, modificación y eliminación colaborativa de contraseñas, consolidando luego los cambios en un repositorio compartido.&lt;/p&gt;
&lt;p&gt;&lt;mark&gt;&lt;strong&gt;Nota 2:&lt;/strong&gt;&lt;/mark&gt;&lt;/p&gt;
&lt;p&gt;Para aprovechar plenamente esta guía, asumimos que poseés conocimientos de:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Gestión de claves públicas ssh&lt;/li&gt;
&lt;li&gt;Gestión de claves gpg&lt;/li&gt;
&lt;li&gt;Uso básico de git&lt;/li&gt;
&lt;li&gt;Uso básico de &lt;strong&gt;Podman&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Conocimientos generales de Linux: bash, systemd, firewalld (iptables/nftables), etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="que-usaremos-para-lograr-todo-esto"&gt;¿Qué usaremos para lograr todo esto?&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;OS: Fedora 38&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;podman&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://www.passwordstore.org/"&gt;pass&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Se podría usar otra distribución, sin embargo es importante que cuente con una versión relativamente reciente de podman. &lt;/p&gt;
&lt;p&gt;¿Por qué usamos podman? Porque tiene una gran similitud con docker, y además, posee la capacidad de correr contenedores de manera mucho más segura y sencilla. En este caso particular, crearemos un contenedor que alojará el repositorio compartido de passwords.&lt;/p&gt;
&lt;p&gt;No será necesario crear servicios web y/o de bases de datos.&lt;/p&gt;
&lt;h4 id="instalacion-de-paquetes"&gt;Instalación de paquetes&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;dnf install -y  git pass&lt;/code&gt;&lt;/p&gt;
&lt;h4 id="inicializacion-de-repositorio-de-passwords"&gt;Inicialización de repositorio de passwords&lt;/h4&gt;
&lt;p&gt;En este ejemplo le pasamos los identificadores de las clave públicas gpg en el siguiente usamos 3 direcciones de mail correspondientes a la clave del host, la del celular y la de otra persona respectivamente.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;pass init jkm@example.com fxi@example.com pyn@example.net&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;pass git init&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;pass generate puertablanca&lt;/code&gt;&lt;/p&gt;
&lt;h4 id="preparacion-del-container"&gt;Preparación del container&lt;/h4&gt;
&lt;p&gt;Creamos el siguiente Dockerfile&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;FROM fedora:38
RUN dnf update -y &amp;amp;&amp;amp; dnf install -y git openssh-server
RUN useradd -ms /bin/bash git
RUN mkdir /home/git/.ssh
RUN ssh-keygen -A
COPY  ssh-pks /home/git/.ssh/authorized_keys
RUN echo "git ALL=(ALL:ALL) NOPASSWD: /usr/sbin/sshd" &amp;gt;&amp;gt; /etc/sudoers &amp;amp;&amp;amp; git clone --bare /mnt/.password-store /home/git/.password-store &amp;amp;&amp;amp; chown -R git:git /home/git  &amp;amp;&amp;amp; chmod 700 /home/git/.ssh &amp;amp;&amp;amp; chmod 600 /home/git/.ssh/authorized_keys
EXPOSE 22
CMD ["sudo","/usr/sbin/sshd", "-D"]
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Esto nos permitirá crear un repositorio con las siguientes características:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Basado en Fedora 38&lt;/li&gt;
&lt;li&gt;Un usuario llamado &lt;em&gt;git&lt;/em&gt; que tendrá el único privilegio de correr el servicio ssh&lt;/li&gt;
&lt;li&gt;Obtendrá una copia del repositorio git antes creado con pass&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="crear-la-imagen-de-podman"&gt;Crear la imagen de podman&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;podman build  -v /home/sergio/.password-store:/mnt/.password-store  -t passteiner .&lt;/code&gt;&lt;/p&gt;
&lt;h4 id="crear-el-container"&gt;Crear el container&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;podman run  -d --name container-pass_git  --user git   -p 60003:22    passteiner&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class="image-reference" href="https://sergiobelkin.com/images/podman-pass-running.png"&gt;&lt;img src="https://sergiobelkin.com/images/podman-pass-running.thumbnail.png" alt=""&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;En este punto, ya estamos en condiciones de crear, editar, modificar nuestras passwords y subirlas al repo del contenedor de manera que esté disponible para otros dispostivos y/o usuarios. &lt;/p&gt;
&lt;p&gt;Cabe aclarar que para usar Password Store en Android hace falta instalar &lt;a href="https://github.com/open-keychain/open-keychain#readme"&gt;OpenKeychain&lt;/a&gt;. Esa aplicación nos permitirá crear un el par de clave privada + clave pública GnuPG, como así también importar la clave pública del resto de los usuarios con quien compartiremos el llavero. Tener en cuenta que es muy importante la passphrase que usemos para cifrar nuestra clave privada: debe ser fácil de memorizar y a la vez robusta. Esa misma passphrase se nos pedirá cuando necesitamos acceder a las contraseñas:&lt;/p&gt;
&lt;p&gt;Y luego con &lt;strong&gt;Password Store&lt;/strong&gt; tendremos que:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Ingresar los parámetros de repositorio que está en el contenedor que hemos creado, tanto la url (por ejemplo ssh://git@10.0.0.10:60003/git/,password-store) y la branch (master).&lt;/li&gt;
&lt;li&gt;Generar la clave pública ssh para autenticarse al repositorio. Esta clave tendrá que copiarse al archivo /home/git/.ssh/authorized_keys del contenedor.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;podman exec container-pass_git bash -c 'echo "clave_publica_ssh" /home/git/.ssh/authorized_keys'&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;(Si queremos que este archivo sea persistente, podríamos modiicar el Dockerfile para que use un volumen).&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Clonar el repositorio del contenedor.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Una vez que hemos clonado el repositorio, obtendremos el listado de passwords y el menú para operar con él:&lt;/p&gt;
&lt;p&gt;&lt;a class="image-reference" href="https://sergiobelkin.com/images/photo_2023-08-18_18-14-14.jpg"&gt;&lt;img src="https://sergiobelkin.com/images/photo_2023-08-18_18-14-14.thumbnail.jpg" alt="Menú de Password Store"&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id="actualizando-nuestro-repositorio"&gt;Actualizando nuestro repositorio&lt;/h3&gt;
&lt;p&gt;Hay varias configuraciones posibles, pero la que recomiendo es la siguiente:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;pass git config pull.rebase false&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Para bajar las actualizaciones del contenedor:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;pass git pull&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Para subir las propias modificaciones al contenedor:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;pass git push&lt;/code&gt;&lt;/p&gt;
&lt;h3 id="comentario-finales"&gt;Comentario finales&lt;/h3&gt;
&lt;p&gt;Al finalizar habrás conseguido que:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;El contenedor se ejecuta como un usuario sin privilegios dentro del sistema.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Todo - excepto el proceso sshd - se ejecutará como un usuario sin privilegios &lt;strong&gt;aun dentro del container&lt;/strong&gt;. Salvo que explícitamente uses algo como &lt;code&gt;docker run --user root.....&lt;/code&gt; . Pero ¿por qué lo harías?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Por fuera del contenedor en realidad, mapea a nuestro propio usuario.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a class="image-reference" href='https://sergiobelkin.com/images/podman-pass-container-top.png"'&gt;&lt;img src="https://sergiobelkin.com/images/podman-pass-container-top.thumbnail.png" alt=""&gt;&lt;/a&gt; &lt;/p&gt;
&lt;h3 id="enlaces-utiles"&gt;Enlaces útiles&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.howtogeek.com/devops/how-to-use-pass-a-command-line-password-manager-for-linux-systems/"&gt;How to Use Pass, a Command-Line Password Manager for Linux Systems&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.devdungeon.com/content/gpg-tutorial"&gt;GPG Tutorial | DevDungeon&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=zeObvF1tk8M"&gt;(135) QtPass and opensource project management The road from a 2 day project till inclusion in all distro… - YouTube&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description><category>contenedores</category><category>seguridad</category><guid>https://sergiobelkin.com/posts/gestion-de-contrasenas-usando-contenedores-podman/</guid><pubDate>Tue, 29 Aug 2023 22:06:14 GMT</pubDate></item><item><title>3 pasos para configurar unidad de systemd para VM de Virtualbox</title><link>https://sergiobelkin.com/posts/como-configurar-una-maquina-virtual-como-servicio/</link><dc:creator>sebelk</dc:creator><description>&lt;p&gt;&lt;a class="image-reference" href="https://sergiobelkin.com/images/ashutosh-dave-MWaWwd7VxDQ-unsplash.jpg"&gt;&lt;img src="https://sergiobelkin.com/images/ashutosh-dave-MWaWwd7VxDQ-unsplash.thumbnail.jpg" alt="Bonita imagen ilustrativa 😄"&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;Foto de &lt;a href="https://unsplash.com/@ashu?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Ashutosh Dave&lt;/a&gt; en &lt;a href="https://unsplash.com/es/s/fotos/start?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;h4 id="1-encontrar-el-uuid-de-la-vm-por-ejemplo-si-tenemos-una-maquina-llamada-rhel7-ejecutamos"&gt;1. Encontrar el UUID de la VM, por ejemplo si tenemos una máquina llamada RHEL7, ejecutamos:&lt;/h4&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$&lt;span class="w"&gt; &lt;/span&gt;VBoxManage&lt;span class="w"&gt; &lt;/span&gt;showvminfo&lt;span class="w"&gt; &lt;/span&gt;RHEL7&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'^UUID'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;awk&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'{ print $NF }'&lt;/span&gt;
f02a9f08-2ff2-4a92-b3cd-a8dfb17513c6
&lt;/pre&gt;&lt;/div&gt;

&lt;h4 id="2-crear-el-archivo-template-de-servicio-configsystemduservirtualbox_vmservice"&gt;2. Crear el archivo template de servicio ~/.config/systemd/user/virtualbox_vm@.service:&lt;/h4&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="k"&gt;[Unit]&lt;/span&gt;
&lt;span class="na"&gt;Description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;VirtualBox VM %i&lt;/span&gt;

&lt;span class="k"&gt;[Service]&lt;/span&gt;
&lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;simple&lt;/span&gt;
&lt;span class="na"&gt;KillMode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;mixed&lt;/span&gt;
&lt;span class="na"&gt;ExecStart&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/usr/lib/virtualbox/VBoxHeadless --comment RHEL7 --startvm f02a9f08-2ff2-4a92-b3cd-a8dfb17513c6 --vrde config&lt;/span&gt;

&lt;span class="k"&gt;[Install]&lt;/span&gt;
&lt;span class="na"&gt;WantedBy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;default.target&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;h4 id="3-recargar-systemd-habilitar-y-arrancar-el-servicio"&gt;3. Recargar systemd, Habilitar y arrancar el servicio&lt;/h4&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;systemctl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;daemon&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;reload&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;systemctl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;enable&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;virtualbox_vm&lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;RHEL7&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;service&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;¡Listo!&lt;/p&gt;</description><category>systemd</category><guid>https://sergiobelkin.com/posts/como-configurar-una-maquina-virtual-como-servicio/</guid><pubDate>Sat, 10 Sep 2022 16:17:19 GMT</pubDate></item><item><title>Tutorial: Cifrar $HOME con gocryptfs</title><link>https://sergiobelkin.com/posts/tutorial-cifrar-un-directorio-con-gocryptfs/</link><dc:creator>sebelk</dc:creator><description>&lt;p&gt;En un artículo anterior: &lt;strong&gt;&lt;a href="https://sergiobelkin.com/posts/tutorial-de-fscrypt-para-cifrar-archivos/"&gt;Tutorial de fscrypt para cifrar archivos&lt;/a&gt;&lt;/strong&gt;, habíamos visto como cifrar archivos con &lt;strong&gt;fscrypt&lt;/strong&gt; y ext4. Ahora aprenderemos otro método independiente del sistema de archivos utilizado, se trata de una herramienta llamada &lt;strong&gt;gocryptfs&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Conocimientos previos necesarios:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Uso habitual de línea de comandos en Linux (incluyendo entre otros manejo de propietarios y permisos)&lt;/li&gt;
&lt;li&gt;Instalación y desinstalación de paquetes&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;En el ejemplo en cuestión estoy usando Debian Buster (te recomiendo primero instalarla en una máquina virtual para hacer pruebas), de modo que los pasos a seguir pueden ser un poco diferentes en otras distribuciones, pero los principios generales se mantienen.
&lt;strong&gt;Todos los pasos hasta que lo pruebes como usuario común deben hacerse con privilegios de superusuario.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Es muy importante contar espacio suficiente para copiar temporalmente los archivos del directorio que se desea cifrar.&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;He cambiado el shell del usuario sergio que es &lt;em&gt;dash&lt;/em&gt; (predeterminado en Debian) por &lt;strong&gt;bash&lt;/strong&gt;, ya que el primero no está pensado para un uso interactivo habitual además de ser menos potente.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a class="image-reference" href="https://sergiobelkin.com/images/rob-king-Au6eR7Yg9CY-unsplash.jpg"&gt;&lt;img src="https://sergiobelkin.com/images/rob-king-Au6eR7Yg9CY-unsplash.thumbnail.jpg" alt=""&gt;&lt;/a&gt; &lt;/p&gt;
&lt;h3 id="instalar-grocryptfs"&gt;Instalar grocryptfs&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;apt install grocryptfs&lt;/code&gt;&lt;/p&gt;
&lt;h3 id="crear-el-directorio-para-cifrar"&gt;Crear el directorio para cifrar&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;mkdir /home/sergio_cifrado&lt;/code&gt;&lt;/p&gt;
&lt;h3 id="inicializar-el-directorio"&gt;Inicializar el directorio&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Aquí seteamos la misma contraseña que la del usuario&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;gocryptfs --init /home/sergio_cifrado/
Choose a password for protecting your files.
Password: 
Repeat: 

Your master key is:

    9c43faf4-16a07508-42213628-50a5c55e-
    e0c17483-c41453a0-6355f9f0-897b3aa9

If the gocryptfs.conf file becomes corrupted or you ever forget your password,
there is only one hope for recovery: The master key. Print it to a piece of
paper and store it in a drawer. This message is only printed once.

The gocryptfs filesystem has been created successfully.
You can now mount it using: gocryptfs /home/sergio_cifrado MOUNTPOINT
&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id="montar-el-directorio"&gt;Montar el directorio&lt;/h3&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;mkdir /home/sergio_montaje_temporario &amp;amp;&amp;amp; chmod 750 /home/sergio_montaje_temporario &amp;amp;&amp;amp; chown sergio. /home/sergio_temporario &amp;amp;&amp;amp;
gocryptfs /home/sergio_cifrado/ /home/sergio_temporario/
Password: 
Decrypting master key
Filesystem mounted and ready.
&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id="ajustamos-los-propietarios-y-permisos"&gt;Ajustamos los propietarios y permisos&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;chown -R sergio. /home/sergio{_cifrado} &amp;amp;&amp;amp; chmod 750 /home/sergio_cifrado&lt;/code&gt;&lt;/p&gt;
&lt;h3 id="copiar-todos-los-archivos-del-directorio-del-usuario-al-directorio-temporal"&gt;Copiar todos los archivos del directorio del usuario al directorio temporal&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;cp -Tav /home/sergio /home/sergio_temporario&lt;/code&gt;&lt;/p&gt;
&lt;h3 id="borrar-el-contenido-del-directorio-del-usuario-por-favor-realizar-previamente-un-backup"&gt;Borrar el contenido del directorio del usuario (por favor realizar previamente un backup)&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;rm -rf /home/sergio&lt;/code&gt;&lt;/p&gt;
&lt;h3 id="desmontar-el-directorio-cifrado"&gt;Desmontar el directorio cifrado&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;fusermount -u /home/sergio_temporario&lt;/code&gt;&lt;/p&gt;
&lt;h3 id="le-cambiamos-el-nombre-al-directorio-temporario-por-el-original"&gt;Le cambiamos el nombre al directorio temporario por el original&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;mv /home/sergio_temporario /home/sergio&lt;/code&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Todo lo que viene a continuación es necesario cuando queremos que el directorio se monte de manera automática en el momento del login.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id="instalamos-el-modulo-de-pam-para-montaje-de-volumenes"&gt;Instalamos el módulo de PAM para montaje de volúmenes&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;apt install -y libpam-mount&lt;/code&gt;&lt;/p&gt;
&lt;h3 id="ejecutamos-el-configurador-de-pam"&gt;Ejecutamos el configurador de pam&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;pam-auth-update&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class="image-reference" href="https://sergiobelkin.com/images/pam_auth_update.png"&gt;&lt;img src="https://sergiobelkin.com/images/pam_auth_update.thumbnail.png" alt="pam-auth-update"&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;y presionamos en &lt;strong&gt;Aceptar&lt;/strong&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;En otras distribuciones y configuraciones, puede ser necesario editar otros archivos del directorio /etc/pam.d.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Luego hay que editar el archivo &lt;code&gt;/etc/security/pam_mount.conf.xml&lt;/code&gt; agregando lo siguiente antes de &lt;code&gt;&amp;lt;/pam_mount&amp;gt;&lt;/code&gt;:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;volume&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"sergio"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;fstype&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"fuse"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"nodev,nosuid,quiet,nonempty,allow_other"&lt;/span&gt;
&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/usr/bin/gocryptfs#/home/%(USER)_cifrado"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;mountpoint&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/home/%(USER)"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id="configuramos-fuse"&gt;Configuramos FUSE&lt;/h3&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="gh"&gt;#&lt;/span&gt; /etc/fuse.conf - Configuration file for Filesystem in Userspace (FUSE)

&lt;span class="gh"&gt;#&lt;/span&gt; Set the maximum number of FUSE mounts allowed to non-root users.
&lt;span class="gh"&gt;#&lt;/span&gt; The default is 1000.
&lt;span class="gh"&gt;#&lt;/span&gt;mount_max = 1000

&lt;span class="gh"&gt;#&lt;/span&gt; Allow non-root users to specify the allow_other or allow_root mount options.
&lt;span class="gh"&gt;#&lt;/span&gt; Modificamos aquí:
user_allow_other
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Eso es todo, felicitaciones si llegaste hasta aquí 😀,  podemos reiniciar y probar la configuración:&lt;/p&gt;
&lt;iframe width="560" height="315" src="https://www.youtube.com/embed/aFezsKg2iRY" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen&gt;&lt;/iframe&gt;

&lt;p&gt;Para login gráfico:&lt;/p&gt;
&lt;iframe width="560" height="315" src="https://www.youtube.com/embed/wwwVL8k_bes" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen&gt;&lt;/iframe&gt;

&lt;h3 id="conclusion"&gt;Conclusión&lt;/h3&gt;
&lt;p&gt;De esta manera pudiste configurar el cifrado automática de un directorio $HOME de un usuario. Este método es principalmente útil para equipos donde trabaja un solo usuario (podría ser tu laptop de trabajo diario por ejemplo).&lt;/p&gt;
&lt;h3 id="fuentes-y-mas-recursos"&gt;Fuentes y más recursos&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://nuetzlich.net/gocryptfs/"&gt;gocryptfs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/rfjakob/gocryptfs"&gt;rfjakob/gocryptfs: Encrypted overlay filesystem written in Go&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://pam-mount.sourceforge.net/"&gt;pam_mount — Pluggable Authentication Module to mount volumes for a user session&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description><category>criptografia</category><guid>https://sergiobelkin.com/posts/tutorial-cifrar-un-directorio-con-gocryptfs/</guid><pubDate>Wed, 12 May 2021 18:11:58 GMT</pubDate></item><item><title>Tutorial de fscrypt para cifrar archivos</title><link>https://sergiobelkin.com/posts/tutorial-de-fscrypt-para-cifrar-archivos/</link><dc:creator>sebelk</dc:creator><description>&lt;h4 id="conocimientos-previos-necesarios"&gt;Conocimientos previos necesarios:&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Instalación de Linux.&lt;/li&gt;
&lt;li&gt;Uso habitual de línea de comandos en Linux (incluyendo entre otros manejo de propietarios y permisos).&lt;/li&gt;
&lt;li&gt;Instalación y desinstalación de paquetes.&lt;/li&gt;
&lt;li&gt;Montaje de sistemas de archivos.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a class="image-reference" href="https://sergiobelkin.com/images/alex-motoc-Y83nsKGkxSw-unsplash.jpg"&gt;&lt;img src="https://sergiobelkin.com/images/alex-motoc-Y83nsKGkxSw-unsplash.thumbnail.jpg" alt="Cifrado de archivos"&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;El sistema ext4 proporciona cifrado de bloques de datos y nombres de archivos. Veremos a continuación de algunas reglas generales para cifrar el directorio /home de un usuario.&lt;/p&gt;
&lt;p&gt;En el ejemplo en cuestión estoy usando Debian Buster (te recomiendo primero instalarla en una máquina virtual para hacer pruebas), de modo que los pasos a seguir pueden ser un poco diferentes en otras distribuciones, pero los principios generales se mantienen.&lt;/p&gt;
&lt;p&gt;¡Manos a la obra!&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Los comandos precedidos por &lt;code&gt;sudo&lt;/code&gt; indican que necesitan privilegios de root. Si querés usar sudo, sencillamente ejecutá como root:&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;code&gt;usermod -aG sudo sergio&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Obviamente aquí y en cada caso reemplazalo con tu usuario común.&lt;/p&gt;
&lt;h3 id="preparacion-del-sistema-de-archivos"&gt;Preparación del sistema de archivos&lt;/h3&gt;
&lt;p&gt;Algo que tendremos que hacer es habilitar la funcionalidad de cifrado, suponiendo que la partición de cifrado es /dev/sda1, haríamos:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;sudo tune2fs -O encrypt /dev/sda1&lt;/code&gt;&lt;/p&gt;
&lt;h3 id="descarga-y-compilacion"&gt;Descarga y compilación&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;sudo apt update &amp;amp;&amp;amp; sudo apt build-dep fscrypt&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;do apt -y install git &amp;amp;&amp;amp; go get -d github.com/google/fscrypt/...&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;cd go/src/github.com/google/fscrypt/&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;make &amp;amp;&amp;amp; sudo make install PREFIX=/usr&lt;/code&gt;&lt;/p&gt;
&lt;h3 id="configuracion"&gt;Configuración&lt;/h3&gt;
&lt;p&gt;Tenemos que actualizar la configuración de PAM, que servirán para desbloquear directorios al loguearse, bloquear al desloguearse, y cambiar contraseñas de acceso a los recursos cifrados.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;sudo pam-auth-update&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class="image-reference" href="https://sergiobelkin.com/images/pam-auth-update-fscrypt.png"&gt;&lt;img src="https://sergiobelkin.com/images/pam-auth-update-fscrypt.thumbnail.png" alt="pam-auth-update"&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;Para configurar globalmente:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;sudo fscrypt setup&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;No se puede cifrar un directorio que ya tiene contenido, de manera que hay que crear un nuevo directorio, y luego migrar el contenido del directorio del usuario:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;sudo mkdir /home/sergio_temp &amp;amp;&amp;amp; sudo chown sergio.sergio /home/sergio_temp&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;fscrypt encrypt /home/sergio_temp&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Allí podríamos elegir entre la contraseña del usuario, una passphrase o bien un archivo con clave 256-bit. En nuestro elegimos la primera opción, siempre teniendo en cuenta lo importante que es contar con una buena contraseña.&lt;/p&gt;
&lt;p&gt;Luego chequeamos que esté todo en orden:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;fscrypt status /home/sergio_temp&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Ahora sí, migramos el contenido:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;cp -av -T /home/sergio /home/sergio_temp&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Bloqueamos el contenido del directorio&lt;/p&gt;
&lt;p&gt;&lt;code&gt;sudo fscrypt lock /home/sergio_temp --user=/home/sergio_temp&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Probamos desbloquear&lt;/p&gt;
&lt;p&gt;&lt;code&gt;fscrypt unlock /home/sergio_temp&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Si funciona podemos reemplazarlo por el nuevo directorio:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;sudo su -&lt;/code&gt;
&lt;code&gt;mv /home/sergio{,_para-borrar}&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;mv /home/sergio{_temp,}&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Luego al reiniciar podemos probar:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;reboot&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;¿Cómo se ven los archivos cifrados?&lt;/p&gt;
&lt;p&gt;&lt;a class="image-reference" href="https://sergiobelkin.com/images/fscrypt-access.png"&gt;&lt;img src="https://sergiobelkin.com/images/fscrypt-access.thumbnail.png" alt=""&gt;&lt;/a&gt; &lt;/p&gt;
&lt;h4 id="mas-recursos"&gt;Más Recursos&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/google/fscrypt"&gt;fscrypt: Go tool for managing Linux filesystem encryption&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://wiki.archlinux.org/index.php/Fscrypt"&gt;fscrypt - ArchWiki&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.kernel.org/doc/html/v4.18/filesystems/fscrypt.html"&gt;Filesystem-level encryption (fscrypt) — The Linux Kernel documentation&lt;/a&gt; &lt;/li&gt;
&lt;/ul&gt;</description><category>criptografia</category><category>seguridad</category><guid>https://sergiobelkin.com/posts/tutorial-de-fscrypt-para-cifrar-archivos/</guid><pubDate>Sat, 24 Apr 2021 13:30:29 GMT</pubDate></item></channel></rss>