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.
- Configuración del balanceador de carga.
- Instalación de PHP-FPM.
- Instalación de Nginx.
- Instalación de MySQL.
- Instalación de Baikal.
- Cliente PC.
- Cliente Android.
- Integración con AwesomeWM.
- Troubleshooting.
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