Cómo instalar Zulip Chat Server usando Docker en Rocky Linux 9
Zulip es un servidor de chat de código abierto similar a Microsoft Teams, Rocket Chat o Slack. Está escrito en Python y utiliza Django, PostgreSQL y JavaScript. Se integra con más de 90 plugins de terceros, como Github, Jira, Stripe, Zendesk, Sentry, etc. Puedes ampliar las integraciones conectándolas con Zapier e IFTTT. Incluye funciones como mensajería privada, chats de grupo, conversaciones hilvanadas, canales personalizados, videollamadas, carga de archivos mediante arrastrar y soltar, emojis personalizados, integración con Giphy, previsualización de imágenes y tweets, y muchas más. Zulip viene con aplicaciones de escritorio y móviles para todas las plataformas, por lo que es agnóstico en cuanto a plataformas.
Este tutorial te enseña a instalar y configurar Zulip Chat en un servidor Rocky Linux 9.
Requisitos previos
- Un servidor con Rocky Linux 9.
- Al menos 2 GB de RAM si esperas menos de 100 usuarios. Para más de 100 usuarios, consigue un servidor de 4 GB de RAM y 2 CPU.
- Un usuario no root con privilegios sudo.
- Un nombre de dominio configurado para apuntar al servidor,
zulip.example.com
. - Todo actualizado.
$ sudo dnf update
- Pocos paquetes que necesite tu sistema.
$ sudo dnf install wget curl nano unzip yum-utils policycoreutils-python-utils -y
Puede que algunos de estos paquetes ya estén instalados en tu sistema.
Paso 1 – Configurar el cortafuegos
Antes de instalar ningún paquete, el primer paso es configurar el cortafuegos para abrir puertos para HTTP, y HTTPS. Rocky Linux utiliza el cortafuegos Firewalld. Comprueba el estado del cortafuegos.
$ sudo firewall-cmd --state running
El cortafuegos funciona con diferentes zonas, y la zona pública es la que utilizaremos por defecto. Enumera todos los servicios y puertos activos en el cortafuegos.
$ sudo firewall-cmd --zone=public --list-all
Debería mostrar la siguiente salida.
public target: default icmp-block-inversion: no interfaces: enp1s0 sources: services: cockpit dhcpv6-client ssh ports: protocols: forward: yes masquerade: no forward-ports: source-ports: icmp-blocks: rich rules:
Abre los puertos HTTP y HTTPS en el cortafuegos.
$ sudo firewall-cmd --zone=public --add-service=http $ sudo firewall-cmd --zone=public --add-service=https
Vuelve a comprobar el estado del cortafuegos.
$ sudo firewall-cmd --zone=public --list-all
Deberías ver un resultado similar.
public target: default icmp-block-inversion: no interfaces: enp1s0 sources: services: cockpit dhcpv6-client http https ssh ports: protocols: forward: yes masquerade: no forward-ports: source-ports: icmp-blocks: rich rules:
Haz permanentes todos los cambios y vuelve a cargar el cortafuegos para activar los cambios.
$ sudo firewall-cmd --runtime-to-permanent $ sudo firewall-cmd --reload
Paso 2 – Instala Docker y Docker Compose
Instala el repositorio oficial de Docker.
$ sudo dnf install yum-utils $ sudo dnf config-manager \ --add-repo \ https://download.docker.com/linux/centos/docker-ce.repo
Instala Docker.
$ sudo dnf install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
Habilita y ejecuta el demonio Docker.
$ sudo systemctl enable docker --now
Comprueba el estado del servicio Docker.
$ sudo systemctl status docker ? docker.service - Docker Application Container Engine Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; preset: disabled) Active: active (running) since Tue 2024-02-06 07:17:33 UTC; 5s ago TriggeredBy: ? docker.socket Docs: https://docs.docker.com Main PID: 22302 (dockerd) Tasks: 10 Memory: 31.3M CPU: 198ms CGroup: /system.slice/docker.service ??22302 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
Añade tu usuario de sistema al grupo Docker para evitar utilizar sudo
para ejecutar comandos Docker.
$ sudo usermod -aG docker $(whoami)
Vuelve a acceder a tu servidor después de cerrar la sesión para activar el cambio.
Paso 3 – Instalar Nginx
Para el entorno de producción, se recomienda ejecutar el servidor Synapse utilizando un proxy Nginx.
Rocky Linux 9 viene con una versión antigua de Nginx. Necesitas utilizar el repositorio oficial de Nginx para instalar la última versión.
Crea y abre el archivo /etc/yum.repos.d/nginx.repo
para editarlo.
$ sudo nano /etc/yum.repos.d/nginx.repo
Pega en él el siguiente código.
[nginx-stable] name=nginx stable repo baseurl=http://nginx.org/packages/centos/$releasever/$basearch/ gpgcheck=1 enabled=1 gpgkey=https://nginx.org/keys/nginx_signing.key module_hotfixes=true [nginx-mainline] name=nginx mainline repo baseurl=http://nginx.org/packages/mainline/centos/$releasever/$basearch/ gpgcheck=1 enabled=0 gpgkey=https://nginx.org/keys/nginx_signing.key module_hotfixes=true
Cuando hayas terminado, guarda el archivo pulsando Ctrl + X e introduciendo Y cuando se te pida.
Vamos a instalar la versión principal de Nginx, así que habilita el paquete correspondiente.
$ sudo dnf config-manager --enable nginx-mainline
Instala Nginx.
$ sudo dnf install nginx -y
Verifica la instalación.
$ nginx -v nginx version: nginx/1.25.3
Habilita e inicia el servicio del servidor Nginx.
$ sudo systemctl enable nginx --now
Comprueba el estado del servicio.
$ sudo systemctl status nginx ? nginx.service - nginx - high performance web server Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; preset: disabled) Active: active (running) since Tue 2024-02-06 07:18:56 UTC; 5s ago Docs: http://nginx.org/en/docs/ Process: 22762 ExecStart=/usr/sbin/nginx -c /etc/nginx/nginx.conf (code=exited, status=0/SUCCESS) Main PID: 22763 (nginx) Tasks: 5 (limit: 50339) Memory: 4.9M CPU: 16ms CGroup: /system.slice/nginx.service ??22763 "nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf" ??22764 "nginx: worker process" ??22765 "nginx: worker process" ??22766 "nginx: worker process" ??22767 "nginx: worker process"
Paso 4 – Instalar SSL
Necesitamos instalar Certbot para generar el certificado SSL. Para ello utilizaremos el instalador de paquetes Snapd. Como Rocky Linux no lo incluye, instala el instalador Snapd. Necesita el repositorio EPEL (Extra Packages for Enterprise Linux) para funcionar.
Instala el repositorio EPEL.
$ sudo dnf install epel-release -y
Instala el paquete Snapd.
$ sudo dnf install snapd -y
Activa e inicia el servicio Snap.
$ sudo systemctl enable snapd --now
Instala el paquete Snap core, y asegúrate de que tu versión de Snapd está actualizada.
$ sudo snap install core && sudo snap refresh core
Crea los enlaces necesarios para que Snapd funcione.
$ sudo ln -s /var/lib/snapd/snap /snap $ echo 'export PATH=$PATH:/var/lib/snapd/snap/bin' | sudo tee -a /etc/profile.d/snapd.sh
Instala Certbot.
$ sudo snap install --classic certbot
Asegúrate de que se puede ejecutar el comando Certbot creando un enlace simbólico al directorio /usr/bin
.
$ sudo ln -s /snap/bin/certbot /usr/bin/certbot
Comprueba la versión de Certbot.
$ certbot --version certbot 2.8.0
Ejecuta el siguiente comando para generar un certificado SSL.
$ sudo certbot certonly --nginx --agree-tos --no-eff-email --staple-ocsp --preferred-challenges http -m [email protected] -d zulip.example.com
El comando anterior descargará un certificado en el directorio /etc/letsencrypt/live/zulip.example.com
de tu servidor.
Genera un certificado de grupo Diffie-Hellman.
$ sudo openssl dhparam -dsaparam -out /etc/ssl/certs/dhparam.pem 4096
Comprueba el servicio programador de renovación de Certbot.
$ systemctl list-timers
Encontrarás snap.certbot.renew.service
como uno de los servicios programados para ejecutarse.
NEXT LEFT LAST PASSED UNIT ACTIVATES ---------------------------------------------------------------------------------------------------------------------------------- Tue 2024-02-06 07:30:00 UTC 6min left Tue 2024-02-06 07:20:11 UTC 3min 41s ago sysstat-collect.timer sysstat-collect.service Tue 2024-02-06 08:22:43 UTC 58min left Tue 2024-02-06 07:22:39 UTC 1min 13s ago dnf-makecache.timer dnf-makecache.service Tue 2024-02-06 09:36:00 UTC 2h 12min left - - snap.certbot.renew.timer snap.certbot.renew.service
Realiza una ejecución en seco del proceso para comprobar si la renovación SSL funciona correctamente.
$ sudo certbot renew --dry-run
Si no ves ningún error, ya está todo listo. Tu certificado se renovará automáticamente.
Paso 5 – Configurar SELinux
Aplica la política para permitir conexiones a hosts externos.
$ sudo setsebool -P httpd_can_network_connect 1
Aplica la política para permitir que Nginx dé acceso a PostgreSQL.
$ sudo setsebool -P httpd_can_network_connect_db 1
Paso 6 – Preparar y configurar Zulip para la instalación
En primer lugar, crea una clave secreta para Zulip. Guarda la clave generada porque la necesitaremos más adelante.
$ openssl rand -base64 32 sLIeucGPMCNbR0LwcRhyXafXmputmtse6+EYU04+9JY=
Crea un directorio para el archivo Zulip Docker Compose y pasa a él.
$ mkdir ~/docker-zulip $ cd ~/docker-zulip
Crea y abre el archivo de entorno para editarlo.
$ nano .env
Pega en él el siguiente código.
[email protected] EXTERNAL_HOST=zulip.example.com ZULIP_AUTH_BACKENDS=EmailAuthBackend ZULIP_PUSH_NOTIFICATION_BOUNCER_URL=https://push.zulipchat.com DISABLE_HTTPS=true SSL_CERTIFICATE_GENERATION=self-signed EMAIL_HOST=email-smtp.us-west-2.amazonaws.com EMAIL_HOST_USER=AMAZONSESUSERNAME EMAIL_PASSWORD=AMAZONSESPASSWORD EMAIL_PORT=465 EMAIL_USE_SSL=True EMAIL_USE_TLS=False [email protected] ZULIP_GIT_URL=https://github.com/zulip/zulip.git ZULIP_GIT_REF=8.2 SECRET_KEY=sLIeucGPMCNbR0LwcRhyXafXmputmtse6+EYU04+9JY= POSTGRES_USER=zulip POSTGRES_DB=zulip POSTGRES_PASSWORD=REPLACE_WITH_SECURE_POSTGRES_PASSWORD REDIS_PASSWORD=REPLACE_WITH_SECURE_REDIS_PASSWORD MEMCACHED_PASSWORD=REPLACE_WITH_SECURE_MEMCACHED_PASSWORD RABBITMQ_DEFAULT_USER=zulip RABBITMQ_DEFAULT_PASS=REPLACE_WITH_SECURE_RABBITMQ_PASSWORD
Guarda el archivo pulsando Ctrl + X e introduciendo Y cuando se te pida una vez hayas terminado.
Repasemos todas las variables que hemos definido.
- ZULIP_ADMINISTRATOR – es la dirección de correo electrónico principal de la cuenta de administrador creada durante la instalación.
- EXTERNAL_HOST – es el nombre de dominio que utilizaremos para nuestra instalación de Zulip.
- ZULIP_AUTH_BACKENDS – define el método para iniciar sesión. Nosotros utilizamos
EmailAuthBackend
, lo que significa que Zulip te pedirá una dirección de correo electrónico y una contraseña. Existen otros métodos de autenticación que utilizan credenciales de Google, GitHub y Apple para iniciar sesión. Puedes encontrar más información en la documentación de Zulip y en el archivo por defectosettings.py
por defecto. - ZULIP_PUSH_NOTIFICATION_BOUNCER_URL – es la URL que Zulip utilizará para enviar notificaciones push móviles. Para la versión comunitaria de Zulip para una organización con 10 o menos usuarios, las notificaciones push son gratuitas. Tu organización aún puede optar a notificaciones push ilimitadas gratuitas en función de los requisitos. Consulta la documentación de facturación de Z ulip para más detalles.
- DISABLE_HTTPS – Lo hemos puesto a true para desactivar SSL para Zulip porque lo gestionaremos fuera del contenedor.
- SSL_CERTIFICATE_GENERATION – Como hemos deshabilitado SSL para Zulip, necesitamos configurarlo para generar certificados autofirmados.
- EMAIL_HOST – El host de correo SMTP que necesitamos para activar las notificaciones por correo electrónico. Aquí estamos utilizando el servicio de correo electrónico Amazon SES para nuestro tutorial.
- EMAIL_HOST_USER – El nombre de usuario del correo SMTP.
- EMAIL_PASSWORD – La contraseña del correo electrónico SMTP.
- EMAIL_PORT – El puerto de correo SMTP.
- EMAIL_USE_SSL – Si el host SMTP admite autenticación SSL.
- EMAIL_USE_TLS – Si el host SMTP admite autenticación TLS.
- EMAIL_NOREPLY_ADD – La dirección de correo electrónico sin respuesta utilizada para enviar correos electrónicos de notificación.
- ZULIP_GIT_URL – Estamos utilizando la imagen docker de Zulip, pero si quieres crear una imagen personalizada, debes introducir la URL del repositorio Git de Zulip.
- ZULIP_GIT_REF – La versión de Zulip a utilizar del repositorio Git para construir la imagen docker.
- SECRET_KEY – Una clave secreta fuerte que Zulip necesita para la autenticación. Introduce la clave que hemos creado antes.
- POSTGRES_USER – Elige un nombre de usuario para tu usuario PostgreSQL.
- POSTGRES_DB – Elige el nombre de la base de datos para tu base de datos PostgreSQL.
- POSTGRES_PASSWORD – Elige una contraseña segura para la base de datos PostgreSQL.
- REDIS_PASSWORD – Elige una contraseña segura para la base de datos Redis.
- MEMCACHED_PASSWORD – Elige una contraseña segura para el servicio Memcached.
- RABBITMQ_DEFAULT_USER – Elige un nombre de usuario para el servicio RabbitMQ.
- RABBITMQ_DEFAULT_PASS – Elige una contraseña segura para el servicio RabbitMQ.
Crea y abre el archivo Docker compose para editarlo.
$ nano docker-compose.yml
Añade el siguiente código para definir el servicio database
.
services: database: image: "zulip/zulip-postgresql:14" container_name: zulip-db restart: unless-stopped environment: POSTGRES_DB: ${POSTGRES_DB} POSTGRES_USER: ${POSTGRES_USER} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} volumes: - "postgresql-14:/var/lib/postgresql/data:rw" networks: network: ipv4_address: 10.5.0.2
El servicio database
contiene las siguientes opciones:
- image – Indica a Docker que extraiga la imagen
zulip-postgresql:14
. Aunque la última versión de Zulip admite PostgreSQL 16, la imagen docker correspondiente sólo admite PostgreSQL 14. - nombre_contenedor – especifica un nombre para el contenedor.
- reinicio – define la política de reinicio del contenedor. Hemos configurado el contenedor para que se reinicie automáticamente a menos que se detenga manualmente.
- environment – Debes establecer variables de entorno para el contenedor. Hemos establecido tres variables que definen la base de datos PostgreSQL, el nombre de usuario y la contraseña.
- volúmenes – Aquí creamos un volumen con nombre llamado
postgresql-14
que apunta al directorio de datos PostgreSQL en el contenedor. - redes – utilizamos esto para dar al contenedor una dirección IP estática que pueda utilizarse para acceder a él desde otros contenedores.
A continuación, debajo de la sección del servicio database
, añade la definición del servicio memcached
.
memcached: image: "memcached:alpine" restart: unless-stopped container_name: zulip-memcached command: - "sh" - "-euc" - | echo 'mech_list: plain' > "$$SASL_CONF_PATH" echo "zulip@$$HOSTNAME:$$MEMCACHED_PASSWORD" > "$$MEMCACHED_SASL_PWDB" echo "zulip@localhost:$$MEMCACHED_PASSWORD" >> "$$MEMCACHED_SASL_PWDB" exec memcached -S environment: SASL_CONF_PATH: "/home/memcache/memcached.conf" MEMCACHED_SASL_PWDB: "/home/memcache/memcached-sasl-db" MEMCACHED_PASSWORD: ${MEMCACHED_PASSWORD} networks: network: ipv4_address: 10.5.0.3
El servicio memcached
contiene las siguientes definiciones específicas para él:
- imagen – Aquí utilizaremos la imagen
memcached:alpine
para el contenedor. Una imagen alpina reduce el tamaño de la imagen, ya que sólo incluye lo esencial. - comando – Aquí ejecutaremos algunos comandos que se ejecutan tras la creación del contenedor para configurar Memcached y establecer las credenciales de Zulip. Estos comandos también anulan los comandos por defecto declarados por la imagen.
- entorno – Aquí establecemos la ubicación del archivo de configuración de Memcached, el archivo de la base de datos de contraseñas y la contraseña.
- red – Aquí establecemos una dirección IP privada única para el contenedor docker.
A continuación, añade la definición del servicio rabbitmq
debajo de la sección memcached
.
rabbitmq: image: "rabbitmq:alpine" restart: unless-stopped container_name: zulip-rabbitmq environment: RABBITMQ_DEFAULT_USER: ${RABBITMQ_DEFAULT_USER} RABBITMQ_DEFAULT_PASS: ${RABBITMQ_DEFAULT_PASS} volumes: - "rabbitmq:/var/lib/rabbitmq:rw" networks: network: ipv4_address: 10.5.0.4
El servicio rabbitmq
contiene las siguientes definiciones específicas para él:
- image – Al igual que antes, utilizaremos la imagen alpine para el contenedor RabbitMQ.
- entorno – Usamos la sección entorno para establecer el nombre de usuario y la contraseña por defecto de RabbitMQ.
- volúmenes – Aquí creamos un volumen con nombre llamado
rabbitmq
que apunta al directorio RabbitMQ en el contenedor. - red – Igual que antes, establecemos una dirección IP única para el contenedor.
A continuación, añade la definición del servicio redis
debajo de la sección rabbitmq
.
redis: image: "redis:alpine" restart: unless-stopped container_name: zulip-redis command: - "sh" - "-euc" - | echo "requirepass '$$REDIS_PASSWORD'" > /etc/redis.conf exec redis-server /etc/redis.conf environment: REDIS_PASSWORD: ${REDIS_PASSWORD} volumes: - "redis:/data:rw" networks: network: ipv4_address: 10.5.0.5
El servicio redis
contiene las siguientes definiciones específicas para él:
- imagen – Aquí utilizaremos la imagen alpina para el contenedor Redis.
- comando – Utilizaremos los comandos para configurar la contraseña de Redis e iniciar el servidor con ella.
- volúmenes – Aquí creamos un volumen con nombre llamado
redis
que apunta al directorio de datos del contenedor. - red – Igual que antes, establecemos una dirección IP única para el contenedor Redis.
Por último, añade la definición del servicio zulip
debajo de la sección redis
.
zulip: image: "zulip/docker-zulip:8.2-0" restart: unless-stopped container_name: zulip ports: - "8080:80" environment: DB_HOST: "database" DB_HOST_PORT: "5432" DB_USER: ${POSTGRES_USER} DISABLE_HTTPS: ${DISABLE_HTTPS} SSL_CERTIFICATE_GENERATION: ${SSL_CERTIFICATE_GENERATION} LOADBALANCER_IPS: 10.5.0.0/16 SETTING_MEMCACHED_LOCATION: "memcached:11211" SETTING_RABBITMQ_HOST: "rabbitmq" SETTING_REDIS_HOST: "redis" SECRETS_email_password: ${EMAIL_PASSWORD} SECRETS_rabbitmq_password: ${RABBITMQ_DEFAULT_PASS} SECRETS_postgres_password: ${POSTGRES_PASSWORD} SECRETS_memcached_password: ${MEMCACHED_PASSWORD} SECRETS_redis_password: ${REDIS_PASSWORD} SECRETS_secret_key: ${SECRET_KEY} SETTING_EXTERNAL_HOST: ${EXTERNAL_HOST} SETTING_ZULIP_ADMINISTRATOR: ${ZULIP_ADMINISTRATOR} SETTING_EMAIL_HOST: ${EMAIL_HOST} SETTING_EMAIL_HOST_USER: ${EMAIL_HOST_USER} SETTING_EMAIL_PORT: ${EMAIL_PORT} SETTING_EMAIL_USE_SSL: ${EMAIL_USE_SSL} SETTING_EMAIL_USE_TLS: ${EMAIL_USE_TLS} ZULIP_AUTH_BACKENDS: ${ZULIP_AUTH_BACKENDS} SETTING_NOREPLY_EMAIL_ADDRESS: ${EMAIL_NOREPLY_ADD} # Uncomment this when configuring the mobile push notifications service # SETTING_PUSH_NOTIFICATION_BOUNCER_URL: ${ZULIP_PUSH_NOTIFICATION_BOUNCER_URL} volumes: - "zulip:/data:rw" ulimits: nofile: soft: 1000000 hard: 1048576 networks: network: ipv4_address: 10.5.0.6
El servicio zulip
contiene las siguientes definiciones específicas para él:
- puertos – El contenedor Zulip ejecuta nginx como parte del proceso. Aquí hemos asignado el puerto 80 del contenedor al puerto 8080 del servidor anfitrión. Lo utilizaremos más adelante para configurar Nginx como gestor proxy fuera del contenedor.
- entorno – Aquí configuramos variables de entorno para configurar Zulip. La mayoría de las variables de entorno se recogen del archivo
.env
que hemos explicado antes. El host de la base de datos se establece en el servicio de contenedordatabase
y el puerto en el puerto predeterminado PostgreSQL 5432. La variableLOADBALANCER_IPS
se establece en la subred de red de Docker. Esto es necesario para que Zulip funcione desde detrás de un servidor proxy inverso. La variableMEMCACHED_LOCATION
se establece en el serviciomemcached
con su puerto por defecto 11211. Del mismo modo, hemos configurado los hosts RabbitMQ y Redis para que apunten a sus respectivos servicios de contenedor. - volúmenes – Aquí establecemos un volumen con nombre y lo fijamos en el directorio
/data
en modo lectura-escritura. - ulimits – Aquí establecemos los límites blandos y duros para el uso de recursos del usuario para el contenedor.
- networks – Igual que antes, establecemos una dirección IP única para el contenedor Zulip.
Y por último, pega el siguiente código.
volumes: zulip: postgresql-14: rabbitmq: redis: networks: network: driver: bridge ipam: config: - subnet: 10.5.0.0/16 gateway: 10.5.0.1
Aquí definimos los volúmenes con nombre que creamos anteriormente para nuestros contenedores. A continuación, definimos la red puente para conectar todos los contenedores y proporcionamos las direcciones IP de subred y puerta de enlace.
Una vez terminado, guarda el archivo pulsando Ctrl + X e introduciendo Y cuando se te pida una vez terminado.
El archivo Docker compose terminado tendrá el siguiente aspecto.
services: database: image: "zulip/zulip-postgresql:14" restart: unless-stopped environment: POSTGRES_DB: ${POSTGRES_DB} POSTGRES_USER: ${POSTGRES_USER} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} volumes: - "postgresql-14:/var/lib/postgresql/data:rw" networks: network: ipv4_address: 10.5.0.2 memcached: image: "memcached:alpine" restart: unless-stopped command: - "sh" - "-euc" - | echo 'mech_list: plain' > "$$SASL_CONF_PATH" echo "zulip@$$HOSTNAME:$$MEMCACHED_PASSWORD" > "$$MEMCACHED_SASL_PWDB" echo "zulip@localhost:$$MEMCACHED_PASSWORD" >> "$$MEMCACHED_SASL_PWDB" exec memcached -S environment: SASL_CONF_PATH: "/home/memcache/memcached.conf" MEMCACHED_SASL_PWDB: "/home/memcache/memcached-sasl-db" MEMCACHED_PASSWORD: ${MEMCACHED_PASSWORD} networks: network: ipv4_address: 10.5.0.3 rabbitmq: image: "rabbitmq:alpine" restart: unless-stopped environment: RABBITMQ_DEFAULT_USER: ${RABBITMQ_DEFAULT_USER} RABBITMQ_DEFAULT_PASS: ${RABBITMQ_DEFAULT_PASS} volumes: - "rabbitmq:/var/lib/rabbitmq:rw" networks: network: ipv4_address: 10.5.0.4 redis: image: "redis:alpine" restart: unless-stopped command: - "sh" - "-euc" - | echo "requirepass '$$REDIS_PASSWORD'" > /etc/redis.conf exec redis-server /etc/redis.conf environment: REDIS_PASSWORD: ${REDIS_PASSWORD} volumes: - "redis:/data:rw" networks: network: ipv4_address: 10.5.0.5 zulip: image: "zulip/docker-zulip:8.1-0" restart: unless-stopped #build: # context: . # args: # ZULIP_GIT_URL: ${ZULIP_GIT_URL} # ZULIP_GIT_REF: ${ZULIP_GIT_REF} # Set this up if you plan to use your own CA certificate bundle for building # CUSTOM_CA_CERTIFICATES: ${ZULIP_CUSTOM_CA_CERTIFICATES} ports: - "8080:80" environment: DB_HOST: 10.5.0.2 DB_HOST_PORT: "5432" DB_USER: ${POSTGRES_USER} DISABLE_HTTPS: ${DISABLE_HTTPS} LOADBALANCER_IPS: 10.5.0.6 SSL_CERTIFICATE_GENERATION: ${SSL_CERTIFICATE_GENERATION} SETTING_MEMCACHED_LOCATION: "memcached:11211" SETTING_RABBITMQ_HOST: "rabbitmq" SETTING_REDIS_HOST: "redis" SECRETS_email_password: ${EMAIL_PASSWORD} SECRETS_rabbitmq_password: ${RABBITMQ_DEFAULT_PASS} SECRETS_postgres_password: ${POSTGRES_PASSWORD} SECRETS_memcached_password: ${MEMCACHED_PASSWORD} SECRETS_redis_password: ${REDIS_PASSWORD} SECRETS_secret_key: ${SECRET_KEY} SETTING_EXTERNAL_HOST: ${EXTERNAL_HOST} SETTING_ZULIP_ADMINISTRATOR: ${ZULIP_ADMINISTRATOR} SETTING_EMAIL_HOST: ${EMAIL_HOST} SETTING_EMAIL_HOST_USER: ${EMAIL_HOST_USER} SETTING_EMAIL_PORT: ${EMAIL_PORT} SETTING_EMAIL_USE_SSL: ${EMAIL_USE_SSL} SETTING_EMAIL_USE_TLS: ${EMAIL_USE_TLS} ZULIP_AUTH_BACKENDS: ${ZULIP_AUTH_BACKENDS} SETTING_NOREPLY_EMAIL_ADDRESS: ${EMAIL_NOREPLY_ADD} # Uncomment this when configuring the mobile push notifications service # SETTING_PUSH_NOTIFICATION_BOUNCER_URL: ${ZULIP_PUSH_NOTIFICATION_BOUNCER_URL} volumes: - "zulip:/data:rw" ulimits: nofile: soft: 1000000 hard: 1048576 networks: network: ipv4_address: 10.5.0.6 volumes: zulip: postgresql-14: rabbitmq: redis: networks: network: driver: bridge ipam: config: - subnet: 10.5.0.0/16 gateway: 10.5.0.1
Paso 7 – Instalar Zulip
Inicia el contenedor Zulip utilizando el siguiente comando.
$ docker compose up -d
Comprueba el estado de los contenedores utilizando los siguientes comandos.
$ docker ps
Deberías ver una salida similar.
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES fea5d02f53d7 rabbitmq:alpine "docker-entrypoint.s…" 2 minutes ago Up 2 minutes 4369/tcp, 5671-5672/tcp, 15691-15692/tcp, 25672/tcp zulip-rabbitmq 01cb77f16c1a zulip/zulip-postgresql:14 "docker-entrypoint.s…" 2 minutes ago Up 2 minutes 5432/tcp zulip-db f5b6523a3a8c zulip/docker-zulip:8.2-0 "/sbin/entrypoint.sh…" 2 minutes ago Up 2 minutes 443/tcp, 0.0.0.0:8080->80/tcp, :::8080->80/tcp zulip c0a358209b09 redis:alpine "docker-entrypoint.s…" 2 minutes ago Up 2 minutes 6379/tcp zulip-redis 27be352a0a35 memcached:alpine "docker-entrypoint.s…" 2 minutes ago Up 2 minutes 11211/tcp zulip-memcached
También puedes utilizar el siguiente comando para lo mismo.
$ docker compose ps
En este caso, tu salida sería como la siguiente.
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS zulip zulip/docker-zulip:8.2-0 "/sbin/entrypoint.sh…" zulip About a minute ago Up About a minute 443/tcp, 0.0.0.0:8080->80/tcp, :::8080->80/tcp zulip-db zulip/zulip-postgresql:14 "docker-entrypoint.s…" database About a minute ago Up About a minute 5432/tcp zulip-memcached memcached:alpine "docker-entrypoint.s…" memcached About a minute ago Up About a minute 11211/tcp zulip-rabbitmq rabbitmq:alpine "docker-entrypoint.s…" rabbitmq About a minute ago Up About a minute 4369/tcp, 5671-5672/tcp, 15691-15692/tcp, 25672/tcp zulip-redis redis:alpine "docker-entrypoint.s…" redis About a minute ago Up About a minute 6379/tcp
El contenedor Zulip tardará algún tiempo en empezar a funcionar. Puedes seguir el progreso utilizando el siguiente comando.
$ docker logs zulip --follow
Verás una larga lista de comandos que se ejecutan para configurar el contenedor. Una vez que veas la siguiente salida, significa que Zulip está instalado.
2024-02-21 09:02:55,310 INFO success: go-camo entered RUNNING state, process has stayed up for > than 1 seconds (startsecs) 2024-02-21 09:02:55,311 INFO success: smokescreen entered RUNNING state, process has stayed up for > than 1 seconds (startsecs) 2024-02-21 09:02:55,311 INFO success: zulip-django entered RUNNING state, process has stayed up for > than 1 seconds (startsecs) 2024-02-21 09:02:55,311 INFO success: zulip-tornado entered RUNNING state, process has stayed up for > than 1 seconds (startsecs) 2024-02-21 09:02:55,311 INFO success: zulip_deliver_scheduled_emails entered RUNNING state, process has stayed up for > than 1 seconds (startsecs) 2024-02-21 09:02:55,311 INFO success: zulip_deliver_scheduled_messages entered RUNNING state, process has stayed up for > than 1 seconds (startsecs) 2024-02-21 09:02:55,311 INFO success: process-fts-updates entered RUNNING state, process has stayed up for > than 1 seconds (startsecs) 2024-02-21 09:02:55,311 INFO success: cron entered RUNNING state, process has stayed up for > than 1 seconds (startsecs) 2024-02-21 09:02:55,311 INFO success: nginx entered RUNNING state, process has stayed up for > than 1 seconds (startsecs) 2024-02-21 09:02:55,311 INFO success: zulip_events_deferred_work entered RUNNING state, process has stayed up for > than 1 seconds (startsecs) 2024-02-21 09:02:55,311 INFO success: zulip_events_digest_emails entered RUNNING state, process has stayed up for > than 1 seconds (startsecs) 2024-02-21 09:02:55,311 INFO success: zulip_events_email_mirror entered RUNNING state, process has stayed up for > than 1 seconds (startsecs) 2024-02-21 09:02:55,312 INFO success: zulip_events_embed_links entered RUNNING state, process has stayed up for > than 1 seconds (startsecs) 2024-02-21 09:02:55,312 INFO success: zulip_events_embedded_bots entered RUNNING state, process has stayed up for > than 1 seconds (startsecs) 2024-02-21 09:02:55,312 INFO success: zulip_events_invites entered RUNNING state, process has stayed up for > than 1 seconds (startsecs) 2024-02-21 09:02:55,312 INFO success: zulip_events_email_senders entered RUNNING state, process has stayed up for > than 1 seconds (startsecs) 2024-02-21 09:02:55,312 INFO success: zulip_events_missedmessage_emails entered RUNNING state, process has stayed up for > than 1 seconds (startsecs) 2024-02-21 09:02:55,312 INFO success: zulip_events_missedmessage_mobile_notifications entered RUNNING state, process has stayed up for > than 1 seconds (startsecs) 2024-02-21 09:02:55,312 INFO success: zulip_events_outgoing_webhooks entered RUNNING state, process has stayed up for > than 1 seconds (startsecs) 2024-02-21 09:02:55,312 INFO success: zulip_events_user_activity entered RUNNING state, process has stayed up for > than 1 seconds (startsecs) 2024-02-21 09:02:55,312 INFO success: zulip_events_user_activity_interval entered RUNNING state, process has stayed up for > than 1 seconds (startsecs) 2024-02-21 09:02:55,312 INFO success: zulip_events_user_presence entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
Pulsa Ctrl + C para salir de la pantalla. Zulip está instalado. Sin embargo, aún tenemos que configurar Nginx para que sirva a Zulip.
Paso 8 – Configurar Nginx
Abre el archivo /etc/nginx/nginx.conf
para editarlo.
$ sudo nano /etc/nginx/nginx.conf
Añade la siguiente línea antes de la línea include /etc/nginx/conf.d/*.conf;
.
server_names_hash_bucket_size 64;
Guarda el archivo pulsando Ctrl + X e introduciendo Y cuando se te solicite.
Crea y abre el archivo /etc/nginx/conf.d/zulip.conf
para editarlo.
$ sudo nano /etc/nginx/conf.d/zulip.conf
Pega en él el siguiente código.
server { listen 80; listen [::]:80; location / { return 301 https://$host$request_uri; } } server { listen 443 ssl; listen [::]:443 ssl; http2 on; server_name zulip.example.com; ssl_certificate /etc/letsencrypt/live/zulip.example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/zulip.example.com/privkey.pem; ssl_trusted_certificate /etc/letsencrypt/live/zulip.example.com/chain.pem; ssl_session_timeout 1d; ssl_session_cache shared:MozSSL:10m; ssl_session_tickets off; ssl_prefer_server_ciphers on; ssl_stapling on; ssl_stapling_verify on; ssl_dhparam /etc/ssl/certs/dhparam.pem; resolver 1.1.1.1 1.0.0.1 [2606:4700:4700::1111] [2606:4700:4700::1001] 8.8.8.8 8.8.4.4 [2001:4860:4860::8888] [2001:4860:4860::8844] valid=60s; resolver_timeout 2s; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384; tcp_nopush on; gzip on; location / { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header Host $host; proxy_http_version 1.1; proxy_buffering off; proxy_read_timeout 20m; proxy_pass http://127.0.0.1:8080; } }
Guarda el archivo pulsando Ctrl + X e introduciendo Y cuando se te solicite una vez hayas terminado.
Comprueba la sintaxis del archivo de configuración de Nginx.
$ sudo nginx -t nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful
Reinicia el servicio Nginx.
$ sudo systemctl restart nginx
Paso 9 – Acceder a la interfaz de Zulip
Visita https://zulip.example.com/
en tu navegador, y aparecerá la siguiente pantalla.
Utilizando el enlace Nueva Organización de la parte superior accederás a la siguiente página.
Como puedes ver, Zulip no te permite crear una organización desde el front-end. Vuelve al terminal y ejecuta el siguiente comando para crear la URL de la página de la nueva organización. Hablaremos más sobre cómo utilizar los comandos de Zulip en la siguiente sección.
$ docker compose exec -u zulip zulip /home/zulip/deployments/current/manage.py generate_realm_creation_link Please visit the following secure single-use link to register your new Zulip organization: https://zulip.example.com/new/svvss33z4qmwewmanbbcalen
Abre la URL https://zulip.example.com/new/cjjivovgcillw44z7gsnobkv
en tu navegador y accederás a la siguiente página.
Introduce el nombre de tu organización, el tipo de organización, el idioma y el ID de correo electrónico para empezar a crear tu organización. Haz clic en el botón Crear organización para continuar.
En la siguiente pantalla se te pedirá que configures una cuenta.
Introduce tu nombre, elige una contraseña para iniciar sesión y haz clic en el botón Registrarse para continuar.
Una vez terminado, se abrirá el panel de control de Zulip y podrás empezar a utilizarlo.
Paso 10 – Comandos del Servidor Zulip
De vez en cuando, para ejecutar comandos de Zulip Server, necesitarás acceder al shell del contenedor. Para acceder al shell como usuario zulip
, utiliza el siguiente comando.
$ docker compose exec -u zulip zulip bash
O puedes utilizar el siguiente comando.
$ docker exec -itu zulip zulip bash
Para ejecutar un comando dentro de un contenedor, puedes ejecutarlo utilizando un único comando, como se indica a continuación.
$ docker compose exec -u zulip zulip \ /home/zulip/deployments/current/manage.py help <subcommand>
Sin embargo, hay un método más sencillo de hacerlo. Podemos crear un script de shell para ejecutar comandos. Crea y abre zulip_manage.sh
para editarlo.
$ nano zulip_manage.sh
Pega en él el siguiente código.
#!/bin/sh docker compose exec -u zulip zulip /home/zulip/deployments/current/manage.py "$@"
Guarda el archivo pulsando Ctrl + X e introduciendo Y cuando se te pida.
Haz que el script sea ejecutable.
$ chmod +x zulip_manage.sh
Para detener el servidor Zulip, utiliza el siguiente comando.
$ docker exec -u zulip zulip /home/zulip/deployments/current/scripts/stop-server process-fts-updates: stopped zulip-django: stopped zulip-tornado: stopped zulip-workers:zulip_events_deferred_work: stopped zulip-workers:zulip_events_digest_emails: stopped zulip-workers:zulip_events_email_mirror: stopped zulip-workers:zulip_events_email_senders: stopped zulip-workers:zulip_events_embed_links: stopped zulip-workers:zulip_events_embedded_bots: stopped zulip-workers:zulip_events_invites: stopped zulip-workers:zulip_events_missedmessage_emails: stopped zulip-workers:zulip_events_missedmessage_mobile_notifications: stopped zulip-workers:zulip_events_outgoing_webhooks: stopped zulip-workers:zulip_events_user_activity: stopped zulip-workers:zulip_events_user_activity_interval: stopped zulip-workers:zulip_events_user_presence: stopped zulip_deliver_scheduled_emails: stopped zulip_deliver_scheduled_messages: stopped Zulip stopped successfully!
Para volver a iniciar el servidor, utiliza el siguiente comando.
$ docker exec -u zulip zulip /home/zulip/deployments/current/scripts/start-server 2024-02-21 09:18:52,932 start-server: Running syntax and database checks System check identified no issues (28 silenced). 2024-02-21 09:18:54,944 start-server: Starting Tornado process zulip-tornado: started 2024-02-21 09:18:56,089 start-server: Starting django server zulip-django: started 2024-02-21 09:18:58,133 start-server: Starting workers process-fts-updates: started zulip-workers:zulip_events_deferred_work: started zulip-workers:zulip_events_digest_emails: started zulip-workers:zulip_events_email_mirror: started zulip-workers:zulip_events_email_senders: started zulip-workers:zulip_events_embed_links: started zulip-workers:zulip_events_embedded_bots: started zulip-workers:zulip_events_invites: started zulip-workers:zulip_events_missedmessage_emails: started zulip-workers:zulip_events_missedmessage_mobile_notifications: started zulip-workers:zulip_events_outgoing_webhooks: started zulip-workers:zulip_events_user_activity: started zulip-workers:zulip_events_user_activity_interval: started zulip-workers:zulip_events_user_presence: started zulip_deliver_scheduled_emails: started zulip_deliver_scheduled_messages: started 2024-02-21 09:19:19,571 start-server: Done! Zulip started successfully!
Reinicia el servidor de forma similar.
$ docker exec -u zulip zulip /home/zulip/deployments/current/scripts/restart-server
Hay muchas tareas de gestión que puedes realizar utilizando el script manage.py
incluido con Zulip.
Puedes ejecutar el script utilizando el siguiente comando. Utilizaremos el subcomando help
para enumerar todas las operaciones posibles que se pueden realizar.
$ ./zulip_manage.sh help Type 'manage.py help <subcommand>' for help on a specific subcommand. Available subcommands: [analytics] check_analytics_state clear_analytics_tables clear_single_stat populate_analytics_db update_analytics_counts [django] dbshell makemigrations migrate shell showmigrations [zerver] add_users_to_streams archive_messages audit_fts_indexes backup bulk_change_user_name change_password change_realm_subdomain change_user_email change_user_role check_redis checkconfig compilemessages convert_gitter_data convert_mattermost_data convert_rocketchat_data convert_slack_data create_default_stream_groups create_realm create_realm_internal_bots create_stream create_user deactivate_realm deactivate_user delete_old_unclaimed_attachments delete_realm delete_user deliver_scheduled_emails deliver_scheduled_messages edit_linkifiers email_mirror enqueue_digest_emails enqueue_file export export_search export_single_user export_usermessage_batch fetch_tor_exit_nodes fill_memcached_caches generate_realm_creation_link get_migration_status import list_realms logout_all_users makemessages merge_streams process_queue promote_new_full_members purge_queue query_ldap rate_limit reactivate_realm realm_domain register_server remove_users_from_stream reset_authentication_attempt_count restore_messages runtornado scrub_realm send_custom_email send_password_reset_email send_realm_reactivation_email send_test_email send_to_email_mirror send_webhook_fixture_message send_welcome_bot_message show_admins soft_deactivate_users sync_ldap_user_data transfer_uploads_to_s3 unarchive_stream
El archivo entrypoint.sh de Docker también proporciona algunas otras opciones. Ejecuta el siguiente comando para verlas.
$ docker exec -it zulip bash /sbin/entrypoint.sh app:help
Deberías ver el siguiente resultado.
Available commands: > app:help - Show this help menu and exit > app:version - Container Zulip server version > app:managepy - Run Zulip's manage.py script (defaults to "shell") > app:backup - Create backups of Zulip instances > app:restore - Restore backups of Zulip instances > app:certs - Create self-signed certificates > app:run - Run the Zulip server > [COMMAND] - Run given command with arguments in shell
Paso 11 – Prueba del correo electrónico saliente
Para probar tu configuración de correo saliente, puedes enviar un correo de prueba utilizando el siguiente comando.
$ ~/docker-zulip/zulip_manage.sh send_test_email [email protected] If you run into any trouble, read: https://zulip.readthedocs.io/en/latest/production/email.html#troubleshooting The most common error is not setting `ADD_TOKENS_TO_NOREPLY_ADDRESS=False` when using an email provider that doesn't support that feature. Sending 2 test emails from: * [email protected] * [email protected] Successfully sent 2 emails to [email protected]
Paso 12 – Actualizar Zulip
El primer paso para actualizar Zulip es detener los contenedores existentes.
$ cd ~/docker-zulip $ docker compose stop
Abre el archivo docker-compose.yml
para editarlo.
$ nano docker-compose.yml
Comprueba la última versión disponible en la página de etiquetas DockerHub de Zulip. Modifica la versión en la sección siguiente.
..... zulip: image: "zulip/docker-zulip:8.2-0" restart: unless-stopped container_name: zulip ....
Realiza cualquier otro cambio que necesites. Tendrás que consultar el registro de cambios de Zulip y el repositorio Docker GitHub de Zulip para ello.
Cuando hayas terminado, guarda el archivo pulsando Ctrl + X e introduciendo Y cuando se te pida.
Inicia de nuevo los contenedores. El contenedor Zulip se volverá a crear con los cambios.
$ docker compose up -d
Elimina los contenedores antiguos.
$ docker compose rm
Conclusión
Con esto concluye nuestro tutorial sobre la instalación y configuración del servidor de Chat Zulip en un servidor Rocky Linux 9. Puedes seguir la documentación oficial de Z ulip para explorar en detalle. Si tienes alguna pregunta, publícala en los comentarios a continuación.