<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Daniel M.</title>
    <description>The latest articles on Forem by Daniel M. (@daniconil).</description>
    <link>https://forem.com/daniconil</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F766604%2F54b10629-dae5-413d-828b-0e04867b5e95.jpeg</url>
      <title>Forem: Daniel M.</title>
      <link>https://forem.com/daniconil</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/daniconil"/>
    <language>en</language>
    <item>
      <title>Cómo resolver 'grub_memcpy not found' en Manjaro</title>
      <dc:creator>Daniel M.</dc:creator>
      <pubDate>Mon, 09 Feb 2026 09:39:07 +0000</pubDate>
      <link>https://forem.com/daniconil/como-resolver-grubmemcpy-not-found-en-manjaro-1a8o</link>
      <guid>https://forem.com/daniconil/como-resolver-grubmemcpy-not-found-en-manjaro-1a8o</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foyc3i41z0451l3e2zbqx.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foyc3i41z0451l3e2zbqx.jpg" alt=" " width="767" height="619"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Dentro de los ordenadores portátiles, o laptops, existe un pequeño componente consumible, la pila de litio, que cambiarla puede llegar a ser un suplicio. No me refiero al hecho de quitar la gastada y poner otra como quien le cambia las pilas a un mando, sino a dos hechos unidos que a su vez te consumen a ti: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;desmontar la parte trasera del portátil.&lt;/li&gt;
&lt;li&gt;recuperar la parte del sistema que gestiona el arranque, el bootloader.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;En este tutorial recopilo los pasos que he seguido para volver a habilitar el bootloader de Manjaro, una distribución basada en Arch Linux. El portátil es un Slimbook PROX14 que, por suerte, contiene la pila de litio debajo de la batería, por lo que el desmontaje no era complicado. Una vez cambiada la pila, vamos a seguir los pasos pero antes saber cuál era el síntoma:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;error: symbol &lt;span class="s1"&gt;'grub_memcpy'&lt;/span&gt; not found.
Entering rescue mode...
grub rescue&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;y hasta aquí, no esperemos que venga nadie a rescatarnos. Hemos perdido la configuración UEFI y tenemos una partición raíz cifrada con LUKS. El workaround ha sido arrancar con un Manjaro instalado en un USB y elegir un bootloader de ese sistema, ubicado en la carpeta:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;/boot/EFI/Manjaro
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Recuperamos el bootloader
&lt;/h1&gt;

&lt;h2&gt;
  
  
  1. Arrancar con un Manjaro Live USB
&lt;/h2&gt;

&lt;p&gt;Arranca el equipo desde un USB de Manjaro en modo &lt;strong&gt;UEFI&lt;/strong&gt;. Este sistema se instaló con Balena Etcher.&lt;/p&gt;

&lt;p&gt;Abrimos una terminal para seguir estos pasos.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Identificar las particiones
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;lsblk &lt;span class="nt"&gt;-f&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ejemplo típico:&lt;/p&gt;

&lt;p&gt;Partición   Tipo          Uso               Ruta&lt;/p&gt;




&lt;p&gt;nvme0n1p1   vfat          EFI               /boot/efi&lt;br&gt;
  nvme0n1p2   crypto_LUKS   Sistema cifrado   /&lt;/p&gt;


&lt;h2&gt;
  
  
  3. Desbloquear la partición cifrada
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;cryptsetup open /dev/nvme0n1p2 luksroot
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Insertamos la contraseña de ese sistema cifrado y nos aparece si buscamos en:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt; /dev/mapper/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  4. Montar el sistema
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;mount /dev/mapper/luksroot /mnt
&lt;span class="nb"&gt;sudo &lt;/span&gt;mount /dev/nvme0n1p1 /mnt/boot/efi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No nos debería dar ningún error y si listamos el directorio &lt;code&gt;/mnt&lt;/code&gt;, nos debería ir saliendo nuestro sistema nativo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt; /mnt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  5. Montar sistemas virtuales
&lt;/h2&gt;

&lt;p&gt;Esta parte fue clave, lo obvié en un primer intento y no lo conseguí. Con esos pasos fue distinto y no salieron errores en los pasos posteriores.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;mount &lt;span class="nt"&gt;--bind&lt;/span&gt; /dev /mnt/dev
&lt;span class="nb"&gt;sudo &lt;/span&gt;mount &lt;span class="nt"&gt;--bind&lt;/span&gt; /proc /mnt/proc
&lt;span class="nb"&gt;sudo &lt;/span&gt;mount &lt;span class="nt"&gt;--bind&lt;/span&gt; /sys /mnt/sys
&lt;span class="nb"&gt;sudo &lt;/span&gt;mount &lt;span class="nt"&gt;--bind&lt;/span&gt; /run /mnt/run
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  6. Entrar en el sistema instalado mediante chroot
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo chroot&lt;/span&gt; /mnt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  7. Asegurar que EFI variables está montado
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mount &lt;span class="nt"&gt;-t&lt;/span&gt; efivarfs efivarfs /sys/firmware/efi/efivars
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  8. Reinstalar GRUB limpio
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;grub-install   &lt;span class="nt"&gt;--target&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;x86_64-efi   &lt;span class="nt"&gt;--efi-directory&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/boot/efi   &lt;span class="nt"&gt;--bootloader-id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Manjaro   &lt;span class="nt"&gt;--recheck&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;El resultado de los pasos 7 y 8:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;[&lt;/span&gt;manjaro /]# mount &lt;span class="nt"&gt;-t&lt;/span&gt; efivarfs efivarfs /sys/firmware/efi/efivars
&lt;span class="o"&gt;[&lt;/span&gt;manjaro /]# grub-install &lt;span class="se"&gt;\ &lt;/span&gt;&lt;span class="nt"&gt;--target&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;x86_64-efi &lt;span class="se"&gt;\ &lt;/span&gt;&lt;span class="nt"&gt;--efi-directory&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/boot/efi &lt;span class="se"&gt;\ &lt;/span&gt;&lt;span class="nt"&gt;--bootloader-id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Manjaro &lt;span class="se"&gt;\ &lt;/span&gt;&lt;span class="nt"&gt;--recheck&lt;/span&gt;
Installing &lt;span class="k"&gt;for &lt;/span&gt;x86_64-efi platform. 
Installation finished. 
No error reported.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  9. Regenerar la configuración de GRUB
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;grub-mkconfig &lt;span class="nt"&gt;-o&lt;/span&gt; /boot/grub/grub.cfg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  10. Crear el fallback de arranque
&lt;/h2&gt;

&lt;p&gt;En ese primer intento que comentaba en el paso 5, seguí los pasos que podrían darse para Arch Linux, pero al comprobar que Manjaro tiene su propio sistema, dupliqué algunas carpetas de /boot. Expongo el contenido de la carpeta &lt;code&gt;/boot/efi/EFI&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;[&lt;/span&gt;manjaro /]# &lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-laR&lt;/span&gt; /boot/efi/EFI

/boot/efi/EFI: total 24 
drwxr-xr-x 6 root root 4096 ene 8 10:27 &lt;span class="nb"&gt;.&lt;/span&gt; 
drwxr-xr-x 4 root root 4096 ene 1 1970 .. 
drwxr-xr-x 2 root root 4096 ago 14 2024 boot 
drwxr-xr-x 4 root root 4096 ene 8 10:58 EFI 
drwxr-xr-x 2 root root 4096 ene 8 10:25 GRUB 
drwxr-xr-x 2 root root 4096 ago 14 2024 Manjaro

/boot/efi/EFI/boot: total 268 
drwxr-xr-x 2 root root 4096 ago 14 2024 &lt;span class="nb"&gt;.&lt;/span&gt; 
drwxr-xr-x 6 root root 4096 ene 8 10:27 .. 
&lt;span class="nt"&gt;-rwxr-xr-x&lt;/span&gt; 1 root root 266240 sep 29 08:24 bootx64.efi

/boot/efi/EFI/EFI: total 16 
drwxr-xr-x 4 root root 4096 ene 8 10:58 &lt;span class="nb"&gt;.&lt;/span&gt; 
drwxr-xr-x 6 root root 4096 ene 8 10:27 .. 
drwxr-xr-x 3 root root 4096 ene 8 10:58 EFI 
drwxr-xr-x 2 root root 4096 ene 8 10:27 manjaro

/boot/efi/EFI/EFI/EFI: total 12 
drwxr-xr-x 3 root root 4096 ene 8 10:58 &lt;span class="nb"&gt;.&lt;/span&gt; 
drwxr-xr-x 4 root root 4096 ene 8 10:58 .. 
drwxr-xr-x 2 root root 4096 ene 8 10:58 manjaro

/boot/efi/EFI/EFI/EFI/manjaro: total 164 
drwxr-xr-x 2 root root 4096 ene 8 10:58 &lt;span class="nb"&gt;.&lt;/span&gt; 
drwxr-xr-x 3 root root 4096 ene 8 10:58 .. 
&lt;span class="nt"&gt;-rwxr-xr-x&lt;/span&gt; 1 root root 159744 ene 8 10:58 grubx64.efi

/boot/efi/EFI/EFI/manjaro: total 164 
drwxr-xr-x 2 root root 4096 ene 8 10:27 &lt;span class="nb"&gt;.&lt;/span&gt; 
drwxr-xr-x 4 root root 4096 ene 8 10:58 .. 
&lt;span class="nt"&gt;-rwxr-xr-x&lt;/span&gt; 1 root root 159744 ene 8 10:27 grubx64.efi

/boot/efi/EFI/GRUB: total 164 
drwxr-xr-x 2 root root 4096 ene 8 10:25 &lt;span class="nb"&gt;.&lt;/span&gt; 
drwxr-xr-x 6 root root 4096 ene 8 10:27 .. 
&lt;span class="nt"&gt;-rwxr-xr-x&lt;/span&gt; 1 root root 159744 ene 8 10:25 grubx64.efi

/boot/efi/EFI/Manjaro: total 344 
drwxr-xr-x 2 root root 4096 ago 14 2024 &lt;span class="nb"&gt;.&lt;/span&gt; 
drwxr-xr-x 6 root root 4096 ene 8 10:27 .. 
&lt;span class="nt"&gt;-rwxr-xr-x&lt;/span&gt; 1 root root 344064 feb 8 21:32 grubx64.efi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Me centro en las importantes, &lt;code&gt;/boot/efi/EFI/Manjaro&lt;/code&gt; y la del fallback, &lt;code&gt;/boot/efi/EFI/boot&lt;/code&gt;. El resto las borraré después, en realidad son dos que contienen las otras 6. Copio el archivo grubx64.efi y lo sobrenombro en la ubicación de la fallback.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cp&lt;/span&gt; /boot/efi/EFI/Manjaro/grubx64.efi    /boot/efi/EFI/boot/bootx64.efi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Aunque sería raro que no fuese así, aquí compruebo que los tamaños coinciden.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;[&lt;/span&gt;manjaro /]# &lt;span class="nb"&gt;cp&lt;/span&gt; /boot/efi/EFI/Manjaro/grubx64.efi &lt;span class="se"&gt;\ &lt;/span&gt;/boot/efi/EFI/boot/bootx64.efi 
&lt;span class="o"&gt;[&lt;/span&gt;manjaro /]# &lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt; /boot/efi/EFI/boot/bootx64.efi 
&lt;span class="nt"&gt;-rwxr-xr-x&lt;/span&gt; 1 root root 344064 feb 8 21:46 /boot/efi/EFI/boot/bootx64.efi 
&lt;span class="o"&gt;[&lt;/span&gt;manjaro /]# &lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt; /boot/efi/EFI/Manjaro/grubx64.efi 
&lt;span class="nt"&gt;-rwxr-xr-x&lt;/span&gt; 1 root root 344064 feb 8 21:32 /boot/efi/EFI/Manjaro/grubx64.efi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  11. Salir y reiniciar
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;exit
sudo &lt;/span&gt;reboot
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;y extraímos el USB con el Manjaro Live.&lt;/p&gt;




&lt;h1&gt;
  
  
  Limpieza del GRUB y orden de arranque
&lt;/h1&gt;

&lt;p&gt;Si todo ha ido bien y nuestro sistema nativo ha arrancado, procedemos a poner un poco de orden.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Ver entradas UEFI
&lt;/h2&gt;

&lt;p&gt;Como comentaba en el paso 5 del bloque anterior, tenía más de dos carpetas en &lt;code&gt;/boot&lt;/code&gt; por lo que decidí comprobar cuáles eran las mal copiadas. Con el siguiente comando, puedes ver el registro del arranque y decidir qué hacer con las carpetas redundantes. En mi caso, las moví a un backup y probé si todo iba bien, por lo que decidí borrarlas a posteriori.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;efibootmgr &lt;span class="nt"&gt;-v&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;El contenido:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;BootCurrent: 0001 Timeout: 1 seconds 
BootOrder: 0001,0000 
Boot0000&lt;span class="k"&gt;*&lt;/span&gt; Manjaro HD&lt;span class="o"&gt;(&lt;/span&gt;1,GPT,73b40a30-b2a6-4754-a2c9-d97789fc433c,0x1000,0x96000&lt;span class="o"&gt;)&lt;/span&gt;/&lt;span class="se"&gt;\E&lt;/span&gt;FI&lt;span class="se"&gt;\M&lt;/span&gt;ANJARO&lt;span class="se"&gt;\G&lt;/span&gt;RUBX64.EFI dp: 04 01 2a 00 01 00 00 00 00 10 00 00 00 00 00 00 00 60 09 00 00 00 00 00 30 0a b4 73 a6 b2 54 47 a2 c9 d9 77 89 &lt;span class="nb"&gt;fc &lt;/span&gt;43 3c 02 02 / 04 04 36 00 5c 00 45 00 46 00 49 00 5c 00 4d 00 41 00 4e 00 4a 00 41 00 52 00 4f 00 5c 00 47 00 52 00 55 00 42 00 58 00 36 00 34 00 2e 00 45 00 46 00 49 00 00 00 / 7f ff 04 00 
Boot0001&lt;span class="k"&gt;*&lt;/span&gt; UEFI OS HD&lt;span class="o"&gt;(&lt;/span&gt;1,GPT,73b40a30-b2a6-4754-a2c9-d97789fc433c,0x1000,0x96000&lt;span class="o"&gt;)&lt;/span&gt;/&lt;span class="se"&gt;\E&lt;/span&gt;FI&lt;span class="se"&gt;\B&lt;/span&gt;OOT&lt;span class="se"&gt;\B&lt;/span&gt;OOTX64.EFI0000424f dp: 04 01 2a 00 01 00 00 00 00 10 00 00 00 00 00 00 00 60 09 00 00 00 00 00 30 0a b4 73 a6 b2 54 47 a2 c9 d9 77 89 &lt;span class="nb"&gt;fc &lt;/span&gt;43 3c 02 02 / 04 04 30 00 5c 00 45 00 46 00 49 00 5c 00 42 00 4f 00 4f 00 54 00 5c 00 42 00 4f 00 4f 00 54 00 58 00 36 00 34 00 2e 00 45 00 46 00 49 00 00 00 / 7f ff 04 00 data: 00 00 42 4f
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Poner Manjaro como primera opción
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;efibootmgr &lt;span class="nt"&gt;-o&lt;/span&gt; 0000,0001
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;El contenido:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;➜ ~ &lt;span class="nb"&gt;sudo &lt;/span&gt;efibootmgr &lt;span class="nt"&gt;-o&lt;/span&gt; 0000,0001 
BootCurrent: 0001 Timeout: 1 seconds BootOrder: 0000,0001 
Boot0000&lt;span class="k"&gt;*&lt;/span&gt; Manjaro HD&lt;span class="o"&gt;(&lt;/span&gt;1,GPT,73b40a30-b2a6-4754-a2c9-d97789fc433c,0x1000,0x96000&lt;span class="o"&gt;)&lt;/span&gt;/&lt;span class="se"&gt;\E&lt;/span&gt;FI&lt;span class="se"&gt;\M&lt;/span&gt;ANJARO&lt;span class="se"&gt;\G&lt;/span&gt;RUBX64.EFI 
Boot0001&lt;span class="k"&gt;*&lt;/span&gt; UEFI OS HD&lt;span class="o"&gt;(&lt;/span&gt;1,GPT,73b40a30-b2a6-4754-a2c9-d97789fc433c,0x1000,0x96000&lt;span class="o"&gt;)&lt;/span&gt;/&lt;span class="se"&gt;\E&lt;/span&gt;FI&lt;span class="se"&gt;\B&lt;/span&gt;OOT&lt;span class="se"&gt;\B&lt;/span&gt;OOTX64.EFI0000424f
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;El arranque de Manjaro sería el primero y si falla, el fallback toma el testigo. Este último registro se podría eliminar con:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;efibootmgr &lt;span class="nt"&gt;-b&lt;/span&gt; 0001 &lt;span class="nt"&gt;-B&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pero mejor dejarlo así.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Limpiar copias antiguas (opcional)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; /boot/efi/EFI/backup-EFI
&lt;span class="nb"&gt;sudo rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; /boot/efi/EFI/backup-GRUB
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Y hasta aquí, he podido restaurar el sistema de arranque de Manjaro sin víctimas. Mis agradecimientos a Juanra, Alejandro y José Luis porque este tutorial es un compendio de todos sus consejos.&lt;/p&gt;

&lt;p&gt;Foto: "&lt;a href="https://www.flickr.com/photos/pschube/8115702243/" rel="noopener noreferrer"&gt;Albion Low Loader Heavy Haulage 1951&lt;br&gt;
&lt;/a&gt; by pschube is licensed with &lt;a href="https://creativecommons.org/licenses/by/2.0/" rel="noopener noreferrer"&gt;CC BY 2.0&lt;/a&gt;&lt;/p&gt;

</description>
      <category>manjaro</category>
      <category>bootloader</category>
      <category>memcpy</category>
      <category>grub</category>
    </item>
    <item>
      <title>Servicios usados para un Data Lake en AWS</title>
      <dc:creator>Daniel M.</dc:creator>
      <pubDate>Tue, 12 Mar 2024 09:45:48 +0000</pubDate>
      <link>https://forem.com/daniconil/servicios-usados-para-un-data-lake-en-aws-4hdp</link>
      <guid>https://forem.com/daniconil/servicios-usados-para-un-data-lake-en-aws-4hdp</guid>
      <description>&lt;p&gt;Este artículo no es una guía, sino una serie de anotaciones de los servicios usados para montar un data lake con AWS. Partiendo de datos extraídos de una base de datos Amazon Aurora PostgreSQL, del que ya facilité &lt;a href="https://dev.to/daniconil/un-script-para-exportar-selectivamente-tablas-de-una-bd-en-aws-25l3"&gt;el script usado&lt;/a&gt; en este mismo espacio, y un esquema previo, fuimos preparando esta plataforma. Por mi parte, mi rol fue el de habilitar los flujos y las automatizaciones. Uno de los puntos en los que se dedicó más tiempo fue a afinar permisos para evitar posibles agujeros de seguridad.&lt;/p&gt;

&lt;p&gt;Pero, ¿qué es un data lake? Se trata de un repositorio en el que se almacenan datos en bruto con los que obtener información, a través de analítica y "cocina", para facilitar la toma de decisiones, ya sean estratégicas o de marketing.&lt;/p&gt;

&lt;p&gt;Como decía al principio, la información expuesta abajo son apuntes de los servicios usados, descartes y precisiones que se hicieron, especialmente en el AWS Identity and Access Management (IAM) para determinar los roles. &lt;/p&gt;

&lt;p&gt;⚠️ Este proyecto partió de cero con un esquema que fue modificándose con el tiempo haciéndolo más sencillo. Los nombres de los roles son ejemplos.&lt;/p&gt;

&lt;p&gt;Hecha la introducción, y recordando que ya subí el &lt;a href="https://dev.to/daniconil/un-script-para-exportar-selectivamente-tablas-de-una-bd-en-aws-25l3"&gt;script&lt;/a&gt; con el que se extraían los datos de una instancia de Amazon Aurora PostgreSQL (RDS), comento los servicios usados:&lt;/p&gt;

&lt;h2&gt;
  
  
  IAM
&lt;/h2&gt;

&lt;p&gt;AWS Identity and Access Management (IAM) es un servicio web que lo ayuda a controlar de forma segura el acceso a los recursos de AWS. Con IAM, puede administrar de forma centralizada los permisos que controlan a qué recursos de AWS pueden acceder los usuarios. Utilice IAM para controlar quién está autenticado (ha iniciado sesión) y autorizado (tiene permisos) para utilizar recursos.&lt;/p&gt;

&lt;h3&gt;
  
  
  Roles
&lt;/h3&gt;

&lt;p&gt;De nombre AWSGlueServiceRole-crawlers, estos son los permisos asociaciados a este rol: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;AWSCodeCommitFullAccess (AWS managed)&lt;/li&gt;
&lt;li&gt;AWSGlueServiceRole (AWS managed)&lt;/li&gt;
&lt;li&gt;AWSGlueServiceRole-crawlers-s3Policy (Customer managed, expuesto más abajo)&lt;/li&gt;
&lt;li&gt;AWSKeyManagementServicePowerUser (AWS managed)
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2012-10-17"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Statement"&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="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Principal"&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="nl"&gt;"Service"&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;"databrew.amazonaws.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="s2"&gt;"kms.amazonaws.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="s2"&gt;"glue.amazonaws.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="s2"&gt;"codecommit.amazonaws.com"&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="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sts:AssumeRole"&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="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Policies
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;AWSGlueServiceRole-ics-glue&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Rol para albergar la calendarización con permisos de tomar y depositar objetos en un bucket S3.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2012-10-17"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Statement"&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="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Action"&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;"s3:GetObject"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"s3:PutObject"&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="nl"&gt;"Resource"&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;"arn:aws:s3:::calendar-files-eu*"&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="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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;AWSGlueServiceRole-crawlers-EZCRC-s3Policy&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Recuerdo que nos tomó cierto tiempo hasta descubrir que era imprescindible indicar las acciones &lt;code&gt;Encrypt&lt;/code&gt; y &lt;code&gt;Decrypt&lt;/code&gt; de manera explícita.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2012-10-17"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Statement"&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="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Sid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"VisualEditor0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Action"&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;"s3:PutObject"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"s3:GetObject"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"s3:DeleteObject"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"kms:GenerateDataKey"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"kms:Encrypt"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"kms:Decrypt"&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="nl"&gt;"Resource"&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;"arn:aws:kms:us-west-2:[AWS_ID]:key/[appflow-key]"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:kms:us-west-2:[AWS_ID]:key/[rds_key]"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:kms:us-west-2:[AWS_ID]:key/[ssh_key]"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:s3:::datalake/ga4-funnel-events-flow/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:s3:::datalake/ga4-user-ids-flow/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:s3:::datalake/ga4-user-engagement-flow/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:s3:::datalake/ga4-traffic-flow/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:s3:::datalake/ga4-user-searches-flow/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:s3:::datalake/ga4-destinations-flow/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:s3:::datalake/ga4-listing-views-referrers-flow/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:s3:::datalake/raw_internal/export/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:s3:::datalake/processed_data/*"&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="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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Nota:&lt;/strong&gt; &lt;code&gt;ga4&lt;/code&gt; es la implementación de Google Analytics 4.&lt;/p&gt;

&lt;h2&gt;
  
  
  KMS
&lt;/h2&gt;

&lt;p&gt;AWS KMS sirve para cifrar datos en sus cargas de trabajo de KMS, firmar datos de manera digital, cifrar dentro de sus aplicaciones con SDK de cifrado de AWS y generar y verificar códigos de autenticación de mensajes. En el JSON de arriba aparecen expuesto tres, que están descritos en este apartado. El KMS viene representado por una ristra de números y caracteres típico de una clave pública. En este caso, lo hemos cambiado por el nombre y puesto entre corchetes para indicar que en realidad es otro dato el que debería ir ahí y que, por seguridad, no se expone. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;appflow_key&lt;/strong&gt;, se trata de la clave que autoriza el acceso de servicios externos como Google Analytics. Más información en la &lt;a href="https://aws.amazon.com/es/appflow/"&gt;sección de Integración de SaaS de AWS&lt;/a&gt;. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;rds_key&lt;/strong&gt;, la clave de autorización del intercambio de información desde una instancia del servicio RDS.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ssh_key&lt;/strong&gt;, la conexión con las instancias.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  CodeCommit
&lt;/h2&gt;

&lt;p&gt;Este servicio es un repositorio de código, usado para alojar las versiones de los distintos scripts usados por la persona que ostente el rol de analista. CodeCommit es sencillo de implementar y automatiza cualquier cambio desde Athena, es decir, si se modifica el script, esta acción conlleva hacer git add, commit y push. No consume apenas porque para este cometido no llega a superar la capa gratuita de AWS. Dentro de Glue cabe también la posibilidad de usar GitHub, pero preferimos usar el nativo de AWS. &lt;/p&gt;

&lt;h2&gt;
  
  
  Glue
&lt;/h2&gt;

&lt;p&gt;AWS Glue es un servicio de integración de datos sin servidor que facilita a los usuarios de análisis descubrir, preparar, migrar e integrar datos de varios orígenes. Puede utilizarlo para análisis, machine learning y desarrollo de aplicaciones. También incluye herramientas adicionales de productividad y operaciones de datos para la creación, la ejecución de trabajos y la implementación de flujos de trabajo empresariales. &lt;/p&gt;

&lt;p&gt;Como sysadmin, se me escapa el uso más allá de acceder a él para preparar las automatizaciones con otros servicios.&lt;/p&gt;

&lt;h2&gt;
  
  
  DataBrew
&lt;/h2&gt;

&lt;p&gt;Este servicio fue descartado porque conseguimos extraer la información directamente de la base de datos en un formato, .parquet, que le venía bien al analista de datos. &lt;/p&gt;

&lt;h2&gt;
  
  
  S3
&lt;/h2&gt;

&lt;p&gt;Servicio de alojamiento donde albergar la información. Tanto en el script como en estas notas tiene el nombre raíz de "datalake".&lt;/p&gt;

&lt;h2&gt;
  
  
  Athena
&lt;/h2&gt;

&lt;p&gt;Amazon Athena es un servicio de análisis interactivo y sin servidor creado en marcos de código abierto, lo que lo hace compatible con formatos abiertos de archivos y tablas. Athena proporciona un método simplificado y flexible de analizar petabytes de datos donde residan. Analice datos o cree aplicaciones a partir de un lago de datos de Amazon Simple Storage Service (S3) y más de 30 orígenes de datos, que incluyen orígenes de datos en las instalaciones u otros sistemas en la nube que usan SQL o Python.&lt;/p&gt;

&lt;p&gt;En nuestro caso, comenzamos implementando Athena conectándolo a la base de datos vía Metabase con el conector oficial.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.metabase.com/docs/latest/databases/connections/athena"&gt;Amazon Athena&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Script de exportación
&lt;/h2&gt;

&lt;p&gt;Alojado en una instancia EC2 y programado, en estas notas ha sido enlazado en más de una ocasión y qué menos que indicarlo aquí también como otro de los requisitos:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/daniconil/un-script-para-exportar-selectivamente-tablas-de-una-bd-en-aws-25l3"&gt;Un script para exportar selectivamente tablas de una BD en AWS&lt;/a&gt;. &lt;/p&gt;




&lt;p&gt;Termino recordando de qué se trata este artículo, son el esbozo de unas anotaciones para construir un data lake con AWS del que partimos con más corazón que conocimientos y un esquema que fue modificándose poco a poco.&lt;/p&gt;

</description>
      <category>datalake</category>
      <category>aws</category>
      <category>athena</category>
      <category>iam</category>
    </item>
    <item>
      <title>Un script para exportar selectivamente tablas de una BD en AWS</title>
      <dc:creator>Daniel M.</dc:creator>
      <pubDate>Fri, 08 Mar 2024 11:14:42 +0000</pubDate>
      <link>https://forem.com/daniconil/un-script-para-exportar-selectivamente-tablas-de-una-bd-en-aws-25l3</link>
      <guid>https://forem.com/daniconil/un-script-para-exportar-selectivamente-tablas-de-una-bd-en-aws-25l3</guid>
      <description>&lt;p&gt;Eres el sysadmin de una empresa y el departamento destinado a mejorar el producto te solicita un "data lake" donde albergar datos en bruto procedentes de bases de datos para cocinarlos y tomar decisiones. Una de las partes fundamentales de un proyecto así es la extracción de datos, así como su fiabilidad y rapidez en el proceso, que en este caso es diario. Preparas una extracción pero dura demasiado y son gigas y gigas de transferencia que no necesitan, por lo que, finalmente, comprobáis que sólo requieren información de unas 90 tablas de un total de más de 14000 que tiene el proyecto completo. La plataforma está montada en AWS y hemos de ver cómo hacerles llegar esa información totalmente optimizada en tiempo, filtrado y orden. Contamos con una pequeña máquina de EC2 en la infraestructura donde alojamos scripts, por lo que es el sitio idóneo para ello. A partir de aquí, el comando &lt;a href="https://awscli.amazonaws.com/v2/documentation/api/latest/reference/rds/start-export-task.html"&gt;&lt;code&gt;start-export-task&lt;/code&gt;&lt;/a&gt; se convierte en nuestro aliado.&lt;/p&gt;

&lt;h2&gt;
  
  
  ¿Qué servicios AWS usaremos?
&lt;/h2&gt;

&lt;p&gt;El listado de servicios que usaremos son los siguientes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;S3, donde se albergan los datos.&lt;/li&gt;
&lt;li&gt;RDS, la instancia de la base de datos. En este caso, postgres.&lt;/li&gt;
&lt;li&gt;EC2, la máquina donde configuramos el script.&lt;/li&gt;
&lt;li&gt;SNS, el servicio de notificaciones para envíos por correo.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  ¿Qué requisitos necesitamos?
&lt;/h2&gt;

&lt;p&gt;La máquina donde alojaremos el script ha de tener instalado AWS CLI. Se presupone que en una máquina de AWS ha de venir de serie, pero por si queremos hacerlo en otra instancia, ya sea una máquina virtual o en nuestro propio equipo, es muy sencillo, sólo hay que copiar &lt;a href="https://docs.aws.amazon.com/es_es/cli/latest/userguide/getting-started-install.html"&gt;el siguiente comando proporcionado por AWS&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="s2"&gt;"https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip"&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="s2"&gt;"awscliv2.zip"&lt;/span&gt;
unzip awscliv2.zip
&lt;span class="nb"&gt;sudo&lt;/span&gt; ./aws/install
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para comprobar que está todo correcto:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; ~ aws --version
aws-cli/2.7.35 Python/3.9.11 Linux/5.15.0-97-generic exe/x86_64.ubuntu.20 prompt/off
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ya lo tenemos todo para dejar preparado un script que haga lo siguiente:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Eliminar la copia del día anterior. Los datos no son necesario albergarlos y no pueden mezclarse, por lo que se pueden borrar.&lt;/li&gt;
&lt;li&gt;Mediante la opción &lt;code&gt;start-export-task&lt;/code&gt; del comando &lt;code&gt;rds&lt;/code&gt;, identificar la base de datos y las tablas que queremos exportar con el parámetro &lt;code&gt;--export-only&lt;/code&gt;. En este caso, hemos puesto 6 tablas.&lt;/li&gt;
&lt;li&gt;Ha de existir un rol en IAM que tenga acceso de lectura en RDS y escritura en S3, así como la capacidad de crear "buckets".&lt;/li&gt;
&lt;li&gt;Se hizo un &lt;code&gt;case&lt;/code&gt; para enviar un correo según el estado en el que se encontraba la exportación. Se hacen comprobaciones cada 120 segundos y mientras fuera distinto de "COMPLETE", vuelve a esperarse 120 segundos antes de otra comprobación del estado. Para conocer el estado, la línea es &lt;code&gt;identifier postgres-partial-export-$DATE | jq -r&lt;/code&gt;.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-ex&lt;/span&gt;
&lt;span class="nv"&gt;DATE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt; +%Y-%m-%d-%H-%M&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;PRO_DBNAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;database
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Removing old data"&lt;/span&gt;
aws s3 &lt;span class="nb"&gt;rm &lt;/span&gt;s3://datalake/raw_internal/export &lt;span class="nt"&gt;--recursive&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Copying &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PRO_DBNAME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; @ postgres tables to the Data Lake directory"&lt;/span&gt;
aws rds start-export-task &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--export-task-identifier&lt;/span&gt; postgres-partial-export-&lt;span class="nv"&gt;$DATE&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--source-arn&lt;/span&gt; arn:aws:rds:us-west-2:[AWS_ID]:cluster:[nombre_cluster_rds] &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--s3-bucket-name&lt;/span&gt; datalake &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--s3-prefix&lt;/span&gt; raw_internal/export &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--export-only&lt;/span&gt; database.public.tabla1 database.public.tabla1 database.public.tabla2 database.public.tabla3 database.public.tabla4 database.public.tabla5 database.public.tabla6 &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--iam-role-arn&lt;/span&gt; arn:aws:iam::[AWS_ID]:role/rds-export-to-s3 &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--kms-key-id&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;KMS_ID] &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--no-cli-pager&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Process started"&lt;/span&gt;
&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$status&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="s2"&gt;"COMPLETE"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"What's the status?"&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$status&lt;/span&gt;
&lt;span class="nv"&gt;status&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;aws rds describe-export-tasks &lt;span class="nt"&gt;--export-task-identifier&lt;/span&gt; postgres-partial-export-&lt;span class="nv"&gt;$DATE&lt;/span&gt; | jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s2"&gt;".ExportTasks[].Status"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nv"&gt;$status&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;
&lt;span class="s2"&gt;"STARTING"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nb"&gt;sleep &lt;/span&gt;120 &lt;span class="p"&gt;;;&lt;/span&gt;
&lt;span class="s2"&gt;"IN_PROGRESS"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nb"&gt;sleep &lt;/span&gt;120 &lt;span class="p"&gt;;;&lt;/span&gt;
&lt;span class="s2"&gt;"CANCELING"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nb"&gt;sleep &lt;/span&gt;120 &lt;span class="p"&gt;;;&lt;/span&gt;
&lt;span class="s2"&gt;"CANCELED"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Canceled, sending an email"&lt;/span&gt;
aws ses send-email &lt;span class="nt"&gt;--from&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;report@domain.com]&lt;span class="o"&gt;(&lt;/span&gt;mailto:report@domain.com&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;--to&lt;/span&gt; datascience[@domain.com]&lt;span class="o"&gt;(&lt;/span&gt;mailto:datalake@domain.com&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;--subject&lt;/span&gt; &lt;span class="s2"&gt;"Export status &lt;/span&gt;&lt;span class="nv"&gt;$status&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;--text&lt;/span&gt; &lt;span class="s2"&gt;"Hi, the export has been canceled. This email has been sent at &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt; via AWS CLI"&lt;/span&gt;
&lt;span class="nb"&gt;break&lt;/span&gt;
&lt;span class="p"&gt;;;&lt;/span&gt;
&lt;span class="s2"&gt;"COMPLETE"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Ready to move it to the main directory"&lt;/span&gt;
&lt;span class="nb"&gt;sleep &lt;/span&gt;5
aws s3 &lt;span class="nb"&gt;mv &lt;/span&gt;s3://datalake/raw_internal/export/postgres-partial-export-&lt;span class="nv"&gt;$DATE&lt;/span&gt;/database/ s3://datalake/raw_internal/export &lt;span class="nt"&gt;--recursive&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Leaving successfully"&lt;/span&gt;
aws ses send-email &lt;span class="nt"&gt;--from&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;report@domain.com]&lt;span class="o"&gt;(&lt;/span&gt;mailto:report@domain.com&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;--to&lt;/span&gt; datascience[@domain.com]&lt;span class="o"&gt;(&lt;/span&gt;mailto:datalake@domain.com&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;--subject&lt;/span&gt; &lt;span class="s2"&gt;"Export status &lt;/span&gt;&lt;span class="nv"&gt;$status&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;--html&lt;/span&gt; &lt;span class="s2"&gt;"&amp;lt;p&amp;gt;Hi,&amp;lt;/p&amp;gt; &amp;lt;p&amp;gt;the export status is &lt;/span&gt;&lt;span class="nv"&gt;$status&lt;/span&gt;&lt;span class="s2"&gt;.&amp;lt;/p&amp;gt;&amp;lt;p&amp;gt;The report: [https://us-west-2.console.aws.amazon.com/rds/home?region=us-west-2#exports-in-s3:](https://us-west-2.console.aws.amazon.com/rds/home?region=us-west-2#exports-in-s3:) &amp;lt;/p&amp;gt;&amp;lt;p&amp;gt;The export bucket: [https://us-west-2.console.aws.amazon.com/s3/buckets/datalake?region=us-west-2&amp;amp;prefix=raw_internal/export/&amp;amp;showversions=false](https://us-west-2.console.aws.amazon.com/s3/buckets/datalake?region=us-west-2&amp;amp;prefix=raw_internal/export/&amp;amp;showversions=false)&amp;lt;/p&amp;gt; &amp;lt;p&amp;gt;This automated message has been sent at &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt; via AWS CLI, please do not reply.&amp;lt;/p&amp;gt;"&lt;/span&gt;
&lt;span class="p"&gt;;;&lt;/span&gt;
&lt;span class="s2"&gt;"FAILED"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Failed, sending an e-mail"&lt;/span&gt;
aws ses send-email &lt;span class="nt"&gt;--from&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;report@domain.com]&lt;span class="o"&gt;(&lt;/span&gt;mailto:report@domain.com&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;--to&lt;/span&gt; datascience[@domain.com]&lt;span class="o"&gt;(&lt;/span&gt;mailto:datalake@domain.com&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;--subject&lt;/span&gt; &lt;span class="s2"&gt;"Export status &lt;/span&gt;&lt;span class="nv"&gt;$status&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;--text&lt;/span&gt; &lt;span class="s2"&gt;"Hi, the export has failed. Exports in Amazon S3: [https://us-west-2.console.aws.amazon.com/rds/home?region=us-west-2#exports-in-s3:](https://us-west-2.console.aws.amazon.com/rds/home?region=us-west-2#exports-in-s3:) //  This email has been sent at &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt; via AWS CLI"&lt;/span&gt;
&lt;span class="nb"&gt;break&lt;/span&gt;
&lt;span class="p"&gt;;;&lt;/span&gt;
&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Unknown response"&lt;/span&gt; &lt;span class="p"&gt;;;&lt;/span&gt;
&lt;span class="k"&gt;esac&lt;/span&gt;
&lt;span class="k"&gt;done
&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Process finished"&lt;/span&gt;
&lt;span class="nb"&gt;exit &lt;/span&gt;0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Programar el script
&lt;/h2&gt;

&lt;p&gt;Hay dos opciones para hacer que el script se ejecute con periodicidad:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://linuxhandbook.com/crontab/"&gt;Incluirlo en crontab&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://linuxhandbook.com/create-systemd-services/"&gt;Crear un servicio systemd&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>aws</category>
      <category>rds</category>
      <category>cli</category>
      <category>s3</category>
    </item>
    <item>
      <title>Cómo montar una VPN rápido y sin complicaciones donde quieras</title>
      <dc:creator>Daniel M.</dc:creator>
      <pubDate>Fri, 08 Mar 2024 09:45:52 +0000</pubDate>
      <link>https://forem.com/daniconil/como-montar-una-vpn-rapido-y-sin-complicaciones-donde-quieras-12pb</link>
      <guid>https://forem.com/daniconil/como-montar-una-vpn-rapido-y-sin-complicaciones-donde-quieras-12pb</guid>
      <description>&lt;p&gt;⚠️ Este tutorial sirve para montar una VPN en 5 minutos por si necesitas conexiones esporádicas a alguna red en concreto. Si lo usas de manera profesional, asegúrate de tener la paquetería de seguridad actualizada.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dónde instalar el servidor VPN
&lt;/h2&gt;

&lt;p&gt;Partimos de cero eligiendo una VPS según nuestros requisitos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Si es para &lt;strong&gt;conectarnos a una red local&lt;/strong&gt; del que queramos usar servicios, montamos una máquina virtual, Raspberry Pi o cualquier otra opción que nos ofrezca poder instalar una distribución de Ubuntu Server. &lt;/li&gt;
&lt;li&gt;Si es para &lt;strong&gt;facilitarnos una IP específica&lt;/strong&gt; de un país, ya sea porque trabajamos en un marketplace con geolocalización y necesitamos comprobar que sale la moneda local de inicio, entre otros casos. Si es así, en servicios como Digital Ocean o Linode podemos crear una VPS (&lt;a href="https://www.digitalocean.com/community/tutorials/initial-server-setup-with-ubuntu-20-04"&gt;Droplet&lt;/a&gt; en el caso de Digital Ocean) con Ubuntu Server.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Cómo instalar el servidor VPN
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Saber cuál es nuestra IP real, podemos verla en &lt;a href="http://whatismyip.com"&gt;whatismyip.com&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Una vez montada la instancia de Ubuntu Server según nuestras necesidades, descargamos el script de GitHub con permisos de root:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-O&lt;/span&gt; https://raw.githubusercontent.com/angristan/openvpn-install/master/openvpn-install.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Damos permisos de ejecución al script:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;chmod&lt;/span&gt; +x openvpn-install.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Ejecutamos el script:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./openvpn-install.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Los primeros pasos para configurar la VPN son:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;IP pública del servidor&lt;/li&gt;
&lt;li&gt;Activar o no el soporte IPv6 (por defecto: no)&lt;/li&gt;
&lt;li&gt;Puerto del VPN (por defecto: 1194)&lt;/li&gt;
&lt;li&gt;Protocolo: (UDP)&lt;/li&gt;
&lt;li&gt;DNS: En mi caso, he elegido OpenDNS (8)&lt;/li&gt;
&lt;li&gt;Activar compresión (por defecto: no)&lt;/li&gt;
&lt;li&gt;Personalizar las opciones de cifrado (por defecto: no)&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;
&lt;li&gt;&lt;p&gt;¡Listo! Siguiendo con la configuración de openVPN, el script permite crear el primer archivo .ovpn de credenciales. Es muy sencillo, escribe un nombre y la opción de si incluir una contraseña o no de importación.    &lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyrilsp4o1zbfvvl7qvt5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyrilsp4o1zbfvvl7qvt5.png" alt="Archivos de configuración de openVPN" width="700" height="166"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;También podemos revisar el estado de openVPN con este comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;systemctl status openvpn
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Con un resultado similar a éste:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;● openvpn.service - OpenVPN service
Loaded: loaded &lt;span class="o"&gt;(&lt;/span&gt;/lib/systemd/system/openvpn.service&lt;span class="p"&gt;;&lt;/span&gt; enabled&lt;span class="p"&gt;;&lt;/span&gt; vendor preset: enabled&lt;span class="o"&gt;)&lt;/span&gt;
Active: active &lt;span class="o"&gt;(&lt;/span&gt;exited&lt;span class="o"&gt;)&lt;/span&gt; since Tue 2022-08-30 09:21:07 UTC&lt;span class="p"&gt;;&lt;/span&gt; 1 day 23h ago
Main PID: 12963 &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;code&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;exited, &lt;span class="nv"&gt;status&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0/SUCCESS&lt;span class="o"&gt;)&lt;/span&gt;
CPU: 4ms
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Cómo añadir perfiles
&lt;/h3&gt;

&lt;p&gt;Una vez hecho todo lo de arriba, no tenemos que volver a configurar nada si queremos crear perfiles y descargar las credenciales, o también revocarlas si queremos denegarles el acceso.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bash openvpn-install.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;El menú es el siguiente:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Welcome to OpenVPN-install!
The git repository is available at: [https://github.com/angristan/openvpn-install](https://github.com/angristan/openvpn-install)
It looks like OpenVPN is already installed.
What do you want to do?
1) Add a new user
2) Revoke existing user
3) Remove OpenVPN
4) Exit
Select an option [1-4]:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Si queremos crear un nuevo perfil, elegimos la primera opción y los pasos serán los mismos que en la última parte del proceso inicial.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Nombre del perfil.&lt;/li&gt;
&lt;li&gt;Como medida de seguridad, podemos asignarle una contraseña. Por ello, elegimos la segunda opción, “Use a password for the client” just to import it.&lt;/li&gt;
&lt;li&gt;Copiar ese archivo a nuestro equipo local para conectarnos, o enviársela a una persona para que se conecte.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Cómo compartir el archivo con otras personas
&lt;/h3&gt;

&lt;p&gt;Existe multitud de opciones, por ejemplo usando el comando scp para enviar remotamente copias de archivos, pero en este caso, vamos a hacerlo de una manera más simple.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;archivo.ovpn
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Entendiendo que hacemos el listado del archivo conectado por ssh a donde hemos instalado el servidor VPN, copiamos el contenido y, ya en &lt;strong&gt;local&lt;/strong&gt;, usamos nuestro editor favorito:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vim archivo.ovpn
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;el archivo, al no existir en local, se crea nuevo y sólo necesitamos pulsar la tecla &lt;code&gt;i&lt;/code&gt; ([INSERT]) y &lt;code&gt;CTRL+shift+v&lt;/code&gt; para copiar el contenido.&lt;/p&gt;

&lt;p&gt;El último paso para salir:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;:wq
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Cómo comprobar las conexiones recientes
&lt;/h3&gt;

&lt;p&gt;Puedes ver quién está conectado a la instancia con:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; /var/log/openvpn/status.log
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Con un resultado como éste:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;OpenVPN CLIENT LIST
Updated,2023-02-07 14:41:27
Common Name,Real Address,Bytes Received,Bytes Sent,Connected Since
&lt;span class="o"&gt;[&lt;/span&gt;nombrearchivo],[IP de su equipo]:49161,2759574,2477388,2023-02-07 14:39:55
ROUTING TABLE
Virtual Address,Common Name,Real Address,Last Ref
10.8.0.2,gh-[name+username],[remote IP]:49161:49161,2023-02-07 14:41:26
GLOBAL STATS
Max bcast/mcast queue length,0
END
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Cómo instalar el cliente VPN en Ubuntu
&lt;/h2&gt;

&lt;p&gt;🦘 Si ya tienes configurado el cliente VPN en el sistema, salta directamente al punto 4. Los puntos previos son para instalar y activar los servicios. Los pasos a seguir son para distribuciones tipo Debian.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Abre un terminal e instala la paquetería necesaria&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;openvpn network-manager-openvpn
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Activa y habilita el servicio openVPN:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl start openvpn &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl &lt;span class="nb"&gt;enable &lt;/span&gt;openvpn
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Revisa el estado del permiso con:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl status openvpn
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;obtendrás un mensaje similar a éste&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;● openvpn.service - OpenVPN service
Loaded: loaded &lt;span class="o"&gt;(&lt;/span&gt;/lib/systemd/system/openvpn.service&lt;span class="p"&gt;;&lt;/span&gt; enabled&lt;span class="p"&gt;;&lt;/span&gt; vendor preset: enabled&lt;span class="o"&gt;)&lt;/span&gt;
Active: active &lt;span class="o"&gt;(&lt;/span&gt;exited&lt;span class="o"&gt;)&lt;/span&gt; since Wed 2022-08-31 08:12:00 CEST&lt;span class="p"&gt;;&lt;/span&gt; 3h 11min ago
Main PID: 1427 &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;code&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;exited, &lt;span class="nv"&gt;status&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0/SUCCESS&lt;span class="o"&gt;)&lt;/span&gt;
Tasks: 0 &lt;span class="o"&gt;(&lt;/span&gt;limit: 37661&lt;span class="o"&gt;)&lt;/span&gt;
Memory: 0B
CGroup: /system.slice/openvpn.service
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Sube el archivo de configuración de extensión .ovpn&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4vfq06l6bao3u1byqm77.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4vfq06l6bao3u1byqm77.png" alt="Escritorio GNOME" width="800" height="661"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Tras seguir los pasos de cómo cargar el archivo .ovpn, puedes comprobar tu IP de nuevo en &lt;a href="http://whatismyip.com"&gt;whatismyip.com&lt;/a&gt; y verificar si ha ido todo correcto.&lt;/p&gt;

&lt;p&gt;Esto es todo, muy sencillo por ejemplo si tienes un servidor NAS en casa pero no quieres conectarlo a la red pública por privacidad. O tienes una cuenta compartida de algún servicio de streaming y necesitas que tu dispositivo se identifique como "hogar" una vez al mes ;-)&lt;/p&gt;

&lt;p&gt;Termino este tutorial igual que como lo empecé, aconsejando que la paquetería de seguridad sea debidamente actualizada.&lt;/p&gt;

&lt;h2&gt;
  
  
  VPN known issues
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Timeout error
&lt;/h3&gt;

&lt;p&gt;En caso de que tengas un timeout en el log[1] y estás usando un escritorio distinto a GNOME, reinicia el servicio de network-manager. Dos opciones:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;service network-manager restart
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;o en su lugar&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl restart systemd-networkd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ubuntu usa network-manager en lugar del servicio por defecto de otras distribuciones.&lt;/p&gt;

&lt;p&gt;[1] Obtén información tecleando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;grep &lt;/span&gt;openvpn /var/log/syslog
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Slack
&lt;/h3&gt;

&lt;p&gt;Encendiendo o apagando la VPN, Slack tendrá un retraso en la conexión de al menos 30-40 segundos en la app de Slack, como si se quedara desconectado. Vía web no me ha ocurrido y tampoco con otra aplicación.&lt;/p&gt;

&lt;h3&gt;
  
  
  Kubuntu
&lt;/h3&gt;

&lt;p&gt;Hay un bug en KDE no resuelto. Importamos el archivo openvpn en la interfaz del network-manager. Se conecta, timeout, pero no tenemos más pistas. Lo llamativo es que conectándonos vía terminal va perfectamente:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;openvpn —config &lt;span class="o"&gt;[&lt;/span&gt;file].ovpn
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hemos de abrir el archivo openvpn y extraer el bloque &lt;strong&gt;key&lt;/strong&gt; en un archivo independiente. El bloque es algo como esto:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;-----BEGIN OpenVPN Static key V1-----
92e2de5ae643729863zzzz4a0ebe952
.
.
.

cc05zxzxczczxxczxzxczxce902b498a5
-----END OpenVPN Static key V1-----

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sálvalo con la extensión &lt;code&gt;[archivo].key&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Por ello:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Abre la conexión openVPN ya creada en networkmanager.&lt;/li&gt;
&lt;li&gt;Elige "Advanced..." en la pestaña VPN, luego &lt;strong&gt;TLS Settings&lt;/strong&gt;, y cambia sólo dos cosas:

&lt;ol&gt;
&lt;li&gt;Modo a &lt;strong&gt;TLS-Crypt&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;y el hueco de "Key File", usa la ruta del archivo .key creado anteriormente. ¡No lo elimines!&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Et voilà, la conexión funcionará.&lt;/p&gt;

&lt;p&gt;Información sobre este bug:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://bugs.launchpad.net/ubuntu/+source/network-manager-openvpn/+bug/1847144"&gt;Bug #1847144 “network-manager-openvpn config import ignores tls-...” : Bugs : network-manager-openvpn package : Ubuntu&lt;/a&gt;&lt;/p&gt;

</description>
      <category>vpn</category>
      <category>openvpn</category>
      <category>ubuntu</category>
    </item>
    <item>
      <title>Cómo montar un servidor de arranque PXE en Ubuntu 22.04</title>
      <dc:creator>Daniel M.</dc:creator>
      <pubDate>Wed, 14 Dec 2022 17:54:11 +0000</pubDate>
      <link>https://forem.com/daniconil/como-montar-un-servidor-de-arranque-pxe-en-ubuntu-2204-13f0</link>
      <guid>https://forem.com/daniconil/como-montar-un-servidor-de-arranque-pxe-en-ubuntu-2204-13f0</guid>
      <description>&lt;p&gt;Eres SysAdmin de una empresa y tienes por delante restaurar la distribución de 25 equipos que necesitan reinstalación. Puede considerarse una labor tediosa que piensas que es mejor automatizar, además añadiendo una configuración personalizada. Pero, ¿esto es posible? Sí. ¿Que puedo dejar instalados 25 equipos todos iguales de manera simultánea? ¡Sí! Existe PXE, como si tienes 90 o 100 equipos, pero, ¿qué es eso y cómo puedo montarlo? Vamos a ello, solo necesitaremos Ubuntu Server 22.04 instalado en una máquina virtual donde montaremos este servidor PXE para poder instalar imágenes de Ubuntu 22.04. Podemos elegir otra versión, como la 20.04, pero así comprobamos la compatibilidad con la más LTS más reciente. El último punto será crear la personalización que, como las opiniones, cada uno puede tener la suya. &lt;/p&gt;

&lt;h2&gt;
  
  
  Introducción
&lt;/h2&gt;

&lt;p&gt;PXE es un protocolo utilizado para iniciar sistemas operativos a través de la red. Se puede usar este método para instalar nuestra distribución de GNU/Linux favorita en portátil, servidor u ordenador de escritorio a través de la red.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configurando IP estática en Ubuntu Server 22.04 LTS
&lt;/h2&gt;

&lt;p&gt;Antes de continuar, es mejor configurar el servidor de arranque PXE con una dirección IP estática. En esta primera sección, veremos cómo configurarla.&lt;/p&gt;

&lt;p&gt;Para configurar una dirección IP estática en Ubuntu Server 22.04 LTS, abrimos el archivo de configuración de netplan con un editor de texto, en este caso &lt;strong&gt;nano&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo nano /ect/netplan/00-installer-config.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;E incluimos lo siguiente teniendo en cuenta que:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;La interfaz en este caso es enp0s3, puedes saber cuál es al teclear

&lt;code&gt;ip a&lt;/code&gt;

en el terminal,&lt;/li&gt;
&lt;li&gt;192.168.180/24 es la IP que deseamos darle y la máscara de red de la configuración,&lt;/li&gt;
&lt;li&gt;192.168.1.1 es la IP del router como servidor DHCP,&lt;/li&gt;
&lt;li&gt;1.1.1.1 y 8.8.8.8 son direcciones DNS reconocidas&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;y podemos crearlo bajo nuestros propios parámetros.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#This is the network config written by 'subiquity'. IP addresses are an example&lt;/span&gt;
network:
  ethernets:
    enp0s3:
      dhcp4: no
      addresses:
        - 192.168.1.180/24
      routes:
        - to: default
          via: 192.168.1.1
      nameservers:
        addresses:
          - 1.1.1.1
          - 8.8.8.8
  version: 2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Para aplicar los cambios, ejecutamos:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo netplan apply
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Creando la estructura de directorios requerida
&lt;/h2&gt;

&lt;p&gt;Nuestra estructura de directorios tendrá la siguiente forma:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;/pxeboot&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;y como subdirectorios&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;/config/&lt;/code&gt;&lt;/strong&gt; , donde guardaremos los archivos de arranque.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;/firmware/&lt;/code&gt;&lt;/strong&gt;, donde guardaremos los firmware.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;/images/&lt;/code&gt;&lt;/strong&gt;, donde guardaremos las imágenes que pueden listarse en el menú.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;En el directorio &lt;code&gt;/pxeboot/images/&lt;/code&gt; copiaremos el contenido de cada imagen ISO en un subdirectorio por cada distribución. Esto lo veremos más adelante.  &lt;/p&gt;

&lt;p&gt;Para crear todos los directorios requeridos en un solo comando, ejecutamos:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo mkdir -pv /pxeboot/{config,firmware,images}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Descargando el código fuente de iPXE y compilación en Ubuntu 22.04
&lt;/h2&gt;

&lt;p&gt;Estos pasos los haremos en nuestra carpeta de &lt;code&gt;\home\$USER&lt;/code&gt;, lo último será moverlo todo a los directorios creados en el paso anterior.&lt;/p&gt;

&lt;p&gt;En primer lugar, actualizamos los repositorios e instalamos los siguientes paquetes:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt update &amp;amp;&amp;amp; sudo apt install build-essential liblzma-dev isolinux git -y
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Clonamos el repositorio de iPXE en GitHub en nuestro servidor:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone https://github.com/ipxe/ipxe.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Accedemos a la carpeta &lt;code&gt;ipxe/src&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd ipxe/src
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Para configurar iPXE como arranque automático, hemos de crear el script correspondiente y relacionarlo con los firmwares de BIOS y UEFI cuando ya esté todo compilado.&lt;/p&gt;

&lt;p&gt;Creamos el script de arranque para iPXE &lt;strong&gt;bootconfig.ipxe&lt;/strong&gt; y lo abrimos con nuestro editor favorito:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nano bootconfig.ipxe
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Copiando el siguiente contenido:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!ipxe&lt;/span&gt;
dhcp
chain tftp://192.168.1.180/config/boot.ipxe
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Recordemos que la IP es la que hemos configurado como IP estática del servidor.&lt;/p&gt;

&lt;p&gt;Para compilar los firmwares de iPXE tanto para BIOS como para UEFI y relacionadrlo con el menú de arranque, ejecutamos el siguiente comando:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;make bin/ipxe.pxe bin/undionly.kpxe bin/undionly.kkpxe bin/undionly.kkkpxe bin-x86_64-efi/ipxe.efi EMBED=bootconfig.ipxe
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Esta tarea tomará varios minutos.&lt;/p&gt;
&lt;h2&gt;
  
  
  Copiando los firmwares ya compilados
&lt;/h2&gt;

&lt;p&gt;Una vez que los firmwares de iPXE estén compilados, los copiamos en &lt;code&gt;/pxeboot/firmware&lt;/code&gt; de nuestro servidor de arranque para que los equipos donde deseemos instalar los sistemas operativos puedan acceder vía TFTP.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo cp -v bin/{ipxe.pxe,undionly.kpxe,undionly.kkpxe,undionly.kkkpxe} bin-x86_64-efi/ipxe.efi /pxeboot/firmware/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Los archivos &lt;strong&gt;ipxe.pxe, undionly.kpxe, undionly.kkpxe, and undionly.kkkpxe&lt;/strong&gt; son para arranques BIOS, mientras que &lt;strong&gt;ipxe.efi&lt;/strong&gt; es para arranques UEFI.&lt;/p&gt;
&lt;h2&gt;
  
  
  Instalando y configurando DHCP y TFTP
&lt;/h2&gt;

&lt;p&gt;Para que PXE arranque, necesitaremos un servidor DHCP y TFTP ejecutándose. En este caso, usaremos &lt;strong&gt;dnsmasq&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt install dnsmasq -y
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Crearemos un nuevo archivo de configuración para dnsmasq. Renombramos el original &lt;code&gt;/etc/dnsmasq.conf&lt;/code&gt; a &lt;code&gt;/etc/dnsmasq.conf.backup&lt;/code&gt; de la siguiente manera:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo mv -v /etc/dnsmasq.conf /etc/dnsmasq.conf.backup
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Creamos un archivo vacío:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo nano /etc/dnsmasq.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Y añadimos el siguiente contenido:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;interface&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;enp0s3
bind-interfaces
&lt;span class="nv"&gt;domain&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;glampinghub.local
dhcp-range&lt;span class="o"&gt;=&lt;/span&gt;192.168.1.181,192.168.1.190,255.255.255.0,12h
dhcp-option&lt;span class="o"&gt;=&lt;/span&gt;option:router,192.168.1.1
dhcp-option&lt;span class="o"&gt;=&lt;/span&gt;option:dns-server,1.1.1.1
dhcp-option&lt;span class="o"&gt;=&lt;/span&gt;option:dns-server,8.8.8.8
enable-tftp
tftp-root&lt;span class="o"&gt;=&lt;/span&gt;/pxeboot

&lt;span class="c"&gt;# boot config for BIOS systems&lt;/span&gt;
dhcp-match&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;set&lt;/span&gt;:bios-x86,option:client-arch,0
dhcp-boot&lt;span class="o"&gt;=&lt;/span&gt;tag:bios-x86,firmware/ipxe.pxe

&lt;span class="c"&gt;# boot config for UEFI systems&lt;/span&gt;
dhcp-match&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;set&lt;/span&gt;:efi-x86_64,option:client-arch,7
dhcp-match&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;set&lt;/span&gt;:efi-x86_64,option:client-arch,9
dhcp-boot&lt;span class="o"&gt;=&lt;/span&gt;tag:efi-x86_64,firmware/ipxe.efi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Para que los cambios tengan efecto, reiniciamos el servidor de &lt;strong&gt;dnsmasq&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo systemctl restart dnsmasq
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Para comprobar que el servicio está ejecutándose, podemos comprobarlo de la siguiente manera:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo systemctl status dnsmasq
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;● dnsmasq.service - dnsmasq - A lightweight DHCP and caching DNS server
     Loaded: loaded &lt;span class="o"&gt;(&lt;/span&gt;/lib/systemd/system/dnsmasq.service&lt;span class="p"&gt;;&lt;/span&gt; enabled&lt;span class="p"&gt;;&lt;/span&gt; vendor preset: enabled&lt;span class="o"&gt;)&lt;/span&gt;
     Active: active &lt;span class="o"&gt;(&lt;/span&gt;running&lt;span class="o"&gt;)&lt;/span&gt; since Mon 2022-11-07 07:53:18 UTC&lt;span class="p"&gt;;&lt;/span&gt; 3h 41min ago
    Process: 697 &lt;span class="nv"&gt;ExecStartPre&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/etc/init.d/dnsmasq checkconfig &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;code&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;exited, &lt;span class="nv"&gt;status&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0/SUCCESS&lt;span class="o"&gt;)&lt;/span&gt;
    Process: 743 &lt;span class="nv"&gt;ExecStart&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/etc/init.d/dnsmasq systemd-exec &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;code&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;exited, &lt;span class="nv"&gt;status&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0/SUCCESS&lt;span class="o"&gt;)&lt;/span&gt;
    Process: 768 &lt;span class="nv"&gt;ExecStartPost&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/etc/init.d/dnsmasq systemd-start-resolvconf &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;code&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;exited, &lt;span class="nv"&gt;status&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0/SUCCESS&lt;span class="o"&gt;)&lt;/span&gt;
   Main PID: 766 &lt;span class="o"&gt;(&lt;/span&gt;dnsmasq&lt;span class="o"&gt;)&lt;/span&gt;
      Tasks: 1 &lt;span class="o"&gt;(&lt;/span&gt;limit: 4576&lt;span class="o"&gt;)&lt;/span&gt;
     Memory: 3.5M
        CPU: 35ms
     CGroup: /system.slice/dnsmasq.service
             └─766 /usr/sbin/dnsmasq &lt;span class="nt"&gt;-x&lt;/span&gt; /run/dnsmasq/dnsmasq.pid &lt;span class="nt"&gt;-u&lt;/span&gt; dnsmasq &lt;span class="nt"&gt;-7&lt;/span&gt; /etc/dnsmasq.d,.dpkg-dist,.dpkg-old,.dpkg-new &lt;span class="nt"&gt;--local-service&lt;/span&gt; &lt;span class="nt"&gt;--trust-anchor&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;.,20326,8,2,e06d44b80b8f1d39a95c0b0d7c65d08458e880409bbc683457104237c7f8ec8d

nov 07 07:53:18 ubuntu2204pxe dnsmasq[766]: &lt;span class="nb"&gt;read&lt;/span&gt; /etc/hosts - 7 addresses
nov 07 07:53:18 ubuntu2204pxe systemd[1]: Started dnsmasq - A lightweight DHCP and caching DNS server.
nov 07 07:58:56 ubuntu2204pxe dnsmasq-dhcp[766]: DHCPDISCOVER&lt;span class="o"&gt;(&lt;/span&gt;enp0s3&lt;span class="o"&gt;)&lt;/span&gt; 08:00:27:37:b9:ec
nov 07 07:58:56 ubuntu2204pxe dnsmasq-dhcp[766]: DHCPOFFER&lt;span class="o"&gt;(&lt;/span&gt;enp0s3&lt;span class="o"&gt;)&lt;/span&gt; 192.168.1.123 08:00:27:37:b9:ec
nov 07 07:58:56 ubuntu2204pxe dnsmasq-dhcp[766]: DHCPDISCOVER&lt;span class="o"&gt;(&lt;/span&gt;enp0s3&lt;span class="o"&gt;)&lt;/span&gt; 08:00:27:37:b9:ec
nov 07 07:58:56 ubuntu2204pxe dnsmasq-dhcp[766]: DHCPOFFER&lt;span class="o"&gt;(&lt;/span&gt;enp0s3&lt;span class="o"&gt;)&lt;/span&gt; 192.168.1.123 08:00:27:37:b9:ec
nov 07 07:59:14 ubuntu2204pxe dnsmasq-dhcp[766]: DHCPDISCOVER&lt;span class="o"&gt;(&lt;/span&gt;enp0s3&lt;span class="o"&gt;)&lt;/span&gt; 08:00:27:37:b9:ec
nov 07 07:59:14 ubuntu2204pxe dnsmasq-dhcp[766]: DHCPOFFER&lt;span class="o"&gt;(&lt;/span&gt;enp0s3&lt;span class="o"&gt;)&lt;/span&gt; 192.168.1.123 08:00:27:37:b9:ec
nov 07 07:59:15 ubuntu2204pxe dnsmasq-dhcp[766]: DHCPDISCOVER&lt;span class="o"&gt;(&lt;/span&gt;enp0s3&lt;span class="o"&gt;)&lt;/span&gt; 08:00:27:37:b9:ec
nov 07 07:59:15 ubuntu2204pxe dnsmasq-dhcp[766]: DHCPOFFER&lt;span class="o"&gt;(&lt;/span&gt;enp0s3&lt;span class="o"&gt;)&lt;/span&gt; 192.168.1.123 08:00:27:37:b9:ec
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Instalando y configurando el servidor NFS
&lt;/h2&gt;

&lt;p&gt;Ubuntu 22.04 usa &lt;strong&gt;casper&lt;/strong&gt; para arrancar la instalación modo "live". &lt;strong&gt;casper&lt;/strong&gt; soporta arranque PXE solo a través del protocolo &lt;strong&gt;NFS&lt;/strong&gt;. Por ello, para arrancar Ubuntu Desktop 22.04 a través de PXE, necesitaremos un servidor NFS que sea accesible por toda la red local.&lt;/p&gt;

&lt;p&gt;Para instalar NFS en el servidor, ejecutamos:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt install nfs-kernel-server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Abrimos el archivo de configuración de NFS &lt;code&gt;/etc/exports&lt;/code&gt; de la siguiente manera:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo nano /etc/exports
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Y añadimos la siguiente línea al final:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/pxeboot           *(ro,sync,no_wdelay,insecure_locks,no_root_squash,insecure,no_subtree_check)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Para efectuar los cambios y compartir la nueva configuración para que sea visible, ejecuta:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo exportfs -av
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Obteniendo el siguiente resultado por pantalla:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;user@serverpxe:$ sudo exportfs -av
*:/pxeboot
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Configurando iPXE
&lt;/h2&gt;


⚠️ La imagen ISO que descargaremos será de servidor, convirtiéndola en una versión de escritorio a través del autoinstalador de cloud-init como veremos en el último paso.


&lt;p&gt;Descargamos la imagen de Ubuntu Server 22.04 en nuestro directorio de &lt;code&gt;/home/$USER&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;wget https://releases.ubuntu.com/jammy/ubuntu-22.04.4-live-server-amd64.iso
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Una vez descargado, montamos la imagen en el directorio &lt;code&gt;/mnt&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo mount -o loop ubuntu-22.04.4-live-server-amd64.iso /mnt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Creamos un directorio dedicado a Ubuntu 22.04 en &lt;code&gt;/pxeboot/images/&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo mkdir -pv /pxeboot/images/ubuntu-22.04
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Para copiar los contenidos de la ISO, ejecutamos rsync de la siguiente manera:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo rsync -avz /mnt/ /pxeboot/images/ubuntu-22.04
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Desmontamos la imagen de Ubuntu 22.04 LTS de '/mnt':&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo umount /mnt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Creamos el archivo de configuración &lt;code&gt;/pxeboot/config/boot.ipxe&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo nano /pxeboot/config/boot.ipxe
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Y añadimos lo siguiente:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!ipxe&lt;/span&gt;

&lt;span class="nb"&gt;set &lt;/span&gt;server_ip  192.168.1.180
&lt;span class="nb"&gt;set &lt;/span&gt;root_path  /pxeboot

menu Select an OS to boot
item ubuntu-22.04         Install Ubuntu 22.04 LTS
choose &lt;span class="nt"&gt;--default&lt;/span&gt; &lt;span class="nb"&gt;exit&lt;/span&gt; &lt;span class="nt"&gt;--timeout&lt;/span&gt; 10000 option &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; goto &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;option&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;
:ubuntu-22.04

&lt;span class="nb"&gt;set &lt;/span&gt;os_root ubuntu-22.04
kernel tftp://&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;server_ip&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;/images/&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;os_root&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;/casper/vmlinuz
initrd tftp://&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;server_ip&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;/images/&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;os_root&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;/casper/initrd
imgargs vmlinuz &lt;span class="nv"&gt;initrd&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;initrd &lt;span class="nv"&gt;boot&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;casper &lt;span class="nv"&gt;netboot&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;nfs &lt;span class="nv"&gt;ip&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;dhcp &lt;span class="nv"&gt;nfsroot&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;server_ip&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;:&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;root_path&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;/images/&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;os_root&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nv"&gt;ds&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;nocloud&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="nv"&gt;s&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/cdrom/nocloud/ autoinstall quiet splash &lt;span class="nt"&gt;---&lt;/span&gt;
boot
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;El ejemplo de arriba es si montamos una sola imagen en el servidor. En el caso de que tengamos dos, por ejemplo Ubuntu 22.04 y Ubuntu 20.04, tendríamos un archivo similar a esto repitiendo los procesos de descarga, creación y montaje descritos arriba:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!ipxe&lt;/span&gt;

&lt;span class="nb"&gt;set &lt;/span&gt;server_ip  192.168.1.180
&lt;span class="nb"&gt;set &lt;/span&gt;root_path  /pxeboot

menu Select an OS to boot
item ubuntu-20.04         Install Ubuntu 20.04 LTS
item ubuntu-22.04         Install Ubuntu 22.04 LTS
choose &lt;span class="nt"&gt;--default&lt;/span&gt; ubuntu-20.04 &lt;span class="nt"&gt;--timeout&lt;/span&gt; 10000 option &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; goto &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;option&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;

:ubuntu-22.04
&lt;span class="nb"&gt;set &lt;/span&gt;os_root ubuntu-22.04
kernel tftp://&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;server_ip&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;/images/&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;os_root&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;/casper/vmlinuz
initrd tftp://&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;server_ip&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;/images/&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;os_root&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;/casper/initrd
imgargs vmlinuz &lt;span class="nv"&gt;initrd&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;initrd &lt;span class="nv"&gt;boot&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;casper maybe-ubiquity &lt;span class="nv"&gt;netboot&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;nfs &lt;span class="nv"&gt;ip&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;dhcp &lt;span class="nv"&gt;nfsroot&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;server_ip&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;:&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;root_path&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;/images/&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;os_root&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nv"&gt;ds&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;nocloud&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="nv"&gt;s&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/cdrom/nocloud/ autoinstall quiet splash &lt;span class="nt"&gt;---&lt;/span&gt;
boot

:ubuntu-20.04
&lt;span class="nb"&gt;set &lt;/span&gt;os_root ubuntu-20.04
kernel tftp://&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;server_ip&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;/images/&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;os_root&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;/casper/vmlinuz
initrd tftp://&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;server_ip&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;/images/&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;os_root&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;/casper/initrd
imgargs vmlinuz &lt;span class="nv"&gt;initrd&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;initrd &lt;span class="nv"&gt;boot&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;casper maybe-ubiquity &lt;span class="nv"&gt;netboot&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;nfs &lt;span class="nv"&gt;ip&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;dhcp &lt;span class="nv"&gt;nfsroot&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;server_ip&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;:&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;root_path&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;/images/&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;os_root&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nv"&gt;ds&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;nocloud&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="nv"&gt;s&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/cdrom/nocloud/ autoinstall quiet splash &lt;span class="nt"&gt;---&lt;/span&gt;
boot
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Por comentar el menú de arriba, el parámetro &lt;code&gt;ds=nocloud;s=/cdrom/nocloud/&lt;/code&gt; captará la configuración de cloud-init y &lt;code&gt;autoinstall&lt;/code&gt; comenzará automáticamente la instalación. Eliminar este último es útil para cuando tenemos equipos que no descartan por defecto seguir eligiendo el arranque por red tras la instalación, entrando así en un bucle de instalaciones que no terminaría nunca. Si estamos con otra cosa y en un equipo ya está instalado y reiniciado, quitando &lt;code&gt;autoinstall&lt;/code&gt; nos encontraremos con una pregunta sobre proceder con la instalación y la necesidad de pulsar "Yes" o "No". &lt;/p&gt;
&lt;h2&gt;
  
  
  Autoinstall con cloud-init
&lt;/h2&gt;

&lt;p&gt;Hasta ahora, hemos instalado una versión fresca de Ubuntu tal como vienen en las ISO. ¿Y si queremos hacer una instalación personalizada? Como introducción a este tema, &lt;a href="https://cloud-init.io/" rel="noopener noreferrer"&gt;cloud-init&lt;/a&gt; es un proyecto de Canonical, empresa responsable de Ubuntu, para hacer esas plantillas automatizadas. Es multiplataforma, por lo que funciona también con distribuciones como Fedora o Arch Linux.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd /pxeboot/images
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Accedemos, en este caso, a la imagen creada de Ubuntu 20.04:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd ubuntu-20.04
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;y creamos la carpeta &lt;code&gt;nocloud&lt;/code&gt; dentro de ella:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo mkdir nocloud &amp;amp;&amp;amp; cd nocloud
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Creando dos archivos nuevos:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo touch meta-data
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;meta-data se quedará así vacío, quedando el que nos interesa:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo nano user-data
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;En este archivo, copiaremos el contenido de este gist de GitHub donde podemos observar algunas personalizaciones:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Instalación de software concreto.&lt;/li&gt;
&lt;li&gt;Nombre del host.&lt;/li&gt;
&lt;li&gt;Creación de perfiles concretos con una configuración especial, tal la creación del archivo de claves públicas o la clave.&lt;/li&gt;
&lt;li&gt;Sección interactiva, para añadir aquella que queramos desarrollar manualmente durante la instalación. &lt;/li&gt;
&lt;li&gt;¡y un largo etcétera! Te animo a que leas la &lt;a href="https://cloudinit.readthedocs.io/en/latest/topics/examples.html" rel="noopener noreferrer"&gt;documentación sobre cloud-init&lt;/a&gt; al respecto.&lt;/li&gt;
&lt;/ul&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;El archivo, al estar escrito en formato YAML, es fácilmente legible comprendiendo cada caso. Por ejemplo, que al final de todo el proceso haga una actualización general de los repositorios y cuando arranquemos, tengamos una distribución flamante.&lt;/p&gt;

&lt;h2&gt;
  
  
  Arrancando Ubuntu 22.04
&lt;/h2&gt;

&lt;p&gt;Hecho todo lo anterior, arranca cualquier equipo con la opción por red y este detectará el servidor de arranque PXE presente en la red local.&lt;/p&gt;

&lt;p&gt;¿Te ha sido difícil? Con este servidor configurado y con algunas pruebas previas, tienes un sistema de automatización para instalar imágenes en otros equipos muy interesante con el fin de no olvidar ningún detalle. ¡Ya puedes guardar la "checklist" en el cajón y anota todo en el cloud-init!&lt;/p&gt;

</description>
      <category>devops</category>
      <category>beginners</category>
    </item>
    <item>
      <title>El archivo de configuración SSH es una navaja suiza</title>
      <dc:creator>Daniel M.</dc:creator>
      <pubDate>Fri, 25 Feb 2022 15:12:51 +0000</pubDate>
      <link>https://forem.com/daniconil/el-archivo-de-configuracion-ssh-es-una-navaja-suiza-3d21</link>
      <guid>https://forem.com/daniconil/el-archivo-de-configuracion-ssh-es-una-navaja-suiza-3d21</guid>
      <description>&lt;p&gt;El archivo &lt;code&gt;config&lt;/code&gt; de ssh permite automatizar el modo de acceso a servidores remotos. Probablemente, accedas a un VPS por un puerto distinto, a otra instancia quieras ir directamente a un directorio distinto o cualquier otra excepción a un acceso estándar sin necesidad de escribir toda la cadena de parámetros.&lt;/p&gt;

&lt;p&gt;Por ejemplo, imaginamos que tenemos un servidor en VirtualBox donde tenemos instalado &lt;strong&gt;Apache&lt;/strong&gt; y &lt;strong&gt;openssh-server&lt;/strong&gt; con:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;un puerto distinto al establecido por defecto, es decir, diferente al puerto 22,&lt;/li&gt;
&lt;li&gt;un usuario distinto al del sistema local. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;En él, hemos creado el usuario &lt;code&gt;administracion&lt;/code&gt; y queremos acceder vía SSH de manera rápida. ¿Cuál es la opción principal? Escribir&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ ssh -p 2220 administrador@[IP]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para, luego, teclear la contraseña y tener que acceder a la carpeta &lt;code&gt;/var/www/html&lt;/code&gt;. Esto lo podemos automatizar con la configuración ofrecida en la siguiente hoja de ruta:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Generar el par de claves público y privada como hemos detallado en &lt;a href="https://dev.to/daniconil/gestion-ordenada-de-claves-publica-y-privada-para-acceso-por-ssh-515o"&gt;otro tutorial&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Asegurarnos de que tenemos instalado &lt;strong&gt;openssh-server&lt;/strong&gt; en el servidor al que nos queremos conectar. Si no, simplemente teclear
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;code&gt;$ sudo apt install openssh-server&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;en el servidor remoto.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Crear un listado más de parámetros en el archivo config de nuestro equipo local ubicado en &lt;code&gt;~/.ssh/config&lt;/code&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    # Ubuntu Server 20.04 Virtualbox
    Host ubuntuserver
    Hostname 192.168.1.150
    User administracion
    Port 2220
    RequestTTY yes
    RemoteCommand cd /var/www/html; exec $SHELL
    PreferredAuthentications publickey
    IdentityFile ~/.ssh/privatekeys/ubuntuserver
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Por partes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Host ubuntuserver
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;nos permite poner nombre para el acceso directo, como veremos a continuación.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Hostname 192.168.1.150 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;es la IP del servidor. En nuestro caso, hemos configurado en el router que DHCP siempre ofrezca esa IP a la MAC de la tarjeta del servidor.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User administracion
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;para que acceda con ese usuario. Si no, tomará el nuestro por defecto del host.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Port 2220
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Por defecto, ssh intentará acceder al puerto 22. Si el puerto está modificado, hemos de añadir esta opción. En este caso, estaría configurado el 2220.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;RequestTTY yes
RemoteCommand cd /var/www/html; exec $SHELL
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;para que acceda directamente a la carpeta que queremos. La orden puede ser la que quieras, por ejemplo podemos hacer que actualice los repositorios indicando &lt;code&gt;sudo apt update&lt;/code&gt; en lugar de &lt;code&gt;cd /var/www/html/&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PreferredAuthentications publickey
IdentityFile ~/.ssh/privatekeys/ubuntuserver
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;para indicar que queremos que acceda por par de claves.&lt;/p&gt;

&lt;p&gt;Una vez hecho esto, desde nuestro equipo local accederemos con&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ssh ubuntuserver
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;al servidor remoto y directamente entraremos en&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;administracion@ubuntuserver:/var/www/html$

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Así, accederemos de manera automática a nuestro servidor y a la carpeta en la que trabajamos normalmente, con el $USER deseado y a través del puerto habilitado.&lt;/p&gt;

&lt;p&gt;Foto: "&lt;a href="https://www.flickr.com/photos/bg_dn/10479413433/"&gt;Old Railroad switching device&lt;/a&gt;" by begemot_dn is licensed under &lt;a href="https://creativecommons.org/licenses/by-nc/2.0/deed.es"&gt;CC BY-NC 2.0&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>config</category>
      <category>ssh</category>
      <category>sysadmin</category>
      <category>linux</category>
    </item>
    <item>
      <title>Instalación de DDEV y despliegue de proyecto Drupal 9 en Ubuntu 20.04</title>
      <dc:creator>Daniel M.</dc:creator>
      <pubDate>Fri, 03 Dec 2021 11:08:56 +0000</pubDate>
      <link>https://forem.com/daniconil/instalacion-de-ddev-y-despliegue-de-proyecto-drupal-9-en-ubuntu-2004-236</link>
      <guid>https://forem.com/daniconil/instalacion-de-ddev-y-despliegue-de-proyecto-drupal-9-en-ubuntu-2004-236</guid>
      <description>&lt;p&gt;Instalación de los componentes necesarios para ejecutar DDEV y crear entornos locales de trabajo de PHP. Docker y Docker Compose son requisitos imprescindibles y los instalaremos con la configuración mínima para que funcione DDEV.&lt;/p&gt;

&lt;p&gt;El índice de este tutorial es:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Instalación de Docker&lt;/li&gt;
&lt;li&gt;Instalación de Docker Compose&lt;/li&gt;
&lt;li&gt;Instalación de DDEV y la plantilla de Drupal 9&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  ¿Qué es DDEV?
&lt;/h2&gt;

&lt;p&gt;DDEV es una herramienta de código abierto que facilita la creación de entornos locales de desarrollo PHP. Al montar una instancia en tu servidor, existe la posibilidad de implementar marcos de trabajo de Drupal, WordPress, TYPO3, Backdrop, Magento, Laravel, etc. &lt;/p&gt;

&lt;p&gt;Un importante detalle de DDEV es su naturaleza de entorno local de desarrollo, es decir, no es visible en red. Para que sea accesible desde otro equipo, puedes usar &lt;a href="https://ngrok.com" rel="noopener noreferrer"&gt;ngrok&lt;/a&gt; para dotar de URL al entorno.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ddev.com" rel="noopener noreferrer"&gt;Web oficial de DDEV&lt;/a&gt;&lt;br&gt;
&lt;a href="https://ddev.readthedocs.io/en/stable/" rel="noopener noreferrer"&gt;Centro de documentación de DDEV&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  ¿Qué es Docker?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Funw4px2tl74kvzdjex2z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Funw4px2tl74kvzdjex2z.png" alt="Logo de Docker" width="739" height="190"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Docker es una plataforma que empaqueta software en unidades llamadas "contenedores" incluyendo los requisitos necesarios para ejecutar un proyecto determinado, como por ejemplo configurar una versión concreta de un servidor de base de datos, bibliotecas, java, etc, distinta a la del sistema operativo que lo contiene. Por eso el uso de la palabra "contenedor", porque encapsula dichos requisitos para un desarrollo óptimo de lo que se ejecute en él.&lt;/p&gt;

&lt;p&gt;Aunque esta definición de Docker se pueda asimilar a una virtualización, hay que tener en cuenta que la diferencia principal es el menor consumo de recursos en el uso de contenedores con respecto a máquinas virtuales debido a que, en el primer caso, no es necesario instalar un sistema operativo sobre otro tal como ocurre en las virtualizaciones.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.docker.com" rel="noopener noreferrer"&gt;Web oficial de Docker&lt;/a&gt;&lt;br&gt;
&lt;a href="https://docs.docker.com" rel="noopener noreferrer"&gt;Centro de documentación de Docker&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  ¿Qué es Docker Compose?
&lt;/h2&gt;

&lt;p&gt;Docker Compose es una herramienta para gestionar varios contenedores a través de un archivo de configuración YAML, permitiendo que, a través de un solo comando, se pueda poner en marcha o eliminar un contenedor.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.docker.com/compose" rel="noopener noreferrer"&gt;Documentación sobre Docker Compose&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;❤️ para &lt;a class="mentioned-user" href="https://dev.to/davidjguru"&gt;@davidjguru&lt;/a&gt; , &lt;a href="https://github.com/drud/ddev-contrib/pull/128" rel="noopener noreferrer"&gt;penyaskito&lt;/a&gt;, &lt;a href="https://www.digitalocean.com/community/tutorials/how-to-install-and-use-docker-compose-on-ubuntu-20-04" rel="noopener noreferrer"&gt;erikaheidi&lt;/a&gt; y &lt;a href="https://www.digitalocean.com/community/tutorials/how-to-install-and-use-docker-on-ubuntu-20-04" rel="noopener noreferrer"&gt;bhogan&lt;/a&gt;.&lt;/p&gt;


&lt;h2&gt;
  
  
  Instalación de Docker
&lt;/h2&gt;

&lt;p&gt;Actualizamos nuestro sistema para instalar los paquetes más recientes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ sudo apt update
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instalamos los requisitos necesarios:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ sudo apt install build-essential apt-transport-https ca-certificates software-properties-common curl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agregamos la clave GPG del repositorio oficial de Docker:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;y, tras el OK, agregamos el repositorio:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu focal stable"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;En caso de que no actualice repositorios automáticamente, ejecutamos de nuevo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ sudo apt update
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Con la actualización anterior, comprobamos que no hay ningún error e instalamos Docker desde el repositorio oficial, no desde los originales de Ubuntu:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ sudo apt install docker-ce
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Comprobamos si ha sido instalado y ejecutándose si ejecutamos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ sudo systemctl status docker
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;y obtenemos una salida similar a esta:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[sudo] password for daniel:   
● docker.service - Docker Application Container Engine  
     Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled)  
     Active: active (running)  since Fri 2021-08-27 19:27:56 CEST; 25min ago  
TriggeredBy: ● docker.socket  
       Docs: https://docs.docker.com  
   Main PID: 736 (dockerd)  
      Tasks: 11  
      Memory: 114.5M  
     CGroup: /system.slice/docker.service  
             └─736 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para el cometido de este tutorial sería suficiente, puedes investigar sobre los comandos de Docker ejecutando&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ docker
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;o accediendo a la &lt;a href="https://docs.docker.com/engine/reference/commandline/docker" rel="noopener noreferrer"&gt;documentación oficial dedicada&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Extra
&lt;/h2&gt;

&lt;p&gt;Si al arrancar Docker obtenemos el siguiente error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/  &amp;gt;docker.sock: Get http://%2Fvar%2Frun%2Fdocker.sock/v1.27/containers/json: dial unix /var/run/docker.&amp;gt;sock: connect: permission denied
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Otorgamos permisos al &lt;em&gt;user&lt;/em&gt; en el grupo &lt;em&gt;docker&lt;/em&gt; de la siguiente manera&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ sudo usermod -aG docker $USER &amp;amp;&amp;amp; sudo reboot
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;forzando a reiniciar para aplicar los cambios.&lt;/p&gt;

&lt;h2&gt;
  
  
  Instalación de Docker Compose
&lt;/h2&gt;

&lt;p&gt;Procedemos a la descarga y configuración de permisos para ejecutar Docker Compose.&lt;/p&gt;

&lt;h3&gt;
  
  
  Descarga del archivo
&lt;/h3&gt;

&lt;p&gt;A la hora de realizar este tutorial, la última versión corresponde a &lt;code&gt;2.1.1&lt;/code&gt;, comprueba cuál es la más reciente en el &lt;a href="https://github.com/docker/compose/releases" rel="noopener noreferrer"&gt;listado de lanzamientos en GitHub&lt;/a&gt;. Sólamente tendrías que cambiar el número. Las variables &lt;code&gt;$(uname -s)&lt;/code&gt; y &lt;code&gt;$(uname -m)&lt;/code&gt; eligen tu sistema y arquitectura (32 ó 64 bits), respectivamente.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ sudo curl -L "https://github.com/docker/compose/releases/download/v2.1.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Permisos
&lt;/h2&gt;

&lt;p&gt;Ajustamos los permisos para que sea ejecutable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ sudo chmod +x /usr/local/bin/docker-compose
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Comprobamos la instalación:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ docker-compose --version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Debemos tener un resultado similar a:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;docker-compose version 2.1.1&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Así, comprobamos que Docker Compose está correctamente instalado.&lt;/p&gt;

&lt;h2&gt;
  
  
  Instalación de DDEV y la plantilla de Drupal 9
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk5ml5hyujztr2n0v9ifj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk5ml5hyujztr2n0v9ifj.png" alt="Logos de DDEV y Drupal" width="800" height="330"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Dividimos en dos esta parte para mayor claridad.&lt;/p&gt;

&lt;h2&gt;
  
  
  Instalación de DDEV
&lt;/h2&gt;

&lt;p&gt;Descargamos el script con los comandos para descargar e instalar DDEV:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ curl -O https://raw.githubusercontent.com/drud/ddev/master/scripts/install_ddev.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;En el siguiente enlace podemos observar el &lt;a href="https://github.com/drud/ddev/blob/master/scripts/install_ddev.sh" rel="noopener noreferrer"&gt;contenido de este script&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Otorgamos permisos para que el script sea ejecutable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ chmod +x install_ddev.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;y ejecutamos con:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ ./install_ddev.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Durante el proceso, es posible que solicite instalar algunas dependencias o requisitos. Una vez finalizado, ejecuta el siguiente comando para comprobar que está correcto:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ ddev version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Obtenemos una salida similar a esta, dependiendo de las versiones y la arquitectura de nuestro sistema:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ITEM            VALUE                                                
 DDEV version    v1.18.1                                              
 architecture    amd64                                                
 db              drud/ddev-dbserver-mariadb-10.3:20211017_mysql_arm64 
 dba             phpmyadmin:5                                         
 ddev-ssh-agent  drud/ddev-ssh-agent:v1.18.0                          
 docker          20.10.11                                             
 docker-compose  v2.1.1                                               
 mutagen         0.12.0                                               
 os              linux                                                
 router          drud/ddev-router:v1.18.0                             
 web             drud/ddev-webserver:v1.18.1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A través de&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ ddev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;listamos los comandos de &lt;code&gt;ddev&lt;/code&gt;. Puedes visitar el &lt;a href="https://ddev.readthedocs.io/en/stable/users/cli-usage/#favorite-commands" rel="noopener noreferrer"&gt;centro de documentación&lt;/a&gt; para más detalles.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Nota: Hasta este punto, cualquier instalación con DDEV será igual, por lo que si queremos instalar otras plantillas como Magento, en lugar de Drupal, toda la tarea realizada hasta ahora no es necesario repetirla.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Instalación de la plantilla Drupal 9
&lt;/h2&gt;

&lt;p&gt;Creamos y accedemos a la carpeta donde albergaremos el proyecto:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ mkdir miproyecto &amp;amp;&amp;amp; cd miproyecto 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Dentro de la carpeta raíz, creamos la estructura de directorios de Drupal 9. Ambas opciones ofrecen el mismo resultado, sirviendo su observación para conocer mejor el funcionamiento de DDEV.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Opción 1&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Al escribir en el terminal&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ ddev config
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nos preguntará la ruta donde queremos guardarla y el tipo de plantilla. En este caso, elegiremos Drupal 9. Marco en negrita lo que he introducido. El resto es la salida de la instalación:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;daniel@ubuntuserver:~/miproyecto$ ddev config  
Creating a new ddev project config in the current directory (/home/daniel/miproyecto)  
Once completed, your configuration will be written to /home/daniel/miproyecto/.ddev/config.yaml  

Project name (miproyecto): Drupalea          

The docroot is the directory from which your site is served.  
This is a relative path from your project root at /home/daniel/miproyecto  
You may leave this value blank if your site files are in the project root   
Docroot Location (current directory):  [He dejado en blanco]   
Found a php codebase at /home/daniel/miproyecto.  
Project Type [backdrop, drupal6, drupal7, drupal8, drupal9, laravel, magento, magento2, php, shopware6, typo3, wordpress] (php): drupal9  
Ensuring write permissions for Drupalea  
No settings.php file exists, creating one  
Existing settings.php file includes settings.ddev.php  
Configuration complete. You may now run 'ddev start'.  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Devolviéndonos el terminal. Importante indicar que &lt;code&gt;Docroot location&lt;/code&gt; lo he dejado en blanco para que la estructura se cree, por defecto, en la carpeta raíz y no sea, por ejemplo, un subdirectorio.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Opción 2&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;De antemano, podemos incluir las dos opciones incluidas arriba a través de parámetros:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ ddev config --docroot=web --create-docroot --project-type=drupal9
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Obtenemos la siguiente salida:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Creating a new ddev project config in the current directory (/home/daniel/miproyecto)  
Once completed, your configuration will be written to /home/daniel/miproyecto/.ddev/config.yaml  

Created docroot at /home/daniel/miproyecto/web  
You have specified a project type of drupal9 but no project of that type is found in /home/daniel/miproyecto/web  
Ensuring write permissions for miproyecto   
No settings.php file exists, creating one  
Existing settings.php file includes settings.ddev.php  
Configuration complete. You may now run 'ddev start'.  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Por ahora, no es necesario ejecutar &lt;code&gt;ddev start&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Descarga de la plantilla Drupal 9 a través de Composer
&lt;/h3&gt;

&lt;p&gt;Una vez tenemos la estructura, y sin salirnos de la carpeta raíz, ejecutamos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ yes | ddev composer create drupal/recommended-project
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;El "yes" del inicio sirve para automatizar el paso en el que solicita si puede seguir para reescribir la estructura creada en el anterior paso. Al modificar parte del árbol de directorios creado con &lt;code&gt;ddev config&lt;/code&gt;, es normal que solicite permisos para seguir. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;Nota: No hay que confundir "Docker Compose", descrito en este tutorial, con "Composer", el administrador para proyectos PHP con el que instalaremos los paquetes de Drupal 9.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Instalamos &lt;strong&gt;Drush&lt;/strong&gt;, una aplicación basada en shell que se utiliza para controlar, manipular y administrar los sitios web de Drupal, además de otros módulos básicos para este CMS como admin_toolbar y devel que añadirán funcionalidades extra de navegación.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ ddev composer require drush/drush drupal/admin_toolbar drupal/devel
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Obteniendo una salida similar a esta:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Using version ^10.6 for drush/drush  
./composer.json has been created  
Running composer update drush/drush  
Loading composer repositories with package information  
Updating dependencies  
Lock file operations: 46 installs, 0 updates, 0 removals  
&amp;amp;nbsp;&amp;amp;nbsp;-Locking chi-teck/drupal-code-generator (1.33.1)  
 ...  
Writing lock file  
Installing dependencies from lock file (including require-dev)  
Package operations: 46 installs, 0 updates, 0 removals  
&amp;amp;nbsp;&amp;amp;nbsp;-Downloading ... Extracting archive  
&amp;amp;nbsp;&amp;amp;nbsp;-Installing ...: Extracting archive  
...  
12 package suggestions were added by new dependencies, use `composer suggest` to see details.  
Package container-interop/container-interop is abandoned, you should avoid using it. Use psr/container instead.  
Generating autoload files  
18 packages you are using are looking for funding.  
Use the `composer fund` command to find out more!  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Nota: Los puntos suspensivos representa la larga lista de paquetes que se van descargando e instalando automáticamente.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Sobre este tipo de instalación via línea de comandos, tienes más información en la &lt;a href="https://www.drupal.org/docs/develop/using-composer/using-composer-to-install-drupal-and-manage-dependencies" rel="noopener noreferrer"&gt;web oficial de Drupal&lt;/a&gt; dedicado a esta materia.&lt;/p&gt;

&lt;p&gt;Antes de lanzar la instancia, configuramos la base de datos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ ddev exec drush si --site-name=Drupaleame --account-name=admin --account-pass=password -y
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Como último paso antes de obtener una instancia de Drupal 9, lanzamos lo instalado:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ ddev start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Obteniendo una salida similar a:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Starting Drupalea... 
Building ddev-ssh-agent 
Recreating ddev-ssh-agent ...  
Recreating ddev-ssh-agent ... done 
ssh-agent container is running: If you want to add authentication to the ssh-agent container, run 'ddev auth ssh' to enable your keys. 
Running   Command=ip address show dev docker0
Building db 
Building web 
Creating ddev-Drupalea-db ...  
Creating ddev-Drupalea-db ... done 
Creating ddev-Drupalea-dba ...  
Creating ddev-Drupalea-web ...  
Creating ddev-Drupalea-web ... done 
Creating ddev-Drupalea-dba ... done 
Creating ddev-router ...  
Creating ddev-router ... done 
Ensuring write permissions for Drupalea 
Existing settings.php file includes settings.ddev.php 
Ensuring write permissions for Drupalea 
Successfully started Drupalea 
Project can be reached at https://drupalea.ddev.site https://127.0.0.1:49154 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Nota: El puerto puede ser diferente.&lt;/em&gt; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Opción 1, sistema con entorno gráfico&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;En caso de que el entorno local donde hayamos instalado &lt;code&gt;DDEV&lt;/code&gt; &lt;strong&gt;tenga escritorio tipo GNOME, KDE, XFCE, etc&lt;/strong&gt;, podemos ejecutar lo siguiente desde terminal para lanzar a nuestro navegador el configurador de Drupal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ ddev launch
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Opción 2, sistema sin entorno gráfico&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Si hemos instalado DDEV en un servidor sin escritorio y lanzamos &lt;code&gt;ddev launch&lt;/code&gt;, obtenemos el siguiente error&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/home/daniel/miproyecto/.ddev/commands/host/launch: line 61: xdg-open: command not found  
Failed to run launch ; error=exit status 127  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Como es lógico, al no tener entorno gráfico, xdg-open no se encuentra instalado en el sistema ni objetivo sobre el que ejecutar, que sería un navegador tipo Mozilla Firefox.&lt;/p&gt;

&lt;p&gt;En este caso, probamos el navegador &lt;strong&gt;lynx&lt;/strong&gt; de la siguiente manera:&lt;/p&gt;

&lt;p&gt;Instalamos el navegador desde repositorios de Ubuntu:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ sudo apt install lynx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;y probamos&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$lynx drupalea.ddev.site
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Veremos, en el terminal, el texto de una página de configuración de Drupal.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Welcome to Example-Drupal |Example-Drupal (p1 of 2)&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
   #alternate  &lt;/p&gt;

&lt;p&gt;   Skip to main content  &lt;/p&gt;

&lt;p&gt;User account menu  &lt;/p&gt;

&lt;p&gt;   Show — User account menu Hide — User account menu&lt;br&gt;&lt;br&gt;
     * Log in  &lt;/p&gt;

&lt;p&gt;   Home&lt;br&gt;&lt;br&gt;
   Drupaleame  &lt;/p&gt;

&lt;p&gt;Main navigation  &lt;/p&gt;

&lt;p&gt;   Show — Main navigation Hide — Main navigation&lt;br&gt;&lt;br&gt;
     * Home  &lt;/p&gt;

&lt;p&gt;Welcome to Drupaleame  &lt;/p&gt;

&lt;p&gt;   No front page content has been created yet.&lt;br&gt;&lt;br&gt;
   Follow the User Guide to start building your site.&lt;br&gt;&lt;br&gt;
   Subscribe to  &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A partir de ahora, con Docker, Docker Compose y DDEV ya presentes en nuestro equipo, podemos probar otras plantillas como WordPress o Magento a través de DDEV.&lt;/p&gt;




&lt;p&gt;Foto: &lt;a href="https://www.flickr.com/photos/60132504@N08/5939008153" rel="noopener noreferrer"&gt;Containers&lt;/a&gt; by tsuna72 is licensed with &lt;a href="https://creativecommons.org/licenses/by/2.0/" rel="noopener noreferrer"&gt;CC BY 2.0&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ddev</category>
      <category>drupal</category>
      <category>docker</category>
      <category>ubuntu</category>
    </item>
    <item>
      <title>Gestión ordenada de claves pública y privada para acceso por SSH</title>
      <dc:creator>Daniel M.</dc:creator>
      <pubDate>Fri, 03 Dec 2021 10:12:35 +0000</pubDate>
      <link>https://forem.com/daniconil/gestion-ordenada-de-claves-publica-y-privada-para-acceso-por-ssh-515o</link>
      <guid>https://forem.com/daniconil/gestion-ordenada-de-claves-publica-y-privada-para-acceso-por-ssh-515o</guid>
      <description>&lt;p&gt;¿Cómo crear y gestionar claves SSH de manera ordenada? (Versión GNU/Linux)&lt;/p&gt;

&lt;p&gt;Tras el anuncio en julio de 2020 en el que GitHub &lt;a href="https://github.blog/2020-07-30-token-authentication-requirements-for-api-and-git-operations/"&gt;anunciaba la desactivación del acceso&lt;/a&gt; a los repositorios mediante user/pass, la mejor opción y más segura es usar claves SSH. Esta forma de acceso y autenticación no es nueva, seguramente tengas más de una clave ya configurada con cifrado antiguo y guardadas de aquella manera. ¿Qué mejor momento que ordenarlas, eliminar las que no uses y actualizarlas? En este breve tutorial vamos a crear nuevas claves con cifrado ed22519 para 3 plataformas: GitLab, GitHub y Bitbucket.&lt;/p&gt;

&lt;p&gt;Renovación de pares de claves al cifrado ed25519 y ordenación para autenticación en múltiples plataformas.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Importante:&lt;/strong&gt;Importante: si no tienes ninguna clave creada, ve directamente al punto 2. El 1 está dedicado a mostrar cómo podemos tener de desordenado el acceso a servidores remotos mediante claves si ya se han creado anteriormente.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  1. Localizar las claves y mostrar el directorio
&lt;/h2&gt;

&lt;p&gt;Dentro de nuestra carpeta  /home/$USER, existen dos tipos de archivos, los que están sin ocultar que se visualizan con normalidad y los ocultos que tienen un punto delante. Para poder listar los segundos, debemos añadir la opción -a a la orden:&lt;/p&gt;

&lt;p&gt;Listado de archivos sin ocultar&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ls -l
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Listado de archivos sin ocultar y ocultos&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ls -la
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Si observamos entre las carpetas ocultas, tendremos .ssh que será en la que organizaremos las claves públicas y privadas.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ cd ~/.ssh &amp;amp;&amp;amp; ls -l
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Importante:&lt;/strong&gt; Este punto, como he comentado anteriormente, es orientativo, solo sirve para comprobar si tenemos claves sin usar y/o antiguas ya creadas.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Probablemente, tengas una estructura similar a esta&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;-rw-rw-r-- 1 [USER] [GROUP]  370 jul 28 2016 clavessh
-rw-rw-r-- 1 [USER] [GROUP]  370 jul 28 2016 clavessh.pub
-rw-rw-r-- 1 [USER] [GROUP]  378 jun 21 2018 clave1.pub
-rw-rw-r-- 1 [USER] [GROUP]  380 jun 21 2018 clave1
-rw-rw-r-- 1 [USER] [GROUP]  370 jul 28 17:37 claveprivada.pub
-rw------- 1 [USER] [GROUP] 5762 jul 28 17:38 known_hosts
-rw------- 1 [USER] [GROUP] 3770 jun 18 10:56 known_hosts.old
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Sabes que el par de claves &lt;strong&gt;clavessh&lt;/strong&gt; accede a algo pero no a qué, y mucho menos &lt;strong&gt;clave1&lt;/strong&gt;. Por otro lado, claveprivada.pub, que no tiene sentido, tiene perdida su parte privada. En definitiva, un lío que es mejor eliminar.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. La casa por la ventana y muebles nuevos, aplicamos algoritmo de cifrado ed22519
&lt;/h2&gt;

&lt;p&gt;Sin posibilidad de recordar qué tipo de cifrado tenemos (lo veremos posteriormente), es posible que se trate de &lt;strong&gt;RSA&lt;/strong&gt; con una longitud de bits entre 1024 y 2048. Introducido en la versión 6.5 (2014) de OpenSSH, &lt;strong&gt;ed22519&lt;/strong&gt; presenta mejor robustez y, además, está recomendado por plataformas como GitLab.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.gitlab.com/ee/ssh/index.html"&gt;GitLab and SSH keys&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  2.1 Eliminamos los archivos que tenemos desperdigados en la carpeta .ssh
&lt;/h3&gt;

&lt;p&gt;Procedemos a identificar qué archivos son. Presumiblemente, los que tienen la extensión .pub son la par pública y los que no tienen extensión, la privada. Recuerda que hemos de estar en la carpeta oculta .ssh tal como hicimos en el primer comando, es decir&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ cd ~/.ssh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Realizamos la siguiente operación en uno de los archivos arriba expuestos&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ cat clavessh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;mostrando lo siguiente&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;-----BEGIN OPENSSH PRIVATE KEY-----
[Filas de caracteres aleatorios]
-----END OPENSSH PRIVATE KEY-----
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Nos aseguramos de que este archivo sí es una clave privada. Si realizamos&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ cat ~/.ssh/clavessh.pub
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;nos muestra una información con la siguiente estructura&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ssh-rsa [caracteres aleatorios] -C [e-mail]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Ya hemos descubierto que se trata de un algoritmo RSA. Visto esto, e identificando cuáles son los archivos de claves, los eliminaremos y crearemos nuevos con el siguiente comando&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ rm clavessh* clave1 claveprivada*
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;o bien, teniendo en cuenta que todos empiezan por la cadena "clave"&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ rm clave*
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2.2 Crear carpetas para las claves privadas y públicas
&lt;/h3&gt;

&lt;p&gt;Con el objetivo de tener las claves ordenadas, creamos dos carpetas dentro de .ssh&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ mkdir clavesprivadas
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;y&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ mkdir clavespublicas
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  3. Creación de claves
&lt;/h2&gt;

&lt;p&gt;Si nos hemos movido, volvemos a la carpeta .ssh&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ cd ~/.ssh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Generamos las claves con&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ ssh-keygen -t ed25519 -C "[inserta tu e-mail]"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Y obtenemos lo siguiente.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Generating public/private ed25519 key pair.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;En la siguiente pregunta, escribe, por ejemplo, la plataforma en la que vas a usar esta clave. En este caso, he indicado &lt;code&gt;gitlab&lt;/code&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Enter file in which to save the key (/home/[USER]/.ssh/id_ed25519): gitlab
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Puedes incluir, o no, una capa extra que sería la contraseña:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Ya tenemos los datos guardados en la carpeta .ssh, dos archivos llamados gitlab (clave privada) y gitlab.pub (clave pública)&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Your identification has been saved in gitlab
Your public key has been saved in gitlab.pub
The key fingerprint is:
SHA256:[Códigos aleatorios] [el e-mail que incluiste]
The key's randomart image is:
+--[ED25519 256]--+
|            * *O=|
|         E + *=**|
|        . = .E==*|
|         + . ..+*|
|        s o   .o*|
|       . o + .  *|
|        . . = o.+|
|             = +o|
|              =++|
+----[SHA256]-----+
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Si listamos la carpeta .ssh, nos encontramos con los dos archivos recientemente creados y las carpetas donde guardaremos las claves&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ ls -l ~/.ssh
total 24
-rw-rw-r-- 1 [USER] [GROUP]  411 jul 29 12:00 gitlab
-rw-rw-r-- 1 [USER] [GROUP]   99 jul 29 12:00 gitlab.pub
-rw------- 1 [USER] [GROUP] 5762 jul 28 17:38 known_hosts
-rw------- 1 [USER] [GROUP] 3770 jun 18 10:56 known_hosts.old
drwxrwxr-x 2 [USER] [GROUP] 4096 jul 29 11:55 clavesprivadas
drwxrwxr-x 2 [USER] [GROUP] 4096 jul 29 11:55 clavespublicas
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;De la misma manera, podemos crear nuevas claves para cualquier plataforma. Como recordatorio, no es obligatorio poner el nombre de la plataforma, pero así quedaría mejor organizado.&lt;/p&gt;

&lt;h3&gt;
  
  
  3.1 Agregar clave ssh al ssh-agent
&lt;/h3&gt;

&lt;p&gt;Iniciamos el agente ssh en un segundo plano&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ eval "$(ssh-agent -s)"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Arrojando un PID (Process ID) garantizando que ha sido arrancado correctamente&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Agent pid XXXXX
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Siendo XXXXX un número diferente cada vez. Agregamos la clave privada al agente SSH&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ ssh-add ~/.ssh/gitlab
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Repetimos este último paso de agregar la clave privada con el resto que hayamos creado.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Guardado de claves
&lt;/h2&gt;

&lt;p&gt;Simplemente, se trata de mover cada clave a su carpeta&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ mv gitlab clavesprivadas/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;y&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ mv gitlab.pub clavespublicas/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Si hemos creado otras claves, realizamos el mismo proceso modificando el nombre del archivo en la orden de arriba.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Copia de clave pública en plataformas
&lt;/h2&gt;

&lt;p&gt;Para que GitLab, en este caso, nos reconozca la clave, hay que agregar la clave en la sección correspondiente. Como primer paso, hay que acceder a la carpeta donde está almacenada&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ cd clavespublicas
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;vemos el contenido&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ cat gitlab.pub
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nos aparecerá una línea similar a esta&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ssh-rsa [caracteres aleatorios] [e-mail]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Seleccionamos la línea completa y copiamos su contenido.&lt;/p&gt;

&lt;h3&gt;
  
  
  5.1 Registro en plataforma
&lt;/h3&gt;

&lt;p&gt;Siguiendo con el ejemplo de GitLab, seguimos los pasos para llegar al lugar donde se registran tras acceder a nuestro perfil&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;(Opción 1) &lt;a href="https://gitlab.com/-/profile/keys"&gt;Acceso directo a la sección Claves SSH de Preferencias&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;(Opción 2) Esquina superior derecha &lt;strong&gt;Preferences&lt;/strong&gt; -&amp;gt; Columna izquierda &lt;strong&gt;Claves SSH&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Una vez dentro&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;En "Clave", copiamos el contenido de nuestra clave pública. Asegúrate que empieza por &lt;code&gt;ssh-ed25519&lt;/code&gt; y que termine con el correo electrónico que anotamos cuando la creamos.&lt;/li&gt;
&lt;li&gt;En el cajón "Título", elige una definición descriptiva. Por ejemplo, el equipo que usa esa clave.&lt;/li&gt;
&lt;li&gt;Como medida opcional de seguridad, puedes agregar una fecha de caducidad.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Ya tendríamos la clave registrada. La siguiente tarea consistirá en probar que funciona. Vamos al terminal y, dentro de la subcarpeta clavesprivadas de .ssh, escribimos&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ ssh -T -i gitlab git@gitlab.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Y obtendrías el siguiente mensaje en caso de haber configurado correctamente la clave SSH&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Welcome to GitLab, @[GitLab_User]!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Si quieres ver cómo funciona el test de conexión o mirar qué puede haber fallado (ruta mal escrita, archivo desubicado,...), puedes probar añadiendo el parámetro -v de "verbose"&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ ssh -T -v -i gitlab git@gitlab.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tras mostrar por pantalla las conexiones establecidas, las 4 últimas líneas serían&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Welcome to GitLab, @[GitLab_User]!
debug1: channel 0: free: client-session, nchannels 1
Transferred: sent 2084, received 2400 bytes, in 0.6 seconds
Bytes per second: sent 3568.5, received 4109.6
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  6. Creación del archivo config de SSH
&lt;/h2&gt;

&lt;p&gt;Una vez guardadas las claves en carpetas, creamos el archivo de configuración que servirá para dos objetivos básicos: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Identificar las claves con la plataforma en donde las estamos usando.&lt;/li&gt;
&lt;li&gt;Crear un índice para identificar las que no estamos usando y, por seguridad, podemos borrar.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Para crear el archivo, debemos llamarlo "config" y ubicarlo dentro de la carpeta .ssh. Con el comando &lt;code&gt;nano&lt;/code&gt; creamos y abrimos directamente el nuevo archivo:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ nano ~/.ssh/config
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Una vez que nos encontramos con el archivo recién creado, identificamos cada clave de la siguiente manera:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Texto informativo que identifique cada plataforma
Host ejemplo.ltd
HostName ejemplo.ltf
PreferredAuthentications publickey
IdentityFile ~/.ssh/clavesprivadas/claveprivada
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Aplicando el ejemplo de GitLab, quedaría así:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# GitLab
Host gitlab.com
HostName gitlab.com
PreferredAuthentications publickey
IdentityFile ~/.ssh/clavesprivadas/gitlab
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Podemos crear en el mismo archivo, manteniendo la misma estructura, todas las claves privadas. A continuación, un supuesto caso de que tuviésemos las claves en GitLab, GitHub y Bitbucket:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# GitHub
Host github.com
HostName github.com
PreferredAuthentications publickey
IdentityFile ~/.ssh/clavesprivadas/github

# GitLab
Host gitlab.com
HostName gitlab.com
PreferredAuthentications publickey
IdentityFile ~/.ssh/clavesprivadas/gitlab

# Bitbucket
Host bitbucket.org
HostName bitbucket.org
PreferredAuthentications publickey
IdentityFile ~/.ssh/clavesprivadas/bitbucket
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Si queremos probar la conexión, copiamos el siguiente comando en el caso de GitLab.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ ssh -T -v -i gitlab git@gitlab.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Teniendo en cuenta que hemos añadido la opción &lt;em&gt;verbose&lt;/em&gt; con &lt;code&gt;-v&lt;/code&gt;, podemos observar que entre las líneas de respuesta encontramos un fragmento similar a este:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;debug1: Trying private key: /home/[USER]/.ssh/clavesprivadas/gitlab
debug1: Authentication succeeded (publickey).
Authenticated to gitlab.com ([IP]:[PUERTO (normalmente, 22)]).
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Con este resultado, comprobamos que la conexión de la clave privada con nuestro repositorio es exitosa.&lt;/p&gt;




&lt;h2&gt;
  
  
  Extra
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Actualizar URI de repositorio de https a SSH
&lt;/h3&gt;

&lt;p&gt;¿Qué ocurre si ya teníamos un repositorio que se identificase a través de https y lo que queremos es a través de las claves? Probablemente, una vez configuradas las claves, hayas intentado realizar un commit y siga solicitando user/pass. Para ello, debemos realizar, dentro de la carpeta del repositorio, el siguiente comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ git remote set-url git@gitlab.com:USERNAME/REPOSITORY.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Más información en &lt;a href="https://devconnected.com/how-to-change-git-remote-origin/"&gt;&lt;em&gt;How to change Git Remote Origin&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Protección extra de la carpeta de claves privadas
&lt;/h3&gt;

&lt;p&gt;Si realizamos un listado de la carpeta con el siguiente comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ ls ~/.ssh/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Obtenemos un resultado similar:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;total 24
-rw------- 1 [USER] [GROUP] 5762 jul 28 17:38 known_hosts
-rw------- 1 [USER] [GROUP] 3770 jun 18 10:56 known_hosts.old
drwxrwxr-x 2 [USER] [GROUP] 4096 jul 29 11:55 clavesprivadas
drwxrwxr-x 2 [USER] [GROUP] 4096 jul 29 11:55 clavespublicas
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Normalmente, los archivos tienen permisos 644, es decir:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;6 como permisos de lectura y escritura con nuestro propio &lt;em&gt;user&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;4 como permisos de lectura para quienes estén en el mismo grupo asociado.&lt;/li&gt;
&lt;li&gt;4 como permisos de lectura para otras personas que estén en nuestro sistema.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Y los directorios, 755. Para profundizar en este tema, recomiendo este enlace de &lt;em&gt;atareao&lt;/em&gt; &lt;a href="https://atareao.es/tutorial/terminal/propietarios-y-permisos/"&gt;Propietarios y permisos&lt;/a&gt;.  &lt;/p&gt;

&lt;p&gt;¿Qué podemos hacer al respecto? Cambiar los permisos a 600 para que nadie puede acceder ni leer los archivos de las claves privadas si no es con nuestro propio &lt;em&gt;user&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ chmod 700 ~/.ssh/clavesprivadas
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Así, si volvemos a hacer &lt;code&gt;ls -l&lt;/code&gt; obtenemos el mismo listado pero con una ligera diferencia:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;total 24
-rw------- 1 [USER] [GROUP] 5762 jul 28 17:38 known_hosts
-rw------- 1 [USER] [GROUP] 3770 jun 18 10:56 known_hosts.old
drwx------ 2 [USER] [GROUP] 4096 jul 29 11:55 clavesprivadas
drwxrwxr-x 2 [USER] [GROUP] 4096 jul 29 11:55 clavespublicas
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;En la línea del directorio &lt;strong&gt;clavesprivadas&lt;/strong&gt; han desaparecido los permisos para el mismo grupo y "otros". De esta manera, una persona que no sea yo no tiene acceso ni permisos de lectura de una carpeta con un contenido tan sensible como es la que contiene nuestras claves privadas.&lt;/p&gt;

&lt;p&gt;Foto: "&lt;a href="https://search.creativecommons.org/photos/07a7f9fe-3b41-424c-990a-3499bd07a792"&gt;Engranaje&lt;/a&gt;" por J4R está licenciada con &lt;a href="https://creativecommons.org/licenses/by-sa/2.0/"&gt;CC BY-SA 2.0&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ssh</category>
      <category>linux</category>
      <category>productividad</category>
      <category>buenaspracticas</category>
    </item>
  </channel>
</rss>
