{"id":50499670,"url":"https://github.com/thl-corporation/thl-sql","last_synced_at":"2026-06-02T10:30:41.451Z","repository":{"id":350013367,"uuid":"1203990145","full_name":"thl-corporation/thl-sql","owner":"thl-corporation","description":"Production-ready PostgreSQL platform with PgBouncer, HAProxy, and one-command multi-distro installation.","archived":false,"fork":false,"pushed_at":"2026-04-15T14:38:46.000Z","size":550,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-15T16:15:18.839Z","etag":null,"topics":["automation","database","devops","haproxy","infrastructure","linux","pgbouncer","postgresql","sql","vps"],"latest_commit_sha":null,"homepage":"https://thlcorporation.com","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/thl-corporation.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":".github/CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":".github/CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":".github/SECURITY.md","support":".github/SUPPORT.md","governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-07T15:28:10.000Z","updated_at":"2026-04-15T14:39:10.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/thl-corporation/thl-sql","commit_stats":null,"previous_names":["thl-corporation/thl-sql"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/thl-corporation/thl-sql","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thl-corporation%2Fthl-sql","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thl-corporation%2Fthl-sql/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thl-corporation%2Fthl-sql/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thl-corporation%2Fthl-sql/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/thl-corporation","download_url":"https://codeload.github.com/thl-corporation/thl-sql/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thl-corporation%2Fthl-sql/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33818563,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-02T02:00:07.132Z","response_time":109,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["automation","database","devops","haproxy","infrastructure","linux","pgbouncer","postgresql","sql","vps"],"created_at":"2026-06-02T10:30:36.826Z","updated_at":"2026-06-02T10:30:41.443Z","avatar_url":"https://github.com/thl-corporation.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"docs/assets/thl-corporation-logo.png\" alt=\"THL Corporation\" width=\"180\"\u003e\n\u003c/p\u003e\n\n# THL SQL\n\n**EN** | Production-ready SQL platform for fast and repeatable Linux deployments.  \n**ES** | Plataforma SQL lista para produccion con despliegues rapidos y repetibles en Linux.\n\nCompany / Empresa: [THL Corporation](https://thlcorporation.com)  \nContact / Contacto: `admin@thlcorporation.com`\n\n---\n\n## Why THL SQL / Por que THL SQL\n\n**EN**\n\n- Scales concurrent client traffic with `HAProxy + PgBouncer`.\n- Keeps PostgreSQL isolated on an internal port.\n- Manages SQL access by IP/CIDR from the admin panel.\n- Standardizes Linux setup with a one-command installer.\n- Optional Tailscale VPN for private access to the panel and databases.\n- Container-aware: detects cgroup limits for accurate CPU/RAM metrics inside Docker.\n\n**ES**\n\n- Escala trafico concurrente con `HAProxy + PgBouncer`.\n- Mantiene PostgreSQL aislado en un puerto interno.\n- Gestiona acceso SQL por IP/CIDR desde el panel de administracion.\n- Estandariza la configuracion de Linux con un instalador de un solo comando.\n- VPN Tailscale opcional para acceso privado al panel y bases de datos.\n- Compatible con contenedores: detecta limites cgroup para metricas precisas de CPU/RAM en Docker.\n\n### Architecture / Arquitectura\n\n```\nSQL Client -\u003e HAProxy:5432 -\u003e PgBouncer:6432 -\u003e PostgreSQL:5433\n```\n\n---\n\n## Quick Install / Instalacion Rapida\n\n**EN** | Run as root on a fresh Linux VPS. The installer is fully interactive.  \n**ES** | Ejecutar como root en un VPS Linux nuevo. El instalador es completamente interactivo.\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/thl-corporation/thl-sql/main/install.sh | bash\n```\n\nFallback (manual download / descarga manual):\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/thl-corporation/thl-sql/main/install.sh -o install.sh\nchmod +x install.sh\n./install.sh\n```\n\n### Supported Distros / Distribuciones Soportadas\n\n- Debian / Ubuntu\n- RHEL / Rocky / AlmaLinux / CentOS\n\n---\n\n## Installation Modes / Modos de Instalacion\n\n**EN** | Three modes are available. If you run the one-liner without `THL_ACTION`, the installer shows an interactive menu.  \n**ES** | Tres modos disponibles. Si ejecutas el one-liner sin `THL_ACTION`, el instalador muestra un menu interactivo.\n\n### 1. Full wipe + new install / Instalacion limpia\n\n```bash\nTHL_ACTION=reinstall THL_FORCE=1 \\\n  curl -fsSL https://raw.githubusercontent.com/thl-corporation/thl-sql/main/install.sh | bash\n```\n\n### 2. Upgrade in place / Actualizar sin perder datos\n\n```bash\nTHL_ACTION=upgrade \\\n  curl -fsSL https://raw.githubusercontent.com/thl-corporation/thl-sql/main/install.sh | bash\n```\n\n### 3. Uninstall / Desinstalar\n\n```bash\nTHL_ACTION=uninstall THL_FORCE=1 \\\n  curl -fsSL https://raw.githubusercontent.com/thl-corporation/thl-sql/main/install.sh | bash\n```\n\n### Production example / Ejemplo produccion\n\n```bash\nTHL_DOMAIN=sql.example.com \\\nTHL_ADMIN_USER=admin \\\nTHL_ADMIN_PASS='Change_This_Immediately_123!' \\\n  curl -fsSL https://raw.githubusercontent.com/thl-corporation/thl-sql/main/install.sh | bash\n```\n\n---\n\n## Tailscale VPN\n\n**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.  \n**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.\n\n### How it works / Como funciona\n\n1. **EN** | During installation the installer asks _\"Install Tailscale?\"_. Set `THL_INSTALL_TAILSCALE=1` to skip the prompt.  \n   **ES** | Durante la instalacion se pregunta _\"Instalar Tailscale?\"_. Usar `THL_INSTALL_TAILSCALE=1` para omitir el prompt.\n\n2. **EN** | `tailscale up` runs and prints an authentication URL. Open it in your browser to link the node.  \n   **ES** | `tailscale up` se ejecuta y muestra una URL de autenticacion. Abrirla en el navegador para vincular el nodo.\n\n3. **EN** | Once authenticated, the installer automatically:\n   - Sets `PUBLIC_DB_HOST` to the Tailscale IP.\n   - Updates `ALLOWED_ORIGINS` so the panel accepts requests via VPN.\n   - Configures the firewall to allow Tailscale interface traffic.\n   - Restarts `pg_manager` so the app serves the Tailscale IP in all connection strings.  \n   **ES** | Una vez autenticado, el instalador automaticamente:\n   - Establece `PUBLIC_DB_HOST` con la IP de Tailscale.\n   - Actualiza `ALLOWED_ORIGINS` para que el panel acepte peticiones via VPN.\n   - Configura el firewall para permitir trafico en la interfaz de Tailscale.\n   - Reinicia `pg_manager` para que la app entregue la IP de Tailscale en todos los connection strings.\n\n4. **EN** | Connection strings displayed in the panel will show `postgresql://user:pass@100.x.x.x:5432/db`.  \n   **ES** | Los connection strings que se muestran en el panel indicaran `postgresql://user:pass@100.x.x.x:5432/db`.\n\n### Docker + Tailscale\n\n**EN** | In containers without systemd, the installer starts `tailscaled` in userspace networking mode automatically. No extra Docker flags are required.  \n**ES** | En contenedores sin systemd, el instalador inicia `tailscaled` en modo userspace networking automaticamente. No se necesitan flags adicionales de Docker.\n\n### Manual override / Override manual\n\n**EN** | If Tailscale is already configured outside the installer, set these in `backend/.env`:  \n**ES** | Si Tailscale ya esta configurado fuera del instalador, establecer en `backend/.env`:\n\n```dotenv\nPUBLIC_DB_HOST=100.x.x.x\nPUBLIC_DB_HOST_SOURCE=tailscale\nTAILSCALE_IP=100.x.x.x\n```\n\n---\n\n## Installer Variables / Variables del Instalador\n\n| Variable | Description / Descripcion |\n|----------|--------------------------|\n| `THL_DOMAIN` | Domain for HTTPS (certbot). Leave empty for IP mode. / Dominio para HTTPS. Dejar vacio para modo IP. |\n| `THL_BIND_IP` | Bind IP for the panel. / IP de enlace del panel. |\n| `THL_PORT` | Web port (default `80`). / Puerto web. |\n| `THL_ADMIN_USER` | Admin username (default `admin`). / Usuario administrador. |\n| `THL_ADMIN_PASS` | Admin password. Auto-generated if empty. / Contrasena admin. Se genera automaticamente si esta vacia. |\n| `THL_PG_PASSWORD` | PostgreSQL password. Auto-generated if empty. / Contrasena PostgreSQL. |\n| `THL_NONINTERACTIVE=1` | Skip all prompts. / Omitir todos los prompts. |\n| `THL_UX_MODE=1` | Minimal prompts (default). / Prompts minimos. |\n| `THL_INSTALL_TAILSCALE=1` | Install Tailscale without prompting. / Instalar Tailscale sin preguntar. |\n| `THL_INSTALL_DEBUG=1` | Enable `set -x` trace. / Habilitar traza `set -x`. |\n| `THL_INSTALL_LOG_FILE` | Log file path. / Ruta del archivo de log. |\n| `THL_SYSTEM_UPGRADE_POLICY` | `none`, `upgrade`, or `full` (default). / Politica de actualizacion del sistema. |\n| `THL_PRESERVE_EXISTING=1` | Keep credentials/config on upgrade (default). / Preservar credenciales al actualizar. |\n| `THL_ACTION` | `reinstall`, `upgrade`, or `uninstall`. / Modo de instalacion. |\n| `THL_FORCE=1` | Required for destructive non-interactive actions. / Requerido para acciones destructivas. |\n| `THL_AUTO_CACHE_CLEAN=1` | Clear package/temp caches (default). / Limpiar caches automaticamente. |\n| `PUBLIC_HOST` | Override public panel host (useful in Docker). / Override del host publico del panel. |\n| `PUBLIC_PORT` | Override public panel port (useful in Docker). / Override del puerto publico del panel. |\n| `PUBLIC_SCHEME` | `http` or `https` override. / Override del esquema. |\n| `PANEL_URL` | Full panel URL override. / Override completo de la URL del panel. |\n| `PUBLIC_DB_HOST` | SQL host shown in credentials. / Host SQL mostrado en credenciales. |\n| `PUBLIC_DB_PORT` | SQL port shown in credentials. / Puerto SQL mostrado en credenciales. |\n| `ALLOWED_PORTS` | Panel firewall policy (`*` = unrestricted). / Politica de firewall del panel. |\n| `PROTECTED_PORTS` | Ports the panel cannot close/open. / Puertos que el panel no puede cerrar/abrir. |\n| `CONTAINER_CPU_CORES` | Override CPU core count in containers. / Override de cores CPU en contenedores. |\n| `CONTAINER_MEMORY_BYTES` | Override memory limit in containers (bytes). / Override de limite de memoria en contenedores. |\n\n---\n\n## Docker Usage / Uso con Docker\n\n```bash\ndocker build -t thl-sql:local .\n```\n\n```bash\ndocker run -d \\\n  -p 8080:80 \\\n  -p 2222:22 \\\n  -p 5432:5432 \\\n  -e PUBLIC_HOST=localhost \\\n  -e PUBLIC_PORT=8080 \\\n  -e PUBLIC_DB_HOST=localhost \\\n  -e PUBLIC_DB_PORT=5432 \\\n  --name thl_sql_01 \\\n  thl-sql:local\n```\n\n**EN** | Then run the installer inside the container:  \n**ES** | Luego ejecutar el instalador dentro del contenedor:\n\n```bash\ndocker exec -it thl_sql_01 bash -lc 'THL_ACTION=reinstall THL_FORCE=1 bash /opt/thl-sql/install.sh --no-systemd'\n```\n\nDocker Compose:\n\n```bash\ndocker compose up -d\ndocker compose exec thl-sql bash -lc 'THL_ACTION=reinstall THL_FORCE=1 bash /opt/thl-sql/install.sh --no-systemd'\n```\n\n### Docker Notes / Notas Docker\n\n**EN**\n\n- `Dockerfile` sets `PUBLIC_HOST=localhost`, `PUBLIC_PORT=80`, `PUBLIC_SCHEME=http`, `PUBLIC_DB_HOST=localhost`, `PUBLIC_DB_PORT=5432` as safe defaults.\n- If the mapped host port differs from `80`, set `PUBLIC_PORT` explicitly.\n- If the mapped SQL port differs from `5432`, set `PUBLIC_DB_PORT` explicitly.\n- Inside Docker, the panel cannot publish new container ports; published ports come from `docker run -p` or Compose.\n- SQL allowlists are enforced by HAProxy when no host firewall backend is available.\n- Container CPU/RAM metrics read from cgroups. If detection fails, set `CONTAINER_CPU_CORES` and `CONTAINER_MEMORY_BYTES` env vars.\n\n**ES**\n\n- `Dockerfile` establece `PUBLIC_HOST=localhost`, `PUBLIC_PORT=80`, `PUBLIC_SCHEME=http`, `PUBLIC_DB_HOST=localhost`, `PUBLIC_DB_PORT=5432` como valores por defecto.\n- Si el puerto mapeado en el host no es `80`, establecer `PUBLIC_PORT` explicitamente.\n- Si el puerto SQL mapeado no es `5432`, establecer `PUBLIC_DB_PORT` explicitamente.\n- Dentro de Docker, el panel no puede publicar puertos nuevos; los puertos publicados vienen de `docker run -p` o Compose.\n- Las listas de acceso SQL son aplicadas por HAProxy cuando no hay firewall del host disponible.\n- 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`.\n\n---\n\n## Dashboard Metrics / Metricas del Dashboard\n\n**EN**\n\n- On host installs, `/api/stats` uses `psutil` for CPU and memory.\n- On container installs, `/api/stats` reads cgroup v1/v2 files for container-accurate metrics.\n- Supports hybrid cgroup setups and walks up the cgroup hierarchy to find limits.\n- Uses `os.sched_getaffinity()` as a fallback for CPU set detection.\n- When cgroup detection fails, set `CONTAINER_CPU_CORES` and `CONTAINER_MEMORY_BYTES` as env var overrides.\n- Startup logs print detected cgroup version, assigned cores, and memory limits for diagnostics.\n- The dashboard cards show both current usage and assigned capacity.\n- Refresh interval: 10 seconds.\n\n**ES**\n\n- En instalaciones host, `/api/stats` usa `psutil` para CPU y memoria.\n- En instalaciones contenedor, `/api/stats` lee archivos cgroup v1/v2 para metricas precisas del contenedor.\n- Soporta configuraciones hibridas de cgroup y recorre la jerarquia cgroup buscando limites.\n- Usa `os.sched_getaffinity()` como fallback para deteccion de CPU set.\n- Si la deteccion de cgroup falla, usar `CONTAINER_CPU_CORES` y `CONTAINER_MEMORY_BYTES` como variables de entorno.\n- Los logs de inicio imprimen la version de cgroup detectada, cores asignados y limites de memoria para diagnostico.\n- Las tarjetas del dashboard muestran uso actual y capacidad asignada.\n- Intervalo de refresco: 10 segundos.\n\n---\n\n## Firewall Behavior / Comportamiento del Firewall\n\n**EN**\n\n- On host installs, the installer configures the native firewall safely and keeps existing rules intact.\n- Debian/Ubuntu: `ufw --force enable` for non-interactive installation.\n- RHEL-family: uses the current firewalld default zone.\n- Legacy `ALLOWED_PORTS=22,80,443,5432` is treated as unrestricted behavior for backwards compatibility.\n- Protected ports (SSH, web, SQL) are blocked from direct close/open operations in the UI.\n- In containers, SQL IP restrictions work through HAProxy ACLs.\n- When Tailscale is enabled, the Tailscale interface (`tailscale0`) is allowed through the firewall automatically.\n\n**ES**\n\n- En instalaciones host, el instalador configura el firewall nativo de forma segura y preserva reglas existentes.\n- Debian/Ubuntu: `ufw --force enable` para instalacion no interactiva.\n- Familia RHEL: usa la zona por defecto actual de firewalld.\n- El valor legacy `ALLOWED_PORTS=22,80,443,5432` se trata como comportamiento sin restriccion por compatibilidad.\n- Puertos protegidos (SSH, web, SQL) estan bloqueados de operaciones directas de cierre/apertura en la UI.\n- En contenedores, las restricciones de IP de SQL funcionan a traves de ACLs de HAProxy.\n- Cuando Tailscale esta habilitado, la interfaz de Tailscale (`tailscale0`) se permite en el firewall automaticamente.\n\n---\n\n## Troubleshooting / Solucion de Problemas\n\n**EN** | If the installer stops at `[1/11]`, re-run in debug mode:  \n**ES** | Si el instalador se detiene en `[1/11]`, re-ejecutar en modo debug:\n\n```bash\nTHL_INSTALL_DEBUG=1 \\\nTHL_INSTALL_LOG_FILE=/var/log/thl-sql-install.log \\\n  curl -fsSL https://raw.githubusercontent.com/thl-corporation/thl-sql/main/install.sh | bash\n```\n\n```bash\n# Quick diagnostics / Diagnosticos rapidos\ntail -n 120 /var/log/thl-sql-install.log\njournalctl -u pg_manager -n 80 --no-pager\n```\n\n### Domain notes / Notas de dominio\n\n- **EN** | If `THL_DOMAIN` is set, installer uses HTTPS with certbot. If empty, IP mode (`http://IP:PORT`).\n- **ES** | Si `THL_DOMAIN` esta definido, el instalador usa HTTPS con certbot. Si esta vacio, modo IP (`http://IP:PUERTO`).\n\n### Preflight on Ubuntu / Preflight en Ubuntu\n\n```bash\nid -u          # must be 0 (root) / debe ser 0 (root)\nsystemctl --version\n```\n\n---\n\n## Update Existing Server / Actualizar Servidor Existente\n\n```bash\ncd /var/www/pg_manager \u0026\u0026 git pull origin main \u0026\u0026 bash deploy_remote.sh\n```\n\n**EN** | `deploy_remote.sh` preserves Tailscale configuration during upgrades automatically.  \n**ES** | `deploy_remote.sh` preserva la configuracion de Tailscale durante actualizaciones automaticamente.\n\n---\n\n## Technical Validation / Validacion Tecnica\n\n**EN** | On the VPS:  \n**ES** | En el VPS:\n\n```bash\ncd /var/www/pg_manager\nsource venv/bin/activate\npython verify_deployment.py\npython server/run_sql_load_test.py --connections 1000 --hold-seconds 20 --sample-seconds 8\nbash server/run_test_suite.sh\n```\n\n**EN** | From an external client:  \n**ES** | Desde un cliente externo:\n\n```bash\npython verify_remote.py\n```\n\n---\n\n## Repository Sync / Sincronizacion de Repositorios\n\n```powershell\n./push_dual_repos.ps1              # push to both repos / push a ambos repos\n./push_dual_repos.ps1 -DryRun     # validate without publishing / validar sin publicar\n```\n\n**EN** | Targets: `thl-corporation/thl-sql` (corp) and `thl-corporation-spa/thl-sql` (SPA mirror).  \n**ES** | Destinos: `thl-corporation/thl-sql` (corp) y `thl-corporation-spa/thl-sql` (mirror SPA).\n\nEnvironment overrides: `THL_SQL_CORP_SSH_KEY`, `THL_SQL_SPA_REPO_URL`, `THL_SQL_SPA_LEGACY_REPO_URL`, `THL_SQL_CORP_REPO_URL`.\n\n---\n\n## Publication Safety / Seguridad de Publicacion\n\n**EN** | No real secrets are stored in git. Sensitive values use `*.example` templates. Keys and credentials are blocked in `.gitignore`.  \n**ES** | No se almacenan secretos reales en git. Los valores sensibles usan plantillas `*.example`. Claves y credenciales estan bloqueadas en `.gitignore`.\n\n```bash\nbash server/check_repo_safety.sh\n```\n\n---\n\n## Documentation / Documentacion\n\n- `docs/INSTALL_LINUX_MULTI_DISTRO.md`\n- `docs/REPLICAR_EN_OTRO_VPS.md`\n- `docs/PRUEBA_1000_CONEXIONES.md`\n- `INSTRUCCIONES_UPDATE_VPS.md`\n- `INSTRUCCIONES_TEST_REMOTO.md`\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthl-corporation%2Fthl-sql","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthl-corporation%2Fthl-sql","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthl-corporation%2Fthl-sql/lists"}