diff --git a/docs/README.md b/docs/README.md index 36f1f16..ef60bc5 100644 --- a/docs/README.md +++ b/docs/README.md @@ -13,7 +13,7 @@ docs walk you from a freshly forked repo to a production deploy. phone number, wire the webhook. 4. **[Environment variables](./environment-variables.md)** — the full reference. 5. **[Deploy on Hostinger](./deployment-hostinger.md)** — recommended hosting - walkthrough (Node.js VPS). + walkthrough (Managed Node.js Hosting). 6. **[Automations cron](./automations-and-cron.md)** — schedule the pending executions drain so waits and delays fire. 7. **[Troubleshooting](./troubleshooting.md)** — the usual suspects. @@ -26,8 +26,8 @@ docs walk you from a freshly forked repo to a production deploy. WhatsApp Business app. - A WhatsApp phone number that is **not** already tied to the regular WhatsApp or WhatsApp Business mobile apps. -- A [Hostinger](https://www.hostinger.com/vps-hosting) VPS plan (or any Node - host that supports long-running Node.js 20+ processes). +- A [Hostinger Managed Node.js Hosting](https://www.hostinger.com/web-apps-hosting) + plan (or any Node host that runs long-running Node.js 20+ processes). ## Stack at a glance @@ -35,7 +35,7 @@ docs walk you from a freshly forked repo to a production deploy. - **Database + auth + storage** — Supabase (Postgres + RLS). - **WhatsApp transport** — Meta Cloud API (official WhatsApp Business API). - **Encryption** — AES-256-CBC for per-user access tokens. -- **Scheduler** — external cron that pings `GET /api/automations/cron`. +- **Scheduler** — cron (or any pinger) that hits `GET /api/automations/cron`. ## Getting help diff --git a/docs/automations-and-cron.md b/docs/automations-and-cron.md index 92c9b76..e269f0d 100644 --- a/docs/automations-and-cron.md +++ b/docs/automations-and-cron.md @@ -34,25 +34,17 @@ Copy the result into `AUTOMATION_CRON_SECRET` in your deployment env. ## 2. Schedule the pinger -### Option A — cron on the same VPS (Hostinger) +### Option A — hPanel cron (Hostinger Managed Node.js) -```bash -crontab -e +hPanel → **Advanced → Cron Jobs** → add a new job set to every minute +(`* * * * *`). Command: + +``` +curl -s -H "x-cron-secret: " https://crm.example.com/api/automations/cron > /dev/null ``` -```cron -* * * * * curl -s -H "x-cron-secret: $AUTOMATION_CRON_SECRET" https://crm.example.com/api/automations/cron > /dev/null -``` - -Export the secret into the cron environment. The simplest way is to add -it to the user's shell profile and wrap the command: - -```cron -* * * * * bash -lc 'curl -s -H "x-cron-secret: $AUTOMATION_CRON_SECRET" https://crm.example.com/api/automations/cron > /dev/null' -``` - -Or, for a more disciplined setup, use a `systemd` timer with -`EnvironmentFile=/etc/wacrm.env`. +Paste the literal secret — hPanel cron jobs don't inherit the Node app's +environment variables. ### Option B — external pinger diff --git a/docs/deployment-hostinger.md b/docs/deployment-hostinger.md index 7785f2f..351ef21 100644 --- a/docs/deployment-hostinger.md +++ b/docs/deployment-hostinger.md @@ -1,158 +1,153 @@ # Deploy on Hostinger -Hostinger's **VPS Hosting** plans are the recommended way to run WaCRM in -production: you get a dedicated Node.js process, predictable pricing, and -Hostinger's `hPanel` handles SSL and firewalls for you. +Hostinger's **[Managed Node.js Hosting](https://www.hostinger.com/web-apps-hosting)** +is the recommended way to run WaCRM in production: Hostinger patches the +OS and the Node runtime, handles SSL, and gives you a Git-based deploy +flow from hPanel. You deploy from your fork without ever opening an SSH +session if you don't want to. -This walkthrough uses a VPS running Ubuntu 24.04. +This walkthrough assumes you have already completed +[getting-started](./getting-started.md), [supabase-setup](./supabase-setup.md), +and [whatsapp-setup](./whatsapp-setup.md) — i.e., your fork builds locally +and you have your Supabase + Meta credentials ready. -## 1. Provision the VPS +## 1. Buy a Managed Node.js plan -1. Sign up at and pick a plan. The - **KVM 2** tier (2 vCPU / 8 GB RAM) is a comfortable starting point. -2. During the setup wizard: - - **OS template** → Ubuntu 24.04 (plain, not the managed Node template — - we install what we need manually). - - **Location** → region closest to your users. - - **SSH key** → upload your public key (`~/.ssh/id_ed25519.pub` or - similar) so you can SSH in passwordless. -3. Wait for provisioning. In hPanel you will see the IPv4 address and - root credentials. +1. Sign up at and choose a + Node.js plan that gives you enough memory for `npm run build` (2 GB+ + recommended). +2. During the onboarding wizard, pick the **Node.js** stack and the region + closest to your users. +3. Finish setup until you land in **hPanel**. -## 2. SSH in and install dependencies +## 2. Create the app in hPanel -```bash -ssh root@ +In hPanel, open the hosting plan and go to **Websites → Create / Manage** +and pick the **Node.js** application option, then: -# Create a non-root user for the app -adduser wacrm -usermod -aG sudo wacrm -rsync --archive --chown=wacrm:wacrm ~/.ssh /home/wacrm +- **Application name** — `wacrm`. +- **Application root** — accept the default (e.g., `domains/yourdomain/public_html`). +- **Application URL** — the domain or subdomain you want to use (e.g., + `crm.example.com`). You can attach a domain now or later under + **Domains**. +- **Node.js version** — 20 or newer. +- **Application startup file / command** — Next.js uses `npm start` once + it is built, so set: + - Start command: `npm start` + - Alternatively: `node node_modules/next/dist/bin/next start -p $PORT` -# Switch user -su - wacrm +Save the app. hPanel provisions a container and shows you the app's +control page. -# Install Node.js 20 LTS -curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash - -sudo apt-get install -y nodejs git +## 3. Connect your GitHub fork -# Install PM2 for process management -sudo npm install --global pm2 -``` +In hPanel → **Git**: -## 3. Clone your fork +1. **Create repository** → paste your fork's HTTPS URL + (e.g., `https://github.com//wacrm.git`). +2. Pick the branch you want to deploy (usually `main`). +3. Set the deploy path to the **Application root** from step 2. -```bash -cd ~ -git clone https://github.com//wacrm.git -cd wacrm -npm ci -``` +Alternative: if you prefer ZIP uploads, use **File Manager** instead — +upload the repo contents into the application root. Git-based deploy is +simpler because redeploying is one click. -## 4. Configure env vars +## 4. Install dependencies and build -Create `/home/wacrm/wacrm/.env.local` with the values from -[environment-variables.md](./environment-variables.md). Make sure -`NEXT_PUBLIC_SITE_URL` is set to the exact public URL you will use -(e.g., `https://crm.example.com`). +hPanel's Node.js app page exposes a **Run NPM install** button and a +terminal. Either works: -```bash -chmod 600 .env.local -``` +- **Button flow**: + 1. Click **Run NPM install**. Wait for it to finish. + 2. Click **Run NPM Build** (or execute `npm run build` from the app + terminal). +- **Terminal flow**: + ```bash + npm ci + npm run build + ``` -## 5. Build and start with PM2 +> Next.js expects `NEXT_PUBLIC_*` variables to be present **at build +> time**, so set env vars (step 5) **before** running the build. -```bash -npm run build -pm2 start npm --name wacrm -- start -pm2 save -pm2 startup systemd -u wacrm --hp /home/wacrm -# Follow the command PM2 prints — it enables auto-start on reboot. -``` +## 5. Configure environment variables -WaCRM is now listening on `127.0.0.1:3000`. +In hPanel → **Node.js app → Environment variables**, add every value from +[environment-variables.md](./environment-variables.md): -## 6. Front with nginx + SSL +- `NEXT_PUBLIC_SUPABASE_URL` +- `NEXT_PUBLIC_SUPABASE_ANON_KEY` +- `SUPABASE_SERVICE_ROLE_KEY` +- `ENCRYPTION_KEY` +- `META_APP_SECRET` +- `NEXT_PUBLIC_SITE_URL` — set to `https://` (with the + scheme, without a trailing slash). +- `AUTOMATION_CRON_SECRET` — if you plan to use Wait steps + ([automations-and-cron.md](./automations-and-cron.md)). -Point your domain's `A` record at the VPS IP. Then: +Save, then **re-run the build** so the new `NEXT_PUBLIC_*` values get +baked into the client bundle. -```bash -sudo apt-get install -y nginx certbot python3-certbot-nginx -``` +## 6. Start the app -Create `/etc/nginx/sites-available/wacrm`: +From the app page, click **Restart application** (or run the equivalent +from the terminal). hPanel boots `npm start` behind its own reverse proxy +on the domain you configured. Hit the URL in a browser — you should land +on the WaCRM marketing page. -```nginx -server { - server_name crm.example.com; +SSL is provisioned automatically. If you used a subdomain, Hostinger's +AutoSSL usually takes a minute or two; until then the site may serve the +plain-HTTP version. - client_max_body_size 25m; # WhatsApp media upload ceiling - - location / { - proxy_pass http://127.0.0.1:3000; - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "upgrade"; - proxy_set_header Host $host; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - } - - listen 80; -} -``` - -Enable and issue a cert: - -```bash -sudo ln -s /etc/nginx/sites-available/wacrm /etc/nginx/sites-enabled/wacrm -sudo nginx -t && sudo systemctl reload nginx -sudo certbot --nginx -d crm.example.com -``` - -Certbot writes the 443 block, enables HTTP→HTTPS redirect, and schedules -renewals in `systemd`. - -## 7. Firewall - -hPanel → **Firewall**: allow inbound 22 (SSH), 80, 443. Everything else -stays closed. - -## 8. Update the Meta webhook +## 7. Update the Meta webhook Back in **Meta for Developers → WhatsApp → Configuration**, change the -callback URL to `https://crm.example.com/api/whatsapp/webhook` and re-verify. +callback URL to `https:///api/whatsapp/webhook` and re-verify. -## 9. Schedule the automation cron +## 8. Schedule the automations cron -Follow [automations-and-cron.md](./automations-and-cron.md) to drain -pending executions. A simple `cron` entry on the same VPS works: +If you use the Wait step in any automation, schedule the cron drain. -```bash -crontab -e -``` +- **Inside hPanel** — open **Advanced → Cron Jobs** and add: + ``` + * * * * * curl -s -H "x-cron-secret: " https:///api/automations/cron > /dev/null + ``` + Paste the literal secret here (cron jobs in hPanel don't read app env + vars) or store it in a file the cron reads. +- **Outside** — any uptime monitor (UptimeRobot, Better Stack, GitHub + Actions) can hit the URL once a minute. See + [automations-and-cron.md](./automations-and-cron.md) for detail. -```cron -* * * * * curl -s -H "x-cron-secret: $AUTOMATION_CRON_SECRET" https://crm.example.com/api/automations/cron > /dev/null -``` +## 9. Deploying updates -Load `AUTOMATION_CRON_SECRET` into the cron environment via -`/etc/environment` or an `EnvironmentFile=` in a `systemd` unit. +Two options: -## 10. Deploying updates +- **Click-deploy**: push to your fork, then hit **Pull** in hPanel → Git + and **Restart application**. +- **Terminal**: + ```bash + cd + git pull + npm ci + npm run build + # then restart from the Node.js app page + ``` -```bash -ssh wacrm@ -cd ~/wacrm -git pull -npm ci -npm run build -pm2 reload wacrm -``` +If the database schema changed, apply any new SQL files from +`supabase/migrations/` in the Supabase SQL editor first — migrations are +idempotent. -`pm2 reload` performs a zero-downtime restart. If the database schema -changed, apply any new SQL files from `supabase/migrations/` in the -Supabase SQL editor first — migrations are idempotent. +## When to reach for a VPS instead + +Managed Node.js covers most WaCRM deploys. Consider +[Hostinger VPS](https://www.hostinger.com/vps-hosting) if you need: + +- Long-running background workers beyond what the single Next.js process + gives you. +- System-level cron behaviour you can't replicate from hPanel. +- Custom binaries (e.g., ffmpeg) for media transforms. + +Otherwise, Managed Node.js is the fast path. ## Where to go next diff --git a/docs/environment-variables.md b/docs/environment-variables.md index 00852ce..4b88425 100644 --- a/docs/environment-variables.md +++ b/docs/environment-variables.md @@ -48,8 +48,9 @@ AUTOMATION_CRON_SECRET=generate-a-long-random-string ## Security checklist - Never commit `.env.local`. The repo already ignores it. -- On Hostinger / any VPS, set env vars via the platform's **Environment** - panel rather than writing them into a tracked file on disk. +- On Hostinger Managed Node.js (and any other host), set env vars via the + platform's **Environment variables** panel rather than writing them + into a tracked file on disk. - Rotate `SUPABASE_SERVICE_ROLE_KEY` if it leaks — Supabase lets you regenerate it under Project Settings → API. - Treat `ENCRYPTION_KEY` like a database master key. Losing it means diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md index 586c534..780e9c7 100644 --- a/docs/troubleshooting.md +++ b/docs/troubleshooting.md @@ -96,23 +96,32 @@ up. Either consolidate to one deploy or route the webhook to exactly one. ## Deploy -### `502 Bad Gateway` from nginx +### `502 Bad Gateway` or "Application not running" from Hostinger -- `pm2 status` — is the `wacrm` process up? -- `pm2 logs wacrm` — is the Node process crashing on boot (usually a - missing env var)? -- `sudo nginx -t` — is the nginx config valid? +- Open the Node.js app page in hPanel and confirm the status is **Started**. +- Check the app log viewer for a crash on boot — almost always a missing + env var. Re-save your env vars, re-run the build, and restart. +- Confirm the **Application startup command** is `npm start` (or + equivalent) and that a build has actually run (`.next/` exists in the + application root). -### Meta webhook works until the cert renews +### Env var changes don't take effect in the browser -Certbot renews in-place and reloads nginx. If you see a certificate error -right after renewal, restart nginx (`sudo systemctl restart nginx`) and -check `/var/log/letsencrypt/letsencrypt.log` for the last renew attempt. +`NEXT_PUBLIC_*` values are baked into the client bundle at build time. +After changing any of them, re-run `npm run build` (hPanel's **Run NPM +Build** button works) and restart the app. + +### Meta webhook suddenly stops after a domain change + +Hostinger provisions a new SSL certificate when you attach a new domain +or subdomain. Until it is issued, the webhook URL serves plain HTTP and +Meta rejects it. Wait for AutoSSL to complete (minutes), then re-verify +the webhook in Meta. ## Still stuck? Open an issue with: -- Environment (local / Hostinger / other). -- The exact error from server logs (`pm2 logs wacrm` or Next's dev output). +- Environment (local / Hostinger Managed Node.js / other). +- The exact error from the app log viewer in hPanel or Next's dev output. - What you were trying to do when it happened. diff --git a/src/components/landing/footer.tsx b/src/components/landing/footer.tsx index c3d2520..b465257 100644 --- a/src/components/landing/footer.tsx +++ b/src/components/landing/footer.tsx @@ -38,7 +38,7 @@ export function Footer() { }, { href: '#self-host', label: 'Self-host' }, { - href: 'https://www.hostinger.com/vps-hosting', + href: 'https://www.hostinger.com/web-apps-hosting', label: 'Deploy on Hostinger', external: true, }, diff --git a/src/components/landing/open-source.tsx b/src/components/landing/open-source.tsx index 733a3ec..49834df 100644 --- a/src/components/landing/open-source.tsx +++ b/src/components/landing/open-source.tsx @@ -3,7 +3,7 @@ import { Section, SectionHeader } from './section' import { GithubIcon } from './github-icon' const REPO_URL = 'https://github.com/ArnasDon/wacrm' -const HOSTINGER_URL = 'https://www.hostinger.com/vps-hosting' +const HOSTINGER_URL = 'https://www.hostinger.com/web-apps-hosting' export function OpenSource() { return ( @@ -11,7 +11,7 @@ export function OpenSource() {
@@ -53,11 +53,12 @@ export function OpenSource() {

- Best fit for this template — spin up a Node.js VPS, point it at - your forked repo, and WaCRM is live in a few minutes. + Best fit for this template — connect your forked repo to + Managed Node.js Hosting and WaCRM is live in a few minutes. No + servers to patch.

- Get Hostinger VPS + Managed Node.js Hosting