From f7b7a27e53948e9f06d2db3b7c67c272f72478bc Mon Sep 17 00:00:00 2001 From: Huzaifa Inam Date: Fri, 7 Aug 2026 21:19:17 +0500 Subject: [PATCH] Ports fixed v0.4 --- COOLIFY.md | 78 ++++++++++++++++++++++++---------------------- README.md | 25 +++++---------- docker-compose.yml | 14 ++++++--- 3 files changed, 59 insertions(+), 58 deletions(-) diff --git a/COOLIFY.md b/COOLIFY.md index f13fd96..4969582 100644 --- a/COOLIFY.md +++ b/COOLIFY.md @@ -1,19 +1,41 @@ -# Coolify & PostgreSQL Deployment Guide +# Coolify Deployment & "No Available Server" Troubleshooting Guide This application consists of: 1. **Server Side**: Node.js + Express backend (`server.ts`) serving REST APIs, managing authentication, ledger reconciliation, audit logs, FX rates, SMTP dispatching, and financial reports. 2. **Database**: PostgreSQL (via `pg` connection pool) with automatic JSON fallback backup. -3. **Frontend**: React SPA served directly via Express in production. +3. **Frontend**: React SPA served directly via Express in production on port `3000`. --- -## 1. Quick Coolify Deployment Options +## 🔧 Resolving "No Available Server" in Coolify -### Option A: Docker Compose Deployment (Application + PostgreSQL in One Stack) +If Coolify displays **"No available server"** or Traefik returns a **503 / 502 error**, follow these exact fixes: + +### 1. Fix Health Check Path & IPv4 Resolution (Included in codebase) +- **Cause**: Alpine Linux `wget` resolves `localhost` to IPv6 (`::1`), while Node Express binds to IPv4 (`0.0.0.0`). When `wget` fails, Docker marks the container `unhealthy`, causing Coolify Traefik to drop the container. +- **Fix**: The updated `Dockerfile` and `docker-compose.yml` use native Node.js HTTP checks against `http://127.0.0.1:3000/api/health`: + ```bash + node -e "require('http').get('http://127.0.0.1:3000/api/health', (r) => process.exit(r.statusCode === 200 ? 0 : 1))" + ``` +- **Coolify UI Setting**: Under your resource in Coolify -> **Health Check**: + - **Path**: `/api/health` + - **Port**: `3000` + +### 2. Configure Exposed Port in Coolify UI +- **In Coolify Dashboard**: + - Open your deployed application/stack. + - Go to **Settings** -> **Exposed Port** (or **Port**). + - Ensure the port is set to `3000`. + +--- + +## 🚀 Deployment Methods in Coolify + +### Option A: Docker Compose Deployment (App + Dedicated PostgreSQL) 1. **In Coolify Dashboard**: - Click **+ Add Resource** -> **Docker Compose**. - - Point to your Git Repository or paste the contents of `docker-compose.yml`. + - Point to your Git Repository or paste `docker-compose.yml`. 2. **Environment Variables**: Add the following in Coolify: ```env @@ -21,7 +43,7 @@ This application consists of: PORT=3000 POSTGRES_PASSWORD=your_custom_secure_password - # SMTP Email Dispatch Settings + # SMTP Email Settings (Optional) SMTP_HOST=smtp.your-server.com SMTP_PORT=587 SMTP_USER=alerts@networkbank.com @@ -29,42 +51,24 @@ This application consists of: SMTP_FROM="Balance Sheet Portal " SMTP_USE_TLS=true ``` -3. **Deploy**: - - Coolify will build the app container and spin up a dedicated `postgres:16-alpine` database container with health checks and persistent volume storage (`balance_sheet_postgres_data`). The application uses `expose: "3000"` to avoid host port binding conflicts while allowing Coolify's reverse proxy (Traefik/Nginx) to route external web traffic. +3. **Health Check Endpoint**: Set path to `/api/health` on port `3000`. +4. **Deploy**: Coolify builds the app and provisions `postgres:16-alpine`. --- -### Option B: Coolify Managed PostgreSQL + Standalone App Container +### Option B: Standalone Application Container (Using Coolify Managed PostgreSQL) -If you prefer using Coolify's built-in managed PostgreSQL database resource: - -1. **Create Database in Coolify**: +1. **Create PostgreSQL Resource**: - Click **+ Add Resource** -> **PostgreSQL**. - - Coolify will provide an internal database connection URL (e.g., `postgresql://postgres:pass@coolify-postgres-host:5432/balance_sheet_db`). -2. **Deploy App Service**: - - Add your Git repo as a **Dockerfile** application. - - Set environment variable in Coolify UI: + - Note the database internal connection string (e.g. `postgresql://postgres:pass@postgres-host:5432/balance_sheet_db`). +2. **Create Dockerfile Application**: + - Add Git Repository as a **Dockerfile Application**. + - Set Environment Variables: ```env - DATABASE_URL=postgresql://postgres:pass@coolify-postgres-host:5432/balance_sheet_db + NODE_ENV=production PORT=3000 - - # SMTP Email Settings - SMTP_HOST=smtp.your-server.com - SMTP_PORT=587 - SMTP_USER=alerts@networkbank.com - SMTP_PASS=your_smtp_password + DATABASE_URL=postgresql://postgres:pass@postgres-host:5432/balance_sheet_db ``` -3. **Deploy**: - - The Express server will automatically connect to the PostgreSQL database, create the necessary table structures on boot, and store all portal state in PostgreSQL. - ---- - -## 2. Server-Side Architecture & Configuration - -- **Internal Container Port**: Application listens on `3000` inside the container (`EXPOSE 3000`). -- **Conflict Prevention**: Uses Docker Compose `expose` (`3000` for app, `5432` for postgres) instead of direct host port bindings to eliminate host interface port allocation conflicts. -- **SMTP Environment Overrides**: SMTP configuration (`SMTP_HOST`, `SMTP_PORT`, `SMTP_USER`, `SMTP_PASS`, `SMTP_FROM`, `SMTP_USE_TLS`) is fully managed via environment variables. -- **Automatic Table Creation**: On server boot, the backend runs `initPgDatabase()` to verify/create `app_portal_state`. -- **Automatic State Recovery**: If PostgreSQL contains existing data, portal state is loaded directly from PostgreSQL. -- **Resilient Fallback**: If `DATABASE_URL` is omitted, the app gracefully operates using persistent JSON storage (`/app/data/portal-data.json`). -- **Health Check**: Express exposes `GET /api/health` for Docker container monitoring. + - In Settings -> **Exposed Port**: Set to `3000`. + - In Health Check: Set path to `/api/health`. +3. **Deploy**: Express connects directly to PostgreSQL and initializes required tables automatically. diff --git a/README.md b/README.md index 901d32a..e368560 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ A full-stack enterprise web application built for multi-branch balance sheet con - **Multi-Branch Operations**: Head Office Admin, Branch Users, Maker-Checker authorization matrix. - **Server-Side Architecture**: Express backend (`server.ts`) handling state management, calculations, audit logging, and email dispatches. - **PostgreSQL & Fallback Storage**: Connects to PostgreSQL via `pg` connection pool with automatic fallback to JSON data persistence (`/app/data/portal-data.json`). -- **Containerized Deployment**: Ready for Docker, Docker Compose, and **Coolify** self-hosting. +- **Containerized Deployment**: Built for Docker, Docker Compose, and **Coolify** self-hosting. --- @@ -17,22 +17,22 @@ A full-stack enterprise web application built for multi-branch balance sheet con | File | Description | | :--- | :--- | -| `Dockerfile` & `dockerfile` | Multi-stage production container build (Vite client + Express CJS server, exposing port 3000). | -| `docker-compose.yml` | Full-stack orchestration using `expose: "3000"` and `expose: "5432"` to prevent host port binding conflicts. | -| `.dockerignore` | Defines context exclusions for slim Docker image builds. | +| `Dockerfile` & `dockerfile` | Multi-stage production container build (Vite client + Express CJS server, exposing port 3000 with IPv4 health check). | +| `docker-compose.yml` | Full-stack orchestration (App container on port 3000 + PostgreSQL container on port 5432). | +| `.dockerignore` | Context exclusions for slim Docker image builds. | | `.env.example` | Template environment variables (`DATABASE_URL`, `PORT`, `DATA_PATH`, `SMTP_*`). | -| `COOLIFY.md` | Complete deployment guide for Coolify platform & managed databases. | +| `COOLIFY.md` | Deployment & "No Available Server" troubleshooting guide for Coolify platform & Traefik proxies. | | `server.ts` | Express server entry point with PostgreSQL initialization, environment SMTP dispatching, and REST API routes. | --- ## 🛠️ Local Development & Running via Docker -### 1. Run via Docker Compose (With PostgreSQL & Exposed Port 3000) +### 1. Run via Docker Compose ```bash docker-compose up --build -d ``` -The application container exposes port `3000` internally via Docker network `expose` configuration, avoiding host port allocation conflicts. Reverse proxies (Coolify, Traefik, Nginx) or container networks route directly to port `3000`. +The application container exposes port `3000` (`http://localhost:3000`), with an automated health check on `/api/health`. ### 2. Run via Docker CLI ```bash @@ -40,17 +40,8 @@ docker build -t balance-sheet-portal . docker run -p 3000:3000 -v portal_data:/app/data balance-sheet-portal ``` -### 3. Native Node.js Development -```bash -# Install dependencies -npm install - -# Start development server (Express + Vite hot reload) -npm run dev -``` - --- ## ☁️ Deployment on Coolify -Refer to [`COOLIFY.md`](./COOLIFY.md) for step-by-step instructions on deploying via Docker Compose or Coolify Managed PostgreSQL. +Refer to [`COOLIFY.md`](./COOLIFY.md) for step-by-step instructions on deploying via Docker Compose or Coolify Managed PostgreSQL, and resolving Traefik "No available server" status. diff --git a/docker-compose.yml b/docker-compose.yml index 1f871f6..6913d0f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -15,8 +15,8 @@ services: volumes: - postgres_db_data:/var/lib/postgresql/data healthcheck: - test: ["CMD-SHELL", "pg_isready -U postgres -d balance_sheet_db"] - interval: 10s + test: ["CMD-SHELL", "pg_isready -U postgres"] + interval: 5s timeout: 5s retries: 5 @@ -31,10 +31,16 @@ services: depends_on: postgres: condition: service_healthy + ports: + - "3000:3000" expose: - "3000" + labels: + - "coolify.managed=true" + - "coolify.port=3000" environment: - NODE_ENV=production + - PORT=3000 - DATABASE_URL=postgresql://postgres:${POSTGRES_PASSWORD:-postgres_secure_pass_2026}@postgres:5432/balance_sheet_db - DATA_PATH=/app/data/portal-data.json - SMTP_HOST=${SMTP_HOST:-} @@ -46,8 +52,8 @@ services: volumes: - portal_data:/app/data healthcheck: - test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:3000/api/health"] - interval: 30s + test: ["CMD", "node", "-e", "require('http').get('http://127.0.0.1:3000/api/health', (r) => process.exit(r.statusCode === 200 ? 0 : 1))"] + interval: 15s timeout: 5s retries: 3 start_period: 10s