parent
f8f7f18410
commit
0ee615afb5
@ -0,0 +1,148 @@
|
|||||||
|
---
|
||||||
|
weight: 4
|
||||||
|
title: "Apuntes de impresión 3D"
|
||||||
|
date: 2022-08-20T12:04:30+0200
|
||||||
|
draft: false
|
||||||
|
hiddenFromHomePage: true
|
||||||
|
summary: "Apuntes incompletos de impresión 3D"
|
||||||
|
categories:
|
||||||
|
- notes
|
||||||
|
tags:
|
||||||
|
- 3dprinter
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
## Instalación del software en nuestro ordenador
|
||||||
|
|
||||||
|
### Instalación de octoprint en docker
|
||||||
|
|
||||||
|
___Pronterface___ se ha vuelto imposible de instalar para mi, así que vamos a probar ___Octoprint___ dockerizado, así ya lo tenemos controlado para instalarlo en una _Orangepi Zero_ en la propia impresora.
|
||||||
|
|
||||||
|
El fichero `docker-compose.yml` para el Octoprint (cortesía de Caligari):
|
||||||
|
|
||||||
|
```yml
|
||||||
|
version: '2.4'
|
||||||
|
|
||||||
|
services:
|
||||||
|
octoprint:
|
||||||
|
image: octoprint/octoprint
|
||||||
|
container_name: octoprint
|
||||||
|
restart: unless-stopped
|
||||||
|
network_mode: bridge
|
||||||
|
ports:
|
||||||
|
- "80:80"
|
||||||
|
devices:
|
||||||
|
- "/dev/bus/usb"
|
||||||
|
volumes:
|
||||||
|
- "./data:/octoprint"
|
||||||
|
- "/run/udev:/run/udev:ro"
|
||||||
|
device_cgroup_rules:
|
||||||
|
- "c 188:* rmw" # USB to serial
|
||||||
|
- "c 81:* rmw" # USB webcams
|
||||||
|
# uncomment the lines below to ensure camera streaming is enabled when
|
||||||
|
# you add a video device
|
||||||
|
#environment:
|
||||||
|
# - ENABLE_MJPG_STREAMER=true
|
||||||
|
|
||||||
|
####
|
||||||
|
# uncomment if you wish to edit the configuration files of octoprint
|
||||||
|
# refer to docs on configuration editing for more information
|
||||||
|
####
|
||||||
|
#config-editor:
|
||||||
|
# image: linuxserver/code-server
|
||||||
|
# ports:
|
||||||
|
# - 8443:8443
|
||||||
|
# depends_on:
|
||||||
|
# - octoprint
|
||||||
|
# restart: unless-stopped
|
||||||
|
# environment:
|
||||||
|
# - PUID=0
|
||||||
|
# - PGID=0
|
||||||
|
# - TZ=America/Chicago
|
||||||
|
# volumes:
|
||||||
|
# - octoprint:/octoprint
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
Tenemos que adaptar la parte del mapeo del puerto USB para usarlo en nuestro ordenador.
|
||||||
|
|
||||||
|
A continuación algunas notas de como se puede hacer el mapeo del puerto USB en nuestro ordenador.
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
DSM docker UI application does not have option to set "device".
|
||||||
|
|
||||||
|
But you still can do this by following steps:
|
||||||
|
|
||||||
|
create "octoprint" container with all settings you need (volumes, ports etc)
|
||||||
|
select "Settings" -> "Export" and export docker container configuration JSON to local computer
|
||||||
|
open exported JSON in any editor
|
||||||
|
find string
|
||||||
|
|
||||||
|
"devices" : null,
|
||||||
|
|
||||||
|
and replace it with
|
||||||
|
|
||||||
|
"devices" : [
|
||||||
|
{
|
||||||
|
"pathOnHost": "/dev/ttyUSB0",
|
||||||
|
"PathInContainer": "/dev/ttyUSB0",
|
||||||
|
"CgroupPermissions": "rwm"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
|
||||||
|
Import JSON file back to DSM docker UI
|
||||||
|
|
||||||
|
P.S. Also I found that my "/dev/ttyUSB0" has "crw-------" permission, and can't be accessed inside docker by octoprint application. So I have to manually set to "crw-rw-rw-" with
|
||||||
|
|
||||||
|
chmod a+rw /dev/ttyUSB0
|
||||||
|
|
||||||
|
|
||||||
|
-----
|
||||||
|
also
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Suggest adding instructions to to identify the USB port being used and then passing this device into the container.
|
||||||
|
|
||||||
|
With the pi connected to the printer via usb
|
||||||
|
ls /dev | grep tty
|
||||||
|
|
||||||
|
This should return a long list of 'tty' The one we need is found at the end of the list and is probably
|
||||||
|
ttyUSB0 if no other USB devices are plugged in.
|
||||||
|
|
||||||
|
In order to use this ttyUSB0 add this to your docker run command
|
||||||
|
|
||||||
|
docker run -device /dev/ttyUSB0:/dev/ttyUSB0 .....
|
||||||
|
|
||||||
|
Now octoprint can detect the the USB port and connect to the printer.
|
||||||
|
|
||||||
|
Hi
|
||||||
|
i installed everything and it works. unfortunately I can't enable the usb and launching the command (pi4): docker: invalid reference format: repository name must be lowercase.
|
||||||
|
See 'docker run --help'.
|
||||||
|
|
||||||
|
some advice?
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Partes de repuesto
|
||||||
|
|
||||||
|
- [Engranaje de poleas](https://www.aliexpress.com/item/32817328238.html)
|
||||||
|
- [Pantalla de control](https://www.aliexpress.com/item/1005003952110687.html)
|
||||||
|
- [Husillos de lujo](https://www.aliexpress.com/item/1005004176770736.html)
|
||||||
|
- [Husillos normales](https://www.aliexpress.com/item/32818374370.html)
|
||||||
|
- https://www.aliexpress.com/item/1005003057778867.html
|
||||||
|
- https://www.aliexpress.com/item/1005003065012440.html
|
||||||
|
- https://www.aliexpress.com/item/1005004448072856.html
|
||||||
|
|
||||||
|
- [Porta bobinas](https://www.aliexpress.com/item/1005003873495589.html)
|
||||||
|
- [Limpiador de filamento](https://www.aliexpress.com/item/1005001431768691.html)
|
||||||
|
- [Patas antivibración](https://www.aliexpress.com/item/4000298849640.html)
|
||||||
|
- [Caja para secar el filamento](https://www.aliexpress.com/item/1005004415842339.html) (es muy mejorable)
|
||||||
|
- [Tornillos para la cama](https://www.aliexpress.com/item/4001155732510.html)
|
||||||
|
- [Conjunto de poleas sencillo](https://www.aliexpress.com/item/4001148474252.html)
|
@ -0,0 +1,96 @@
|
|||||||
|
---
|
||||||
|
weight: 4
|
||||||
|
title: "Apuntes de SDR"
|
||||||
|
date: 2020-05-29
|
||||||
|
draft: false
|
||||||
|
summary: "Notas sobre SDR y montaje de Open Plotter en Raspberry Pi"
|
||||||
|
categories:
|
||||||
|
- notes
|
||||||
|
tags:
|
||||||
|
- raspi
|
||||||
|
- sdr
|
||||||
|
- barco
|
||||||
|
---
|
||||||
|
|
||||||
|
{{< admonition type=warning title="Work in progress" open=true >}}
|
||||||
|
|
||||||
|
No está completo.
|
||||||
|
|
||||||
|
{{< /admonition >}}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Referencias
|
||||||
|
|
||||||
|
- https://www.youtube.com/watch?v=N8zxaMjA0qA
|
||||||
|
- https://youtu.be/oqOyNPMbu5o
|
||||||
|
- [A good quickstart guide for RTL-SDR Linux Users](https://www.rtl-sdr.com/a-good-quickstart-guide-for-rtl-sdr-linux-users/)
|
||||||
|
https://ranous.wordpress.com/rtl-sdr4linux/
|
||||||
|
- [Skywavelinux](https://skywavelinux.com/)
|
||||||
|
|
||||||
|
## Inhibir drivers DVB en udev rules para nuestro dispositivo SDR
|
||||||
|
|
||||||
|
Si echamos un vistazo al log del sistema en `/var/log/syslog` mientras conectamos el dispositivo SDR-RTL al puerto usb, obtenemos:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
tail -f /var/log/syslog
|
||||||
|
.
|
||||||
|
.
|
||||||
|
.
|
||||||
|
Aug 25 16:50:19 achernar kernel: [51499.253763] usb 1-3: new high-speed USB device number 12 using xhci_hcd
|
||||||
|
Aug 25 16:50:19 achernar kernel: [51499.415521] usb 1-3: New USB device found, idVendor=0bda, idProduct=2838, bcdDevice= 1.00
|
||||||
|
Aug 25 16:50:19 achernar kernel: [51499.415534] usb 1-3: New USB device strings: Mfr=1, Product=2, SerialNumber=3
|
||||||
|
Aug 25 16:50:19 achernar kernel: [51499.415541] usb 1-3: Product: RTL2838UHIDIR
|
||||||
|
Aug 25 16:50:19 achernar kernel: [51499.415546] usb 1-3: Manufacturer: Realtek
|
||||||
|
Aug 25 16:50:19 achernar kernel: [51499.415550] usb 1-3: SerialNumber: 00000001
|
||||||
|
Aug 25 16:50:19 achernar kernel: [51499.426274] usb 1-3: dvb_usb_v2: found a 'Realtek RTL2832U reference design' in warm state
|
||||||
|
Aug 25 16:50:19 achernar kernel: [51499.486288] usb 1-3: dvb_usb_v2: will pass the complete MPEG2 transport stream to the software demuxer
|
||||||
|
Aug 25 16:50:19 achernar kernel: [51499.486303] dvbdev: DVB: registering new adapter (Realtek RTL2832U reference design)
|
||||||
|
Aug 25 16:50:19 achernar kernel: [51499.486311] usb 1-3: media controller created
|
||||||
|
Aug 25 16:50:19 achernar kernel: [51499.487207] dvbdev: dvb_create_media_en tity: media entity 'dvb-demux' registered.
|
||||||
|
.
|
||||||
|
.
|
||||||
|
.
|
||||||
|
```
|
||||||
|
|
||||||
|
De este log podemos sacar el `idVendor` y el `idProduct`, además vemos que linux le está asignando un driver `dvd_usb` (_Digital Video Broadcast_) o sea que lo identifica como un sintonizador de televisión y no queremos que eso pase.
|
||||||
|
|
||||||
|
De momento la única solución parece ser poner el driver en la lista negra. Para ello creamos un fichero `/etc/modprobe.d/blacklist-rtl.conf` con el siguiente contenido:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
blacklist dvb_usb_rtl28xxu
|
||||||
|
```
|
||||||
|
|
||||||
|
Tras reiniciar el sistema veremos que al introducir el dispositivo usb, no se le asigna el _driver_ de televisión.
|
||||||
|
|
||||||
|
|
||||||
|
Instalamos los drivers (yo uso un pincho USB RTL-SDR v3) Los drivers disponibles en mi Linux Mint tienen la misma versión que en el github del proyecto.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo apt install rtl-sdr
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Para solucionarlo podemos crear un fichero `/etc/udev/rules/99-sdl-rtl.rule` con el siguiente contenido:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# for arduino brand, stop ModemManager grabbing port
|
||||||
|
ATTRS{idVendor}=="2a03", ENV{ID_MM_DEVICE_IGNORE}="1"
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
SUBSYSTEMS=="usb", ATTRS{idVendor}=="0bda", ATTRS{idProduct}=="2838", MODE:="0666"
|
||||||
|
|
||||||
|
idVendor=0bda, idProduct=2838
|
||||||
|
|
||||||
|
|
||||||
|
Aug 24 18:33:45 achernar kernel: [26699.444347] usb 1-3: new high-speed USB device number 8 using xhci_hcd
|
||||||
|
Aug 24 18:33:45 achernar kernel: [26699.608542] usb 1-3: New USB device found, idVendor=0bda, idProduct=2838, bcdDevice= 1.00
|
||||||
|
Aug 24 18:33:45 achernar kernel: [26699.608557] usb 1-3: New USB device strings: Mfr=1, Product=2, SerialNumber=3
|
||||||
|
Aug 24 18:33:45 achernar kernel: [26699.608564] usb 1-3: Product: RTL2838UHIDIR
|
||||||
|
Aug 24 18:33:45 achernar kernel: [26699.608569] usb 1-3: Manufacturer: Realtek
|
||||||
|
Aug 24 18:33:45 achernar kernel: [26699.608574] usb 1-3: SerialNumber: 00000001
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,58 @@
|
|||||||
|
---
|
||||||
|
weight: 4
|
||||||
|
title: "Editores"
|
||||||
|
date: 2022-06-18T12:44:28+0200
|
||||||
|
draft: true
|
||||||
|
summary: "Apuntes de distintos editores para programar en Linux"
|
||||||
|
categories:
|
||||||
|
- notes
|
||||||
|
tags:
|
||||||
|
- emacs
|
||||||
|
- neovim
|
||||||
|
- pycharm
|
||||||
|
- codium
|
||||||
|
- vs_code
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
## Editores
|
||||||
|
|
||||||
|
### Emacs
|
||||||
|
|
||||||
|
#### lsp-mode
|
||||||
|
|
||||||
|
**TODO** Revisar comando lsp-workspace-add-folder et al
|
||||||
|
|
||||||
|
### Neovim
|
||||||
|
|
||||||
|
### Codium
|
||||||
|
|
||||||
|
En ___Codium___ y ___VS Code___ las herramientas soportadas para los entornos virtuales de Python no incluyen `pyenv`.
|
||||||
|
|
||||||
|
Podemos definir un _fichero de definiciones de variables de entorno_ identificado por el `python.envFile`, por defecto tiene valor `${workspaceFolder}/.env` **TODO COMPLETAR ESTO**
|
||||||
|
|
||||||
|
Podemos establecer los _workspace settings_ con `C-,` y `Extensions: Python` y la opción `Edit in settings.json`. El ficher `json` del _workspace_ quedará:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"folders": [
|
||||||
|
{
|
||||||
|
"path": "."
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"settings": {
|
||||||
|
"python.pythonPath": "/home/salvari/.pyenv/versions/ve_celery/bin/python",
|
||||||
|
"python.linting.enabled": true,
|
||||||
|
"python.linting.pylintEnabled": true,
|
||||||
|
"python.linting.pylintPath": "/home/salvari/.pyenv/versions/ve_celery/pylint",
|
||||||
|
|
||||||
|
"python.linting.pylintArgs": [
|
||||||
|
"--init-hook",
|
||||||
|
"import sys; sys.path.append(\"/home/salvari/.pyenv/versions/ve_celery/lib/python3.9/site-packages\");",
|
||||||
|
],
|
||||||
|
"python.autoComplete.extraPaths": [
|
||||||
|
"/home/salvari/.pyenv/versions/ve_celery/lib/python3.9/site-packages",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
@ -0,0 +1,82 @@
|
|||||||
|
---
|
||||||
|
weight: 4
|
||||||
|
title: "Apuntes de Fotografía"
|
||||||
|
date: 2022-04-24T23:36:44+0200
|
||||||
|
draft: true
|
||||||
|
summary: "Mis. apuntes de fotografía"
|
||||||
|
categories:
|
||||||
|
- notes
|
||||||
|
tags:
|
||||||
|
- fotografía
|
||||||
|
- darktable
|
||||||
|
- olympus
|
||||||
|
---
|
||||||
|
|
||||||
|
## Olympus
|
||||||
|
|
||||||
|
{{< admonition type=note title="Work In Progress" open=true >}}
|
||||||
|
|
||||||
|
PENDIENTE DE COMPLETAR
|
||||||
|
|
||||||
|
|
||||||
|
{{< /admonition >}}
|
||||||
|
|
||||||
|
|
||||||
|
## Cianotipia
|
||||||
|
|
||||||
|
### Preparación de los liquidos
|
||||||
|
|
||||||
|
Materiales necesarios:
|
||||||
|
|
||||||
|
- Ferrocianuro de potasio (también llamado prusiato rojo)
|
||||||
|
- Citrato férrico amoniacal (también llamado citrato verde)
|
||||||
|
- Agua destilada (sospecho que el cloro del agua puede interferir en el preparado)
|
||||||
|
- Guantes de proteccion
|
||||||
|
- Gafas de protección (por si acaso)
|
||||||
|
- Jeringuilla para medir mililitros (mejor si tienes dos)
|
||||||
|
- Tres botes opacos (no demasiado grandes)
|
||||||
|
- Cinta de carrocero para etiquetar y/o hacer aun más opacos los botes.
|
||||||
|
- Brochas o esponjas para extender los líquidos sobre el papel o la tela
|
||||||
|
- Una hoja de Goma Eva del mismo tamaño que el negativo (p.ej. A4)
|
||||||
|
- Un cristal del mismo tamaño que el negativo (p.ej. A4 o un cristal de un marco de fotos de tamaño adecuado)
|
||||||
|
- Material base para la cianotipia, puede ser tela o papel que aguante bien la inmersión en agua (papel de acuarela)
|
||||||
|
- Negativos de acetato
|
||||||
|
|
||||||
|
#### Composición de los líquidos
|
||||||
|
|
||||||
|
Vamos a adoptar el convenio de que la solución de Citrato Férrico Amoniacal o Citrato Verde será la ___Solución A___, evidentemente la de Ferrocianuro de Potasio o Prusiato Rojo será la ___Solución B___
|
||||||
|
|
||||||
|
- Receta 1
|
||||||
|
- 8 gr. de prusiato rojo en 100 ml de agua
|
||||||
|
- 20 gr. de citrato verde en 100 ml de agua
|
||||||
|
|
||||||
|
- Receta 2
|
||||||
|
- 10 - 12 gr. de ferrocianuro de potasio (prusiato rojo)
|
||||||
|
- 25 gr. de citrato férrico amoniacal (citrato verde)
|
||||||
|
|
||||||
|
Al parecer conviene hacer la preparación de los liquidos con poca luz.
|
||||||
|
|
||||||
|
Evidentemente es __muy importante__ mantener los líquidos aislados, no está de más usar diferentes jeringuillas para preparar cada uno o de lo contrario limpiar exhaustivamente después de hacer un liquido y antes de preparar el segundo.
|
||||||
|
|
||||||
|
Los líquidos deben conservarse a oscuras y bien cerrados pueden llegar a durar un año.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Darktable
|
||||||
|
|
||||||
|
### Detalles del darkroom
|
||||||
|
|
||||||
|
* ___Darktable___ siempre muestra todas y cada una de las operaciones que realiza sobre la imagen
|
||||||
|
* Todos los módulos de ___Darktable___ tienen un orden de aplicación predefinido (se supone óptimo) El orden en el que en realidad se aplican los módulos a la imagen puede verse en la pestaña de módulos activos del _darkroom_.
|
||||||
|
* Hay distintas colecciones predeterminadas de módulos que podemos activar para no tener la lista completa de módulos (que es enorme). También podemos crear nuestra propia colección.
|
||||||
|
* El panel de acceso rápido (_Quick access_) __contiene versiones resumidas__ de los módulos más habituales, pero siempre podemos ir al módulo completo con el atajo de la esquina superior derecha.
|
||||||
|
* Debajo de la imagen a la izquierda tenemos acceso a los presets (sólo los creados por nosotros) y a los estilos.
|
||||||
|
* Todos los módulos se pueden resetear a los valores por defecto
|
||||||
|
* Todos los "deslizantes" pueden accionarse con el botón derecho y teclear un valor concreto si queremos
|
||||||
|
|
||||||
|
### Flujo de trabajo
|
||||||
|
|
||||||
|
* Importar las fotos (generalmente desde las cámaras) con ___Shotwell___.
|
||||||
|
* Añadir los directorios de ___Shotwell___ a la biblioteca de ___Darktable___
|
||||||
|
* Hacer una revisión en la mesa de luz de todas las fotos y destruir las malas
|
@ -0,0 +1,135 @@
|
|||||||
|
---
|
||||||
|
weight: 4
|
||||||
|
title: "Notas de FreeCAD"
|
||||||
|
date: 2021-06-28T09:35:03+0200
|
||||||
|
draft: true
|
||||||
|
summary: "Notas sobre FreeCAD"
|
||||||
|
categories:
|
||||||
|
- notes
|
||||||
|
tags:
|
||||||
|
- freecad
|
||||||
|
---
|
||||||
|
|
||||||
|
Apuntes **muy incompletos** sobre _FreeCAD_.
|
||||||
|
|
||||||
|
<!--more-->
|
||||||
|
|
||||||
|
{{< image src="/images/FreeCAD-Logo.png" >}}
|
||||||
|
|
||||||
|
{{< admonition type=warning title="Work in progress" open=true >}}
|
||||||
|
Estos apuntes son personales y no valen para aprender, mejor búscate un buen tutorial en la red
|
||||||
|
{{< /admonition >}}
|
||||||
|
|
||||||
|
|
||||||
|
## FreeCAD
|
||||||
|
|
||||||
|
### Ejecutar varias versiones de FreeCAD con sus configuraciones independientes
|
||||||
|
|
||||||
|
Yo uso las Appimages de FreeCAD, para cada configuración independiente necesitamos un directorio diferente. En mi caso uso tres directorios:
|
||||||
|
|
||||||
|
* `~/apps/freecad/fc019` Para FreeCAD 0.19
|
||||||
|
* `~/apps/freecad/fc020` Para FreeCAD 0.20
|
||||||
|
* `~/apps/freecad/fcrt` Para FreeCAD RealThunder
|
||||||
|
|
||||||
|
Cada vez que descargo una nueva versión de Appimage, la descargo al directorio correspondiente.
|
||||||
|
|
||||||
|
En cada directorio tengo un enlace simbólico `current` apuntando a la Appimage que quiero ejecutar (el enlace simbólico se crea con el comando `ln <target> <symlink>`) . Por ejemplo, en el directorio `fc019` ahora mismo tengo:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ls -l ~/apps/freecad/fc019
|
||||||
|
total 1647152
|
||||||
|
lrwxrwxrwx 1 salvari salvari 56 Jun 28 09:12 current -> FreeCAD_0.19-24291-Linux-Conda_glibc2.12-x86_64.AppImage
|
||||||
|
-rwxr--r-- 1 salvari salvari 839349440 Apr 26 21:55 FreeCAD_0.19-24276-Linux-Conda_glibc2.12-x86_64.AppImage
|
||||||
|
-rwxr--r-- 1 salvari salvari 847320256 Jun 28 08:55 FreeCAD_0.19-24291-Linux-Conda_glibc2.12-x86_64.AppImage
|
||||||
|
```
|
||||||
|
|
||||||
|
Por último tengo tres scripts en `~/.local/bin` que se llaman `fc019`, `fc020` y `fcrt`. Pongo el contenido de `fc019` como ejemplo:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
export HOME=/home/salvari/apps/freecad/fc019
|
||||||
|
export FREECAD_USER_HOME=$HOME
|
||||||
|
~/current --user-cfg ~/user.cfg --system-cfg ~/system.cfg --module-path ~/Mod
|
||||||
|
```
|
||||||
|
|
||||||
|
Con estos scripts puedo lanzar los tres FreeCAD y las configuraciónes de cada uno quedarán guardadas en su respectivo directorio.
|
||||||
|
|
||||||
|
### Letras con FreeCAD e Inkscape
|
||||||
|
|
||||||
|
En Inkscape:
|
||||||
|
|
||||||
|
* Escribimos el texto que nos interese. Hay que fijarse en darle ya las dimensiones que queremos en realidad
|
||||||
|
* Selecionamos el objeto texto y ejecutamos el comando `Path::Object to Path` (también vale `Ctrl+alt+C`)
|
||||||
|
* Salvamos el texto en un fichero `texto.svg`
|
||||||
|
|
||||||
|
En FreeCAD:
|
||||||
|
* Abrimos un nuevo fichero e importamos el SVG como geometría.
|
||||||
|
|
||||||
|
* Para cada letra del texto tendremos uno o varios `path`: uno con el contorno de la letra y uno por cada "hueco". Nos aseguramos de estar en el *Draft Workbench* y para cada `path` hacemos un `Modification::Downgrade` y un `Modification::Upgrade`, con eso transformamos cada `path` en un `wire`
|
||||||
|
|
||||||
|
* Ahora pasamos al *Part Workbench* y a cada `wire` le aplicamos un `Part::2D offset`.
|
||||||
|
* Volvemos al *Draft Workbench* y al objeto `2D offset` le hacemos un downgrade. Esto descompone el objeto en el `wire` original y un conjunto de `edges` (que quedan seleccionados). Si a continuación hacemos un upgrade (con todos los `edge` seleccionados) tendremos un `wire` para la silueta externa de la letra y otro `wire` para la interna (conviene renombrarlos)
|
||||||
|
* Para que todo vaya bien (no tengo otra explicación) hay que pasar los `wire` a objetos `Shape2DView`, y a cada uno de los objetos resultantes aplicarles la operación `Draft to Sketch`. Con eso obtendremos dos objetos `sketch` para los contornos exterior e interior de la letra respectivamente.
|
||||||
|
* Es muy conveniente pasar al *Sketcher Workbench* y validar ambos objetos `sketch` buscando y arreglando los `open vertexes`.
|
||||||
|
* Ya podemos ir al *Part Design Workbench*, antes de nada conviene crear un objeto `Part` en la raiz de nuestro documento y un objeto `body` dentro del `Part`
|
||||||
|
* Arrastramos el `sketch` exterior al `Body` y hacemos un `pad` a nuestro gusto
|
||||||
|
* Arrastramos el `sketch` interior al `Body` pero teniendo cuidado de mapearlo a la cara superior de nuestra letra.
|
||||||
|
* Con el `sketch` mapeado en la cara superior creamos un `Pocket` controlando la profundidad podemos hacer que nuestra letra sea una caja o solo una pared
|
||||||
|
|
||||||
|
## Tutoriales
|
||||||
|
|
||||||
|
### Rafael García
|
||||||
|
|
||||||
|
[Aquí](https://www.youtube.com/watch?v=136sG-7zins&list=PLvDOxR8gzkX_3LtuEKBIoNLFFgJK_AXkE&index=1)
|
||||||
|
|
||||||
|
* FreeCAD 001: Intro
|
||||||
|
* FreeCAD 002: Más intro con el sketcher
|
||||||
|
* FreeCAD 003: Más intro con el sketcher (un poco de splines)
|
||||||
|
* FreeCAD 004: Boceto sobre caras y algo de matrices polares
|
||||||
|
* FreeCAD 005: Revolución de sketches
|
||||||
|
* FreeCAD 006-01: Pieza solucionada con Dar espesor a un sólido
|
||||||
|
* FreeCAD 006-02: Continuación
|
||||||
|
* FreeCAD 007: Pieza de los 200 ejercicios
|
||||||
|
* FreeCAD 008: Simetrias y multitransformación en Part Design
|
||||||
|
* FreeCAD 009: Pantalones de caldereria
|
||||||
|
* FreeCAD 009_bis: Planos técnicos con Techdraw
|
||||||
|
* FreeCAD 010: Una T de fontanería
|
||||||
|
* FreeCAD 011: Enlazar diseño paramétrico con una hoja de datos
|
||||||
|
* FreeCAD 012: Caja con tornillos
|
||||||
|
* FreeCAD 013: Extruir caras de nuestros sólidos
|
||||||
|
* FreeCAD 014: Uso de imágenes para crear proyectos
|
||||||
|
* FreeCAD 015: Primera pieza de la cizalla
|
||||||
|
* FreeCAD 016: Cuchilla de la cizalla hidráulica
|
||||||
|
* FreeCAD 017: Más cuchilla
|
||||||
|
* FreeCAD 018: Materiales
|
||||||
|
* FreeCAD 019: Pasadores para la cizalla
|
||||||
|
* FreeCAD 020: Más cizalla
|
||||||
|
* FreeCAD 021: Todavía más cizalla
|
||||||
|
* FreeCAD 022: Algunos trucos en sketcher
|
||||||
|
* FreeCAD 023: Tiralineas
|
||||||
|
* FreeCAD 024:
|
||||||
|
* FreeCAD 025:
|
||||||
|
* FreeCAD 026:
|
||||||
|
* FreeCAD 027:
|
||||||
|
* FreeCAD 028:
|
||||||
|
* FreeCAD 029:
|
||||||
|
* FreeCAD 030:
|
||||||
|
* FreeCAD 031:
|
||||||
|
* FreeCAD 032:
|
||||||
|
* FreeCAD 033:
|
||||||
|
* FreeCAD 034:
|
||||||
|
* FreeCAD 035:
|
||||||
|
* FreeCAD 036:
|
||||||
|
* FreeCAD 037:
|
||||||
|
* FreeCAD 038:
|
||||||
|
* FreeCAD 039:
|
||||||
|
|
||||||
|
### MangoJelly
|
||||||
|
|
||||||
|
- [FreeCAD: Learn Python](https://invidious.snopyta.org/playlist?list=PLWuyJLVUNtc15o92Bo6SgtYzXt7zlSIsh) ver también [doc](https://wiki.freecadweb.org/Power_users_hub)
|
||||||
|
- [FreeCAD 6 for Beginners](https://invidious.snopyta.org/playlist?list=PLWuyJLVUNtc0UszswD0oD5q4VeWTrK7JC)
|
||||||
|
|
||||||
|
### Misc
|
||||||
|
|
||||||
|
- [Apuntes de Federico Coca](https://fgcoca.github.io/Mis-notas-de-FreeCAD/6-TD/)
|
@ -0,0 +1,28 @@
|
|||||||
|
---
|
||||||
|
weight: 4
|
||||||
|
title: "Apuntes del protocolo Gemini"
|
||||||
|
date: 2021-11-02T12:43:07+0100
|
||||||
|
draft: true
|
||||||
|
summary: "Protocolo Gemini"
|
||||||
|
categories:
|
||||||
|
- notes
|
||||||
|
tags:
|
||||||
|
- gemini
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
{{< admonition type=warning title="Work in progress" open=true >}}
|
||||||
|
|
||||||
|
No está completo.
|
||||||
|
|
||||||
|
{{< /admonition >}}
|
||||||
|
|
||||||
|
## Referencias
|
||||||
|
|
||||||
|
- <https://thedorkweb.substack.com/p/gopher-gemini-and-the-smol-internet>
|
||||||
|
- <https://www.ochobitshacenunbyte.com/2021/10/27/conociendo-el-protocolo-gemini/>
|
||||||
|
- <https://victorhckinthefreeworld.com/2021/11/01/introduccion-rapida-del-lenguaje-de-marcado-para-el-protocolo-gemini/>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,198 @@
|
|||||||
|
---
|
||||||
|
weight: 4
|
||||||
|
title: "Apuntes de Arte Generativo"
|
||||||
|
date: 2023-02-01T11:00:40+0100
|
||||||
|
draft: false
|
||||||
|
summary: "Pues eso, apuntes sueltos de arte generado por ordenador"
|
||||||
|
categories:
|
||||||
|
- notes
|
||||||
|
tags:
|
||||||
|
- python
|
||||||
|
- processing
|
||||||
|
- py5
|
||||||
|
- openFrameworks
|
||||||
|
- generative art
|
||||||
|
---
|
||||||
|
|
||||||
|
<!--
|
||||||
|
https://www.instructables.com/Exploring-Generative-Art-How-to-Create-Stunning-Ar/
|
||||||
|
https://www.freecodecamp.org/news/how-to-create-generative-art-in-less-than-100-lines-of-code-d37f379859f/
|
||||||
|
https://blog.prototypr.io/the-short-guide-to-generative-art-creative-coding-fc36ff163708
|
||||||
|
https://aiartists.org/ai-generated-art-tools
|
||||||
|
-->
|
||||||
|
|
||||||
|
{{< admonition type=warning title="EN CONSTRUCCION" open=true >}}
|
||||||
|
|
||||||
|
Esta página está muy lejos de estar completa, solo son apuntes sueltos para uso personal.
|
||||||
|
|
||||||
|
{{< /admonition >}}
|
||||||
|
|
||||||
|
|
||||||
|
{{< admonition type=info title="Referencias" open=true >}}
|
||||||
|
- [Processing](https://processing.org/)
|
||||||
|
- [py5](http://py5coding.org/) un port de Processing para Python
|
||||||
|
- [py5 source](https://github.com/py5coding/py5)
|
||||||
|
- [Install py5](https://py5coding.org/content/install.html)
|
||||||
|
- [Generative Design Landing Page](http://www.generative-gestaltung.de/ "A landing page for the book") Un libro de arte generativo con muchos ejemplos de ___Processing___
|
||||||
|
- [The Nature of Code](https://natureofcode.com/ "The book from Daniel Shiffman") Un libro de Daniel Shiffman que se puede leer on-line. Simulaciones de procesos físicos con ___Processing___
|
||||||
|
- [Portando todos los ejemplos de Processing a py5 por Alexandre Villares](https://github.com/villares/py5examples/tree/processing-python-mode-examples/examples-from-Processing-Python-mode)
|
||||||
|
- [Structure Synth](https://structuresynth.sourceforge.net/)
|
||||||
|
- [Design for Complexity with Structure Synth](https://www.shapeways.com/blog/archives/32934-tutorial-tuesday-27-design-complexity-structure-synth.html)
|
||||||
|
- [Scripting in Structure Synth](http://blog.hvidtfeldts.net/index.php/2010/11/scripting-in-structure-synth/)
|
||||||
|
- [Context Free Art](https://www.contextfreeart.org/)
|
||||||
|
- [Generative Design](https://github.com/generative-design) The book on Github
|
||||||
|
- [Generative Arts Links](http://blog.hvidtfeldts.net/index.php/generative-art-links/)
|
||||||
|
{{< /admonition >}}
|
||||||
|
|
||||||
|
|
||||||
|
## py5, un port de Processing a Python
|
||||||
|
|
||||||
|
### Requisitos
|
||||||
|
|
||||||
|
Para que todo funcione correctamente necesitamos:
|
||||||
|
|
||||||
|
- Python 3.8
|
||||||
|
- Java 17
|
||||||
|
- La biblioteca de gráficos _Cairo_ (esta es opcional, y yo ya la tenía instalada con `apt install libcairo2-dev`)
|
||||||
|
|
||||||
|
### Instalación
|
||||||
|
|
||||||
|
1. Instalamos la última versión de Python 3.8 (por precaución no instalo en la última versión de Python pero puedes probar)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pyenv install --list |grep 3.8.
|
||||||
|
pyenv install 3.8.15
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Creamos un entorno virtual
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pyenv virtualenv 3.8.15 ve_py5
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Activamos el entorno e instalamos py5
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pyenv ve_py5 activate
|
||||||
|
myve
|
||||||
|
pip install 'py5[jupyter]'
|
||||||
|
pip install cairosvg
|
||||||
|
```
|
||||||
|
|
||||||
|
4. Instalamos java mediante python (asegúrate de que sigues en el mismo virtualenv)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pip install install-jdk
|
||||||
|
python -c "import jdk; print('Java installed to', jdk.install('17'))"
|
||||||
|
```
|
||||||
|
|
||||||
|
Con esto ya tenemos todo instalado. Podemos probar `py5` con un programa sencillo:
|
||||||
|
|
||||||
|
```python3
|
||||||
|
import py5
|
||||||
|
|
||||||
|
def setup():
|
||||||
|
py5.size(200, 200)
|
||||||
|
py5.rect_mode(py5.CENTER)
|
||||||
|
|
||||||
|
def draw():
|
||||||
|
py5.rect(py5.mouse_x, py5.mouse_y, 10, 10)
|
||||||
|
|
||||||
|
py5.run_sketch()
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### Java 17
|
||||||
|
|
||||||
|
Yo uso Openjdk en mi linux:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
java -version
|
||||||
|
|
||||||
|
openjdk version "11.0.17" 2022-10-18
|
||||||
|
OpenJDK Runtime Environment (build 11.0.17+8-post-Ubuntu-1ubuntu222.04)
|
||||||
|
OpenJDK 64-Bit Server VM (build 11.0.17+8-post-Ubuntu-1ubuntu222.04, mixed mode, sharing)
|
||||||
|
```
|
||||||
|
|
||||||
|
El Java 17 que hemos instalado se queda en `~/.jdk`.
|
||||||
|
|
||||||
|
`py5` no necesita configuración adicional para usar el Java 17, sabe donde tiene que buscarlo. Si por alguna razón quieres usar esa versión de Java para otras historias puedes añadir un alias, como el siguiente, al fichero de alias (`~/.zalias.zsh`)
|
||||||
|
|
||||||
|
```zsh
|
||||||
|
# Java 17 installed in ~/.jdk
|
||||||
|
java17() {
|
||||||
|
export JAVA_HOME="$HOME/.jdk"
|
||||||
|
export PATH="$HOME/.jdk/jdk-17.0.6+10/bin:$PATH"
|
||||||
|
java -version
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Con ese alias podremos activar el Java 17 en nuestra sesión de terminal sin más que ejecutar `java17`
|
||||||
|
|
||||||
|
|
||||||
|
### Modos de funcionamiento de _py5_
|
||||||
|
|
||||||
|
#### Modo _module_
|
||||||
|
|
||||||
|
Este se parece bastante al modo clásico de _Processing_. En este modo podemos crear las funciones `settings`, `setup` y `draw`. Ninguna es obligatoria pero en la práctica es raro que no necesites `setup` y si quieres algo dinámico te hará falta `draw`.
|
||||||
|
|
||||||
|
Un ejemplo típico de programa en modo _module_:
|
||||||
|
|
||||||
|
```python3
|
||||||
|
import py5
|
||||||
|
|
||||||
|
def setup():
|
||||||
|
py5.size(300, 200)
|
||||||
|
py5.rect_mode(py5.CENTER)
|
||||||
|
|
||||||
|
def draw():
|
||||||
|
py5.rect(py5.mouse_x, py5.mouse_y, 10, 10)
|
||||||
|
|
||||||
|
py5.run_sketch()
|
||||||
|
```
|
||||||
|
|
||||||
|
En `setup` podemos invocar funciones de `settings` y ahorrarnos escribir esa función, pero todo lo que pertenezca a `settings` tiene que ir al principio de la función `setup`.
|
||||||
|
|
||||||
|
{{< admonition type=danger title="import py5" open=true >}}
|
||||||
|
Ni se te ocurra hacer `from py5 import *` tendrás problemas con varias cosas. __py5__ no está programado para soportar este tipo de _import_ que, en todo caso, siempre es poco aconsejable.
|
||||||
|
{{< /admonition >}}
|
||||||
|
|
||||||
|
#### Modo _Class_
|
||||||
|
|
||||||
|
Nos permite crear Clases que heredan del objeto "_Sketch_" de __py5__.
|
||||||
|
|
||||||
|
#### Modo _Imported_
|
||||||
|
|
||||||
|
Imita el funcionamiento de __Processing__, sin imports ni prefijos en las funciones de __py5__. Sólo podemos usar este modo desde __Jupyter__ tras instalar el _kernel_ de __py5__
|
||||||
|
|
||||||
|
#### Modo _Static_
|
||||||
|
|
||||||
|
Para crear imágenes estáticas
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## openFrameworks
|
||||||
|
|
||||||
|
Nos bajamos los fuentes para linux 64bits desde [la página web del proyecto](https://openframeworks.cc), y las descomprimimos en un directorio para proceder a compilarlas.
|
||||||
|
|
||||||
|
No hay más que seguir [las instrucciones de instalación para linux](https://openframeworks.cc/setup/linux-install/).
|
||||||
|
|
||||||
|
La instalación no es demasiado intrusiva si tienes Ubuntu 18 o mayor y una versión reciente del gcc.
|
||||||
|
|
||||||
|
Al instalar las dependencias añadimos los siguientes paquetes a nuestro sistema:
|
||||||
|
|
||||||
|
~~~~bash
|
||||||
|
installing OF dependencies
|
||||||
|
OF needs to install the following packages using apt-get:
|
||||||
|
curl libjack-jackd2-0 libjack-jackd2-dev freeglut3-dev libasound2-dev libxmu-dev libxxf86vm-dev g++ libgl1-mesa-dev libglu1-mesa-dev libraw1394-dev libudev-dev libdrm-dev libglew-dev libopenal-dev libsndfile-dev libfreeimage-dev libcairo2-dev libfreetype6-dev libssl-dev libpulse-dev libusb-1.0-0-dev libgtk-3-dev libopencv-dev libassimp-dev librtaudio-dev libboost-filesystem-dev libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev gstreamer1.0-libav gstreamer1.0-pulseaudio gstreamer1.0-x gstreamer1.0-plugins-bad gstreamer1.0-alsa gstreamer1.0-plugins-base gstreamer1.0-plugins-good gdb libglfw3-dev liburiparser-dev libcurl4-openssl-dev libpugixml-dev libgconf-2-4 libgtk2.0-0 libpoco-dev
|
||||||
|
~~~~
|
||||||
|
|
||||||
|
No te olvides de compilar también el _Project Generator_.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Structure Synth
|
||||||
|
|
||||||
|
Instalamos con `sudo apt install structure-synth sunflow`
|
||||||
|
|
||||||
|
## Context Free Art
|
@ -0,0 +1,260 @@
|
|||||||
|
---
|
||||||
|
weight: 4
|
||||||
|
title: "Apuntes de Git"
|
||||||
|
date: 2022-07-28T20:30:52+0200
|
||||||
|
draft: false
|
||||||
|
summary: "Pues eso, apuntes sueltos de git"
|
||||||
|
categories:
|
||||||
|
- notes
|
||||||
|
tags:
|
||||||
|
- git
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
## Detached-HEAD
|
||||||
|
|
||||||
|
Lo normal es que te enteres después de hacer uno o varios *commits* en *Detached*
|
||||||
|
|
||||||
|
### Con rama temporal
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git branch tmp
|
||||||
|
git checkout main
|
||||||
|
git merge tmp
|
||||||
|
git branch -d tmp
|
||||||
|
```
|
||||||
|
|
||||||
|
### Directamente
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git checkout main
|
||||||
|
git merge HEAD@{1}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Dejar de seguir un fichero
|
||||||
|
|
||||||
|
### Sin borrarlo del directorio de trabajo
|
||||||
|
|
||||||
|
1. Primero añadimos el fichero o directorio que quieres ignorar al .gitignore.
|
||||||
|
2. Ejecutamos:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git rm -r --cached <file>
|
||||||
|
git add .
|
||||||
|
```
|
||||||
|
|
||||||
|
Vale para ficheros o directorios, la opción `-r` es para hacerlo recursivo, la opción `--cached` esta para que no borre nada en el _working tree_ solo borra en _index_
|
||||||
|
|
||||||
|
__OJO__: Este método borra los ficheros para el resto del equipo cuando hagan un `git pull`
|
||||||
|
|
||||||
|
### Queremos hacer modificaciones del fichero en local sin propagarlas al resto del equipo
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git --update-index --skip-worktree <file>
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Hacer un merge
|
||||||
|
|
||||||
|
1. Asegúrate de completar todas las tareas para dejar lista la rama que vas a fusionar
|
||||||
|
2. Asegúrate de cambiár a la rama receptora (`git checkout`) y de que estás en ella (`git status`)
|
||||||
|
3. Actualiza la rama receptora con el _remote_ (puedes usar `git fetch` y `git pull`)
|
||||||
|
4. Ejecuta el _merge_ con `git merge`
|
||||||
|
|
||||||
|
## Borrar submódulo
|
||||||
|
|
||||||
|
La forma correcta de hacerlo, conservando el contenido del módulo si es necesario.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mv a/submodule a/submodule_tmp # keeps a backup of module contents
|
||||||
|
# do this only if keeping the contents
|
||||||
|
|
||||||
|
git submodule deinit -f a/submodule # removes submodule from repo
|
||||||
|
rm -rf .git/modules/a/submodule # removes submodule reference
|
||||||
|
git rm -f a/submodule # Note: a/submodule (no trailing slash)
|
||||||
|
|
||||||
|
# or, if you want to leave it in your working tree and have done step 0
|
||||||
|
git rm --cached a/submodule
|
||||||
|
mv a/submodule_tmp a/submodule
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Clonar cuando hay submódulos
|
||||||
|
|
||||||
|
La opción `-jn` asigna n recursos para las tareas de clonado.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone --recursive -j8 git://github.com/foo/bar.git
|
||||||
|
```
|
||||||
|
|
||||||
|
## Deshacer un _amend_
|
||||||
|
|
||||||
|
Siempre y cuando no la hayas pifiado ya en la historia compartida.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git reset --soft HEAD@{1}
|
||||||
|
git commit -C HEAD@{1}
|
||||||
|
```
|
||||||
|
|
||||||
|
La primera orden mueve el _HEAD_ a donde estaba apuntando el _commit_ antiguo. Además dejamos el _index_ intacto para poder hacer otra vez un _commit_ con los cambios pendientes.
|
||||||
|
|
||||||
|
`HEAD@{1}` nos da el _commit_ al que _HEAD_ estaba apuntando antes de apuntar al que está apuntando (léelo un par de veces más). No es lo mismo que `HEAD~1` que devuelve el _commit_ padre del _commit_ al que está apuntando _HEAD_.
|
||||||
|
|
||||||
|
La segunda sentencia es más retorcida. Significa: _haz un commit del tree actual, usando los detalles del commit erroneo_. Fíjate que `HEAD@{1}` ahora apunta al _commit_ erróneo, puesto que apunta al _commit_ al que apuntaba _HEAD_ antes de apuntar a donde apunta ahora mismo.
|
||||||
|
|
||||||
|
## _Revert_ a un _commit_ previo
|
||||||
|
|
||||||
|
### _Detached Head_
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git checkout <old-commit-hash>
|
||||||
|
```
|
||||||
|
|
||||||
|
__¡Ojo!__ ahora mismo estás en un _detached head_ es decir no estás en ningún _branch_. Si haces cambios en el _commit_ `<old-commit-hash>` vas a tener muchos problemas. Antes de hacer cambios puedes crear una nueva rama:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git switch -c <new-branch-name>
|
||||||
|
```
|
||||||
|
|
||||||
|
O volver a donde estabas con `git checkout`
|
||||||
|
|
||||||
|
### Con una rama
|
||||||
|
|
||||||
|
Si quieres hacer cambios es lo más recomendable:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git checkout -b old-state <old-commit-hash>
|
||||||
|
```
|
||||||
|
|
||||||
|
### A fuego (quemando las naves)
|
||||||
|
|
||||||
|
__Si no tienes nada en la historia compartida__ puedes hacer reset:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Perderás todos los cambios locales!
|
||||||
|
git reset --hard <old-commit-hash>
|
||||||
|
|
||||||
|
# Si quieres guardar cambios pendientes
|
||||||
|
git stash
|
||||||
|
git reset --hard <old-commit-hash>
|
||||||
|
git stash pop
|
||||||
|
# Salvar modificaciones y reaplicar
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
__Si ya has compartido la historia__ tendrás que trabajar con _revert_.
|
||||||
|
|
||||||
|
Esta también es la forma más segura y recomendable si quieres conservar la historia completa:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git revert --no-commit <old-commit-hash>..HEAD
|
||||||
|
git commit
|
||||||
|
```
|
||||||
|
|
||||||
|
El _flag_ `--no-commit` permite hacer un _revert_ de todos los _commits_ de un golpe, si no lo pasas hará un nuevo _commit_ por cada _commit_ "revertido" y la historia va a quedar un poco enrevesada.
|
||||||
|
|
||||||
|
## Cambiar el nombre a una rama
|
||||||
|
|
||||||
|
En _Gitlab_ hay que usar _main_ en lugar de _master_.
|
||||||
|
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git branch -m <New_Branch_Name>
|
||||||
|
git push origin :<Old_Branch_Name> <New_Branch_Name>
|
||||||
|
git push --set-upstream origin <New_Branch_Name>
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Cambiar de master a main (otro método)
|
||||||
|
|
||||||
|
En local:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git branch -m master main
|
||||||
|
git status
|
||||||
|
git push -u origin main
|
||||||
|
git push origin --delete master
|
||||||
|
```
|
||||||
|
|
||||||
|
Resto del equipo:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git checkout master
|
||||||
|
git branch -m master main
|
||||||
|
git fetch
|
||||||
|
git branch --unset-upstream
|
||||||
|
git branch -u origin/main
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Crear una nueva rama
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git branch <newbranch_name> # Crea una nueva rama
|
||||||
|
git checkout <newbranch_name> # Cambia a la nueva rama
|
||||||
|
git switch <newbranch_name> # También cambia a la nueva rama
|
||||||
|
git push -u origin <newbranch_name> # Sube la nueva rama al repo remoto
|
||||||
|
```
|
||||||
|
|
||||||
|
Hay otras alternativas:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git branch <new_branch> ffeeddaa # Crea una rama a partir de un commit
|
||||||
|
git branch <new_branch> v1.2 # Crea una rama a partir de un tag
|
||||||
|
git branch --track <new_branch> origin/<base_branch> # Crea una rama a partir de una rama remota
|
||||||
|
```
|
||||||
|
|
||||||
|
## Borrar un fichero con información sensible de la historia del repo
|
||||||
|
|
||||||
|
|
||||||
|
### Usando solo git
|
||||||
|
```bash
|
||||||
|
git filter-branch --force --index-filter \
|
||||||
|
"git rm --cached --ignore-unmatch PATH-TO-YOUR-FILE-WITH-SENSITIVE-DATA" \
|
||||||
|
--prune-empty --tag-name-filter cat -- --all
|
||||||
|
git push --force --verbose --dry-run
|
||||||
|
git push --force
|
||||||
|
```
|
||||||
|
|
||||||
|
### Usando git-filter-repo
|
||||||
|
|
||||||
|
Es una herramienta escrita en Python (ver [github](https://github.com/newren/git-filter-repo))
|
||||||
|
|
||||||
|
|
||||||
|
## rebase interactive
|
||||||
|
|
||||||
|
- <https://jordanelver.co.uk/blog/2020/06/04/fixing-commits-with-git-commit-fixup-and-git-rebase-autosquash/>
|
||||||
|
|
||||||
|
|
||||||
|
## Escribir mensajes de commit significativos
|
||||||
|
|
||||||
|
- <https://www.freecodecamp.org/news/how-to-write-better-git-commit-messages/>
|
||||||
|
|
||||||
|
**Mis tipos de _commit_**
|
||||||
|
|
||||||
|
Para usar con este formato:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
<type>[optional scope]: <description>
|
||||||
|
|
||||||
|
[optional body]
|
||||||
|
|
||||||
|
[optional footer(s)]
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
| Type | Tipo | Descripción |
|
||||||
|
|:--|:--|:--|
|
||||||
|
| dev | desarrollo | Es un _commit_ de desarrollo en las fases iniciales del proyecto |
|
||||||
|
| fix | fix | Se arregla un _bug_ |
|
||||||
|
| chore | mantenimiento | El _commit_ no implica ni cambios de código ni de test |
|
||||||
|
| refactor | | refactorización de código que no arregla un _bug_ ni añade features |
|
||||||
|
| docs | | Añade o retoca documentación del proyecto |
|
||||||
|
| style | | Cambios que no afectan el significado del código, probablemente relacionados con el formateado del código, y similares |
|
||||||
|
| test | | Crea nuevos test o corrige test existentes |
|
||||||
|
| perf | | mejoras de _performance_ |
|
||||||
|
| ci | | Relacionados con integración contínua (_continuous integration_) |
|
||||||
|
| build | | cambios que afecta al _build_ del proyecto, p.ej. cambios de dependencias |
|
||||||
|
| revert | | Vuelta a un _commit_ previo |
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,94 @@
|
|||||||
|
---
|
||||||
|
weight: 4
|
||||||
|
title: "Apuntes de Autonomía Digital"
|
||||||
|
date: 2022-03-29T18:54:41+0200
|
||||||
|
draft: true
|
||||||
|
summary: "Más valdría hablar de guerrilla digital"
|
||||||
|
categories:
|
||||||
|
- notes
|
||||||
|
tags:
|
||||||
|
- soberania digital
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
{{< admonition type=warning title="Work in progress" open=true >}}
|
||||||
|
|
||||||
|
No está completo.
|
||||||
|
|
||||||
|
{{< /admonition >}}
|
||||||
|
|
||||||
|
## ¿Qué es la Autonomía Digital?
|
||||||
|
|
||||||
|
Últimamente se habla mucho de Soberanía Digital y de servicios auto alojados (o _self hosted_). Yo dejaría el término _Soberanía Digital_ para cuestiones que afectan a las naciones o a la Unión Europea en nuestro caso, por que los medios necesarios para alcanzar la Soberanía Digital tendrán que ser transnacionales para hacer frente a las potencias en juego, ya hablemos de paises como China, USA o Rusia, o a empresas como Google, Facebook, Amazon, Microsoft, etc.
|
||||||
|
|
||||||
|
A nivel de individuo, creo que el término _Autonomía Digital_ sería más ajustado.
|
||||||
|
|
||||||
|
Por otro lado, me temo que igual que la Soberanía Digital exige medios a nivel Europeo (como poco), la Autonomía Digital también exige esfuerzos que no están al alcance de todos. Cuanto más aprendo de este tema más convencido estoy que debería organizarse mediante la cooperación de varias personas, seguramente mediante una comunidad de intereses comunes, ya sea una asociación, una cooperativa o la forma que se le quiera dar. Creo que la Autonomía Digital es de interés para cualquiera, pero ciertamente no todos tendrán conocimientos suficientes para implementarla por su cuenta. Un ejemplo de comunidad organizada para procurarse la autonomía digital es [Disroot](https://disroot.org), no he buscado mucho así que es de suponer que habrá más.
|
||||||
|
|
||||||
|
Añadir definición de autonomía digital
|
||||||
|
|
||||||
|
## ¿Por qué?
|
||||||
|
|
||||||
|
Detallar razones. Todo el mundo cita la privacidad como la primera razón para implementar estos servicios de modo auto-alojado.
|
||||||
|
|
||||||
|
## ¿Cómo lo hacemos?
|
||||||
|
|
||||||
|
Vamos a describir como implementaremos nuestro plan de autonomía.
|
||||||
|
|
||||||
|
### Arquitectura: la infraestructura
|
||||||
|
|
||||||
|
En mi caso tengo:
|
||||||
|
|
||||||
|
**Dominio propio con su DNS Zone**
|
||||||
|
|
||||||
|
: Contratado con un proveedor de internet reconocido.
|
||||||
|
|
||||||
|
|
||||||
|
- Correo electrónico subcontratado a un proveeder de buena reputación y que nos permita usar nuestro propio dominio.
|
||||||
|
- VPS
|
||||||
|
- Servicio de almacenamiento local en casa
|
||||||
|
|
||||||
|
### Servicios deseados
|
||||||
|
|
||||||
|
#### Almacenamiento
|
||||||
|
|
||||||
|
Para que queremos
|
||||||
|
|
||||||
|
## Implementación
|
||||||
|
|
||||||
|
### Dominio propio
|
||||||
|
|
||||||
|
### Correo electrónico
|
||||||
|
|
||||||
|
### Almacenamiento
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Referencias
|
||||||
|
|
||||||
|
- <https://github.com/awesome-selfhosted/awesome-selfhosted>
|
||||||
|
- <https://www.rosehosting.com/blog/self-hosted-alternatives/>
|
||||||
|
- <https://selfhosted.show/> No se que es esto
|
||||||
|
- [Veracrypt](https://veracrypt.fr/en/Downloads.html)
|
||||||
|
- [fscrypt](https://github.com/google/fscrypt)
|
||||||
|
- [ecryptfs](https://www.ecryptfs.org/)
|
||||||
|
- [gocryptfs](https://nuetzlich.net/gocryptfs/)
|
||||||
|
- [cryfs](https://www.cryfs.org/)
|
||||||
|
- <https://www.addictivetips.com/ubuntu-linux-tips/best-linux-encryption-tools/>
|
||||||
|
|
||||||
|
### Servicios en la red
|
||||||
|
|
||||||
|
- [disroot](https://disroot.org)
|
||||||
|
- [monocles](https://monocles.de/)
|
||||||
|
|
||||||
|
## Cursos en la Domus
|
||||||
|
|
||||||
|
### Primer curso el dia 10 de marzo de 2023
|
||||||
|
|
||||||
|
- Taller de iniciación a la seguridad digital.
|
||||||
|
- conceptos básicos de seguridad hash, password segura
|
||||||
|
- fortaleza de contraseñas
|
||||||
|
- gestor de contraseñas
|
||||||
|
- mas nociones generales
|
@ -0,0 +1,234 @@
|
|||||||
|
---
|
||||||
|
weight: 4
|
||||||
|
title: "Apuntes de Hugo"
|
||||||
|
date: 2020-04-17T11:52:19+02:00
|
||||||
|
draft: false
|
||||||
|
summary: "Como usar Hugo para hacer un blog en gitlab"
|
||||||
|
categories:
|
||||||
|
- notes
|
||||||
|
tags:
|
||||||
|
- hugo
|
||||||
|
- git
|
||||||
|
- gitlab
|
||||||
|
---
|
||||||
|
Como montar un blog como este, con Hugo
|
||||||
|
|
||||||
|
<!-- more -->
|
||||||
|
|
||||||
|
Hace años que soy consciente de la existencia de las _Github Pages_ y/o las _Gitlab Pages_ Las probé en su momento en [Github](https://github.com/) pero no volví a prestarles atención por falta de tiempo.
|
||||||
|
|
||||||
|
También se desde hace tiempo que hay generadores de sitios web estáticos, en su dia hice algunas pruebas con [Pelican](https://github.com/getpelican/pelican) (basado en Python) y con [Jekill](https://github.com/jekyll/jekyll) pero no llegué a utilizarlos para nada funcional.
|
||||||
|
|
||||||
|
Como ahora tengo tiempo y sentía curiosidad por el tema, he investigado un poco como podría empezar rápido.
|
||||||
|
|
||||||
|
## Hugo: el generador de sitios estáticos
|
||||||
|
|
||||||
|
Un generador de sitios estáticos es un software que a partir de unos ficheros de contenido, y unos ficheros de temas genera un sitio estático completo. Es decir, un sitio web compuesto de htlm, css y nada más.
|
||||||
|
|
||||||
|
Los ficheros de contenido suelen estar escritos en alguna variedad de markdown, org-mode, o algún lenguaje de marcas por el estilo.
|
||||||
|
|
||||||
|
Los temas se suelen encontrar en grandes cantidades en la red, y escritos con distintos objetivos. Hay temas para hacer tu página de presentación personal y dar a conocer tu curriculum, temas para blogs, para galerias de fotos, para publicar documentación, etc. etc.
|
||||||
|
|
||||||
|
El generador se encargará de procesar los ficheros de contenido para generar un sitio web completo con el estilo del tema que escojamos.
|
||||||
|
|
||||||
|
Hay cantidad de generadores de sitios estáticos. Tras investigar un poco (muy poco la verdad) limité mis opciones a dos generadores: [Jekill](https://jekyllrb.com/) y [Hugo](https://gohugo.io/se). Tengo la sensación (totalmente subjetiva) de que Jekill es más potente e intuyo que será más complicado de usar así que he decidido empezar por Hugo.
|
||||||
|
|
||||||
|
Hugo parece sencillo de instalar y de usar y no me ha dado pegas hasta ahora.
|
||||||
|
|
||||||
|
Aquí tienes [una serie de videos](https://www.youtube.com/watch?v=qtIqKaDlqXo&list=PLLAZ4kZ9dFpOnyRlyS-liKL5ReHDcj4G3) cortitos donde se explican todos los detalles de Hugo si te interesan.
|
||||||
|
|
||||||
|
### Instalación de Hugo
|
||||||
|
|
||||||
|
Mi instalación es completamente espartana, me he descargado el paquete binario en su última versión (0.69.0 cuando escribo esto) desde [aquí](https://github.com/gohugoio/hugo/releases) Y he dejado el ejecutable `Hugo` en mi directorio `~/bin`. Nada más, ese directorio ya está en mi `PATH` así que con eso basta para mi.
|
||||||
|
|
||||||
|
{{< admonition warning >}}
|
||||||
|
**Ojo** la primera vez instale el paquete binario _Hugo_ para Linux 64 bit, pero más tarde lo tuve que cambiar por el paquete **Hugo_extended**
|
||||||
|
{{< /admonition >}}
|
||||||
|
|
||||||
|
Una vez instalado Hugo, no está de más hacer [el tutorial](https://gohugo.io/getting-started/quick-start/)
|
||||||
|
|
||||||
|
## Temas para Hugo: Zdoc y Zzo
|
||||||
|
|
||||||
|
Después de hacer el tutorial y algunas pruebas me di una vuelta por [la página de temas de Hugo](https://themes.gohugo.io/). Me interesaba buscar un tema que fuera adecuado para publicar guías algo extensas y que soportara publicar en varios idiomas. Al final escogí el tema [Zdoc](https://themes.gohugo.io/hugo-theme-zdoc/) por que cumplía mis requisitos, parecía muy bien documentado y con un aspecto gráfico que me gustaba. Pero en un momento dado entré en [la página del autor del tema](https://zzodocs.netlify.app) y casí sin darme cuenta me instalé el tema [zzo](https://github.com/zzossig/hugo-theme-zzo) que tampoco está nada mal, y parece más completo incluso que el anterior (con galerias de fotos, reseñas de libros, etc) así que continué con este. De todas formas, sigue pendiente probar el tema Zdoc para algúna guía larga y ver como queda.
|
||||||
|
|
||||||
|
Hay que agradecerle a [Zzossig](https://github.com/zzossig) el currazo que se ha metido creando estos temas.
|
||||||
|
|
||||||
|
### Creación de un site e instalación del tema
|
||||||
|
|
||||||
|
Para usar un tema en nuestro site lo más práctico es hacer un fork del tema original. Por un lado podremos mandarle al autor nuestras contribuciones (en mi caso traducciones nada más) por si le interesa incorporarlas a la distribución oficial del tema. Y por otro lado, si hacemos otras modificaciones del tema las tendremos controladas en nuestro fork.
|
||||||
|
|
||||||
|
Así que:
|
||||||
|
|
||||||
|
1) Creamos un fork del tema original (en github en mi caso)
|
||||||
|
|
||||||
|
2) Creamos un directorio en nuestro ordenador, para todos los ficheros de nuestro sitio estático, de aquí en adelante voy a suponer que nuestro sitio estático se va a llamar "comacero", puedes llamar al directorio como quieras pero yo le voy a llamar simplemente `blog`.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mkdir blog
|
||||||
|
cd blog
|
||||||
|
```
|
||||||
|
|
||||||
|
3) Clonamos nuestro fork del tema elegido en el directorio `blog`, aquí haremos las modificaciones del tema (__ajusta la url a tu fork__)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/zzossig/hugo-theme-zzo
|
||||||
|
```
|
||||||
|
|
||||||
|
4) Creamos el nuevo sitio localmente en nuestro ordenador con Hugo. Lo creamos dentro del directorio `blog`. Puedes llamarlo como quieras, yo lo voy a llamar igual que el sitio que queremos crear (`comacero` para este ejemplo):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mkdir comacero
|
||||||
|
cd comacero
|
||||||
|
hugo new site .
|
||||||
|
|
||||||
|
ls
|
||||||
|
archetypes config.toml content data layouts static themes
|
||||||
|
```
|
||||||
|
|
||||||
|
Ya tenemos el esqueleto de nuestro sitio estático, Hugo se ha encargado de poblarlo con directorios.
|
||||||
|
|
||||||
|
Para usarlo en Gitlab nuestro sitio tiene que ser un repositorio git:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git init
|
||||||
|
echo public > .gitignore
|
||||||
|
git add .gitignore
|
||||||
|
git commit -m "First commit"
|
||||||
|
```
|
||||||
|
|
||||||
|
{{< admonition info >}}
|
||||||
|
Cuando tengamos todo preparado y generemos nuestro sitio en local con Hugo, todo el sitio estático se creará en el directorio `comacero/public`. Pero __no queremos__ que ese directorio suba a Gitlab, es solo para nuestra "vista-previa" del site en local. Por eso lo añadimos al fichero `.gitignore`
|
||||||
|
{{< /admonition >}}
|
||||||
|
|
||||||
|
Tenemos que añadir el tema, así que clonamos **nuestro fork** en la ruta `themes/zzo`
|
||||||
|
|
||||||
|
{{< admonition warning >}}
|
||||||
|
Los _Gitlab Runners_ que son los procesos virtuales que van a generar nuestro sitio en Gitlab, __no pueden__ clonar un repo por ssh. Así que al añadir el tema tienes que hacerlo con un site `https://` o incluso clonar directamente el directorio.
|
||||||
|
{{< /admonition >}}
|
||||||
|
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git submodule add https://github.com/zzossig/hugo-theme-zzo themes/zzo
|
||||||
|
git submodule update --remote --merge
|
||||||
|
```
|
||||||
|
|
||||||
|
Alternativamente **si tenemos nuestro site y nuestro fork del tema** en el mismo directorio `blog` podemos hacer referencia al submódulo con una ruta relativa:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git submodule add ../hugo-theme-zzo themes/zzo
|
||||||
|
git submodule update --remote --merge
|
||||||
|
```
|
||||||
|
|
||||||
|
Pero si optamos por la segunda opción tenemos que ser cuidadosos al subir todo a Gitlab (lo explicamos luego)
|
||||||
|
|
||||||
|
Una vez que tenemos nuestro tema descargado podemos copiar la configuración completa del site de ejemplo que viene con el tema. Desde el directorio donde tenemos nuestro site creado por Hugo, copiamos los ficheros de configuración y contenido del site de ejemplo en el site que hemos creado (que está vacío):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
rm config.toml
|
||||||
|
cp -r themes/zzo/exampleSite/* .
|
||||||
|
```
|
||||||
|
|
||||||
|
Y ya tenemos todo listo para probar, arrancamos el hugo como servidor web:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
hugo -D server
|
||||||
|
```
|
||||||
|
|
||||||
|
Si todo va bien tendríamos que poder conectarnos a `http://localhost:1313` y ver el site de ejemplo.
|
||||||
|
|
||||||
|
#### Configuración del site
|
||||||
|
|
||||||
|
Con el site funcionando podemos retocar los ficheros de configuración `config.toml` y `params.toml` que están en el directorio `config/_default`. Tendremos que adaptar la configuración de idiomas, nombre del sitio generado, etc. etc. en la página web de zzo tenemos instrucciones bien detalladas.
|
||||||
|
|
||||||
|
## Integración con Gitlab Pages
|
||||||
|
|
||||||
|
Como ya comenté, había mirado las páginas de Github y de Gitlab (y también las de Bitbucket) hace algunos años. Incluso había probado algún generador de sitios estáticos para temas del trabajo. Me quedé con ideas preconcebidas (y equivocadas): yo pensaba que toda la generación del sitio la hacías en local y después subias a Gitlab el sitio generado. Es decir, yo pensaba que después de ejecutar Hugo para generar todo el sitio estático en el directorio `public` subias ese contenido generado a Gitlab.
|
||||||
|
|
||||||
|
No es así para nada.
|
||||||
|
|
||||||
|
En Gitlab la generación de sitios estáticos está completamente integrada con el software Gitlab, lo que permite hacer [integración contínua](https://es.wikipedia.org/wiki/Integraci%C3%B3n_continua). Esta es otra asignatura que tengo pendiente así que me vino muy bien para ir aprendiendo. :smile:
|
||||||
|
|
||||||
|
{{< admonition info >}}
|
||||||
|
Si quieres aprender como va el despliegue de sitios estáticos con _Gitlab Pages_ es muy recomendable que leas [la documentación de las Gitlab Pages](https://docs.gitlab.com/ee/user/project/pages/) y que para empezar [crees un site basado en la plantilla html/plain](https://docs.gitlab.com/ee/user/project/pages/getting_started/pages_bundled_template.html) (un template predefinido).
|
||||||
|
{{< /admonition >}}
|
||||||
|
|
||||||
|
Los siguientes pasos serán:
|
||||||
|
|
||||||
|
* Crear nuestro proyecto en Gitlab para subir nuestros ficheros del sitio
|
||||||
|
* Subir todo menos el contenido del directorio `public`
|
||||||
|
* Crear el fichero que le especifica al _runner_ que operaciones tiene que hacer para crear el sitio web
|
||||||
|
|
||||||
|
### Crear nuestro proyecto en Gitlab
|
||||||
|
|
||||||
|
En el disco duro yo tengo una estructura de directorios tal que así:
|
||||||
|
|
||||||
|
{{< mermaid >}}
|
||||||
|
graph TD;
|
||||||
|
blog --> theme_zzo;
|
||||||
|
blog --> comacero;
|
||||||
|
{{< /mermaid >}}
|
||||||
|
|
||||||
|
* En el directorio `comacero` tenemos nuestro site
|
||||||
|
* En el directorio `theme_zzo` tenemos el fork del tema original con nuestras modificaciones.
|
||||||
|
|
||||||
|
En Gitlab he creado una estructura parecida:
|
||||||
|
|
||||||
|
* Un grupo que se llama `comacero`
|
||||||
|
* Un proyecto `comacero.gitlab.io` dentro del grupo `comacero` que almacenará el sitio estático, ligado al directorio `blog/comacero` de mi disco duro
|
||||||
|
* Un proyecto `zzo_hugo_theme` que almacena mi fork del tema original, ligado la directorio `blog/theme_zzo` de mi disco duro
|
||||||
|
|
||||||
|
{{< admonition info >}}
|
||||||
|
Conviene leerse la [documentación de Gitlab](https://docs.gitlab.com/ee/user/project/pages/getting_started_part_one.html#gitlab-pages-default-domain-names) con respecto a los nombres de dominio y su correspondencia con los nombres de proyecto.
|
||||||
|
{{< /admonition >}}
|
||||||
|
|
||||||
|
### Subimos nuestro site a Gitlab
|
||||||
|
|
||||||
|
* En el repo del directorio `blog/comacero` añadimos la url del remoto en Gitlab (`comacero.gitlab.io`) con `git remote set-url`
|
||||||
|
* En el repo del directorio `blog/theme_zzo` tenemos el fork del tema que apunta a un repo de github. Añadimos un remoto adicional apuntando a la url de Gitlab (`zzo_hugo_theme`)
|
||||||
|
* Hacemos un push desde nuestros repos locales hacia Gitlab y ya tenemos los repos preparados.
|
||||||
|
|
||||||
|
|
||||||
|
Para que nuestro repo genere las páginas web tenemos que incluir un fichero con las ordenes que va a ejecutar el _Gitlab runner_.
|
||||||
|
|
||||||
|
### Activar el _runner_ de Gitlab
|
||||||
|
|
||||||
|
Tenemos que crear en la raiz de nuestro repo `comacero.gitlab.io` un fichero `.gitlab-ci.yml` con el siguiente contenido:
|
||||||
|
|
||||||
|
```.gitlab-ci.yml
|
||||||
|
# All available Hugo versions are listed here: https://gitlab.com/pages/hugo/container_registry
|
||||||
|
# image: registry.gitlab.com/pages/hugo:latest
|
||||||
|
image: registry.gitlab.com/pages/hugo/hugo_extended:latest
|
||||||
|
|
||||||
|
variables:
|
||||||
|
GIT_SUBMODULE_STRATEGY: recursive
|
||||||
|
|
||||||
|
test:
|
||||||
|
script:
|
||||||
|
- hugo
|
||||||
|
except:
|
||||||
|
- master
|
||||||
|
|
||||||
|
pages:
|
||||||
|
script:
|
||||||
|
- hugo
|
||||||
|
artifacts:
|
||||||
|
paths:
|
||||||
|
- public
|
||||||
|
only:
|
||||||
|
- master
|
||||||
|
```
|
||||||
|
|
||||||
|
{{< admonition warning >}}
|
||||||
|
Mucho ojo, porque para nuestro tema necesitamos usar hugo-extended y no es fácil encontrar la imagen correcta en Gitlab. Afortunadamente había hecho pruebas con el template que nos da Gitlab para Hugo, y si os fijais en el comentario de la cabecera nos indica en que URL están todas las imágenes disponibles de Hugo.
|
||||||
|
{{< /admonition >}}
|
||||||
|
|
||||||
|
## Final
|
||||||
|
|
||||||
|
Siguiendo estos pasos deberíamos tener nuestro site disponible en la dirección https://comacero.gitlab.io, pero es muy posible que tarde **mucho** en estar disponible después de la creación. Yo tuve que esperar 48 horas antes de poder acceder al site. Aunque ahora las actualizaciones de contenido apenas llevan tiempo. Cuando subo un cambio el site se actualiza en cuestión de minutos.
|
||||||
|
|
||||||
|
|
||||||
|
## Problemas encontrados
|
||||||
|
|
||||||
|
* Si escribes en _Pandoc_ (básicamente lo único que cambia es la extensión: `pdc` en lugar de `md`) **no funcionan** las tablas de contenido (TOC). En cambio se renderizan correctamente los párrafos al margen de los retornos insertados en el editor de texto.
|
||||||
|
|
||||||
|
* Si escribes en _Markdown_ (ver el punto anterior) no puedes poner retornos de linea en el texto fuente (excepto para separar párrafos claro). Parece que Hugo los coserva al renderizar y el texto queda horrible con los retornos de linea insertados.
|
@ -0,0 +1,686 @@
|
|||||||
|
---
|
||||||
|
weight: 4
|
||||||
|
title: "Microprocesadores: apuntes"
|
||||||
|
date: 2023-09-08T12:12:46+0200
|
||||||
|
draft: false
|
||||||
|
summary: "Apuntes de microprocesadores"
|
||||||
|
categories:
|
||||||
|
- notes
|
||||||
|
tags:
|
||||||
|
- ch340
|
||||||
|
- attiny
|
||||||
|
- arduino
|
||||||
|
- platformio
|
||||||
|
- esp32
|
||||||
|
- esp8266
|
||||||
|
- wemos d1
|
||||||
|
- stm32
|
||||||
|
- STM32CubeIDE
|
||||||
|
---
|
||||||
|
|
||||||
|
{{< figure src="/images/microproc/arduinos_a.jpg"
|
||||||
|
title="arduinos"
|
||||||
|
width=300 >}}
|
||||||
|
|
||||||
|
|
||||||
|
## Notas conectando distintos procesadores al portátil y al IDE Arduino
|
||||||
|
|
||||||
|
### Troubleshooting
|
||||||
|
|
||||||
|
Prueba a parar el infame _ModemManager_:
|
||||||
|
|
||||||
|
~~~bash
|
||||||
|
sudo systemctl stop ModemManager
|
||||||
|
~~~
|
||||||
|
|
||||||
|
Si tienes una versión antigua de _brltty_ (`brltty -V` menor que 6.5) puedes probar a parar el servicio:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
systemctl stop brltty-udev.service
|
||||||
|
```
|
||||||
|
|
||||||
|
### attiny
|
||||||
|
|
||||||
|
Es necesario instalar `libusb-0.1-4` en nuestro S.O.
|
||||||
|
|
||||||
|
~~~bash
|
||||||
|
sudo apt install libusb-0.1-4
|
||||||
|
~~~
|
||||||
|
|
||||||
|
También debemos crear el fichero `/etc/udev/rules.d/49-digispark.rules`
|
||||||
|
con el siguiente contenido:
|
||||||
|
|
||||||
|
~~~
|
||||||
|
SUBSYSTEM=="usb", ATTR{idVendor}=="16d0", ATTR{idProduct}=="0753", MODE="0660", GROUP="dialout"
|
||||||
|
~~~
|
||||||
|
|
||||||
|
Una vez hecho esto lo attiny funcionan correctamente, pero son peculiares: hay que lanzar el download desde el arduino IDE con el dispositivo desconectado y conectarlo al puerto usb cuando nos lo indique el IDE.
|
||||||
|
|
||||||
|
Configuración en IDE Arduino
|
||||||
|
|
||||||
|
- **Board**: Digispark (Default - 16.5mhz)
|
||||||
|
- **Port**: No creo que importe
|
||||||
|
- **Programmer**: Micronucleous
|
||||||
|
|
||||||
|
### ch340/ch341
|
||||||
|
|
||||||
|
#### Problemas con ModemManager
|
||||||
|
|
||||||
|
Añadimos además una linea al fichero `99-arduino.rules` que queda así:
|
||||||
|
|
||||||
|
~~~bash
|
||||||
|
# for arduino brand, stop ModemManager grabbing port
|
||||||
|
ATTRS{idVendor}=="2a03", ENV{ID_MM_DEVICE_IGNORE}="1"
|
||||||
|
# for sparkfun brand, stop ModemManager grabbing port
|
||||||
|
ATTRS{idVendor}=="1b4f", ENV{ID_MM_DEVICE_IGNORE}="1"
|
||||||
|
# for ardupilot brand, stop ModemManager grabbing port
|
||||||
|
ATTRS{idVendor}=="2341", ENV{ID_MM_DEVICE_IGNORE}="1"
|
||||||
|
# for ch401, stop ModemManager grabbing port
|
||||||
|
ATTRS{idVendor}=="1a86", ENV{ID_MM_DEVICE_IGNORE}="1"
|
||||||
|
~~~
|
||||||
|
|
||||||
|
Estas reglas como indican los comentarios evitan que _ModemManager_ capture estas marcas de dispositivos.
|
||||||
|
|
||||||
|
#### Problemas con Brltty
|
||||||
|
|
||||||
|
En Linux Mint Vera aparece un nuevo problema: El sistema usa una versión antigua (menor que 6.5) de _Brltty_ (se puede comprobar ejecutando `brltty -V`) En esta versión el _ch340_ es reconocido como un transductor Braille y capturado por el _Brltty_. Si no queremos tener problemas con los Arduino con _ch340_ tenemos que editar el fichero `/usr/lib/udev/rules.d/85-brltty.rules` y comentar la linea que se corresponde con el _Device ID_ del arduino:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Device: 1A86:7523
|
||||||
|
# Baum [NLS eReader Zoomax (20 cells)]
|
||||||
|
# ENV{PRODUCT}=="1a86/7523/*", ENV{BRLTTY_BRAILLE_DRIVER}="bm", GOTO="brltty_usb_run"
|
||||||
|
```
|
||||||
|
|
||||||
|
Puedes recargar las reglas de dispositivos con el comando `sudo udevadm control --reload-rules`
|
||||||
|
|
||||||
|
Otra forma más expeditiva de terminar con el problema es desactivar completamente y para siempre el servicio _brltty_. Yo prefiero dejarlo configurado.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Find-out the service
|
||||||
|
systemctl list-units | grep brltty
|
||||||
|
|
||||||
|
# Mask the service to avoid starting it in the future
|
||||||
|
systemctl mask brltty-udev.service
|
||||||
|
|
||||||
|
# Stop the service now
|
||||||
|
systemctl stop brltty-udev.service
|
||||||
|
```
|
||||||
|
|
||||||
|
### Arduino Nano con ch341
|
||||||
|
|
||||||
|
- **Board**: Arduino Nano
|
||||||
|
- **Processor**: Depende, hay que probar combinaciones de procesador y _bootloader_
|
||||||
|
- **Port**: El que toque (ttyUSBn)
|
||||||
|
- **Programmer**: None
|
||||||
|
|
||||||
|
### Arduino Pro mini
|
||||||
|
|
||||||
|
Hay que usar FTDI adapter, con el mio el cable va plano.
|
||||||
|
|
||||||
|
|Pin Adap. | Pin micro|
|
||||||
|
|--------- | ---------|
|
||||||
|
|3.3v | No usado |
|
||||||
|
|GND | GND |
|
||||||
|
|VBUS | VCC |
|
||||||
|
|TXD | RXI |
|
||||||
|
|RXD | TXO |
|
||||||
|
|DTR | DTR |
|
||||||
|
|
||||||
|
- **Board**: Arduino Pro or Pro mini
|
||||||
|
- **Processor**: atmega328P 5V 16mhz
|
||||||
|
- **Port**: El que toque (ttyUSBn)
|
||||||
|
- **Programmer**: None
|
||||||
|
|
||||||
|
![arduinos](/images/microproc/arduinos_a.jpg)
|
||||||
|
|
||||||
|
### Arduino IDE
|
||||||
|
|
||||||
|
#### Orígenes de bibliotecas configurados en el IDE Arduino
|
||||||
|
|
||||||
|
~~~
|
||||||
|
https://adafruit.github.io/arduino-board-index/package_adafruit_index.json
|
||||||
|
https://github.com/stm32duino/BoardManagerFiles/raw/master/STM32/package_stm_index.json
|
||||||
|
http://dan.drown.org/stm32duino/package_STM32duino_index.json
|
||||||
|
https://dl.espressif.com/dl/package_esp32_index.json
|
||||||
|
http://arduino.esp8266.com/stable/package_esp8266com_index.json
|
||||||
|
http://digistump.com/package_digistump_index.json
|
||||||
|
https://raw.githubusercontent.com/damellis/attiny/ide-1.6.x-boards-manager/package_damellis_attiny_index.json
|
||||||
|
~~~
|
||||||
|
|
||||||
|
### ESP8266
|
||||||
|
|
||||||
|
#### ESP8266 Arduino IDE
|
||||||
|
|
||||||
|
Seguimos [esta
|
||||||
|
página](https://randomnerdtutorials.com/how-to-install-esp8266-board-arduino-ide/)
|
||||||
|
a ver a donde llegamos.
|
||||||
|
|
||||||
|
Añadimos este origen en el IDE Arduino: <http://arduino.esp8266.com/stable/package_esp8266com_index.json>
|
||||||
|
|
||||||
|
Works!! al menos el blink
|
||||||
|
|
||||||
|
La tarjeta que tenemos equipa un ESP-12E
|
||||||
|
|
||||||
|
- **Board**: NodeMCU 1.0 (ESP-12E Module)
|
||||||
|
- **Port**: El que toque (ttyUSBn)
|
||||||
|
|
||||||
|
#### Wemos D1 Lite
|
||||||
|
|
||||||
|
##### Wemos D1 Lite en Arduino IDE
|
||||||
|
|
||||||
|
- **Board**: LOLIN(Wemos) D1 mini Lite (con mi placa)
|
||||||
|
- **Port**: El que toque (ttyUSBn)
|
||||||
|
- Resto de parámetros por defecto
|
||||||
|
|
||||||
|
Funciona sin necesidad de _virtualenv_ ni nada (cargado WifiScan)
|
||||||
|
|
||||||
|
###### Probas
|
||||||
|
|
||||||
|
Vamos a echar un ojo al código que nos propone Andreas Spiess en [este
|
||||||
|
video](https://www.youtube.com/watch?v=G73fiaOpUAc)
|
||||||
|
|
||||||
|
Nos descargamos el repo de ejemplos de
|
||||||
|
[aqui](https://github.com/wemos/D1_mini_Examples) y los programas
|
||||||
|
corregidos por el señor Spiess de
|
||||||
|
[aqui](https://github.com/SensorsIot/Wemos-Shields)
|
||||||
|
|
||||||
|
Aunque tampoco es que consigamos gran cosa mirando esto.
|
||||||
|
|
||||||
|
Vamos a instalar la Biblioteca para el sensor SHT30 descargando de [el
|
||||||
|
github](https://github.com/wemos/WEMOS_SHT3x_Arduino_Library)
|
||||||
|
|
||||||
|
Y con este programilla funciona:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#include <WEMOS_SHT3X.h>
|
||||||
|
|
||||||
|
SHT3X sht30(0x45);
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
|
||||||
|
Serial.begin(115200);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
|
||||||
|
if(sht30.get()==0){
|
||||||
|
Serial.print("Temperature in Celsius : ");
|
||||||
|
Serial.println(sht30.cTemp);
|
||||||
|
Serial.print("Temperature in Fahrenheit : ");
|
||||||
|
Serial.println(sht30.fTemp);
|
||||||
|
Serial.print("Relative Humidity : ");
|
||||||
|
Serial.println(sht30.humidity);
|
||||||
|
Serial.println();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Serial.println("Error!");
|
||||||
|
}
|
||||||
|
delay(1000);
|
||||||
|
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Para probar el OLED instalamos la librería _Adafruit SSD 1306 Wemos
|
||||||
|
mini OLED_ (de Adafruit y mcauser) también necesitamos la _Adafruit GFX_
|
||||||
|
|
||||||
|
**NO FUNCIONA** (creo que me he cargado el OLED)
|
||||||
|
|
||||||
|
|
||||||
|
Biblioteca para MQTT en ESP8266 <https://github.com/knolleary/pubsubclient>
|
||||||
|
|
||||||
|
### ESP32
|
||||||
|
|
||||||
|
|
||||||
|
#### ESP32 Arduino IDE
|
||||||
|
|
||||||
|
Mi placa funciona en el IDE Arduino:
|
||||||
|
|
||||||
|
* Arrancar el IDE desde el virtualenv de PlatformIO (el IDE Arduino necesita pyserial instalado)
|
||||||
|
* **Board**: ESP32 Dev Module
|
||||||
|
* El resto por defecto
|
||||||
|
|
||||||
|
Probar con esto:
|
||||||
|
- <https://diyprojects.io/getting-start-programming-esp32-platformio-ide/#.X3JHm5qxWV4>
|
||||||
|
- Una guía: <https://tttapa.github.io/ESP8266/Chap01%20-%20ESP8266.html>
|
||||||
|
|
||||||
|
#### TTGO T4
|
||||||
|
|
||||||
|
* Instalamos la librería *TFT_eSPI*
|
||||||
|
|
||||||
|
Aparentemente hay que usar el 'ESP32 Dev Module' en el IDE Arduino
|
||||||
|
|
||||||
|
* [Una demo con cryptomonedas](https://github.com/LilyGO/TTGO-T4-DEMO)
|
||||||
|
* [Test code](https://github.com/Xinyuan-LilyGO/LilyGo_Txx)
|
||||||
|
* [Hackaday](https://hackaday.com/2018/05/23/esp32-boards-with-displays-an-overview/)
|
||||||
|
* [Proyectos con Arduino y MicroPython](https://kreier.github.io/t-display/)
|
||||||
|
<!--
|
||||||
|
https://jonstephensonsblog.com/2019/12/06/using-the-ttgo-t-display-board/
|
||||||
|
https://www.youtube.com/watch?v=b8254--ibmM
|
||||||
|
https://sites.google.com/site/jmaathuis/arduino/lilygo-ttgo-t-display-esp32
|
||||||
|
http://pdacontroles.com/revision-modulo-esp32-ttgo-t-display-1-14/
|
||||||
|
https://www.profetolocka.com.ar/series/usando-la-placa-ttgo-t-display-de-lilygo/
|
||||||
|
-->
|
||||||
|
|
||||||
|
Andreas Spies
|
||||||
|
|
||||||
|
* [Hoja comparativa](https://docs.google.com/spreadsheets/d/1Mu-bNwpnkiNUiM7f2dx8-gPnIAFMibsC2hMlWhIHbPQ/edit#gid=0)
|
||||||
|
* [Video comparativo](https://www.youtube.com/watch?v=s12XuR7BJkw)
|
||||||
|
|
||||||
|
Mas cosas:
|
||||||
|
|
||||||
|
* [esta puede ser útil o no](https://github.com/LilyGO/TTGO-T2-SSD1331-SD)
|
||||||
|
* [Y esta igual](https://sites.google.com/site/jmaathuis/arduino/lilygo-ttgo-t-display-esp32)
|
||||||
|
|
||||||
|
#### ESP32-C3
|
||||||
|
|
||||||
|
Para el Arduino IDE instalamos las bibliotecas _latest_ siguiendo las instrucciones de [este enlace](https://docs.espressif.com/projects/arduino-esp32/en/latest/installing.html#windows-manual-installation)
|
||||||
|
|
||||||
|
Basicamente:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mkdir -p ~/Arduino/hardware/espressif && \
|
||||||
|
cd ~/Arduino/hardware/espressif && \
|
||||||
|
git clone https://github.com/espressif/arduino-esp32.git esp32 && \
|
||||||
|
cd esp32/tools && \
|
||||||
|
python3 get.py
|
||||||
|
```
|
||||||
|
|
||||||
|
Reiniciamos el _Arduino IDE_ si estaba arrancado y en el menú de _Boards_ veremos la entrada _ESP32 Arduino (in sketchbook)_ con las últimas versiones de las tarjetas.
|
||||||
|
|
||||||
|
{{< admonition type=warning title="Actualizar ESP32 Arduino (in sketchbook)" open=true >}}
|
||||||
|
|
||||||
|
Es de suponer que estas bibliotecas se actualizan via git,
|
||||||
|
|
||||||
|
{{< /admonition >}}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### STM32 Blue Pill
|
||||||
|
|
||||||
|
Los micros que yo tengo son STM32F103C8T6
|
||||||
|
|
||||||
|
Para programar el _Blue Pill_ desde el _Arduino IDE_ tenemos dos posibles ruta para añadir en nuestras _Arduino Ide Preferences_
|
||||||
|
|
||||||
|
- La de la comunidad stm32duino (ver [el github](https://github.com/rogerclarkmelbourne/Arduino_STM32)): `http://dan.drown.org/stm32duino/package_STM32duino_index.json` esta versión soporta las placas Mapple. Con este origen en el _Board Manager_ de Arduino nos aparecen dos opciones:
|
||||||
|
- __STM32F1xx/GD32F1xx boards by stm32duino__
|
||||||
|
- __STM32F4xx boards by stm32duino__
|
||||||
|
- La que parece oficial de STMicroelectronics:`https://github.com/stm32duino/BoardManagerFiles/raw/main/package_stmicroelectronics_index.json`. Puede comprobarse la dirección [aquí](https://github.com/stm32duino/Arduino_Core_STM32). Con este origen en el _Board Manager_ del IDE nos aparece una opción:
|
||||||
|
- __STM32 MCU based boards by STMicroelectronics__ con soporte para muchísimas placas
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## PlatformIO ##
|
||||||
|
|
||||||
|
Hacemos la instalación de _Platformio_ a través de _VS Code_ como detallamos [en este documento](https://git.comacero.com/salvari/guide_LinuxMint#platformio).
|
||||||
|
|
||||||
|
{{< admonition type=tip title="udev rules" open=true >}}
|
||||||
|
|
||||||
|
En mi ordenador todas las pruebas con distintos micros han funcionado hasta ahora sin problemas con los _udev rules_ que tenía configurados. Pero desde el propio _Platformio_ recomiendan instalar a mayores el fichero [99-platformio-udev.rules](https://github.com/platformio/platformio-core/blob/develop/scripts/99-platformio-udev.rules)
|
||||||
|
|
||||||
|
Para recargar las _udev rules_: `udevadm control --reload-rules && udevadm trigger`
|
||||||
|
|
||||||
|
{{< /admonition >}}
|
||||||
|
|
||||||
|
Una vez que _VS Code_ instala el _Platformio_ tendremos disponible un entorno virtual con las herramientas que se han instalado en `~/.platformio/penv/`. Yo me he creado un alias `mypio` que me permite activar ese entorno virtual, por ejemplo para acceder al _Platformio CLI_.
|
||||||
|
|
||||||
|
|
||||||
|
_Platformio_, por defecto, deja los proyectos en `~/Documents/PlatformIO/Projects`
|
||||||
|
|
||||||
|
Probado con un Arduino Nano y funciona a la primera con VsCode:
|
||||||
|
|
||||||
|
```ini
|
||||||
|
; PlatformIO Project Configuration File
|
||||||
|
;
|
||||||
|
; Build options: build flags, source filter
|
||||||
|
; Upload options: custom upload port, speed and extra flags
|
||||||
|
; Library options: dependencies, extra library storages
|
||||||
|
; Advanced options: extra scripting
|
||||||
|
;
|
||||||
|
; Please visit documentation for the other options and examples
|
||||||
|
; https://docs.platformio.org/page/projectconf.html
|
||||||
|
|
||||||
|
[env:nanoatmega168]
|
||||||
|
platform = atmelavr
|
||||||
|
board = nanoatmega168
|
||||||
|
framework = arduino
|
||||||
|
```
|
||||||
|
|
||||||
|
### ESP32
|
||||||
|
|
||||||
|
#### Framework 'arduino'
|
||||||
|
|
||||||
|
Creamos un nuevo proyecto con
|
||||||
|
|
||||||
|
```ini
|
||||||
|
[env:esp32dev]
|
||||||
|
platform = espressif32
|
||||||
|
board = esp32dev
|
||||||
|
framework = arduino
|
||||||
|
```
|
||||||
|
|
||||||
|
Si es la primera vez que usas el _framework_ (_arduino_ en este caso) tardará un ratillo en descargarlo de internet.
|
||||||
|
|
||||||
|
#### Framework 'ESP-IDF'
|
||||||
|
|
||||||
|
Creamos un nuevo proyecto con:
|
||||||
|
|
||||||
|
```ini
|
||||||
|
[env:esp32dev]
|
||||||
|
platform = espressif32
|
||||||
|
board = esp32dev
|
||||||
|
framework = espidf
|
||||||
|
```
|
||||||
|
|
||||||
|
El código del blink:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#include <driver/gpio.h>
|
||||||
|
#include <freertos/FreeRTOS.h>
|
||||||
|
#include <freertos/task.h>
|
||||||
|
|
||||||
|
#define LED_PIN 2
|
||||||
|
|
||||||
|
void led_blink(void *pvParams) {
|
||||||
|
gpio_pad_select_gpio(LED_PIN);
|
||||||
|
gpio_set_direction (LED_PIN,GPIO_MODE_OUTPUT);
|
||||||
|
while (1) {
|
||||||
|
gpio_set_level(LED_PIN,0);
|
||||||
|
vTaskDelay(1000/portTICK_RATE_MS);
|
||||||
|
gpio_set_level(LED_PIN,1);
|
||||||
|
vTaskDelay(1000/portTICK_RATE_MS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void app_main() {
|
||||||
|
xTaskCreate(&led_blink,"LED_BLINK",512,NULL,5,NULL);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
{{< admonition type=note title="TODOs" open=false >}}
|
||||||
|
|
||||||
|
- [Probar Wemos D1](https://docs.platformio.org/en/latest/boards/espressif8266/d1_mini.html)
|
||||||
|
- [Probar con ESP32](https://docs.platformio.org/en/latest/tutorials/index.html)
|
||||||
|
- [Probar ESP32-S3](https://docs.platformio.org/en/latest/boards/espressif32/esp32-s3-devkitc-1.html#board-espressif32-esp32-s3-devkitc-1)
|
||||||
|
- [ESP32 Wrover](https://docs.platformio.org/en/latest/boards/espressif32/esp-wrover-kit.html#board-espressif32-esp-wrover-kit)
|
||||||
|
- [Wemos D1 and Micropython](https://www.wemos.cc/en/latest/tutorials/index.html)
|
||||||
|
|
||||||
|
{{< /admonition >}}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Referencias ##
|
||||||
|
|
||||||
|
* [PlatformIO samples (github)](https://github.com/platformio/platformio-examples)
|
||||||
|
* [PlatformIO for Arduino, ESP8266, and ESP32 Tutorial (Andreas)](https://www.youtube.com/watch?v=0poh_2rBq7E)
|
||||||
|
* [PlatformIO and Wemos D1](https://www.youtube.com/watch?v=V6bG-UvD54Q)
|
||||||
|
|
||||||
|
|
||||||
|
## Micropython
|
||||||
|
|
||||||
|
{{< admonition type=info title="Referencias Micropython" open=true >}}
|
||||||
|
- [micropython.org](https://micropython.org/)
|
||||||
|
- [Micropython on ESP32](https://bhave.sh/micropython-urequests/)
|
||||||
|
- [Run Micropython on Docker Container](https://bhave.sh/micropython-docker/)
|
||||||
|
{{< /admonition >}}
|
||||||
|
|
||||||
|
### Instalación del editor Thonny
|
||||||
|
|
||||||
|
Para poder usar la biblioteca Tkinter en cualquier entorno virtual parece que tenemos que tener instalado el paquete `python3-tk` en nuestro sistema.
|
||||||
|
|
||||||
|
En principio nos dicen que Thonny viene con Python 3.7 incluido, pero para Linux no parece que traiga ningún Python. Thonny arrancará usando el Python por defecto del entorno virtual que creemos, pero nos dejará seleccionar otras versiones si las ve disponibles. De momento creamos el entorno virtual para Thonny con la última versión disponible (en _pyenv_) de Python 3.7
|
||||||
|
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo apt install python3-tk # Asegurate de tener esto instalado
|
||||||
|
|
||||||
|
pyenv install 3.7.13 # Instalamos el último python 3.7
|
||||||
|
pyenv virtualenv 3.7.13 ve_thonny # creamos el entorno virtual
|
||||||
|
|
||||||
|
mkdir ~/work/thonny # creamos un directorio de trabajo
|
||||||
|
cd ~/work/thonny
|
||||||
|
pyenv local ve_thony # asignamos un ve al directorio
|
||||||
|
pip install thonny # instalamos thonny
|
||||||
|
thonny # y lo arrancamos
|
||||||
|
```
|
||||||
|
|
||||||
|
### MicroPython con las Raspberry Pi Pico
|
||||||
|
|
||||||
|
Para instalar el MicroPython en nuestra Pico necesitamos que se monte como un dispositivo de almacenamiento externo. Si viene directa de fábrica es el comportamiento por defecto, de lo contrario tenemos que:
|
||||||
|
|
||||||
|
* Desconectar el USB de la Pico del ordenador
|
||||||
|
* Con el USB desconectado pulsamos el boton de _Boot Select_ en la Pico y sin soltarlo la conectamos por USB al ordenador
|
||||||
|
* Mantenemos el botón pulsado tres segundos y soltamos, deberíamos ver la Pico montada como almacenamiento externo
|
||||||
|
|
||||||
|
Ahora basta con descargar el fichero UF2 de MicroPython desde [la página oficial](https://www.raspberrypi.com/documentation/microcontrollers/micropython.html) y dejar una copia en el sistema de ficheros de la Pico, en cuanto tenga el fichero descargado se reiniciará y ejecutará el MicroPython
|
||||||
|
|
||||||
|
Una vez tengamos la Pico conectada y ejecutando el Python podemos usar el editor _Thonny_ para conectarnos a ella, basta con arrancar el edito y en la opcion `Run::Select Interpreter` escoger la opción `MicroPython (Raspberry Pi Pico)`, con eso ya estaremo conectados al interprete de la Pico y podremos ejecutar programas (Hay que salvarlos en la Pico, el editor te dejará escoger donde quieres salvarlos)
|
||||||
|
|
||||||
|
#### T-Pico C3
|
||||||
|
|
||||||
|
- [Github site from Xinyuan Lilygo](https://github.com/Xinyuan-LilyGO/T-PicoC3)
|
||||||
|
- [Report on CNX](https://www.cnx-software.com/2022/05/02/lilygo-t-picoc3-board-merges-rp2040-esp32-c3-integrates-color-display/ )
|
||||||
|
|
||||||
|
|
||||||
|
## STM32 y el entorno STM32CubeIDE
|
||||||
|
|
||||||
|
{{< admonition type=info title="Referencias" open=true >}}
|
||||||
|
|
||||||
|
- [STM32F1xxxx Reference Manual (pdf)](https://www.st.com/content/ccc/resource/technical/document/reference_manual/59/b9/ba/7f/11/af/43/d5/CD00171190.pdf/files/CD00171190.pdf/jcr:content/translations/en.CD00171190.pdf)
|
||||||
|
- [STM32F4xxxx Reference Manual (pdf)](https://www.st.com/resource/en/reference_manual/rm0090-stm32f405415-stm32f407417-stm32f427437-and-stm32f429439-advanced-armbased-32bit-mcus-stmicroelectronics.pdf)
|
||||||
|
- [USB intro en la wiki de st.com](https://wiki.st.com/stm32mcu/wiki/Introduction_to_USB_with_STM32)
|
||||||
|
- [Una página con algunas referencias a distintas placas con micros STM32](https://stm32-base.org/)
|
||||||
|
|
||||||
|
{{< /admonition >}}
|
||||||
|
|
||||||
|
|
||||||
|
De momento solo estoy probando la BluePill con STLink V2 (chino). Las BluePill que tengo yo llevan el micro F103C8T6
|
||||||
|
|
||||||
|
Instalamos el STM32CubeIDE con la opción de paquetes `.deb`
|
||||||
|
|
||||||
|
{{< admonition type=tip title="Programar con STLink V2" open=true >}}
|
||||||
|
|
||||||
|
Para cualquier proyecto de STM32 donde queramos programar el micro
|
||||||
|
usando el _ST Link V2_, siempre tenemos que configurar el _debugger_
|
||||||
|
desde la opción `System Core::sys::` tenemos que asegurarnos de que:
|
||||||
|
- `Debug: Serial Wire`
|
||||||
|
- `Timebase Source: SysTick`
|
||||||
|
|
||||||
|
{{< /admonition >}}
|
||||||
|
|
||||||
|
### Programando un Blink
|
||||||
|
|
||||||
|
Configuramos el pin 13 (corresponde al pin de usuario) como `output` no le ponemos nada a mayores. Si optamos por ponerle una etiqueta, p. ej. `LEDUSER` podemos hacer referencia a la etiqueta en el código.
|
||||||
|
|
||||||
|
{{< admonition type=warning title="Bloques de código" open=true >}}
|
||||||
|
|
||||||
|
Es **IMPORTANTE** insertar nuestro código en los bloques señalados por comentarios, por que de lo contrario, si cambiamos algo en la configuración del micro y regeneramos el código lo que no esté en los bloques marcados se eliminará automáticamente.
|
||||||
|
|
||||||
|
{{< /admonition >}}
|
||||||
|
|
||||||
|
|
||||||
|
```c
|
||||||
|
/* USER CODE BEGIN WHILE */
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
HAL_Delay(1000);
|
||||||
|
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, 0);
|
||||||
|
HAL_Delay(1000);
|
||||||
|
// Otra solución
|
||||||
|
HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
|
||||||
|
HAL_Delay(1000);
|
||||||
|
// Usando etiquetas de GPIO
|
||||||
|
HAL_GPIO_TogglePin(LEDUSER_GPIO_Port, LEDUSER_Pin);
|
||||||
|
HAL_Delay(1000);
|
||||||
|
|
||||||
|
/* USER CODE END WHILE */
|
||||||
|
/* USER CODE BEGIN 3 */
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### STM32 USB-CDC
|
||||||
|
|
||||||
|
|
||||||
|
**¡Ojo!** además de configurar correctamente el USB, es decir, activarlo en la sección de _Connectivity_ y configurar correctamente el reloj para poder dar señal al USB, tendremos que añadir el _Middleware_ que nos interese (en este ejemplo usamos _Virtual Port COM_ )
|
||||||
|
|
||||||
|
También tendremos que hacer un `#include "usbd_cdc_if.h"` en la sección correspondiente a los _Private Includes_ de nuestro `main.c`.
|
||||||
|
|
||||||
|
Sección de _includes_:
|
||||||
|
|
||||||
|
```c
|
||||||
|
/* Private includes ----------------------------------------------------------*/
|
||||||
|
/* USER CODE BEGIN Includes */
|
||||||
|
#include "usbd_cdc_if.h"
|
||||||
|
/* USER CODE END Includes */
|
||||||
|
```
|
||||||
|
|
||||||
|
Sección del programa:
|
||||||
|
|
||||||
|
```c
|
||||||
|
/* Infinite loop */
|
||||||
|
/* USER CODE BEGIN WHILE */
|
||||||
|
uint8_t txBuffer[] = {'H', 'o', 'l', 'a', '\n'};
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
CDC_Transmit_FS(txBuffer, 5);
|
||||||
|
HAL_Delay(100);
|
||||||
|
|
||||||
|
/* USER CODE END WHILE */
|
||||||
|
|
||||||
|
/* USER CODE BEGIN 3 */
|
||||||
|
}
|
||||||
|
/* USER CODE END 3 */
|
||||||
|
```
|
||||||
|
|
||||||
|
Si cargamos el programa y conectamos la _Blue Pill_ al usb de nuestro ordenador (yo desconecto previamente el stlink) podremos comprobar que estamos recibiendo con:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cat /dev/ttyACM0
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## PlatformIO
|
||||||
|
|
||||||
|
### Instalando el Espressif SDK
|
||||||
|
|
||||||
|
- Abrimos VS code
|
||||||
|
- Abrimos el Platformio
|
||||||
|
- Nuevo proyecto
|
||||||
|
- Escogemos **Espressif ESP32 Dev** como _board_
|
||||||
|
- Escogemos **ESP-IDF** como _framework_
|
||||||
|
|
||||||
|
Con esto conseguiremos que el módulo _Platformio_ descargue el _framework_ de Espressif en el directorio `~/.platformio/packages/framework-espidf`
|
||||||
|
|
||||||
|
<!-- https://docs.platformio.org/en/latest/tutorials/espressif32/espidf_debugging_unit_testing_analysis.html#tutorial-espressif32-espidf-debugging-unit-testing-analysis -->
|
||||||
|
|
||||||
|
## Experimentos con el ESP32
|
||||||
|
|
||||||
|
<!--
|
||||||
|
https://emariete.com/cargador-bateria-esp8266-esp32-bien-hecho/
|
||||||
|
-->
|
||||||
|
|
||||||
|
|
||||||
|
## Conversores usb ttl ##
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### CP2102 5PIN ###
|
||||||
|
|
||||||
|
1. tamaño de PCB: 26,5mm * 15,6mm
|
||||||
|
2. PCB Color: rojo
|
||||||
|
3. Peso: 4g
|
||||||
|
4. Uso del nuevo chip CP2102
|
||||||
|
5. Con fusible reajustable. En el caso de cortocircuito accidental
|
||||||
|
puede proteger eficazmente su dispositivo y el puerto USB del
|
||||||
|
ordenador para descargar
|
||||||
|
6. Con tres leds: Indicador de potencia, recepción de datos del
|
||||||
|
indicador, indicador de transmisión de datos, estado del trabajo de
|
||||||
|
un vistazo
|
||||||
|
7. 3,3 V y 5V con dos salidas de potencia
|
||||||
|
8. Todos los pines de plomo útiles
|
||||||
|
9. Con la salida de señal de reinicio puede ser directamente Pro mini
|
||||||
|
y otra tarjeta Arduino para descargar!
|
||||||
|
10. Sistemas operativos compatibles:
|
||||||
|
|
||||||
|
- Windows 98 / Me / 2000 / XP / 7
|
||||||
|
- MAC OS-9
|
||||||
|
- MAC OS
|
||||||
|
- X-Windows CE
|
||||||
|
- Linux 2,40 o posterior
|
||||||
|
|
||||||
|
### PL2303HX ###
|
||||||
|
|
||||||
|
Características:
|
||||||
|
|
||||||
|
* Controlador importado RS232 TTL, que puede estabilizar el flash con alta velocidad
|
||||||
|
* Fusible de autorecuperación de 500mA para protección
|
||||||
|
* Dos indicadores de transmisión de datos pueden monitorizar el estado de la transferencia de datos en tiempo real
|
||||||
|
* Reserve interfaz de pin de 3,3 V y 5V, fácil para el DDWRT de diferentes sistemas de voltaje que necesitan energía
|
||||||
|
* La placa entera está recubierta por una manga termoretráctil transparente de alta calidad, haciendo que la PCB esté aislada desde el exterior,
|
||||||
|
* Para que la tabla no se queme con Un corte corto de material.
|
||||||
|
* Paquete electrostático, asegura que la placa no se dañará antes de su uso
|
||||||
|
* Apoyo WIN7 sistema
|
||||||
|
|
||||||
|
Especificaciones:
|
||||||
|
|
||||||
|
* Dimensión: about50x15x7mm
|
||||||
|
* Peso neto: 5g
|
||||||
|
* Peso del paquete: 15g
|
||||||
|
* Color: azul el pin con muchísimas patitas
|
||||||
|
|
||||||
|
### USB a TTL CH340G ###
|
||||||
|
|
||||||
|
|
||||||
|
Características:
|
||||||
|
|
||||||
|
* USB incorporado al chip de transferencia TTL.
|
||||||
|
* Diseñado para ser utilizado para proyectos electrónicos USB a TTL.
|
||||||
|
* Salida de interfaz TTL, fácil de conectar a su MCU.
|
||||||
|
* LED de estado
|
||||||
|
* Salida de potencia Dual de 3,3 V y 5V, funciona con dispositivos de 3,3v y 5v.
|
||||||
|
* Tamaño: 55mm * 16mm
|
||||||
|
* ¿Servidor 2008/Win7/Win8 32 bits / 64 bits?
|
||||||
|
|
||||||
|
1. soporte de WINDOWS 98/ME/2000/XP/Server 2003/VISTA/
|
||||||
|
2. 3 V3 y 5V por una selección de riesgo de cortocircuito;
|
||||||
|
3. No solo tiene led de alimentación PWR, también hay indicador TXD y
|
||||||
|
RXD, si el producto es fácil de aprender e intuitivo de trabajar en
|
||||||
|
la ausencia delinstrumento en la caja;
|
||||||
|
4. pin amarillo de alta calidad, pin duradero que el mercado negro, hermoso;
|
||||||
|
5. Nuevos chips CH340G originales, los chips se recomiendan USB
|
||||||
|
oficial a los chips TTL no aparecerán debido a diferentes
|
||||||
|
controladores/diferentes ordenadores como resultado de
|
||||||
|
incompatibilidades.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
CH340/módulo interruptor USB TTL/Transferencia USB RS232/sobre PL2303/ downloader/ 9 cepillo Junta STC oficial descargar chip Perfectamente compatible con todas las Series MCU no será debido a los diferentes controladores que conduzcan a problemas como PL2303 no puede descargar el programa. Ultra-estable
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Referencias ##
|
||||||
|
|
||||||
|
### Cursos:
|
||||||
|
|
||||||
|
* esp-32:
|
||||||
|
- [idf-esp framework course](https://learnesp32.com/) 17 horas y media de video. El curso tiene muy buena pinta pero vale 50 eurazos.
|
||||||
|
- [ESP32 and PlatformIO IoT Project](https://www.udemy.com/course/esp32-platformio/) By Dalmaris parece muy orientado a la nube y con Platformio, son 10 horas de video
|
||||||
|
- [MicroPython with the ESP32](https://www.udemy.com/course/micropython-with-the-esp32/) By Dalmaris 10 horas y media de videos acerca de Micropython en esp32.
|
||||||
|
- [Deepbluembedded](https://deepbluembedded.com/esp32-programming-tutorials/) Una colección de cursos que parecen basados en el Arduino IDE
|
||||||
|
- [IoT Application Development with the ESP32 Using the ESP-IDF](https://www.udemy.com/course/iot-application-development-with-the-esp32-using-the-esp-idf/) by Kevin Aguilar (ocho horas de video) Un curso avanzado de uso del ESP-IDF y FreeRTOS, pero parece que depende/usa el AWS de Amazon.
|
||||||
|
- [ESP32 for Arduino Makers](https://www.udemy.com/course/esp32-for-arduino-makers/) Curso con Arduino IDE by Dalmaris, tal vez no sea tan malo
|
||||||
|
|
||||||
|
* stm-32
|
||||||
|
- [De Arduino a STM32 (by Tutoelectro)](https://www.youtube.com/watch?v=E8JpLtMlokw&list=PL1Hs_F1k2mdTwlGSv7lglkF_LtY0125OB)
|
||||||
|
|
||||||
|
|
||||||
|
### Referencias Generales ###
|
||||||
|
|
||||||
|
* [Smart health connected devices](https://www.absmarthealth.com/how-to-diy-smart-health-connected-objects/)
|
||||||
|
* [Zephir project RTOS by The Linux Foundation](https://docs.zephyrproject.org)
|
@ -0,0 +1,88 @@
|
|||||||
|
---
|
||||||
|
weight: 4
|
||||||
|
title: "Apuntes de Odoo"
|
||||||
|
date: 2022-04-19T11:35:38+0200
|
||||||
|
draft: false
|
||||||
|
summary: "Notas de Odoo un CRM de software libre"
|
||||||
|
categories:
|
||||||
|
- notes
|
||||||
|
tags:
|
||||||
|
- crm
|
||||||
|
- odoo
|
||||||
|
- python
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
{{< admonition type=danger title="Work in Progress" open=true >}}
|
||||||
|
|
||||||
|
Estos apuntes **NO ESTÁN ACABADOS** son sólo para uso personal.
|
||||||
|
|
||||||
|
{{< /admonition >}}
|
||||||
|
|
||||||
|
## ¿Qué es Odoo?
|
||||||
|
|
||||||
|
## Instalación de Odoo 15.0 en Linux Mint Una
|
||||||
|
|
||||||
|
Básicamente he seguido las indicaciones de la documentación oficial de la version 15.0 que podemos ver [aquí](https://www.odoo.com/documentation/15.0/administration/install/install.html#id7).
|
||||||
|
|
||||||
|
- Yo he optado por hacer un fork en mi github y clonar desde mi fork
|
||||||
|
- Además he creado un _virtualenv_ con pyenv para ejecutar Odoo
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mkdir odooTest
|
||||||
|
pyenv virtualenv 3.9.6 ve_odooTest
|
||||||
|
pyenv local ve_odooTest
|
||||||
|
my_ve # Esto instala mis bibliotecas básicas de python y el pylsp
|
||||||
|
git clone git@github.com:salvari/odoo.git
|
||||||
|
```
|
||||||
|
|
||||||
|
Debemos comprobar que tenemos instaladas las dependencias básicas de nuestro SO:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo apt install python3-dev libxml2-dev libxslt1-dev libldap2-dev libsasl2-dev \
|
||||||
|
libtiff5-dev libjpeg8-dev libopenjp2-7-dev zlib1g-dev libfreetype6-dev \
|
||||||
|
liblcms2-dev libwebp-dev libharfbuzz-dev libfribidi-dev libxcb1-dev libpq-dev
|
||||||
|
```
|
||||||
|
|
||||||
|
Y dentro de nuestro _virtualenv_ instalar las dependencias Python de Odoo:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd odooTest/odoo
|
||||||
|
pyenv which pip # para asegurarnos de donde estamos
|
||||||
|
pip install -r ./requirements.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
Yo tengo ya instalado en mi sistema _wkhtmltopdf_
|
||||||
|
|
||||||
|
Necesitamos la base de datos _Postgress_, yo la voy a instalar aislada en un contenedor Docker, así que en nuestro linux instalamos sólo el cliente:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo apt install postgresql-client
|
||||||
|
docker pull postgres
|
||||||
|
docker volume create postgres-data
|
||||||
|
docker run -d --name postgres-server -p 5432:5432 -v postgres-data:/var/lib/postgresql/data -e "POSTGRES_PASSWORD=la_password" postgres
|
||||||
|
```
|
||||||
|
|
||||||
|
Una vez instalada con nuestro cliente podemos conectarnos y crear el usuario para Odoo:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
psql -h 127.0.0.1 -U postgres
|
||||||
|
create database odoodb;
|
||||||
|
create user odoo with encrypted password 'odoopass';
|
||||||
|
grant all privileges on database odoodb to odoo;
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
Ya tenemos ***Odoo*** instalado y la base de datos con su usuario dedicado preparada en nuestro _Postgresql_ así que podemos arrancar el servidor (asegúrate de tener el _virtualenv_ activo):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
/odoo-bin --addons=./addons --db_host=127.0.0.1 --db_user=odoo --database=odoodb --db_password=odooPass
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
El usuario por defecto para hacer login es `admin` con password `admin`. Deberíamos crear otro usuario administrador cuanto antes y borrar el que viene por defecto.
|
||||||
|
|
||||||
|
|
||||||
|
## Referencias
|
||||||
|
|
||||||
|
- Odoo Developer Tutorials: [Getting Started](https://www.odoo.com/documentation/15.0/developer/howtos/rdtraining/01_architecture.html)
|
@ -0,0 +1,300 @@
|
|||||||
|
---
|
||||||
|
weight: 4
|
||||||
|
title: "Apuntes: org-mode en Emacs"
|
||||||
|
date: 2020-12-17T10:19:04+0100
|
||||||
|
draft: false
|
||||||
|
summary: "Aprendiendo a usar org-mode"
|
||||||
|
categories:
|
||||||
|
- notes
|
||||||
|
tags:
|
||||||
|
- emacs
|
||||||
|
- org-mode
|
||||||
|
---
|
||||||
|
|
||||||
|
Apuntes **no terminados** sobre Emacs y org-mode
|
||||||
|
|
||||||
|
<!--more-->
|
||||||
|
|
||||||
|
{{< admonition type=warning title="Work in progress" open=true >}}
|
||||||
|
Estos apuntes no están completos, (ni de lejos)
|
||||||
|
{{< /admonition >}}
|
||||||
|
|
||||||
|
|
||||||
|
_org-mode_ es un invento de [Carsten Dominik](https://staff.fnwi.uva.nl/c.dominik/). Mr. Carsten lo inventó como un método para implementar GTD, pero poco a poco lo fue refinando añdiendo _Emacs Calc_ y _org-babel_. A partir de ahí no ha parado de mejorar.
|
||||||
|
|
||||||
|
## Esquema básico con cabeceras
|
||||||
|
|
||||||
|
Lo primero que te encuentras en _org-mode_ es un esquema basado en cabeceras:
|
||||||
|
|
||||||
|
* Cada cabecera empieza con uno (o varios) caracteres *
|
||||||
|
* Pulsando `Tab` en la linea de cabecera se colapsa o expande esa
|
||||||
|
sección
|
||||||
|
* Pulsando `S-Tab` en cualquier parte del documento se cambia el
|
||||||
|
estado colapsado/expandido en todo el documento
|
||||||
|
* Pulsando `Alt` (que llamamos `Meta` en Emacs) y las flechas derecha
|
||||||
|
e izquierda en una linea de cabecera cambiamos el nivel de la
|
||||||
|
cabecera
|
||||||
|
* Pulsado `M-Up` o `M-Down` en una linea de cabecera la cambiamos de
|
||||||
|
posición en el documento
|
||||||
|
* La combinación `C-c C-w` en una cabecera nos permite cambiarla de
|
||||||
|
rama (interactivo)
|
||||||
|
|
||||||
|
|
||||||
|
## Listas de Tareas
|
||||||
|
|
||||||
|
Cualquier cabecera puede marcarse como `TODO` o `DONE` (son las
|
||||||
|
opciones por defecto), basta con presionar `S-right` o `S-left` en la
|
||||||
|
linea de cabecera para ir cambiando de estado. Alternativamente puedes
|
||||||
|
usar `C-c C-t` para poner un estado interactivamente (más rápido)
|
||||||
|
|
||||||
|
Si necesitamos algo más sofisticado podemos añadir estados en la
|
||||||
|
cabecera de nuestro fichero `.org`
|
||||||
|
|
||||||
|
Los estados a la izquierda del _pipe_ son `TODO`, y a la derecha son
|
||||||
|
`DONE`
|
||||||
|
|
||||||
|
```org-mode
|
||||||
|
#+SEQ_TODO: Next(n) TODO(t) Waiting(w) Someday(s) | DONE(d) CANCELLED(c)
|
||||||
|
```
|
||||||
|
|
||||||
|
Si cambias las lineas de configuración en la cabecera, puedes recargar
|
||||||
|
el `local setup` con `C-c C-c` (en la cabecera)
|
||||||
|
|
||||||
|
### Agendar tareas
|
||||||
|
|
||||||
|
Para agendar (_schedule_) una tarea usamos `C-c C-s`, en la linea de
|
||||||
|
_schedule_ podemos añadir una hora o un periódo:
|
||||||
|
|
||||||
|
```org-mode
|
||||||
|
SCHEDULED: <2020-10-15 Thu 16:00>
|
||||||
|
SCHEDULED: <2020-10-15 Thu 16:00-17:00>
|
||||||
|
```
|
||||||
|
|
||||||
|
En `org-mode` normalmente se considera que la fecha `SCHEDULED` es el momento en que se debe **empezar** con la tarea.
|
||||||
|
|
||||||
|
Si queremos definir la fecha en la que la tarea debe estar **realizada** usamos `DEADLINE` que se define de forma análoga a `SCHEDULED` con la combinación `C-c C-d`
|
||||||
|
|
||||||
|
En generál en `org-mode` las fechas entre ángulos son fechas _activas_ y las fechas entre corchetes son _informativas_, una vista de tarea podría ser:
|
||||||
|
|
||||||
|
```org-mode
|
||||||
|
** TODO [2021-03-15 Mon] Probar Caddy :hometask:
|
||||||
|
SCHEDULED: <2021-03-20 Sat> DEADLINE: <2021-03-21 Sun>
|
||||||
|
:PROPERTIES:
|
||||||
|
:Effort: 2:00
|
||||||
|
:Beat: Now
|
||||||
|
:END:
|
||||||
|
```
|
||||||
|
|
||||||
|
Donde tenemos una fecha de captura de la tarea (informativa) y las fechas de `SCHEDULED` y `DEADLINE` (activas).
|
||||||
|
|
||||||
|
|
||||||
|
### Vista de agenda
|
||||||
|
|
||||||
|
Nuestro fichero o ficheros `.org` pueden tener distintas tareas con fechas asignadas pero no estarán ordenados cronológicamente.
|
||||||
|
|
||||||
|
Para una visión cronológica disponemos de las _Agenda Views_.
|
||||||
|
|
||||||
|
Para acceder a las vistas de agenda usamos: `C-c a` y después seleccionamos la vista deseada. **Recuerda** si usamos un prefijo `C-u n` justo antes de `C-c a` limitaremos a `n` dias las vistas de agenda.
|
||||||
|
|
||||||
|
Dentro de la vista agenda, podemos activar el _Follow mode_ con `S-f` para que la vista del fichero se mueva a la tarea señalada en la
|
||||||
|
agenda. También podemos usar las teclas `f` y `b` para movernos adelante,atrás (p.ej. en la agenda semanal cambiaríamos a semana anterior
|
||||||
|
o siguiente)
|
||||||
|
|
||||||
|
Por defecto el margen de aviso para tareas con `DEADLINE` es de 14 dias, pero se puede configurar en la variable `org-deadline-warning-days`
|
||||||
|
|
||||||
|
### Agenda Advance
|
||||||
|
- `C-c a` Agenda
|
||||||
|
- Se puede limitar a n dias con prefijo: `C-u n` P.ej. para ver las task para hoy pulsamos `C-u 1 C-c a`
|
||||||
|
- Si seleccionamos `a` entramos en la agenda, con el prefijo podemos limitar a n dias
|
||||||
|
- Con `t` vamos a la lista de tareas podemos filtrar más siguiendo instrucciones
|
||||||
|
- Con `T` vamos a la lista de tareas con una o varias palabras clave especiales (p.ej. `TODO|NEXT`)
|
||||||
|
- Con `m` podemos seleccionar un TAG y más criterios. P. ej.
|
||||||
|
`phone+TODO="NEXT"`. Con la mayúscula `M` restringimos a tareas
|
||||||
|
`TODO`
|
||||||
|
- Con `s` podemos buscar una palabra en todas las tareas (buscará en
|
||||||
|
cabecera y contenido de la tarea). Si usámos la mayúscula `S`
|
||||||
|
restringimos a las tareas `TODO`
|
||||||
|
|
||||||
|
Ejemplos
|
||||||
|
- `+mini +docker` todas las tareas que contengan las dos palabras: `mini` y `docker`
|
||||||
|
- `{regexp}` las regexp van entre llaves
|
||||||
|
|
||||||
|
### Vistas de agenda "a medida"
|
||||||
|
|
||||||
|
```elisp
|
||||||
|
(setq org-agenda-custom-commands
|
||||||
|
'(("c" "Desk Work" tags-todo "computer" ;; (1) (2) (3) (4)
|
||||||
|
((org-agenda-files '("~/org/widgets.org" "~/org/clients.org")) ;; (5)
|
||||||
|
(org-agenda-sorting-strategy '(priority-up effort-down))) ;; (5) cont.
|
||||||
|
("~/computer.html")) ;; (6)
|
||||||
|
;; ...other commands here
|
||||||
|
))
|
||||||
|
```
|
||||||
|
|
||||||
|
En la primera linea tenemos el atajo (1), el título de la búsqueda
|
||||||
|
(2), el criterio de búsqueda, `tags-todo` (3) y la cadena que queremos
|
||||||
|
buscar `"computer"`
|
||||||
|
|
||||||
|
En la segunda linea (5) podemos poner restricciones y/o condiciones a
|
||||||
|
nuestra búsqueda, en este caso restringimos los ficheros a buscar y en
|
||||||
|
que orden mostramos los resultados.
|
||||||
|
|
||||||
|
En la sexta linea especificamos que esta busqueda se exportaria al
|
||||||
|
fichero `~/computer.html` en el caso de que hiciésemos una exportación
|
||||||
|
de la agenda.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Tareas repetitivas
|
||||||
|
|
||||||
|
Podemos hacer las tareas repetitivas añadiendo la especificación de
|
||||||
|
repetición a la fecha _schedule_:
|
||||||
|
|
||||||
|
- `+1w` Repetir en una semana (w, d, m, y)
|
||||||
|
- `++1w` Siguiente repetición en una semana, pero asegurate que sea en
|
||||||
|
el futuro. Esto nos garantiza que la repetición se programa bien en
|
||||||
|
el caso de que completemos la tarea con retraso
|
||||||
|
- `.+1w` Una semana después de marcarla como realizada
|
||||||
|
|
||||||
|
|
||||||
|
### Checklist
|
||||||
|
|
||||||
|
- `- [ ]` como esta
|
||||||
|
- `M-S-enter` genera una nueva entrada en la checklist
|
||||||
|
- `C-c C-c` cambia el estado de la linea
|
||||||
|
- Con [/] o [%] podemos ver el estado del avance de la lista de checklists
|
||||||
|
|
||||||
|
## Tags
|
||||||
|
- `C-c C-q` para añadir Tags
|
||||||
|
- Pueden ser predefinidas `#+TAGS: PHONE(p) COMPUTER(c) GARAGE(g)`
|
||||||
|
- Con `Tab` podemos teclear un tag no predefinido
|
||||||
|
- En mi caso para borrar todos los tag puedo user `C-q C-j enter`
|
||||||
|
- Las etiquetas (Tags) se heredan, aunque no las veas las etiquetas se
|
||||||
|
heredan en las ramas
|
||||||
|
|
||||||
|
## Drawers (o cajones)
|
||||||
|
|
||||||
|
Podemos definir un _drawer_ con una sintáxis (`:drawer_name:`) muy parecida a la de una etiqueta (_tag_). Pero los _drawers_ no van en la primera linea (como las etiquetas) y se terminan con un `:END:`
|
||||||
|
|
||||||
|
Los _drawers_ son también plegables, así que podemos usarlos como un nivel más de plegado dentro de la etiqueta. Pero los más utilizados son los predefinidos `:PROPERTIES:` y `LOGBOOK`
|
||||||
|
|
||||||
|
En el cajón de `:PROPERTIES:` se guardan las propiedades que vayamos añadiendo a nuestra entrada en el fichero `.org`
|
||||||
|
|
||||||
|
En el cajón de `:LOGBOOK:` se guardan las notas de progreso o cambios de estado de nuestra entrada.
|
||||||
|
|
||||||
|
### Log. Notas asociadas al `:LOGBOOK:`
|
||||||
|
- `C-c C-z` Para escribir una nota asociada a una entrada, la cerramos con `C-c C-c`
|
||||||
|
Podemos configurar si las notas se guardan en un _drawer_ o no con las opciones
|
||||||
|
- En la cabecera: `#+STARTUP: logdrawer / nologdrawer`
|
||||||
|
- Añadiendo a una rama la _Property_: `LOG_INTO_DRAWER`
|
||||||
|
|
||||||
|
### Registrando los cambios de estado
|
||||||
|
|
||||||
|
Cuando especificamos los estados en la cabecera podemos especificar que hacer al entrar y salir del estado.
|
||||||
|
|
||||||
|
```org-mode
|
||||||
|
#+SEQ_TODO: Next(n) TODO(t@/!) Waiting(w) Someday(s) | DONE(d) CANCELLED(c)
|
||||||
|
```
|
||||||
|
|
||||||
|
`@` implica grabar un timestamp y una nota al entrar en el estado
|
||||||
|
`!` implica un timestamp al salir del estado
|
||||||
|
`#+STARTUP: logdone` Graba timestamp al pasar de un estado `TODO` a un estado `CLOSE`
|
||||||
|
|
||||||
|
También hay opciones para grabar los reschedules `org-log-reschedule`
|
||||||
|
|
||||||
|
## Archivado
|
||||||
|
|
||||||
|
Las tareas se pueden archivar internamente (sin quitarlas de su fichero `.org` original) o moviéndolas a un fichero externo.
|
||||||
|
|
||||||
|
El archivado interno supone pegar una etiqueta `:ARCHIVE:` con la combinación `C-c C-x a`. Una tarea archivada ya no aparecerá en las vistas de la agenda.
|
||||||
|
|
||||||
|
Para el archivado externo podemos configurar el fichero de destino de varias maneras:
|
||||||
|
|
||||||
|
* Definiendo un fichero de archivo en la cabecera con, por ejemplo (valor por defecto), `#+ARCHIVE: %s_archive::`, donde `%s` es el nombre de nuestro fichero `.org`
|
||||||
|
* Definiendo un fichero de archivo en una rama con:
|
||||||
|
|
||||||
|
```org-mode
|
||||||
|
:PROPERTIES:
|
||||||
|
:ARCHIVE: <archiveName>::* <headSection>
|
||||||
|
:END:
|
||||||
|
```
|
||||||
|
|
||||||
|
* Definiendo los objetivos de archivado a nivel global con la variable `org-refile-targets` que permite establecer una lista de ficheros objetivo. Esta sería una manera _indirecta_ de archivar tareas. Ya que no es una operación de archivo propiamente dicha
|
||||||
|
|
||||||
|
Para las dos primeras opciones el atajo de teclado sería `C-c$` para activar el archivado.
|
||||||
|
|
||||||
|
Para la última opción invocaríamos __refile__ con el atajo `C-c C-w`
|
||||||
|
|
||||||
|
## Fórmulas matemáticas
|
||||||
|
|
||||||
|
Si especificamos la opción
|
||||||
|
|
||||||
|
```orgmode
|
||||||
|
#+STARTUP entitiespretty
|
||||||
|
```
|
||||||
|
|
||||||
|
Se renderizarán las entidades LaTeX (probar a escribir por ejemplo: `\alpha + \beta`)
|
||||||
|
|
||||||
|
La opción `C-c C-x C-l` invoca a `org-toggle-latex-preview`
|
||||||
|
|
||||||
|
El paquete `org-fragtog` parece muy interesante para esto.
|
||||||
|
|
||||||
|
## Links
|
||||||
|
|
||||||
|
* [Guia](https://orgmode.org/orgguide.pdf)
|
||||||
|
* [Youtube List](https://www.youtube.com/watch?v=15w3I6MwCfs&list=PLVtKhBrRV_ZkPnBtt_TD1Cs9PJlU0IIdE&index=2)
|
||||||
|
* [Tutorials](https://orgmode.org/worg/org-tutorials/)
|
||||||
|
* [Mastering emacs](https://www.masteringemacs.org/)
|
||||||
|
|
||||||
|
### Revisar
|
||||||
|
|
||||||
|
* [org-math](https://github.com/dryman/org-math) como tomar apuntes de matemáticas en _org-mode_
|
||||||
|
* [Latex for the impatients](https://karthinks.com/software/latex-input-for-impatient-scholars/): como teclear LaTeX rápido.
|
||||||
|
* [org-clock-remainder](https://github.com/inickey/org-clock-reminder): un módulo para configurar avisos en `org-mode`
|
||||||
|
* [Use org-mode to create LaTeX documents](https://opensource.com/article/20/4/emacs-org-mode)
|
||||||
|
* [Una serie de artículos con configuraciones de Emacs](https://lucidmanager.org/productivity/more-productive-with-emacs/)
|
||||||
|
* [Ricing Emacs](https://lucidmanager.org/productivity/ricing-org-mode/)
|
||||||
|
* Fniessen /org-mode html themes/
|
||||||
|
* [cheatsheet](https://github.com/fniessen/refcard-org-mode)
|
||||||
|
* [Repo in github](https://github.com/fniessen/org-html-themes)
|
||||||
|
* Olmon /org-mode html themes collection/
|
||||||
|
* [la página](https://olmon.gitlab.io/org-themes/)
|
||||||
|
* el [repo](https://gitlab.com/OlMon/org-themes/) en gitlab
|
||||||
|
|
||||||
|
## chuleta de comandos
|
||||||
|
|
||||||
|
##### Esquema básico
|
||||||
|
|
||||||
|
| Atajo | Entorno | Significado |
|
||||||
|
|:-------------------|:-----------|:------------------------|
|
||||||
|
| `Tab` | Cabecera | Colapsa/Expande |
|
||||||
|
| `S-Tab` | Cualquiera | Colap/Exp. Global |
|
||||||
|
| `M-right`/`M-left` | Cabecera | Sección cambia de nivel |
|
||||||
|
| `M-Up`/`M-Down` | Cabecera | Sección cambia posición |
|
||||||
|
| `C-c C-w` | Cabecera | Sección cambia de rama |
|
||||||
|
|
||||||
|
|
||||||
|
##### Lista de tareas
|
||||||
|
|
||||||
|
| Atajo | Entorno | Significado |
|
||||||
|
|:-------------------|:-------------|:-----------------------------|
|
||||||
|
| `S-Right`/`S-Left` | Cabecera | Ciclar estado 'todo' |
|
||||||
|
| `C-c C-t` | Cabecera | Cambiar estado 'todo' |
|
||||||
|
| `C-s` | Cabecera | Agendar tarea |
|
||||||
|
| `C-d` | Cabecera | _Deadline_ |
|
||||||
|
| `C-c a` | Cualquiera | Vista de agenda (int.) |
|
||||||
|
| `S-f` | Vista Agenda | Act./Desactiva _follow mode_ |
|
||||||
|
| `f`/`b` | Vista Agenda | Adelante atrás |
|
||||||
|
| `q` | Vista Agenda | Salir de agenda |
|
||||||
|
|
||||||
|
###### checklist
|
||||||
|
|
||||||
|
| Atajo | Entorno | Significado |
|
||||||
|
|:------------|:----------------|:------------|
|
||||||
|
| `C-S-enter` | Añade una linea | |
|
||||||
|
|
||||||
|
##### Misc
|
||||||
|
|
||||||
|
| Atajo | Entorno | Significado |
|
||||||
|
|:----------|:--------|:--------------------------------|
|
||||||
|
| `C-c C-c` | Varios | "Ejecutar"" esa linea o sección |
|
@ -0,0 +1,691 @@
|
|||||||
|
---
|
||||||
|
weight: 4
|
||||||
|
title: "Apuntes de Proxmox VE"
|
||||||
|
date: 2022-03-23T20:02:31+0100
|
||||||
|
draft: false
|
||||||
|
summary: "Apuntes de Proxmox VE"
|
||||||
|
categories:
|
||||||
|
- notes
|
||||||
|
tags:
|
||||||
|
- proxmox
|
||||||
|
- docker
|
||||||
|
- traefik
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
Estos apuntes son de _Proxmox VE_ un gestor de virtualizaciones muy potente implementado sobre Debian 11 Bullseye en la versión actual, la
|
||||||
|
7.1-11 en el momento de escribir esto.
|
||||||
|
|
||||||
|
(Actualizado el 2022-03-23)
|
||||||
|
<!--more-->
|
||||||
|
|
||||||
|
# Proxmox VE
|
||||||
|
|
||||||
|
_Promox VE_ es un software libre producto de _Proxmox Technologies_; una empresa austríaca que suministra productos de software libre (obvio). _Proxmox VE_, _Proxmox Backup Server_ y _Proxmox Mail Gateway_, como vemos en [su página web](https://www.proxmox.com)
|
||||||
|
|
||||||
|
{{< admonition type=abstract title="Referencias" open=true >}}
|
||||||
|
|
||||||
|
- [Blog de drivemeca](https://drivemeca.blogspot.com/2017/06/el-servidor-perfecto-proxmox-ve.html)
|
||||||
|
|
||||||
|
{{< /admonition >}}
|
||||||
|
|
||||||
|
|
||||||
|
## Motivación
|
||||||
|
|
||||||
|
Inicialmente configuré el mini-PC (Beelink Gemini T4) con Debian Server y Docker para poder implementar micro-servicios e instalar _Home Assistant_ (dockerizado).
|
||||||
|
|
||||||
|
Como sentía curiosidad por ver como funciona la versión _Supervised_ de HAss (_Home Assistant_) empecé a mirar opciones para manejar máquinas virtuales en un servidor _headless_. Estudié la posibilidad de instalar Qemu, pero lo descarté por que tiene dependencias con Xorg que no me convencen. Varias personas me han hablado maravillas de _Proxmox_ y como tengo toda la instalación del mini-pc bien documentada y con copias de seguridad me he decidido a cambiar a _Proxmox_. Al fin y al cabo es saltar desde Debian a Debian con Proxmox, no debería ser muy traumático.
|
||||||
|
|
||||||
|
## Instalación de Proxmox
|
||||||
|
|
||||||
|
Preparamos un USB con _Etcher_ con la ISO descargada de la [página web](https://www.proxmox.com/en/downloads)
|
||||||
|
|
||||||
|
Arrancamos el minipc desde el USB (pulsando `F7`) y lanzamos la
|
||||||
|
instalación. Durante la instalación sólo he tenido que configurar:
|
||||||
|
|
||||||
|
__Parámetros de LVM__
|
||||||
|
|
||||||
|
El disco SSD del minipc es de 256Gb
|
||||||
|
|
||||||
|
`Filesystem`
|
||||||
|
: Escogemos `ext4`
|
||||||
|
|
||||||
|
`hdsize`
|
||||||
|
: Lo fija el instalador autmáticamente
|
||||||
|
|
||||||
|
`swapsize`
|
||||||
|
: Lo he fijado a 16Gb (creo que es mala idea en un SSD, si vemos que empieza a tirar de swap habrá que plantearse quitarla)
|
||||||
|
|
||||||
|
`maxroot`
|
||||||
|
: escogí 60Gb, este es el tamaño de la partición `root` que tendrá
|
||||||
|
formato `ext4`
|
||||||
|
|
||||||
|
`minfree`
|
||||||
|
: la parte del disco que quedará disponible sin usar, he dejado reservados 60Gb
|
||||||
|
|
||||||
|
`maxvz`
|
||||||
|
: sería el límite máximo para el LVM `data` lo he puesto a 200 para
|
||||||
|
que no limite, todo el disco menos los segmentos especificados en
|
||||||
|
las opciones anteriores será usado para `data`
|
||||||
|
|
||||||
|
__Parámetros de Red__
|
||||||
|
|
||||||
|
Especificamos la IP, el nombre del servidor (con dominio, aunque te lo puedes inventar claro) y el DNS
|
||||||
|
|
||||||
|
__Timezone__
|
||||||
|
|
||||||
|
Especificamos en que zona horaria estamos.
|
||||||
|
|
||||||
|
Con esto se completa la instalación y el sistema se reiniciará.
|
||||||
|
|
||||||
|
Una vez reiniciado el sistema podremos conectarnos al PVE via web.
|
||||||
|
|
||||||
|
También podemos conectarnos via _ssh_. Como tengo muchas claves generadas para distintas conexiones en mi ordenador, si nos conectamos sin más nos dará error de exceso de intentos (probará todas las claves). Para las primeras conexiones tendremos que usar:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ssh -o PreferredAuthentications=password root@<proxmox_ip> 25
|
||||||
|
```
|
||||||
|
|
||||||
|
## Postinstalación
|
||||||
|
|
||||||
|
Lo primero que tenemos que hacer, terminada la instalación es ajustar los orígenes del software y actualizar todos los paquetes. Es decir, lo que se hace siempre en una instalación de Debian.
|
||||||
|
|
||||||
|
Cambiamos el origen de sw `pve-enterprise` por el `pve-no-subscription` (a menos que queramos alguna de las opciones de pago de _Proxmox_ que sería lo recomendable en un entorno de producción).
|
||||||
|
|
||||||
|
Comentamos la linea en el fichero `/etc/apt/sources.list.d/pve-enterprise.list`
|
||||||
|
|
||||||
|
Y creamos un nuevo fichero:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
echo "deb http://download.proxmox.com/debian/pve buster pve-no-subscription" > /etc/apt/sources.list.d/pve-no-suscription.list
|
||||||
|
```
|
||||||
|
|
||||||
|
En el fichero `/etc/apt/sources.list` cambiamos los orígenes de software de Debian, e incluimos `contrib` y `non-free`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
deb http://deb.debian.org/debian/ buster main contrib non-free
|
||||||
|
deb-src http://deb.debian.org/debian/ buster main contrib non-free
|
||||||
|
|
||||||
|
deb http://security.debian.org/debian-security buster/updates main contrib non-free
|
||||||
|
deb-src http://security.debian.org/debian-security buster/updates main contrib non-free
|
||||||
|
|
||||||
|
# buster-updates, previously known as 'volatile'
|
||||||
|
deb http://deb.debian.org/debian/ buster-updates main contrib non-free
|
||||||
|
deb-src http://deb.debian.org/debian/ buster-updates main contrib non-free
|
||||||
|
```
|
||||||
|
|
||||||
|
Actualizamos todos los paquetes con:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
apt update
|
||||||
|
apt upgrade
|
||||||
|
```
|
||||||
|
|
||||||
|
Podemos actualizar todos los paquetes de _Proxmox_ con el comando
|
||||||
|
`pveam update`, o hacerlo desde el interfaz gráfico, que es más
|
||||||
|
ilustrativo para las primeras veces (lo vemos luego)
|
||||||
|
|
||||||
|
Una vez actualizado el sistema operativo procedemos a instalar nuestros paquetes habituales.
|
||||||
|
|
||||||
|
### Instalamos _git_ y _etckeeper_
|
||||||
|
|
||||||
|
Suelo instalar _etckeeper_ para tener un histórico automático de cambios en el `/etc`
|
||||||
|
|
||||||
|
Como `root` ejecutamos:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
apt install git
|
||||||
|
git config --global user.email "whaterver@mail.com"
|
||||||
|
git config --global user.name "Name Surname"
|
||||||
|
apt install etckeeper
|
||||||
|
```
|
||||||
|
|
||||||
|
Si quieres ver el histórico de cambios de `/etc` solo tienes que ejecutar como `root`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /etc
|
||||||
|
git log
|
||||||
|
```
|
||||||
|
|
||||||
|
{{< admonition type=tip title="Problemas con default locales" open=false >}}
|
||||||
|
|
||||||
|
Si (como a mi) te dan problemas los `locales` (suele pasar en la instalación de _Debian Server_ veras que `apt` y `apt-get` protestan por la configuración de `locales`) se puede arreglar fácilmente sin más que ejecutar `sudo dpkg-reconfigure locales` Puedes aprovechar la ejecución para dejar generado algún `locale` adicional.
|
||||||
|
|
||||||
|
Estos son los que yo he dejado configurados en mi server (se pueden consultar con el comando `locale`):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
## Antes de la reconfiguración
|
||||||
|
LANGUAGE = (unset),
|
||||||
|
LC_ALL = (unset),
|
||||||
|
LC_MONETARY = "es_ES.UTF-8",
|
||||||
|
LC_ADDRESS = "es_ES.UTF-8",
|
||||||
|
LC_TELEPHONE = "es_ES.UTF-8",
|
||||||
|
LC_NAME = "es_ES.UTF-8",
|
||||||
|
LC_MEASUREMENT = "es_ES.UTF-8",
|
||||||
|
LC_IDENTIFICATION = "es_ES.UTF-8",
|
||||||
|
LC_NUMERIC = "es_ES.UTF-8",
|
||||||
|
LC_PAPER = "es_ES.UTF-8",
|
||||||
|
LANG = "en_US.UTF-8"
|
||||||
|
|
||||||
|
## Después de la reconfiguración
|
||||||
|
LANG=en_US.UTF-8
|
||||||
|
LANGUAGE=
|
||||||
|
LC_CTYPE="en_US.UTF-8"
|
||||||
|
LC_NUMERIC=es_ES.UTF-8
|
||||||
|
LC_TIME="en_US.UTF-8"
|
||||||
|
LC_COLLATE="en_US.UTF-8"
|
||||||
|
LC_MONETARY=es_ES.UTF-8
|
||||||
|
LC_MESSAGES="en_US.UTF-8"
|
||||||
|
LC_PAPER=es_ES.UTF-8
|
||||||
|
LC_NAME=es_ES.UTF-8
|
||||||
|
LC_ADDRESS=es_ES.UTF-8
|
||||||
|
LC_TELEPHONE=es_ES.UTF-8
|
||||||
|
LC_MEASUREMENT=es_ES.UTF-8
|
||||||
|
LC_IDENTIFICATION=es_ES.UTF-8
|
||||||
|
LC_ALL=
|
||||||
|
```
|
||||||
|
|
||||||
|
{{< /admonition >}}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Varios programas instalados en Debian 10
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
__OJO__: `apt` instala por defecto los paquetes recomendados, si no
|
||||||
|
quieres que eso ocurra usa `apt-get` o `aptitude` con las opciones
|
||||||
|
correspondientes.
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
Instalamos varias librerías de compresión:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
apt install rar unrar zip unzip unace bzip2 lzop p7zip p7zip-full
|
||||||
|
```
|
||||||
|
|
||||||
|
Instalamos algunas utilidades:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
apt install most mc tree neofetch tmux aptitude htop
|
||||||
|
```
|
||||||
|
|
||||||
|
Instalamos sudo:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
apt install sudo
|
||||||
|
```
|
||||||
|
|
||||||
|
Cualquier usuario que pertenezca al grupo `sudo` podrá ejecutar
|
||||||
|
comandos con privilegios de _root_. (podemos añadirlos, por ejemplo, con `gpasswd -a <username> sudo`)
|
||||||
|
|
||||||
|
### Configuramos el acceso via _ssh_
|
||||||
|
|
||||||
|
El PVE incluye su propio cortafuegos. Tendremos que revisar su configuración más tarde.
|
||||||
|
|
||||||
|
#### Creamos un usuario de administración
|
||||||
|
|
||||||
|
Me voy a crear un usuario de administración para no tener que hacer login con `root`. El usuario va a estar en el grupo `sudo` así que va a ser todopoderoso, pero tendrá que saber su password para poder "sudar".
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# sudo adduser administrator
|
||||||
|
# sudo gpasswd -a administrator sudo
|
||||||
|
$ adduser --uid=1111 hostadmin
|
||||||
|
gpasswd -a hostadmin sudo
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
#### Parámetros de login _ssh_
|
||||||
|
|
||||||
|
Vamos a:
|
||||||
|
|
||||||
|
* Deshabilitar el login de root via ssh (queremos que todos entren con
|
||||||
|
su usuario persona y después usen sudo)
|
||||||
|
* Deshabilitar el login con contraseña (queremos que todo el mundo use
|
||||||
|
autenticación por clave pública)
|
||||||
|
|
||||||
|
Lo primero de todo es configurar y probar nuestro acceso con clave ssh, copiamos nuestra clave al servidor, debemos copiarla tanto para el usuario `root` como para el usuario administrador que hayamos creado:
|
||||||
|
|
||||||
|
`ssh-copy-id -o IdentitiesOnly=yes -i ~/.ssh/mykey.pub <username>@<proxmox_ip>`
|
||||||
|
|
||||||
|
Y probamos a conectarnos con la clave.
|
||||||
|
|
||||||
|
`ssh -i ~/.ssh/mykey <username>@<proxmox_ip>`
|
||||||
|
|
||||||
|
Si todo va bien podemos añadir (en nuestro pc, no en el servidor _Proxmox_) la información de conexión a nuestro fichero `~/.ssh/config`
|
||||||
|
|
||||||
|
```cfg
|
||||||
|
Host <hostname>
|
||||||
|
HostName <ip_address>
|
||||||
|
User <username>
|
||||||
|
Port 22
|
||||||
|
IdentityFile ~/.ssh/<mykey>
|
||||||
|
```
|
||||||
|
|
||||||
|
El fichero que controla la configuración del demonio _ssh_ en nuestro
|
||||||
|
servidor es `/etc/ssh/sshd_config` tenemos que asegurarnos de añadir
|
||||||
|
las siguientes lineas:
|
||||||
|
|
||||||
|
```cfg
|
||||||
|
PermitRootLogin no
|
||||||
|
PasswordAuthentication no
|
||||||
|
ChallengeResponseAuthentication no
|
||||||
|
UsePAM no
|
||||||
|
```
|
||||||
|
|
||||||
|
Después de cambiar la configuración reiniciamos el servicio con `sudo
|
||||||
|
systemctl restart ssh`
|
||||||
|
|
||||||
|
Tras el reinicio no deberíamos poder hacer login con `root` via ssh.
|
||||||
|
|
||||||
|
#### _ssh-agent_
|
||||||
|
|
||||||
|
Esto es un apunte uso para trabajar cómodo con Gitlab desde el servidor _Proxmox_, con las claves _ssh_ instaladas en el servidor.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
eval `ssh-agent`
|
||||||
|
ssh-add .ssh/dev_rsa
|
||||||
|
ssh-add -l
|
||||||
|
ssh-add -L
|
||||||
|
```
|
||||||
|
|
||||||
|
### Disco duro interno
|
||||||
|
|
||||||
|
{{< admonition type=info title="Referencias de HDD" open=false >}}
|
||||||
|
|
||||||
|
- [Opciones para `ext4`](https://man7.org/linux/man-pages/man5/ext4.5.html)
|
||||||
|
- [Un buen resumen](https://www.howtogeek.com/444814/how-to-write-an-fstab-file-on-linux/)
|
||||||
|
- [Filtrar discos del LVM](https://forum.proxmox.com/threads/disk-prevent-from-spinning-down-because-of-pvestatd.53237/)
|
||||||
|
- [Crear un servicio systemd con las optimizaciones](https://unix.stackexchange.com/questions/80437/how-can-i-run-an-hdparm-command-after-boot-and-resume-on-fedora-19)
|
||||||
|
|
||||||
|
{{< /admonition >}}
|
||||||
|
|
||||||
|
|
||||||
|
En mi caso el disco duro interno que quiero añadir está mapeado en `/dev/sda`, se trata de un disco de 2Tb y queremos hacer dos particiones: una para almacenar backups, templates, snapshots, etc. etc. Y otra partición (mucho más grande) que usaremos para crear discos para las VM.
|
||||||
|
|
||||||
|
Con nuestro programa de particionado favorito creamos las dos particiones. Yo tengo disponibles `fdisk` y `parted` pero nada impide instalar el que nos guste.
|
||||||
|
|
||||||
|
He creado una partición de 250 Gb para almacenamiento y el resto de la capacidad para discos de VM.
|
||||||
|
|
||||||
|
#### Creando el "directorio"
|
||||||
|
|
||||||
|
Navegamos hasta nuestra máquina host debajo del `Datacenter` localizamos el interfaz `Disks::Directory` y creamos el nuevo directorio apuntando a la partición que hemos creado en el paso anterior (`/dev/sda1` en mi caso), con el sistema de ficheros que nos guste (lo he dejado como ext4) y le damos un nombre descriptivo (para mi `hdd_directory`).
|
||||||
|
|
||||||
|
#### Creado el volumen lógico
|
||||||
|
|
||||||
|
Navegamos a `LVM` debe estar muy cerca, por encima de `Directory`. Seleccionamos el botón `Create Volume Group`: sólo tenemos que especificar la partición a utilizar y un nombre. Y eso es todo ya tenemos un VG donde podremos crear discos para nuestras máquinas virtuales.
|
||||||
|
|
||||||
|
|
||||||
|
### Discos duros USB externos
|
||||||
|
|
||||||
|
Si son discos nuevos ejecutamos estos pasos
|
||||||
|
1. Conectamos los discos al mini-pc
|
||||||
|
1. Comprobamos los discos con `lsblk -p |grep disk` o con `sudo fdisk -l`
|
||||||
|
1. Si es necesario los podemos formatear a _ext4_ con el comando `sudo mkfs.ext4 /dev/sdX` (donde X será la letra que corresponda a nuestros discos)
|
||||||
|
1. Creamos el/los puntos de montaje de nuestros discos, p.ej. `/mnt/usbA`, con el comando `sudo mkdir /mnt/usbA`
|
||||||
|
1. Montamos el/los discos con el comando `sudo mount /dev/sdX /mnt/usbA`
|
||||||
|
|
||||||
|
Para dejar los discos duros mapeado permanentemente en nuestro servidor debemos modificar el fichero `/etc/fstab`:
|
||||||
|
|
||||||
|
1. Averiguamos la identidad de los discos con `sudo blkid`
|
||||||
|
2. Añadimos las lineas correspondientes al fichero `/etc/fstab` que serán de esta forma (cambia los UUID):
|
||||||
|
|
||||||
|
```fstab
|
||||||
|
UUID=1a716b79-b39a-49bf-bae6-4992376022e0 /mnt/usbA ext4 defaults 0 2
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Discos duros externos que no dejan de funcionar
|
||||||
|
|
||||||
|
Mis discos duros externos son un par de discos USB portátiles, dudo mucho que puedan estar funcionando continuamente.
|
||||||
|
|
||||||
|
_Proxmox_ escanea continuamente todos los discos duros del sistema. Si queremos que los discos duros se duerman tenemos que cambiar la configuración en el fichero `/etc/lvm/lvm.conf`. Concretamente cambiamos la linea:
|
||||||
|
|
||||||
|
`global_filter = [ "r|/dev/sd(b|c)|" , "r|/dev/zd.*|", "r|/dev/mapper/pve-.*|" "r|/dev/mapper/.*-(vm|base)--[0-9]+--disk--[0-9]+|"]`
|
||||||
|
|
||||||
|
Con la primera entrada (`"r|/dev/sd(b|c)|"`) estamos indicando que se ignore los discos `/dev/sdb` y `/dev/sdc`. Con esto perdemos también la posibilidad de crear volúmenes _lvm_ en estos discos, pero a mi de momento no me interesa.
|
||||||
|
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
### _dynhost_ en OVH
|
||||||
|
|
||||||
|
Instalado [el script de actualización de dynhost](https://github.com/BorisPAING/dynhost-ovh) en OVH.
|
||||||
|
|
||||||
|
Es necesario tener disponible `dig` así que instalamos:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo apt install dnsutils
|
||||||
|
```
|
||||||
|
|
||||||
|
Después basta con programar el *script* periódicamente en el crontab
|
||||||
|
de `root` con las credenciales de OVH.
|
||||||
|
|
||||||
|
### Comprobamos la instalación de python
|
||||||
|
|
||||||
|
```bash
|
||||||
|
apt install python-all-dev python3-all-dev
|
||||||
|
apt install virtualenv python3-virtualenv virtualenvwrapper
|
||||||
|
```
|
||||||
|
|
||||||
|
### Instalado el zsh
|
||||||
|
|
||||||
|
Lo he dejado instalado siguiendo [la guía](https://gitlab.com/salvari/linuxmint_ulyana_20).
|
||||||
|
|
||||||
|
|
||||||
|
## Revisión de la instalación de Proxmox
|
||||||
|
|
||||||
|
* Nos conectamos al interfaz web con el usuario `root` y la contraseña que hemos establecido durante la instalación.
|
||||||
|
* Clicamos en nuestro nodo (el servidor en el árbol de la izquierda) y comprobamos las actualizaciones pendientes (_Updates_)
|
||||||
|
|
||||||
|
## Instalación de una máquina virtual con Home Assistant
|
||||||
|
|
||||||
|
{{< admonition type=info title="Referencias" open=false >}}
|
||||||
|
|
||||||
|
- [Install HAss on Proxmox](https://community.home-assistant.io/t/installing-home-assistant-os-using-proxmox-7/201835) (by Kanga-Who)
|
||||||
|
|
||||||
|
{{< /admonition >}}
|
||||||
|
|
||||||
|
Una de las misiones principales de mi servidor Proxmox es soportar la VM de Homeassistant. Crear la máquina virtual es muy fácil gracias a los scripts creados por _Whiskerz007_ y _Kanga-Who_. Vamos a seguir la página de este último.
|
||||||
|
|
||||||
|
Antes de arrancar la VM conviene revisar el hardware asignado y las opciones de la VM (yo solo tuve que ajustar la memoria asignada)
|
||||||
|
|
||||||
|
|
||||||
|
## Instalación de Docker
|
||||||
|
|
||||||
|
{{< admonition type=info title="Referencias" open=false >}}
|
||||||
|
|
||||||
|
- [Running Docker on Proxmox](https://danthesalmon.com/running-docker-on-proxmox/)
|
||||||
|
|
||||||
|
{{< /admonition >}}
|
||||||
|
|
||||||
|
|
||||||
|
Tendríamos tres formas de instalar Docker en nuestro sistema _Proxmox_
|
||||||
|
|
||||||
|
- Instalándolo en el S.O. Debian base
|
||||||
|
- Como contenedor LXC
|
||||||
|
- Como máquina virtual
|
||||||
|
|
||||||
|
Mi intención era usar el primer método e instalar el _Docker_ sobre Debian. Este método no debería usarse nunca en producción pero para el uso que yo quiero darle parece aceptable. Lo he instalado aunque, de momento, dejo el servicio _Docker_ desactivado.
|
||||||
|
|
||||||
|
El segundo método que he usado es crear una máquina virtual con _Alpine Linux_ e instalar _Docker_ sobre esa máquina.
|
||||||
|
|
||||||
|
### Instalar Docker en Debian
|
||||||
|
|
||||||
|
Vamos allá
|
||||||
|
|
||||||
|
```bash
|
||||||
|
apt update
|
||||||
|
apt install apt-transport-https ca-certificates curl gnupg2 software-properties-common
|
||||||
|
add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/debian $(lsb_release -cs) stable"
|
||||||
|
apt-key adv --keyserver ha.pool.sks-keyservers.net --recv-keys 7EA0A9C3F273FCD8
|
||||||
|
apt update
|
||||||
|
apt-cache policy docker-ce
|
||||||
|
apt install docker-ce
|
||||||
|
|
||||||
|
systemctl status docker
|
||||||
|
|
||||||
|
gpasswd -a username docker
|
||||||
|
```
|
||||||
|
|
||||||
|
Y ya tenemos docker instalado.
|
||||||
|
|
||||||
|
Ahora completamos con la instalación de _docker-compose_.
|
||||||
|
|
||||||
|
Primero comprobamos la versión. En el momento de escribir esto es la
|
||||||
|
1.28.5. Con el siguiente comando descargamos el binario
|
||||||
|
correspondiente a nuestro sistema en `/usr/local/bin` y le damos
|
||||||
|
permisos de ejecución.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -L https://github.com/docker/compose/releases/download/1.28.5/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
|
||||||
|
chmod +x /usr/local/bin/docker-compose
|
||||||
|
```
|
||||||
|
|
||||||
|
Para parar el servicio _Docker_ y dejarlo desactivado (con los alias de zsh):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
scs docker # systemctl status docker
|
||||||
|
scsp docker # systemctl stop docker
|
||||||
|
scd docker # systemctl disable docker
|
||||||
|
scs docker # systemctl status docker
|
||||||
|
```
|
||||||
|
|
||||||
|
### Instalar Docker en una máquina virtual
|
||||||
|
|
||||||
|
{{< admonition type=info title="Referencias" open=false >}}
|
||||||
|
|
||||||
|
- [How to install docker on Alpine Linux VM](https://nubcakes.net/index.php/2019/03/15/how-to-install-docker-on-alpine-linux-vm/)
|
||||||
|
- [How to install Docker CE on Alpine Linux](https://www.how2shout.com/how-to/how-to-install-docker-ce-on-alpine-linux.html)
|
||||||
|
- [Alpine Linux Wiki: Docker](https://wiki.alpinelinux.org/wiki/Docker)
|
||||||
|
- [Howto Alpine Wall](https://wiki.alpinelinux.org/wiki/How-To_Alpine_Wall)
|
||||||
|
|
||||||
|
{{< /admonition >}}
|
||||||
|
|
||||||
|
|
||||||
|
* Descargamos la imagen ISO de Alpine optimizada para sistemas virtuales desde [aquí](https://alpinelinux.org/downloads/)
|
||||||
|
* Subimos la imagen ISO a nuestro nodo en _Proxmox_ (En el árbol vamos a: __nodo → local(nodo) → Iso Images__)
|
||||||
|
* Creamos una máquina virtual (he dejado prácticamente los valores por defecto, asignando 32Gb de disco duro)
|
||||||
|
* Una vez arrancada la máquina ejecutamos `setup-alpine` y vamos asignando las [opciones de instalación](https://wiki.alpinelinux.org/wiki/Installation#Questions_asked_by_setup-alpine):
|
||||||
|
* Teclado `es-winkeys`
|
||||||
|
* Hostname: `srvname`
|
||||||
|
* Asignamos IP estática
|
||||||
|
* Es necesario tener acceso a internet para asignar los repos de software de Alpine, así que hay que asignar _gateway_ y _dns server_.
|
||||||
|
* Escogemos "sys" para la estructura de disco
|
||||||
|
* Damos permiso para usar y borrar el disco
|
||||||
|
|
||||||
|
Una vez instalado y rearrancado el sistema editamos `/etc/apk/repositories` y habilitamos `comunity`.
|
||||||
|
|
||||||
|
__¡Ojo!__ si habilitas `edge` estarás habilitando la rama de desarrollo de Alpine y no es lo que queremos ahora mismo.
|
||||||
|
|
||||||
|
Actualizamos los paquetes del sistema con `apk update`.
|
||||||
|
|
||||||
|
Instalamos `apk add qemu-guest-agent`
|
||||||
|
|
||||||
|
{{< admonition type=info title="Qemu-guest-agent" open=true >}}
|
||||||
|
|
||||||
|
El _qemu-guest-agent_ sirve para que _Proxmox_ pueda parar la VM y/o congelar su sistema de ficheros de forma segura. Esto facilita mucho varias operaciones como por ejemplo hacer _backups_ de las VM
|
||||||
|
|
||||||
|
{{< /admonition >}}
|
||||||
|
|
||||||
|
|
||||||
|
Editamos el fichero `/etc/init-d/qemu-guest-agent`, su última línea tiene que ser:
|
||||||
|
|
||||||
|
`command_args="-m ${GA_METHOD:-virtio-serial} -p ${GA_PATH:-/dev/vport2p1} -l /var/log/qemu-ga.log -d"`
|
||||||
|
|
||||||
|
Añadimos el agente al arranque: `rc-update add qemu-guest-agent boot`
|
||||||
|
|
||||||
|
Paramos la máquina virtual y en el interfaz _Proxmox_ cambiamos las
|
||||||
|
opciones para habilitar el `Qemu Guest Agent`
|
||||||
|
|
||||||
|
Volvemos a arrancar la VM (Importante reiniciar desde el Proxmox) y comprobamos que en el `Summary` el `qemu-guest-agent` se conecta correctamente.
|
||||||
|
|
||||||
|
{{< admonition type=warning title="Qemu-guest-agent: fallo al crear el canal" open=false >}}
|
||||||
|
|
||||||
|
Mi `qemu-guest-agent` fallaba al arrancar con los siguientes mensajes en `/var/log/qemu-ga.log`
|
||||||
|
|
||||||
|
```log
|
||||||
|
1618081791.809004: critical: error opening channel: No such file or directory
|
||||||
|
1618081791.809056: critical: error opening channel
|
||||||
|
1618081791.809070: critical: failed to create guest agent channel
|
||||||
|
1618081791.809082: critical: failed to initialize guest agent channel
|
||||||
|
```
|
||||||
|
|
||||||
|
Por alguna razón la máquina que he creado no tiene el dispositivo `/dev/vport1p1`. El dispositivo en mi máquina es el `/dev/vport2p1`. Evidentemente el agente falla hasta que corregimos el fichero `/etc/init-d/qemu-guest-agent`
|
||||||
|
|
||||||
|
{{< /admonition >}}
|
||||||
|
|
||||||
|
|
||||||
|
A continuación procedemos a instalar `sudo` con `apk add sudo` y con `visudo` habilitamos sudo para el grupo `wheel` (descomentar la linea correspondiente)
|
||||||
|
|
||||||
|
Creamos grupo y usuario para _Docker_:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
addgroup -g 150 docker
|
||||||
|
addgroup dockadmin
|
||||||
|
adduser -G dockadmin dockadmin
|
||||||
|
adduser dockadmin wheel
|
||||||
|
adduser dockadmin docker
|
||||||
|
cat /etc/passwd
|
||||||
|
```
|
||||||
|
|
||||||
|
Instalamos _Docker_:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
apk add docker
|
||||||
|
rc-update add docker boot
|
||||||
|
service docker start
|
||||||
|
service docker status
|
||||||
|
```
|
||||||
|
|
||||||
|
Y lo probamos:
|
||||||
|
|
||||||
|
`docker run --rm hello-world`
|
||||||
|
|
||||||
|
Como todo va bien instalamos también el `docker-compose`
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo apk add docker-compose
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Cortafuegos
|
||||||
|
|
||||||
|
Instalamos el UFW
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo apk add ufw
|
||||||
|
```
|
||||||
|
|
||||||
|
Y hacemos una configuración inicial
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo ufw status verbose # Comprobamos que está deshabilitado
|
||||||
|
sudo ufw app list # comprobamos que apps soporta
|
||||||
|
sudo ufw default deny incoming # le decimos que por defecto no acepta nada entrante
|
||||||
|
sudo ufw default allow outgoing # por defecto permitimos conexiones salientes
|
||||||
|
sudo ufw allow ssh # permitimos conexiones ssh
|
||||||
|
sudo ufw enable # lo habilitamos
|
||||||
|
sudo ufw status verbose # vemos el estado del cortafuegos
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Instalando nuestros primeros contenedores
|
||||||
|
|
||||||
|
Una vez comprobado que funciona todo añadimos una configuración básica con _Traefik_ y _Portainer_ como comentamos en [el ejemplo 3 de los apuntes de _Traefik_]({{< ref "notes_traefik/#ejemplo03-una-configuraci%C3%B3n-sencilla-para-empezar-con-traefik-en-producci%C3%B3n" >}})
|
||||||
|
|
||||||
|
|
||||||
|
#### Almacenamiento para Docker
|
||||||
|
|
||||||
|
* [Referencia](https://www.hiroom2.com/2018/08/29/alpinelinux-3-8-sshfs-en/)
|
||||||
|
|
||||||
|
Como hemos sacado los discos duros externos del Proxmox no podemos crear volúmenes en los mismos. Para darle espacio de almacenamiento a los contenedores en esos discos duros vamos a hacer algo un poco rebuscado: montar un directorio del disco externo via `sshfs`.
|
||||||
|
|
||||||
|
En nuestra máquina virtual Alpine:
|
||||||
|
|
||||||
|
1. Instalamos los paquetes `sshfs` y `util-linux`, además configuramos el sistema para que se carge el módulo del kernel `fuse`
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo apk add sshfs util-linux
|
||||||
|
sudo modprobe fuse
|
||||||
|
echo fuse | sudo tee -a /etc/modules
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Creamos el directorio local (en nuestra VM) donde montaremos el disco duro externo.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mkdir $HOME/mnt/store
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Creamos una clave con `ssh-keygen` que nos permita facilitar la conexión a la máquina virtual.
|
||||||
|
|
||||||
|
Una vez creada la clave , podriamos crear el fichero `~/.ssh/config` y montar la unidad por comando con el usuario administrador de docker (por ejemplo). Pero nos interesa más montar el directorio del disco duro en el arranque de la máquina virtual dejándolo especificado en el fichero `/etc/fstab`
|
||||||
|
|
||||||
|
Generalmente no permitimos el acceso del usuario `root` via ssh en ningún sistema, así que tendremos que especificar el montaje con un usuario. Usaremos el usuarios `dockadmin` del servidor host y el usuario del mismo nombre que creamos en la máquina virtual de Docker.
|
||||||
|
|
||||||
|
4. Añadimos la clave pública al fichero `~/.ssh/authorized_keys` del usuario `dockadmin` en la VM. (depende de tu escenario, yo lo hice pasando por mi ordenador personal, desde donde estoy configurando todo)
|
||||||
|
|
||||||
|
5. Creamos una entrada para la VM en el fichero `/etc/hosts`
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo echo "<ip_host> hostname" >> /etc/hosts
|
||||||
|
```
|
||||||
|
|
||||||
|
6. Habilitamos `netmount`
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo rc-update add netmount
|
||||||
|
```
|
||||||
|
|
||||||
|
7. Añadimos la linea al fichero `/etc/fstab`
|
||||||
|
|
||||||
|
```fstab
|
||||||
|
dockadmin@sirio:/mnt/usbA/Work/dockerStore:/home/dockadmin/mnt/store fuse.sshfs _netdev,identityfile=/home/dockadmin/.ssh/id_mount,allow_other,uid=dockeradmin,gid=dockeradmin 0 0
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Recetillas
|
||||||
|
|
||||||
|
### Quitando el mensaje de "invalid subscription"
|
||||||
|
|
||||||
|
{{< admonition type=info title="Referencia" open=false >}}
|
||||||
|
|
||||||
|
- [Remove Proxmox subscription warning](https://johnscs.com/remove-proxmox51-subscription-notice/)
|
||||||
|
|
||||||
|
{{< /admonition >}}
|
||||||
|
|
||||||
|
Editamos el fichero `/usr/share/javascript/proxmox-widget-toolkit/promoxlib.js`
|
||||||
|
|
||||||
|
Localizamos la cadena `No valid subscription` y cambiamos al función para que quede así:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
void({ //Ext.Msg.show({
|
||||||
|
title: gettext('No valid subscription'),
|
||||||
|
```
|
||||||
|
|
||||||
|
Reiniciamos el servicio con `systemctl restart pveproxy.service`
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!-- notes
|
||||||
|
|
||||||
|
---------------------------------------
|
||||||
|
|
||||||
|
### wifi
|
||||||
|
|
||||||
|
```cfg
|
||||||
|
root@cube:~# cat /etc/network/interfaces
|
||||||
|
auto lo
|
||||||
|
iface lo inet loopback
|
||||||
|
|
||||||
|
iface eno1 inet dhcp
|
||||||
|
|
||||||
|
allow-hotplug wlp0s20f3
|
||||||
|
iface wlp0s20f3 inet static
|
||||||
|
address 192.168.1.10/24
|
||||||
|
gateway 192.168.1.1
|
||||||
|
post-up echo 1 > /proc/sys/net/ipv4/ip_forward
|
||||||
|
post-up echo 1 > /proc/sys/net/ipv4/conf/wlp0s20f3/proxy_arp
|
||||||
|
wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf
|
||||||
|
|
||||||
|
|
||||||
|
auto vmbr0
|
||||||
|
iface vmbr0 inet static
|
||||||
|
address 10.10.10.1/24
|
||||||
|
bridge_ports none
|
||||||
|
bridge_stp off
|
||||||
|
bridge_fd 0
|
||||||
|
root@cube:~#
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Referencia
|
||||||
|
|
||||||
|
- [Documentación de Proxmox](https://pve.proxmox.com/pve-docs/chapter-sysadmin.html#_masquerading_nat_with_span_class_monospaced_iptables_span)
|
||||||
|
- [Dan the salmon](https://danthesalmon.com/running-docker-on-proxmox/)
|
||||||
|
- https://www.juanmtech.com/install-proxmox-and-virtualize-home-assistant/
|
||||||
|
- https://marcelo-ochoa.medium.com/using-oracle-cloud-object-storage-as-docker-volume-3ec7882f51b7
|
||||||
|
|
||||||
|
|
||||||
|
-->
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,24 @@
|
|||||||
|
---
|
||||||
|
weight: 4
|
||||||
|
title: "Notas de R (lenguaje de programación)"
|
||||||
|
date: 2022-03-02T17:11:10+0100
|
||||||
|
draft: true
|
||||||
|
summary: "Notas sobre R el lenguaje de programación especializado en estadísticas"
|
||||||
|
categories:
|
||||||
|
- notes
|
||||||
|
tags:
|
||||||
|
- rlang
|
||||||
|
- programacion
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Referencias
|
||||||
|
|
||||||
|
- [A Short R Tutorial](https://strata.uga.edu/software/pdf/Rtutorial.pdf) (pdf)
|
||||||
|
- [R: A self-learn tutorial](https://gsp.humboldt.edu/OLM/R/Tutorials/BestFirstRTutorial.pdf) (pdf)
|
||||||
|
- <https://www.r-tutor.com/> (evaluar)
|
||||||
|
- <https://www.w3schools.com/r/default.asp> W3Schools (evaluar)
|
||||||
|
- <https://www.tutorialspoint.com/r/r_overview.htm> Tutorialspoint (evaluar)
|
||||||
|
- <https://www.guru99.com/r-tutorial.html> Guru99 (evaluar)
|
@ -0,0 +1,201 @@
|
|||||||
|
---
|
||||||
|
weight: 4
|
||||||
|
title: "Instalación de Rocket Chat en Docker"
|
||||||
|
date: 2021-03-07T17:24:04+0100
|
||||||
|
draft: false
|
||||||
|
summary: "Instalación de Rocket Chat en Docker"
|
||||||
|
categories:
|
||||||
|
- notes
|
||||||
|
tags:
|
||||||
|
- docker
|
||||||
|
- traefik
|
||||||
|
- rocketchat
|
||||||
|
---
|
||||||
|
|
||||||
|
Como instalar el servicio Rocket.Chat sobre Docker con Traefik v2.
|
||||||
|
|
||||||
|
<!--more-->
|
||||||
|
|
||||||
|
# Rocket Chat sobre Docker tras Traefik v2
|
||||||
|
|
||||||
|
[Rocketchat](https://rocket.chat/) es un interesante servicio de chat
|
||||||
|
que [es software libre y
|
||||||
|
abierto](https://github.com/RocketChat/Rocket.Chat/blob/master/LICENSE).
|
||||||
|
|
||||||
|
|
||||||
|
## Directorios de trabajo
|
||||||
|
|
||||||
|
{{< admonition type=abstract title="Referencias" state=open >}}
|
||||||
|
|
||||||
|
|
||||||
|
Para configurar el servicio _Rocketchat_ seguimos las siguientes
|
||||||
|
referencias:
|
||||||
|
|
||||||
|
- [github del proyecto rocketchat](https://github.com/RocketChat/Rocket.Chat)
|
||||||
|
- [Realtarget traefik-docker-stack](https://github.com/realtarget/traefik2-docker-stack)
|
||||||
|
|
||||||
|
{{</ admonition >}}
|
||||||
|
|
||||||
|
Para realizar la instalación de ***Rocketchat*** suponemos que tenemos
|
||||||
|
un servicio _Docker_ instalado con _Traefik v2_ funcionando como proxy
|
||||||
|
inverso. Por ejemplo como describimos [aquí]({{< relref
|
||||||
|
"notes_traefik/#ejemplo03-una-configuraci%C3%B3n-sencilla-para-empezar-con-traefik-en-producci%C3%B3n"
|
||||||
|
>}})
|
||||||
|
|
||||||
|
Partimos del fichero `docker-compose.yml` que nos proponen en [el
|
||||||
|
github del
|
||||||
|
proyecto](https://github.com/RocketChat/Rocket.Chat/blob/develop/docker-compose.yml)
|
||||||
|
|
||||||
|
Para ello creamos un directorio para nuestra configuración _docker_ del _Rocket Chat_:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mkdir -p ~/work/010_rocketchat/{mongo, rocketchat}
|
||||||
|
touch ~/work/010_rocketchat/docker-compose.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
## Configuración del contenedor Docker
|
||||||
|
|
||||||
|
Modificamos el fichero que nos proponen en el github:
|
||||||
|
|
||||||
|
- Fijamos las versiones concretas a utilizar de las imágenes _Rocket.Chat_ y
|
||||||
|
_Mongodb_
|
||||||
|
- Configuramos el host para que use HTTPS
|
||||||
|
- Conectamos los contenedores de _Rocket.Chat_ y _Mongodb_ a la red
|
||||||
|
___backend___ y les asignamos direcciones IP manualmente
|
||||||
|
(___backend___ es una red interna de nuestra configuración _Docker_)
|
||||||
|
- Conectamos el contenedor de _Rocket.Chat_ a la red ___frontend___
|
||||||
|
(puesto que tendrá que comunicarse con _Traefik_), asignando la
|
||||||
|
dirección IP explicitamente.
|
||||||
|
- El servicio estará disponible a través de _Traefik_ así que quitamos
|
||||||
|
la sección `ports` (no queremos puertos mapeados a nuestro _host_) y ...
|
||||||
|
- añadimos la sección `labels` a la definición del servicio
|
||||||
|
`rocketchat` en nuestro fichero `docker-compose.yml` para definir
|
||||||
|
los enrutamientos _Traefik_ al servicio _Rocket.Chat_
|
||||||
|
- No es necesario añadir el servidor de correo SMTP al entorno,
|
||||||
|
podremos configurarlo sin problemas desde el interfaz de
|
||||||
|
administración del chat una vez lanzados los contenedores de
|
||||||
|
servicios.
|
||||||
|
- Hemos corregido la activación de la replica de la base de datos
|
||||||
|
_Mongo_, en realidad no estamos replicando nada, pero queda todo
|
||||||
|
listo para dar redundancia en el futuro si así lo decidimos. (Más
|
||||||
|
info
|
||||||
|
[aquí](https://docs.mongodb.com/manual/tutorial/deploy-replica-set/))
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
version: '3'
|
||||||
|
|
||||||
|
services:
|
||||||
|
rocketchat:
|
||||||
|
image: rocketchat/rocket.chat:3.12.0
|
||||||
|
container_name: rocketchat
|
||||||
|
networks:
|
||||||
|
frontend:
|
||||||
|
ipv4_address: 172.21.0.100
|
||||||
|
backend:
|
||||||
|
ipv4_address: 172.20.0.100
|
||||||
|
command: >
|
||||||
|
bash -c
|
||||||
|
"for i in `seq 1 30`; do
|
||||||
|
node main.js &&
|
||||||
|
s=$$? && break || s=$$?;
|
||||||
|
echo \"Tried $$i times. Waiting 5 secs...\";
|
||||||
|
sleep 5;
|
||||||
|
done; (exit $$s)"
|
||||||
|
restart: unless-stopped
|
||||||
|
volumes:
|
||||||
|
- ./rocketchat/uploads:/app/uploads
|
||||||
|
environment:
|
||||||
|
- PORT=3000
|
||||||
|
- ROOT_URL=https://chat.comacero.com
|
||||||
|
- MONGO_URL=mongodb://mongo:27017/rocketchat
|
||||||
|
- MONGO_OPLOG_URL=mongodb://mongo:27017/local
|
||||||
|
# - MAIL_URL=smtp://mail.server.com
|
||||||
|
# - HTTP_PROXY=http://proxy.domain.com
|
||||||
|
# - HTTPS_PROXY=http://proxy.domain.com
|
||||||
|
depends_on:
|
||||||
|
- mongo
|
||||||
|
# ports:
|
||||||
|
# - 80:3000
|
||||||
|
labels:
|
||||||
|
- traefik.enable=true
|
||||||
|
- traefik.http.routers.rocket.entrypoints=https
|
||||||
|
- traefik.http.routers.rocket.rule=Host(`chat.yourdomain.com`)
|
||||||
|
- traefik.http.routers.rocket.tls.certresolver=letsencrypt
|
||||||
|
- traefik.http.services.rocket.loadbalancer.server.port=3000
|
||||||
|
- traefik.docker.network=frontend
|
||||||
|
|
||||||
|
mongo:
|
||||||
|
image: mongo:4.0
|
||||||
|
container_name: mongo
|
||||||
|
networks:
|
||||||
|
backend:
|
||||||
|
ipv4_address: 172.20.0.110
|
||||||
|
restart: unless-stopped
|
||||||
|
volumes:
|
||||||
|
- ./mongo/data/db:/data/db
|
||||||
|
- ./mongo/data/dump:/dump
|
||||||
|
command: mongod --smallfiles --oplogSize 128 --replSet rs0 --storageEngine=mmapv1
|
||||||
|
|
||||||
|
# this container's job is just run the command to initialize the replica set.
|
||||||
|
# it will run the command and remove himself (it will not stay running)
|
||||||
|
mongo-init-replica:
|
||||||
|
image: mongo:4.0
|
||||||
|
container_name: mongo_replica
|
||||||
|
networks:
|
||||||
|
- backend
|
||||||
|
command: >
|
||||||
|
bash -c
|
||||||
|
"for i in `seq 1 30`; do
|
||||||
|
mongo mongo/rocketchat --eval \"
|
||||||
|
rs.initiate({
|
||||||
|
_id: 'rs0',
|
||||||
|
members: [ { _id: 0, host: 'mongo:27017' } ]})\" &&
|
||||||
|
s=$$? && break || s=$$?;
|
||||||
|
echo \"Tried $$i times. Waiting 5 secs...\";
|
||||||
|
sleep 5;
|
||||||
|
done; (exit $$s)"
|
||||||
|
depends_on:
|
||||||
|
- mongo
|
||||||
|
|
||||||
|
networks:
|
||||||
|
frontend:
|
||||||
|
external: true
|
||||||
|
backend:
|
||||||
|
external: true
|
||||||
|
```
|
||||||
|
|
||||||
|
## Configuraciones adicionales
|
||||||
|
|
||||||
|
- Evidentemente necesitamos una entrada en nuestra zona DNS que apunte
|
||||||
|
al chat ya que hemos usado un subdominio.
|
||||||
|
- En la documentación de _Rocket Chat_ nos recomiendan añadir la linea
|
||||||
|
`chat.yourdomain.com` a nuestro fichero `/etc/hosts` de forma que
|
||||||
|
apunte a `127.0.0.1` (_localhost_)
|
||||||
|
- Necesitamos un servidor SMTP de correo. Nuestro proveedor del
|
||||||
|
dominio lo da gratis para volúmenes bajos de correo y es el que
|
||||||
|
hemos usado, pero también hay algunas opciones en Internet que se
|
||||||
|
pueden usar.
|
||||||
|
- Una vez arrancado el servicio daremos de alta __un usuario
|
||||||
|
administrador__ para el _Rocket Chat_ conectando a <https://chat.yourdomain.com>
|
||||||
|
- Configuramos las opciones del servidor de correo (para poder
|
||||||
|
verificar las direcciones de correo de los usuarios que se registren
|
||||||
|
y poder enviar contraseñas en caso de reseteo)
|
||||||
|
- Nos damos de alta en [Rocket Chat Cloud](https://cloud.rocket.chat)
|
||||||
|
que nos proporcionará gratis servicios de doble factor de
|
||||||
|
autenticación (via correo), para nuestro servicio.
|
||||||
|
- Configuramos la conexión de nuestro servidor _Rocket Chat_ con el
|
||||||
|
_cloud.rocket.chat_. Basta con añadir el _token_, que nos dan en el
|
||||||
|
paso anterior, mediante el interfaz de administración de nuestro
|
||||||
|
servicio.
|
||||||
|
- Revisamos __cuidadosamente__ como queremos dejar la configuración
|
||||||
|
para el registro de nuevos usuarios. Parece recomendable activar al
|
||||||
|
menos que solo se puedan loguear usuarios con el correo verificado y
|
||||||
|
probablemente deberíamos activar la aprobación manual de nuevos
|
||||||
|
usuarios.
|
||||||
|
|
||||||
|
{{< admonition type=warning title="Seguridad" state=open >}}
|
||||||
|
|
||||||
|
Como siempre que abrimos servicios a internet, conviene ir con cuidado
|
||||||
|
y tomar todo tipo de precauciones. Si dejamos abierto el registro de nuevos usuarios nos podemos encontrar con una avalancha de peticiones de nuevos usuarios por parte de bots.
|
||||||
|
|
||||||
|
{{</ admonition >}}
|
@ -0,0 +1,225 @@
|
|||||||
|
---
|
||||||
|
weight: 4
|
||||||
|
title: "Apuntes de Robot Operating System (ROS)"
|
||||||
|
date: 2023-02-27T16:42:06+0100
|
||||||
|
draft: false
|
||||||
|
summary: "Apuntes de ROS"
|
||||||
|
categories:
|
||||||
|
- notes
|
||||||
|
tags:
|
||||||
|
- ros
|
||||||
|
- docker
|
||||||
|
- robot
|
||||||
|
---
|
||||||
|
|
||||||
|
## ¿Qué es ROS?
|
||||||
|
|
||||||
|
{{< admonition type=info title="Referencias" open=true >}}
|
||||||
|
|
||||||
|
- [ROS2 vs ROS1](https://medium.com/@oelmofty/ros2-how-is-it-better-than-ros1-881632e1979a)
|
||||||
|
- [ROS1 vs ROS2](https://roboticsbackend.com/ros1-vs-ros2-practical-overview) Practical Overview from Robotics Backend
|
||||||
|
- [Robot Operating System 2: Design, architecture, and uses in the wild](https://www.science.org/doi/10.1126/scirobotics.abm6074)
|
||||||
|
|
||||||
|
{{< /admonition >}}
|
||||||
|
|
||||||
|
|
||||||
|
_Robot Operating System_ (ROS) es un _framework_ para programar __robots__, nos da facilidades para programar tareas de diferentes tipos como navegación (usando el stack de navegación de ROS), manipulación (usando _moveit_), percepción (usando por ejemplo [PCL]^(Point Cloud Library))
|
||||||
|
|
||||||
|
### Conceptos básicos de ROS
|
||||||
|
|
||||||
|
__Nodos__
|
||||||
|
|
||||||
|
: Son los procesos básicos en ROS, cada nodo representa un proceso independiente dentro del _ROS stack_. Los nodos pueden comunicarse entre si de tres maneras:
|
||||||
|
|
||||||
|
- ___ROS topics___ (_publisher/subscriber_) posibilitan a un nodo a publicar mensajes para que los lean otros nodos que se suscriban al _topic_
|
||||||
|
- ___ROS services___ (_request/response_) posibilita que un nodo cliente lance peticiones (_request_) a otro nodo servidor solicitando un servicio. Una vez que se completa la tarea el nodo servidor responde (_response_) enviando el resultado de la petición.
|
||||||
|
|
||||||
|
- ___ROS actions___ (_action/feedback/result_) Con este método un nodo cliente puede enviar una petición de acción a otro nodo servidor. Mientras el servidor está ejecutando la acción envía información continuamente al cliente del progreso de la acción. Una vez completada la tarea, el servidor envia el resultado al cliente, este sería el producto final de la acción. Las "acciones" se parecen a los servicios, la diferencia es la realimentación continua que el servidor da al cliente mientras ejecuta la acción.
|
||||||
|
|
||||||
|
___Parameter Server _
|
||||||
|
|
||||||
|
: En este servidor podemos almacenar parámetros globales que todos los nodos pueden consultar.
|
||||||
|
|
||||||
|
### ROS1 y ROS2
|
||||||
|
|
||||||
|
_ROS Noetic_ es la última versión de ROS 1, y está destinada a ser la última versión de ROS 1. _ROS Noetic_ utiliza ya Python 3 y está basada en Ubuntu 20.04. Hay un montón de literatura, tutoriales y ejemplos basados en ROS1 pero creo que lo mejor es centrarse directamente en ROS2.
|
||||||
|
|
||||||
|
ROS2 es la nueva versión de ROS. La motivación principal de ROS2 es ser un sistema operativo orientado a ser usado en el mundo real y no un sistema operativo de investigación y desarrollo como era ROS1, sus objetivos declarados son:
|
||||||
|
|
||||||
|
__Seguridad__
|
||||||
|
|
||||||
|
: Tiene que ser seguro y usar la encriptación adecuada siempre que sea necesario.
|
||||||
|
|
||||||
|
__Sistemas Embebidos__
|
||||||
|
|
||||||
|
: ROS2 tiene que poder ejecutarse en sistemas embebidos.
|
||||||
|
|
||||||
|
__Diversidad de red__
|
||||||
|
|
||||||
|
: Es necesario que pueda conectarse y comunicarse usando todo tipo de redes desde LAN a redes satelitales, para adecuarse a cualquier entorno en el que se usen robots.
|
||||||
|
|
||||||
|
__Computación en Tiempo Real__
|
||||||
|
|
||||||
|
: Tiene que ser capaz de llevar a cabo [RTC]^(Real Time Computing) de forma fiable, dado que esta es crucial para la robótica.
|
||||||
|
|
||||||
|
__Orientado al producto__
|
||||||
|
|
||||||
|
: Tiene que cumplir con los estándares industriales para usarlo en productos comerciales
|
||||||
|
|
||||||
|
|
||||||
|
ROS2 implica cambiar muchas cosas:
|
||||||
|
|
||||||
|
- Usa [DDS](https://en.wikipedia.org/wiki/Data_Distribution_Service) como protocolo de red para todas las comunicaciones.
|
||||||
|
- Prescinde del _ROS Master_ que actuaba como coordinador de nodos en ROS1. Usa funcionalidades del protocolo [DDS]^(Data Distribution Service) para que los nodos se descubran.
|
||||||
|
- Es más robusto frente a problemas de comunicación que ROS1, también gracias a la funcionalidad de DDS
|
||||||
|
- ROS2 es multiplataforma, corre de forma nativa en Linux, Windows y MacOS
|
||||||
|
- Los nodos de ROS2 pueden correr en un mismo proceso y su ciclo de vida es gestionable
|
||||||
|
- Las bibliotecas de ROS2 comparten una implementación común (escrita en C)
|
||||||
|
- Incluye un bridge (_ROS1 bridge_) para facilitar la comunicación con, y migración de, antiguos sistemas.
|
||||||
|
|
||||||
|
## Tutoriales de ROS2
|
||||||
|
|
||||||
|
- <https://docs.ros.org/en/humble/Tutorials.html> Los tutos oficiales
|
||||||
|
- <https://ubuntu.com/tutorials/getting-started-with-ros-2#1-overview>
|
||||||
|
- <https://www.tutorialspoint.com/market/course/ros2_for_beginners_ros_foxy/index.jsp> (de pago en tutorialspoint)
|
||||||
|
- <https://www.udemy.com/course/ros2-for-beginners/?couponCode=FEB_2023> de pago en Udemy
|
||||||
|
- <https://www.youtube.com/watch?v=0aPbWsyENA8> Lista en youtube aparentemente del mismo autor
|
||||||
|
- <https://www.youtube.com/watch?v=Gg25GfA456o> Un curso condensado del mismo autor
|
||||||
|
|
||||||
|
### El tutorial oficial
|
||||||
|
|
||||||
|
1. Empezar con [las instrucciones de instalación](https://docs.ros.org/en/humble/Installation.html)
|
||||||
|
2. Seguir con [los tutoriales](https://docs.ros.org/en/humble/Tutorials.html)
|
||||||
|
|
||||||
|
## Probando ROS2 con Docker
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Probar ROS1 con Docker
|
||||||
|
|
||||||
|
{{< admonition type=info title="Referencias" open=true >}}
|
||||||
|
|
||||||
|
- [Docker and Ros](https://roboticseabass.com/2021/04/21/docker-and-ros/) by Robotic Sea Bass
|
||||||
|
- [Getting Started with ROS and Docker](https://wiki.ros.org/docker/Tutorials/Docker) de la wiki de ROS
|
||||||
|
- [Gráficos en Docker](https://wiki.ros.org/docker/Tutorials/GUI) de la wiki de ROS
|
||||||
|
- [Install ROS Noetic with Docker](https://varhowto.com/install-ros-noetic-docker/)
|
||||||
|
|
||||||
|
{{< /admonition >}}
|
||||||
|
|
||||||
|
|
||||||
|
Gracias a Docker podemos usar ROS fácilmente en cualquier linux (aunque no sea Ubuntu)
|
||||||
|
|
||||||
|
Lanzar un completo _ROS Noetic_ en Docker es tan simple como:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker pull osrf/ros:noetic-desktop-full
|
||||||
|
|
||||||
|
# Si queremos una sesión interactiva:
|
||||||
|
docker run -it osrf/ros:noetic-desktop-full bash
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
Imágenes Docker de ROS disponibles:
|
||||||
|
|
||||||
|
__noetic-ros-core__
|
||||||
|
|
||||||
|
: Esta imagen nos permite usar paquetes básicos de ROS: podremos publicar y suscribirnos a nodos ROS, invocar servicios ROS y lazar ficheros ROS.
|
||||||
|
|
||||||
|
__noetic-ros-base__
|
||||||
|
|
||||||
|
: Basada en la anterior. Añade algunos paquetes esenciales como: _actionlib_, _dynamic reconfigure_, _nodelets_ y _pluginlib_.
|
||||||
|
|
||||||
|
__noetic-robot__
|
||||||
|
|
||||||
|
: Basada en __noetic-ros-base__ añade los metapaquetes `robot`y `viz`, así como la mayor parte de los paquetes utilizados en los tutoriales oficiales. Esta sería la imagen mínima para hacer los tutoriales. También sería la imagen ideal para instalar en un robot.
|
||||||
|
|
||||||
|
__noetic-perception__
|
||||||
|
|
||||||
|
: Esta imagen incluye [PCL]^(Point Cloud Library), la biblioteca `perception_pcl` y bibliotecas relacionadas con el procesamiento de imágenes como:
|
||||||
|
|
||||||
|
- `image_common`
|
||||||
|
- `image_pipeline`
|
||||||
|
- `image_transport_plugins`
|
||||||
|
- `laser_pipeline`00
|
||||||
|
|
||||||
|
__noetic-desktop__
|
||||||
|
|
||||||
|
|
||||||
|
: Es similar a la anterior (__noetic-robot__) pero no está basada en ella.
|
||||||
|
|
||||||
|
__noetic-desktop-full__
|
||||||
|
|
||||||
|
: Basada en la anterior pero además añade paquetes de percepción y simulación, tales como `Gazebo` y `PCL`.
|
||||||
|
|
||||||
|
|
||||||
|
## Experimento
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Si queremos una sesión interactiva:
|
||||||
|
docker run -it osrf/ros:noetic-desktop-full bash
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
Dentro del contenedor actualizamos
|
||||||
|
|
||||||
|
```bash
|
||||||
|
apt update
|
||||||
|
apt upgrade
|
||||||
|
apt install python3-rosdep python3-rosinstall python3-rosinstall-generator python3-wstool build-essential
|
||||||
|
apt install python3-rosdep
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Un dockerfile:
|
||||||
|
|
||||||
|
```dockerfile
|
||||||
|
FROM: osrf/ros:noetic-desktop-full
|
||||||
|
|
||||||
|
|
||||||
|
RUN: apt-get update && apt-get upgrade -y
|
||||||
|
RUN: apt-get install python3-rosdep python3-rosinstall python3-rosinstall-generator python3-wstool build-essential python3-rosdep
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
IFS=$'\n\t'
|
||||||
|
|
||||||
|
|
||||||
|
# Lanzar Xephyr en el DISPLAY :1
|
||||||
|
Xephyr -ac -screen 800x600 -br -reset -terminate 2> /dev/null :1 &
|
||||||
|
|
||||||
|
docker run -it --name correMundos pabloImage roscore
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
world_files=`docker exec -it correMundos 'ls' '-1' '/opt/ros/noetic/share/stage/worlds/' |grep '\.world' `
|
||||||
|
|
||||||
|
if [ ${#world_files[@]} -eq 0 ]; then
|
||||||
|
echo "No se encontraron archivos con la extensión .world en este directorio."
|
||||||
|
else
|
||||||
|
echo "Archivos .world encontrados:"
|
||||||
|
for i in "${!world_files[@]}"; do
|
||||||
|
echo "$((i+1)): ${world_files[i]}"
|
||||||
|
done
|
||||||
|
|
||||||
|
read -p "Ingrese el número del archivo que desea ejecutar: " selection
|
||||||
|
case $selection in
|
||||||
|
[1-${#world_files[@]}])
|
||||||
|
selected_file=${world_files[$((selection-1))]}
|
||||||
|
echo "Ejecutando archivo $selected_file..."
|
||||||
|
docker exec -it correMundos "rosrun stage_ros stageros /opt/ros/noetic/share/stage/worlds/$selected_file"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Selección inválida. Saliendo del programa."
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
```
|
@ -0,0 +1,71 @@
|
|||||||
|
---
|
||||||
|
weight: 4
|
||||||
|
title: "Apuntes de Shotcut"
|
||||||
|
date: 2022-06-16T11:10:34+0200
|
||||||
|
draft: true
|
||||||
|
summary: "Apuntes incompletos del editor de video Shotcut"
|
||||||
|
categories:
|
||||||
|
- notes
|
||||||
|
tags:
|
||||||
|
- shotcut
|
||||||
|
- edicionVideo
|
||||||
|
---
|
||||||
|
|
||||||
|
{{< admonition type=warning title="APUNTES INCOMPLETOS" open=true >}}
|
||||||
|
|
||||||
|
Estos apuntes **no están** completos.
|
||||||
|
|
||||||
|
{{< /admonition >}}
|
||||||
|
|
||||||
|
## Referencias
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Varias notas
|
||||||
|
|
||||||
|
* Todos los paneles se pueden mover, fijar, cerrar, etc. etc.
|
||||||
|
* Podemos usar `Ctrl+z` para deshacer. Tenemos opciones _Undo_ y _Redo_ y tenemos un _History Panel_ para hacer y rehacer acciones.
|
||||||
|
* Se pueden reabrir con el menú _Panels_
|
||||||
|
* Nuestras fuentes se añaden en el _Playlist Panel_
|
||||||
|
* El _Timeline_ tiene varias pistas (_Tracks_) en cada pista podemos ir añadiendo tomas (_Shots_)
|
||||||
|
* Podemos añadir nuevos _Tracks_ de audio o de video
|
||||||
|
* Podemos hacer zoom con la rueda del ratón
|
||||||
|
* En cada _Track_ podemos:
|
||||||
|
* silenciar el sonido o ocultar el video (evidentemente afectan al resultado final)
|
||||||
|
* bloquearlo para impedir cambios accidentales.
|
||||||
|
* Podemos arrastrar cualquier toma (_Shot_) dentro de su _Track_ o a otra pista diferente. Si arrastramos una toma de video a una pista de audio sólo se usará el audio de ese video.
|
||||||
|
* Si arrastramos dos tomas de forma que se superpongan se creará una transición entre tomas.
|
||||||
|
* Podemos editar los parámetros de la transición haciendo click derecho sobre ella
|
||||||
|
* Si arrastramos la esquina superior izquierda de una toma podemos añadir una transición para que empiece "suavemente"
|
||||||
|
* Para cada toma (_Shot_) si la seleccionamos (marco rojo rodeando la toma), podremos:
|
||||||
|
* Ver y editar sus propiedades (cambiando la relación de aspecto, el sync del audio o los metadatos) podemos cambiar su velocidad o su duración (recortándolo)
|
||||||
|
* Podemos cortar una toma en dos usando los iconos en el _Timeline_ o con el botón derecho del ratón.
|
||||||
|
* El panel de _Preview_ tiene dos modos de funcionamiento, en pestañas separadas:
|
||||||
|
* _Source_ es para previsualizar fuentes del _Playlist Panel_
|
||||||
|
* _Project_ es para previsualizar el proyecto actual (la _Timeline_)
|
||||||
|
* En este modo veremos el _marker_ en el _Timeline_, podemos moverlo con el ratón o con los cursores para ir _frame_ a _frame_
|
||||||
|
* Tenemos la posibilidad de activar un _Grid_(hay varias configuraciones) o hacer zoom.
|
||||||
|
* Con el _Peakmeter Panel_ podemos comprobar los niveles de sonido
|
||||||
|
* Con el menú _View::Scopes_ podemos activar varias herramientas de visualización de sonido y video
|
||||||
|
* Podemos aplicar muchos filtros de todo tipo desde el _Filters Panel_ permiten todo tipo de operaciones de corrección de imágenes y sonido o inclusión de texto 3D o 2D.
|
||||||
|
* El efecto de los filtros se puede limitar con marcas de tiempo.
|
||||||
|
* Cuando tengamos todo listo podemos exportar el video (hay muchas plantillas de exportación)
|
||||||
|
|
||||||
|
|
||||||
|
### Notas al arrancar el programa
|
||||||
|
|
||||||
|
**Playlist**
|
||||||
|
|
||||||
|
: Situada en el tercio izquierdo.
|
||||||
|
- Con doble click podemos abrir cualquier video del _Playlist_ en el reproductor
|
||||||
|
- Se pueden previsualizar clips sin necesidad de añadirlos al _Playlist_
|
||||||
|
- Para ajustar cualquier item de la _Playlist_ lo abrimos con doble click, hacemos los cambios y le damos al botón de actualizar (no veo como hacer esto)
|
||||||
|
- Podemos reordenar los items con _Drag-n-drop_
|
||||||
|
|
||||||
|
:
|
||||||
|
|
||||||
|
## Borrador de flujo de trabajo
|
||||||
|
|
||||||
|
* Abrimos un nuevo proyecto especificando el _videomode_ (_framerate_ y resolución)
|
||||||
|
* Importamos nuestras fuentes (videos, audios, imágenes) en el panel _Playlist_ (lo tengo a la izquierda)
|
||||||
|
* Arrastramos nuestras fuentes desde el panel _Playlist_ hasta el _Timeline_ (lo tengo abajo)
|
@ -0,0 +1,53 @@
|
|||||||
|
---
|
||||||
|
weight: 4
|
||||||
|
title: "Diseño y construcción de un telar"
|
||||||
|
date: 2021-08-12T11:33:13+0200
|
||||||
|
draft: true
|
||||||
|
summary: "El telar"
|
||||||
|
categories:
|
||||||
|
- notes
|
||||||
|
tags:
|
||||||
|
- python
|
||||||
|
- programacion
|
||||||
|
---
|
||||||
|
|
||||||
|
{{< admonition type=warning title="Work in progress" open=true >}}
|
||||||
|
|
||||||
|
No está completo.
|
||||||
|
|
||||||
|
{{< /admonition >}}
|
||||||
|
|
||||||
|
## Referencias
|
||||||
|
|
||||||
|
* [Peines de telar cortados en aluminio](https://aitor-martin.blogspot.com/2014/07/peines-aluminio-telar-amona-micro-loom.html)
|
||||||
|
* [Blog actionweaver](https://actionweaver.wordpress.com/) el blog del autor del [telar Meinholf](https://actionweaver.wordpress.com/2010/03/31/collapsible-loom-building-plans-on-line-and-soon-in-print-in-oakland-ca/)
|
||||||
|
|
||||||
|
https://www.textilesnaturales.com/es/tienda-online/libros-artesania/tejeduria-tradicional-en-galicia-el-telar-y-la-tecnica-por-samuel-ortiz-ma-jose-lois-albino-quiinteiro-jose-ortiz
|
||||||
|
|
||||||
|
https://editorialcanela.gal/es/catalogo/sin-categorizar/tejeduria-tradicional-en-galicia-el-telar-y-la-tecnica/
|
||||||
|
|
||||||
|
https://tartan.galician.org/es/historia.htm#galicia
|
||||||
|
|
||||||
|
https://lanaytelar.es/telares/
|
||||||
|
|
||||||
|
http://www.aceam.org/down/TELAR.pdf
|
||||||
|
|
||||||
|
https://artesaniaeltelardebajolizo.blogspot.com/
|
||||||
|
|
||||||
|
https://historiaybiografias.com/telar_key/
|
||||||
|
|
||||||
|
https://repositorio.uam.es/bitstream/handle/10486/8514/45852_4.pdf?sequence=1
|
||||||
|
|
||||||
|
https://www.researchgate.net/publication/324756724_Desarrollo_de_un_prototipo_de_telar_plano_programable_para_tejido_artesanal
|
||||||
|
|
||||||
|
https://angeltelar.blogspot.com/2008/09/especial-telar-maria-de-peine-o-mesa.html
|
||||||
|
|
||||||
|
https://pre.museosdetenerife.org/assets/downloads/publication-f306689f7a.pdf
|
||||||
|
|
||||||
|
https://www.mimecanicapopular.com/verhaga.php?n=124
|
||||||
|
|
||||||
|
https://www.geniolandia.com/13092723/cuales-son-las-partes-de-un-telar
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,26 @@
|
|||||||
|
---
|
||||||
|
weight: 4
|
||||||
|
title: "Apuntes de Video"
|
||||||
|
date: 2021-11-05T21:56:02+0100
|
||||||
|
draft: true
|
||||||
|
summary: "Apuntes incompletos de Video"
|
||||||
|
categories:
|
||||||
|
- notes
|
||||||
|
tags:
|
||||||
|
- obs
|
||||||
|
- owncast
|
||||||
|
- streaming
|
||||||
|
- videocast
|
||||||
|
---
|
||||||
|
|
||||||
|
## OBS
|
||||||
|
|
||||||
|
## kdenlive
|
||||||
|
|
||||||
|
## shotcut
|
||||||
|
|
||||||
|
|
||||||
|
## Referencias
|
||||||
|
|
||||||
|
- [Consejos para livestream de video](https://steele.blue/livestream-setup/)
|
||||||
|
- [Curso de kdenlive de podcastlinux](https://devtube.dev-wiki.de/video-channels/canalpodcastlinux/videos)
|
@ -0,0 +1,502 @@
|
|||||||
|
---
|
||||||
|
weight: 4
|
||||||
|
title: "Apuntes de WireGuard"
|
||||||
|
date: 2021-04-18T22:20:51+0200
|
||||||
|
draft: false
|
||||||
|
summary: "Apuntes de WireGuard"
|
||||||
|
categories:
|
||||||
|
- notes
|
||||||
|
tags:
|
||||||
|
- wireguard
|
||||||
|
- debian
|
||||||
|
- alpine
|
||||||
|
---
|
||||||
|
|
||||||
|
Apuntes sobre WireGuard. Una herramienta para implementar redes VPN
|
||||||
|
|
||||||
|
<!--more-->
|
||||||
|
|
||||||
|
{{< admonition type=warning title="Work in progress" open=true >}}
|
||||||
|
Estos apuntes no están completos, (ni de lejos)
|
||||||
|
{{< /admonition >}}
|
||||||
|
|
||||||
|
|
||||||
|
# WireGuard
|
||||||
|
|
||||||
|
{{< admonition type=abstract title="Referencias" open=false >}}
|
||||||
|
|
||||||
|
|
||||||
|
- [WireGuard: Conceptual Overview](https://www.wireguard.com/#conceptual-overview)
|
||||||
|
- [WireGuard on Ubuntu](https://www.xmodulo.com/wireguard-vpn-server-ubuntu.html)
|
||||||
|
- [Set up WireGuard on Alpine Linux](https://www.cyberciti.biz/faq/how-to-set-up-wireguard-vpn-server-on-alpine-linux/)
|
||||||
|
- [Firewall rules for WireGuard](https://www.cyberciti.biz/faq/how-to-set-up-wireguard-firewall-rules-in-linux/)
|
||||||
|
- [Debian 10 set up WireGuard VPN server](https://www.cyberciti.biz/faq/debian-10-set-up-wireguard-vpn-server/)
|
||||||
|
- [Setting up a private mesh VPN with WireGuard](https://www.scaleway.com/en/docs/wireguard-mesh-network/)
|
||||||
|
- [Wireguard network managers](https://kaspars.net/blog/wireguard-managers)
|
||||||
|
- [wg-gen-web](https://github.com/vx3r/wg-gen-web)
|
||||||
|
|
||||||
|
{{< /admonition >}}
|
||||||
|
|
||||||
|
<!--
|
||||||
|
|
||||||
|
AQUI TENEMOS INSTRUCCIONES PARA NETWORKMANAGER <https://www.xmodulo.com/wireguard-vpn-network-manager-gui.html>
|
||||||
|
- [Referencia Alpine Awall](https://www.cyberciti.biz/faq/how-to-set-up-a-firewall-with-awall-on-alpine-linux/)
|
||||||
|
|
||||||
|
-->
|
||||||
|
|
||||||
|
|
||||||
|
Las implementaciones tradicionales de VPN (_**V**irtual **P**rivate **N**etwork_) más utilizadas en la industria (como _IPsec_ por ejemplo) se implementan dentro del kernel; insertando una capa extra, que se encarga del cifrado y el encapsulado, entre la pila IP y el interfaz de red.
|
||||||
|
|
||||||
|
Esto se hace así por que se quiere que sea un proceso tan rápido como sea posible que no penalice la eficiencia de las comunicaciones. A cambio es necesario implementar por separado el _plano de tráfico_ (la capa que hemos mencionado dentro del kernel) y _el plano de control_ que se crea en el espacio de usuario. Esta arquitectura hace que tanto la implementación (el software) como la gestión de estas soluciones sean complejas.
|
||||||
|
|
||||||
|
En las implementaciones de VPN en el espacio de usuario, como por ejemplo _OpenVPN_, todo el proceso de cifrado lo hace un demonio en el espacio de usuario. Con esta arquitectura inevitablemente se penaliza el rendimiento, por qué los paquetes tienen que pasar del espacio kernel al espacio de usuario y viceversa varias veces. Aunque esto no impide que sean soluciones muy populares debido a su facilidad de uso.
|
||||||
|
|
||||||
|
_WireGuard_ es una alternativa relativamente reciente a _OpenVPN_ que puede ser muy interesante. Por un lado se implementa como un módulo del Kernel, y por otro mantiene la gestión y configuración a un nivel muy asequible por qué usa ficheros de configuración **muy sencillos** y se basa en la metáfora de _interfaz de red_, que se gestiona como cualquier otro interfaz del sistema con las herramientas estándar como `ip` o `ifconfig`.
|
||||||
|
|
||||||
|
_WireGuard_ cifra y encapsula paquetes IP sobre UDP. Básicamente hay que añadir un interface _WireGuard_, configurarlo con tu clave privada y la clave pública de los pares (_peers_) con los que se va a comunicar y ya puedes enviar paquetes a través de ese túnel. En realidad es mucho más parecido a _SSH_ o _Mosh_ que a _OpenVPN_.
|
||||||
|
|
||||||
|
Como hemos dicho, al usar _WireGuard_ se añadirán uno (o varios) interfaces de red de tipo _WireGuard_ (wg0, wg1, ....) a tu máquina. Estos interfaces de red se pueden configurar normalmente con las herramientas del sistema, igual que un `eth0` o `wlan0`. Los aspectos específicos del _WireGuard Interface_ se configuran con la herramienta `wg`. Los interfaces _WireGuard_ se comportan como un túnel cifrado.
|
||||||
|
|
||||||
|
_WireGuard_ asocia las direcciones IP de los túneles con los extremos remotos y sus claves públicas.
|
||||||
|
|
||||||
|
Cuando el interfaz envía un paquete a un _peer_ hace lo siguiente:
|
||||||
|
|
||||||
|
1. Veamos, este paquete es para `192.168.30.8`. ¿Qué _peer_ es este? Vale, es para el _peer_ `pepito`. Si no soy capaz de determinar a que _peer_ esta dirigido descartaré el paquete (_drop_) **¡OJO!** WireGuard determina el _peer_ a partir de la IP destino
|
||||||
|
2. Cifra el paquete con la clave pública del _peer_ `pepito`
|
||||||
|
3. ¿Qué extremo remoto corresponde a este _peer_? Vale, es el puerto UDP 53133 en 216.58.211.110
|
||||||
|
4. Procedo a enviar los bytes cifrados al extremo remoto via UDP
|
||||||
|
|
||||||
|
En el extremo remoto, el _peer_ `pepito`que recibe el paquete:
|
||||||
|
|
||||||
|
1. Me ha llegado un paquete del puerto `7361` de `98.139.183.24`. Voy a descifrarlo.
|
||||||
|
2. Descifro y además compruebo que se garantiza la autenticidad para el peer `manolito`. Ya que estamos actualizo mi tabla de direcciones: Apunto que el destino más reciente para `manolito` es el `98.139.183.24:7361/UDP`
|
||||||
|
3. El paquete descifrado viene de `192.168.43.89` si el _peer_ `manolito` está autorizado a enviar paquetes con esa IP origen lo aceptamos, de lo contrario lo descartamos (_drop_)
|
||||||
|
|
||||||
|
El concepto fundamental en el que se base _WireGuard_ es el ___Cryptokey Routing___, consiste en almacenar una lista de claves públicas junto con la lista de direcciones IP origen que permitimos, ambas asociadas al _peer_ al que corresponde esa clave.
|
||||||
|
|
||||||
|
Así:
|
||||||
|
- Cada interfaz de red tiene una clave privada
|
||||||
|
- Cada interfaz de red tiene una lista de _peers_
|
||||||
|
- Cada _peer_ tiene una clave pública
|
||||||
|
- Para cada _peer_ se especifican las direcciones IP origen autorizadas
|
||||||
|
|
||||||
|
Un _servidor_ de _WireGuard_ podría tener una configuración como esta (no está completa es una configuración simplificada):
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[Interface]
|
||||||
|
PrivateKey = yAnz5TF+lXXJte14tji3zlMNq+hd2rYUIgJBgB3fBmk=
|
||||||
|
ListenPort = 51820
|
||||||
|
|
||||||
|
[Peer]
|
||||||
|
PublicKey = xTIBA5rboUvnH4htodjb6e697QjLERt1NAB4mZqp8Dg=
|
||||||
|
AllowedIPs = 10.192.122.3/32, 10.192.124.1/24
|
||||||
|
|
||||||
|
[Peer]
|
||||||
|
PublicKey = TrMvSoP4jYQlY6RIzBgbssQqY3vxI2Pi+y71lOWWXX0=
|
||||||
|
AllowedIPs = 10.192.122.4/32, 192.168.0.0/16
|
||||||
|
|
||||||
|
[Peer]
|
||||||
|
PublicKey = gN65BkIKy1eCE9pP1wdc8ROUtkHLF2PfAqYdyYBz6EA=
|
||||||
|
AllowedIPs = 10.10.10.230/32
|
||||||
|
```
|
||||||
|
|
||||||
|
Un _cliente_ puede tener una configuración más simple (no está completa):
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[Interface]
|
||||||
|
PrivateKey = gI6EdUSYvn8ugXOt8QQD6Yc+JyiZxIhp3GInSWRfWGE=
|
||||||
|
ListenPort = 21841
|
||||||
|
|
||||||
|
[Peer]
|
||||||
|
PublicKey = HIgo9xNzJMWLKASShiTqIybxZ0U3wGLiUeJ1PKf8ykw=
|
||||||
|
Endpoint = 192.95.5.69:51820
|
||||||
|
AllowedIPs = 0.0.0.0/0
|
||||||
|
```
|
||||||
|
|
||||||
|
Tanto el _"servidor"_ como el _"cliente"_ tienen un interfaz de red (al menos) con su clave privada asociada. Pero no te lies con los términos servidor y cliente, nada impide que configures varios interfaces de tu VPN como servidores.
|
||||||
|
|
||||||
|
El _servidor_ tiene también una lista de _peer_; cada uno con su lista `AllowedIPs`: la lista de direcciones IP origen que están autorizadas para ese _peer_
|
||||||
|
|
||||||
|
La configuración mínima para un cliente solo necesita tener como _peer_ al servidor. Se almacena una dirección ___inicial___ del servidor.
|
||||||
|
|
||||||
|
Deliberadamente no se mantienen direcciones estáticas para los _peer_, los _peer_ se identifican al descifrar un paquete recibido. Y se mantiene una tabla de direcciones más recientes para cada _peer_ que se actualiza con cada mensaje recibido. De esta forma los _peer_ podrían hacer _roaming_ por distintas redes.
|
||||||
|
|
||||||
|
Cuando el servidor recibe un paquete comprueba, una vez descifrado, que el _peer_ puede enviar paquetes con ese origen, en caso que no sea así lo descarta.
|
||||||
|
|
||||||
|
Cuando el servidor quiere enviar un paquete comprueba las redes asociadas a cada _peer_ para decidir a quien enviarlo, y lo envía a la dirección IP más reciente que tenga registrada para ese _peer_.
|
||||||
|
|
||||||
|
En el cliente (con la configuración de ejemplo) se aceptan paquetes de cualquier origen si provienen del _servidor_. También se envian todos los paquetes, sea cual sea la dirección de destino hacia el _servidor_. Como hemos dicho, los paquetes se envían a la dirección registrada más recientemente para el servidor, si el cliente ya ha recibido algún paquete, o a la dirección inicial especificada en la configuración si aún no ha recibido nada desde el _servidor_.
|
||||||
|
|
||||||
|
## Instalación de _WireGuard_
|
||||||
|
|
||||||
|
|
||||||
|
### Instalación de WireGuard en Debian Server 10
|
||||||
|
|
||||||
|
Añadimos `backports` a nuestros orígenes de software e instalamos _WireGuard_.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
echo 'deb http://ftp.debian.org/debian buster-backports main' | sudo tee /etc/apt/sources.list.d/buster-backports.list
|
||||||
|
apt update
|
||||||
|
apt install wireguard
|
||||||
|
```
|
||||||
|
|
||||||
|
_WireGuard_ se ejecuta como un **módulo del kernel**
|
||||||
|
|
||||||
|
Genemos las claves en `/etc/wireguard`
|
||||||
|
|
||||||
|
```bash
|
||||||
|
umask 077
|
||||||
|
wg genkey | sudo tee /etc/wireguard/privatekey | wg pubkey | sudo tee /etc/wireguard/publickey
|
||||||
|
```
|
||||||
|
|
||||||
|
Editamos el fichero `sudo nano /etc/wireguard/wg0.conf` con el contenido:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[Interface]
|
||||||
|
Address = 10.0.0.1/24
|
||||||
|
SaveConfig = true
|
||||||
|
ListenPort = 51820
|
||||||
|
PrivateKey = SERVER_PRIVATE_KEY
|
||||||
|
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -t nat -A POSTROUTING -o ens3 -j MASQUERADE
|
||||||
|
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -t nat -D POSTROUTING -o ens3 -j MASQUERADE
|
||||||
|
```
|
||||||
|
|
||||||
|
El fichero de configuración no tiene por que ser accesible para nadie (`chmod 600 /etc/wireguard/wg0.conf`), al fin y al cabo contiene la clave privada.
|
||||||
|
|
||||||
|
Este fichero de configuración correspondería a un "servidor" de VPN clásico para dar acceso a internet a los "clientes" de la VPN via NAT.
|
||||||
|
|
||||||
|
Los campos del fichero de configuración:
|
||||||
|
|
||||||
|
|
||||||
|
**Address**
|
||||||
|
|
||||||
|
: La dirección IP **privada** (una dirección interna de la VPN) asignada al interfaz. Asignamos IP y máscara en un solo comando.
|
||||||
|
|
||||||
|
**SaveConfig**
|
||||||
|
|
||||||
|
: Si vale `true`la configuración del interfaz se salva en el fichero de configuración cada vez que hacemos un shutdown del interfaz
|
||||||
|
|
||||||
|
**ListenPort**
|
||||||
|
|
||||||
|
: El puerto UDP que escucha nuestro interfaz, los _peer_ (clientes) tienen que dirigirse a ese puerto
|
||||||
|
|
||||||
|
**PrivateKey**
|
||||||
|
|
||||||
|
: La clave de cifrado para este interfaz
|
||||||
|
|
||||||
|
**PostUp**
|
||||||
|
|
||||||
|
: Un comando o un script que se tiene que ejecutar **antes** de levantar el interfaz. En este ejemplo estamos habilitando _IP masquerading_. Esto permitirá que el tráfico salga del servidor dando a los clientes de la VPN acceso a internet (habría que sustituir `ens3` por el verdadero nombre del interfaz público del servidor)
|
||||||
|
|
||||||
|
**PostDown**
|
||||||
|
|
||||||
|
: Un comando o script que se tiene que ejecutar **antes** de bajar el interface. En nuestro ejemplo se borran la configuración de _IP masquerading_ de las IPtables. Es imprescindible sustituir `ens3` por el puerto real del servidor.
|
||||||
|
|
||||||
|
|
||||||
|
Podemos arrancar ya el interfaz `wg0` con el comando `wg-quick up wg0` (en mi caso necesité reiniciar el servidor previamente, supongo que para completar la instalación del módulo wireguard en el kernel)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
root@vmi504132:~# wg-quick up wg0
|
||||||
|
[#] ip link add wg0 type wireguard
|
||||||
|
[#] wg setconf wg0 /dev/fd/63
|
||||||
|
[#] ip -4 address add 10.0.0.1/24 dev wg0
|
||||||
|
[#] ip link set mtu 1420 up dev wg0
|
||||||
|
[#] iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
|
||||||
|
root@vmi504132:~# wg show wg0
|
||||||
|
interface: wg0
|
||||||
|
public key: rgbUE5KCfrUWT/7Vhh7NTdosCyP9LGx7M5vnJU9EAxw=
|
||||||
|
private key: (hidden)
|
||||||
|
listening port: 51820
|
||||||
|
root@vmi504132:~# ip addr show wg0
|
||||||
|
24: wg0: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1420 qdisc noqueue state UNKNOWN group default qlen 1000
|
||||||
|
link/none
|
||||||
|
inet 10.0.0.1/24 scope global wg0
|
||||||
|
valid_lft forever preferred_lft forever
|
||||||
|
```
|
||||||
|
|
||||||
|
Hasta aquí hemos configurado nuestro nuevo interfaz `wg0` pero necesitamos completar un par de cosas más antes de terminar:
|
||||||
|
|
||||||
|
#### Abrir el cortafuegos para WireGuard
|
||||||
|
|
||||||
|
Tenemos que permitir tráfico entrante UDP en el puerto `51820`, en mi caso estoy usando UFW en el servidor:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ufw allow 51820/udp
|
||||||
|
ufw enable
|
||||||
|
ufw status numbered
|
||||||
|
ufw status verbose
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Habilitar _ip forwarding_
|
||||||
|
|
||||||
|
Editamos el fichero `/etc/sysctl.conf` y descomentamos la linea:
|
||||||
|
|
||||||
|
`net.ipv4.ip_forward=1`
|
||||||
|
|
||||||
|
Recargamos el fichero ejecutando `sysctl -p /etc/sysctl.conf`
|
||||||
|
|
||||||
|
Evidentemente si queremos usar IPV6 tenemos que descomentar la linea correspondiente.
|
||||||
|
|
||||||
|
#### Configurar el arranque automático del interfaz cuando arranca el servidor
|
||||||
|
|
||||||
|
Para dejar configurado el arranque automático del interfaz `wg0`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
wg-quick down wg0 # Paramos el interfaz que hemos levantado manualmente
|
||||||
|
|
||||||
|
systemctl enable wg-quick@wg0 # Dejamos el servicio habilitado
|
||||||
|
systemctl status wg-quick@wg0 # Comprobamos el status del servicio
|
||||||
|
|
||||||
|
|
||||||
|
# systemctl start wg-quick@wg0 # Comandos para arrancar o parar el servicio
|
||||||
|
# systemctl stop wg-quick@wg0 # manualmente
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### Creación de una máquina virtual en Proxmox con Alpine Linux y WireGuard
|
||||||
|
|
||||||
|
Creamos la máquina virtual igual que creamos la de Docker
|
||||||
|
|
||||||
|
1. Creamos la máquina virtual, basada en la ISO de _Alpine Linux_, asignamos un disco duro de 16Gb
|
||||||
|
2. Ejecutamos `alpine-setup` asignamos IP estática y el tipo de instalación `sys`
|
||||||
|
2. Instalamos `qemu-guest-agent` y configuramos adecuadamente
|
||||||
|
3. Instalamos `sudo` y habilitamos el grupo `wheel` (editando `/etc/sudoers`)
|
||||||
|
3. Añadimos usuario `wgadmin` (ya de paso lo metemos en `wheel`)
|
||||||
|
4. Instalamos UFW
|
||||||
|
5. Instalamos el WireGuard
|
||||||
|
|
||||||
|
```bash
|
||||||
|
apk add sudo
|
||||||
|
addgroup wgadmin
|
||||||
|
adduser -G wgadmin wgadmin
|
||||||
|
adduser wgadmin wheel
|
||||||
|
apk add ufw
|
||||||
|
ufw default deny incoming
|
||||||
|
ufw default allow outgoing
|
||||||
|
ufw allow ssh
|
||||||
|
ufw enable
|
||||||
|
apk add wireguard-tools
|
||||||
|
```
|
||||||
|
|
||||||
|
Ya tenemos todo listo para proceder con la configuración de _WireGuard_
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /etc/wireguard
|
||||||
|
umask 077; wg genkey | tee privatekey | wg pubkey > publickey
|
||||||
|
```
|
||||||
|
|
||||||
|
Creamos el fichero de configuración `wg0.conf`
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[Interface]
|
||||||
|
Address = 10.0.0.2/24
|
||||||
|
ListenPort = 51820
|
||||||
|
PrivateKey = 2IHAoIOz+tWxRZ4oRlI1xHiD5FADVBTKOePnLSZNSkw=
|
||||||
|
|
||||||
|
|
||||||
|
[Peer]
|
||||||
|
PublicKey = d7TRyBXIX0I3sC/tPOqrIpNAGwEt2bW43QXKK4cEeGw=
|
||||||
|
AllowedIPs = 0.0.0.0/0
|
||||||
|
Endpoint = 207.180.207.206:51820
|
||||||
|
PersistentKeepalive = 20
|
||||||
|
```
|
||||||
|
|
||||||
|
Habilitamos el _IP Forwarding_:
|
||||||
|
|
||||||
|
Por comando: `sysctl net.ipv4.ip_forward=1`
|
||||||
|
|
||||||
|
O si lo queremos permanente añadimos la linea `net.ipv4.ip_forward=1` en el fichero `/etc/sysctl.conf`
|
||||||
|
|
||||||
|
También tenemos que abrir el cortafuegos `ufw allow 51820/udp`
|
||||||
|
|
||||||
|
Ya podemos levantar el interfaz con `wg-quick up wg0`
|
||||||
|
|
||||||
|
Para que la cosa funcione tenemos que habilitar la redirección del puerto 51820/udp en nuestro router de internet para que apunte a la máquina virtual que hemos creado.
|
||||||
|
|
||||||
|
Llegamos por ping a la maquina siriowg pero no más allá (faltan rutas de vuelta hacia el servidor)
|
||||||
|
|
||||||
|
<!--
|
||||||
|
|
||||||
|
### Escenario: Salida a internet via VPN para el servidor HASS
|
||||||
|
|
||||||
|
Configuración de VPN server (el "servidor central")
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[Interface]
|
||||||
|
Address = 10.200.200.1/24
|
||||||
|
PrivateKey = <vps_privatekey>
|
||||||
|
ListenPort = 37466
|
||||||
|
|
||||||
|
# Do not forget to change eth0 to the interface that is connected to the Internet!
|
||||||
|
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables - tnat -A POSTROUTING - oeth0 -j MASQUERADE
|
||||||
|
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables - tnat -D POSTROUTING - oeth0 -j MASQUERADE
|
||||||
|
|
||||||
|
# This is the peer inside the local subnet we want to have access to.
|
||||||
|
# For that to happen, you need to add your local subnet to the AllowedIPs
|
||||||
|
# option just like I did below.
|
||||||
|
[Peer]
|
||||||
|
PublicKey = <pi_publickey>
|
||||||
|
AllowedIPs = 10.200.200.2/32, 192.168.1.0/24
|
||||||
|
|
||||||
|
# A client...
|
||||||
|
[Peer]
|
||||||
|
PublicKey = <client_publickey>
|
||||||
|
AllowedIPs = 10.200.200.3/32
|
||||||
|
|
||||||
|
# An additional client...
|
||||||
|
[Peer]
|
||||||
|
PublicKey = <some other public key>
|
||||||
|
AllowedIPs = 10.200.200.4/32
|
||||||
|
```
|
||||||
|
|
||||||
|
Configuración en el cliente
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[Interface]
|
||||||
|
Address = 10.200.200.2/24
|
||||||
|
PrivateKey = <pi_privatekey>
|
||||||
|
DNS = 1.1.1.1 # you can also use your own DNS server
|
||||||
|
|
||||||
|
[Peer]
|
||||||
|
PublicKey = <vps_publickey>
|
||||||
|
Endpoint = <vps_public_ip>:37466 # do not forget to put your VPS IP here
|
||||||
|
AllowedIPs = 0.0.0.0/0, ::/0
|
||||||
|
PersistentKeepalive = 25 # keep connections alive across NAT
|
||||||
|
```
|
||||||
|
CONFIGURACION DE ADDON WIREGUARD EN MODO (PSEUDO)CLIENTE
|
||||||
|
|
||||||
|
Instalamos el addon de Wireguard en Hassio.
|
||||||
|
|
||||||
|
Tras la instalación, en el host del Hassio aparecerá un nuevo directorio para el addon que estará inicialmente vacío:
|
||||||
|
|
||||||
|
/mnt/data/supervisor/addons/data/a0d7b954_wireguard
|
||||||
|
|
||||||
|
También podemos comprobar que en el directorio de claves ssl para los addons, no hay ningún dato todavía del wireguard:
|
||||||
|
|
||||||
|
/mnt/data/supervisor/ssl
|
||||||
|
|
||||||
|
Si arrancamos el addon con los datos de configuración por defecto, vemos que aparece un fichero "options.json" que contiene la configuración por defecto.
|
||||||
|
|
||||||
|
/mnt/data/supervisor/addons/data/a0d7b954_wireguard/options.json
|
||||||
|
|
||||||
|
También podemos ver que tras arrancar el addon, aparece un directorio para wireguard en el directorio de claves ssl:
|
||||||
|
|
||||||
|
/mnt/data/supervisor/ssl/wireguard
|
||||||
|
|
||||||
|
En este directorio de claves tendremos un fichero "private_key" que contendrá la clave privada del addon, así como una carpeta llamada "hassio". Esta carpeta corresponde a la configuración del cliente de Wireguard que se crea en la configuración por defecto. Si modificamos esa configuración y declaramos varios clientes de Wireguard, nos aparecerán varias carpetas cada una con el nombre que le hayamos puesto.
|
||||||
|
|
||||||
|
client.conf
|
||||||
|
Fichero con la configuración del cliente de la configuración por defecto. Este fichero, si quisiésemos usar el addon como servidor (que es lo que se hace habitualmente) nos lo deberíamos llevar al PC que quisiésemos usar para conectarnos remotamente a nuestro Hassio. Contiene tanto la clave privada del cliente como la clave pública de nuestro Hassio, así como otros parámetros de la configuración por defecto. OJO: La carpeta hassio es una carpeta para el cliente de Wireguard, no para nuestra instancia de Hassio.
|
||||||
|
|
||||||
|
private_key
|
||||||
|
Fichero con la clave privada del cliente Wireguard. Es la misma que aparece en el fichero client.conf, así que no aporta nada nuevo.
|
||||||
|
|
||||||
|
qrcode.png
|
||||||
|
Este fichero contiene una imagen de un código QR que codifica el contenido del fichero client.conf. Si nos llevamos este fichero a un PC y lo visualizamos, podremos cargar la configuración desde la aplicación para móviles de Wireguard de forma fácil y sencilla.
|
||||||
|
|
||||||
|
|
||||||
|
Bueno, pues hasta aquí la descripción sobre dónde se almacena la configuración del addon de Wireguard en Hassio. En cada arranque del addon, un script se encarga de procesar estos ficheros e incorporarlos a la configuración interna de Wireguard dentro del contenedor.
|
||||||
|
|
||||||
|
Podríamos entrar en el contenedor y modificar la configuración de Wireguard a nuestro gusto, pero esa configuración se perdería tras un reinicio.
|
||||||
|
|
||||||
|
Podríamos modificar a mano los ficheros de configuración en el host de Hassio, pero si usásemos alguna opción de configuración no contemplada por el script que traduce e incorpora el json al contenedor, tampoco serviría de nada.
|
||||||
|
|
||||||
|
Pero, por fortuna, hay algunas opciones que sí se permiten en el fichero json y que por lo tanto son reconocidas por el addon, que nos permiten hacer que el nuestra instancia de Hassio sea la que intente establecer las conexiones hacia los clientes.
|
||||||
|
|
||||||
|
A partir de este punto vamos a explicar la configuración necesaria para que nuestro addon de Wireguard se comporte como un cliente e inicie la conexión hacia otro servidor Wireguard que tengamos accesible públicamente, por ejemplo en un VPS.
|
||||||
|
|
||||||
|
Vamos a cargar la siguiente configuración:
|
||||||
|
|
||||||
|
*****************************************************************
|
||||||
|
server:
|
||||||
|
host: 10.10.10.10
|
||||||
|
addresses:
|
||||||
|
- 10.22.10.2
|
||||||
|
private_key: <ponga aqui la clave privada del peer que corresponde al Hass, sin comillas ni ná>
|
||||||
|
dns: []
|
||||||
|
peers:
|
||||||
|
- name: hassvpn (aquí podemos poner el nombre que queramos)
|
||||||
|
public_key: <ponga aqui la clave pública del Wireguard del VPS, sin comillas ni ná>
|
||||||
|
endpoint: 'x.x.x.x:yyyy' #Esta es la IP del VPS y el puerto por donde está escuchando el Wireguard
|
||||||
|
addresses:
|
||||||
|
- 10.22.10.1
|
||||||
|
allowed_ips:
|
||||||
|
- 10.22.10.0/24
|
||||||
|
client_allowed_ips: []
|
||||||
|
log_level: info
|
||||||
|
*****************************************************************
|
||||||
|
|
||||||
|
Pero antes de cargarla en el addon, aclaremos algunas cosas:
|
||||||
|
|
||||||
|
Se supone que ya tenemos un Wireguard configurado en nuestro VPS, y queremos que nuestro Hassio se conecte a él. Por lo tanto, ya hemos generado en nuestro VPS las claves públicas y privadas de todos los miembros de la VPN. Lo que vamos a hacer es que el addon de Wireguard en nuestro Hassio adopte esas claves en lugar de utilizar las que ha generado él al iniciarse.
|
||||||
|
|
||||||
|
Por lo tanto, lo que estamos haciendo es algo así como montar una VPN donde hay dos servidores: por un lado el que hemos montado en nuestro VPS, y por otro lado el addon de nuestro Hassio, que está pensado para actuar también como servidor.
|
||||||
|
|
||||||
|
Es necesario aclarar que en la filosofía de diseño que se ha seguido en Wireguard no existen realmente ni servidores ni clientes, sino que todos se comportan como peers al mismo nivel. Lo que diferencia a un servidor de un cliente es que el servidor no intenta iniciar la comunicación con ningún cliente, sino que se mantiene a la escucha. La razón lógica es que los clientes pueden tener cualquier IP porque su ubicación es la que puede cambiar, mientras que el servidor es la máquina que tiene una dirección invariable y conocida por todos los demás, y por lo tanto es a quien intentarán conectarse.
|
||||||
|
|
||||||
|
La otra pequeña diferencia que hay entre un servidor y un cliente en Wireguard, es que en el servidor se configura un NAT por defecto para que los clientes de la VPN puedan salir al exterior (este es el cometido general de una VPN). Pero a nivel de establecimiento de los túneles, todos los miembros de la VPN se comportan igual: cada uno tiene su clave privada y conoce la clave pública de su interlocutor.
|
||||||
|
|
||||||
|
|
||||||
|
Ahora una breve explicación de los campos:
|
||||||
|
|
||||||
|
- server.host: Es la dirección INTERNA de nuestro Hassio, es decir, la IP que usamos para acceder a él cuando estamos en nuestra red doméstica.
|
||||||
|
|
||||||
|
- server.addresses: Será la dirección IP que asignemos para el interfaz del túnel de la VPN. En este ejemplo, yo tengo un servidor Wireguard funcionando con la 10.22.10.1, así que le asigno la 10.22.10.2 a mi Hassio, la 10.22.10.3 a mi móvil, y así con cada uno de los clientes vaya a tener la VPN.
|
||||||
|
|
||||||
|
- server.private_key: Esta es una de las claves de cliente (peer) que se han generado en el Wireguard de nuestro VPS. OJO!!! No es la clave privada del servidor Wireguard del VPS, sino que es la clave privada de uno de los peer que se ha generado. De todos los peer que hayamos generado en el VPS, debemos elegir uno para que sea utilizado por nuestro Hassio.
|
||||||
|
|
||||||
|
- server.dns: Aquí podemos indicarle el DNS que queremos que se utilice en la VPN. Si no indicamos nada, el addon usará el servicio de DNS por defecto del Hassio.
|
||||||
|
|
||||||
|
- peers.name: Es el nombre del cliente con el que se conectará nuestro Hassio. Es decir, es el nombre que tendrá nuestro VPS a ojos del Hassio. En el ejemplo le hemos llamado hassvpn.
|
||||||
|
|
||||||
|
- peers.name.public_key: Es la clave pública del cliente con el que se conectará nuestro Hassio. Es decir, es la clave pública de nuestro servidor Wireguard del VPS.
|
||||||
|
|
||||||
|
- peers.name.endpoint: Es la IP:puerto (pública, se entiende), o bien la URL:puerto, del cliente con el que se conectará nuestro Hassio. Es decir, es la IP/URL de nuestro VPS con el puerto donde esté escuchando el Wireguard de nuestro VPS.
|
||||||
|
|
||||||
|
- peers.name.addresses: Es la dirección IP del interfaz del túnel en el Wireguard de nuestro VPS. Como ya hemos dicho antes, lo habíamos configurado para que usase la 10.22.10.1, así que aquí pondremos esa misma.
|
||||||
|
|
||||||
|
- peers.name.allowed_ips: Es una enumeración de direcciones IP's a las que queremos llegar por el túnel, o de las que permitiremos que nos lleguen paquetes por él. Esta línea se comporta como una especia de enrutamiento y filtro de entrada. A la hora de transmitir paquetes, nuestro Hass solo enviará por el túnel los que vayan dirigidos a las subredes que anotemos aquí. A la hora de recibir paquetes, nuestro Hass solo hará caso a los tengan procedencia de alguna de las subredes que anotemos aquí. En nuestro ejemplo, nosotros solamente admitiremos paquetes que provengan de algún miembro de la VPN, por lo que tan solo anotaremos la subred que hemos elone que ya tenemos un Wireguard configurado en nuestro VPS, y queremos que nuestro Hassio se conecte a él. Por lo tanto, ya hemos generado en nuestro VPS las claves públicas y privadas de todos los miembros de la VPN. Lo que vamos a hacer es que el addon de Wireguard en nuestro Hassio adopte esas claves en lugar de utilizar las que ha generado él al iniciarse.
|
||||||
|
|
||||||
|
Por lo tanto, lo que estamos haciendo es algo así como montar una VPN donde hay dos servidores: por un lado el que hemos montado en nuestro VPS, y por otro lado el addon de nuestro Hassio, que está pensado para actuar también como servidor.
|
||||||
|
|
||||||
|
Es necesario aclarar que en la filosofía de diseño que se ha seguido en Wireguard no existen realmente ni servidores ni clientes, sino que todos se comportan como peers al mismo nivel. Lo que diferencia a un servidor de un cliente es que el servidor no intenta iniciar la comunicación con ningún cliente, sino que se mantiene a la escucha. La razón lógica es que los clientes pueden tener cualquier IP porque su ubicación es la que puede cambiar, mientras que el servidor es la máquina que tiene una dirección invariable y conocida por todos los demás, y por lo tanto es a quien intentarán conectarse.
|
||||||
|
|
||||||
|
La otra pequeña diferencia que hay entre un servidor y un cliente en Wireguard, es que en el servidor se configura un NAT por defecto para que los clientes de la VPN puedan salir al exterior (este es el cometido general de una VPN). Pero a nivel de establecimiento de los túneles, todos los miembros de la VPN se comportan igual: cada uno tiene su clave privada y conoce la clave pública de su interlocutor.
|
||||||
|
|
||||||
|
|
||||||
|
Ahora una breve explicación de los campos:
|
||||||
|
|
||||||
|
- server.host: Es la dirección INTERNA de nuestro Hassio, es decir, la IP que usamos para acceder a él cuando estamos en nuestra red doméstica.
|
||||||
|
|
||||||
|
- server.addresses: Será la dirección IP que asignemos para el interfaz del túnel de la VPN. En este ejemplo, yo tengo un servidor Wireguard funcionando con la 10.22.10.1, así que le asigno la 10.22.10.2 a mi Hassio, la 10.22.10.3 a mi móvil, y así con cada uno de los clientes vaya a tener la VPN.
|
||||||
|
|
||||||
|
- server.private_key: Esta es una de las claves de cliente (peer) que se han generado en el Wireguard de nuestro VPS. OJO!!! No es la clave privada del servidor Wireguard del VPS, sino que es la clave privada de uno de los peer que se ha generado. De todos los peer que hayamos generado en el VPS, debemos elegir uno para que sea utilizado por nuestro Hassio.
|
||||||
|
|
||||||
|
- server.dns: Aquí podemos indicarle el DNS que queremos que se utilice en la VPN. Si no indicamos nada, el addon usará el servicio de DNS por defecto del Hassio.
|
||||||
|
|
||||||
|
- peers.name: Es el nombre del cliente con el que se conectará nuestro Hassio. Es decir, es el nombre que tendrá nuestro VPS a ojos del Hassio. En el ejemplo le hemos llamado hassvpn.
|
||||||
|
|
||||||
|
- peers.name.public_key: Es la clave pública del cliente con el que se conectará nuestro Hassio. Es decir, es la clave pública de nuestro servidor Wireguard del VPS.
|
||||||
|
|
||||||
|
- peers.name.endpoint: Es la IP:puerto (pública, se entiende), o bien la URL:puerto, del cliente con el que se conectará nuestro Hassio. Es decir, es la IP/URL de nuestro VPS con el puerto donde esté escuchando el Wireguard de nuestro VPS.
|
||||||
|
|
||||||
|
- peers.name.addresses: Es la dirección IP del interfaz del túnel en el Wireguard de nuestro VPS. Como ya hemos dicho antes, lo habíamos configurado para que usase la 10.22.10.1, así que aquí pondremos esa misma.
|
||||||
|
|
||||||
|
- peers.name.allowed_ips: Es una enumeración de direcciones IP's a las que queremos llegar por el túnel, o de las que permitiremos que nos lleguen paquetes por él. Esta línea se comporta como una especia de enrutamiento y filtro de entrada. A la hora de transmitir paquetes, nuestro Hass solo enviará por el túnel los que vayan dirigidos a las subredes que anotemos aquí. A la hora de recibir paquetes, nuestro Hass solo hará caso a los tengan procedencia de alguna de las subredes que anotemos aquí. En nuestro ejemplo, nosotros solamente admitiremos paquetes que provengan de algún miembro de la VPN, por lo que tan solo anotaremos la subred que hemos elegido para asignar IP's a los interfaces de los túneles, la 10.22.10.0/24.
|
||||||
|
|
||||||
|
- peers.name.client_allowed_ips: Este campo es similar al anterior, pero aplicaría a la hora de generar los ficheros de configuración de los clientes del addon. Es decir, lo que pongamos en este campo sería lo que aparecería en el "allowed_ips" del fichero de configuración del cliente. NO AFECTA AL FUNCIONAMIENTO DEL ADDON YA QUE SOLO SE USA PARA GENERAR FICHEROS DE CONFIGURACION PARA OTRAS MAQUINAS. Como nosotros no vamos a usar estos ficheros porque ya tenemos nuestro Wireguard configurado en el VPS, no vamos a poner nada aquí.
|
||||||
|
|
||||||
|
- log_level: Aquí podemos indicar varios niveles de logging, con más o menos detalle. El valor habitual es "info". Si ponemos "trace" tendremos más información de depuración. Los valores posibles están indicados en la documentación del addon que podemos consultar directamente desde el Supervisor de nuestro Hassio.
|
||||||
|
|
||||||
|
|
||||||
|
Explicado todo esto, y si personalizamos la configuración que hemos puesto anteriormente, podemos cargarla directamente en nuestro addon a través del interfaz del Supervisor. Al guardar la nueva configuración, nos preguntará si queremos reiniciar el addon, a lo que deberemos responder que sí. Si todo ha ido bien, nuestro Hassio ya debería estar conectándose a nuestro VPS.
|
||||||
|
|
||||||
|
Si después de reiniciar el addon comprobamos el contenido de los directorios que hemos comentado antes, podremos comprobar varias cosas:
|
||||||
|
|
||||||
|
- El fichero options.json del directorio /mnt/data/supervisor/addons/data/a0d7b954_wireguard contendrá nuestra configuración personalizada.
|
||||||
|
- El fichero private_key del directorio /mnt/data/supervisor/ssl/wireguard todavía contiene la clave privada que generó el addon la primera vez que lo iniciamos. No nos debe preocupar, porque prevalece lo que hayamos indicado en el fichero de configuración.
|
||||||
|
- En el directorio /mnt/data/supervisor/ssl/wireguard se habrá creado una carpeta con el mismo nombre que le hemos dado a nuestro cliente (en nuestro ejemplo, hassvpn). En esta carpeta habrá dos ficheros, uno llamado client.conf y otro qrcode.png. Estos ficheros serían los que tendríamos que llevarnos al cliente (ojo, al cliente del Hassio, es decir, el VPS) si las claves y la configuración la hubiésemos hecho desde el Hassio. Como en nuestro caso todas las claves se generaron en el VPS, no tenemos que hacer nada con estos ficheros. También debemos fijarnos en la ausencia de private_key en el directorio hassvpn. Esto se debe a que como hemos indicado una clave pública en la configuración, el addon no genera ninguna clave privada para el cliente porque interpreta que para ese cliente ya tenemos las claves generadas (además de que es imposible calcular la clave privada a partir de la clave pública).
|
||||||
|
|
||||||
|
El último paso, y yo creo que recomendable, es ocultar un poco la clave privada de la configuración del addon en el Hassio. Para ello, podemos eliminar directamente la línea correspondiente de la configuración del addon siempre que editemos el fichero private_key del directorio /mnt/data/supervisor/ssl/wireguard y la pongamos ahí, sustituyendo a la que había generado el addon de forma automática.
|
||||||
|
|
||||||
|
-->
|
Loading…
Reference in new issue