diff --git a/group_vars/all.yml b/group_vars/all.yml index 20215a5..acf6df1 100644 --- a/group_vars/all.yml +++ b/group_vars/all.yml @@ -22,3 +22,41 @@ a412b12 (Fix: V3.2 upgrade paths) # Activepieces Configuration ap_encryption_key: "ff7d959b67bc4b31752d51c3db3bbb5b" ap_jwt_secret: "eW4o2aZs0yNT3Z9kSS6IYDLtMtJ/Uh1acV0HIYOfrtI=" +# ============================================================================ +# ALICANTE CORE V3.3 - Credenciales estándar +# ============================================================================ + +# Usuario estándar CORE +core_user: + username: "CORE" + firstname: "ALICANTE" + lastname: "CORE" + email: "ANT1NONAME@DISROOT.ORG" + password: "coreALICANTE@2026" + +# Credenciales de bases de datos +core_db_credentials: + postgres_root_password: "coreALICANTE@2026" + dolibarr_db_name: "dolibarr_db" + dolibarr_db_user: "dolibarr_core" + dolibarr_db_pass: "coreALICANTE@2026" + teable_db_name: "teable_db" + teable_db_user: "teable_core" + teable_db_pass: "coreALICANTE@2026" + activepieces_db_name: "activepieces_db" + activepieces_db_user: "activepieces_core" + activepieces_db_pass: "coreALICANTE@2026" + wikijs_db_name: "wikijs_db" + wikijs_db_user: "wikijs_core" + wikijs_db_pass: "coreALICANTE@2026" + metabase_db_name: "metabase_db" + metabase_db_user: "metabase_core" + metabase_db_pass: "coreALICANTE@2026" + +# Dominios (adaptar a tus dominios reales de NPM) +dolibarr_domain: "dolibarr.tudominio.com" +teable_domain: "teable.tudominio.com" +activepieces_domain: "activepieces.tudominio.com" +wikijs_domain: "wiki.tudominio.com" +metabase_domain: "metabase.tudominio.com" +authentik_domain: "auth.tudominio.com" diff --git a/roles/core/templates/business-compose.j2 b/roles/core/templates/business-compose.j2 index 8bc43fc..05d5adb 100644 --- a/roles/core/templates/business-compose.j2 +++ b/roles/core/templates/business-compose.j2 @@ -1,83 +1,57 @@ +version: '3.8' + services: - # DB Interna del Stack - db: - image: postgres:16-alpine - restart: always - environment: - POSTGRES_PASSWORD: {{ global_db_pass }} - POSTGRES_USER: postgres - POSTGRES_DB: postgres - volumes: - - pg_data:/var/lib/postgresql/data - healthcheck: - test: ["CMD-SHELL", "pg_isready -U postgres"] - interval: 5s - timeout: 5s - retries: 5 - - redis: - image: redis:alpine - restart: always - command: redis-server --requirepass {{ global_redis_pass }} - healthcheck: - test: ["CMD", "redis-cli", "ping"] - interval: 5s - timeout: 3s - retries: 5 - - # APPS - dolibarr: - image: upshift/dolibarr:latest - depends_on: - db: - condition: service_healthy - environment: - DOLI_DB_HOST: db - DOLI_DB_PORT: 5432 - DOLI_DB_TYPE: pgsql - DOLI_DB_USER: postgres - DOLI_DB_PASSWORD: {{ global_db_pass }} - DOLI_ADMIN_LOGIN: admin - DOLI_ADMIN_PASSWORD: admin - ports: - - "8080:80" - teable: image: teableio/teable:latest - depends_on: - db: - condition: service_healthy - redis: - condition: service_healthy - environment: - PRISMA_DATABASE_URL: "postgresql://postgres:{{ global_db_pass }}@db:5432/teable" - REDIS_URL: "redis://:{{ global_redis_pass }}@redis:6379/0" - PUBLIC_ORIGIN: "http://{{ ansible_host }}:3000" - SECRET_KEY: "TeableSecretKey123" + container_name: business-teable-1 ports: - "3000:3000" + environment: + - DATABASE_URL=postgresql://{{ core_db_credentials.teable_db_user }}:{{ core_db_credentials.teable_db_pass }}@host.docker.internal:5432/{{ core_db_credentials.teable_db_name }} + - REDIS_URL=redis://redis:6379 + - PUBLIC_ORIGIN=http://{{ teable_domain }} + - NEXT_PUBLIC_BUILD_STANDALONE=1 + volumes: + - teable_data:/app/.assets + extra_hosts: + - "host.docker.internal:host-gateway" + depends_on: + - redis + restart: unless-stopped activepieces: image: activepieces/activepieces:latest - depends_on: - db: - condition: service_healthy - redis: - condition: service_healthy - environment: - AP_POSTGRES_HOST: db - AP_POSTGRES_PORT: 5432 - AP_POSTGRES_DATABASE: activepieces - AP_POSTGRES_USERNAME: postgres - AP_POSTGRES_PASSWORD: {{ global_db_pass }} - AP_REDIS_HOST: redis - AP_REDIS_PORT: 6379 - AP_REDIS_PASSWORD: {{ global_redis_pass }} - AP_FRONTEND_URL: "http://{{ ansible_host }}:8081" - AP_ENCRYPTION_KEY: "{{ ap_encryption_key }}" - AP_JWT_SECRET: "{{ ap_jwt_secret }}" + container_name: business-activepieces-1 ports: - "8081:80" + environment: + - AP_POSTGRES_DATABASE={{ core_db_credentials.activepieces_db_name }} + - AP_POSTGRES_HOST=host.docker.internal + - AP_POSTGRES_PORT=5432 + - AP_POSTGRES_USERNAME={{ core_db_credentials.activepieces_db_user }} + - AP_POSTGRES_PASSWORD={{ core_db_credentials.activepieces_db_pass }} + - AP_REDIS_HOST=redis + - AP_REDIS_PORT=6379 + - AP_ENCRYPTION_KEY={{ ap_encryption_key }} + - AP_JWT_SECRET={{ ap_jwt_secret }} + - AP_FRONTEND_URL=http://{{ activepieces_domain }} + volumes: + - activepieces_data:/root/.activepieces + extra_hosts: + - "host.docker.internal:host-gateway" + depends_on: + - redis + restart: unless-stopped + + redis: + image: redis:7-alpine + container_name: business-redis-1 + command: redis-server --appendonly yes + volumes: + - redis_data:/data + restart: unless-stopped volumes: - pg_data: + teable_data: + activepieces_data: + redis_data: diff --git a/roles/core/templates/docs-compose.j2 b/roles/core/templates/docs-compose.j2 index ee306da..53c8e1b 100644 --- a/roles/core/templates/docs-compose.j2 +++ b/roles/core/templates/docs-compose.j2 @@ -1,46 +1,56 @@ +version: '3.8' + services: - - - # Base de datos para Wiki.js (PostgreSQL) - wikidb: - image: postgres:16-alpine - environment: - POSTGRES_DB: wikijs - POSTGRES_PASSWORD: {{ global_db_pass }} - POSTGRES_USER: wikijs - volumes: - - wikijs_db_data:/var/lib/postgresql/data - restart: unless-stopped - - # Wiki.js wikijs: image: ghcr.io/requarks/wiki:2 - environment: - DB_TYPE: postgres - DB_HOST: wikidb - DB_PORT: 5432 - DB_USER: wikijs - DB_PASS: {{ global_db_pass }} - DB_NAME: wikijs + container_name: docs-wikijs-1 ports: - "6875:3000" - depends_on: - - wikidb + environment: + - DB_TYPE=postgres + - DB_HOST=host.docker.internal + - DB_PORT=5432 + - DB_NAME={{ core_db_credentials.wikijs_db_name }} + - DB_USER={{ core_db_credentials.wikijs_db_user }} + - DB_PASS={{ core_db_credentials.wikijs_db_pass }} + volumes: + - wikijs_data:/wiki/data + extra_hosts: + - "host.docker.internal:host-gateway" restart: unless-stopped - metabase: image: metabase/metabase:latest + container_name: docs-metabase-1 ports: - "3001:3000" + environment: + - MB_DB_TYPE=postgres + - MB_DB_DBNAME={{ core_db_credentials.metabase_db_name }} + - MB_DB_PORT=5432 + - MB_DB_USER={{ core_db_credentials.metabase_db_user }} + - MB_DB_PASS={{ core_db_credentials.metabase_db_pass }} + - MB_DB_HOST=host.docker.internal + volumes: + - metabase_data:/metabase-data + extra_hosts: + - "host.docker.internal:host-gateway" + restart: unless-stopped gotenberg: image: gotenberg/gotenberg:8 + container_name: docs-gotenberg-1 ports: - "3002:3000" - + command: + - "gotenberg" + - "--api-timeout=30s" + volumes: + - gotenberg_fonts:/usr/share/fonts + - /opt/gotenberg-templates:/usr/share/gotenberg/templates:ro + restart: unless-stopped volumes: - wikijs_db_data: - # ... otros volúmenes - + wikijs_data: + metabase_data: + gotenberg_fonts: diff --git a/roles/core_setup_automation/tasks/main.yml b/roles/core_setup_automation/tasks/main.yml new file mode 100644 index 0000000..f335042 --- /dev/null +++ b/roles/core_setup_automation/tasks/main.yml @@ -0,0 +1,36 @@ +--- +- name: Esperar a que servicios estén listos + wait_for: + host: "{{ core_ip }}" + port: "{{ item }}" + timeout: 180 + loop: + - 8080 # Dolibarr + - 3000 # Teable + - 8081 # Activepieces + - 6875 # Wiki.js + - 3001 # Metabase + +- name: Mensaje de configuración manual + debug: + msg: | + ============================================================ + ALICANTE CORE V3.3 DESPLEGADO CORRECTAMENTE + ============================================================ + + Todos los servicios están disponibles en: + - Dolibarr: http://{{ dolibarr_domain }}:8080 + - Teable: http://{{ teable_domain }}:3000 + - Activepieces: http://{{ activepieces_domain }}:8081 + - Wiki.js: http://{{ wikijs_domain }}:6875 + - Metabase: http://{{ metabase_domain }}:3001 + + Credenciales estándar: + - Usuario: CORE + - Email: ANT1NONAME@DISROOT.ORG + - Contraseña: coreALICANTE@2026 + + NOTA: Dolibarr requiere completar setup wizard manualmente + en primera ejecución. Los demás servicios usarán las + credenciales automáticamente. + ============================================================ diff --git a/roles/dolibarr_native/handlers/main.yml b/roles/dolibarr_native/handlers/main.yml new file mode 100644 index 0000000..ebbd38f --- /dev/null +++ b/roles/dolibarr_native/handlers/main.yml @@ -0,0 +1,5 @@ +--- +- name: restart apache + systemd: + name: apache2 + state: restarted diff --git a/roles/dolibarr_native/tasks/main.yml b/roles/dolibarr_native/tasks/main.yml new file mode 100644 index 0000000..31d86d2 --- /dev/null +++ b/roles/dolibarr_native/tasks/main.yml @@ -0,0 +1,180 @@ +--- +- name: Instalar Apache y PHP 8.2 + apt: + name: + - apache2 + - php8.2 + - php8.2-cli + - php8.2-fpm + - php8.2-pgsql + - php8.2-curl + - php8.2-gd + - php8.2-intl + - php8.2-xml + - php8.2-zip + - php8.2-mbstring + - php8.2-ldap + - libapache2-mod-php8.2 + - wget + - unzip + state: present + update_cache: yes + +- name: Habilitar módulos Apache necesarios + apache2_module: + name: "{{ item }}" + state: present + loop: + - rewrite + - headers + notify: restart apache + +- name: Crear directorio base Dolibarr + file: + path: /var/www/dolibarr + state: directory + owner: www-data + group: www-data + mode: '0755' + +- name: Descargar Dolibarr 20.0.2 + get_url: + url: https://github.com/Dolibarr/dolibarr/archive/refs/tags/20.0.2.tar.gz + dest: /tmp/dolibarr-20.0.2.tar.gz + timeout: 120 + +- name: Extraer Dolibarr + unarchive: + src: /tmp/dolibarr-20.0.2.tar.gz + dest: /tmp/ + remote_src: yes + creates: /tmp/dolibarr-20.0.2 + +- name: Mover contenido a /var/www/dolibarr + shell: | + cp -r /tmp/dolibarr-20.0.2/htdocs /var/www/dolibarr/ + cp -r /tmp/dolibarr-20.0.2/scripts /var/www/dolibarr/ + args: + creates: /var/www/dolibarr/htdocs + +- name: Crear directorios necesarios + file: + path: "{{ item }}" + state: directory + owner: www-data + group: www-data + mode: '0755' + loop: + - /var/www/dolibarr/documents + - /var/www/dolibarr/htdocs/conf + - /var/www/dolibarr/htdocs/custom + +- name: Crear conf.php inicial + template: + src: conf.php.j2 + dest: /var/www/dolibarr/htdocs/conf/conf.php + owner: www-data + group: www-data + mode: '0640' + +- name: Configurar permisos correctos + file: + path: "{{ item }}" + owner: www-data + group: www-data + recurse: yes + loop: + - /var/www/dolibarr/htdocs/conf + - /var/www/dolibarr/documents + +- name: Crear VirtualHost Apache para Dolibarr + copy: + dest: /etc/apache2/sites-available/dolibarr.conf + content: | + + ServerAdmin admin@localhost + DocumentRoot /var/www/dolibarr/htdocs + + + Options -Indexes +FollowSymLinks + AllowOverride All + Require all granted + + + + Require all denied + + + ErrorLog ${APACHE_LOG_DIR}/dolibarr-error.log + CustomLog ${APACHE_LOG_DIR}/dolibarr-access.log combined + + notify: restart apache + +- name: Cambiar Apache a puerto 8080 + lineinfile: + path: /etc/apache2/ports.conf + regexp: '^Listen 80' + line: 'Listen 8080' + notify: restart apache + +- name: Deshabilitar sitio default + command: a2dissite 000-default + notify: restart apache + ignore_errors: yes + +- name: Habilitar sitio Dolibarr + command: a2ensite dolibarr + notify: restart apache + +- name: Asegurar Apache iniciado + systemd: + name: apache2 + state: started + enabled: yes + +- name: Esperar a que Apache esté listo + wait_for: + port: 8080 + timeout: 30 + +- name: Crear install.lock para seguridad + file: + path: /var/www/dolibarr/documents/install.lock + state: touch + owner: www-data + group: www-data + mode: '0444' + +- name: Crear script backup Dolibarr + copy: + dest: /usr/local/bin/backup-dolibarr.sh + mode: '0755' + content: | + #!/bin/bash + DATE=$(date +%Y%m%d_%H%M%S) + BACKUP_DIR="/opt/backups/dolibarr" + mkdir -p "$BACKUP_DIR" + + tar -czf "$BACKUP_DIR/dolibarr_files_$DATE.tar.gz" \ + /var/www/dolibarr/documents \ + /var/www/dolibarr/htdocs/conf + + su - postgres -c "pg_dump {{ core_db_credentials.dolibarr_db_name }}" | gzip > "$BACKUP_DIR/dolibarr_db_$DATE.sql.gz" + + find "$BACKUP_DIR" -mtime +14 -delete + + echo "✓ Backup Dolibarr: $DATE" + +- name: Crear directorio backups Dolibarr + file: + path: /opt/backups/dolibarr + state: directory + mode: '0755' + +- name: Programar backup semanal Dolibarr + cron: + name: "Backup Dolibarr" + weekday: "0" + hour: "4" + minute: "0" + job: "/usr/local/bin/backup-dolibarr.sh >> /var/log/dolibarr-backup.log 2>&1" diff --git a/roles/dolibarr_native/templates/conf.php.j2 b/roles/dolibarr_native/templates/conf.php.j2 new file mode 100644 index 0000000..ef4b98c --- /dev/null +++ b/roles/dolibarr_native/templates/conf.php.j2 @@ -0,0 +1,24 @@ + diff --git a/roles/postgresql_native/handlers/main.yml b/roles/postgresql_native/handlers/main.yml new file mode 100644 index 0000000..a1dd485 --- /dev/null +++ b/roles/postgresql_native/handlers/main.yml @@ -0,0 +1,5 @@ +--- +- name: restart postgresql + systemd: + name: postgresql + state: restarted diff --git a/roles/postgresql_native/tasks/main.yml b/roles/postgresql_native/tasks/main.yml new file mode 100644 index 0000000..59af55e --- /dev/null +++ b/roles/postgresql_native/tasks/main.yml @@ -0,0 +1,101 @@ +--- +- name: Instalar PostgreSQL 15 + apt: + name: + - postgresql-15 + - postgresql-contrib + - python3-psycopg2 + state: present + update_cache: yes + +- name: Configurar PostgreSQL para escuchar en localhost + lineinfile: + path: /etc/postgresql/15/main/postgresql.conf + regexp: '^#?listen_addresses' + line: "listen_addresses = 'localhost'" + notify: restart postgresql + +- name: Permitir conexiones locales con password + lineinfile: + path: /etc/postgresql/15/main/pg_hba.conf + insertafter: '^# "local" is for Unix domain socket' + line: "host all all 127.0.0.1/32 scram-sha-256" + notify: restart postgresql + +- name: Asegurar PostgreSQL iniciado y habilitado + systemd: + name: postgresql + state: started + enabled: yes + +- name: Esperar a que PostgreSQL esté listo + wait_for: + port: 5432 + timeout: 30 + +- name: Cambiar contraseña del usuario postgres + postgresql_user: + name: postgres + password: "{{ core_db_credentials.postgres_root_password }}" + login_unix_socket: /var/run/postgresql + become_user: postgres + +- name: Crear bases de datos + postgresql_db: + name: "{{ item.name }}" + encoding: UTF-8 + lc_collate: es_ES.UTF-8 + lc_ctype: es_ES.UTF-8 + template: template0 + login_unix_socket: /var/run/postgresql + become_user: postgres + loop: + - { name: "{{ core_db_credentials.dolibarr_db_name }}" } + - { name: "{{ core_db_credentials.teable_db_name }}" } + - { name: "{{ core_db_credentials.activepieces_db_name }}" } + - { name: "{{ core_db_credentials.wikijs_db_name }}" } + - { name: "{{ core_db_credentials.metabase_db_name }}" } + +- name: Crear usuarios de bases de datos + postgresql_user: + name: "{{ item.user }}" + password: "{{ item.pass }}" + db: "{{ item.db }}" + priv: ALL + login_unix_socket: /var/run/postgresql + become_user: postgres + loop: + - { user: "{{ core_db_credentials.dolibarr_db_user }}", pass: "{{ core_db_credentials.dolibarr_db_pass }}", db: "{{ core_db_credentials.dolibarr_db_name }}" } + - { user: "{{ core_db_credentials.teable_db_user }}", pass: "{{ core_db_credentials.teable_db_pass }}", db: "{{ core_db_credentials.teable_db_name }}" } + - { user: "{{ core_db_credentials.activepieces_db_user }}", pass: "{{ core_db_credentials.activepieces_db_pass }}", db: "{{ core_db_credentials.activepieces_db_name }}" } + - { user: "{{ core_db_credentials.wikijs_db_user }}", pass: "{{ core_db_credentials.wikijs_db_pass }}", db: "{{ core_db_credentials.wikijs_db_name }}" } + - { user: "{{ core_db_credentials.metabase_db_user }}", pass: "{{ core_db_credentials.metabase_db_pass }}", db: "{{ core_db_credentials.metabase_db_name }}" } + +- name: Crear script de backup automático + copy: + dest: /usr/local/bin/backup-postgres-core.sh + mode: '0755' + content: | + #!/bin/bash + DATE=$(date +%Y%m%d_%H%M%S) + BACKUP_DIR="/opt/backups/postgres" + mkdir -p "$BACKUP_DIR" + + su - postgres -c "pg_dumpall" | gzip > "$BACKUP_DIR/all_dbs_$DATE.sql.gz" + + find "$BACKUP_DIR" -name "*.sql.gz" -mtime +7 -delete + + echo "✓ Backup PostgreSQL completado: $DATE" + +- name: Crear directorio de backups + file: + path: /opt/backups/postgres + state: directory + mode: '0755' + +- name: Programar backup diario PostgreSQL + cron: + name: "Backup PostgreSQL CORE" + minute: "0" + hour: "3" + job: "/usr/local/bin/backup-postgres-core.sh >> /var/log/postgres-backup.log 2>&1" diff --git a/site.yml b/site.yml index b0c4e59..5ac99b3 100644 --- a/site.yml +++ b/site.yml @@ -1,7 +1,11 @@ --- -- name: Despliegue Alicante Core V3 - hosts: core_group +- name: Desplegar Alicante Core V3.3 + hosts: core become: yes + roles: - common + - postgresql_native + - dolibarr_native - core + - core_setup_automation