Compare commits

...

4 Commits

31 changed files with 1287 additions and 122 deletions

Binary file not shown.

12
ansible.cfg Normal file
View File

@ -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

View File

@ -1,24 +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.2 CONFIGURATION ---
# Carbone (Stack Docs)
core_ip: "10.10.10.104"
a412b12 (Fix: V3.2 upgrade paths)
# Activepieces Configuration
ap_encryption_key: "ff7d959b67bc4b31752d51c3db3bbb5b"
ap_jwt_secret: "eW4o2aZs0yNT3Z9kSS6IYDLtMtJ/Uh1acV0HIYOfrtI="
# Versiones
versions:
nextcloud: "31.0"
joomla: "6.0"
dolibarr: "22.0"

View File

@ -1,2 +0,0 @@
[core_group]
10.10.10.104 ansible_user=root

5
inventory/hosts Normal file
View File

@ -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

16
inventory/hosts.yml Normal file
View File

@ -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

32
playbooks/deploy_v4_1.yml Normal file
View File

@ -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.)

View File

@ -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 }}

View File

@ -0,0 +1,5 @@
---
- name: restart apache2
service:
name: apache2
state: restarted

View File

@ -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

View File

@ -0,0 +1,13 @@
<VirtualHost *:{{ ports.dolibarr }}>
DocumentRoot /var/www/html/dolibarr/htdocs
<Directory /var/www/html/dolibarr/htdocs/>
Require all granted
AllowOverride All
Options FollowSymLinks MultiViews
</Directory>
<FilesMatch \.php$>
SetHandler "proxy:unix:/run/php/php8.2-fpm.sock|fcgi://localhost"
</FilesMatch>
</VirtualHost>

View File

@ -0,0 +1,5 @@
---
- name: restart apache2
service:
name: apache2
state: restarted

View File

@ -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

View File

@ -0,0 +1,13 @@
<VirtualHost *:{{ ports.joomla }}>
DocumentRoot /var/www/html/joomla
<Directory /var/www/html/joomla/>
Require all granted
AllowOverride All
Options FollowSymLinks MultiViews
</Directory>
<FilesMatch \.php$>
SetHandler "proxy:unix:/run/php/php8.3-fpm.sock|fcgi://localhost"
</FilesMatch>
</VirtualHost>

View File

@ -0,0 +1,5 @@
---
- name: restart apache2
service:
name: apache2
state: restarted

View File

@ -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

View File

@ -0,0 +1,17 @@
<VirtualHost *:{{ ports.nextcloud }}>
DocumentRoot /var/www/html/nextcloud
<Directory /var/www/html/nextcloud/>
Require all granted
AllowOverride All
Options FollowSymLinks MultiViews
<IfModule mod_dav.c>
Dav off
</IfModule>
</Directory>
<FilesMatch \.php$>
SetHandler "proxy:unix:/run/php/php8.3-fpm.sock|fcgi://localhost"
</FilesMatch>
</VirtualHost>

View File

@ -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

View File

@ -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

View File

@ -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:

View File

@ -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:

View File

@ -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.
============================================================

View File

@ -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

View File

@ -0,0 +1,5 @@
---
- name: restart apache
systemd:
name: apache2
state: restarted

View File

@ -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: |
<VirtualHost *:8080>
ServerAdmin admin@localhost
DocumentRoot /var/www/dolibarr/htdocs
<Directory /var/www/dolibarr/htdocs>
Options -Indexes +FollowSymLinks
AllowOverride All
Require all granted
</Directory>
<Directory /var/www/dolibarr/documents>
Require all denied
</Directory>
ErrorLog ${APACHE_LOG_DIR}/dolibarr-error.log
CustomLog ${APACHE_LOG_DIR}/dolibarr-access.log combined
</VirtualHost>
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"

View File

@ -0,0 +1,24 @@
<?php
// Auto-generated by Ansible - Alicante Core V3.3
$dolibarr_main_url_root='http://{{ dolibarr_domain }}';
$dolibarr_main_document_root='/var/www/dolibarr/htdocs';
$dolibarr_main_url_root_alt='/custom';
$dolibarr_main_document_root_alt='/var/www/dolibarr/htdocs/custom';
$dolibarr_main_data_root='/var/www/dolibarr/documents';
$dolibarr_main_db_host='localhost';
$dolibarr_main_db_port='5432';
$dolibarr_main_db_name='{{ core_db_credentials.dolibarr_db_name }}';
$dolibarr_main_db_prefix='llx_';
$dolibarr_main_db_user='{{ core_db_credentials.dolibarr_db_user }}';
$dolibarr_main_db_pass='{{ core_db_credentials.dolibarr_db_pass }}';
$dolibarr_main_db_type='pgsql';
$dolibarr_main_db_character_set='utf8';
$dolibarr_main_db_collation='utf8_unicode_ci';
$dolibarr_main_authentication='dolibarr';
$dolibarr_main_prod='1';
$dolibarr_main_force_https='0';
$dolibarr_main_restrict_os_commands='mysqldump, mysql, pg_dump, pgsql';
$dolibarr_nocsrfcheck='0';
$dolibarr_main_cookie_cryptkey='{{ lookup("password", "/dev/null chars=ascii_letters,digits length=32") }}';
$dolibarr_mailing_limit_sendbyweb='0';
?>

View File

@ -0,0 +1,5 @@
---
- name: restart postgresql
systemd:
name: postgresql
state: restarted

View File

@ -0,0 +1,106 @@
---
- name: Instalar PostgreSQL (versión disponible en Debian)
apt:
name:
- postgresql
- postgresql-contrib
- python3-psycopg2
state: present
update_cache: yes
- name: Detectar versión de PostgreSQL instalada
shell: "ls -1 /etc/postgresql/ | head -1"
register: pg_version
changed_when: false
- name: Configurar PostgreSQL para escuchar en localhost
lineinfile:
path: "/etc/postgresql/{{ pg_version.stdout }}/main/postgresql.conf"
regexp: '^#?listen_addresses'
line: "listen_addresses = 'localhost'"
notify: restart postgresql
- name: Permitir conexiones locales con password
lineinfile:
path: "/etc/postgresql/{{ pg_version.stdout }}/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"

View File

@ -0,0 +1,5 @@
---
- name: restart apache2
service:
name: apache2
state: restarted

View File

@ -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

View File

@ -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