


[{"content":"","date":"28 marzo 2025","externalUrl":null,"permalink":"/tags/devops/","section":"","summary":"","title":"Devops","type":"tags"},{"content":" Introduction # Let\u0026rsquo;s continue with the series of blog posts about moving from Docker to Podman.\nToday I\u0026rsquo;ll cover a short issue which might help you with your transition:\nWhy --restart unless-stopped doesn\u0026rsquo;t work??\nLet\u0026rsquo;s say you read that Podman\u0026rsquo;s command line API is 1:1 compatible with Docker\u0026rsquo;s and you ran your container as always, but you realised that it didn\u0026rsquo;t boot up automatically after a reboot of the system as it was happening when using Docker. Well, this was something to be expected as we moved from a container manager that runs as a daemon to another that runs as a regular process.\nDocker vs Podman at System\u0026rsquo;s Boot # When our system boots up, we have a systemd service that handles starting Docker. Then, Docker itself is in charge of starting all those containers marked to be started automatically. Kind of magic to us, as we only need to specify the argument --restart unless-stopped when running a container.\nBut Podman doesn\u0026rsquo;t work that way. There\u0026rsquo;s no service running Podman in background. A disadvantage? I don\u0026rsquo;t think so. Why to place Docker\u0026rsquo;s service in the middle if we can write our own systemd service to trigger our target container. That would be cleaner, wouldn\u0026rsquo;t it?\nOur New Best Friend: systemd # Podman doesn\u0026rsquo;t reinvent the wheel, there\u0026rsquo;s an excellent piece of SW that already handles services in our OS: systemd. So instead of duplicating features, it relies on systemd to handle the life-cycle of our containers.\nIf you\u0026rsquo;re not very familiar with systemd, I\u0026rsquo;d suggest you to have a look at this great book: Linux Service Management Made Easy with systemd by Donald Al Tevault.\nThis section covers how to achieve the same feature we had when using --restart unless-stopped while running our containers.\nUnderstanding The New Deployment Schema # This diagram from the book Podman in Action by Daniel J. Walsh depicts how all the pieces will be put together:\nWe\u0026rsquo;ll need to define a systemd unit file that describes how do we expect to run our container. Then systemd will use it to trigger our container when required. What if you don\u0026rsquo;t know how to write a unit file? No worries, as Podman devs have been really kind providing a tool that generates such file on behalf of us. But a brief understanding of unit files would be good anyway. Remember that you have man systemd.unit at hand if you need to clarify any option from the future unit file.\nLet\u0026rsquo;s get our hands dirty and make an example of it.\nBooting a Container at Boot # For the sake of the tutorial, I\u0026rsquo;ll use one image of my own: La Coctelera Backend, this image is the one that I use to deploy the backend service of La Coctelera.\nFirst, we need either to create a container or use a running one. This will be used by Podman to detect what settings are needed when the unit file gets made.\n$ podman create \\ --restart unless-stopped \\ --network host \\ --env-file /home/user/.local/share/coctelera/coctelera.env \\ -v coctelera:/app/config \\ ghcr.io/felipet/lacoctelera_backend:main Remember to include the restart policy!\nNow, we can use podman generate systemd to generate a systemd unit file. I usually don\u0026rsquo;t provide names to the containers as I enjoy using the automatic funny names that are generated. If you are like me, you\u0026rsquo;ll need to get the name that was assigned to your container (podman ps -a).\npodman generate systemd --new amazing_feistel \u0026gt; ~/.config/systemd/user/lacoctelera_backend.service I intend to run my service as a regular user, that\u0026rsquo;s why I place the unit file in the user\u0026rsquo;s local storage. Let\u0026rsquo;s take a look at the file that was generated:\n[Unit] Description=La Coctelera backend service Wants=network-online.target After=network-online.target RequiresMountsFor=%t/containers [Service] Environment=PODMAN_SYSTEMD_UNIT=%n Restart=always TimeoutStopSec=70 ExecStart=/usr/bin/podman run \\ --cidfile=%t/%n.ctr-id \\ --cgroups=no-conmon \\ --rm \\ --sdnotify=conmon \\ -d \\ --network host \\ --env-file /home/user/.local/share/coctelera/coctelera.env \\ -v coctelera:/app/config ghcr.io/felipet/lacoctelera_backend:main ExecStop=/usr/bin/podman stop \\ --ignore -t 10 \\ --cidfile=%t/%n.ctr-id ExecStopPost=/usr/bin/podman rm \\ -f \\ --ignore -t 10 \\ --cidfile=%t/%n.ctr-id KillSignal=SIGINT Type=notify NotifyAccess=all [Install] WantedBy=default.target I only made a few minor changes to it: I modified the description, and added KillSignal as my application expects Ctrl + c as the signal to stop the service gracefully. Pretty painless, wasn\u0026rsquo;t it?\nWe only need a few more shell commands before we call it a day. We can test running our container using systemctl:\n$ systemctl --user start lacoctelera_backend.service $ systemctl --user status lacoctelera_backend.service If everything went fine, we shall see that our service is active (running). Now, it\u0026rsquo;s time to enable our service at boot using this command:\n$ systemctl --user enable lacoctelera_backend.service And that\u0026rsquo;s it! Our service will be trigger at boot the next time.\nFinal Thoughts # At this point you might think: such a hassle, I have to write a unit file and learn about how to use systemd while I only needed a simple option when I was using Docker. And this is sort of true. But the bottom line is that we can benefit from the other interesting features that are provided by systemd.\nThe combination of systemd + Podman leads to a more secure and reliable deployment. We\u0026rsquo;ll delve deeper into the security options that we can use from now in future posts.\nAlso, learning how to use systemd is never a waste of time. We can use this knowledge for many other things, as systemd is a core component of our OS.\nAnd a final remark, did you like how Docker handled logs? I personally don\u0026rsquo;t. The command docker logs \u0026lt;container\u0026gt; simply sucks. Then you have to write your logs to a file, and place it in a volume for example, if you aim to access them easily from the host. OK, but what happens when that log grows? And it will, believe me.\nBy using systemd we can make use of journald to handle our log messages. One of the greatest advantages is that journald makes an automatic log rotation of our logs, and it also keeps logs in binary which saves space. And stores our logs independently of our container, so even if our container is down, we can check the logs. That\u0026rsquo;s a nice feature.\nThat\u0026rsquo;s all for today, stay tuned for more posts of the series!\n","date":"28 marzo 2025","externalUrl":null,"permalink":"/posts/podman-containers-at-sysboot/","section":"Posts","summary":"Introduction # Let’s continue with the series of blog posts about moving from Docker to Podman.\nToday I’ll cover a short issue which might help you with your transition:\nWhy --restart unless-stopped doesn’t work??\nLet’s say you read that Podman’s command line API is 1:1 compatible with Docker’s and you ran your container as always, but you realised that it didn’t boot up automatically after a reboot of the system as it was happening when using Docker. Well, this was something to be expected as we moved from a container manager that runs as a daemon to another that runs as a regular process.\n","title":"How To Start Containers with Podman At System's Boot","type":"posts"},{"content":"","date":"28 marzo 2025","externalUrl":null,"permalink":"/tags/podman/","section":"","summary":"","title":"Podman","type":"tags"},{"content":" Introduction # In this blog post, I\u0026rsquo;ll explain the steps that I followed to migrate from Docker to Podman. Whether you are a sysadmin or a regular developer, I\u0026rsquo;m quite sure that you\u0026rsquo;ve heard of Docker before. It\u0026rsquo;s a great piece of software, and it really helped to improve and simplify software delivering. Believe me, I was there before Docker exists, and it was quite chaotic.\nThen, why to move away from Docker? Well, if you\u0026rsquo;re after better integration with the system, like using systemd, or if you\u0026rsquo;re after more security options, or if you prefer software that doesn\u0026rsquo;t use daemons, then Podman is definitely worth a try!\nPodman is an alternative container management tool developed as open source by Red Hat. It was developed after Docker and that meant Podman\u0026rsquo;s developers could learn a lot of lessons from it. Moreover, they dared to improve it, specially targeting the weakest point of Docker: security. They were very clever: they realised it would be hard to take market share of a well established software, so they made Podman fully compatible with Docker\u0026rsquo;s API. To me, this is a key to success because regardless on whether they offer a better piece of software or not, there\u0026rsquo;s a lot of inertia towards Docker and reverting it would be almost impossible, unless you make an offer that you can\u0026rsquo;t refuse: use Podman as you were using Docker. So simple, so brilliant.\nI\u0026rsquo;m not going to get into the nitty-gritty or compare them side-by-side, as there are already some articles out there doing that. I\u0026rsquo;ll just point you to the e-book Podman in Action by Daniel J. Walsh. As of today, it is free to download, and it is really well written. If you\u0026rsquo;re interested in Podman, you should definitely check it out.\nToday\u0026rsquo;s blog post focuses on the migration from Docker to Podman. We\u0026rsquo;ll take advantage of the compatible API, and we\u0026rsquo;ll dare to seamless restart our containers using the same command that we were using with Docker with an single change: replace docker by podman.\nHence, no fancy stuff today, just a straightforward migration. I think it\u0026rsquo;s best to keep it simple, as we\u0026rsquo;re about to touch an important part of your system, and we need to feel confident enough before moving forward. What would be better than proving that we can run Podman as we were doing with Docker, let\u0026rsquo;s get started!\nSave Your Containers # You might be reluctant to move because you have several containers running, and you can\u0026rsquo;t afford losing the content of those. Many images are prepared to place modifiable content in a particular path, this way you could use the option --volume to specify a host folder in which data can outlive the container.\nBut, what if you forgot to use an external volume? Or, what if your particular image keeps many modifications within the running container? If you\u0026rsquo;re in this situation, don\u0026rsquo;t panic! There\u0026rsquo;s a simple procedure to save all the content, and prepare the containers to be loaded into Podman.\nHow To Save a Running Container # First, we\u0026rsquo;ll get the hash identifier or the name of the containers that we aim to migrate. If there are stopped containers, we\u0026rsquo;ll need docker ps --all.\nWe\u0026rsquo;ll use docker commit for the purpose of saving a running container into an image that we can later import into Podman. The process is simple, just use:\n$ docker commit \u0026lt;container id or name\u0026gt; \u0026lt;image name\u0026gt; If the container is running, that command will pause it for a while, so keep that in mind in case you can\u0026rsquo;t interrupt your underlying service.\nOnce we\u0026rsquo;ve made an image of a container, we need to export it this way:\n$ docker save \u0026lt;image name\u0026gt; | gzip \u0026gt; \u0026lt;image name\u0026gt;.tar.gz Repeat that process for each container that you need to migrate, and you\u0026rsquo;ll be ready to start using Podman.\nTip: If you were running docker as superuser, the images that you\u0026rsquo;ll export will be owned by root. As we\u0026rsquo;ll run Podman as a regular user, remember to change the permissions of those images before proceeding with the following steps.\nImport Your Saved Images Into Podman # At this stage, we\u0026rsquo;re ready to start running our containers using Podman instead of Docker. Just a heads-up: you might want to stop your running containers under Docker now, otherwise ports being used by your running containers in Docker would avoid running your containers with Podman using exactly the same configuration.\nFirst, we\u0026rsquo;ll import all the images that from the previous step using:\n$ podman load \u0026lt; \u0026lt;image name\u0026gt;.tar.gz When you are done, go and check everything went OK using podman image ls. You shall see your images listed. Now, it\u0026rsquo;s time to fire up a few containers using those images. One of the greatest things of Podman is that its command line API is 100% compatible with Docker\u0026rsquo;s. So take the command that you used before to run your containers with Docker: docker run [...], and replace docker by podman, that\u0026rsquo;s it!\nFinal Steps # There\u0026rsquo;s not much else to do. We saved all our beloved Docker containers and imported them into Podman. We made a big jump but we had a great safety net. Something didn\u0026rsquo;t go as expected? Just start your stopped container in Docker and you lost nothing but time. However, I hope everything ran smoothly and you faced no big issues during the process.\nKeeping Docker won\u0026rsquo;t harm you, so don\u0026rsquo;t be forced to clean it up before you feel comfortable using Podman. But if you reached this point, you are more than ready to free some space and remove Docker from your system.\nSo far, we made no use of any special feature, as we are using Podman as a 1:1 replacement for Docker. However, Podman offers many interesting features to improve security. I\u0026rsquo;ll cover some interesting features that Podman includes in following blog posts, so keep an eye on my blog!\n","date":"13 marzo 2025","externalUrl":null,"permalink":"/posts/migration-from-docker-to-podman/","section":"Posts","summary":"Introduction # In this blog post, I’ll explain the steps that I followed to migrate from Docker to Podman. Whether you are a sysadmin or a regular developer, I’m quite sure that you’ve heard of Docker before. It’s a great piece of software, and it really helped to improve and simplify software delivering. Believe me, I was there before Docker exists, and it was quite chaotic.\nThen, why to move away from Docker? Well, if you’re after better integration with the system, like using systemd, or if you’re after more security options, or if you prefer software that doesn’t use daemons, then Podman is definitely worth a try!\n","title":"How To Migrate From Docker To Podman","type":"posts"},{"content":"","date":"19 febrero 2025","externalUrl":null,"permalink":"/tags/finance/","section":"","summary":"","title":"Finance","type":"tags"},{"content":"","date":"19 febrero 2025","externalUrl":null,"permalink":"/tags/ibex35/","section":"","summary":"","title":"Ibex35","type":"tags"},{"content":"","date":"19 febrero 2025","externalUrl":null,"permalink":"/tags/programming/","section":"","summary":"","title":"Programming","type":"tags"},{"content":"","date":"19 febrero 2025","externalUrl":null,"permalink":"/categories/shortbot/","section":"Categories","summary":"","title":"Shortbot","type":"categories"},{"content":"","date":"19 febrero 2025","externalUrl":null,"permalink":"/tags/shortbot/","section":"","summary":"","title":"Shortbot","type":"tags"},{"content":" Introduction # The IbexShortBot was a stateless bot. A stateless bot doesn\u0026rsquo;t keep any sort of information of the users. It just replies to the user\u0026rsquo;s requests, one at a time. Despite that design decision made the bot very restricted on its features, it helped me to focus on delivering a solution as quickly as I could, to attract investor\u0026rsquo;s interest on using the bot.\nThe bot has been used for six months and the user\u0026rsquo;s feedback is positive. That\u0026rsquo;s enough for me to decide to take it a step further.\nIt\u0026rsquo;s time for the bot to meet databases.\nNew features # I ran a survey between the users of the bot, and by far, the most requested feature is related to following stocks and receiving updates when any short position changes.\nCompared to the current flow, in which an user has to select the stock every time she/he aims to check whether the position changed or not, the subscription-based flow would heavily simplify the user\u0026rsquo;s experience, and it would avoid missing any update in a position.\nIt seems a simple change: add an SQLite database, keep user\u0026rsquo;s subscriptions and run a timed-service to inform users when a change occurred.\nBut this time, I want to think big. That flow was in my mind since the beginning, but I considered that it was more interesting to deliver a simple solution quickly, than a full solution that would have required more development time.\nA Fully Integrated Stock Market Data Information System # One year ago, I started to work on the idea of having a Rust-based ecosystem for investment analysis and trading tools. The overall idea is having all the data centralised in a local database system that would feed my analysis tools.\nInformation about investment and trading is everywhere these days. One just needs to choose an investment strategy and follow it. However, what if I\u0026rsquo;d like to explore and implement my own financial models, or design custom trading oscillators? What if I rather make my own way than follow someone else\u0026rsquo;s? Most would say, that\u0026rsquo;s stupid, as only a few can beat the market. I\u0026rsquo;ll say that mostly true when you look where most of people do. But I\u0026rsquo;m convinced that it is possible to beat inefficient markets.\nI won\u0026rsquo;t enter in what is an efficient market, and what is not. It would be a pretty long explanation (it would well deserve it\u0026rsquo;s own blog entry). Let\u0026rsquo;s say, very very briefly, that an efficient market would find a fair price for a stock pretty quickly, whilst an inefficient market wouldn\u0026rsquo;t do it. It means that inefficient markets include both under valuated and over valuated stocks in higher proportions than efficient markets. Here\u0026rsquo;s where one can beat the market.\nMy market of choice is the IBEX35, and I do believe it is an inefficient market. Why do you tell me all this nonsense, you\u0026rsquo;d ask. The answer is related to what I said in the second paragraph of this section: inefficient markets don\u0026rsquo;t offer the market information as easily as efficient markets do, and that\u0026rsquo;s why it is so important for me to develop a fully integrated stock market data information system.\nAnd a (small) part of this information system is the IbexShortBot.\nIbexShortBot and The Finance Data Harvesting Library # A few days ago, I posted an entry in the blog talking about a new library that I wrote in Rust for collecting financial data from several sources and centralise it in a local database. You can read more about it in this entry: A Finance Data Harvesting Library.\nThe library along a CLI tool that makes use of it are in production now, and the bot simply needs to connect to the DB, and retrieve the active positions for the chosen ticker by the user. That meant I had to remove all the code related to collecting and processing data from the external source (CNMV\u0026rsquo;s page) and write a simple handler for the database. The changes are included in the PR-11 of the repository.\nImprovements Achieved # The most obvious improvement is the huge reduction in the latency of an user request: from tens of seconds to nearly zero! Short positions are cached now in my local database, so the bot just needs to issue a query rather than a complex procedure to collect and parse data from an external website (which is pretty slow, by the way).\nOnly that would have been worth the changes and the effort. It\u0026rsquo;s a change that heavily improves user\u0026rsquo;s experience.\nOther improvements are not so obvious to end users, but equally important as they leverage more important changes to come: positions are kept in a database, so the bot will not only access current short positions (as it happened before) but an entire registry with the evolution of the positions. Further analyses will be possible such as tendency of the overall short position against a company, track the activity of a particular hedge fund, or get notified when a company starts getting short positions. There are endless possibilities!\nAside from that, the project is better structured now because the logic related to the data harvesting is taken to a different library, which means the bot repository only tracks code related to the bot itself.\nFinally, the usage of the external website with the data (CNMV\u0026rsquo;s) is fairer now as the requests are centralised from a single place which scans the web a few times per day. Before, the website was requested every time an user of the bot asked for a list of positions. Also, if multiple users requested the same data, it meant that multiple requests were made rather than sharing the results as it happens now. I find it important as well, as I prefer not to abuse of external free services, specially when it is obvious that they suffer from performance issues.\nFuture Plans # The new feature means a considerable step forward for the bot. It is no longer a stateless bot: short positions are kept and an historical record is available. However, the only current benefit of having such record is the latency reduction for the access to the current positions. There is no logic that makes use of past positions.\nIncluding further features that make use of the historical record of short positions scores high in my todo list. Many possible analyses are available now. Also, it will be possible to detect changes: new positions, positions that got removed, \u0026hellip; And notify users, which means a huge change: from a request-based flow to a subscription-based flow.\nWhile including new features related to analysis is sort of easy, going from a request-based flow to a subscription-based flow is not. The architecture of Teloxide bots (the framework in which is based the IbexShortBot) makes it rather difficult if possible. Thus, it will require a lot of analysis and effort, anyway I am keen to see this feature working, so I will take the challenge!\n","date":"19 febrero 2025","externalUrl":null,"permalink":"/posts/shortbot-meets-db/","section":"Posts","summary":"Introduction # The IbexShortBot was a stateless bot. A stateless bot doesn’t keep any sort of information of the users. It just replies to the user’s requests, one at a time. Despite that design decision made the bot very restricted on its features, it helped me to focus on delivering a solution as quickly as I could, to attract investor’s interest on using the bot.\nThe bot has been used for six months and the user’s feedback is positive. That’s enough for me to decide to take it a step further.\n","title":"Shortbot Meets DBs","type":"posts"},{"content":"","date":"10 enero 2025","externalUrl":null,"permalink":"/es/tags/apache/","section":"Tags","summary":"","title":"Apache","type":"tags"},{"content":"","date":"10 enero 2025","externalUrl":null,"permalink":"/es/categories/","section":"Categories","summary":"","title":"Categories","type":"categories"},{"content":"","date":"10 enero 2025","externalUrl":null,"permalink":"/es/tags/deployment/","section":"Tags","summary":"","title":"Deployment","type":"tags"},{"content":" Introducción # En esta entrada, explicaré cómo lograr un despliegue automatizado tras un cambio en un sitio web creado con Hugo y desplegado en Ubuntu Server con Apache gracias a Webhook.\nExisten muchos servicios de hosting que permiten desplegar gratuitamente una página web creada con Hugo. Esto ya se explica en la documentación oficial. Para la mayoría, usar un servicio de hosting externo es la mejor opción, pero ¿qué ocurre si ya tienes un servidor?\nMi plan era alojar mi sitio web personal en mi propio servidor: Nubecita. Este servidor utiliza Ubuntu Server 24.04 y Apache como servidor web. Una de las combinaciones más comunes para alojar contenido en internet. Además, tengo mi sitio web subido a un repositorio en GitHub. Mi objetivo era automatizar el proceso de despliegue, de modo que cada vez que subo un nuevo cambio al repositorio, se implemente en el servidor web de producción.\nEsta guía está diseñada para este tipo de configuración. Espero que a alguien le resulte útil.\nEmpezando por el principio # Antes de empezar a configurar los servicios y escribir los scripts, configuraremos nuestro sistema. Necesitaremos instalar Webhook. Optaré por la versión empaquetada de los repositorios, en lugar de la de la Snap Store:\nsudo apt install webhook Actualización: Necesitarás Webhook \u0026gt;= 2.8.2, ya que esa versión incluye todos los cambios necesarios para ejecutarse con Systemd.\nAdemás, no recomiendo usar Hugo de la Snap Store, ya que te obligaría a tener tus scripts de despliegue en un directorio del sistema en lugar de tu directorio personal. Sin embargo, la decisión es tuya; ten en cuenta que no puedes usar Hugo de la Snap Store para seguir esta guía.\nScript de deployment básico # Una vez que tengamos nuestro sistema listo, podemos comenzar con la parte interesante. Necesitaremos un script de despliegue, que no es más que un script que automatiza todos los pasos que realizarías si hicieras un despliegue manual. Para esta guía, incluiré el script que utilizo, pero tendrás que modificarlo según tus necesidades.\n#!/bin/bash echo \u0026#34;Retrieve new content from the repo...\u0026#34; git clone https://github.com/felipet/personal-site.git --depth 1 cd personal-site echo \u0026#34;Build the static page\u0026#34; hugo cd public echo \u0026#34;Deploy the new content\u0026#34; rsync -r ./ /var/www/html/felipe-site chown -R www-data:www-data /var/www/html/felipe-site systemctl reload apache2 echo \u0026#34;Wiping temporal data...\u0026#34; cd ../../ rm -rf personal-site Aspectos destacables del script:\nAñade --depth 1 al comando clone. Esto ahorrará tiempo si tu repositorio contiene una cantidad considerable de imágenes y otros archivos pesados.\nTras sincronizar con rsync, cambio el propietario de los nuevos datos. El usuario www-data se usa con frecuencia en implementaciones de Apache. Considera si este usuario y grupo son la mejor opción para tu implementación.\nReinicio el servicio apache2 después de la implementación, por lo que este script debe ser ejecutado por un usuario con privilegios.\nPuedes colocar el script donde quieras. Yo elegí la ruta /var/scripts y asigné como propietario del directorio al usuario y grupo www-data. Pruébalo y asegúrate de que funciona correctamente.\nConfigura el Webhook # Nuestro script de despliegue ya está listo, pero ¿cómo lo ponemos en práctica? Aquí es donde entra en juego Webhook. Añadiremos un nuevo servicio Systemd para gestionar Webhook y escribiremos el archivo de configuración que le indicará a Webhook qué webhook debe desplegarse para nuestro propósito.\nEjecutando Webhook como un servicio de Systemd # Configuraremos Webhook para que se ejecute como un servicio de Systemd. Esto se explica detalladamente en la documentación oficial, así que solo mencionaré las pequeñas modificaciones que realicé.\nEn resumen, este es el descriptor del socket:\n[Unit] Description=Webhook server socket [Socket] ## Listen on one specific interface only ListenStream=127.0.0.1:9191 [Install] WantedBy=multi-user.target Como puedes ver, indiqué que el socket solo escuchará las solicitudes provenientes de la dirección local. Planeo usar un proxy inverso, lo que añade una capa adicional de seguridad, ya que no quiero exponerlo al público. Si decides prescindir del proxy inverso, tendrás que escuchar en 0.0.0.0:9191, pero recuerda que necesitarás configurar una capa de seguridad adicional.\nY el descriptor del servicio:\n[Unit] Description=Webhook server [Service] Type=exec ExecStart=/usr/bin/webhook -nopanic -hooks /var/webhooks/hooks.json -verbose -port 9191 StandardOutput=append:/var/log/webhook StandardError=append:/var/log/webhook User=root Group=root Muy importante: El puerto de escucha y el puerto que se pasa como argumento al Webhook deben ser el mismo. Puede parecer un consejo básico, pero si no se utilizan los puertos estándar, es posible que se omita la especificación de algún puerto, lo que puede provocar una pérdida de tiempo.\nComo ya mencioné, es necesario ejecutar este servicio como root para tener los privilegios suficientes para ejecutar systemctl reload apache2.\nConfigura un nuevo Webhook # Quizás hayas notado que pasamos como argumento al Webhook el archivo /var/webhooks/hooks.json. Ahora, analizaremos este archivo.\nElegí la ruta /var/webhooks, pero puedes ubicarla donde prefieras. También le di permisos de lectura y escritura a www-data en esa ruta, ya que mi objetivo es desplegar mi repositorio allí cada vez que se llame al servicio.\nEste es el contenido del archivo hooks.json:\n[ { \u0026#34;id\u0026#34;: \u0026#34;deploy_felipe_site\u0026#34;, \u0026#34;execute-command\u0026#34;: \u0026#34;/var/scripts/deploy_felipe-site.bash\u0026#34;, \u0026#34;command-working-directory\u0026#34;: \u0026#34;/var/webhooks\u0026#34;, \u0026#34;trigger-rule\u0026#34;: { \u0026#34;match\u0026#34;: { \u0026#34;type\u0026#34;: \u0026#34;payload-hmac-sha256\u0026#34;, \u0026#34;secret\u0026#34;: \u0026#34;SOME_SECRET_STRING!!!\u0026#34;, \u0026#34;parameter\u0026#34;: { \u0026#34;source\u0026#34;: \u0026#34;header\u0026#34;, \u0026#34;name\u0026#34;: \u0026#34;X-Hub-Signature-256\u0026#34; } } } } ] El valor de execute-command debe ser la ruta a tu script de despliegue. Los valores del campo match se explican en la documentación oficial de GitHub. No olvides reemplazar el valor de secret. Genera una cadena segura aleatoria e insértala. Guárdala por un tiempo, ya que necesitarás introducir la cadena secreta al configurar nuestro Webhook en GitHub.\nPara terminar # ¿Listo para empezar? Entonces ejecuta estos comandos:\nsudo systemctl enable webhook.socket sudo systemctl start webhook.socket Y comprueba que todo funciona correctamente:\nsystemctl status webhook.socket Deberías obtener algo similar a este resultado:\n● webhook.socket - Webhook server socket Loaded: loaded (/etc/systemd/system/webhook.socket; enabled; preset: enabled) Active: active (listening) since Tue 2025-01-14 10:39:37 UTC; 6s ago Triggers: ● webhook.service Listen: 127.0.0.1:9191 (Stream) Tasks: 0 (limit: 37781) Memory: 8.0K (peak: 256.0K) CPU: 820us CGroup: /system.slice/webhook.socket Jan 14 10:39:37 nubecita.eu systemd[1]: Listening on webhook.socket - Webhook server socket. Configura Apache como un proxy inverso # Aquí, puede que te desvíes del camino que seguí. Si no te gusta usar un proxy inverso, abre directamente un puerto en tu firewall y ofrece tu servicio al público. En ese caso, te recomiendo que sigas la documentación de Webhook para habilitar HTTPS.\nYo uso Apache para alojar varios sitios web y como proxy inverso para algunos servicios web que ofrezco. Para mí, fue la elección obvia. Evito abrir otro puerto en mi firewall y Apache se encarga de la gestión de SSL, una situación ideal.\nPara reenviar las solicitudes al socket de Webhook, añade un nuevo host virtual con el comando ProxyPass:\nProxyPass /webhook http://127.0.0.1:9191/hooks ProxyPassReverse /webhook http://127.0.0.1:9191/hooks Esto redirigirá una solicitud a https://nubecita.eu/webhook/deploy_felipe_site al socket Webhook local. Si creó un nuevo host virtual, habilítelo. En cualquier caso, reinicie el servicio Apache.\nsudo systemctl reload apache2 Nuestro backend ya está listo, hagamos una solicitud sencilla para comprobar que responde. ¡Crucemos los dedos!\nPodemos usar Curl para enviar una solicitud POST al endpoint donde instalamos nuestro webhook:\ncurl -X \u0026#39;POST\u0026#39; \\ \u0026#39;https://nubecita.eu/webhook/deploy_felipe_site\u0026#39; Hook rules were not satisfied.% Como no enviamos nuestras credenciales ni ninguna otra información con la solicitud, nuestro servicio nos indica que no cumplimos con las reglas definidas en hooks.json. Perfecto, nuestro backend responde y bloquea las solicitudes ficticias. Completemos el proceso de implementación con el último paso.\nCrea un webhook en GitHub # Hemos llegado al último paso necesario. Debemos configurar un webhook en nuestro repositorio de GitHub.\nEl proceso se explica en esta página (https://docs.github.com/en/webhooks/using-webhooks/creating-webhooks). Sin embargo, resumamos los pasos:\nVe a la sección de configuración del repositorio que contiene el contenido de tu sitio web. Abre Webhooks en el panel izquierdo y haz clic en «Añadir webhook». Introduce la URL de tu endpoint en «URL de carga útil» y selecciona «application/json» como «Tipo de contenido». ¿Recuerdas la cadena secreta? Ahora es el momento de usarla de nuevo. Añádela en el campo «Secreto». Por supuesto, activa la verificación SSL. Finalmente, elige cuándo quieres que se ejecute el webhook. Yo seleccioné «Envíos» y «Lanzamientos». Guárdalo y ve a la pestaña «Entregas recientes». Verás que se ha iniciado una comprobación de estado. Si se ha realizado correctamente, ¡enhorabuena! El proceso de despliegue está listo.\nRealiza cualquier cambio en el contenido del repositorio y envíalo. Verás que los cambios se han desplegado en tu sitio web de producción.\n","date":"10 enero 2025","externalUrl":null,"permalink":"/es/posts/website-deployment/","section":"Posts","summary":"Descripción de los pasos necesarios para automatizar el despliegue de tu web usando Hugo y GitHub Actions","title":"Despliegue automatizado de tu web","type":"posts"},{"content":"","date":"10 enero 2025","externalUrl":null,"permalink":"/es/tags/github/","section":"Tags","summary":"","title":"Github","type":"tags"},{"content":"","date":"10 enero 2025","externalUrl":null,"permalink":"/es/tags/hugo/","section":"Tags","summary":"","title":"Hugo","type":"tags"},{"content":"","date":"10 enero 2025","externalUrl":null,"permalink":"/es/","section":"La web de Felipe","summary":"","title":"La web de Felipe","type":"page"},{"content":"","date":"10 enero 2025","externalUrl":null,"permalink":"/es/categories/nubecita/","section":"Categories","summary":"","title":"Nubecita","type":"categories"},{"content":"","date":"10 enero 2025","externalUrl":null,"permalink":"/es/posts/","section":"Posts","summary":"","title":"Posts","type":"posts"},{"content":"","date":"10 enero 2025","externalUrl":null,"permalink":"/es/tags/reverse-proxy/","section":"Tags","summary":"","title":"Reverse-Proxy","type":"tags"},{"content":"","date":"10 enero 2025","externalUrl":null,"permalink":"/es/tags/","section":"Tags","summary":"","title":"Tags","type":"tags"},{"content":"","date":"10 enero 2025","externalUrl":null,"permalink":"/es/tags/webhook/","section":"Tags","summary":"","title":"Webhook","type":"tags"},{"content":"Cuando decidí crear este blog, consideré dos opciones principales: WordPress y Hugo. Tengo algo de experiencia con el primero, ya que alojo algunos sitios web en Nubecita, y antes tenía una página personal con WordPress (una simple página de portafolio).\nSin embargo, quería algo fácil y sencillo. Al fin y al cabo, el objetivo del sitio era añadir información sobre mí y algunas entradas de blog. Así que, ¿para qué complicarme con todas las complejidades de WordPress?\nVeamos algunos consejos que me hubiera gustado saber antes.\nEnumera tus necesidades # Es importante tener claro qué quieres que haga tu sitio web.\n¿Solo necesitas una página de perfil sencilla? ¿O quieres ser bloguero? ¿Piensas escribir en más de un idioma? Estas son preguntas importantes, ya que no todos los temas de Hugo ofrecen todas las funciones que podrías necesitar.\nPor lo tanto, es importante tener una lista rápida de tus necesidades como punto de partida, ya que esto influirá en tu siguiente decisión: elegir un tema.\nElige el tema que mejor se adecúe a tus necesidades # Una de las primeras decisiones que debes tomar al crear un sitio web con Hugo es elegir un tema.\nExisten excelentes temas, que puedes encontrar en esta página. Sin embargo, no hay un conjunto estándar de características que todos los temas deban tener. Me gustó mucho el diseño de un tema, pero le faltaban algunas características que necesitaba.\nCuando empiezas, lo último que quieres es modificar o crear un tema. Por lo tanto, debes encontrar un tema que incluya la mayor cantidad posible de las características de tu lista inicial. A partir de ahí, puedes comenzar.\nCometí el error de intentar configurar el sitio web con todas las características que quería desde el principio. Es poco probable que encuentres un tema que cubra todas tus necesidades. Así que elige un tema, empieza con uno y construye tu página paso a paso.\nDespliega tu web lo antes posible # A veces, no te das cuenta de que un tema no funciona como esperabas o no satisface tus necesidades hasta que lo implementas. Y cuando digo implementar, me refiero a subirlo a un servidor web para que la gente pueda acceder a él a través de Internet.\n¿Por qué? Dediqué mucho tiempo a mi sitio web y, al alojarlo, me di cuenta de que el tema tenía problemas con CORS. Tras investigar un poco, parecía que la autora ya lo sabía, pero afirmaba haberlo solucionado. ¿Me apetecía abrir una incidencia en GitHub o intentar arreglarlo yo mismo? No en ese momento. El tema era bonito, pero no perfecto, y prefería elegir otro antes que perder demasiado tiempo arreglándolo.\nAsí que mi mejor consejo es: ve al proyecto de tu tema y busca la demo. La mayoría de los temas la incluyen. Implementa la demo tú mismo y pruébala. Esa sería la mejor manera de hacerlo antes de decidir qué tema elegir.\nAutomatiza tu despliegue # Puede parecer excesivo, pero créeme, te ahorrará muchísimo tiempo. ¿Qué prefieres: usar el sitio cada vez que quieras publicar contenido o dejar que un script lo haga por ti? Si te gusta la segunda opción pero te preocupa la dificultad, ¡no te preocupes! Solo lee mi publicación al respecto:\nDespliegue automatizado ","date":"10 enero 2025","externalUrl":null,"permalink":"/es/posts/hugo-website/","section":"Posts","summary":"En esta entrada explico como empezar a montar un sitio web desde 0 usando Hugo","title":"Aprende a publicar tu sitio web usando Hugo","type":"posts"},{"content":"La Coctelera es un proyecto de código abierto cuyo objetivo es desarrollar una base de datos colaborativa para compartir recetas de cócteles.\nInicios # El proyecto nació en 2024 con el objetivo de conseguir algo similar a lo que AeroPrecipe ofrece en el mundo de las recetas para Aeropress: un lugar donde la comunidad de entusiastas de los cócteles puedan subir sus recetas y compartirlas. Todo de forma colaborativa y descentralizada.\nTip La Coctelera es a los cócteles lo que AeroPrecipe a las recetas para AeroPress.\nObjetivos # El objetivo principal del proyecto es desarrollar un sitio web al estilo de AeroPrecipe donde cualquier usuario pueda subir sus propias recetas, y así conseguir el desarrollo de una comunidad de entusiastas de los cócteles.\nLas recetas deben poder organizarse de forma clara, a fin de que los usuarios puedan encontrar o descubrir recetas. Se pretende permitir descubrir recetas filtrando por ingredientes, o por grados de dificultad. Así mismo, se incluirá un sistema de votación que permita destacar las recetas que tengan más aceptación por la comunidad.\nDesde el punto de vista técnico, el proyecto busca segregar la parte de gestión pura, o backend, de lo que sería la parte de acceso para el usuario, o frontend. Ello busca que gente interesada en colaborar con el proyecto pueda desarrollar sus propias aplicaciones, de manera que el acceso a los datos se permita desde múltiples puntos de entrada: sitio web, aplicación móvil, etc.\nFront-end # El principal punto de acceso a la base de datos será una página web que permitirá a los usuarios acceder fácilmente a recetas de cócteles o registrarse para publicar las suyas.\nEl desarrollo de la interfaz de usuario aún se encuentra en una fase inicial. Si le interesa, visite este repositorio en GitHub:\nfelipet/lacoctelera_frontend Frontend for La Coctelera web service JavaScript 1 0 Back-end # Se ha desarrollado un servicio back-end para permitir que otras personas interesadas conecten sus propios clientes a la base de datos. Si bien desarrollar una solución segregada requiere más trabajo, creemos que esto incentivará a los programadores a desarrollar clientes para otras plataformas en el futuro. El back-end ofrece una API REST cuya documentación se puede consultar en la página del proyecto:\nDocumentación de la API La API incluye varios recursos que permiten acceder a datos sobre ingredientes, autores y recetas. El acceso a los datos es libre, pero para subir o modificar datos de la base de datos se requiere un token de autenticación. Los tokens se pueden solicitar gratuitamente (consulte el enlace en la documentación de la API). Esta medida de seguridad tiene como objetivo principal prevenir el spam y el uso malintencionado de la base de datos.\nDevelopment # El servicio de back-end está cerca de alcanzar su primera versión estable. Si le interesa el desarrollo o el código fuente, es de código abierto y está disponible en:\nfelipet/lacoctelera_backend Backend for La Coctelera web service Rust 1 0 El servicio está implementado temporalmente en nubecita.eu. La base de datos solo contiene algunas recetas de ejemplo por el momento, pero podría empezar a usarse para realizar pruebas.\nSi visitas la página de documentación de la API, encontrarás una interfaz de usuario Swagger que muestra las operaciones permitidas.\nPor ejemplo, puedes realizar una solicitud para comprobar si existe alguna receta para preparar un Cosmopolitan usando curl de la siguiente manera:\ncurl -X \u0026#39;GET\u0026#39; \\ \u0026#39;https://nubecita.eu/coctelera/api/v0/recipe?name=cosmopolitan\u0026#39; \\ -H \u0026#39;accept: application/json\u0026#39; ","date":"9 enero 2025","externalUrl":null,"permalink":"/es/projects/lacoctelera/","section":"Proyectos seleccionados","summary":"La Coctelera es un proyecto de código abierto cuyo objetivo es desarrollar una base de datos colaborativa para compartir recetas de cócteles.","title":"La Coctelera","type":"projects"},{"content":"","date":"9 enero 2025","externalUrl":null,"permalink":"/es/projects/","section":"Proyectos seleccionados","summary":"","title":"Proyectos seleccionados","type":"projects"},{"content":"Ibex ShorBot es un bot de Telegram que ayuda a los inversores a monitorizar las posiciones cortas en empresas incluidas en el índice IBEX35 (el principal índice bursátil español).\nLas posiciones cortas tienden a aumentar la volatilidad del precio y, en la mayoría de los casos, terminan en una fuerte caída. Los inversores que suelen mantener sus posiciones a largo plazo están muy expuestos a este tipo de movimientos.\nLas posiciones cortas son legales y útiles, a pesar de lo que muchos inversores piensen al respecto.\nEl seguimiento de estas posiciones puede generar grandes beneficios, ya sea intentando aprovechar una posible tendencia bajista o evitando comprar acciones de una empresa con un alto volumen de posiciones cortas y esperando a que los fondos comiencen a retirar sus posiciones.\nEl bot permite a los inversores acceder a esta información de forma sencilla y rápida, directamente desde la interfaz de Telegram, mediante un chat.\nEs un proyecto de código abierto, si quieres ver el código, el repositorio está enlazado un poco más abajo. Si simplemente quieres empezar a usarlo, simplemente agrega el bot en tu chat de Telegram. Busca @IbexShortBot. Además del bot, existe un chat público chat group donde se resuelven dudas y aceptan sugerencias.\nfelipet/shortbot A Telegram bot that analises CNMV\u0026rsquo;s page to find short positions Rust 1 0 ","date":"9 enero 2025","externalUrl":null,"permalink":"/es/projects/shortbot/","section":"Proyectos seleccionados","summary":"Un bot de Telegram que rastrea las posiciones en corto en el IBEX35","title":"Shortbot","type":"projects"},{"content":"¡Por fin me he decidido! Tras muchos años pensando en crearme un blog personal, y nunca terminar de dar el paso, aquí está la prueba fehaciente de que, tarde o temprano, a todo le llega su momento.\nY, ¿por qué ahora?\nPara empezar, siempre he sido reticente a abrir mi propio blog ya que pienso que sufrimos un exceso de contenido en Internet. Tanto bueno, como malo. Así que siempre he pensado que no tenía nada verdaderamente importante que decir para justificar añadir más ruido al ya caótico mundo de Internet.\nPero hace cosa de un año, empecé a dedicar más tiempo a una serie de proyectos personales, y creo que es interesante tener una plataforma donde poder añadir información al respecto, y poderlos dar a conocer.\nAsí que mi propósito para esta web es simple: añadir contenido sólo cuando aporte algo interesante. Además, no suelo tener mucho tiempo libre así que seguro que no me paso de publicar sinsentidos.\n","date":"9 enero 2025","externalUrl":null,"permalink":"/es/posts/first-post/","section":"Posts","summary":"¡La primera entrada de mi nuevo blog!!","title":"Mi nuevo blog","type":"posts"},{"content":"","externalUrl":null,"permalink":"/es/authors/","section":"Authors","summary":"","title":"Authors","type":"authors"},{"content":"","externalUrl":null,"permalink":"/es/series/","section":"Series","summary":"","title":"Series","type":"series"}]