https://github.com/thl-corporation/thl-sql
Production-ready PostgreSQL platform with PgBouncer, HAProxy, and one-command multi-distro installation.
https://github.com/thl-corporation/thl-sql
automation database devops haproxy infrastructure linux pgbouncer postgresql sql vps
Last synced: 16 days ago
JSON representation
Production-ready PostgreSQL platform with PgBouncer, HAProxy, and one-command multi-distro installation.
- Host: GitHub
- URL: https://github.com/thl-corporation/thl-sql
- Owner: thl-corporation
- License: mit
- Created: 2026-04-07T15:28:10.000Z (2 months ago)
- Default Branch: main
- Last Pushed: 2026-04-15T14:38:46.000Z (2 months ago)
- Last Synced: 2026-04-15T16:15:18.839Z (2 months ago)
- Topics: automation, database, devops, haproxy, infrastructure, linux, pgbouncer, postgresql, sql, vps
- Language: Shell
- Homepage: https://thlcorporation.com
- Size: 537 KB
- Stars: 1
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Contributing: .github/CONTRIBUTING.md
- License: LICENSE
- Code of conduct: .github/CODE_OF_CONDUCT.md
- Security: .github/SECURITY.md
- Support: .github/SUPPORT.md
Awesome Lists containing this project
README
# THL SQL
**EN** | Production-ready SQL platform for fast and repeatable Linux deployments.
**ES** | Plataforma SQL lista para produccion con despliegues rapidos y repetibles en Linux.
Company / Empresa: [THL Corporation](https://thlcorporation.com)
Contact / Contacto: `admin@thlcorporation.com`
---
## Why THL SQL / Por que THL SQL
**EN**
- Scales concurrent client traffic with `HAProxy + PgBouncer`.
- Keeps PostgreSQL isolated on an internal port.
- Manages SQL access by IP/CIDR from the admin panel.
- Standardizes Linux setup with a one-command installer.
- Optional Tailscale VPN for private access to the panel and databases.
- Container-aware: detects cgroup limits for accurate CPU/RAM metrics inside Docker.
**ES**
- Escala trafico concurrente con `HAProxy + PgBouncer`.
- Mantiene PostgreSQL aislado en un puerto interno.
- Gestiona acceso SQL por IP/CIDR desde el panel de administracion.
- Estandariza la configuracion de Linux con un instalador de un solo comando.
- VPN Tailscale opcional para acceso privado al panel y bases de datos.
- Compatible con contenedores: detecta limites cgroup para metricas precisas de CPU/RAM en Docker.
### Architecture / Arquitectura
```
SQL Client -> HAProxy:5432 -> PgBouncer:6432 -> PostgreSQL:5433
```
---
## Quick Install / Instalacion Rapida
**EN** | Run as root on a fresh Linux VPS. The installer is fully interactive.
**ES** | Ejecutar como root en un VPS Linux nuevo. El instalador es completamente interactivo.
```bash
curl -fsSL https://raw.githubusercontent.com/thl-corporation/thl-sql/main/install.sh | bash
```
Fallback (manual download / descarga manual):
```bash
curl -fsSL https://raw.githubusercontent.com/thl-corporation/thl-sql/main/install.sh -o install.sh
chmod +x install.sh
./install.sh
```
### Supported Distros / Distribuciones Soportadas
- Debian / Ubuntu
- RHEL / Rocky / AlmaLinux / CentOS
---
## Installation Modes / Modos de Instalacion
**EN** | Three modes are available. If you run the one-liner without `THL_ACTION`, the installer shows an interactive menu.
**ES** | Tres modos disponibles. Si ejecutas el one-liner sin `THL_ACTION`, el instalador muestra un menu interactivo.
### 1. Full wipe + new install / Instalacion limpia
```bash
THL_ACTION=reinstall THL_FORCE=1 \
curl -fsSL https://raw.githubusercontent.com/thl-corporation/thl-sql/main/install.sh | bash
```
### 2. Upgrade in place / Actualizar sin perder datos
```bash
THL_ACTION=upgrade \
curl -fsSL https://raw.githubusercontent.com/thl-corporation/thl-sql/main/install.sh | bash
```
### 3. Uninstall / Desinstalar
```bash
THL_ACTION=uninstall THL_FORCE=1 \
curl -fsSL https://raw.githubusercontent.com/thl-corporation/thl-sql/main/install.sh | bash
```
### Production example / Ejemplo produccion
```bash
THL_DOMAIN=sql.example.com \
THL_ADMIN_USER=admin \
THL_ADMIN_PASS='Change_This_Immediately_123!' \
curl -fsSL https://raw.githubusercontent.com/thl-corporation/thl-sql/main/install.sh | bash
```
---
## Tailscale VPN
**EN** | The installer can optionally set up Tailscale so the panel and databases are only reachable through a private VPN IP (e.g. `100.x.x.x`). When enabled, this IP becomes the default connection host for all generated credentials.
**ES** | El instalador puede configurar Tailscale opcionalmente para que el panel y las bases de datos solo sean accesibles a traves de una IP privada de VPN (ej. `100.x.x.x`). Cuando esta habilitado, esta IP se convierte en el host de conexion predeterminado para todas las credenciales generadas.
### How it works / Como funciona
1. **EN** | During installation the installer asks _"Install Tailscale?"_. Set `THL_INSTALL_TAILSCALE=1` to skip the prompt.
**ES** | Durante la instalacion se pregunta _"Instalar Tailscale?"_. Usar `THL_INSTALL_TAILSCALE=1` para omitir el prompt.
2. **EN** | `tailscale up` runs and prints an authentication URL. Open it in your browser to link the node.
**ES** | `tailscale up` se ejecuta y muestra una URL de autenticacion. Abrirla en el navegador para vincular el nodo.
3. **EN** | Once authenticated, the installer automatically:
- Sets `PUBLIC_DB_HOST` to the Tailscale IP.
- Updates `ALLOWED_ORIGINS` so the panel accepts requests via VPN.
- Configures the firewall to allow Tailscale interface traffic.
- Restarts `pg_manager` so the app serves the Tailscale IP in all connection strings.
**ES** | Una vez autenticado, el instalador automaticamente:
- Establece `PUBLIC_DB_HOST` con la IP de Tailscale.
- Actualiza `ALLOWED_ORIGINS` para que el panel acepte peticiones via VPN.
- Configura el firewall para permitir trafico en la interfaz de Tailscale.
- Reinicia `pg_manager` para que la app entregue la IP de Tailscale en todos los connection strings.
4. **EN** | Connection strings displayed in the panel will show `postgresql://user:pass@100.x.x.x:5432/db`.
**ES** | Los connection strings que se muestran en el panel indicaran `postgresql://user:pass@100.x.x.x:5432/db`.
### Docker + Tailscale
**EN** | In containers without systemd, the installer starts `tailscaled` in userspace networking mode automatically. No extra Docker flags are required.
**ES** | En contenedores sin systemd, el instalador inicia `tailscaled` en modo userspace networking automaticamente. No se necesitan flags adicionales de Docker.
### Manual override / Override manual
**EN** | If Tailscale is already configured outside the installer, set these in `backend/.env`:
**ES** | Si Tailscale ya esta configurado fuera del instalador, establecer en `backend/.env`:
```dotenv
PUBLIC_DB_HOST=100.x.x.x
PUBLIC_DB_HOST_SOURCE=tailscale
TAILSCALE_IP=100.x.x.x
```
---
## Installer Variables / Variables del Instalador
| Variable | Description / Descripcion |
|----------|--------------------------|
| `THL_DOMAIN` | Domain for HTTPS (certbot). Leave empty for IP mode. / Dominio para HTTPS. Dejar vacio para modo IP. |
| `THL_BIND_IP` | Bind IP for the panel. / IP de enlace del panel. |
| `THL_PORT` | Web port (default `80`). / Puerto web. |
| `THL_ADMIN_USER` | Admin username (default `admin`). / Usuario administrador. |
| `THL_ADMIN_PASS` | Admin password. Auto-generated if empty. / Contrasena admin. Se genera automaticamente si esta vacia. |
| `THL_PG_PASSWORD` | PostgreSQL password. Auto-generated if empty. / Contrasena PostgreSQL. |
| `THL_NONINTERACTIVE=1` | Skip all prompts. / Omitir todos los prompts. |
| `THL_UX_MODE=1` | Minimal prompts (default). / Prompts minimos. |
| `THL_INSTALL_TAILSCALE=1` | Install Tailscale without prompting. / Instalar Tailscale sin preguntar. |
| `THL_INSTALL_DEBUG=1` | Enable `set -x` trace. / Habilitar traza `set -x`. |
| `THL_INSTALL_LOG_FILE` | Log file path. / Ruta del archivo de log. |
| `THL_SYSTEM_UPGRADE_POLICY` | `none`, `upgrade`, or `full` (default). / Politica de actualizacion del sistema. |
| `THL_PRESERVE_EXISTING=1` | Keep credentials/config on upgrade (default). / Preservar credenciales al actualizar. |
| `THL_ACTION` | `reinstall`, `upgrade`, or `uninstall`. / Modo de instalacion. |
| `THL_FORCE=1` | Required for destructive non-interactive actions. / Requerido para acciones destructivas. |
| `THL_AUTO_CACHE_CLEAN=1` | Clear package/temp caches (default). / Limpiar caches automaticamente. |
| `PUBLIC_HOST` | Override public panel host (useful in Docker). / Override del host publico del panel. |
| `PUBLIC_PORT` | Override public panel port (useful in Docker). / Override del puerto publico del panel. |
| `PUBLIC_SCHEME` | `http` or `https` override. / Override del esquema. |
| `PANEL_URL` | Full panel URL override. / Override completo de la URL del panel. |
| `PUBLIC_DB_HOST` | SQL host shown in credentials. / Host SQL mostrado en credenciales. |
| `PUBLIC_DB_PORT` | SQL port shown in credentials. / Puerto SQL mostrado en credenciales. |
| `ALLOWED_PORTS` | Panel firewall policy (`*` = unrestricted). / Politica de firewall del panel. |
| `PROTECTED_PORTS` | Ports the panel cannot close/open. / Puertos que el panel no puede cerrar/abrir. |
| `CONTAINER_CPU_CORES` | Override CPU core count in containers. / Override de cores CPU en contenedores. |
| `CONTAINER_MEMORY_BYTES` | Override memory limit in containers (bytes). / Override de limite de memoria en contenedores. |
---
## Docker Usage / Uso con Docker
```bash
docker build -t thl-sql:local .
```
```bash
docker run -d \
-p 8080:80 \
-p 2222:22 \
-p 5432:5432 \
-e PUBLIC_HOST=localhost \
-e PUBLIC_PORT=8080 \
-e PUBLIC_DB_HOST=localhost \
-e PUBLIC_DB_PORT=5432 \
--name thl_sql_01 \
thl-sql:local
```
**EN** | Then run the installer inside the container:
**ES** | Luego ejecutar el instalador dentro del contenedor:
```bash
docker exec -it thl_sql_01 bash -lc 'THL_ACTION=reinstall THL_FORCE=1 bash /opt/thl-sql/install.sh --no-systemd'
```
Docker Compose:
```bash
docker compose up -d
docker compose exec thl-sql bash -lc 'THL_ACTION=reinstall THL_FORCE=1 bash /opt/thl-sql/install.sh --no-systemd'
```
### Docker Notes / Notas Docker
**EN**
- `Dockerfile` sets `PUBLIC_HOST=localhost`, `PUBLIC_PORT=80`, `PUBLIC_SCHEME=http`, `PUBLIC_DB_HOST=localhost`, `PUBLIC_DB_PORT=5432` as safe defaults.
- If the mapped host port differs from `80`, set `PUBLIC_PORT` explicitly.
- If the mapped SQL port differs from `5432`, set `PUBLIC_DB_PORT` explicitly.
- Inside Docker, the panel cannot publish new container ports; published ports come from `docker run -p` or Compose.
- SQL allowlists are enforced by HAProxy when no host firewall backend is available.
- Container CPU/RAM metrics read from cgroups. If detection fails, set `CONTAINER_CPU_CORES` and `CONTAINER_MEMORY_BYTES` env vars.
**ES**
- `Dockerfile` establece `PUBLIC_HOST=localhost`, `PUBLIC_PORT=80`, `PUBLIC_SCHEME=http`, `PUBLIC_DB_HOST=localhost`, `PUBLIC_DB_PORT=5432` como valores por defecto.
- Si el puerto mapeado en el host no es `80`, establecer `PUBLIC_PORT` explicitamente.
- Si el puerto SQL mapeado no es `5432`, establecer `PUBLIC_DB_PORT` explicitamente.
- Dentro de Docker, el panel no puede publicar puertos nuevos; los puertos publicados vienen de `docker run -p` o Compose.
- Las listas de acceso SQL son aplicadas por HAProxy cuando no hay firewall del host disponible.
- Las metricas de CPU/RAM del contenedor se leen desde cgroups. Si la deteccion falla, usar las variables `CONTAINER_CPU_CORES` y `CONTAINER_MEMORY_BYTES`.
---
## Dashboard Metrics / Metricas del Dashboard
**EN**
- On host installs, `/api/stats` uses `psutil` for CPU and memory.
- On container installs, `/api/stats` reads cgroup v1/v2 files for container-accurate metrics.
- Supports hybrid cgroup setups and walks up the cgroup hierarchy to find limits.
- Uses `os.sched_getaffinity()` as a fallback for CPU set detection.
- When cgroup detection fails, set `CONTAINER_CPU_CORES` and `CONTAINER_MEMORY_BYTES` as env var overrides.
- Startup logs print detected cgroup version, assigned cores, and memory limits for diagnostics.
- The dashboard cards show both current usage and assigned capacity.
- Refresh interval: 10 seconds.
**ES**
- En instalaciones host, `/api/stats` usa `psutil` para CPU y memoria.
- En instalaciones contenedor, `/api/stats` lee archivos cgroup v1/v2 para metricas precisas del contenedor.
- Soporta configuraciones hibridas de cgroup y recorre la jerarquia cgroup buscando limites.
- Usa `os.sched_getaffinity()` como fallback para deteccion de CPU set.
- Si la deteccion de cgroup falla, usar `CONTAINER_CPU_CORES` y `CONTAINER_MEMORY_BYTES` como variables de entorno.
- Los logs de inicio imprimen la version de cgroup detectada, cores asignados y limites de memoria para diagnostico.
- Las tarjetas del dashboard muestran uso actual y capacidad asignada.
- Intervalo de refresco: 10 segundos.
---
## Firewall Behavior / Comportamiento del Firewall
**EN**
- On host installs, the installer configures the native firewall safely and keeps existing rules intact.
- Debian/Ubuntu: `ufw --force enable` for non-interactive installation.
- RHEL-family: uses the current firewalld default zone.
- Legacy `ALLOWED_PORTS=22,80,443,5432` is treated as unrestricted behavior for backwards compatibility.
- Protected ports (SSH, web, SQL) are blocked from direct close/open operations in the UI.
- In containers, SQL IP restrictions work through HAProxy ACLs.
- When Tailscale is enabled, the Tailscale interface (`tailscale0`) is allowed through the firewall automatically.
**ES**
- En instalaciones host, el instalador configura el firewall nativo de forma segura y preserva reglas existentes.
- Debian/Ubuntu: `ufw --force enable` para instalacion no interactiva.
- Familia RHEL: usa la zona por defecto actual de firewalld.
- El valor legacy `ALLOWED_PORTS=22,80,443,5432` se trata como comportamiento sin restriccion por compatibilidad.
- Puertos protegidos (SSH, web, SQL) estan bloqueados de operaciones directas de cierre/apertura en la UI.
- En contenedores, las restricciones de IP de SQL funcionan a traves de ACLs de HAProxy.
- Cuando Tailscale esta habilitado, la interfaz de Tailscale (`tailscale0`) se permite en el firewall automaticamente.
---
## Troubleshooting / Solucion de Problemas
**EN** | If the installer stops at `[1/11]`, re-run in debug mode:
**ES** | Si el instalador se detiene en `[1/11]`, re-ejecutar en modo debug:
```bash
THL_INSTALL_DEBUG=1 \
THL_INSTALL_LOG_FILE=/var/log/thl-sql-install.log \
curl -fsSL https://raw.githubusercontent.com/thl-corporation/thl-sql/main/install.sh | bash
```
```bash
# Quick diagnostics / Diagnosticos rapidos
tail -n 120 /var/log/thl-sql-install.log
journalctl -u pg_manager -n 80 --no-pager
```
### Domain notes / Notas de dominio
- **EN** | If `THL_DOMAIN` is set, installer uses HTTPS with certbot. If empty, IP mode (`http://IP:PORT`).
- **ES** | Si `THL_DOMAIN` esta definido, el instalador usa HTTPS con certbot. Si esta vacio, modo IP (`http://IP:PUERTO`).
### Preflight on Ubuntu / Preflight en Ubuntu
```bash
id -u # must be 0 (root) / debe ser 0 (root)
systemctl --version
```
---
## Update Existing Server / Actualizar Servidor Existente
```bash
cd /var/www/pg_manager && git pull origin main && bash deploy_remote.sh
```
**EN** | `deploy_remote.sh` preserves Tailscale configuration during upgrades automatically.
**ES** | `deploy_remote.sh` preserva la configuracion de Tailscale durante actualizaciones automaticamente.
---
## Technical Validation / Validacion Tecnica
**EN** | On the VPS:
**ES** | En el VPS:
```bash
cd /var/www/pg_manager
source venv/bin/activate
python verify_deployment.py
python server/run_sql_load_test.py --connections 1000 --hold-seconds 20 --sample-seconds 8
bash server/run_test_suite.sh
```
**EN** | From an external client:
**ES** | Desde un cliente externo:
```bash
python verify_remote.py
```
---
## Repository Sync / Sincronizacion de Repositorios
```powershell
./push_dual_repos.ps1 # push to both repos / push a ambos repos
./push_dual_repos.ps1 -DryRun # validate without publishing / validar sin publicar
```
**EN** | Targets: `thl-corporation/thl-sql` (corp) and `thl-corporation-spa/thl-sql` (SPA mirror).
**ES** | Destinos: `thl-corporation/thl-sql` (corp) y `thl-corporation-spa/thl-sql` (mirror SPA).
Environment overrides: `THL_SQL_CORP_SSH_KEY`, `THL_SQL_SPA_REPO_URL`, `THL_SQL_SPA_LEGACY_REPO_URL`, `THL_SQL_CORP_REPO_URL`.
---
## Publication Safety / Seguridad de Publicacion
**EN** | No real secrets are stored in git. Sensitive values use `*.example` templates. Keys and credentials are blocked in `.gitignore`.
**ES** | No se almacenan secretos reales en git. Los valores sensibles usan plantillas `*.example`. Claves y credenciales estan bloqueadas en `.gitignore`.
```bash
bash server/check_repo_safety.sh
```
---
## Documentation / Documentacion
- `docs/INSTALL_LINUX_MULTI_DISTRO.md`
- `docs/REPLICAR_EN_OTRO_VPS.md`
- `docs/PRUEBA_1000_CONEXIONES.md`
- `INSTRUCCIONES_UPDATE_VPS.md`
- `INSTRUCCIONES_TEST_REMOTO.md`