<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Leonardo</title>
    <description>The latest articles on Forem by Leonardo (@leover22).</description>
    <link>https://forem.com/leover22</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3648406%2F4b4c8747-0894-4e14-a75b-dd39b9c48aca.jpg</url>
      <title>Forem: Leonardo</title>
      <link>https://forem.com/leover22</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/leover22"/>
    <language>en</language>
    <item>
      <title>Post-Mortem: Cuando los Backups Automatizados fallan y el SII te respira en la nuca (Guía de Supervivencia)</title>
      <dc:creator>Leonardo</dc:creator>
      <pubDate>Fri, 05 Dec 2025 19:20:58 +0000</pubDate>
      <link>https://forem.com/leover22/post-mortem-cuando-los-backups-automatizados-fallan-y-el-sii-te-respira-en-la-nuca-guia-de-214c</link>
      <guid>https://forem.com/leover22/post-mortem-cuando-los-backups-automatizados-fallan-y-el-sii-te-respira-en-la-nuca-guia-de-214c</guid>
      <description>&lt;h3&gt;
  
  
  El Viernes Negro
&lt;/h3&gt;

&lt;p&gt;17:45 de un viernes. Clásico. Terminando el día y pensando en el taco de Vespucio, cuando me entra la llamada de un viejo amigo, típico dueño PYME que encuentra caro pagar soporte informático mensual...&lt;/p&gt;

&lt;p&gt;—&lt;em&gt;"Compadre, no entra el sistema. Dice que los archivos están encriptados. Y hay un archivo de texto pidiendo Bitcoins."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Maaal... &lt;strong&gt;Ransomware PYME&lt;/strong&gt;. El terror de cualquier &lt;strong&gt;Soporte TI en Santiago&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Le dije lo que todo ingeniero dice para calmar las aguas: &lt;em&gt;"Tranquilo, tenemos **backups automatizados&lt;/em&gt;* diarios a las 3 AM. Borramos todo, restauramos y el lunes operan normal."*&lt;/p&gt;

&lt;p&gt;Me conecté por VPN, fui a la carpeta &lt;code&gt;/var/backups/&lt;/code&gt; y ahí estaban los archivos &lt;code&gt;.sql.gz&lt;/code&gt;. Todos con fecha de hoy. Pesaban 45KB.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;45KB.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Una base de datos de 10 años de facturación no pesa 45KB.&lt;/strong&gt; Al abrir el archivo, no había &lt;code&gt;INSERT INTO&lt;/code&gt;. Solo había un mensaje de error de &lt;code&gt;mysqldump&lt;/code&gt; que se había guardado como si fuera el respaldo.&lt;/p&gt;

&lt;p&gt;Llevaban 6 meses respaldando un error. &lt;strong&gt;6 meses de Facturación Electrónica SII a la basura.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Si crees que esto no te puede pasar porque tienes un cronjob corriendo, siéntate. Te voy a explicar cómo la &lt;strong&gt;recuperación de desastres&lt;/strong&gt; es lo único que te separa de la quiebra (y de las multas del fisco).&lt;/p&gt;

&lt;h3&gt;
  
  
  Cuando el SII se suma a la fiesta
&lt;/h3&gt;

&lt;p&gt;En Chile, perder datos no es solo un problema técnico; es un problema tributario grave.&lt;/p&gt;

&lt;p&gt;El &lt;strong&gt;Ransomware PYME&lt;/strong&gt; no solo te bloquea la operación. Si pierdes el libro de ventas o las referencias de la &lt;strong&gt;Facturación Electrónica SII&lt;/strong&gt;, entras en un terreno pantanoso.&lt;/p&gt;

&lt;p&gt;Según la normativa vigente (y el Código Tributario, Art. 97), el "no llevar contabilidad" o la pérdida de registros puede acarrear multas que duelen. Estamos hablando de sanciones que van desde 1 UTM hasta el 50% o 300% de los impuestos eludidos si no puedes probar tus ventas.&lt;/p&gt;

&lt;p&gt;¿Sabes cuánto cuesta reconstruir la contabilidad de un año a mano? Mucho más que contratar una &lt;strong&gt;consultoría preventiva de ciberseguridad en Chile&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;El problema real es la falsa sensación de seguridad. &lt;strong&gt;El 90% de los sysadmins configuran el backup y nunca, jamás, hacen un simulacro de restauración hasta que tienen el fuego en la cocina.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Un Script de Backup "A Prueba de Balas"
&lt;/h3&gt;

&lt;p&gt;Olvídate de los scripts de una línea. Un &lt;strong&gt;script bash backup&lt;/strong&gt; decente tiene que validar que lo que guardó sirve.&lt;/p&gt;

&lt;p&gt;Aquí te dejo la versión sanitizada del script que implementamos después del desastre. Copia, pega y adáptalo. &lt;strong&gt;Esto no es código de tutorial, es código de producción.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;

&lt;span class="c"&gt;# ---------------------------------------------------------&lt;/span&gt;
&lt;span class="c"&gt;# AUTOR: Tu SysAdmin de Confianza&lt;/span&gt;
&lt;span class="c"&gt;# DESCRIPCIÓN: Backup MySQL con verificación de integridad&lt;/span&gt;
&lt;span class="c"&gt;# y subida a Nube (S3/MinIO).&lt;/span&gt;
&lt;span class="c"&gt;# ---------------------------------------------------------&lt;/span&gt;

&lt;span class="c"&gt;# CONFIGURACIÓN&lt;/span&gt;
&lt;span class="nv"&gt;DB_USER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"root"&lt;/span&gt;
&lt;span class="nv"&gt;DB_PASS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"TuPasswordSuperSegura123"&lt;/span&gt;
&lt;span class="nv"&gt;DB_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"facturacion_prod"&lt;/span&gt;
&lt;span class="nv"&gt;BACKUP_DIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/mnt/backups/mysql"&lt;/span&gt;
&lt;span class="nv"&gt;DATE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt; +%Y-%m-%d_%H%M&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;FILENAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"backup_&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;DB_NAME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;_&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;DATE&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.sql.gz"&lt;/span&gt;
&lt;span class="nv"&gt;LOG_FILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/var/log/db_backup.log"&lt;/span&gt;
&lt;span class="nv"&gt;SLACK_WEBHOOK&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"https://hooks.slack.com/services/T000/B000/XXXX"&lt;/span&gt;

&lt;span class="c"&gt;# Función de Log&lt;/span&gt;
log_message&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"[&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt; &lt;span class="s1"&gt;'+%Y-%m-%d %H:%M:%S'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;] &lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$LOG_FILE&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

log_message &lt;span class="s2"&gt;"INICIO: Comenzando backup de &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;DB_NAME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="c"&gt;# 1. DUMP DE LA BASE DE DATOS&lt;/span&gt;
&lt;span class="c"&gt;# Usamos --single-transaction para no bloquear tablas InnoDB en producción&lt;/span&gt;
mysqldump &lt;span class="nt"&gt;-u&lt;/span&gt; &lt;span class="nv"&gt;$DB_USER&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt;&lt;span class="nv"&gt;$DB_PASS&lt;/span&gt; &lt;span class="nt"&gt;--single-transaction&lt;/span&gt; &lt;span class="nt"&gt;--quick&lt;/span&gt; &lt;span class="nt"&gt;--lock-tables&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;false&lt;/span&gt; &lt;span class="nv"&gt;$DB_NAME&lt;/span&gt; | &lt;span class="nb"&gt;gzip&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$BACKUP_DIR&lt;/span&gt;/&lt;span class="nv"&gt;$FILENAME&lt;/span&gt;

&lt;span class="c"&gt;# Verificamos código de salida de mysqldump (PIPESTATUS para capturar el error antes del gzip)&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PIPESTATUS&lt;/span&gt;&lt;span class="p"&gt;[0]&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;-ne&lt;/span&gt; 0 &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;log_message &lt;span class="s2"&gt;"ERROR CRÍTICO: Falló el mysqldump. Abortando."&lt;/span&gt;
    curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'Content-type: application/json'&lt;/span&gt; &lt;span class="nt"&gt;--data&lt;/span&gt; &lt;span class="s1"&gt;'{"text":"🚨 FALLÓ BACKUP DB: Error en mysqldump"}'&lt;/span&gt; &lt;span class="nv"&gt;$SLACK_WEBHOOK&lt;/span&gt;
    &lt;span class="nb"&gt;exit &lt;/span&gt;1
&lt;span class="k"&gt;fi&lt;/span&gt;

&lt;span class="c"&gt;# 2. VALIDACIÓN DE INTEGRIDAD (El paso que todos se saltan)&lt;/span&gt;
&lt;span class="c"&gt;# Verificamos que el archivo no esté vacío y tenga un tamaño mínimo (ej. 1MB)&lt;/span&gt;
&lt;span class="nv"&gt;FILESIZE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;stat&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt;%s &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$BACKUP_DIR&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;$FILENAME&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;MINSIZE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1048576 &lt;span class="c"&gt;# 1MB en bytes&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;$FILESIZE&lt;/span&gt; &lt;span class="nt"&gt;-lt&lt;/span&gt; &lt;span class="nv"&gt;$MINSIZE&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;log_message &lt;span class="s2"&gt;"ERROR: El backup pesa menos de 1MB (&lt;/span&gt;&lt;span class="nv"&gt;$FILESIZE&lt;/span&gt;&lt;span class="s2"&gt; bytes). Sospechoso."&lt;/span&gt;
    curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'Content-type: application/json'&lt;/span&gt; &lt;span class="nt"&gt;--data&lt;/span&gt; &lt;span class="s1"&gt;'{"text":"⚠️ ALERTA: Backup generado es sospechosamente pequeño."}'&lt;/span&gt; &lt;span class="nv"&gt;$SLACK_WEBHOOK&lt;/span&gt;
    &lt;span class="c"&gt;# No borramos, pero alertamos.&lt;/span&gt;
&lt;span class="k"&gt;else
    &lt;/span&gt;log_message &lt;span class="s2"&gt;"ÉXITO: Backup generado. Tamaño: &lt;/span&gt;&lt;span class="k"&gt;$((&lt;/span&gt;&lt;span class="nv"&gt;$FILESIZE&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="m"&gt;1024&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="m"&gt;1024&lt;/span&gt;&lt;span class="k"&gt;))&lt;/span&gt;&lt;span class="s2"&gt; MB"&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;

&lt;span class="c"&gt;# 3. PRUEBA DE RESTAURACIÓN (La prueba de fuego)&lt;/span&gt;
&lt;span class="c"&gt;# Restauramos en una DB temporal para asegurar que el SQL es válido&lt;/span&gt;
&lt;span class="nv"&gt;TEST_DB&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"test_restore_db"&lt;/span&gt;
mysql &lt;span class="nt"&gt;-u&lt;/span&gt; &lt;span class="nv"&gt;$DB_USER&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt;&lt;span class="nv"&gt;$DB_PASS&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"DROP DATABASE IF EXISTS &lt;/span&gt;&lt;span class="nv"&gt;$TEST_DB&lt;/span&gt;&lt;span class="s2"&gt;; CREATE DATABASE &lt;/span&gt;&lt;span class="nv"&gt;$TEST_DB&lt;/span&gt;&lt;span class="s2"&gt;;"&lt;/span&gt;
zcat &lt;span class="nv"&gt;$BACKUP_DIR&lt;/span&gt;/&lt;span class="nv"&gt;$FILENAME&lt;/span&gt; | mysql &lt;span class="nt"&gt;-u&lt;/span&gt; &lt;span class="nv"&gt;$DB_USER&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt;&lt;span class="nv"&gt;$DB_PASS&lt;/span&gt; &lt;span class="nv"&gt;$TEST_DB&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;$?&lt;/span&gt; &lt;span class="nt"&gt;-eq&lt;/span&gt; 0 &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;log_message &lt;span class="s2"&gt;"VERIFICACIÓN: Restauración en DB de prueba exitosa."&lt;/span&gt;
    &lt;span class="c"&gt;# Limpieza&lt;/span&gt;
    mysql &lt;span class="nt"&gt;-u&lt;/span&gt; &lt;span class="nv"&gt;$DB_USER&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt;&lt;span class="nv"&gt;$DB_PASS&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"DROP DATABASE &lt;/span&gt;&lt;span class="nv"&gt;$TEST_DB&lt;/span&gt;&lt;span class="s2"&gt;;"&lt;/span&gt;
&lt;span class="k"&gt;else
    &lt;/span&gt;log_message &lt;span class="s2"&gt;"ERROR FATAL: El backup no se pudo restaurar."&lt;/span&gt;
    curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'Content-type: application/json'&lt;/span&gt; &lt;span class="nt"&gt;--data&lt;/span&gt; &lt;span class="s1"&gt;'{"text":"🔥 ERROR CRÍTICO: El backup está corrupto, no pasa el restore test."}'&lt;/span&gt; &lt;span class="nv"&gt;$SLACK_WEBHOOK&lt;/span&gt;
    &lt;span class="nb"&gt;exit &lt;/span&gt;1
&lt;span class="k"&gt;fi&lt;/span&gt;

&lt;span class="c"&gt;# 4. OFFSITE COPY (AWS S3 CLI)&lt;/span&gt;
&lt;span class="c"&gt;# aws s3 cp $BACKUP_DIR/$FILENAME s3://mi-bucket-backups/&lt;/span&gt;
&lt;span class="c"&gt;# log_message "Subido a S3"&lt;/span&gt;

&lt;span class="nb"&gt;exit &lt;/span&gt;0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Cómo perder tu pega en 3 pasos
&lt;/h3&gt;

&lt;p&gt;Hemos visto varios servidores morir y siempre es por lo mismo. Si estás cometiendo estos errores, arréglalos hoy. No mañana. &lt;strong&gt;Hoy.&lt;/strong&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  A. El Backup Local ("Backup nube local vs AWS")
&lt;/h4&gt;

&lt;p&gt;Guardar el backup en el mismo disco duro donde está la base de datos (&lt;code&gt;/var/lib/mysql&lt;/code&gt; y &lt;code&gt;/home/backups&lt;/code&gt; en el mismo disco físico). Si el disco muere, pierdes los datos y el respaldo.&lt;br&gt;
&lt;strong&gt;Solución:&lt;/strong&gt; Mínimo un montaje NFS externo, o mejor, directo a S3/Azure Blob. La regla 3-2-1 es sagrada: 3 copias, 2 medios, 1 offsite.&lt;/p&gt;

&lt;h4&gt;
  
  
  B. Ignorar la "Normativa SII respaldo digital"
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Muchos creen que con tener los XML en el portal del proveedor de facturación basta.&lt;/strong&gt; Grave error si usas un ERP propio o un sistema de gestión, ya que la responsabilidad de la integridad de la data histórica es tuya. Ante una fiscalización, el SII te va a pedir libros mayores y auxiliares. Si tu base está corrupta, prepárate para las &lt;strong&gt;multas SII por pérdida de datos&lt;/strong&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  C. El "Script Silencioso"
&lt;/h4&gt;

&lt;p&gt;El script corre, falla, y no le avisa a nadie. Pasan meses. Cuando vas a buscar el archivo, te das cuenta de que el disco se llenó en febrero y estamos en agosto.&lt;br&gt;
&lt;strong&gt;Solución:&lt;/strong&gt; Monitoreo activo. &lt;strong&gt;Si el backup se hace o no, debe sonar una alarma. El silencio no es éxito.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusión: No seas el héroe, sé el paranoico
&lt;/h3&gt;

&lt;p&gt;La &lt;strong&gt;recuperación de desastres&lt;/strong&gt; no es un producto que compras, es una mentalidad. Ese viernes en Patronato logramos recuperar data de un disco viejo que el dueño tenía en su casa (pura suerte), pero perdieron 2 semanas de ventas. El costo operativo fue brutal.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;¡No esperes a tener el ransomware en la pantalla para preocuparte!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Si este post te incomodó porque te hizo recordar alguna mala práctica... revisa tus crons ahora mismo y valida tus respaldos, pruébalos.&lt;/p&gt;

&lt;p&gt;Si necesitas estructurar un plan serio de respaldos y dejar de sufrir con la informática, apóyate en un &lt;strong&gt;&lt;a href="https://www.ionet.cl/ciberseguridad-empresas" rel="noopener noreferrer"&gt;equipo de Soporte TI y Continuidad Operativa que mantenga tus sistemas andando&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Si sabes de alguien que tiene la idea de que no necesita una empresa de soporte TI porque tiene "un amigo que lo puede ver", cuéntale esta historia de lo caro que le puede salir.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;¿Y tú? ¿Ya verificaste que están sanos los respaldos?&lt;/strong&gt; Comenta (y sé honesto, que aquí no juzgamos... tanto).&lt;/p&gt;

</description>
      <category>devops</category>
      <category>watercooler</category>
      <category>security</category>
      <category>database</category>
    </item>
  </channel>
</rss>
