ZincSearch es un motor de búsqueda de texto completo escrito en Go que se distribuye como un único binario. Implementa parte de la API de Elasticsearch (ingesta _bulk y búsquedas con la sintaxis Query DSL), por lo que muchos scripts y clientes existentes funcionan sin cambios, con un consumo de memoria muy inferior. En este tutorial instalarás ZincSearch en Ubuntu 24.04 como servicio systemd, crearás un índice para logs de acceso con un mapping explícito, cargarás datos y harás búsquedas con filtros y agregaciones.
Requisitos previos
Para seguir esta guía necesitas:
- Un servidor con Ubuntu 24.04 LTS de 64 bits (x86_64), por ejemplo un VPS de CubePath.
- Un usuario no root con privilegios
sudo. - Al menos 1 GB de RAM y espacio en disco acorde al volumen de datos que vayas a indexar.
ZincSearch escuchará solo en 127.0.0.1:4080. Accederás a su interfaz web mediante un túnel SSH, así que no hace falta abrir puertos.
Notaesta guía usa ZincSearch 0.4.10, la última versión estable con binarios publicados. El proyecto ha empezado a publicar versiones 1.0.0 en fase beta; revisa la página de versiones antes de instalar en producción.
Paso 1: Descargar e instalar el binario
Descarga el paquete para Linux x86_64 y la lista de sumas de comprobación:
ZINC_VERSION=0.4.10
cd /tmp
wget "https://github.com/zincsearch/zincsearch/releases/download/v${ZINC_VERSION}/zincsearch_${ZINC_VERSION}_linux_x86_64.tar.gz"
wget "https://github.com/zincsearch/zincsearch/releases/download/v${ZINC_VERSION}/checksums.txt"
Verifica el archivo. La opción --ignore-missing omite las entradas de otras plataformas que no has descargado:
sha256sum -c --ignore-missing checksums.txt
zincsearch_0.4.10_linux_x86_64.tar.gz: OK
Extrae el binario e instálalo en /usr/local/bin:
tar xzf "zincsearch_${ZINC_VERSION}_linux_x86_64.tar.gz" zincsearch
sudo install -m 0755 zincsearch /usr/local/bin/zincsearch
Paso 2: Crear el usuario y el directorio de datos
Ejecutarás ZincSearch con un usuario de sistema sin privilegios que solo puede escribir en su directorio de datos:
sudo useradd --system --no-create-home --shell /usr/sbin/nologin zincsearch
sudo install -d -o zincsearch -g zincsearch -m 0750 /var/lib/zincsearch
sudo install -d -m 0755 /etc/zincsearch
Paso 3: Configurar ZincSearch
ZincSearch se configura con variables de entorno. Las guardarás en un archivo que solo pueda leer root y el usuario del servicio, porque contiene la contraseña del administrador:
sudo nano /etc/zincsearch/zincsearch.env
Añade el siguiente contenido. Sustituye your_strong_password por una contraseña robusta, por ejemplo una generada con openssl rand -base64 24:
ZINC_DATA_PATH=/var/lib/zincsearch
ZINC_SERVER_ADDRESS=127.0.0.1
ZINC_SERVER_PORT=4080
ZINC_FIRST_ADMIN_USER=admin
ZINC_FIRST_ADMIN_PASSWORD=your_strong_password
ZINC_TELEMETRY=false
ZINC_SENTRY=false
GIN_MODE=release
Qué hace cada variable:
| Variable | Función |
|---|---|
ZINC_DATA_PATH | Directorio donde se guardan índices y metadatos |
ZINC_SERVER_ADDRESS / ZINC_SERVER_PORT | Dirección y puerto de escucha |
ZINC_FIRST_ADMIN_USER / ZINC_FIRST_ADMIN_PASSWORD | Usuario administrador que se crea en el primer arranque. Son obligatorias la primera vez |
ZINC_TELEMETRY, ZINC_SENTRY | Desactivan el envío de telemetría y de errores a los servidores del proyecto, activos por defecto |
GIN_MODE=release | Quita los mensajes de depuración del framework HTTP |
Restringe los permisos del archivo:
sudo chown root:zincsearch /etc/zincsearch/zincsearch.env
sudo chmod 0640 /etc/zincsearch/zincsearch.env
Paso 4: Crear el servicio systemd
Crea la unidad del servicio:
sudo nano /etc/systemd/system/zincsearch.service
Añade este contenido:
[Unit]
Description=ZincSearch
After=network.target
[Service]
Type=simple
User=zincsearch
Group=zincsearch
EnvironmentFile=/etc/zincsearch/zincsearch.env
WorkingDirectory=/var/lib/zincsearch
ExecStart=/usr/local/bin/zincsearch
Restart=on-failure
RestartSec=5
LimitNOFILE=65536
NoNewPrivileges=true
ProtectSystem=strict
ReadWritePaths=/var/lib/zincsearch
ProtectHome=true
PrivateTmp=true
[Install]
WantedBy=multi-user.target
Recarga systemd e inicia el servicio:
sudo systemctl daemon-reload
sudo systemctl enable --now zincsearch
Comprueba que el servicio está activo y que responde. El endpoint /healthz no requiere autenticación:
sudo systemctl status zincsearch
curl -s http://127.0.0.1:4080/healthz
{"status":"ok"}
Guarda las credenciales en variables de la sesión para no repetirlas en cada comando. Usa la contraseña que pusiste en el archivo de entorno:
export ZINC_URL="http://127.0.0.1:4080"
export ZINC_AUTH="admin:your_strong_password"
Comprueba que la autenticación funciona consultando la lista de índices, que de momento estará vacía:
curl -s -u "$ZINC_AUTH" "$ZINC_URL/api/index"
Importanteuna vez creado el administrador, cambia su contraseña desde la interfaz web y borra la línea
ZINC_FIRST_ADMIN_PASSWORDdel archivo de entorno. Solo se usa en el primer arranque.
Para abrir la interfaz web desde tu equipo, crea un túnel SSH sustituyendo your_user y your_server_ip, y visita http://localhost:4080:
ssh -L 4080:127.0.0.1:4080 your_user@your_server_ip
Paso 5: Crear un índice con mapping
ZincSearch crea los índices de forma automática al recibir el primer documento, pero entonces adivina el tipo de cada campo. Para datos como logs de acceso es mejor definir el mapping. Los tipos disponibles son text (texto analizado para búsqueda), keyword (valor exacto), numeric, boolean, date y geo_point. aggregatable y sortable permiten usar el campo en agregaciones y ordenaciones:
curl -s -u "$ZINC_AUTH" -X POST "$ZINC_URL/api/index" \
-H 'Content-Type: application/json' \
-d '{
"name": "logs-nginx",
"storage_type": "disk",
"mappings": {
"properties": {
"ip_cliente": {"type": "keyword", "index": true, "store": true, "aggregatable": true},
"metodo": {"type": "keyword", "index": true, "store": true, "aggregatable": true},
"ruta": {"type": "text", "index": true, "store": true, "highlightable": true},
"status": {"type": "numeric", "index": true, "store": true, "sortable": true, "aggregatable": true},
"bytes": {"type": "numeric", "index": true, "store": true, "sortable": true, "aggregatable": true},
"user_agent": {"type": "text", "index": true, "store": true}
}
}
}'
{"message":"ok","index":"logs-nginx","storage_type":"disk"}
Paso 6: Cargar documentos con la API _bulk
La ruta /es/_bulk acepta el mismo formato NDJSON que Elasticsearch: una línea de acción seguida de una línea con el documento. El campo @timestamp es especial en ZincSearch: si lo envías en formato RFC 3339 se usa como fecha del documento, y si lo omites se usa la hora de ingesta. Crea un archivo de ejemplo:
nano /tmp/logs.ndjson
{"index": {"_index": "logs-nginx"}}
{"@timestamp": "2026-09-20T10:31:00Z", "ip_cliente": "203.0.113.10", "metodo": "POST", "ruta": "/api/pedidos", "status": 201, "bytes": 456, "user_agent": "curl/8.5.0"}
{"index": {"_index": "logs-nginx"}}
{"@timestamp": "2026-09-20T10:31:05Z", "ip_cliente": "203.0.113.11", "metodo": "GET", "ruta": "/api/usuarios", "status": 401, "bytes": 78, "user_agent": "Mozilla/5.0"}
{"index": {"_index": "logs-nginx"}}
{"@timestamp": "2026-09-20T10:32:00Z", "ip_cliente": "203.0.113.10", "metodo": "GET", "ruta": "/api/productos", "status": 200, "bytes": 2310, "user_agent": "Mozilla/5.0"}
{"index": {"_index": "logs-nginx"}}
{"@timestamp": "2026-09-20T10:33:12Z", "ip_cliente": "203.0.113.12", "metodo": "GET", "ruta": "/api/productos/42", "status": 404, "bytes": 120, "user_agent": "Mozilla/5.0"}
El archivo debe terminar con un salto de línea. Envíalo con --data-binary, que respeta los saltos de línea (-d los eliminaría):
curl -s -u "$ZINC_AUTH" -X POST "$ZINC_URL/es/_bulk" \
-H 'Content-Type: application/x-ndjson' \
--data-binary @/tmp/logs.ndjson
La respuesta sigue el formato de Elasticsearch. Comprueba que el campo errors es false:
{"took":3,"errors":false,"items":[{"index":{"_index":"logs-nginx","_id":"...","_version":1,"result":"created",...
Para añadir un único documento también puedes usar POST /api/logs-nginx/_doc con el JSON en el cuerpo.
Paso 7: Buscar con la sintaxis de Elasticsearch
Los documentos pueden tardar un segundo en ser visibles para la búsqueda. Busca las peticiones a rutas que contengan "productos" con código de estado menor que 400, ordenadas de la más reciente a la más antigua:
curl -s -u "$ZINC_AUTH" -X POST "$ZINC_URL/es/logs-nginx/_search" \
-H 'Content-Type: application/json' \
-d '{
"query": {
"bool": {
"must": [{"match": {"ruta": "productos"}}],
"filter": [{"range": {"status": {"lt": 400}}}]
}
},
"sort": [{"@timestamp": "desc"}],
"size": 10
}'
{"took":1,"timed_out":false,"hits":{"total":{"value":1},"max_score":0.98,"hits":[{"_index":"logs-nginx","_id":"...","_score":0.98,"@timestamp":"2026-09-20T10:32:00Z","_source":{"ip_cliente":"203.0.113.10","metodo":"GET","ruta":"/api/productos","status":200,...
Las agregaciones permiten resumir los datos, por ejemplo para un panel de errores. Esta consulta cuenta las peticiones por método y por código de estado, sin devolver documentos ("size": 0):
curl -s -u "$ZINC_AUTH" -X POST "$ZINC_URL/es/logs-nginx/_search" \
-H 'Content-Type: application/json' \
-d '{
"query": {"match_all": {}},
"aggs": {
"por_metodo": {"terms": {"field": "metodo", "size": 10}},
"por_status": {"terms": {"field": "status", "size": 10}}
},
"size": 0
}'
..."aggregations":{"por_metodo":{"buckets":[{"key":"GET","doc_count":3},{"key":"POST","doc_count":1}]},"por_status":{"buckets":[...]}}}
Solo los campos marcados como aggregatable en el mapping pueden usarse en agregaciones.
Paso 8: Borrar datos antiguos
ZincSearch no tiene políticas de ciclo de vida como el ILM de Elasticsearch. La forma habitual de gestionar la retención de logs es crear un índice por mes (por ejemplo logs-nginx-2026-09) y borrar los antiguos:
curl -s -u "$ZINC_AUTH" -X DELETE "$ZINC_URL/api/index/logs-nginx-2026-06"
Para ver cuánto ocupa cada índice en disco:
sudo du -sh /var/lib/zincsearch/*
Solución de problemas
El servicio no arranca. Revisa el log:
sudo journalctl -u zincsearch -n 50 --no-pager
El mensaje ZINC_FIRST_ADMIN_USER and ZINC_FIRST_ADMIN_PASSWORD must be set on first start indica que falta alguna de esas variables en el primer arranque. Un error de permisos sobre el directorio de datos se corrige con sudo chown -R zincsearch:zincsearch /var/lib/zincsearch.
Respuesta 401 en la API. Las credenciales no son correctas. Recuerda que la contraseña del archivo de entorno solo se aplica en el primer arranque; si la cambiaste desde la interfaz web, usa la nueva.
Una petición que funciona en Elasticsearch falla en ZincSearch. ZincSearch implementa solo una parte de la API: no incluye ILM, snapshots, rollover ni pipelines de ingesta. Si necesitas esas funciones, valora OpenSearch o Elasticsearch.
Conclusión
Tienes ZincSearch funcionando como servicio en Ubuntu 24.04, con un índice definido por ti, datos cargados mediante la API _bulk compatible con Elasticsearch y consultas con filtros y agregaciones. Como siguientes pasos, puedes enviar los logs de Nginx con un agente como Fluent Bit o Vector usando su salida para Elasticsearch apuntando a /es/, crear usuarios con permisos limitados para cada aplicación desde la interfaz web, o publicar ZincSearch detrás de un proxy inverso con HTTPS si otras máquinas necesitan acceder a él.
