Alicante Core V3 - Architecture

This commit is contained in:
SysAdmin DCC 2025-12-01 21:06:16 +00:00
parent 76fd8fd408
commit 77461d1401
14 changed files with 186 additions and 239 deletions

View File

@ -1,9 +1,6 @@
---
timezone: "Europe/Madrid"
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"
# 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"

2
inventory Normal file
View File

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

View File

@ -3,31 +3,40 @@
apt:
update_cache: yes
upgrade: dist
environment:
DEBIAN_FRONTEND: noninteractive
- name: Instalar Dependencias Base
- name: Instalar Dependencias
apt:
name:
- curl
- git
- htop
- ufw
- ca-certificates
- gnupg
- sudo
- python3-pip
- python3-psycopg2
state: present
- name: Instalar Docker
shell: curl -fsSL https://get.docker.com | sh
- name: Instalar Docker (Oficial)
shell: |
if [ ! -f /usr/bin/docker ]; then
curl -fsSL https://get.docker.com | sh
fi
args:
creates: /usr/bin/docker
- name: Instalar Webmin
- name: Configurar Firewall UFW
shell: |
curl -o setup-repos.sh https://raw.githubusercontent.com/webmin/webmin/master/setup-repos.sh
sh setup-repos.sh --force
apt-get install webmin --install-recommends -y
args:
creates: /etc/webmin
environment:
DEBIAN_FRONTEND: noninteractive
ufw allow 22/tcp
ufw allow 10000/tcp # Webmin
ufw allow 9000/tcp # Authentik
ufw allow 9443/tcp # Authentik SSL
ufw allow 8080/tcp # Dolibarr
ufw allow 3000/tcp # Teable
ufw allow 8081/tcp # Activepieces
ufw allow 6875/tcp # Bookstack
ufw allow 3001/tcp # Metabase
ufw allow 7575/tcp # Homarr
ufw allow 5001/tcp # Dockge
ufw --force enable
ignore_errors: yes

View File

@ -1,39 +1,17 @@
---
- name: Crear Red Interna
community.docker.docker_network: name=alicante_net
- name: Crear directorios de Stacks
file: path=/opt/stacks/{{ item }} state=directory mode=0755
loop: ['security', 'business', 'docs', 'management']
- name: Crear directorios
file: path=/opt/stacks/{{ item }} state=directory
loop: ['infra-shared', 'business', 'docs', 'dashboard']
- name: Copiar Templates Docker Compose
template:
src: "{{ item }}-compose.j2"
dest: "/opt/stacks/{{ item }}/compose.yaml"
loop: ['security', 'business', 'docs', 'management']
- name: Desplegar Infra Shared
template: src=infra-shared-compose.j2 dest=/opt/stacks/infra-shared/compose.yaml
- name: Levantar Infra
community.docker.docker_compose_v2: project_src=/opt/stacks/infra-shared
- name: Esperar DB
command: docker exec postgres-core pg_isready
retries: 10
delay: 5
- name: Crear Bases de Datos
community.postgresql.postgresql_db:
name: "{{ item }}"
login_host: "{{ ansible_host }}"
login_password: "{{ global_db_root_pass }}"
port: 5432
loop: ['dolibarr', 'teable', 'activepieces', 'metabase', 'nextcloud']
- name: Configurar Negocio
template: src=apps-business-compose.j2 dest=/opt/stacks/business/compose.yaml
- name: Configurar Docs
template: src=apps-docs-compose.j2 dest=/opt/stacks/docs/compose.yaml
- name: Configurar Dashboard
template: src=dashboard-compose.j2 dest=/opt/stacks/dashboard/compose.yaml
- name: Levantar Todo
community.docker.docker_compose_v2: project_src=/opt/stacks/{{ item }}
loop: ['business', 'docs', 'dashboard']
- name: Levantar Stacks
community.docker.docker_compose_v2:
project_src: "/opt/stacks/{{ item }}"
state: present
pull: always
loop: ['security', 'business', 'docs', 'management']

View File

@ -1,38 +0,0 @@
services:
dolibarr:
image: upshift/dolibarr:latest
environment:
DOLI_DB_HOST: postgres-core
DOLI_DB_PASSWORD: {{ global_db_root_pass }}
DOLI_ADMIN_LOGIN: admin
DOLI_DB_TYPE: pgsql
networks:
- alicante_net
ports:
- "8080:80"
teable:
image: teableio/teable:latest
environment:
PRISMA_DATABASE_URL: "postgresql://postgres:{{ global_db_root_pass }}@postgres-core:5432/teable"
REDIS_URL: "redis://:{{ global_redis_pass }}@redis-core:6379/0"
networks:
- alicante_net
ports:
- "3000:3000"
activepieces:
image: activepieces/activepieces:latest
environment:
AP_POSTGRES_HOST: postgres-core
AP_POSTGRES_PASSWORD: {{ global_db_root_pass }}
AP_REDIS_HOST: redis-core
AP_REDIS_PASSWORD: {{ global_redis_pass }}
networks:
- alicante_net
ports:
- "8081:80"
networks:
alicante_net:
external: true

View File

@ -1,35 +0,0 @@
services:
metabase:
image: metabase/metabase:latest
environment:
MB_DB_TYPE: postgres
MB_DB_HOST: postgres-core
MB_DB_USER: postgres
MB_DB_PASS: {{ global_db_root_pass }}
MB_DB_DBNAME: metabase
networks:
- alicante_net
ports:
- "3001:3000"
bookstack:
image: lscr.io/linuxserver/bookstack:latest
environment:
DB_HOST: mariadb-core
DB_USER: root
DB_PASS: {{ global_db_root_pass }}
networks:
- alicante_net
ports:
- "6875:80"
gotenberg:
image: gotenberg/gotenberg:8
networks:
- alicante_net
# Gotenberg es una API, no suele necesitar puerto expuesto si se usa internamente,
# pero lo dejamos accesible por si acaso en el 3000 interno (o mapeado si quieres)
networks:
alicante_net:
external: true

View File

@ -0,0 +1,81 @@
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"
ports:
- "3000:3000"
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"
ports:
- "8081:80"
volumes:
pg_data:

View File

@ -0,0 +1,37 @@
services:
mariadb:
image: lscr.io/linuxserver/mariadb:latest
restart: always
environment:
MYSQL_ROOT_PASSWORD: {{ global_db_pass }}
MYSQL_DATABASE: bookstackapp
MYSQL_USER: bookstack
MYSQL_PASSWORD: BookStackPass
volumes:
- mysql_data:/config
bookstack:
image: lscr.io/linuxserver/bookstack:latest
depends_on:
- mariadb
environment:
APP_URL: http://{{ ansible_host }}:6875
DB_HOST: mariadb
DB_USER: bookstack
DB_PASS: BookStackPass
DB_DATABASE: bookstackapp
ports:
- "6875:80"
metabase:
image: metabase/metabase:latest
ports:
- "3001:3000"
gotenberg:
image: gotenberg/gotenberg:8
ports:
- "3002:3000"
volumes:
mysql_data:

View File

@ -1,34 +0,0 @@
services:
postgres:
image: postgres:{{ pg_version }}
container_name: postgres-core
environment:
POSTGRES_PASSWORD: {{ global_db_root_pass }}
ports:
- "5432:5432"
volumes:
- pg_data:/var/lib/postgresql/data
networks:
- alicante_net
redis:
image: redis:alpine
container_name: redis-core
command: redis-server --requirepass {{ global_redis_pass }}
networks:
- alicante_net
mariadb:
image: mariadb:10.6
container_name: mariadb-core
environment:
MYSQL_ROOT_PASSWORD: {{ global_db_root_pass }}
networks:
- alicante_net
networks:
alicante_net:
external: true
volumes:
pg_data:

View File

@ -3,8 +3,6 @@ services:
image: ghcr.io/ajnart/homarr:latest
volumes:
- /var/run/docker.sock:/var/run/docker.sock
networks:
- alicante_net
ports:
- "7575:7575"
@ -15,11 +13,5 @@ services:
- /opt/stacks:/opt/stacks
environment:
- DOCKGE_STACKS_DIR=/opt/stacks
networks:
- alicante_net
ports:
- "5001:5001"
networks:
alicante_net:
external: true

View File

@ -1,53 +1,58 @@
services:
postgresql:
image: docker.io/library/postgres:16-alpine
restart: unless-stopped
postgres:
image: postgres:16-alpine
restart: always
environment:
POSTGRES_PASSWORD: {{ authentik_pg_pass }}
POSTGRES_PASSWORD: {{ global_db_pass }}
POSTGRES_USER: authentik
POSTGRES_DB: authentik
volumes:
- database:/var/lib/postgresql/data
- db_data:/var/lib/postgresql/data
redis:
image: docker.io/library/redis:alpine
restart: unless-stopped
image: redis:alpine
restart: always
command: redis-server --requirepass {{ global_redis_pass }}
volumes:
- redis:/data
- redis_data:/data
server:
image: ghcr.io/goauthentik/server:2024.10
restart: unless-stopped
restart: always
command: server
environment:
AUTHENTIK_REDIS__HOST: redis
AUTHENTIK_POSTGRESQL__HOST: postgresql
AUTHENTIK_REDIS__PASSWORD: {{ global_redis_pass }}
AUTHENTIK_POSTGRESQL__HOST: postgres
AUTHENTIK_POSTGRESQL__USER: authentik
AUTHENTIK_POSTGRESQL__NAME: authentik
AUTHENTIK_POSTGRESQL__PASSWORD: {{ authentik_pg_pass }}
AUTHENTIK_POSTGRESQL__PASSWORD: {{ global_db_pass }}
AUTHENTIK_SECRET_KEY: {{ authentik_secret }}
AUTHENTIK_BOOTSTRAP_TIMEOUT: 300
ports:
- "9000:9000"
- "9443:9443"
depends_on:
- postgresql
- postgres
- redis
worker:
image: ghcr.io/goauthentik/server:2024.10
restart: unless-stopped
restart: always
command: worker
environment:
AUTHENTIK_REDIS__HOST: redis
AUTHENTIK_POSTGRESQL__HOST: postgresql
AUTHENTIK_REDIS__PASSWORD: {{ global_redis_pass }}
AUTHENTIK_POSTGRESQL__HOST: postgres
AUTHENTIK_POSTGRESQL__USER: authentik
AUTHENTIK_POSTGRESQL__NAME: authentik
AUTHENTIK_POSTGRESQL__PASSWORD: {{ authentik_pg_pass }}
AUTHENTIK_POSTGRESQL__PASSWORD: {{ global_db_pass }}
AUTHENTIK_SECRET_KEY: {{ authentik_secret }}
AUTHENTIK_BOOTSTRAP_TIMEOUT: 300
depends_on:
- postgresql
- postgres
- redis
volumes:
database:
redis:
db_data:
redis_data:

View File

@ -1,18 +0,0 @@
---
- name: Crear directorios
file: path=/opt/stacks/{{ item }} state=directory mode=0755
loop: ['npm', 'authentik']
- name: Configurar NPM
template: src=npm-compose.j2 dest=/opt/stacks/npm/compose.yaml
- name: Configurar Authentik
template: src=authentik-compose.j2 dest=/opt/stacks/authentik/compose.yaml
vars:
authentik_host_ip: "{{ ansible_host }}"
- name: Levantar Stacks
community.docker.docker_compose_v2:
project_src: "/opt/stacks/{{ item }}"
state: present
loop: ['npm', 'authentik']

View File

@ -1,11 +0,0 @@
services:
app:
image: 'jc21/nginx-proxy-manager:latest'
restart: unless-stopped
ports:
- '80:80'
- '81:81'
- '443:443'
volumes:
- ./data:/data
- ./letsencrypt:/etc/letsencrypt

View File

@ -1,25 +1,7 @@
---
- name: 1. Preparación Común
hosts: all
become: yes
roles:
- common
- name: 2. Despliegue Core
- name: Despliegue Alicante Core V3
hosts: core_group
become: yes
roles:
- common
- core
- name: 3. Despliegue Gateway
hosts: gateway_group
become: yes
roles:
- gateway
tasks:
- name: "INTEGRACIÓN: Añadir IP del Core al /etc/hosts del Gateway"
lineinfile:
path: /etc/hosts
line: "{{ hostvars[groups['core_group'][0]]['ansible_host'] }} alicante-core"
state: present