| Componente | Detalle |
|---|---|
| Nombre | pmpserverubu |
| IP local | 192.168.1.10 |
| IP pública | 194.224.94.34 |
| Sistema operativo | Ubuntu Server 24.04 LTS |
| Dominio | pampl.ing |
| Disco sistema | 1.1 TB (sdg), 100 GB asignados via LVM |
| Disco backups | 558 GB (sda), montado en /backups |
| Discos disponibles | sdb, sdc, sdd, sde, sdf (558 GB cada uno) |
| Parámetro | Valor |
|---|---|
| Versión | v4.0.0-beta.470 |
| Acceso panel | http://192.168.1.10:9000 (solo red local) |
| Proxy | Traefik v3.6 |
| Certificados SSL | Let's Encrypt (TLS challenge) |
| Puerto HTTP | 80 |
| Puerto HTTPS | 443 |
Proyecto 1: Wiki
Proyecto 2: API de datos
Proyecto 3: Apps
El acceso al servidor es exclusivamente por clave SSH. No se permite acceso con contraseña ni acceso root directo.
Configuración en /etc/ssh/sshd_config:
PermitRootLogin no
PasswordAuthentication no
MaxAuthTries 3
Aplicar cambios: sudo systemctl restart ssh
Instalado y activo. Bloquea automáticamente IPs con intentos fallidos de acceso SSH.
# Verificar estado
sudo systemctl status fail2ban
sudo fail2ban-client status sshd
Reglas activas:
| Puerto | Acceso | Servicio |
|---|---|---|
| 22/tcp | Todo internet | SSH |
| 80/tcp | Todo internet | HTTP (apps públicas) |
| 443/tcp | Todo internet | HTTPS (apps públicas) |
| 53 | Solo red local (192.168.1.0/24) | DNS interno (dnsmasq) |
| 9000 | Solo red local | Panel de Coolify |
| 6001-6002 | Solo red local | Coolify realtime |
| 5432 | Solo red local | PostgreSQL (Beekeeper) |
| Todos | Solo red local | Cualquier servicio interno |
# Verificar estado
sudo ufw status verbose
El dominio pampl.ing está gestionado en Dondominio/Plesk. Los registros DNS apuntan la IP pública:
pampl.ing → A → 194.224.94.34
*.pampl.ing → A → 194.224.94.34
| Puerto externo | Puerto interno | Destino |
|---|---|---|
| 80 | 80 | 192.168.1.10 |
| 443 | 443 | 192.168.1.10 |
Solo estos dos puertos están redirigidos. El cortafuegos corporativo también tiene abiertos estos puertos.
Los equipos de la red local no pueden acceder a los subdominios de pampl.ing a través de la IP pública (problema de hairpin NAT). Dnsmasq resuelve todos los subdominios directamente a 192.168.1.10.
Se desactivó systemd-resolved para evitar conflictos:
sudo systemctl disable systemd-resolved
sudo systemctl stop systemd-resolved
/etc/resolv.conf:
nameserver 127.0.0.1
/etc/dnsmasq.conf:
address=/pampl.ing/192.168.1.10
server=8.8.8.8
server=8.8.4.4
listen-address=192.168.1.10,127.0.0.1
bind-interfaces
# Reiniciar
sudo systemctl restart dnsmasq
# Verificar
dig wiki.pampl.ing @192.168.1.10
Para que los equipos de la red usen este DNS, IT debe configurar 192.168.1.10 como DNS primario en el DHCP del router. Cada equipo también puede configurarlo manualmente.
Al desactivar systemd-resolved, los contenedores Docker pierden la capacidad de resolver dominios externos. Se configuró DNS explícito en /etc/docker/daemon.json:
{
"dns": ["192.168.1.10", "8.8.8.8", "8.8.4.4"],
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
}
}
# Reiniciar Docker tras cambios
sudo systemctl restart docker
# Verificar que Docker resuelve DNS
sudo docker exec coolify-proxy nslookup acme-v02.api.letsencrypt.org
Los certificados se generan automáticamente con Let's Encrypt a través de Traefik, usando el método TLS challenge (puerto 443).
Contexto: inicialmente se intentó HTTP challenge, pero el router HTTP de Coolify interceptaba las peticiones ACME y las redirigía a
/login. Se cambió a TLS challenge.
Configuración en /data/coolify/proxy/docker-compose.yml:
- '--certificatesresolvers.letsencrypt.acme.tlschallenge=true'
- '--certificatesresolvers.letsencrypt.acme.storage=/traefik/acme.json'
- '--certificatesresolvers.letsencrypt.acme.email=jose.moya@pampling.com'
- '--entrypoints.https.http.tls.certResolver=letsencrypt'
- '--serversTransport.insecureSkipVerify=true'
Los certificados se renuevan automáticamente cada 90 días. Archivo: /data/coolify/proxy/acme.json
# Ver dominios con certificado
cat /data/coolify/proxy/acme.json | python3 -c "
import sys, json
d = json.load(sys.stdin)
certs = d.get('letsencrypt', {}).get('Certificates')
if certs:
for c in certs:
print(c.get('domain', {}).get('main', 'unknown'))
else:
print('No hay certificados generados')
"
# Ver logs de ACME
sudo docker logs coolify-proxy --since 30m 2>&1 | grep -i "acme\|certificate"
# Regenerar certificados si hay problemas
sudo rm -f /data/coolify/proxy/acme.json
cd /data/coolify/proxy && sudo docker compose up -d --force-recreate
Archivo /etc/docker/daemon.json: ver sección DNS de Docker.
# Ver contenedores activos
sudo docker ps --format '{{.Names}}: {{.Image}}'
# Ver uso de recursos
sudo docker stats --no-stream
| Repositorio | Tecnología | Propósito |
|---|---|---|
| pampling/pampling-analytics | FastAPI (Python) | API de datos + dashboard |
Coolify se conecta a Bitbucket mediante deploy keys SSH.
ssh-keygen -t ed25519 -C "coolify-deploy"git add . && git commit -m "Descripción" && git push origin main*.db
*.sqlite
*.sqlite3
data/
__pycache__/
*.pyc
venv/
.env
node_modules/
Nunca subir bases de datos ni archivos de más de 100 MB. Si un archivo grande se cuela en el historial de Git:
rm -rf .git
git init
git add .
git commit -m "Reinicio limpio"
git remote add origin git@bitbucket.org:pampling/repo.git
git push -u origin main --force
Disco /dev/sda (558 GB) formateado como ext4 y montado en /backups.
sudo mkfs.ext4 -L backups /dev/sda
sudo mkdir -p /backups
sudo mount /dev/sda /backups
Entrada en /etc/fstab para montaje automático:
/dev/sda /backups ext4 defaults 0 2
| Parámetro | Valor |
|---|---|
| Script | /usr/local/bin/backup-coolify.sh |
| Frecuencia | Diaria a las 03:00 |
| Retención | 30 días |
| Log | /var/log/backup-coolify.log |
| Cron | 0 3 * * * /usr/local/bin/backup-coolify.sh >> /var/log/backup-coolify.log 2>&1 |
pg_dumpall comprimido con gzip, busca imagen postgres:*-alpine)/data/coolify/source/.env, proxy/, ssh/)/data/coolify/databases/, services/, applications/)# Ver backups existentes
ls -lh /backups/
# Ver contenido del último backup
ls -lh /backups/$(ls /backups/ | tail -1)/
# Ver log
tail -30 /var/log/backup-coolify.log
# Ejecutar backup manual
sudo /usr/local/bin/backup-coolify.sh
# Descomprimir
gunzip /backups/FECHA/NOMBRE_CONTENEDOR_db.sql.gz
# Restaurar en el contenedor PostgreSQL
cat /backups/FECHA/NOMBRE_CONTENEDOR_db.sql | docker exec -i NOMBRE_CONTENEDOR psql -U USUARIO
# 1. Crear usuario
sudo adduser nombreusuario
# 2. Configurar acceso SSH
sudo mkdir -p /home/nombreusuario/.ssh
echo "CLAVE_PUBLICA_DEL_USUARIO" >> /home/nombreusuario/.ssh/authorized_keys
sudo chown -R nombreusuario:nombreusuario /home/nombreusuario/.ssh
sudo chmod 700 /home/nombreusuario/.ssh
sudo chmod 600 /home/nombreusuario/.ssh/authorized_keys
# 3. Permisos de Docker (necesario para trabajar con contenedores)
sudo usermod -aG docker nombreusuario
# 4. Permisos de administrador (opcional)
sudo usermod -aG sudo nombreusuario
El nuevo usuario genera su clave en su PC:
ssh-keygen -t ed25519 -C "email@pampling.com"
cat ~/.ssh/id_ed25519.pub
Y envía la clave pública al administrador.
| Recurso | Acceso |
|---|---|
| SSH | ssh josemoya@192.168.1.10 |
| Panel Coolify | http://192.168.1.10:9000 (solo red local) |
| Wiki | https://wiki.pampl.ing |
| API datos | https://api.pampl.ing |
| PostgreSQL | 192.168.1.10:5432 (Beekeeper, solo red local) |
| Bitbucket | bitbucket.org/pampling/ |
Verificar DNS en /etc/docker/daemon.json. Debe tener "dns": ["192.168.1.10", "8.8.8.8", "8.8.4.4"].
sudo systemctl restart docker
sudo lvextend -l +100%FREE /dev/ubuntu-vg/ubuntu-lv
sudo resize2fs /dev/ubuntu-vg/ubuntu-lv
# Ver errores
sudo docker logs coolify-proxy --since 30m 2>&1 | grep -i "acme\|certificate\|error"
# Regenerar certificados
sudo rm -f /data/coolify/proxy/acme.json
cd /data/coolify/proxy && sudo docker compose up -d --force-recreate
Verificar que el equipo usa el DNS local (192.168.1.10):
nslookup wiki.pampl.ing 192.168.1.10
Si no resuelve, configurar DNS manualmente o verificar dnsmasq:
sudo systemctl status dnsmasq
sudo docker rm NOMBRE_DEL_CONTENEDOR
Si el toggle "Make it publicly available" en Coolify falla:
find /data/coolify -name "docker-compose.yml" | xargs grep -l "pampling" 2>/dev/null
Editar el archivo y añadir después de container_name:
ports:
- '5432:5432'
Reiniciar: docker compose up -d
Verificar que los puertos 6001 y 6002 están accesibles desde el equipo que usa Coolify.
El TLD .ing está en la lista HSTS preload de Chrome. Si un dominio se bloquea pero funciona en incógnito:
chrome://net-internals/#hstswiki.pampl.ing)# Escuchar tráfico en puerto 443
sudo tcpdump -i eno4 port 443 -c 5
# Acceder desde un móvil con datos (no WiFi) a https://pampl.ing