doc: Add general notes

main
Sergio Alvariño 11 months ago
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

@ -0,0 +1,294 @@
---
weight: 4
title: "Apuntes de Aikido"
date: 2020-09-20T11:37:21+0200
draft: true
summary: "Apuntes de Aikido"
hiddenFromHomePage: true
categories:
- notes
tags:
- aikido
---
## Programa Aikido
### Kyu
#### 6TO KYU (40 Días)
<!--
https://budodragon.com/all-aikido-stances-and-postures/
https://southmountainaikido.com/glossary/
http://www.pinner-aikido.com/en/aikido/knowledge-base/tenkan-433#contentskip
https://budodragon.com/how-to-do-the-aikido-sankyo-wrist-lock/
https://www.youtube.com/watch?v=hhMMaxSTGtg
https://www.youtube.com/watch?v=Z-2migTtvv8 <<-- Tenshin
Hakamas:
Bujin https://www.aikido24.com/hakama/bu-jin-hakama-aikido#10c06f735ec27bcbf0edb7b215746189
Iwata: https://www.budoya.es/es/para-aikido/340-hakama-iwata-cintas-alargadas.html#/talla-25/color_tela-negro
Nobakama (Italiana de lino más algodón) http://budodesign.es/comprar-hakama-aikido-kendo-iaido/812-hakama-blanca-2300100005614.html
Noris: https://www.dragonsports.eu/es/36327-hakama-gama-alta-aikikai-noris.html
Iwata: https://www.dragonsports.eu/es/36328-iwata-hakama-de-alta-gama-tokio-noris.html
Tozando básica: https://tozandoshop.com/products/tsubasa-stretch-aikido-hakama?variant=34119939555461
Okuri Ashi: Avanzar en la guardia básica sin cruzar las piernas
Ayumi Ashi: Avanzar en la guardia básica cruzando las piernas, primero avanza la atrasada)
Sugi Ashi: Avanzar en la guardia básica sin cruzar las piernas adelantando la de atrás primero
Tenkan: Girar 180 grados sobre la pierna adelantada
Irimi-Tenkan: Girar 180 grados adelantando una pierna que termina siendo la pierna adelantada tras el giro
Irimi-Kaiten: Girar 180 grados adelantando una pierna que termina siendo la pierna atrasada tras el giro
-->
- Tai Sabaki:
- Hidari / Migi Hanmi (Pie izq. adelantado / Pie dch. adelantado)
- Irimi (Tsugi-ashi, Ayumi-Ashi)
- Kaiten
- Tenkan
- Irimi-tenkan
- Tenshin
- Irimi-Tenshin
- Shikko:
- Shikko
- Shikko Tai Sabaki
- Ukemis:
- Mae Kaiten
- Ushiro Kaiten
- Mae Yoko Kaiten,
- Uchiro Yoko Kaiten
- Uchiro Mae Kaiten
- Uchiro Mae Yoko Kaiten
- Uchiro Otoshi.
- Técnicas:
- Katate Dori Ai-hanmi Ikkyo (Omote & Ura)
- Katate Dori Ai-hanmi Iriminage (Omote & Ura)
- Katate Dori Ai-hanmi Shihonage (Omote & Ura)
- Katate Dori Ai-hanmi Kotegaeshi (Omote & Ura)
- Katate Dori Ai-hanmi Nikyo (Omote & Ura)
#### 5TO KYU (60 Días)
##### Conocimientos
- Kokyuho
- Shikko
##### Tachi Waza
- Shomen uchi Ikkyo (Omote & Ura)
- Shomen uchi Nikyo (Omote & Ura)
- Shomen uchi Kotegaeshi (Omote & Ura)
- Chudan Tsuki Iriminage (Omote & Ura)
- Chudan Tsuki Kotegaeshi (Omote & Ura)
- Katatedori Shihonage (Omote - Ura)
- Katatedori Tenchinage
- Katatedori Ikkyo (Omote - Ura)
- Katatedori Udekimenage (Omote - Ura)
- Katatedori Kokyunage
<!-- - Shomen uchi Iriminage (Omote & Ura)
- Ryote Dori Tenchi nage (Omote & Ura)
- Ushiro Tekubi Dori Kotegaeshi (Omote & Ura)
- Morote Dori Kokyuho Nage (Omote & Ura)
-->
##### Suwari Waza
- Shomen uchi Ikkyo (Omote - Ura)
- Katadori Ikkyo (Omote - Ura)
#### 4TO KYU (90 Días)
##### Tachi Waza
- Shomen uchi Sankyo (Omote - Ura)
- Shomen uchi Uchikaiten Sankyo
- Yokomen uchi Shihonage (Omote - Ura)
- Yokomen uchi Iriminage (Omote - Ura)
- Yokomen uchi Tenchinage
- Yokomen uchi Kotegaeshi
- Yokomen uchi Udekimenage
- Chundan tsuki Udekimenage
- Chundan tsuki Hijikimeosae
- Jodan tsuki Ikkyo (Omote - Ura)
- Ryotedori Shihonage (Omote - Ura)
- Ryotedori Tenchinage
- Ryotedori Udekimenage
- Ryotedori Ikkyo (Omote - Ura)
- Katatedori Nikyo (Omote - Ura)
- Katateryotedori Kotegaeshi
##### Suwari Waza
- Shomen uchi Nikyo (Omote - Ura)
- Katadori Nikyo (Omote - Ura)
- Ryotedori Kokyuho
<!-- - Shomen uchi Nikkyo (Omote & Ura)
- Yokomen uchi Shihonage (Omote & Ura) (3 formas)
- Chudan Tsuki Iriminage (Omote & Ura)
- Ushiro Tekubi Dori Sankyo (Omote & Ura)
- Ushiro Ryo kata Dori Kotegaeshi (Omote & Ura)
- Katate Dori Gyaku Hanmi Nikkyo (Omote & Ura)
- Suwari waza Shomen uchi Ikkyo (Omote & Ura)
- Suwari waza Kata dori Nikkyo (Omote & Ura)
- Suwari waza Kata dori Sankyo (Omote & Ura)
BUKI WAZA :
- Aiki Ken no subiri (7)
- Aiki Ken no Awase (4)
-->
#### 3ER KYU (100 Días)
- Shomen uchi Sankyo (Omote & Ura)
- Shomen uchi Yonkyo (Omote & Ura)
- Yokomen uchi Iriminage (Omote & Ura) (3 formas)
- Yokomen uchi Kotegaeshi (Omote & Ura) (3 formas)
- Chudan Tsuki Kaiten nage uchi (Omote & Ura)
- Chudan Tsuki Kaiten nage soto (Omote & Ura)
- Ushiro Ryo kata Dori Sankyo (Omote & Ura)
- Morote Dori Iriminage (Omote & Ura) (3 formas)
- Morote dori Jujinage (Irimi, Tenkan)
- Suwari waza Shomen uchi Iriminage (Omote & Ura)
- Suwari waza Shomen uchi Nikkyo (Omote & Ura)
- Suwari waza Shomen uchi Sankyo (Omote & Ura)
- Hanmi handachi Katate Dori Shihonage (Omote & Ura)
- Hanmi handachi Katate Dori Kaiten nage Uchi (Omote & Ura)
- Hanmi handachi Katate Dori Kaiten nage Soto (Omote & Ura)
BUKI WAZA :
- Zengo, Shiho, Happo Giri (ken)
- Ki musubi no tachi
- Aiki jo no suburi (20)
#### 2DO KYU (200 Días)
- Shomen uchi Shihonage (Omote & Ura)
- Shomen uchi Kaiten nage Uchi (Omote & Ura)
- Shomen uchi Kaiten nage Soto (Omote & Ura)
- Yokomen uchi Gokyo (Omote & Ura)
- Ushiro Ryo tekubi Dori Shihonage (Omote & Ura)
- Ushiro Ryo Tekubi Dori Jujinage
- Ushiro Kubishime Koshinage (2 Formas)
- Morote Dori Nikkyo (Omote & Ura) (Ai-hanmi, Gyaku-hanmi)
- Hanmi handanchi Shomen uchi Iriminage (Omote & Ura)
- Hanmi handanchi Katate dori Gyaku Hanmi Nikkyo (Omote & Ura)
- Hanmi handanchi Yokomen uchi Kotegaeshi (Omote & Ura)
- Futari Dori: 2 Personas
- Randori: 3 Personas
BUKI WAZA:
- Zengo, Shiho, Happo Giri (Jo)
- Ku no Kata (9)
- Aiki Ken Buki Dori (5 variaciones)
- Aiki Jo Buki dori (5 variaciones)
- Tanto Dori (5)
#### 1ER KYU (300 Días)
Todos los requerimientos de los Kyu Anteriores.
JIYU WAZA:
- Kata Dori menuchi 5 técnicas
- Yokomen uchi 5 técnicas
- Morote Dori 5 técnicas
- Shomen uchi 5 técnicas
- Tsuki 5 técnicas
- Ryote Dori 5 técnicas
- Uchiro Waza 5 técnicas
- Koshinage 5 técnicas
- Hanmi handachi Ushiro Waza 5 técnicas
- Tanto Dori (5)
- Randori: 5 Personas
BUKI WAZA:
- Ju san Jo no kata (13)
- San Su ichi jo no kata (31)
- Buki Dori (2 ukes)
### Técnicas Kyu por ataques
#### Ai-hammi Katatedori
- (6 Kyu) Iriminage (Omote-Ura)
- (6 Kyu) Kotegaeshi
- (6 Kyu) Ikkyo (Omote-Ura)
- (6 Kyu) Nikkyo (Omote-Ura)
- (6 Kyu) Sankyo (Omote-Ura)
- (6 Kyu) Shihonage (Omote-Ura)
- (6 Kyu) Uchikaitennage
#### Katatedori (Gyaky-hammi)
- (5 Kyu) Shihonage (Omote-Ura)
- (5 Kyu) Tenchinage (Omote-Ura)
- (5 Kyu) Ikkyo (Omote-Ura)
- (5 Kyu) Udekiminage (Omote-Ura)
- (5 Kyu) Kokyunage
- (4 Kyu) Nikyo (Omote-Ura)
- (3 Kyu) Uchikaitennage
- (3 Kyu) Sankyo (Omote-Ura)
- (3 Kyu) Yonkyo (Omote-Ura)
##### Ushiro Waza
- (2 Kyu) Katatedori Kubishime - Ikkyo
- (1 Kyu) Katatedori Kubishime - Sankyo
- (1 Kyu) Katatedori Kubishime - Nikyo
##### Hamihandachi Waza
- Shihonage (Omote-Ura)
- Uchikaitennage
- Ikkyo (Omote-Ura)
#### Shomen Uchi
#### Yokomen Uchi
### DAN
#### SHODAN (300 Días)
- Todos los requerimientos de 1er Kyu
- Henka Waza
- Aiki ken Dori,
- Aiki Jo Dori (jo uke, jo nage)
- 2 Randori de 5 Atacantes.
- Kumi tachi (5) Básico
#### NIDAN (600 Días)
- Todos los requerimientos de Shodan.
- Aiki Jo Dori 2 atacantes
- Aiki Ken Dori 2 atacantes
- Kaeshi Waza
- Randori 5 atacantes
- Kumi tachi (5) y variaciones, (Ken no Ri, Tai no Ri)
- Kumi Jo (10)
#### SANDAN (700 Días)
Sujeto a exámen o promoción según el examinador. Debe asistir a dos seminarios por año.
Todos los requerimientos de Nidan + Buki Waza:
- Kumi Jo (Variaciones)
#### YONDAN (4 años después del Sandan)
Sujeto a exámen o promoción según el examinador. Debe asistir a dos seminarios por año.
- Ken tai Jo (7) (Variaciones)

File diff suppressed because it is too large Load Diff

@ -0,0 +1,684 @@
---
weight: 4
title: "Apuntes de Domótica"
date: 2020-11-03T18:01:27+0100
draft: false
summary: "Notas sobre Domótica"
categories:
- notes
tags:
- domotica
- micros
- mqtt
- mosquitto
- influxdb
- grafana
- homeassistant
---
Apuntes **no terminados** sobre Domótica Libre
<!--more-->
{{< admonition type=warning title="Work in progress" open=true >}}
Estos apuntes no están completos, (ni de lejos)
{{< /admonition >}}
## Grupo de investigación
* Fundado el 2020-11-02, tenemos grupo de telegram y BBB.
* [Cryptpad del grupo de domótica](https://cryptpad.fr/pad/#/2/pad/edit/+K6cC9t-UGKfem6AdmkJ93ja/)
## Hardware para empezar
* __Wemos__: [este](https://es.aliexpress.com/item/32843602421.html)
es el micro procesador que vamos a usar para el sensor. Se puede
programar con el IDE Arduino. Este es el ESP8285, equivale a un
ESP8266 con 1Mb de flash.
* __Sensor de temperatura/humedad__
* __RTC y tarjeta SD__ Como [este](https://es.aliexpress.com/item/32826265932.html)
* __Pantalla OLED__ Como
[esta](https://es.aliexpress.com/item/1005001636650130.html)
compatible con la mecánica Wemos
* __Módulo de gestión de batería__ Como
[este](https://es.aliexpress.com/item/32796003002.html).Para
alimentar el sensor con una batería de 3,3 volt
Ver la tabla de componentes
[aquí](https://cryptpad.fr/sheet/#/2/sheet/edit/PYqEabbLSfwUlQticILskoOC/)
## MQTT
_**M**essage **Q**ueuing **T**elemetry **T**ransport_, es un protocolo
**ligero** (bajo consumo de memoria y cpu) diseñado especificamente
para que dispositivos de bajo consumo transmitan datos de banda
estrecha (con velocidades muy bajas). El protocolo funciona sobre
TCP/IP (otro protocolo, "el de internet"). Es un protocolo viejecito
(1999), lo que pasa es que se ha puesto de moda por que encaja muy
bien con todo el tema de IoT (_**I**nternet **o**f **T**hings_)
### Conceptos
_Broker_
: Es un _middleware_ (un intermediario) entre los _publishers_
(agentes que envían datos) y _receivers_ (agentes que reciben los
datos)
_Publisher_
: Un agente que envía datos al _Broker_, puede ser un dispositivo
sensor, un demonio monitorizando un servidor, una raspi, etc. etc.
_Subscriber_
: Es el receptor de los datos enviados por el _Publisher_
_Topic_
: Los _Publisher_ y _Subscriber_ no se relacionan directamente. Cuando
un _publisher_ envía datos al _broker_ los asocia a un _topic_. El
_topic_ es una cadena en forma de jerarquia (p.ej.
/sensor/cocina/temperatura), el carácter '/' actúa como separador de
nivel, cada campo separado por '/' representa un nivel. Los puedes
organizar como quieras. Cuando un _subscriber_ se conecta al
_broker_ especifica los _topic_ en los que está interesado. El
_broker_ le hará llegar todos los mensajes de esos _topic_.
Tenemos dos operadores o máscaras para especificar las
subscripciones: `#` y `+`.
Supongamos que tenemos los siguientes _topic_:
* `/sensor/cocina/temperatura`
* `/sensor/cocina/humedad`
* `/sensor/cocina/humo`
* `/sensor/salon/temperatura`
* `/sensor/salon/humedad`
* `/sensor/salon/humo`
Con la especificación `/sensor/+/temperatura` me suscribo a todos
los sensores de temperatura. `+` encaja con un nivel simple.
Con la especificación `/sensor/#` me suscribo a todos los sensores.
`#` encaja con múltiples niveles.
Si organizamos los niveles de los _topic_ con lógica, podremos
gestionar fácilmente las suscripciones.
_message_
: Los datos que son enviados y recibidos
### Versiones del protocolo
* V3.1.1
* V5.0
### Brokers MQTT
Hay muchos brokers, esta lista es muy parcial pero todos los que están
tienen licencia libre.
* __Mosquitto__: Mosquitto es un broker sencillo y que aparece en un
montón de tutoriales disponibles en internet. Está incluido en los
repos de Debian y Ubuntu (seguramente no muy actualizado) y hay ppa
disponible. La principal pega de Mosquitto es que no soporta
"clustering" (varios brokers funcionando en paralelo) que es la
forma natural de escalar la carga en el servido y dar redundancia.
Es práctico para desarrollar aplicaciones pero puede dar problemas
si lo quieres usar en un entorno de producción.
* __RabittMQ__: Es un broker multiprotocolo así que no solo soporta
MQTT. El soporte para distintos protocolos de colas de mensajes se
implementa mediante plugins. Soporta clustering así que es escalable
para aguantar cargas grandes de peticiones y se puede implementar
redundancia. El soporte de MQTT no es completo, no tiene soporte
para MQTT V5.0 ni para todas las carácteristicas de MQTT V3.1.1 (por
ejemplo no soporta QoS2)
* __VerneMQ__: Es un broker MQTT puro (no es multiprotocolo) Soporta
clustering y todas las versiones de MQTT, aparentemente con todas
sus funcionalidades.
### Pruebas con _Mosquitto_
Vamos a hacer pruebas con el _broker_ más sencillo: _Mosquitto_
En Ubuntu y derivadas es muy fácil de instalar, añadimos el origen de
paquetes oficiales para estar a la última, instalamos el paquete
`mosquitto` y el paquete `mosquitto-clients`, los clientes nos vendrán
bien para hacer pruebas. En otras distribuciones tendrás que mirar
como se instala, pero no puede ser muy complicado.
```bash
sudo apt-add-repository ppa:mosquitto-dev/mosquitto-ppa
sudo apt-get update
sudo apt install mosquitto mosquitto-clients
```
En Ubuntu y derivadas **queda lanzado el servicio** y podemos hacer
pruebas con los clientes instalados. Si después queremos instalar el
_Mosquitto_ de otra manera (con _docker_ por ejemplo) hay que
acordarse de parar el servicio.
#### Probando
En un terminal con el comando `mosquitto_sub -h localhost -t test`
lanzamos un _subscriber_ que atiende al _topic_ test.
Desde otro terminal con el comando `mosquitto_pub -h localhost -t test
-m "Hola Mundo"` ejecutamos un _publisher_ que manda el mensaje "Hola
Mundo" al _topic_ test.
En la primera ventana podemos ver:
```bash
$ mosquitto_sub -h localhost -t test
Hola mundo
```
Se ha recibido el mensaje en el _topic_ suscrito.
#### Probando con python
Vamos a ver como usar el _mqtt_ desde Python. Así queda mucho más
claro como funciona el _broker_
Creamos un entorno virtual y lo activamos (yo lo he llamado `paho`),
en ese entorno instalamos la librería: `pip install paho-mqtt`
Creamos un programa _subscriber_:
```python
import paho.mqtt.client as mqtt
import time
# la rutina a ejecutar cuando recibimos un mensaje
def on_message(client, userdata, message):
print("received message: ", str(message.payload.decode("utf-8")))
# la rutina a ejecutar al recibir CONNACK
def on_connect(client, b, c, rt):
print("Connected with result " + str(rt))
# hacemos la suscripcion dentro de la rutina on_connect
# de esta forma si tenemos reconexiones ya nos aseguramos
# la suscripcion
client.subscribe("ALEATORIOS")
# dirección del broker
mqttBroker = "localhost"
# creamos un "cliente"
client = mqtt.Client("subs-1")
client.on_connect = on_connect
client.on_message = on_message
# conexión al broker
client.connect(mqttBroker)
# lanzamos un loop no bloqueante
client.loop_start()
# Escuchamos durante 30 segundos y paramos el programa.
time.sleep(30)
client.loop_stop()
```
Y este sería el programa _publisher_
```python
import paho.mqtt.client as mqtt
from random import randrange, uniform
import time
# definimos la rutina a ejecutar cuando recibimos CONNACK
def on_connect(client, userdata, flags, rc):
print("Connected with result " + str(rc))
# definimos la dirección del broker
mqttBroker = "localhost"
# creamos un "cliente"
client = mqtt.Client("publisher-1")
client.on_connect = on_connect
# conexión al broker
client.connect(mqttBroker)
# Bucle infinito, publicamos un número aleatorio y esperamos 1 sg
while True:
randNumber = uniform(0, 10)
client.publish("ALEATORIOS", randNumber)
print("Publicado " + str(randNumber) + " en el topic ALEATORIOS")
time.sleep(1)
```
Podemos ver los programas en acción ejecutando cada uno en su terminal
(terminal=ventana de comandos) ¡Recuerda activar el entorno virtual
en todos los terminales que abras!
##### ¿Qué está pasando aquí?
Cada vez que desde un cliente le pedimos algo al _broker_ este nos
responde con una señal, pero ¡ojo! el protocolo es asíncrono, así que
mas que una conversación entre cliente y servidor tenemos un
intercambio de correos.
Por ejemplo, cuando nosotros le mandamos la petición de conexión al
_broker_ debería llegarnos un _CONNACK_ desde el mismo. En el
_CONNACK_ el _broker_ nos adjunta tres campos: _user data_, _flags_ y
_result code_. El campo más interesante probablemente sea el _result
code_, estos son los valores definidos en el protocolo:
| rc | Significado |
| :-----: |-------------------------------------------------|
| 0 | Connection successful |
| 1 | Connection refused incorrect protocol version |
| 2 | Connection refused invalid client identifier |
| 3 | Connection refused server unavailable |
| 4 | Connection refused bad username or password |
| 5 | Connection refused not authorised |
| 6-255 | Currently unused. |
La biblioteca _paho-mqtt_ nos permite definir rutinas ___callback__
que la librería invocará cuando se produzcan ciertos eventos.
Un par de ejemplos: un evento de conexión reconocida (se ha recibido
el _CONNACK_) hará que se ejecute el _callback on_connect_, el evento
"recibir un mensaje" hará que _paho_ intente ejecutar el _callback
on_message_. Esta tabla cubre los principales eventos:
| Evento | _Callback_ |
|---------------------------|------------------|
| Conexión reconocida | `on_connect` |
| Desconexión reconocida | `on_disconnect` |
| Suscripción reconocida | `on_subscribe` |
| De-suscripción reconocida | `on_unsubscribe` |
| Publicación reconocida | `on_publish` |
| Mensaje recibido | `on_message` |
| Info de log disponible | `on_log` |
Los ejemplos que puse son muy sencillos, si queremos escribir un
código más robusto hay que tener en cuenta todo lo que el protocolo
ofrece y que es un protocolo asíncrono. Un par de ejemplos de mejoras
* La función `on_connect` debería comprobar el _result code_ y no
dejar continuar el programa sin tener una conexión verificada.
* La función `on_message` seguramente tendrá que procesar el _topic_
del mensaje y puede que también la _qos_
## influxdb
* <https://discourse.nodered.org/t/mqtt-node-red-influxdb/34706>
* <https://diyi0t.com/visualize-mqtt-data-with-influxdb-and-grafana/>
* <https://dev.to/project42/install-grafana-influxdb-telegraf-using-docker-compose-56e9>
* <https://lazyadmin.nl/it/installing-grafana-influxdb-and-telegraf-using-docker/>
_Influxdb_ es una base de datos especializada en series temporales de
datos. Eso hace que sea mucho más eficiente que una base de datos
relacional tratando este tipo de datos. Aunque internamente cambia
bastante el funcionamiento el lenguaje de consultas no es muy
diferente de SQL. Otra ventaja relacionada con nuestro escenario es que
se integra muy bien con _Grafana_.
Hasta ahora _influxdb_ viene con varias aplicaciones asociadas:
_Telegraf_
: un agente de recolección de datos, para capturar datos de _stacks_ y
otros sistemas
_Cronograf_
: Un visualizador de datos al estilo de _Graphana_
Kapacitor
: un motor de procesado de datos en tiempo real especializado en
series temporales
Pero está disponible la versión __InfluxDB OSS 2.0__ que integra todas
las herramientas en un único programa. Por lo que veo la instalación
es por binarios únicamente y además __no es compatible con
Raspberry__. Parece interesante pero por ahora lo dejamos.
Si instalamos el _Influxdb_ clásico nos quedamos con la versión 1.8.3
(en este momento). Una vez instalada y arrancado el servicio lo
podemos probar preguntando por las bases de datos disponibles (solo
está la _internal_)
```bash
$ influx
Connected to http://localhost:8086 version 1.8.3
InfluxDB shell version: 1.8.3
> show databases
name: databases
name
----
_internal
>
```
Que no os despiste el interfaz http, no es _human friendly_ ni
funciona con navegadores (en esta versión de _influxdb_). Si que
podemos interrogarlo con _curl_ por ejemplo y nos responderá en
perfecto _json_:
```bash
$ curl -G http://localhost:8086/query --data-urlencode "q=SHOW DATABASES"
{"results":[{"statement_id":0,"series":[{"name":"databases","columns":["name"],"values":[["_internal"]]}]}]}
```
Por lo demás trabajar con _InfluxDB_ no es tan diferente de trabajar
con una base de datos relacional de toda la vida.
* _InfluxDB_ está optimizada para trabajar con series de datos
temporales, es más rápida (con este tipo de datos) que las bases de
datos relacionales clásicas
* Cambia un poco la terminología:
* La base de datos clásica era una colección de tablas, la de
_Influx_ puede verse como una colección de "medidas" (_measurements_)
* Las "medidas" se parecen a las tablas de las bases de datos
relacionales, pero:
* Siempre tienen que tener una referencia temporal
(_timestamp_, basicamente nanosegundos desde el _Linux Epoch_)
* Se distingue entre campos (_fields_) y etiquetas (_tags_),
equivalen a los campos (columnas) de las tablas de las bases
de datos relacionales, pero: **las etiquetas están
indexadas** y los campos no.
* los registros, las filas de las tablas, se llaman puntos
* Se pueden ajustar las políticas de retención de datos, es decir,
cuanto tiempo se mantienen en la base de datos. Depende de para que
quieras usar los datos, a lo mejor quieres un histórico de una hora
o de cinco años. Ajustar bien las políticas de retención influye en
el rendimiento de la base de datos.
### Instalación de _InfluxDB_
Dependerá del sistema operativo, por ejemplo para Linux Mint:
```bash
wget -qO- https://repos.influxdata.com/influxdb.key | sudo apt-key add -
#source /etc/lsb-release
DISTRIB_ID=ubuntu
DISTRIB_CODENAME=focal
echo "deb https://repos.influxdata.com/${DISTRIB_ID} ${DISTRIB_CODENAME} stable" | sudo tee /etc/apt/sources.list.d/influxdb.list
apt update
apt install influxdb
apt install telegraf
```
Una vez instalado verifica que el servicio está arrancado.
El cliente de la base de datos se llama _influx_ si ejecutamos el
cliente podemos preguntar por las bases de datos presentes con: `show
databases` (solo muestra la base de datos interna)
Una sesión completa
* Creamos la base de datos
* La ponemos como base de datos activa
* Insertamos datos
```bash
influx -precision rfc3339
Connected to http://localhost:8086 version 1.8.3
InfluxDB shell version: 1.8.3
> show databases
name: databases
name
----
_internal
>create database mydb
> show databases
name: databases
name
----
_internal
mydb
> use mydb
Using database mydb
> insert temperature,location=campo external=13,internal=23
> insert temperature,location=ciudad external=19, internal=22
```
Las lineas de los _insert_ siguen el esquema:
`<measurement>[,<tag-key>=<tag-value>...] <field-key>=<field-value>[,<field2-key>=<field2-value>...] [unix-nano-timestamp]`
El primer grupo son los _tags_ que **están indexados**. En nuestro
ejemplo el _tag_ sería `location`. El segundo grupo son los _fields_
(no indexados), en nuestro ejemplo tendríamos dos `external` e
`internal`. Opcionalmente podemos escribir el _timestamp_ o dejar que
_influx_ lo ponga automáticamente (pondrá el instante en que se
realiza la inserción)
### Un ejemplo con python
Lo primero es instalar la biblioteca de python así que en nuestro
entorno virtual ejecutamos `pip install influxdb`
Un programa python chorras para ejecutar las inserciones del ejemplo anterior:
```python
from influxdb import InfluxDBClient
client = InfluxDBClient(host=localhost, port=8086)
client.switch_database('mydb')
client.write_points("temperature,location='countryside' external=13,internal=23", protocol='line')
client.write_points("temperature,location='city' external=19,internal=22", protocol='line')
```
Si después de ejecutar el programa vamos al cliente _influx_:
```bash
> use mydb
Using database mydb
> show measurements
name
----
temperature
> select * from temperature
name: temperature
time external internal location
---- -------- -------- --------
2020-11-27T15:23:20.523830387Z 13 23 countryside
2020-11-27T15:23:33.459690565Z 19 22 city
```
## Análisis y Visualización de datos
* __Metabase__: Visualización de gráficos sencilla y potente.
* __Grafana__: Plataforma de visualización y análisis de datos muy completa.
## node-red
### Instalación en Linux
Para instalar node-red en linux necesitamos instalar primero
`node.js`. Hay varias formas de instalar `node.js`, yo voy a optar por
instalar `nvm` que es el **n**ode **v**ersion **m**anager.
Para ello ejecutamos el siguiente comando (la versión actual de `nvm`
es la 0.37.0)
```bash
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.37.0/install.sh | bash
```
El script de instalación añade las siguientes lineas al fichero
`~/.bashrc`, nosotros las eliminamos de `~/.bashrc` y las movemos al
fichero `~/.profile`
```bash
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion
```
Para comprobar la instalación usamos `command -v nvm` que nos
devolverá `nvm`. `which` no funciona en este caso por que es un script
pensado para invocarlo con `source`
### Instalación de `node.js`
Ahora que tenemos `nvm` instalado, ya podemos instalar fácilmente la versión o versiones que queramos de `node.js`
```bash
nvm ls-remote # para listar las versiones disponibles
nvm install node # instala la última versión disponible
nvm install --lts # instala la versión LTS
```
### Instalación de `node-red`
Una vez instalado el `node.js` instalar el `node-red` es muy fácil:
activar el `node.js` que hemos instalado y hacer la instalación de
`node-red`
```bash
nvm use node
npm install -g --unsafe-perm node-red
```
## Instalación del IDE Arduino en Linux para trabajar con Wemos D1
Descargamos el IDE de la [pagina
web](https://www.arduino.cc/en/software). Para proceder a la
instalación se puede consultar [la guía de postinstalación de Linux
Mint](https://gitlab.com/salvari/linuxmint_ulyana_20) que detalla
todos los pasos.
Solo necesitamos habilitar el soporte para ESP8266, añadiendo la linea
siguiente a nuestras preferencias de Arduino:
`http://arduino.esp8266.com/stable/package_esp8266com_index.json`
## Configuración de mini-PC como servidor
Describimos la instalación en un mini-pc Beelink T34 (con 8 gb de RAM
y 256Gb de disco duro SSD). No es obligatorio hacerlo como
describimos, esto es solo para referencia.
Nos hemos decidido por instalar Debian en el mini-pc. Hay varias
formas de instalar Debian, pero como nosotros queremos un Debian sin
interfaz gráfico y con lo mínimo, creemos que lo más fácil es usar el
`netinst`.
Descargamos la imagen iso de `netinst` desde [la página de
Debian](https://cdimage.debian.org/debian-cd/current/amd64/bt-cd/) (la
hemos descargado via torrent)
Desde linux hemos usado Etcher (es multiplataforma) para grabar la
image iso descargada en una memoria USB.
Conectamos nuestro mini-PC a un teclado usb y a un monitor (hemos
usado un coversor HDMI-VGA) y conectamos la memoria USB en algúno de
los puertos libres, también le hemos dado internet con un cable
ethernet a nuestro router.
Al arrancar el mini-PC veremos un aviso: pulsando F7 nos deja elegir
el dispositivo de arranque. Elegimos arrancar desde la memoria USB e
iniciamos la instalación de Debian, con particionado manual y sin LVM.
Hemos creado tres particiones:
| Particion | Tamaño | Tipo | Punto de montaje | Comentarios |
|-----------|--------|------|--------------------|-----------------------------------------------------------|
| /dev/sda1 | 511Mb | EFI | /boot/efi | La crea el programa de instalación |
| /dev/sda2 | 55Gb | ext4 | / | root |
| /dev/sda4 | 171Gb | ext4 | /store | Dejamos casi todo el espacio disponible en esta partición |
El programa de instalación nos ha pedido drivers adicionales pero lo
hemos ignorado.
Hemos escogido idioma inglés con teclado español. También hemos
escogido locales `es_ES-UTF-8`
**Solo** hemos instalado el openssh server y las herramientas básicas.
Tendremos que instalar muchas más cosas pero eso nos deja un sistema
lo más limpio posible.
Tras completar la instalación el sistema **no** arranca normalmente se
queda pillado en el _prompt_ de _grub_. Tras teclear `exit` en el
prompt arranca normalmente.
Se soluciona ejecutando como _root_ `grub-install` y ya no vuelve a fallar.
Una vez arrancado el sistema podemos conectarnos via ssh.
## Referencias
### Wiki de Bricolabs
* [Raspberry Pi, configuración para IOT](https://bricolabs.cc/wiki/guias/raspberry_iot)
* [Sistema IOT de Bricolabs](https://bricolabs.cc/wiki/proyectos/sistema_iot_bricolabs)
### Referencias MQTT
* [Buenos apuntes para aprender de MQTT](https://www.hivemq.com/mqtt-essentials/)
* [Para empezar con python y MQTT (muy completo)](http://www.steves-internet-guide.com/into-mqtt-python-client/)
* [Enviar datos desde ESP via mqtt](https://diyi0t.com/microcontroller-to-raspberry-pi-wifi-mqtt-communication/)
* [Visualizar datos (cont. del ant.)](https://diyi0t.com/visualize-mqtt-data-with-influxdb-and-grafana/)
### Referencias _Influxdb_
* [Getting started](https://docs.influxdata.com/influxdb/v1.7/introduction/getting-started/)
* [Getting started with Influxdb OSS 2.0](https://docs.influxdata.com/influxdb/v2.0/get-started/)
* [Guia de Influxdb](https://devconnected.com/the-definitive-guide-to-influxdb-in-2019/)
* [Instrucciones de instalación para la versión clásica y la nueva 2.0 en ubuntu y debian](https://devconnected.com/how-to-install-influxdb-on-ubuntu-debian-in-2019/#Option_2_Adding_the_repositories_to_your_package_manager)
* [otro getting started](https://www.influxdata.com/blog/getting-started-with-influxdb-2-0-scraping-metrics-running-telegraf-querying-data-and-writing-data/)
* [Python e Influxdb OSS 2.0](https://www.influxdata.com/blog/getting-started-with-python-and-influxdb-v2-0/)
* [Docker compose: Grafana/Influx/Telegraf](https://dev.to/project42/install-grafana-influxdb-telegraf-using-docker-compose-56e9)
* [idem](https://lazyadmin.nl/it/installing-grafana-influxdb-and-telegraf-using-docker/)
* [idem, tiene dos partes](https://thenewstack.io/how-to-setup-influxdb-telegraf-and-grafana-on-docker-part-1/)
* [Acumulados y caducidad: _Continous query and retention policy_](https://docs.influxdata.com/influxdb/v1.8/guides/downsample_and_retain/)
### Home assistant seguros
* <https://makezine.com/2020/03/17/private-by-design-free-and-private-voice-assistants/>
* <https://makezine.com/2020/08/03/set-up-your-own-private-smart-home/>
* https://makezine.com/projects/mycroft-the-open-source-private-voice-assistant-on-raspberry-pi/>
* Magpi vol 99, pag 54 <http://magpi.cc>
### Ejemplos del escenario básico que queremos implementar
* [Visualizar datos con mqtt-influxdb-grafana (bridge-python)](https://diyi0t.com/visualize-mqtt-data-with-influxdb-and-grafana/)
* [Una configuración con Telegraf](https://screenzone.eu/arduino-mqtt-sensor-grafana/)
* [nilhcem (web)](http://nilhcem.com/iot/home-monitoring-with-mqtt-influxdb-grafana)
### Para revisar
* [Pagina especializada en IoT](https://diyi0t.com/)
* <https://esphome.io/index.html#guides>

@ -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,220 @@
---
weight: 4
title: "Apuntes del Fediverso"
date: 2022-05-01T18:16:57+0200
draft: false
summary: "Apuntes del Fediverso, la red social federada"
categories:
- notes
tags:
- fediverso
- mastodon
---
- [Decentralized Social Media](https://www.fosslife.org/mastodon-basics) from Linux Magazine
- [Traefik v2 and Mastodon, a wonderful couple!](https://www.innoq.com/en/blog/traefik-v2-and-mastodon/) (Innoq version)
- [Github for the article above](https://gist.github.com/smashnet/38cf7c30cb06427bab78ae5ab0fd2ae3)
- [Traefik v2 and Mastodon, a wonderful couple!](http://nicolas.inden.one/article/2020/01/24/traefik-v2-and-mastodon.html) (blog version)
- [An all-in-one Mastodon Image](https://github.com/Wonderfall/docker-mastodon)
- [Hubzilla and Traefik](https://framagit.org/anaqreon/hubzilla-docker)
- [Making your own Mastodon Service in ten steps](https://growyourown.services/making-your-own-mastodon-server-in-10-steps/)
- [Image Descriptions on the Fediverse](https://m0yng.uk/Image-descriptions-on-the-Fediverse/)
- [A Hitchhiker's Guide to the Fediverse](https://gofoss.net/fediverse/)
- [Fossllife: Mastodón Basics](https://www.fosslife.org/mastodon-basics)
- [Mastodon Docker Setup with Traeffic via php scripts](https://gitlab.com/dweipert.de/devops/mastodon-docker-traefik)
- [Feditips](https://mstdn.social/@feditips/108215973331591896) (mastodon account)
- [Migadu](https://www.migadu.com/index.html) Email service for Domains
- [Fediverse Party](https://fediverse.party/)
- [Comunidades Fediversales en Español](https://notas.niboe.info/s/6lr2U2myb#)
- [Fedi-Directory](https://fedi.directory/) la colección de @FediFollows
## ¿Qué es el Fediverso?
El origen del Fediverso puede situarse en proyectos como ___Diaspora___ o ___Identi.ca___, los primeros intentos de crear un red social descentralizada. Con el tiempo evolucionaron, el creador de de _Identi.ca_ Evan Prodromou desarrolló _pump.io_, un _framework_ que permitía a los desarrolladores construir servicios de redes sociales.
Con el tiempo el [W3C]^(World Wide Web Consortium) vio las ventajas de _pump.io_ y tomándolo como base publicó la especificación y recomendación ___ActivityPub___.
Y sobre _ActivityPub_ nació el __Fediverso__.
_ActivityPub_ es un protocolo y una API que permite a los servicios definidos con ella la comunicación a través del Fediverso con otros nodos tanto del mismo servicio como de otros servicios diferentes. Por ejemplo, puedes publicar una foto en tu cuenta de ___Pixelfed___ (un servicio para compartir fotos) y hacer que esa foto aparezca en las lineas temporales de la gente que te siga en Mastodon, el servicio de microblogging que es quizás el buque insignia del Fediverso.
El Fediverso no solo comparte publicaciones, los nodos son capaces de compartir recursos entre ellos e incluso a través de técnicas P2P entre clientes. Por ejemplo si publicas un video en una instancia de ___PeerTube___ (puede que en tu propio servidor) Necesitarás bastante ancho de banda pero menos del que crees, los clientes que estén viendo el mismo video compartirán la carga.
Además de ___Mastodon___, ___Peertube___ y ___Pixelfed___, podríamos citar una plataforma para compartir audio dirigida a músicos y podcasters llamada ___Funkwhale___. También podríamos hablar de ___Hubzilla___ que se autodefine como "una potente plataforma para crear sitios web interconectados que ofrecen identidad descentralizada, comunicaciones y una infraestructura de permisos, todo ello basado en tecnología común de servidores web.", de ___Akhoma___, ___Misckey__ o ___Calckey___ para microblogging, de ___Bookwyrm___ para hablar de libros, etc. etc. etc.
En resumidas cuentas, el __Fediverso__ es una red Federada, compuesta de muchas redes sociales interconectadas. El número de usuarios total según la estimación más reciente ronda los cuatro millones de personas.
__Descentralizado__
: En vez de un único proveedor de servicios hay multitud de proveedores que ofrecen acceso al __Fediverso__. Cualquiera puede configurar un servidor (normalmente denominados instancias) ya sea para uso personal o para dar servicio a una comunidad
__Federada__
: Los servidores de distintos servicios se comunican entre si mediante el protocolo ___ActitityPub___
__No comercial__
: Aquí los usuarios no son el producto, el __Fediverso__ no está diseñado para cautivar la atención del usuario o mantenerlo enganchado a la red
__Neutral__
: No hay filtros para priorizar o recomendarte contenido. Los contenidos se muestran en orden cronológico. Los filtros los establece el usuario
### Cosas en el Fediverso
Mastodon
: Microblogs
: [Listado de instancias](https://joinmastodon.org/) Hay muchas instancias de Mastodon para escoger
Pixelfed
: Compartir tus fotos.
: - <https://pixelfed.org/>
: - [Instancia principal](https://pixelfed.social/)
PeerTube
: Red federada para compartir videos
: - <https://joinpeertube.org/>
: - <https://tilvids.com/videos/overview>
: [Sepia Search](https://search.joinpeertube.org/)
BookWrym
: Red social federada para compartir tus lecturas, hablar de libros, escribir reseñas y descubrir que es lo siguiente que vas a leer.
: - <https://joinbookwyrm.com/>
: - <https://bookwyrm.social/>
Funkwhale
: Una red social para compartir y escuchar música
: [Get started](https://funkwhale.audio/#get-started)
: [Instance List](https://network.funkwhale.audio/dashboards/d/overview/funkwhale-network-overview?orgId=1&refresh=2h)
Friendica
: Es una plataforma de comunicaciones descentralizada que puede conectarse con plataformas independientes como el Fediverso o Diaspora o comerciales como Twitter.
Lemmy
: Una plataforma libre y descentralizada de compartición y discusión de enlaces.
Pleroma
: Otra plataforma de microblogging
Misskey
: Otra plaforma más de microblogging
Goldfish
: Parecido a TikTok
Gotosocial
: Microblogging facílisimo de autoalojar en docker.
## ¿Qué es Mastodon?
__Mastodon__ es un servicio de microblogging que ahora mismo parece ser el servicio más conocido del __Fediverso__.
__Mastodon__ puede parecerse mucho a Twiter, pero la verdad es que son muy diferentes no te confundas.
Para empezar __en Mastodon no hay un algoritmo__ para recomendar contenidos (y mantenerte pegado a la pantalla de tu dispositivo). Normalmente si acabas de llegar a la red te parecerá todo muy silencioso y no hay mecanismos automáticos para que deje de serlo.
Aquí eres tú quien tiene que buscar y seguir a gente interesante. Es importante cuidar tu linea de tiempo __local__ (el conjunto de gente que sigues) para tener una experiencia de calidad (hay muchas herramientas para el ajuste fino).
Para empezar puedes buscar algún _hastag_ interesante y descubrirás seguramente gente para seguir. Una vez que sigas a alguien puedes cotillear a quien sigue, para descubrir a mas gente. No hay que tener miedo de seguir gente, y más importante, no dudes en dejar de seguirlos si no te gusta lo que publican. Hay soluciones "más ligeras", puedes silenciar temporalmente una cuenta que se enrolla hablando de algo que no te interesa. Y también hay soluciones más drásticas, puedes silenciar o bloquear a cuentas que te resulten ofensivas e incluso silenciar o bloquear servidores enteros.
Como resultado de esta forma de funcionar, el número de gente que te siga es bastante irrelevante, de hecho el interfaz puede configurarse para ocultartelo a ti mismo. Lo mismo ocurre con los favoritos que obtenga una publicación (sólo los ve el autor). Y ninguna de esas métricas influye en el alcance de tus publicaciones. La información se difunde exclusivamente por _reblogs_ de gente que te lea y de la gente que lea a tus seguidores.
Si tienes mucho interes en acrecentar tu audiencia usa los _hashtags_ prolífica y cuidadosamente.
Sigue gente y _hastag_ que te gusten. Además puedes activar la alerta en la gente que sea importante para ti.
Organiza a la gente que te sigue en listas para facilitar la lectura.
Siempre puedes seguir via RSS a la gente (y hastags) que quieras.
Escoge un interfaz de usuario lo más avanzado posible, la experiencia será muy diferente con el interfaz adecuado.
__Sigue siempre al administrador de tu instancia__, salvo que sea muy brasas considera la posibilidad de activar la campana. Hay que estar atento tanto a sus avisos como a sus peticiones de ayuda.
### Detalles
* Cuando quieres difundir el _toot_ (un _post_) de alguna cuenta que sigues lo único que puedes hacer es un _boost_ (_reblog_), los favoritos y los marcadores (_bookmarks_) son cosas privadas en Mastodon (y en el Fediverso en general)
* Los favoritos se usan para mostrar reconocimiento, aprecio o acuerdo con un _toot_ (escoge como quieres interpretarlos), quedan almacenados en tu perfil para que puedas visitarlos en el futuro.
* Un _bookmark_ es estrictamente privado, el autor del _toot_ no sabrá que te lo has apuntado.
* El _boost_ se usa para difundir lo que sea, animar el diálogo o compartir cosas que te gustan.
* Los _hastag_ son importantes, se usan en búsquedas y además la gente puede seguir _hastags_
* Si publicas en varios idiomas asegúrate de configurar correctamente el idioma de cada publicación. Es muy importante para que la gente pueda filtrar y ver solo las publicaciones que pueda leer.
### Recetas Mastodónticas
Mastodon provee varias herramientas para la gestión de tu linea temporal.
* Puedes añadir notas a cualquier perfil. P.ej. para recordar por qué empezaste a seguirlo, si es un perfil ofensivo, cualquier cosa que quieras recordar
* Puedes deshabilitar los _boost_ usuario a usuario. Podrías querer ver los post de un usuario pero no todo lo que le interese.
* Puedes silenciar (_"mutear"_) temporalmente una cuenta
* Puedes filtrar post por palabras específicas, _hashtags_ o frases
* Y como última medida puedes Bloquear, dejar de seguir o silenciar definitivamente.
* Todas las cuentas de Mastodon tienen RSS, puedes suscribirte por ejemplo a mastodon.technology/comacero.rss
* Modula el alcance de tus _post_, mira si quieres que sean públicos, sólo para seguidores, sólo para mencionados, no-listados, etc. etc.
#### Verificación de la cuenta
Mastodon tiene un mecanismo de verificación. Necesitas tener un sitio web en el que seas conocido.
Enlaza tu perfil en Mastodon desde el sitio web. Puede ser un enlace visible o una etiqueta de enlace en la cabecera del html con un atributo `rel=me`.
Enlaza la página web desde tu perfil de Mastodon. Deberías ver que aparece una marca verde de verificación en el perfil.
#### Usa _hashtags_
Las busquedas en Mastodon funcionan sobre _hashtags_, además con las versiones más modernas de Mastodon puedes seguir _hashtags_. Es importante poner los _hashtags_ al final de tu _post_ y usar notación _CamelCase_. Las dos recomendaciones son para que las aplicaciones de accesibilidad (texto a voz por ejemplo) funcionen correctamente.
#### Usa _alt-text_ en la imágenes
Mastodon nació como una red inclusiva, usa _alt-text_ en todas las imágenes para hacerlas accesibles a todo el mundo.
#### Usa listas
Si tienes intereses muy variados o perteneces a varias comunidades distintas las listas te permiten mantener a toda la gente que sigues ordenada y facilitan mucho la lectura. Puedes asignar a cualquier persona que sigas a una o varias listas.
#### Threads o listas encadenadas de posts
Asegúrate de poner en "publico" solo el post cabecera y el resto en "unlisted" para mantener la linea temporal limpia.
#### Usa filtros
Aun lo estoy estudiando, pero son muy útiles.
<!--
Use Fedifinder to follow all the accounts you followed on Twitter, and sync up your follow and block lists.
Avail yourself of the multiple public lists of hundreds of journalist accounts on Mastodon.
-->
#### Misc
Quizá estás aterrizando en #Mastodon o quizás, ya llevas un ratito por aquí, pero un detalle importante a tener en cuenta es:
No compartir en otros sitios web o redes sociales enlaces a contenidos publicados originalmente en Mastodon sin el consentimiento de sus autores.‼️
En #Mastodon las búsquedas por palabras clave sólo devuelve resultados de contenidos publicados por el propio usuario, incluyendo sus etiquetas, artículos que ha marcado como favoritos, los que ha reenviado o aquellos en los que ha sido mencionado.‼️
La función de citar inevitablemente agrega toxicidad a los comportamientos de las personas. Estás tentado a citar cuando deberías estar respondiendo, por lo que hablas a tu audiencia en lugar de a la persona con la que estás hablando. Se vuelve performativo. Incluso cuando lo haces por "bien", como ridiculizar comentarios horribles, estás dando más atención a los comentarios horribles...‼️
## Calckey
Su instancia tiene 5 diferentes líneas de tiempo habilitadas
La línea de tiempo Inicio es donde puedes ver las publicaciones de tus seguidores.
La línea de tiempo Local es donde puedes ver las publicaciones de todos los demás en esta instancia.
La línea de tiempo recomendada es donde puedes ver las publicaciones de las instancias que los administradores recomiendan.
La línea de tiempo Social es donde puedes ver las publicaciones de los amigos de tus seguidores.
La línea de tiempo Global es donde puedes ver las publicaciones de todas las demás instancias conectadas.
### Configuración
- Activar la opción de _Show local post in **Social Timeline**_
### Varios
- Cuando Calckey dice que no puede cargar un medio se pueden cargar desde el servidor remoto.

@ -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,97 @@
---
weight: 4
title: "Apuntes de Mapas Textiles"
date: 2023-03-29T17:26:48+0200
draft: false
hiddenFromHomePage: true
summary: "Apuntes del curso de Mapas Textiles de Rosario Belda"
categories:
- notes
tags:
- textil
---
## Mapa de estrellas
Desde el principio consideramos proyectos que nos dejaran abierta la posibilidad de incluir fuentes de luz. Así que pensamos en un mapa de los Faros de Galicia o un mapa estelar. Decidimos hacer un mapa de estrellas.
## Fuentes de Mapas Celestes
- [Mag-7 Star Atlas](https://www.siaris.net/astro/atlas/), disponible para descarga en [Internet archive](https://archive.org/details/Mag_7_Star_Atlas), un hermoso mapa a todo color en un tamaño muy manejable. (Siempre llevo una copia en el coche) Compilado por Andrew L. Jonhson.
- [The Beginners Star Atlas](https://vazhorov.wordpress.com/2020/09/03/beginners-star-atlas-v2/) Otro mapa compacto a todo color, obra de Ed Vazhorov. La página está en ruso, pero el artículo para descargar el mapa está en inglés.
- [The Night Sky Maps](https://www.olle-eriksson.com/night-sky-maps/information.html) PDF de descarga gratuita, un mapa genial (tres mapas en realidad) compilado por el astrónomo aficionado Olle Eriksson.
- [Deep Sky Hunter Atlas](https://www.deepskywatch.com/deep-sky-hunter-atlas.html) PDF de descarga gratuita.
- [Tri-Atlas](https://www.deepskywatch.com/deep-sky-hunter-atlas.html) El famoso mapa estelar Tri-Atlas de José R. Torres y Casey Skelton
- [Takis 8.5 Magnitude Star Atlas](https://allans-stuff.com/takis-8-5-magnitude-star-atlas/) Enlazo al mirror por que la página original de Toshimi Taki parece un poco abandonada.
- [Stellarium] y su [versión web](https://stellarium-web.org/)
- [Skymap Online](https://www.skymaponline.net/)
- [Mapa Interactivo de Sky&Telescope](https://skyandtelescope.org/interactive-sky-chart/)
## Etapas del proyecto
### Mapa base
Decidimos bajarnos el mapa desde el mapa interactivo de Sky&Telescope. Como queremos una proyección con Polaris en el centro del mapa, tenemos que fijar nuestra localización en algún punto del ecuador, es decir a 90 grados de latitud, la longitud nos da igual.
Jugando con el tiempo podemos girar nuestro mapa. Aunque probablemente no influya en el resultado final hemos girado el mapa para que Orión nos quede a las tres en el hemisferio norte. Seguramente en el resultado final uniremos los dos hemisferios por la constelación de Orión (que nos gusta mucho).
### Limpiar el mapa con Inkscape
### Imprimir el mapa sobre tela
### Bordando el mapa
## Referencias generales del curso
- [Mapas de palos de polinesia](https://www.vistaalmar.es/ciencia-tecnologia/historia/5565-los-mapas-de-palos-para-la-navegacion-en-las-islas-marshall.html)
- [Mapas de las novelas de Verne](http://verne.garmtdevries.nl/en/maps/originals.html)
- [Deformación en las proyecciones de una cabeza humana](https://recuerdosdepandora.com/geografia-2/una-cabeza-para-mostrar-como-los-mapas-distorsionan-la-realidad/)
- [Mapas Milhaud](https://mapasmilhaud.com/)
- [Recuerdos de Pandora](https://recuerdosdepandora.com/geografia-2/una-cabeza-para-mostrar-como-los-mapas-distorsionan-la-realidad/) el blog de Mapas Milhaud
- [Mola](https://youtu.be/sA_ats3TwT0)
- [Biblioteca del Congreso de EEUU](https://www.loc.gov/collections/world-digital-library/about-this-collection/)
- [Blog de Maxar Technologies](https://blog.maxar.com/) Una empresa de imágenes satelitales
- [ESRI Map Gallery](https://mapgallery.esri.com/)
- [ArcGIS](https://www.arcgis.com/home/webmap/viewer.html)
- [spaM de Madalena Parreira](https://madalenaparreira.com/SPAM)
### Artistas
- [Arounna Khounnoraj](https://www.instagram.com/reel/CkYWVApNW3X/?igshid=MDJmNzVkMjY=)
- [Agnes Hansella](https://agneshansella.com/id/article/oops-loops)
- Rieko Koga
- [Instagram](https://www.instagram.com/riekokoga/)
- [Entrevista en ArteMorbida](https://www.artemorbida.com/interview-with-rieko-koga/?lang=en)
- Paula Kovarik
- [Página personal](https://www.paulakovarik.com/)
- [Instagram](https://www.instagram.com/yellowbrickstudio/)
- Mirjam Gielen (Mirjam Textiles)
- [Instagram](https://www.instagram.com/mirjamtextiles/)
- [Facebook](https://www.facebook.com/mirjamtextiles/)
- Louise Watson
- [Página personal](https://louisemaywatson.blogspot.com/2019/03/threads-by-mirjam-gielen.html)
## Herramientas libres
### cstich
### colores
#### online
- [w3schools colour course](https://www.w3schools.com/colors/default.asp) Un curso muy completo de colores
- [htmlcolorcodes](https://htmlcolorcodes.com/color-picker/) Esta tiene bastante teoría del color, explica por encima los distintos tipos de armonía.
- [colr.org](https://www.colr.org/) Bastante pobre, es para hacer paletas a partir de imágenes.
- [Colorpicker](https://colorpicker.me/) Esta está bien, sólo hace lo justo, escoges un color y te sacas las armonías.
- [Colormind](http://colormind.io/) Se supone que usa Deeplearning para sacar las paletas de colores, no hace mucho más.
#### herramientas
- Gpick
- [delicolour](https://github.com/eepp/delicolour)

@ -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,293 @@
---
weight: 4
title: "Apuntes de Sintetizadores DIY"
date: 2022-07-29T13:53:56+0200
draft: false
math: true
summary: "Apuntes de Sintetizadores"
categories:
- notes
tags:
- electrónica
---
## Conceptos
VCO
: _Voltage Controlled Oscillator_, un oscilador controlado por tensión.
<!--
https://easyeda.com/editor#id=9867176af11f49c48e609c6f65c8fcef
http://musicfromouterspace.com/index.php?MAINTAB=SYNTHDIY&VPW=1910&VPH=779
https://www.cuidevices.com/blog/understanding-audio-jack-switches-and-schematics
videos de something go wrong
Their spec's are completely different:
1) The lousy old LM358 works from a supply as low as 3.0V but the NE5532 needs a minimum of 6.0V.
2) The LM358 has inputs that work at 0V and an output that goes very close to 0V, but the NE5532 has inputs that do not work when they go below 3V and has an output that goes down to only 1.5V.
3) The LM358 has negative input bias current but the NE5532 has positive input bias current.
4) The LM358 has open inputs but the NE5532 has diodes across the inputs.
5) The LM358 has poor high frequency response but the NE5532 has excellent high frequency response.
6) The LM358 has a lot of noise and distortion (to make fuzz?) but the NE5532 has low noise and has very low distortion.
vco en hackaday -> https://hackaday.io/project/174364-synth-vco
vco en DIY Analog Synthesizer https://invidious.sethforprivacy.com/watch?v=SE9ZtG0E58g
moritz klein -> https://invidious.sethforprivacy.com/watch?v=3tMGNI--ofU
moritz klein -> https://invidious.sethforprivacy.com/watch?v=QBatvo8bCa4
birth of a synth -> https://www.birthofasynth.com/Thomas_Henry/Pages/VCO-1.html
-->
Es una de las fuentes de sonido en el sintetizador. El oscilador controlado por tensión (**V**oltage **C**ontroled **O**scillator) puede producir diferentes formas de onda simples o complejas.
Algunos VCO permiten seleccionar el tipo de onda de salida, otros generan diferentes tipos de onda de salida simultanemente, y las ofrecen en sendas tomas de salida.
Los VCO tienen una entrada CV (**C**ontrol **V**oltage Input) que permite controlar la frecuencia de la nota producida (de ahí su nombre). La señal CV puede venir de cualquier fuente. Podemos usar un controlador de teclado que genere los voltajes correspondientes a notas de la escala, pero también podemos obtener los voltajes de control de cualquier fuente que se nos ocurra: de un sensor, de una fuente aleatoria, etc. etc.
Para usar un VCO para generar notas musicales tenemos varios estándares establecidos:
**Voltios por octava**
: Cada voltio equivale a una octava. Propuesto por Moog en la década de los 60. Este es el estándar mejor implantado hoy en dia y casi todos los sintetizadores lo usan.
**Hertzios por octava**
: Subir una octava equivale a doblar el voltaje de control y bajar una octava equivale a reducirlo a la mitad. Un estándar muy utilizado en Yamaha y Korg.
Además de la entrada VC, el VCO puede tener más entradas.
LFO
: _Low Frequency Oscillator_
## Proyectos
### Atari Punk Console
El Atari Punk Console (APC) es uno de los proyectos recomendados para los principiantes ya que es muy fácil de hacer, pero el sonido no es muy melodioso que digamos. El nombre original era "Sintetizador de Sonido" ([Forrest M. Mims III - 1984](http://www.forrestmims.org/)). Mas tarde el grupo Kaustic Machines (la única referencia que encontré es [esta](https://compiler.kaustic.net/machines/back.html), y por si acaso me he salvado todos los esquemas que hay en la página), le puso el nombre de Atari Punk Console por que el sonido que produce se parece al de las primeras consolas Atari.
#### IC555 (Circuito integrado)
El montaje de la APC está basado en el uso de [NE555](https://es.wikipedia.org/wiki/Circuito_integrado_555) posiblemente uno de los chips más versátiles de la historia de la electrónica.
En principio el circuito divide la tensión Vcc en tres partes iguales gracias a su divisor de tensión con tres resistencias de 5K (lo de que se llama 555 por estas tres resistencias es una leyenda desmentida por su creador)
- _Vcc_ y _GND_ son los pines de alimentación. El voltaje de alimentación típico va de 4.5 V hasta los 16 V
- _Output_ (pin 3), aquí tenemos la salida del integrado, la salida alta es tipicamente: $V_{cc} - 1.7 V$, la salida baja
- _Trigger_ (pin 2) cuando en la entrada _Trigger_ tenemos una tensión menor de 1/3 de Vcc, el integrado activa la salida (y yo diria que pone la pata _Discharge_ en alta impedancia)
- _Threshold_ (pin 6), cuando la tensión en la entrada _Threshold_ es mayor que 2/3 de Vcc, el integrado desactiva la salida, y ademas pone el terminal _Discharge_ (pin 7) a tierra (GND)
- _Reset_ (pin 4), Si ponemos _RST_ a un voltaje cercano a cero (por debajo de 0.7 V) pone la salida del circuito a nivel bajo. En caso de no usar esta patilla lo mejor es conectarla a _Vcc_ para evitar reseteos indeseados.
- _CV_ (pin 5) es el pin de control de voltaje, el voltaje aplicado a esta patilla puede variar entre $V_{cc} - 1.7 V$ hasta prácticamente cero, este voltaje nos permitiría alterar los tiempos que definen los pulsos de salida o incluso conseguir salidas en rampa.
##### Configuración astable (no estable) del 555
Esta configuración no presenta un estado estable, tendremos un pulso cuadrado a la salida.
Es una configuración que podemos distinguir fácilmente por las dos resistencias en serie con un condensador y por que los pines _Threshold_ y _Trigger_ están conectados.
Los pines de _Reset_ y _Control Voltage_ no se usan, por eso conectamos la patilla _Reset_ a $V_{cc}$ y la patilla _CV_ a tierra a través del condensador C2.
{{< figure src="/images/synthes/ne555_astable.jpg" title="ne555 aestable" width=500 >}}
- En el momento en que alimentamos el circuito el condensador C1 comienza a cargarse con la corriente que pasa a través $R_1 + R_2$
Mientras el voltaje sea pequeño ($V_{c1} < \frac{1}{3}V_{cc}$) al estar el _Trigger_ por debajo del umbral la salida del circuito estará alta.
- Cuando el voltaje en el condensador C1 iguale o supere $\frac{2}{3}V_{cc}$, al estar _Threshold_ por encima de su umbral, la salida pasará a valor bajo. El pin _Discharge_ se pondrá a tierra, y el condensador C1 empezará a descargarse a través de $R_2$
- Cuando el condensador $C_1$ se descargue hasta $\frac{1}{3}V_{cc}$ de nuevo se activará la entrada _Trigger_ que hará que la salida pase a nivel alto y _Discharge_ pase a estado de alta impedancia.
Y todo el ciclo se repite de nuevo.
##### Configuración monoestable del 555
{{< figure src="/images/synthes/ne555_monostable.jpg" title="ne555 monoestable" width=500 >}}
##### Configuración biestable del 555
<!-- https://angelmicelti.github.io/4ESO/EAN/el_555_como_biestable.html -->
- [Un modelo simple](https://samvssound.com/projects/synthesizers/atari-punk-console/)
- [El mismo modelo con LFO](https://samvssound.com/tag/stepped-tone-generator/)
- <https://sdiy.info/wiki/Atari_Punk_Console>
- <https://compiler.kaustic.net/machines/apc.html>
- <https://www.jameco.com/Jameco/workshop/diy/atari-punk-console.html>
- <https://github.com/wenbakefield/bent-wavefield>
### Baby 8 Sequencer (B8BY)
- [Oh Baby, Baby10 Build A Classic Analog Music Sequencer](https://hackaday.com/2016/01/14/oh-baby-baby10-build-a-classic-analog-music-sequencer/)
- [Eddy Bergman.com: Synthesizer Build Part 8: 8 step sequencer](https://www.eddybergman.com/2019/12/synthesizer-build-part-8-8-step.html)
- [Hackster.io B8BY](https://www.hackster.io/Jettsette/b8by-baby-8-step-sequencer-c5d055)
- [Atary Punk Console & B8BY](https://www.instructables.com/Atari-Punk-Console-With-a-Baby-8-Step-Sequencer/)
- [Baby 5 sequencer Moritz Klein inspired version](https://knopslmodular.design.blog/2022/04/27/baby-5-sequencer-moritz-klein-inspired-version/)
- [Atari Punk Console & Sequencer](http://owyheesound.com/sequencer.php)
- <https://github.com/wenbakefield/bent-wavefield>
### Altavoz
- https://samvssound.com/projects/amplifiers/lm386-power-amplifier/
### Velleman voice changer
- https://diyaudiocircuits.com/velleman-mk171-voice-changer-circuit/
### Weird Sound Generator
### Noise Toaster
### Construir un eurorack
* Construir un Eurorack en cinco videos: [Youtube](https://youtu.be/EjDTz8JsX6c) o [Invideous](https://invidious.slipfox.xyz/watch?v=EjDTz8JsX6c)
* <https://youtu.be/AFhHArHk5JE>
* [Construcción de un Eurorack I](https://invidio.xamh.de/watch?v=6mVbi8B3usY)
* [Construcción de un Eurorack II](https://invidio.xamh.de/watch?v=NLljeZpyGEY)
* [Z-rails A](https://www.gear4music.es/es/Grabacion-y-Ordenadores/Tiptop-Audio-Z-Rail-40HP-Pair-Silver/218F)
* [Z-rails Thomann](https://www.thomann.de/es/tiptop_audio_z_rails_84hp_silver.htm)
* [Tienda en Holanda](https://www.etsy.com/shop/ModularSynthLab?ref=l2-about-shopname)
### Sintes digitales
#### TeensyPoly6
- [TeensyPoly6 en github](https://github.com/albnys/TeensyPoly6)
- [Video del TeensyPoly6](https://invidious.esmailelbob.xyz/watch?v=Exk_K2VwGu0)
- [Tsynth](http://electrotechnique.cc/) Basado en Teensy 4.1 no parece lo mismo
#### Polykit
- [Github del proyecto](https://github.com/polykit)
- <https://www.youtube.com/shorts/rFO4J-EEk-8>
- [Github de Crayg Barnes](https://github.com/craigyjp) Hace variantes del Polykit
#### Bomtempi
- <https://youtu.be/MxDHKpysxYs>
- <https://github.com/floretan/bontempi/tree/master/synth_main>
#### FPGA
- <https://thetinysynth.wordpress.com/technical-details/>
## Referencias
- [Sam vs Sound](https://samvssound.com/)
- [Sam vs Sound: Atari Punk Console](http://samvssound.com/projects/synthesizers/atari-punk-console/)
- [Atari Punk Console Improved](https://samvssound.com/tag/stepped-tone-generator/)
- [Synth DIY Wiki](https://sdiy.info/wiki/Main_Page), parece muy centrada en el [CatGirlSynth](https://sdiy.info/wiki/CatGirl_Synth#The_CGS_modules), una colección de módulos publicada como CC-BY-SHA-NC. La [página original de CGS](https://web.archive.org/web/20070202151335/http://cgs.synth.net/) se ha archivado en _archive.org_
- [Music From Outer Space](http://musicfromouterspace.com/) Probablemente una de las más conocidas, es la página del autor del libro _Make: Analog Synthesizers_
- [Music From Outer Space: Projects](http://musicfromouterspace.com/index.php?MAINTAB=SYNTHDIY&PROJARG=ALIENSCREAMER%2FALIENSCREAMER.php&CATPARTNO=ALIENSCREAMERPCB)
- [MFOS: Weird Sound Generator](http://musicfromouterspace.com/index.php?CATPARTNO=WSG001&PROJARG=WSG2010%2Fwsg_page1.html&MAINTAB=SYNTHDIY&SONGID=NONE&VPW=1910&VPH=807) El proyecto que recomiendan en MFOS para empezar.
- [Especificaciones Eurorack](https://sdiy.info/wiki/Eurorack) (Esta wiki parece abandonada)
- [Eurorack](https://intellijel.com/support/eurorack-101/) Bastante bien explicado
- [www.synth.net](https://web.archive.org/web/20070702154444/http://www.synth.net/) preservada en _archive.org_. En su dia se autodefinían como el _Recurso Definitivo para Sintetizadores_, alojaba varios proyectos diferentes.
- [Minimo](https://minimosynth.com/)
- [OTTO](https://github.com/bitfieldaudio/OTTO) un sintetizador open hardware inspirado en el OP-1 (sea lo que sea OP-1)
- [Una lista de synth abiertos](https://www.synthtopia.com/content/tag/open-hardware/)
- [The Synthesizer Academy](https://synthesizeracademy.com/)
### Videos
- [Building a DIY Kit](https://www.youtube.com/watch?v=cduc68TVWJ4) Un canal bastante interesante
- [DIY Minimoog Clone](https://www.youtube.com/watch?v=PATlf0W3m7k) REVISAR
- [Getting Started with Modular Synths](https://www.youtube.com/watch?v=AFhHArHk5JE) Como contruir un Eurorack
- <https://m.youtube.com/watch?v=Exk_K2VwGu0>
### Para revisar
- <https://hackaday.com/2015/02/04/logic-noise-sweet-sweet-oscillator-sounds/>
- <https://www.schmitzbits.de/>
- <https://www.soundtronics.co.uk/mfos-sound-lab-mini-synth-mkii-diy-electronics-parts-kit.html>
- <https://www.soundtronics.co.uk/mfos-synth-diy-build-knowledge-base/diy-mfos-voltage-controlled-oscillator-kb.html>
- <https://blog.thea.codes/the-design-of-the-juno-dco/>
- <https://synthityourself.com/>
- <https://www.thegeekpub.com/272691/building-a-breadboard-synthesizer-with-a-raspberry-pi-and-an-arduino-uno/>
- <https://northcoastsynthesis.com/synth-diy-projects/>
- <https://www.hongkiat.com/blog/open-source-hardware-synths/>
- <https://diyaudiocircuits.com/velleman-mk171-voice-changer-circuit/>
- [modwiggler](https://www.modwiggler.com/forum/index.php) un foro centrado en el tema de sintetizadores
- [Schemas for Minimoog](https://sites.google.com/site/minimoogwiki/home/notes)
- [Más de Minimoog](http://www.emusic-diy.org/MoogManuals#head-d983034898c0e3ee8d2f85af3aef51ebb66d2744)
- [Más esquemas de Minimoog](http://www.fantasyjackpalance.com/fjp/sound/synth/synthdata/16-moog-minimoog.html)
- [Otro clone de Minimoog](https://661.org/proj/minimoog/)
- [emusic-diy](http://emusic-diy.org/Schematics): Esquemas variados
- [How to Design and Build an Analog Synthesizer from Scracht](https://www.jiisuki.net/reports/howto-build-analog-synth.pdf) Un pdf
- [Minimo Synth](https://minimosynth.com/) Otro synth, pero digital
- [El canal de Ray Wilson en SoundCloud](https://soundcloud.com/raywilson)
- [Electrocumbia en SoundCloud](https://soundcloud.com/drdubastein/electrocumbia)
- [Obras usando el Noise Toaster en SoundCloud](https://soundcloud.com/search?q=noise+toaster)
- [Mateo Mena y sus Hypercubes](https://invidious.esmailelbob.xyz/watch?v=m55dfTXIUgY)
- [Explicación de distintos tipos de jack](https://media.digikey.com/pdf/Application%20Notes/CUI%20Application%20Notes/Audio_Jack_Switches_Schematics.pdf) (es un pdf [aquí](https://www.cuidevices.com/blog/understanding-audio-jack-switches-and-schematics) lo tienen online)
## Software
### Puredata
En Linux Mint se puede instalar _Puredata_ desde los repos, la versión 0.50.2 en el momento de escribir esto:
```bash
sudo apt install puredata multimedia-puredata
apt search ^pd- # para ver todas las bibliotecas de puredata disponibles para instalación
```
Si queremos tener una versión más actualizada podemos recurrir al ppa oficial:
```bash
sudo add-apt-repository ppa:pure-data/pure-data
sudo apt update
sudo apt install puredata
```
#### ELSE: Una biblioteca muy completa que incluye un tutorial de pd
Una vez instalada (y probada) la versión 0.52 de Puredata podemos instalar _Else_ desde el menú `Help::Find Externals`, buscamos `else` e instalamos (le va a llevar un ratito, al menos con mi wifi)
Una vez instalada, tenemos que mover el directorio `live-electronics-folder` que contiene el tutorial a un sitio más adecuado (casi seguro que `~/Documents/Pd` si has seguido las sugerencias durante la instalación). Es preferible dejar el directorio `~/Documents/Pd/externals` para las bibliotecas externas.
Con eso ya tenemos el tutorial disponible, no tenemos más que abrir los ficheros del tutorial desde el propio _Puredata_.
#### Referencias
- [Colección de recursos](https://puredata.info/docs/tutorials/)
- [Programming Electronic Music in Pd](http://www.pd-tutorial.com/english/index.html) de Johannes Kreidler (online)
- [Programando Música Electrónica en Pd](https://lucarda.com.ar/pd-tutorial/index.html) traducción del anterior al castellano (online)
- [The Theory and Technique of Electronic Music](http://msp.ucsd.edu/techniques.htm) de Miller Puckette
- [Live Electronics Tutorial](https://github.com/porres/Live-Electronics-Tutorial/blob/v1.0-rc2/README.md) Este tiene muy buena pinta, pero necesitas tener como mínimo la versión 0.52 de puredata, viene incluido como curso introductorio al instalar ELSE en Puredata.
- [Crear un Synth con Puredata](https://linuxaudio.github.io/libremusicproduction/html/tutorials/creating-simple-synthesizer-pure-data-%E2%80%93-part-i.html)
- [Casper Electronics DIY Synth](https://www.youtube.com/watch?v=FaoJaLmZaL4)
- <https://www.instructables.com/Elements-Little-Synths-With-Big-Sounds-1/>
- <https://drive.google.com/drive/folders/1yG68dSTKySPuuXvIyOB6vzyYmIeTKCn1>
- <https://syntherjack.net/category/article/>
### Supercollider
- [Supercollider](https://supercollider.github.io/) en github.
## Podcast
Vamos a proponer una serie de programas centrados en la música electrónica y sintetizadores analógicos, animando a los que quieran unirse a nosotros en la exploración de este tema e incluso construir algún prototipo con la información disponible.
¿Qué tiene que ver este tema con el hw libre? ¿o con esta sección?
Bueno, por un lado la electrónica analógica es un camino interesante para introducirse en el mundillo. La electrónica analógica te permite obtener resultados _inmediatos_ en el sentido de que te ahorras la fase de programar un firmware. Si además puedes disponer de alguna herramienta para visualizar las señales (un osciloscopio) puedes aprender rápidamente un montón de conceptos que llevaría horas explicar usando sólo la teoría.
Por otro lado, cuando empezamos a investigar la documentación disponible vimos que aunque los sintetizadores analógicos son una tecnología "antigua", que precede en una o dos décadas a toda la revolución de la electrónica digital posterior. El espíritu de muchos (no todos, claro) de los pioneros en la música electrónica es fácil de indentificar con el espíritu del hardware libre en la actualidad. Por ejemplo Ray Wilson (1956-2016) en su página MFOS (una referencia imprescindible) siempre se nego a que sus diseños fuera open source pero:
Ray was happy to share his circuit designs and knowledge with hobbyists but did not give permission to mass or hand produce what he considered his intellectual property. (MFOS designs are now owned by synthCube).
Es decir que compartió sus diseños siempre que fueran para uso No Comercial.
Esta filosofía de compartir conocimientos puede verse en las antiguas páginas web y foros que en muchos casos ya sólo están disponibles en [archive.org](https://archive.org/). Se puede comprobar que los constructores de "Sintes" compartían libremente la información y colaboraban para corregir los fallos y mejorar los diseños.
## Rollos sueltos
Una busqueda en Freetube por "eurorack diy" parece arrojar resultado interesantes.

@ -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

@ -0,0 +1,406 @@
---
weight: 4
title: "Migración de este blog a la última versión del tema FixIt"
date: 2024-01-12T17:30:10+0100
draft:
summary: "Apuntes de la migración del blog al nuevo FixIt"
categories:
- notes
tags:
- hugo
- blog
- FixIt
---
## Intro
Estos son los apuntes que he tomado cambiándo a la última versión del tema [_FixIt_](https://fixit.lruihao.cn/).
Al cambiar la versión del tema he aprovechado para pulir algunos pequeños errores y de momento lo dejo en un sólo idioma. Nunca conseguí tiempo para hacer las traducciones de los artículos.
## Instalación
1. Nos creamos un repo en Github a partir del template que Lruihao (el autor del tema) ha publicado [aqui](https://github.com/hugo-fixit/hugo-fixit-starter1/blob/main/README.en.md).
2. Clonamos este nuevo repo en nuestro disco. Me he hecho copias de este template tanto en [git.comacero.com](https://git.comacero.com) como en [mi gitlab](https://gitlab.com/salvari)
```bash
git clone --recursive https://github.com/salvari/newFixItgit
```
Para actualizar el tema en el futuro:
```bash
git submodule update --remote --merge themes/FixIt
```
3. Probamos el tema:
```bash
hsrv
# hsrv: aliased to hugo --buildDrafts server --disableFastRender
```
4. Procedemos con la configuración
## Configuración
Vamos a usar un directorio de configuración como [se describe](https://gohugo.io/getting-started/configuration/#configuration-directory) en la documentación de Hugo.
### `config.toml`
En el directorio de configuración tenemos la configuración organizada en distintos ficheros. El primero que necesitamos es `config.toml` que queda con el siguiente contenido:
```toml {title="config.toml",hl_lines=["7-8","10-11"]}
# -------------------------------------------------------------------------------------
# Hugo Configuration
# See: https://gohugo.io/getting-started/configuration/
# -------------------------------------------------------------------------------------
# title = "Hugo FixIt Blog"
title = "comacero"
baseURL = "http://comacero.com/"
theme = "FixIt"
defaultContentLanguage = "es"
languageCode = "es"
hasCJKLanguage = true
enableRobotsTXT = true
enableEmoji = true
enableGitInfo = true
relativeURLs = false
buildDrafts = false
summaryLength = 150
# ignore some build errors
ignoreErrors = ["error-remote-getjson", "error-missing-instagram-accesstoken"]
```
### `params.toml`
A continuación configuramos el fichero `params.toml`
En la primera sección del fichero cambiamos sólo tres líneas, configurando la descripción y el tema por defecto. Y ademas desativamos (de momento) la opción `gitRepo`.
```toml{linenos=table,hl_lines=[9,13,15]}
# -------------------------------------------------------------------------------------
# Theme Core Configuration
# See: https://fixit.lruihao.cn/theme-documentation-basics/#site-configuration
# -------------------------------------------------------------------------------------
# FixIt 0.2.15 | CHANGED FixIt theme version
version = "0.2.X" # e.g. "0.2.X", "0.2.15", "v0.2.15" etc.
# site description
description = "Notas personales sobre hardware y software libres"
# site keywords
keywords = ["Hugo", "FixIt"]
# site default theme ["light", "dark", "auto"]
defaultTheme = "dark"
# public git repo url only then enableGitInfo is true
# gitRepo = ""
# FixIt 0.1.1 | NEW which hash function used for SRI, when empty, no SRI is used
# ["sha256", "sha384", "sha512", "md5"]
fingerprint = ""
# FixIt 0.2.0 | NEW date format
dateFormat = "2006-01-02"
# website images for Open Graph and Twitter Cards
images = []
# FixIt 0.2.12 | NEW enable PWA
enablePWA = false
# FixIt 0.2.14 | NEW whether to add external Icon for external links automatically
externalIcon = false
# FixIt 0.2.14 | NEW FixIt will, by default, inject a theme meta tag in the HTML head on the home page only.
# You can turn it off, but we would really appreciate if you dont, as this is a good way to watch FixIt's popularity on the rise.
disableThemeInject = false
```
En las secciones siguientes (`app` y `search`) del fichero `params.toml` no cambiamos nada de momento. Aunque probablemente probemos con otros motores de búsqueda en el futuro.
```toml
# FixIt 0.2.0 | NEW App icon config
[app]
# optional site title override for the app when added to an iOS home screen or Android launcher
title = ""
# whether to omit favicon resource links
noFavicon = false
# modern SVG favicon to use in place of older style .png and .ico files
svgFavicon = ""
# Safari mask icon color
iconColor = "#5bbad5"
# Windows v8-10 tile color
tileColor = "#da532c"
# FixIt 0.2.12 | CHANGED Android browser theme color
[app.themeColor]
light = "#f8f8f8"
dark = "#252627"
# FixIt 0.2.0 | NEW Search config
[search]
enable = true
# type of search engine ["lunr", "algolia", "fuse"]
type = "lunr"
# max index length of the chunked content
contentLength = 4000
# placeholder of the search bar
placeholder = "test"
# FixIt 0.2.1 | NEW max number of results length
maxResultLength = 10
# FixIt 0.2.3 | NEW snippet length of the result
snippetLength = 30
# FixIt 0.2.1 | NEW HTML tag name of the highlight part in results
highlightTag = "em"
# FixIt 0.2.4 | NEW whether to use the absolute URL based on the baseURL in search index
absoluteURL = false
[search.algolia]
index = ""
appID = ""
searchKey = ""
[search.fuse]
# FixIt 0.2.17 | NEW https://fusejs.io/api/options.html
isCaseSensitive = false
minMatchCharLength = 2
findAllMatches = false
location = 0
threshold = 0.3
distance = 100
ignoreLocation = false
useExtendedSearch = false
ignoreFieldNorm = false
```
En la siguiente sección (`header`) si que hacemos cambios. Configuramos el logo, el nombre de la web. y el subtítulo que aparecerá en la cabecera.
Para configurar el logo tendremos que añadir el fichero `cerito.svg` en el directorio `assets/images`. Tendremos que crear ese directorio y copiar el fichero `cerito.svg` en el mismo.
```toml{linenos=table,linenostart=81,hl_lines=[10,12,22],}
# Header config
[header]
# FixIt 0.2.13 | CHANGED desktop header mode ["sticky", "normal", "auto"]
desktopMode = "sticky"
# FixIt 0.2.13 | CHANGED mobile header mode ["sticky", "normal", "auto"]
mobileMode = "auto"
# FixIt 0.2.0 | NEW Header title config
[header.title]
# URL of the LOGO
logo = "/images/cerito.svg"
# title name
name = "comacero"
# you can add extra information before the name (HTML format is supported), such as icons
pre = " "
# you can add extra information after the name (HTML format is supported), such as icons
post = ""
# FixIt 0.2.5 | NEW whether to use typeit animation for title name
typeit = false
# FixIt 0.2.12 | NEW Header subtitle config
[header.subtitle]
# subtitle name
name = "Notas sobre hardware y software libres"
# whether to use typeit animation for subtitle name
typeit = false
# FixIt 0.2.18 | NEW Breadcrumb config
[breadcrumb]
enable = false
sticky = false
showHome = false
```
En la sección `footer` cambiamos sólo el parámetro _site creation year_.
```toml{linenos=table,linenostart=112,hl_lines=[14],}
# Footer config
[footer]
enable = true
# FixIt 0.2.17 | CHANGED Custom content (HTML format is supported)
# For advanced use, see parameter `params.customFilePath.footer`
custom = ""
# FixIt 0.2.0 | NEW whether to show Hugo and theme info
hugo = true
# FixIt 0.2.0 | NEW whether to show copyright info
copyright = true
# FixIt 0.2.0 | NEW whether to show the author
author = true
# Site creation year
since = 2019
# FixIt 0.2.14 | NEW whether to show total word count of site content
wordCount = true
# FixIt 0.2.12 | NEW Public network security only in China (HTML format is supported)
gov = ""
# ICP info only in China (HTML format is supported)
icp = ""
# license info (HTML format is supported)
license = '<a rel="license external nofollow noopener noreferrer" href="https://creativecommons.org/licenses/by-nc-sa/4.0/" target="_blank">CC BY-NC-SA 4.0</a>'
# FixIt 0.2.17 | CHANGED Site creation time
# FixIt 0.2.17 | CHANGED Site creation time
[footer.siteTime]
enable = false
animate = true
icon = "fa-solid fa-heartbeat"
pre = ""
value = "" # e.g. "2021-12-18T16:15:22+08:00"
# FixIt 0.2.17 | NEW footer lines order, optional values: ["first", 0, 1, 2, 3, 4, 5, "last"]
[footer.order]
powered = 0
copyright = 0
statistics = 0
visitor = 0
beian = 0
```
En las secciones `section`, `list` y `tagcloud` no hacemos cambios de momento.
```toml{linenos=table,linenostart=149}
# FixIt 0.2.0 | NEW Section (all posts) page config
[section]
# special amount of posts in each section page
paginate = 20
# date format (month and day)
dateFormat = "01-02"
# amount of RSS pages
rss = 10
# FixIt 0.2.13 | NEW recently updated posts settings
[section.recentlyUpdated]
enable = false
rss = false
days = 30
maxCount = 10
# FixIt 0.2.0 | NEW List (category or tag) page config
[list]
# special amount of posts in each list page
paginate = 20
# date format (month and day)
dateFormat = "01-02"
# amount of RSS pages
rss = 10
# FixIt 0.2.17 | NEW TagCloud config for tags page
[tagcloud]
enable = false
min = 14 # Minimum font size in px
max = 32 # Maximum font size in px
peakCount = 10 # Maximum count of posts per tag
orderby = "name" # Order of tags, optional values: ["name", "count"]
```
En la seccion `home` hacemos los cambios marcados en el listado. Es **importante** borrar el correo del _gravatar_ para que el tema cargue la imagen que le pasamos.
```toml{linenos=table,linenostart=181,hl_lines=[9,11,17]}
# Home page config
[home]
# FixIt 0.2.0 | NEW amount of RSS pages
rss = 10
# Home page profile
[home.profile]
enable = true
# Gravatar Email for preferred avatar in home page
gravatarEmail = ""
# URL of avatar shown in home page
avatarURL = "/images/cerito.svg"
# FixIt 0.2.17 | NEW identifier of avatar menu link
avatarMenu = ""
# FixIt 0.2.7 | CHANGED title shown in home page (HTML format is supported)
title = ""
# subtitle shown in home page
subtitle = "Apuntes personales de hardware y software libres"
# whether to use typeit animation for subtitle
typeit = true
# whether to show social links
social = true
# FixIt 0.2.0 | NEW disclaimer (HTML format is supported)
disclaimer = "Sólo para autoconsumo (^_^)"
# Home page posts
[home.posts]
enable = true
# special amount of posts in each home posts page
paginate = 6
```
En la sección `social` puedes rellenar todas las RRSS que te apetezca que aparezcan en tu página. No voy a detallar todos los cambios pero pego la configuración para mastodon y gitea que, al menos en mi caso, es un poco especial:
```toml
[social.Mastodon]
id = "@salvari"
prefix = "https://mastodon.gal/"
title = "Mastodon"
[social.gitea]
id = "salvari"
prefix = "https://git.comacero.com/"
title = "Gitea"
```
Por el momento no hacemos más cambios en el fichero `params.toml`
### `menus.toml`
Editamos el fichero y lo dejamos con los cambios marcados en el listado a continuación.
```toml{linenos=table,hl_lines=[31,"47-66"]}
# -------------------------------------------------------------------------------------
# Menu Configuration
# See: https://fixit.lruihao.cn/theme-documentation-basics/#menu-advanced-configuration
# -------------------------------------------------------------------------------------
[[main]]
identifier = "posts"
# you can add extra information before the name (HTML format is supported), such as icons
pre = ""
# you can add extra information after the name (HTML format is supported), such as icons
post = ""
name = "Posts"
url = "/posts/"
# title will be shown when you hover on this menu link
title = ""
weight = 1
# FixIt 0.2.14 | NEW add user-defined content to menu items
[main.params]
# add css class to a specific menu item
class = ""
# whether set as a draft menu item whose function is similar to a draft post/page
draft = false
# FixIt 0.2.16 | NEW add fontawesome icon to a specific menu item
icon = "fa-solid fa-archive"
# FixIt 0.2.16 | NEW set menu item type, optional values: ["mobile", "desktop"]
type = ""
[[main]]
identifier = "categories"
pre = ""
post = ""
name = "Categorias"
url = "/categories/"
title = ""
weight = 2
[main.params]
icon = "fa-solid fa-th"
[[main]]
identifier = "tags"
pre = ""
post = ""
name = "Etiquetas"
url = "/tags/"
title = ""
weight = 3
[main.params]
icon = "fa-solid fa-tags"
[[main]]
identifier = "links"
pre = ""
post = ""
name = "Enlaces"
url = "/links/"
title = ""
weight = 6
[main.params]
icon = "fa-solid fa-link"
[[main]]
identifier = "about"
pre = ""
post = ""
name = "Acerca de"
url = "/about/"
title = ""
weight = 10
[main.params]
icon = "fa-solid fa-info-circle"
```

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…
Cancel
Save