From d13ab16256087ee91c1d0c67f74ad86f2c55533f Mon Sep 17 00:00:00 2001 From: Egutierrez Date: Sat, 8 Nov 2025 22:27:01 +0100 Subject: [PATCH] repositorio iniciado --- .env.example | 34 ++++++++ .gitignore | 40 +++++++++ README.md | 86 +++++++++++++++++++ configs/element-config.json.template | 40 +++++++++ configs/homeserver.yaml.template | 90 ++++++++++++++++++++ docker-compose.yml | 68 +++++++++++++++ element-config.json | 40 +++++++++ scripts/backup.sh | 104 +++++++++++++++++++++++ scripts/create-user.sh | 63 ++++++++++++++ scripts/setup.sh | 121 +++++++++++++++++++++++++++ 10 files changed, 686 insertions(+) create mode 100644 .env.example create mode 100644 .gitignore create mode 100644 README.md create mode 100644 configs/element-config.json.template create mode 100644 configs/homeserver.yaml.template create mode 100644 docker-compose.yml create mode 100644 element-config.json create mode 100755 scripts/backup.sh create mode 100755 scripts/create-user.sh create mode 100755 scripts/setup.sh diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..bb982d7 --- /dev/null +++ b/.env.example @@ -0,0 +1,34 @@ +# Matrix Server Configuration +MATRIX_SERVER_NAME=localhost +MATRIX_REPORT_STATS=no + +# Database Configuration +POSTGRES_DB=synapse +POSTGRES_USER=synapse +POSTGRES_PASSWORD=CHANGE_THIS_PASSWORD + +# Ports Configuration +ELEMENT_PORT=8081 +SYNAPSE_PORT=8008 +SYNAPSE_ADMIN_PORT=8082 +POSTGRES_PORT=5432 + +# Network Configuration +MATRIX_NETWORK_SUBNET=10.10.10.0/24 +MATRIX_NETWORK_GATEWAY=10.10.10.1 + +# Element Configuration +ELEMENT_BRAND=Element Local +ELEMENT_DEFAULT_THEME=light + +# Admin User (will be created automatically) +ADMIN_USERNAME=admin +ADMIN_PASSWORD=CHANGE_THIS_PASSWORD + +# Registration Settings +ENABLE_REGISTRATION=true +ENABLE_REGISTRATION_WITHOUT_VERIFICATION=true + +# Optional: SSL Configuration +# SSL_CERT_PATH=./certs/cert.pem +# SSL_KEY_PATH=./certs/key.pem \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d809db6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,40 @@ +# Datos locales antiguos (ya migrados a volúmenes Docker) +postgresdata/ +synapse*/ + +# Archivos temporales de configuración +homeserver_temp.yaml +homeserver_new.yaml + +# Variables de entorno con datos sensibles +.env + +# Logs y archivos temporales +*.log +*.tmp +.DS_Store +Thumbs.db + +# Respaldos +backups/ +*.backup +*.sql + +# Archivos de IDE +.vscode/ +.idea/ +*.swp +*.swo + +# Certificados SSL (si los usas) +certs/ +*.pem +*.key +*.crt + +# Archivos de media de Matrix (pueden ser muy grandes) +*/media_store/ +*/uploads/ + +# Archivos de estado de Docker +.dockerignore \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..fded897 --- /dev/null +++ b/README.md @@ -0,0 +1,86 @@ +# Matrix + Element + Synapse Admin - Docker Setup + +Configuración completa de servidor Matrix con Element Web y panel de administración usando Docker Compose. + +## 🚀 Servicios incluidos + +- **Matrix Synapse**: Servidor Matrix (puerto 8008) +- **Element Web**: Cliente web (puerto 8081) +- **Synapse Admin**: Panel de administración (puerto 8082) +- **PostgreSQL**: Base de datos (puerto 5432) + +## 📋 Requisitos previos + +- Docker y Docker Compose instalados +- Puertos 8008, 8081, 8082, 5432 disponibles + +## ⚡ Inicio rápido + +1. **Clonar repositorio**: + ```bash + git clone + cd element_matrix_chat + ``` + +2. **Configurar variables de entorno**: + ```bash + cp .env.example .env + # Editar .env con tus configuraciones + ``` + +3. **Ejecutar setup**: + ```bash + ./scripts/setup.sh + ``` + +4. **Iniciar servicios**: + ```bash + docker-compose up -d + ``` + +## 🔐 Acceso por defecto + +- **Element Web**: http://localhost:8081 +- **Synapse Admin**: http://localhost:8082 +- **Usuario admin**: `admin` / `admin123` + +## 📁 Estructura del proyecto + +``` +element_matrix_chat/ +├── docker-compose.yml # Configuración Docker +├── element-config.json # Config Element Web +├── configs/ # Plantillas de configuración +├── scripts/ # Scripts de utilidad +└── README.md # Esta documentación +``` + +## 🛠️ Scripts disponibles + +- `./scripts/setup.sh`: Configuración inicial +- `./scripts/create-user.sh`: Crear usuarios +- `./scripts/backup.sh`: Backup de datos + +## ✨ Características habilitadas + +- ✅ Búsqueda de usuarios +- ✅ Directorio de salas públicas +- ✅ Registro de usuarios habilitado +- ✅ Panel de administración web +- ✅ Persistencia de datos + +## 📖 Documentación adicional + +Consulta la [documentación oficial de Matrix](https://matrix.org/docs/) para configuraciones avanzadas. + +## 🔧 Troubleshooting + +Ver logs: +```bash +docker-compose logs [servicio] +``` + +Reiniciar servicios: +```bash +docker-compose restart +``` \ No newline at end of file diff --git a/configs/element-config.json.template b/configs/element-config.json.template new file mode 100644 index 0000000..302cf8b --- /dev/null +++ b/configs/element-config.json.template @@ -0,0 +1,40 @@ +{ + "default_server_config": { + "m.homeserver": { + "base_url": "http://{{MATRIX_SERVER_NAME}}:{{SYNAPSE_PORT}}", + "server_name": "{{MATRIX_SERVER_NAME}}" + } + }, + "brand": "{{ELEMENT_BRAND}}", + "showLabsSettings": true, + "features": { + "feature_new_layout": true, + "feature_voice_messages": true, + "feature_pinning": true, + "feature_custom_status": true, + "feature_custom_tags": true, + "feature_state_counters": true, + "feature_user_directory": true, + "feature_explore_rooms": true + }, + "default_federate": false, + "default_theme": "{{ELEMENT_DEFAULT_THEME}}", + "room_directory": { + "servers": ["{{MATRIX_SERVER_NAME}}"] + }, + "enable_presence_by_hs_url": { + "http://{{MATRIX_SERVER_NAME}}:{{SYNAPSE_PORT}}": true + }, + "disable_custom_urls": false, + "disable_guests": false, + "disable_login_language_selector": false, + "disable_3pid_login": false, + "brand_image_url": "", + "welcomeUserId": "@welcome-bot:{{MATRIX_SERVER_NAME}}", + "roomDirectory": { + "servers": ["{{MATRIX_SERVER_NAME}}"], + "include_all_known_servers": false + }, + "permalink_prefix": "http://{{MATRIX_SERVER_NAME}}:{{ELEMENT_PORT}}", + "bug_report_endpoint_url": "" +} \ No newline at end of file diff --git a/configs/homeserver.yaml.template b/configs/homeserver.yaml.template new file mode 100644 index 0000000..ebe5134 --- /dev/null +++ b/configs/homeserver.yaml.template @@ -0,0 +1,90 @@ +# Matrix Synapse Configuration Template +# Replace variables with actual values before use + +server_name: "{{MATRIX_SERVER_NAME}}" +pid_file: /data/homeserver.pid + +listeners: + - port: 8008 + tls: false + type: http + x_forwarded: true + resources: + - names: [client, federation] + compress: false + - port: 8009 + tls: false + type: http + x_forwarded: true + bind_addresses: ['0.0.0.0'] + resources: + - names: [replication] + compress: false + +database: + name: psycopg2 + args: + user: "{{POSTGRES_USER}}" + password: "{{POSTGRES_PASSWORD}}" + database: "{{POSTGRES_DB}}" + host: postgres + cp_min: 5 + cp_max: 10 + allow_unsafe_locale: true + +log_config: "/data/localhost.log.config" +media_store_path: /data/media_store + +registration_shared_secret: "{{REGISTRATION_SHARED_SECRET}}" +report_stats: {{MATRIX_REPORT_STATS}} + +enable_registration: {{ENABLE_REGISTRATION}} +enable_registration_without_verification: {{ENABLE_REGISTRATION_WITHOUT_VERIFICATION}} + +macaroon_secret_key: "{{MACAROON_SECRET_KEY}}" +form_secret: "{{FORM_SECRET}}" +signing_key_path: "/data/localhost.signing.key" + +trusted_key_servers: + - server_name: "matrix.org" +suppress_key_server_warning: true + +# User directory configuration +user_directory: + enabled: true + search_all_users: true + prefer_local_users: true + +# Allow public room directory +allow_public_rooms_without_auth: true +allow_public_rooms_over_federation: true + +# Room directory configuration +room_list_publication_rules: + - user_id: "*" + alias: "*" + room_id: "*" + action: allow + +# Application service configuration +app_service_config_files: [] + +# Enable user search via federation +user_directory_search_all_users: true + +# Room creation settings +room_prejoin_state: + additional_event_types: + - "m.room.canonical_alias" + - "m.room.name" + - "m.room.topic" + - "m.room.avatar" + +# Public room settings +autocreate_auto_join_rooms: false +auto_join_rooms: [] + +# Statistics and metrics +enable_metrics: true +stats: + enabled: true \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..87fbfa3 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,68 @@ +services: + postgres: + image: postgres:16 + restart: unless-stopped + networks: + default: + ipv4_address: 10.10.10.2 + volumes: + - matrix_postgres_data:/var/lib/postgresql/data + environment: + - POSTGRES_DB=synapse + - POSTGRES_USER=synapse + - POSTGRES_PASSWORD=STRONGPASSWORD123 + ports: + - "5432:5432" + + element: + image: vectorim/element-web:latest + restart: unless-stopped + volumes: + - ./element-config.json:/app/config.json:ro + networks: + default: + ipv4_address: 10.10.10.3 + ports: + - "8081:80" + + synapse: + image: matrixdotorg/synapse:latest + restart: unless-stopped + networks: + default: + ipv4_address: 10.10.10.4 + volumes: + - matrix_synapse_data:/data + ports: + - "8008:8008" + - "8009:8009" + depends_on: + - postgres + user: "0:0" + environment: + - UID=1000 + - GID=1000 + + synapse-admin: + image: awesometechnologies/synapse-admin:latest + restart: unless-stopped + networks: + default: + ipv4_address: 10.10.10.5 + ports: + - "8082:80" + depends_on: + - synapse + +volumes: + matrix_postgres_data: + external: true + name: matrix_postgres_data + matrix_synapse_data: + external: true + name: matrix_synapse_data + +networks: + default: + name: matrix_net + external: true \ No newline at end of file diff --git a/element-config.json b/element-config.json new file mode 100644 index 0000000..48ba7be --- /dev/null +++ b/element-config.json @@ -0,0 +1,40 @@ +{ + "default_server_config": { + "m.homeserver": { + "base_url": "http://localhost:8008", + "server_name": "localhost" + } + }, + "brand": "Element Local", + "showLabsSettings": true, + "features": { + "feature_new_layout": true, + "feature_voice_messages": true, + "feature_pinning": true, + "feature_custom_status": true, + "feature_custom_tags": true, + "feature_state_counters": true, + "feature_user_directory": true, + "feature_explore_rooms": true + }, + "default_federate": false, + "default_theme": "light", + "room_directory": { + "servers": ["localhost"] + }, + "enable_presence_by_hs_url": { + "http://localhost:8008": true + }, + "disable_custom_urls": false, + "disable_guests": false, + "disable_login_language_selector": false, + "disable_3pid_login": false, + "brand_image_url": "", + "welcomeUserId": "@welcome-bot:localhost", + "roomDirectory": { + "servers": ["localhost"], + "include_all_known_servers": false + }, + "permalink_prefix": "http://localhost:8081", + "bug_report_endpoint_url": "" +} \ No newline at end of file diff --git a/scripts/backup.sh b/scripts/backup.sh new file mode 100755 index 0000000..0275a24 --- /dev/null +++ b/scripts/backup.sh @@ -0,0 +1,104 @@ +#!/bin/bash + +# Script de backup para Matrix + Element +set -e + +# Colores +GREEN='\033[0;32m' +BLUE='\033[0;34m' +RED='\033[0;31m' +YELLOW='\033[1;33m' +NC='\033[0m' + +# Configuración +BACKUP_DIR="./backups" +DATE=$(date +"%Y%m%d_%H%M%S") +BACKUP_NAME="matrix_backup_$DATE" + +echo -e "${BLUE}💾 Iniciando backup de Matrix...${NC}" + +# Crear directorio de backup +mkdir -p "$BACKUP_DIR" + +echo -e "${BLUE}📁 Creando directorio de backup: $BACKUP_NAME${NC}" +mkdir -p "$BACKUP_DIR/$BACKUP_NAME" + +# Backup de configuraciones +echo -e "${BLUE}⚙️ Respaldando configuraciones...${NC}" +cp docker-compose.yml "$BACKUP_DIR/$BACKUP_NAME/" +cp element-config.json "$BACKUP_DIR/$BACKUP_NAME/" +cp -r configs "$BACKUP_DIR/$BACKUP_NAME/" 2>/dev/null || true + +# Backup de base de datos PostgreSQL +echo -e "${BLUE}🗄️ Respaldando base de datos...${NC}" +if docker ps | grep -q element_matrix_chat-postgres-1; then + docker exec element_matrix_chat-postgres-1 pg_dump -U synapse synapse > "$BACKUP_DIR/$BACKUP_NAME/database.sql" + echo -e "${GREEN}✅ Base de datos respaldada${NC}" +else + echo -e "${YELLOW}⚠️ PostgreSQL no está ejecutándose, saltando backup de BD${NC}" +fi + +# Backup de datos de Synapse (excluyendo media store por tamaño) +echo -e "${BLUE}📋 Respaldando configuración de Synapse...${NC}" +if [ -d synapse3 ]; then + mkdir -p "$BACKUP_DIR/$BACKUP_NAME/synapse_config" + cp synapse3/homeserver.yaml "$BACKUP_DIR/$BACKUP_NAME/synapse_config/" 2>/dev/null || true + cp synapse3/localhost.log.config "$BACKUP_DIR/$BACKUP_NAME/synapse_config/" 2>/dev/null || true + cp synapse3/localhost.signing.key "$BACKUP_DIR/$BACKUP_NAME/synapse_config/" 2>/dev/null || true + cp -r synapse3/appservices "$BACKUP_DIR/$BACKUP_NAME/synapse_config/" 2>/dev/null || true + echo -e "${GREEN}✅ Configuración de Synapse respaldada${NC}" +fi + +# Crear archivo de información del backup +echo -e "${BLUE}📄 Creando archivo de información...${NC}" +cat > "$BACKUP_DIR/$BACKUP_NAME/backup_info.txt" << EOF +Matrix + Element Backup +====================== +Fecha: $(date) +Versión Docker Compose: $(docker-compose --version) +Contenedores activos: +$(docker ps --format "table {{.Names}}\t{{.Image}}\t{{.Status}}") + +Archivos incluidos: +- docker-compose.yml +- element-config.json +- synapse_config/ (homeserver.yaml, claves, etc.) +- database.sql (dump de PostgreSQL) + +NO incluidos (por tamaño): +- media_store/ +- postgresdata/ + +Para restaurar: +1. Restaurar archivos de configuración +2. docker-compose up -d postgres +3. docker exec -i element_matrix_chat-postgres-1 psql -U synapse synapse < database.sql +4. docker-compose up -d +EOF + +# Comprimir backup +echo -e "${BLUE}🗜️ Comprimiendo backup...${NC}" +cd "$BACKUP_DIR" +tar -czf "${BACKUP_NAME}.tar.gz" "$BACKUP_NAME" +rm -rf "$BACKUP_NAME" +cd .. + +# Información final +BACKUP_SIZE=$(du -h "$BACKUP_DIR/${BACKUP_NAME}.tar.gz" | cut -f1) +echo +echo -e "${GREEN}🎉 Backup completado exitosamente${NC}" +echo -e "${BLUE}📍 Información del backup:${NC}" +echo -e " • Archivo: ${GREEN}$BACKUP_DIR/${BACKUP_NAME}.tar.gz${NC}" +echo -e " • Tamaño: ${GREEN}$BACKUP_SIZE${NC}" +echo -e " • Fecha: ${GREEN}$(date)${NC}" +echo +echo -e "${BLUE}💡 Para restaurar:${NC}" +echo -e " tar -xzf $BACKUP_DIR/${BACKUP_NAME}.tar.gz" +echo -e " # Seguir instrucciones en backup_info.txt" + +# Limpiar backups antiguos (mantener últimos 5) +echo -e "${BLUE}🧹 Limpiando backups antiguos...${NC}" +cd "$BACKUP_DIR" +ls -t matrix_backup_*.tar.gz | tail -n +6 | xargs rm -f 2>/dev/null || true +REMAINING=$(ls matrix_backup_*.tar.gz 2>/dev/null | wc -l) +echo -e "${GREEN}✅ Manteniendo $REMAINING backups${NC}" \ No newline at end of file diff --git a/scripts/create-user.sh b/scripts/create-user.sh new file mode 100755 index 0000000..6c02f57 --- /dev/null +++ b/scripts/create-user.sh @@ -0,0 +1,63 @@ +#!/bin/bash + +# Script para crear usuarios en Matrix +set -e + +# Colores +GREEN='\033[0;32m' +BLUE='\033[0;34m' +RED='\033[0;31m' +YELLOW='\033[1;33m' +NC='\033[0m' + +# Verificar que Synapse esté ejecutándose +if ! docker ps | grep -q element_matrix_chat-synapse-1; then + echo -e "${RED}❌ Synapse no está ejecutándose${NC}" + echo -e "${BLUE}💡 Ejecuta: docker-compose up -d${NC}" + exit 1 +fi + +# Solicitar datos del usuario +echo -e "${BLUE}👤 Creador de usuarios Matrix${NC}" +echo + +read -p "Nombre de usuario: " username +read -s -p "Contraseña: " password +echo +read -p "¿Es administrador? (y/N): " is_admin + +# Configurar flag de administrador +admin_flag="" +if [[ $is_admin =~ ^[Yy]$ ]]; then + admin_flag="-a" + echo -e "${YELLOW}⚠️ El usuario será administrador${NC}" +fi + +echo -e "${BLUE}🔄 Creando usuario...${NC}" + +# Crear usuario +if docker exec element_matrix_chat-synapse-1 register_new_matrix_user \ + -c /data/homeserver.yaml \ + -u "$username" \ + -p "$password" \ + $admin_flag \ + http://localhost:8008; then + echo -e "${GREEN}✅ Usuario '$username' creado exitosamente${NC}" + echo + echo -e "${BLUE}📍 Información del usuario:${NC}" + echo -e " • Usuario: ${GREEN}$username${NC}" + echo -e " • ID Matrix: ${GREEN}@$username:localhost${NC}" + echo -e " • Contraseña: ${GREEN}[configurada]${NC}" + if [[ $is_admin =~ ^[Yy]$ ]]; then + echo -e " • Tipo: ${YELLOW}Administrador${NC}" + else + echo -e " • Tipo: ${GREEN}Usuario normal${NC}" + fi + echo + echo -e "${BLUE}🌐 Para acceder:${NC}" + echo -e " • Element Web: http://localhost:8081" + echo -e " • Servidor: http://localhost:8008" +else + echo -e "${RED}❌ Error al crear el usuario${NC}" + exit 1 +fi \ No newline at end of file diff --git a/scripts/setup.sh b/scripts/setup.sh new file mode 100755 index 0000000..2ce87d9 --- /dev/null +++ b/scripts/setup.sh @@ -0,0 +1,121 @@ +#!/bin/bash + +# Matrix + Element Setup Script +set -e + +echo "🚀 Configurando Matrix + Element + Synapse Admin..." + +# Colores para output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# Verificar Docker +if ! command -v docker &> /dev/null; then + echo -e "${RED}❌ Docker no está instalado${NC}" + exit 1 +fi + +if ! command -v docker-compose &> /dev/null; then + echo -e "${RED}❌ Docker Compose no está instalado${NC}" + exit 1 +fi + +# Verificar archivo .env +if [ ! -f .env ]; then + echo -e "${YELLOW}⚠️ Archivo .env no encontrado, copiando desde .env.example${NC}" + cp .env.example .env + echo -e "${RED}🔧 Por favor edita el archivo .env con tus configuraciones${NC}" + echo -e "${BLUE}💡 Especialmente cambia las contraseñas por defecto${NC}" + exit 1 +fi + +# Cargar variables de entorno +source .env + +echo -e "${BLUE}📋 Verificando configuración...${NC}" + +# Crear red Docker si no existe +echo -e "${BLUE}🌐 Creando red Docker...${NC}" +if ! docker network ls | grep -q matrix_net; then + docker network create --driver=bridge --subnet=${MATRIX_NETWORK_SUBNET} --gateway=${MATRIX_NETWORK_GATEWAY} matrix_net + echo -e "${GREEN}✅ Red matrix_net creada${NC}" +else + echo -e "${YELLOW}ℹ️ Red matrix_net ya existe${NC}" +fi + +# Crear directorios necesarios +echo -e "${BLUE}📁 Creando directorios...${NC}" +mkdir -p synapse_data/appservices +mkdir -p backups + +# Generar configuración de Synapse si no existe +if [ ! -f synapse_data/homeserver.yaml ]; then + echo -e "${BLUE}⚙️ Generando configuración de Synapse...${NC}" + + # Generar configuración inicial + docker run --rm -v "$PWD/synapse_data:/data" \ + -e SYNAPSE_SERVER_NAME=${MATRIX_SERVER_NAME} \ + -e SYNAPSE_REPORT_STATS=${MATRIX_REPORT_STATS} \ + --user root \ + matrixdotorg/synapse:latest generate + + # Cambiar permisos + docker run --rm -v "$PWD:/workdir" --user root alpine sh -c "chown -R $(id -u):$(id -g) /workdir/synapse_data" + + echo -e "${GREEN}✅ Configuración base de Synapse generada${NC}" + echo -e "${YELLOW}🔧 Aplicando configuraciones personalizadas...${NC}" + + # Aquí podrías aplicar modificaciones automáticas al homeserver.yaml + # Por ahora, usamos la configuración manual existente +fi + +echo -e "${BLUE}🐳 Iniciando contenedores...${NC}" +docker-compose up -d + +echo -e "${BLUE}⏳ Esperando que los servicios estén listos...${NC}" +sleep 20 + +# Verificar que todos los servicios estén funcionando +echo -e "${BLUE}🔍 Verificando servicios...${NC}" + +services=("postgres:5432" "synapse:8008" "element:8081" "synapse-admin:8082") +for service in "${services[@]}"; do + name=${service%:*} + port=${service#*:} + + if curl -s http://localhost:$port > /dev/null 2>&1; then + echo -e "${GREEN}✅ $name (puerto $port) - OK${NC}" + else + echo -e "${RED}❌ $name (puerto $port) - ERROR${NC}" + fi +done + +# Crear usuario administrador si no existe +echo -e "${BLUE}👤 Creando usuario administrador...${NC}" +if docker exec element_matrix_chat-synapse-1 register_new_matrix_user \ + -c /data/homeserver.yaml \ + -u ${ADMIN_USERNAME} \ + -p ${ADMIN_PASSWORD} \ + -a \ + http://localhost:8008 2>/dev/null; then + echo -e "${GREEN}✅ Usuario administrador creado: ${ADMIN_USERNAME}${NC}" +else + echo -e "${YELLOW}ℹ️ Usuario administrador ya existe o hubo un error${NC}" +fi + +echo +echo -e "${GREEN}🎉 ¡Configuración completada!${NC}" +echo +echo -e "${BLUE}📍 Acceso a los servicios:${NC}" +echo -e " • Element Web: ${GREEN}http://localhost:${ELEMENT_PORT}${NC}" +echo -e " • Synapse Admin: ${GREEN}http://localhost:${SYNAPSE_ADMIN_PORT}${NC}" +echo -e " • API Matrix: ${GREEN}http://localhost:${SYNAPSE_PORT}${NC}" +echo +echo -e "${BLUE}🔐 Credenciales de administrador:${NC}" +echo -e " • Usuario: ${GREEN}${ADMIN_USERNAME}${NC}" +echo -e " • Contraseña: ${GREEN}${ADMIN_PASSWORD}${NC}" +echo +echo -e "${YELLOW}💡 Para crear más usuarios usa: ./scripts/create-user.sh${NC}" \ No newline at end of file