Esta pagina se ve mejor con JavaScript habilitado

Servidor de calendarios en FreeBSD

 ·  🎃 kr0m

En esta ocasión vamos instalar y configurar un servidor de alojamiento de calendarios, mas concretamente Baikal.

Para ello primero crearemos una jail limpia donde instalaremos la configuración y herramientas básicas que suelo instalar par luego proceder con PHP, Nginx y MySQL.

El tutorial se compone de los siguientes pasos:


Jail e instalación de herramientas básicas:

Creamos la jail y le asignamos una IP:

bastille create -T TimeGuard 14.3-RELEASE 192.168.69.18/24 nfe0

Instalamos las herramientas básicas mediante el sistema de templates :

bastille template TimeGuard datadyne.alfaexploit.com/bastille-basicconfiguration

Configuración del balanceador de carga:

En caso de terner un balanceador de carga la mejor manera de cifrar el tráfico es en este mismo balanceador, lo primero será crear la entrada DNS del dominio que vamos a utilizar para el servidor de calendarios, en mi caso:

baikal.alfaexploit.com

Mis certificados anteriores fueron emitidos mediante ACME, tan solo debo añadir un dominio mas:

/root/.acme.sh/acme.sh --issue --standalone --httpport 88 -d alfaexploit.com -d www.alfaexploit.com -d badguys.alfaexploit.com -d mail.alfaexploit.com -d grafana.alfaexploit.com -d redbulltank.alfaexploit.com -d baikal.alfaexploit.com --renew-hook 'cat /root/.acme.sh/alfaexploit.com_ecc/fullchain.cer /root/.acme.sh/alfaexploit.com_ecc/alfaexploit.com.key > /usr/local/etc/haproxy_certs.pem && haproxy -c -f /usr/local/etc/haproxy.conf && service haproxy restart && cp /root/.acme.sh/alfaexploit.com_ecc/fullchain.cer /root/.acme.sh/alfaexploit.com_ecc/alfaexploit.com.key /root/.acme.sh/alfaexploit.com_ecc/ca.cer /usr/local/www/alfaexploit_certs_mail/ && chmod 644 /usr/local/www/alfaexploit_certs_mail/* && service nginx restart' --force

Comprobamos que el certificado tenga los nombres correctos:

openssl x509 -in /usr/local/etc/haproxy_certs.pem -noout -text | egrep -A1 "Subject:|Subject Alternative Name"
DNS:alfaexploit.com, DNS:badguys.alfaexploit.com, DNS:baikal.alfaexploit.com, DNS:grafana.alfaexploit.com, DNS:mail.alfaexploit.com, DNS:redbulltank.alfaexploit.com, DNS:www.alfaexploit.com

Configuramos el HAProxy, atentos al detalle, se envía la información del origen de las conexiones mediante ProxyProtocol (send-proxy-v2):

vi /usr/local/etc/haproxy.conf
backend baikal
    server baikal 192.168.69.18:80 check send-proxy-v2

Reiniciamos el servicio:

service haproxy restart

Instalación de PHP-FPM:

Instalamos PHP8.4 y las extensiones necesarias para que Baikal funcione correctamente:

pkg install -y php84 php84-session php84-pdo php84-pdo_mysql php84-filter php84-xml php84-dom php84-xmlreader php84-xmlwriter

Configuramos el TimeZone:

cp /usr/local/etc/php.ini-production /usr/local/etc/php.ini
vi /usr/local/etc/php.ini
date.timezone = Europe/Madrid

Habilitamos y arrancamos el servicio de PHP-FPM:

sysrc php_fpm_enable=yes
service php_fpm start

Instalación de Nginx:

Instalamos Nginx:

pkg install -y nginx

Configuramos un Vhost para Baikal, atentos al detalle sobre proxyprotocol(proxy_protocol/set_real_ip_from/real_ip_header):

vi /usr/local/etc/nginx/baikal.conf
server {
  listen 80 proxy_protocol;
  server_name  baikal.alfaexploit.com;
    
  set_real_ip_from 192.168.69.19;
  real_ip_header proxy_protocol;

  root  /usr/local/www/baikal/html;
  index index.php;

  rewrite ^/.well-known/caldav /dav.php redirect;
  rewrite ^/.well-known/carddav /dav.php redirect;

  charset utf-8;

  location ~ /(\.ht|Core|Specific|config) {
    deny all;
    return 404;
  }

  location ~ ^(.+\.php)(.*)$ {
    try_files $fastcgi_script_name =404;
    include        fastcgi_params;
    fastcgi_split_path_info  ^(.+\.php)(.*)$;
    fastcgi_pass   127.0.0.1:9000;
    fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
    fastcgi_param  PATH_INFO        $fastcgi_path_info;
  }
}

Incluimos la configuración desde el fichero principal:

vi /usr/local/etc/nginx/nginx.conf
http {
    include       mime.types;
    default_type  application/octet-stream;

    include baikal.conf;
    ....

Comoprobamos que la ejecución de PHP funcione:

mkdir -p /usr/local/www/baikal/html/
echo "<?php phpinfo(); ?>" > /usr/local/www/baikal/html/info.php

Habilitamos y arrancamos el servicio de Nginx:

sysrc nginx_enable=YES
service nginx restart

Accedemos al php y veremos algo similar a esto.
https://baikal.alfaexploit.com/info.php

Borramos el php una vez comprobado:

rm /usr/local/www/baikal/html/info.php

Recargamos la config de Nginx:

service nginx reload

Instalación de MySQL:

Instalamos MySQL:

pkg install -y mysql80-server percona-toolkit

Habilitamos y arrancamos el servicio de MySQL:

sysrc mysql_enable=YES
service mysql-server start

Securizamos la instalación:

mysql_secure_installation

Generamos el fichero de configuración del cliente para no tener que escribir cada vez el password:

vi .my.cnf
[client]
user     = root
password = PASSWORD

Restringimos los permisos del fichero:

chmod 600 .my.cnf

Creamos la base de datos y el usuario de acceso a esta:

mysql
CREATE DATABASE baikal;
CREATE USER baikal@'192.168.69.18' IDENTIFIED WITH mysql_native_password BY 'PASSWORD';
GRANT ALL PRIVILEGES ON baikal.* TO baikal@'192.168.69.18';
FLUSH PRIVILEGES;
exit;

Instalación de Baikal:

Debemos tener en cuenta que Baikal solo está pensado para administrar los calendarios, no para editar eventos en estos por lo tanto no esperemos poder crear ni editar eventos desde la interfaz web.

Instalamos Baikal:

cd /usr/local/www/
rm -rf baikal
wget https://github.com/sabre-io/Baikal/releases/download/0.10.1/baikal-0.10.1.zip
unzip baikal-0.10.1.zip
rm baikal-0.10.1.zip

Configuramos los permisos de los directorios Specific y config:

chown -R www:www baikal/Specific
chown -R www:www baikal/config

Accedemos a la interfaz web de Baikal y realizamos la configuración inicial:
http://baikal.alfaexploit.com

Hacemos login y creamos un usuario:

Editamos el calendario por defecto:


Cliente PC:

Como cliente vamos a utilizar Khal, este se encuentra disponible tanto para Debian como para FreeBSD:

apt install khal vdirsyncer
pkg install -y py311-khal

En mi caso estoy bajo Debian así que la configuración podría ser ligeramente diferente en FreeBSD sobretodo los paths:

mkdir -p ~/.config/vdirsyncer
vi ~/.config/vdirsyncer/config
[general]
status_path = "~/.local/share/vdirsyncer/status/"

[pair baikal]
a = "baikal_local"
b = "baikal_remote"
collections = ["from b"]
conflict_resolution = "b wins"

[storage baikal_local]
type = "filesystem"
path = "~/.local/share/khal/calendars/"
fileext = ".ics"

[storage baikal_remote]
type = "caldav"
url = "https://baikal.alfaexploit.com/dav.php/calendars/kr0m/default/"
username = "kr0m"
password = "PASSWORD"
auth = "digest"

Khal solo es el visualizador y editor de eventos de los calendarios pero el software que se encarga de mantenerlos sincronizados es Vdirsyncer.

Descubrimos el servidor baikal indicado en la configuración:

vdirsyncer discover baikal
Discovering collections for pair baikal
baikal_local:
baikal_remote:
  - "default" ("Default calendar")
warning: No collection "default" found for storage baikal_local.
Should vdirsyncer attempt to create it? [y/N]: y
Saved for baikal: collections = ["default"]

Sincronizamos:

vdirsyncer sync
Syncing baikal/default

Configuramos Khal:

khal configure
What ordering of year, month, date do you want to use?
[0] year-month-day (today: 2025-08-25)
[1] day/month/year (today: 25/08/2025)
[2] month/day/year (today: 08/25/2025)
[3] Custom
Please choose one of the above options: 1
Date format: %d/%m/%Y (today as an example: 25/08/2025)

What timeformat do you want to use?
[0] 24 hour clock (recommended)
[1] 12 hour clock
Please choose one of the above options [0]: 0
Time format: %H:%M (current time as an example: 11:50)

[0] Create a new calendar on this computer
[1] Use a calendar already on this computer (vdir format)
[2] Sync a calendar from the internet (CalDAV format, requires vdirsyncer)
Please choose one of the above options: 1
The following calendars were found:
Found 1 calendars from vdirsyncer
  baikal_local: ~/.local/share/khal/calendars/*
Use these calendars for khal? [Y/n]: Y

Which calendar do you want as a default calendar?
(The default calendar is used when no calendar is specified.)
Configured calendars: default
Please type one of the above options (default) [default]:
Do you want to write the config to ~/.config/khal/config? (Choosing `No` will abort) [Y/n]: Y
Successfully wrote configuration to ~/.config/khal/config

Ahora ya podemos generar eventos en el calendario:

khal new 25/08/2025 12:00 25/08/2025 13:00 "Coders meeting" ":: Arguee about some code issues"

Podemos consultarlos:

khal list
Today, 25/08/2025
12:00-13:00 Coders meeting :: Arguee about some code issues

Si sincronizamos subiremos los cambios al servidor:

vdirsyncer sync
Syncing baikal/default
Copying (uploading) item WU9QARLFCN7O0Q9WPC5KE9TIUQTOBE4O0HJ2 to baikal_remote/default

También podemos utilizar una interfaz desde consola pero que responde a clicks para generar eventos:

ikhal

Para crear un evento nuevo en el día seleccionado presionamos n:

Por CLI podemos consultar también los eventos, por ejemplo desde hoy vista 30 días:

khal list today 30d
Today, 25/08/2025
12:00-13:00 Coders meeting :: Arguee about some code issues
Friday, 29/08/2025
 Test event ⟳ :: Test description

Si sincronizamos veremos que estamos subiendo un item:

vdirsyncer sync
Syncing baikal/default
Copying (uploading) item Q4MFESW0UBYV89RLTW7E5Y2QJ5ILY02VC1ZB to baikal_remote/default

Para no tener que andar sincronizando lo mejor es crontabearlo:

crontab -e
* * * * * vdirsyncer sync

Cliente Android:

Como ocurre en el PC en Android vamos a necesitar también un software que se encargue de sincronizar los calendarios y otro con el que gestionar los eventos.

Como sincronizador utilizaremos DAVx⁵ instalado desde F-Droid .

Seguimos el asistente inicial:

Añadimos una cuenta:

url: https://baikal.alfaexploit.com/dav.php/calendars/kr0m/default/
username: kr0m
password: PASSWORD

Cambiamos los tiempos de sincronización de la cuenta y deshabilitamos la VPN:

Dejamos tanto el Default calendar como el Default Address Book habilitados:

Como gestor de eventos vamos a utilizar Etar desde GooglePlay, le damos permisos:

Cuando creemos un evento debemos asegurarnos de que lo estamos haciendo en el calendario correcto:

Sincronizamos en el PC y listamos los eventos:

vdirsyncer sync
Syncing baikal/default
Copying (uploading) item 180d4f84-3e1b-47cf-8428-470448b9fd74 to baikal_local/default
Deleting item f9ae1b68-9517-4e43-b8ea-ed2329a7d400 from baikal_local/default
khal list today 30d
Today, 25/08/2025
 Test etar :: Test etar
Wednesday, 27/08/2025
 Hhhhh ⏰ :: Hhhhhh
Friday, 29/08/2025
 test ⟳ :: AAA

Integración con AwesomeWM:

Tan solo debemos clonar el repositorio de los widgets que tengo en GitHub:

cd ~/.config/awesome
git clone https://github.com/ARPABoy/kr0mWidgets.git

Y seguir las instrucciones descritas en GitHub.

El resultado final será similar a este:


Troubleshooting:

El primer paso es asegurarse de estar creando el evento en el calendario correcto desde Etar.

Si queremos resetear la configuración en el PC debemos ejecutar los siguientes comandos:

rm -rf ~/.local/share/khal/calendars/*
rm ~/.config/vdirsyncer/config