diff --git a/alicante-v4.1-backup-20251210.tar.gz b/alicante-v4.1-backup-20251210.tar.gz
new file mode 100644
index 0000000..2076164
Binary files /dev/null and b/alicante-v4.1-backup-20251210.tar.gz differ
diff --git a/ansible.cfg b/ansible.cfg
new file mode 100644
index 0000000..ebde697
--- /dev/null
+++ b/ansible.cfg
@@ -0,0 +1,12 @@
+[defaults]
+inventory = inventory/hosts
+roles_path = roles
+host_key_checking = False
+retry_files_enabled = False
+stdout_callback = yaml
+
+[privilege_escalation]
+become = True
+become_method = sudo
+become_user = root
+become_ask_pass = False
diff --git a/group_vars/all.yml b/group_vars/all.yml
index 2fae967..a7576c9 100644
--- a/group_vars/all.yml
+++ b/group_vars/all.yml
@@ -1,54 +1,55 @@
---
+# Alicante Core V4.1 - Configuración Global
+
+# IPs
+core_ip: "10.10.10.104"
+dcc_ip: "10.10.10.101"
+
+# Credenciales
+core_user: "CORE"
+core_email: "ANT1NONAME@DISROOT.ORG"
+core_password: "coreALICANTE@2026"
+
+# Rutas
+data_root: "/DATA/VOLUMENES"
+docker_root: "/opt/services"
+
+# PHP Multiversión
+php_versions:
+ - "8.1"
+ - "8.2"
+ - "8.3"
+
+# Timezone
timezone: "Europe/Madrid"
-# Contraseñas Maestras (Se usan para configurar las DBs internas de cada stack)
-global_db_pass: "RootSecret123"
-global_redis_pass: "RedisSecret123"
-authentik_secret: "AlicanteAuthSecret2025_ChangeMe"
+# Puertos (Mantenidos de V4)
+ports:
+ dolibarr: 8080
+ nextcloud: 8088
+ joomla: 8090
+ teable: 3000
+ activepieces: 8081
+ wikijs: 6875
+ metabase: 3001
+ gotenberg: 3002
+ dockge: 5001
+ leantime: 8085
+ vaultwarden: 8812
+ pretix: 8095
+ ontime: 4000
+ opensign: 8086
+ beszel: 8177
+ webmin: 10000
-sysadmin_email: "admin@alicante.local"
-global_db_root_pass: "RootSecret123"
-global_db_app_pass: "AppSecret123"
-global_redis_pass: "RedisSecret123"
-authentik_secret: "GenerarStringLargoAleatorio123456"
-authentik_pg_pass: "AuthDBSecret123"
-pg_version: "16"
+# URLs de descarga - VERSIONES MÁS RECIENTES
+download_urls:
+ nextcloud: "https://download.nextcloud.com/server/releases/nextcloud-31.0.0.tar.bz2"
+ joomla: "https://github.com/joomla/joomla-cms/releases/download/6.0.0/Joomla_6.0.0-Stable-Full_Package.zip"
+ dolibarr: "https://github.com/Dolibarr/dolibarr/archive/refs/tags/22.0.1.tar.gz"
-# ============================================================================
-# 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"
+# Versiones
+versions:
+ nextcloud: "31.0"
+ joomla: "6.0"
+ dolibarr: "22.0"
diff --git a/inventory b/inventory
deleted file mode 100644
index 0ee8966..0000000
--- a/inventory
+++ /dev/null
@@ -1,5 +0,0 @@
-[core]
-10.10.10.104 ansible_user=root ansible_connection=ssh
-
-[all:vars]
-ansible_python_interpreter=/usr/bin/python3
diff --git a/inventory/hosts b/inventory/hosts
new file mode 100644
index 0000000..382d20c
--- /dev/null
+++ b/inventory/hosts
@@ -0,0 +1,5 @@
+[core]
+10.10.10.104 ansible_user=root ansible_ssh_private_key_file=~/.ssh/alicante_key
+
+[dcc]
+localhost ansible_connection=local
diff --git a/inventory/hosts.yml b/inventory/hosts.yml
new file mode 100644
index 0000000..b62b614
--- /dev/null
+++ b/inventory/hosts.yml
@@ -0,0 +1,16 @@
+---
+all:
+ children:
+ alicante:
+ hosts:
+ alicante-core:
+ ansible_host: 10.10.10.104
+ ansible_user: root
+ ansible_python_interpreter: /usr/bin/python3
+
+ dcc_servers:
+ hosts:
+ dcc:
+ ansible_host: 10.10.10.101
+ ansible_user: root
+ ansible_connection: local
diff --git a/playbooks/deploy_v4_1.yml b/playbooks/deploy_v4_1.yml
new file mode 100644
index 0000000..2487418
--- /dev/null
+++ b/playbooks/deploy_v4_1.yml
@@ -0,0 +1,32 @@
+---
+- name: Alicante Core V4 -> V4.1 Actualización
+ hosts: core
+ become: yes
+ vars_files:
+ - ../group_vars/all.yml
+
+ pre_tasks:
+ - name: Mostrar información de actualización
+ debug:
+ msg: "Actualizando CORE {{ core_ip }} a V4.1 - Híbrido LAMP+Docker"
+
+ roles:
+ - base_system
+ - webmin_lamp
+ - docker_base
+
+ post_tasks:
+ - name: Resumen de servicios instalados
+ debug:
+ msg: |
+ ✅ V4.1 Base instalada:
+ - Webmin: http://{{ core_ip }}:{{ ports.webmin }}
+ - PHP: 8.1, 8.2, 8.3 instalados
+ - MariaDB + PostgreSQL + Redis activos
+ - Docker + Dockge: http://{{ core_ip }}:{{ ports.dockge }}
+
+ ⚠️ Nota: Webmin, MariaDB y PostgreSQL ya estaban instalados
+
+ Próximos pasos:
+ - Desplegar apps nativas (Joomla, Dolibarr, Nextcloud)
+ - Desplegar apps Docker (Teable, Pretix, etc.)
diff --git a/playbooks/deploy_v4_1_full.yml b/playbooks/deploy_v4_1_full.yml
new file mode 100644
index 0000000..b1bc62b
--- /dev/null
+++ b/playbooks/deploy_v4_1_full.yml
@@ -0,0 +1,53 @@
+---
+- name: Alicante Core V4.1 - Despliegue Completo
+ hosts: core
+ become: yes
+ vars_files:
+ - ../group_vars/all.yml
+
+ pre_tasks:
+ - name: Información del despliegue
+ debug:
+ msg: |
+ 🚀 Desplegando Alicante Core V4.1 COMPLETO
+ 📍 Server: {{ core_ip }}
+ 🔧 Apps Nativas: Nextcloud, Joomla, Dolibarr
+ 🐳 Apps Docker: Teable, Wiki.js, Leantime, Vaultwarden, Metabase, Gotenberg, Ontime
+
+ roles:
+ - base_system
+ - webmin_lamp
+ - docker_base
+ - app_nextcloud_native
+ - app_joomla_native
+ - app_dolibarr_native
+ - apps_docker
+
+ post_tasks:
+ - name: Resumen Final
+ debug:
+ msg: |
+ ✅ ALICANTE CORE V4.1 DESPLEGADO COMPLETAMENTE
+
+ 📱 APPS NATIVAS:
+ - Nextcloud: http://{{ core_ip }}:{{ ports.nextcloud }}
+ - Joomla: http://{{ core_ip }}:{{ ports.joomla }}
+ - Dolibarr: http://{{ core_ip }}:{{ ports.dolibarr }}
+
+ 🐳 APPS DOCKER:
+ - Teable: http://{{ core_ip }}:{{ ports.teable }}
+ - Wiki.js: http://{{ core_ip }}:{{ ports.wikijs }}
+ - Leantime: http://{{ core_ip }}:{{ ports.leantime }}
+ - Vaultwarden: http://{{ core_ip }}:{{ ports.vaultwarden }}
+ - Metabase: http://{{ core_ip }}:{{ ports.metabase }}
+ - Gotenberg: http://{{ core_ip }}:{{ ports.gotenberg }}
+ - Ontime: http://{{ core_ip }}:{{ ports.ontime }}
+ - Dockge: http://{{ core_ip }}:{{ ports.dockge }}
+
+ 🔧 ADMINISTRACIÓN:
+ - Webmin: http://{{ core_ip }}:{{ ports.webmin }}
+
+ 📝 CREDENCIALES:
+ - Usuario: {{ core_user }}
+ - Email: {{ core_email }}
+ - Password: {{ core_password }}
diff --git a/roles/app_dolibarr_native/handlers/main.yml b/roles/app_dolibarr_native/handlers/main.yml
new file mode 100644
index 0000000..670471f
--- /dev/null
+++ b/roles/app_dolibarr_native/handlers/main.yml
@@ -0,0 +1,5 @@
+---
+- name: restart apache2
+ service:
+ name: apache2
+ state: restarted
diff --git a/roles/app_dolibarr_native/tasks/main.yml b/roles/app_dolibarr_native/tasks/main.yml
new file mode 100644
index 0000000..cc038b5
--- /dev/null
+++ b/roles/app_dolibarr_native/tasks/main.yml
@@ -0,0 +1,72 @@
+---
+- name: Verificar si Dolibarr ya existe
+ stat:
+ path: /var/www/html/dolibarr
+ register: dolibarr_exists
+
+- name: Crear base de datos MariaDB para Dolibarr
+ mysql_db:
+ name: dolibarr
+ state: present
+ login_unix_socket: /run/mysqld/mysqld.sock
+ when: not dolibarr_exists.stat.exists
+
+- name: Crear usuario MariaDB para Dolibarr
+ mysql_user:
+ name: dolibarr
+ password: "{{ core_password }}"
+ priv: 'dolibarr.*:ALL'
+ state: present
+ login_unix_socket: /run/mysqld/mysqld.sock
+ when: not dolibarr_exists.stat.exists
+
+- name: Descargar Dolibarr 22.0
+ get_url:
+ url: "{{ download_urls.dolibarr }}"
+ dest: /tmp/dolibarr-22.0.tar.gz
+ when: not dolibarr_exists.stat.exists
+
+- name: Extraer Dolibarr
+ unarchive:
+ src: /tmp/dolibarr-22.0.tar.gz
+ dest: /tmp/
+ remote_src: yes
+ when: not dolibarr_exists.stat.exists
+
+- name: Mover Dolibarr a /var/www/html
+ command: mv /tmp/dolibarr-22.0.1 /var/www/html/dolibarr
+ args:
+ creates: /var/www/html/dolibarr
+ when: not dolibarr_exists.stat.exists
+
+- name: Establecer permisos Dolibarr
+ file:
+ path: /var/www/html/dolibarr
+ owner: www-data
+ group: www-data
+ recurse: yes
+
+- name: Crear directorio documentos Dolibarr
+ file:
+ path: "{{ data_root }}/dolibarr"
+ state: directory
+ owner: www-data
+ group: www-data
+ mode: '0750'
+
+- name: Configurar VirtualHost Dolibarr
+ template:
+ src: dolibarr.conf.j2
+ dest: /etc/apache2/sites-available/dolibarr.conf
+ notify: restart apache2
+
+- name: Habilitar sitio Dolibarr
+ command: a2ensite dolibarr
+ args:
+ creates: /etc/apache2/sites-enabled/dolibarr.conf
+ notify: restart apache2
+
+- name: Informar si Dolibarr ya existe
+ debug:
+ msg: "Dolibarr ya está instalado, saltando descarga"
+ when: dolibarr_exists.stat.exists
diff --git a/roles/app_dolibarr_native/templates/dolibarr.conf.j2 b/roles/app_dolibarr_native/templates/dolibarr.conf.j2
new file mode 100644
index 0000000..ef1e68f
--- /dev/null
+++ b/roles/app_dolibarr_native/templates/dolibarr.conf.j2
@@ -0,0 +1,13 @@
+
+ DocumentRoot /var/www/html/dolibarr/htdocs
+
+
+ Require all granted
+ AllowOverride All
+ Options FollowSymLinks MultiViews
+
+
+
+ SetHandler "proxy:unix:/run/php/php8.2-fpm.sock|fcgi://localhost"
+
+
diff --git a/roles/app_joomla_native/handlers/main.yml b/roles/app_joomla_native/handlers/main.yml
new file mode 100644
index 0000000..670471f
--- /dev/null
+++ b/roles/app_joomla_native/handlers/main.yml
@@ -0,0 +1,5 @@
+---
+- name: restart apache2
+ service:
+ name: apache2
+ state: restarted
diff --git a/roles/app_joomla_native/tasks/main.yml b/roles/app_joomla_native/tasks/main.yml
new file mode 100644
index 0000000..62975bf
--- /dev/null
+++ b/roles/app_joomla_native/tasks/main.yml
@@ -0,0 +1,76 @@
+---
+- name: Verificar si Joomla ya existe
+ stat:
+ path: /var/www/html/joomla/configuration.php
+ register: joomla_exists
+
+- name: Crear base de datos MariaDB para Joomla
+ mysql_db:
+ name: joomla
+ state: present
+ login_unix_socket: /run/mysqld/mysqld.sock
+ when: not joomla_exists.stat.exists
+
+- name: Crear usuario MariaDB para Joomla
+ mysql_user:
+ name: joomla
+ password: "{{ core_password }}"
+ priv: 'joomla.*:ALL'
+ state: present
+ login_unix_socket: /run/mysqld/mysqld.sock
+ when: not joomla_exists.stat.exists
+
+- name: Crear directorio Joomla
+ file:
+ path: /var/www/html/joomla
+ state: directory
+ owner: www-data
+ group: www-data
+
+- name: Instalar unzip si no existe
+ apt:
+ name: unzip
+ state: present
+ when: not joomla_exists.stat.exists
+
+- name: Descargar Joomla 6.0 desde GitHub
+ get_url:
+ url: "{{ download_urls.joomla }}"
+ dest: /tmp/joomla-6.0.zip
+ timeout: 120
+ force: yes
+ when: not joomla_exists.stat.exists
+
+- name: Extraer Joomla
+ unarchive:
+ src: /tmp/joomla-6.0.zip
+ dest: /var/www/html/joomla/
+ remote_src: yes
+ owner: www-data
+ group: www-data
+ when: not joomla_exists.stat.exists
+
+- name: Establecer permisos Joomla
+ file:
+ path: /var/www/html/joomla
+ owner: www-data
+ group: www-data
+ recurse: yes
+ mode: '0755'
+
+- name: Configurar VirtualHost Joomla
+ template:
+ src: joomla.conf.j2
+ dest: /etc/apache2/sites-available/joomla.conf
+ notify: restart apache2
+
+- name: Habilitar sitio Joomla
+ command: a2ensite joomla
+ args:
+ creates: /etc/apache2/sites-enabled/joomla.conf
+ notify: restart apache2
+
+- name: Informar si Joomla ya existe
+ debug:
+ msg: "Joomla ya está instalado, saltando descarga"
+ when: joomla_exists.stat.exists
diff --git a/roles/app_joomla_native/templates/joomla.conf.j2 b/roles/app_joomla_native/templates/joomla.conf.j2
new file mode 100644
index 0000000..33342b1
--- /dev/null
+++ b/roles/app_joomla_native/templates/joomla.conf.j2
@@ -0,0 +1,13 @@
+
+ DocumentRoot /var/www/html/joomla
+
+
+ Require all granted
+ AllowOverride All
+ Options FollowSymLinks MultiViews
+
+
+
+ SetHandler "proxy:unix:/run/php/php8.3-fpm.sock|fcgi://localhost"
+
+
diff --git a/roles/app_nextcloud_native/handlers/main.yml b/roles/app_nextcloud_native/handlers/main.yml
new file mode 100644
index 0000000..670471f
--- /dev/null
+++ b/roles/app_nextcloud_native/handlers/main.yml
@@ -0,0 +1,5 @@
+---
+- name: restart apache2
+ service:
+ name: apache2
+ state: restarted
diff --git a/roles/app_nextcloud_native/tasks/main.yml b/roles/app_nextcloud_native/tasks/main.yml
new file mode 100644
index 0000000..36d0b47
--- /dev/null
+++ b/roles/app_nextcloud_native/tasks/main.yml
@@ -0,0 +1,74 @@
+---
+- name: Verificar si Nextcloud ya existe
+ stat:
+ path: /var/www/html/nextcloud
+ register: nextcloud_exists
+
+- name: Crear base de datos PostgreSQL para Nextcloud
+ postgresql_db:
+ name: nextcloud
+ state: present
+ become_user: postgres
+ when: not nextcloud_exists.stat.exists
+
+- name: Crear usuario PostgreSQL para Nextcloud
+ postgresql_user:
+ name: nextcloud
+ password: "{{ core_password }}"
+ state: present
+ become_user: postgres
+ when: not nextcloud_exists.stat.exists
+
+- name: Otorgar privilegios al usuario Nextcloud
+ postgresql_privs:
+ database: nextcloud
+ roles: nextcloud
+ privs: ALL
+ type: database
+ become_user: postgres
+ when: not nextcloud_exists.stat.exists
+
+- name: Descargar Nextcloud 31
+ get_url:
+ url: "{{ download_urls.nextcloud }}"
+ dest: /tmp/nextcloud-31.tar.bz2
+ when: not nextcloud_exists.stat.exists
+
+- name: Extraer Nextcloud
+ unarchive:
+ src: /tmp/nextcloud-31.tar.bz2
+ dest: /var/www/html/
+ remote_src: yes
+ when: not nextcloud_exists.stat.exists
+
+- name: Establecer permisos Nextcloud
+ file:
+ path: /var/www/html/nextcloud
+ owner: www-data
+ group: www-data
+ recurse: yes
+
+- name: Crear directorio de datos Nextcloud
+ file:
+ path: "{{ data_root }}/nextcloud"
+ state: directory
+ owner: www-data
+ group: www-data
+ mode: '0750'
+
+- name: Configurar VirtualHost Nextcloud
+ template:
+ src: nextcloud.conf.j2
+ dest: /etc/apache2/sites-available/nextcloud.conf
+ notify: restart apache2
+
+- name: Habilitar sitio Nextcloud
+ command: a2ensite nextcloud
+ args:
+ creates: /etc/apache2/sites-enabled/nextcloud.conf
+ notify: restart apache2
+
+- name: Informar si Nextcloud ya existe
+ debug:
+ msg: "Nextcloud ya está instalado, saltando descarga"
+ when: nextcloud_exists.stat.exists
diff --git a/roles/app_nextcloud_native/templates/nextcloud.conf.j2 b/roles/app_nextcloud_native/templates/nextcloud.conf.j2
new file mode 100644
index 0000000..9c4edb4
--- /dev/null
+++ b/roles/app_nextcloud_native/templates/nextcloud.conf.j2
@@ -0,0 +1,17 @@
+
+ DocumentRoot /var/www/html/nextcloud
+
+
+ Require all granted
+ AllowOverride All
+ Options FollowSymLinks MultiViews
+
+
+ Dav off
+
+
+
+
+ SetHandler "proxy:unix:/run/php/php8.3-fpm.sock|fcgi://localhost"
+
+
diff --git a/roles/apps_docker/tasks/main.yml b/roles/apps_docker/tasks/main.yml
new file mode 100644
index 0000000..5740f4b
--- /dev/null
+++ b/roles/apps_docker/tasks/main.yml
@@ -0,0 +1,203 @@
+---
+# Crear todos los directorios de datos
+- name: Crear directorios para apps Docker
+ file:
+ path: "{{ data_root }}/{{ item }}"
+ state: directory
+ mode: '0755'
+ loop:
+ - teable
+ - teable/db
+ - wikijs
+ - wikijs/db
+ - activepieces
+ - activepieces/db
+ - leantime
+ - leantime/db
+ - vaultwarden
+ - pretix
+ - pretix/db
+ - pretix/redis
+ - ontime
+ - opensign
+ - opensign/db
+ - metabase
+ - gotenberg
+
+# TEABLE
+- name: Desplegar Teable Stack
+ community.docker.docker_compose_v2:
+ project_name: teable
+ definition:
+ version: '3.8'
+ services:
+ teable-db:
+ image: postgres:15-alpine
+ restart: unless-stopped
+ environment:
+ POSTGRES_DB: teable
+ POSTGRES_USER: teable
+ POSTGRES_PASSWORD: "{{ core_password }}"
+ volumes:
+ - "{{ data_root }}/teable/db:/var/lib/postgresql/data"
+ networks:
+ - alicante-net
+
+ teable:
+ image: ghcr.io/teableio/teable:latest
+ restart: unless-stopped
+ ports:
+ - "{{ ports.teable }}:3000"
+ environment:
+ DATABASE_URL: "postgresql://teable:{{ core_password }}@teable-db:5432/teable"
+ REDIS_HOST: teable-redis
+ REDIS_PORT: 6379
+ PUBLIC_ORIGIN: "http://{{ core_ip }}:{{ ports.teable }}"
+ volumes:
+ - "{{ data_root }}/teable:/app/.assets"
+ networks:
+ - alicante-net
+ depends_on:
+ - teable-db
+ - teable-redis
+
+ teable-redis:
+ image: redis:7-alpine
+ restart: unless-stopped
+ networks:
+ - alicante-net
+
+ networks:
+ alicante-net:
+ external: true
+
+# WIKI.JS
+- name: Desplegar Wiki.js Stack
+ community.docker.docker_compose_v2:
+ project_name: wikijs
+ definition:
+ version: '3.8'
+ services:
+ wikijs-db:
+ image: postgres:15-alpine
+ restart: unless-stopped
+ environment:
+ POSTGRES_DB: wikijs
+ POSTGRES_USER: wikijs
+ POSTGRES_PASSWORD: "{{ core_password }}"
+ volumes:
+ - "{{ data_root }}/wikijs/db:/var/lib/postgresql/data"
+ networks:
+ - alicante-net
+
+ wikijs:
+ image: ghcr.io/requarks/wiki:2
+ restart: unless-stopped
+ ports:
+ - "{{ ports.wikijs }}:3000"
+ environment:
+ DB_TYPE: postgres
+ DB_HOST: wikijs-db
+ DB_PORT: 5432
+ DB_USER: wikijs
+ DB_PASS: "{{ core_password }}"
+ DB_NAME: wikijs
+ networks:
+ - alicante-net
+ depends_on:
+ - wikijs-db
+
+ networks:
+ alicante-net:
+ external: true
+
+# GOTENBERG
+- name: Desplegar Gotenberg
+ community.docker.docker_container:
+ name: gotenberg
+ image: gotenberg/gotenberg:8
+ restart_policy: unless-stopped
+ ports:
+ - "{{ ports.gotenberg }}:3000"
+ networks:
+ - name: alicante-net
+
+# METABASE
+- name: Desplegar Metabase
+ community.docker.docker_container:
+ name: metabase
+ image: metabase/metabase:latest
+ restart_policy: unless-stopped
+ ports:
+ - "{{ ports.metabase }}:3000"
+ volumes:
+ - "{{ data_root }}/metabase:/metabase-data"
+ env:
+ MB_DB_FILE: /metabase-data/metabase.db
+ networks:
+ - name: alicante-net
+
+# LEANTIME
+- name: Desplegar Leantime Stack
+ community.docker.docker_compose_v2:
+ project_name: leantime
+ definition:
+ version: '3.8'
+ services:
+ leantime-db:
+ image: mysql:8
+ restart: unless-stopped
+ environment:
+ MYSQL_ROOT_PASSWORD: "{{ core_password }}"
+ MYSQL_DATABASE: leantime
+ MYSQL_USER: leantime
+ MYSQL_PASSWORD: "{{ core_password }}"
+ volumes:
+ - "{{ data_root }}/leantime/db:/var/lib/mysql"
+ networks:
+ - alicante-net
+
+ leantime:
+ image: leantime/leantime:latest
+ restart: unless-stopped
+ ports:
+ - "{{ ports.leantime }}:80"
+ environment:
+ LEAN_DB_HOST: leantime-db
+ LEAN_DB_USER: leantime
+ LEAN_DB_PASSWORD: "{{ core_password }}"
+ LEAN_DB_DATABASE: leantime
+ networks:
+ - alicante-net
+ depends_on:
+ - leantime-db
+
+ networks:
+ alicante-net:
+ external: true
+
+# VAULTWARDEN
+- name: Desplegar Vaultwarden
+ community.docker.docker_container:
+ name: vaultwarden
+ image: vaultwarden/server:latest
+ restart_policy: unless-stopped
+ ports:
+ - "{{ ports.vaultwarden }}:80"
+ volumes:
+ - "{{ data_root }}/vaultwarden:/data"
+ networks:
+ - name: alicante-net
+
+# ONTIME
+- name: Desplegar Ontime
+ community.docker.docker_container:
+ name: ontime
+ image: getontime/ontime:latest
+ restart_policy: unless-stopped
+ ports:
+ - "{{ ports.ontime }}:4001"
+ volumes:
+ - "{{ data_root }}/ontime:/data"
+ networks:
+ - name: alicante-net
diff --git a/roles/base_system/tasks/main.yml b/roles/base_system/tasks/main.yml
new file mode 100644
index 0000000..3e525fc
--- /dev/null
+++ b/roles/base_system/tasks/main.yml
@@ -0,0 +1,31 @@
+---
+- name: Actualizar sistema base
+ apt:
+ update_cache: yes
+ upgrade: dist
+
+- name: Instalar paquetes básicos
+ apt:
+ name:
+ - curl
+ - wget
+ - git
+ - htop
+ - vim
+ - unzip
+ - acl
+ - gnupg2
+ - ca-certificates
+ - apt-transport-https
+ state: present
+
+- name: Crear directorios de datos
+ file:
+ path: "{{ item }}"
+ state: directory
+ mode: '0755'
+ loop:
+ - "{{ data_root }}"
+ - "{{ docker_root }}"
+ - "{{ data_root }}/backups"
+ - /var/www/html
diff --git a/roles/docker_base/tasks/main.yml b/roles/docker_base/tasks/main.yml
new file mode 100644
index 0000000..66be7d8
--- /dev/null
+++ b/roles/docker_base/tasks/main.yml
@@ -0,0 +1,60 @@
+---
+- name: Instalar dependencias Python para Docker
+ apt:
+ name:
+ - python3-requests
+ - python3-docker
+ state: present
+
+- name: Verificar si Docker está instalado
+ stat:
+ path: /usr/bin/docker
+ register: docker_exists
+
+- name: Instalar Docker
+ shell: curl -fsSL https://get.docker.com | sh
+ when: not docker_exists.stat.exists
+
+- name: Instalar Docker Compose v2
+ shell: |
+ mkdir -p /usr/local/lib/docker/cli-plugins
+ curl -SL https://github.com/docker/compose/releases/download/v2.24.5/docker-compose-linux-x86_64 -o /usr/local/lib/docker/cli-plugins/docker-compose
+ chmod +x /usr/local/lib/docker/cli-plugins/docker-compose
+ args:
+ creates: /usr/local/lib/docker/cli-plugins/docker-compose
+
+- name: Crear red Docker compartida
+ community.docker.docker_network:
+ name: alicante-net
+ driver: bridge
+
+- name: Crear directorio para Dockge
+ file:
+ path: "{{ docker_root }}/dockge"
+ state: directory
+
+- name: Verificar si Dockge ya existe
+ community.docker.docker_container_info:
+ name: dockge
+ register: dockge_info
+ ignore_errors: yes
+
+- name: Desplegar Dockge (solo si no existe)
+ community.docker.docker_container:
+ name: dockge
+ image: louislam/dockge:1
+ restart_policy: unless-stopped
+ ports:
+ - "{{ ports.dockge }}:5001"
+ volumes:
+ - /var/run/docker.sock:/var/run/docker.sock
+ - "{{ data_root }}/dockge:/app/data"
+ - "{{ docker_root }}:/opt/stacks"
+ env:
+ TZ: "{{ timezone }}"
+ when: not dockge_info.exists
+
+- name: Informar si Dockge ya existe
+ debug:
+ msg: "Dockge ya está corriendo en el puerto {{ ports.dockge }}"
+ when: dockge_info.exists
diff --git a/roles/webmin_lamp/handlers/main.yml b/roles/webmin_lamp/handlers/main.yml
new file mode 100644
index 0000000..670471f
--- /dev/null
+++ b/roles/webmin_lamp/handlers/main.yml
@@ -0,0 +1,5 @@
+---
+- name: restart apache2
+ service:
+ name: apache2
+ state: restarted
diff --git a/roles/webmin_lamp/tasks/main.yml b/roles/webmin_lamp/tasks/main.yml
new file mode 100644
index 0000000..7ef508b
--- /dev/null
+++ b/roles/webmin_lamp/tasks/main.yml
@@ -0,0 +1,95 @@
+---
+- name: Añadir repositorio SURY para PHP multiversión
+ shell: |
+ curl -sSLo /usr/share/keyrings/deb.sury.org-php.gpg https://packages.sury.org/php/apt.gpg
+ echo "deb [signed-by=/usr/share/keyrings/deb.sury.org-php.gpg] https://packages.sury.org/php/ $(lsb_release -sc) main" > /etc/apt/sources.list.d/php.list
+ apt-get update
+ args:
+ creates: /etc/apt/sources.list.d/php.list
+
+- name: Instalar Apache2
+ apt:
+ name:
+ - apache2
+ - libapache2-mod-fcgid
+ state: present
+
+- name: Instalar PHP 8.1, 8.2 y 8.3
+ apt:
+ name:
+ - php8.1
+ - php8.1-fpm
+ - php8.1-mysql
+ - php8.1-pgsql
+ - php8.1-gd
+ - php8.1-mbstring
+ - php8.1-xml
+ - php8.1-zip
+ - php8.1-intl
+ - php8.1-curl
+ - php8.2
+ - php8.2-fpm
+ - php8.2-mysql
+ - php8.2-pgsql
+ - php8.2-gd
+ - php8.2-mbstring
+ - php8.2-xml
+ - php8.2-zip
+ - php8.2-intl
+ - php8.2-curl
+ - php8.3
+ - php8.3-fpm
+ - php8.3-mysql
+ - php8.3-pgsql
+ - php8.3-gd
+ - php8.3-mbstring
+ - php8.3-xml
+ - php8.3-zip
+ - php8.3-intl
+ - php8.3-curl
+ - php8.3-apcu
+ - php8.3-redis
+ state: present
+
+- name: Instalar dependencias Python para Ansible
+ apt:
+ name:
+ - python3-psycopg2
+ - python3-pymysql
+ state: present
+
+- name: Habilitar módulos Apache necesarios
+ apache2_module:
+ name: "{{ item }}"
+ state: present
+ loop:
+ - rewrite
+ - proxy
+ - proxy_fcgi
+ - setenvif
+ notify: restart apache2
+
+- name: Instalar Redis Server
+ apt:
+ name: redis-server
+ state: present
+
+- name: Configurar puertos adicionales en Apache
+ lineinfile:
+ path: /etc/apache2/ports.conf
+ line: "Listen {{ item }}"
+ create: yes
+ loop:
+ - "{{ ports.nextcloud }}"
+ - "{{ ports.joomla }}"
+ - "{{ ports.dolibarr }}"
+ notify: restart apache2
+
+- name: Iniciar y habilitar servicios
+ service:
+ name: "{{ item }}"
+ state: started
+ enabled: yes
+ loop:
+ - apache2
+ - redis-server