Reminders...

Usando TCP puro – nc

Carreta

TCP (Transmission Control Protocol) es el protocolo de transporte sobre el que se construye la mayor parte de internet — HTTP, SMTP, SSH, y prácticamente cualquier comunicación en red. Garantiza que los datos lleguen completos y en orden entre dos puntos.

nc (netcat) es una herramienta de línea de comandos que abre conexiones TCP de forma directa, sin protocolo propio encima. Me parece que puede ser muy útil para hacer backups sin usar practicamente nada de recursos de hardware, para no depender prácticamente nada de dependencias externas y para simplificar brutalmente la depuración.

Creo que esta herramienta es muy útil, sobre todo usando IPv6, donde cada dispositivo dispone de una dirección pública real y las conexiones entre dos puntos pueden establecerse de forma completamente directa, sin servidores intermediarios ni técnicas para atravesar NAT.

Chateando

Establecer una conexión usando nc es extremadamente fácil.

En un computador hay que abrir un puerto que escuche:

nc -l -6 1234

Y en el otro hay que conectarse a la IPv6 de esa computadora y el puerto:

nc 2607:f8b0:4004:c09::64 1234

¡Listo! Solo con eso se establece la conexion y se podrán emitir mensajes por los dos lados.

Enviando bits

nc envía bytes crudos, por lo cual es posible enviar cualquier stream de bytes.

Este ejemplo muestra como se podría enviar una imágen:

Receptor

nc -l 1234 > imagen.jpg

emisor

nc 2607:f8b0:4004:c09::64 1234 < imagen.jpg

Pbcopy/Pbpaste Portapapeles de terminal en Macos

Descripción

Macos tiene dos comandos para controlar el portapapeles en la terminal pbcopy y pbpaste. Ambos leen el std-in/out para copiar y pegar

Ejemplos

Copiar al portapapeles:

echo "portapapeles" | pbcopy

Copiar en multilínea usando heredoc:

cat <<EOF | pbcopy
linea#1
linea#1
EOF

Pegar del portapapeles:


pbpaste > salida.txt
```Como

Usar IPv6 sobre IPv4

Hasta el día de hoy siempre he preferido usar IPv4 sobre IPv6 para conectarme a mi servidor por SSH, compartir carpetas por SSHFS o direccionar servidores web. Sin embargo hoy me doy cuenta de que usar IPv6 genera ventajas de rendimiento que son claramente visibles sobretodo para entornos interactivos como SSH.

La razón principal es que IPv6 elimina la necesidad de NAT (Network Address Translation). Con IPv4, en la mayoría de los entornos domésticos y corporativos, el tráfico debe atravesar una o varias capas de traducción de direcciones antes de llegar a su destino. Cada salto a través de un dispositivo NAT introduce una pequeña latencia adicional y, en el caso de SSH, donde cada pulsación de tecla genera un paquete independiente, esas fracciones de milisegundo se acumulan y se perciben como una leve pero molesta lentitud en la respuesta del terminal.

Con IPv6, en cambio, el cliente se conecta directamente al servidor mediante una dirección global única, sin intermediarios que reescriban cabeceras ni mantengan tablas de estado. El resultado es una comunicación extremo a extremo más limpia, con menor latencia y sin los problemas de traversal que a veces afectan a protocolos como SSHFS cuando el túnel debe negociar con firewalls con estado o routers que hacen NAT de forma agresiva.

Dicho esto, ahora mismo voy a reconfigurar los dominios de mis sitios web con registros AAAA que utilizan IPv6, eliminando por completo el soporte de IPv4.

Best Way to Delete Folders

Personally, I think the best way to delete folders is using this command:

rm -rfv folder

Encriptar con OpenSSL

Introducción

Personalmente creo que la mejor manera de tener los archivos seguros es encriptándolos con OpenSSL. En vez de comprimir un archivo zip o rar con contraseña o encriptar un documento PDF, resulta más seguro y fiable encriptar usando OpenSSL usando la doble extensión ".extension.aes".

Las ventajas de hacer esto son la claridad que se tiene de qué método de encriptación se está usando y cómo, poder definir parámetros con gran grado de personalización y una garantía de compatibilidad futura.

A tener en cuenta....

Al menos en mi caso particular, uso la encriptación para backups y copias de archivo, por lo cual me interesa tener al máximo la garantía de que el archivo va a ser legible ahora o en cuarenta años. Por eso es importante tener en cuenta las siguientes sugerencias:

  • ReadMe: El archivo debe estar acompañado de un readme que especifique cuál es el comando que debe usarse para desencriptarlo, la versión de openssl y los métodos usados.
  • Usar un algoritmo de encriptación estandar: Si bien openssl permite usar muchísimos métodos de encriptación lo mejor es usar el estandar, así hay más garantía de que permanecerá y tendrá soporte dirante mayor tiempo.
  • Especificar el método de derivación: Si el digest no es especificado, OpenSSL isará el predeterminado que los desarrolladores pongan. Un ejemplo que miestra que esto es importante es el que en las versiones antiguas se usaba MD5 y ahora se usa SHA-256.

Comandos

Este es los comandos de encripración/desencriptación que usaré:

GIT – Cliente

Staging Area

La staging area (también llamada index) es una zona intermedia donde Git prepara qué archivos formarán parte del próximo commit.

Añadir archivos al stage:

git add .                  # añade todo desde el directorio actual
git add archivo.js         # añade un archivo concreto
git add carpeta/           # añade una carpeta entera

Ver el estado del stage:

git status                 # qué está staged, modificado o untracked
git diff --staged          # ver qué cambios concretos hay staged

Sacar archivos del stage:

Hay dos comandos para "vaciar" el stage, pero hacen cosas distintas. Confundirlos es muy común. La elección depende de si el archivo ya estaba en algún commit anterior o no.

Comando Qué hace Cuándo usarlo
git restore --staged . Deshace el git add. El archivo sigue tracked si ya estaba en algún commit; si era nuevo, vuelve a untracked. Cuando se ha hecho add de algo que aún no se quería commitear. Es el "deshacer un add" del día a día.
git rm -r --cached . Destrackea los archivos: los saca del index y los marca para borrarse del repositorio en el próximo commit. No toca el Working Directory. Cuando un archivo ya estaba commiteado y se quiere que Git deje de seguirlo (típicamente después de añadirlo al .gitignore).

Aclaración importante: en la versión anterior de este post se usó git restore --staged . como si destrackeara archivos, pero no es así. restore --staged solo deshace un add reciente; no puede destrackear un archivo que ya está en commits anteriores. Para eso es necesario git rm -r --cached.

Caso típico: .env añadido al .gitignore tarde

# El archivo ya está en commits anteriores
echo ".env" >> .gitignore   # añadirlo al gitignore no basta
git rm --cached .env        # destrackearlo
git commit -m "Dejar de trackear .env"
# A partir de aquí, .gitignore por fin tiene efecto sobre .env

Esto no elimina el archivo del historial: los commits viejos siguen conteniéndolo. Si era un secreto, hay que rotarlo y reescribir historia con git filter-repo.

Commits

Un commit es una instantánea del proyecto en un momento dado. Forman una cadena que constituye el historial del repositorio.

Crear un commit:

git commit -m "Mensaje descriptivo"
git commit -am "Mensaje"   # add + commit de archivos ya tracked (no incluye nuevos)

Ver el historial:

git log                    # historial completo
git log --oneline          # versión compacta, una línea por commit
git log --graph --oneline  # visualización del grafo de ramas

Restaurar todo al estado del último commit:

git reset --hard HEAD

No borra archivos untracked (los que Git no conoce). Para limpiar también esos, conviene combinarlo con git clean -fd.

Deshacer commits:

Los tres reset se diferencian en qué zonas afectan:

Comando Qué hace Working Dir Stage Commits
git reset --soft HEAD~1 Quita el commit, deja los cambios staged listos para recommittear. Intacto Intacto Retrocede 1
git reset HEAD~1 (mixed) Quita el commit y saca los cambios del stage. Los cambios quedan como "modified". Intacto Vaciado Retrocede 1
git reset --hard HEAD~1 Quita el commit y descarta los cambios completamente. Destructivo. Retrocede 1 Retrocede 1 Retrocede 1

--hard es irreversible para cambios no commiteados. En caso de duda, conviene usar --soft o --mixed primero.

Alternativa segura: git revert

git revert HEAD            # crea un commit NUEVO que deshace el anterior

A diferencia de reset, no reescribe historia. Es lo recomendado en ramas compartidas.

Restaurar temporalmente el área de trabajo

En muchas ocasiones puede ser importante el restaurar el área de trabajo para ver cómo era el estado anterior de algún archivo en particular. Para hacer esto, usar:

git checkout <commit>

Stash

Stash es un almacén temporal donde se pueden guardar estados y cambios de forma aislada. Deja el working tree en el estado del último commit HEAD además de limpiar el stage area (a menos que se use --keep-index).

Comportamiento:
Las versiones guardadas en el stash están aislados ente sí. En cambio cada stash tiene como padre el HEAD de la rama desde donde se crea este. Los stash se guardan en un stack y debido a que no están relacionados entre sí, es posible borrar un stash que está en un nivel inferior sin ningún tipo de consecuencia. Es importante notar que los stash no se guardan en los remotos sino que se guardan exclusivamente de manera local.

Crear un stash:
Para crear un stash se debe usar el siguientre comando:

git stash push

Si se quiere crear un stash sin eliminar el index (como se había mencionado antes):

git stash push --keep-index

Si se desea agregar una descripción, usar:

git stash push -m "My stash"

El Stack de Stash:
El stack de Stash es una pila LIFO (La última en agregarse es la primera en irse). Los nombres de cada stash vienen numerados dinámicamente usando el modelo stash@{x}. El siguiente cuadro ejemplifica el stack de stash:

refs/stash ──> stash@{0}  "wip login"      ─┐
               stash@{1}  "pruebas API"     ├─ todos cuelgan de HEAD,
               stash@{2}  "WIP on main"    ─┘  no unos de otros
                    │
                    └── entradas del reflog de refs/stash

Poniéndonos un poco más técnicos, la pila se guarda en dos archivos, el primero guarda la referencia de la última entrada guardada y el segundo guarda las referencias de todos los stash guardados.

.git/refs/stash ──────────> último stash
.git/logs/refs/stash ────────> todos los stash

Comandos de Stash A continuación se presenta una tabla con algunos de los comandos de stash.

Comando Efecto
git stash push apila una entrada nueva en stash@{0}
git stash list muestra la pila entera
git stash show -p stash@{N} el diff de una entrada
git stash apply stash@{N} aplica, sin eliminarla
git stash pop stash@{N} aplica y la elimina
git stash drop stash@{N} la saca sin aplicar
git stash clear vacía la pila
git reflog stash la pila en crudo, con hashes

Merge: unir ramas

Al incorporar el trabajo de una rama en otra, Git ofrece tres métodos según la situación.

Fast-forward

Posible solo cuando la rama base (master) no tuvo commits propios mientras existía la otra rama. Git mueve el puntero hacia adelante sin crear ningún commit nuevo. El historial queda lineal, como si la rama nunca hubiera existido.

Antes:
  commit1 → commit2                            (master)
                  ↘
                   commit3 → commit4           (rama-1)

Después:
  commit1 → commit2 → commit3 → commit4
                                       ↑
                                 master, rama-1
  • A favor: historial limpio.
  • En contra: se pierde la información de que existió una rama paralela.

Merge commit

Cuando ambas ramas tienen commits propios, Git crea un commit de merge con dos padres. El historial refleja honestamente que hubo dos líneas paralelas.

Antes:
  commit1 → commit2 → commit3 → commit6 → commit7    (master)
                  ↘
                   commit4 → commit5                  (rama-1)

Después:
                   commit4 → commit5
                  ↗                 ↘
  commit1 → commit2 → commit3 → commit6 → commit7 → mergeCommit
                                                          ↑
                                                       master
  • A favor: historial honesto, refleja la realidad del desarrollo.
  • En contra: el grafo se vuelve complejo con muchas ramas.

Rebase

Reescribe los commits de la rama para que parezcan haber salido del último commit de master. El historial queda lineal, pero "miente" sobre cómo ocurrió el desarrollo real.

Antes:
  commit1 → commit2 → commit3 → commit6 → commit7    (master)
                  ↘
                   commit4 → commit5                  (rama-1)

Después:
  commit1 → commit2 → commit3 → commit6 → commit7 → commit4' → commit5'
                                                                     ↑
                                                                  rama-1

Los commit4 y commit5 originales quedan huérfanos y git gc los eliminará eventualmente. commit4' y commit5' son nuevos commits con los mismos cambios pero distinto hash.

  • A favor: historial lineal, fácil de leer.
  • En contra: reescribe historia. Nunca debe rebasearse una rama ya compartida con otros, porque les rompe su copia local.

Regla práctica:

  • Rebase para limpiar una rama local antes de mergear.
  • Merge commit para integrar trabajo compartido en la rama principal.

Otros comandos útiles

Descartar cambios locales en archivos tracked:

git restore .              # versión moderna (Git 2.23+)
git checkout .             # versión clásica, sigue funcionando

Sustituye los archivos modificados por la versión del stage (o de HEAD si no hay nada staged).

Eliminar archivos untracked del Working Directory:

git clean -fd
#       │└─ d: incluir directorios untracked
#       └── f: force (obligatorio por seguridad)

git clean -nd              # DRY RUN: muestra qué borraría sin borrar nada
git clean -fdx             # también borra archivos ignorados (.env, node_modules, etc.)

Conviene ejecutar siempre git clean -n primero. Los archivos borrados con clean no van a la papelera y, por ser untracked, Git no puede recuperarlos. Con -x se pueden perder archivos como .env con credenciales locales.

Combinación "dejar el repo como recién clonado":

git reset --hard HEAD && git clean -fd

Descarta cambios en archivos tracked y borra los untracked. El Working Directory queda exactamente igual al último commit.