Jobber/DEPLOY_GITEA_VM_CRON_TELEGRAM.md
ilia 9576c3d7a1 feat: workplace filter, job dedup, company skip docs, deploy notes
- Add remote/orchestrator filter by workplace (remote, not remote, unknown) with URL param
- Expose isRemote on job list API; canonicalize URLs and source_job_id dedup on import
- Onboarding: optional VITE_SKIP_RXRESUME_ONBOARDING for RxResume-free onboarding
- Scoring UI + docs for company skip list; pipeline-run dedup note
- Vitest: TZ=UTC for stable time-based tests
- DEPLOY_GITEA_VM_CRON_TELEGRAM.md for VM/cron/Telegram ops

Made-with: Cursor
2026-04-04 14:44:52 -04:00

180 lines
5.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Deploy on a VM or container, run the pipeline on a schedule, notify Telegram
This guide assumes you already pushed this repo to Gitea, for example:
```bash
git remote add gitea gitea@10.0.30.169:ilia/Jobber.git # or: git remote set-url gitea ...
git push -u gitea main
```
If you have **uncommitted** changes, commit them first, then push again:
```bash
git add -A && git commit -m "Your message" && git push gitea main
```
---
## 1. Deploy on a Linux VM (bare metal or cloud)
1. Install **Docker** and **Docker Compose** (plugin v2).
2. Clone from your Gitea server (SSH or HTTPS):
```bash
git clone gitea@10.0.30.169:ilia/Jobber.git
cd Jobber # or job-ops if you kept that folder name
```
3. Copy and edit environment:
```bash
cp .env.example .env
# Edit .env: MODEL / LLM keys, RXRESUME_*, search settings, etc.
```
4. Start the stack:
```bash
docker compose up -d
```
5. Open the UI: `http://<VM-IP>:3005` (port mapped in `docker-compose.yml`).
6. Persist data: the compose file mounts `./data` — back up that directory.
---
## 2. Deploy as a container (same image, any host)
Same as the VM path: only Docker is required. On the VM:
- Ensure port **3005** (or your chosen host port) is reachable if you use the UI from another machine.
- For **only** API/cron use from localhost, you can bind to `127.0.0.1:3005` by changing the `ports:` line in `docker-compose.yml` if you edit it (e.g. `"127.0.0.1:3005:3001"`).
Inside the container the app listens on **3001**; the host maps **3005 → 3001** by default.
**Cron on the host** should call the API on the host:
- UI: `http://127.0.0.1:3005` (browser)
- **API (orchestrator)**: `http://127.0.0.1:3005` — same port; requests to `/api/...` are served by the app behind the reverse proxy built into the image.
If your setup exposes the API only on an internal Docker network, use the container name and port `3001` from another container, or publish `3005` on the host and use `127.0.0.1:3005` from cron.
---
## 3. Run the pipeline three times a day (cron)
`POST /api/pipeline/run` **starts** the pipeline in the **background** and returns immediately (`{ ok: true, data: { message: "Pipeline started" } }`). That is enough for scheduling.
Example **crontab** entries (host time zone — adjust hours as you like):
```cron
# 08:00, 14:00, 20:00 daily — trigger JobOps pipeline
0 8,14,20 * * * /usr/local/bin/jobops-pipeline-run.sh >> /var/log/jobops-pipeline.log 2>&1
```
Create `/usr/local/bin/jobops-pipeline-run.sh`:
```bash
#!/usr/bin/env bash
set -euo pipefail
BASE_URL="${JOBOPS_URL:-http://127.0.0.1:3005}"
# If you set BASIC_AUTH_USER / BASIC_AUTH_PASSWORD in .env, uncomment:
# AUTH=(-u "${BASIC_AUTH_USER:?}:${BASIC_AUTH_PASSWORD:?}")
curl -sS -X POST "${BASE_URL}/api/pipeline/run" \
-H "Content-Type: application/json" \
-d '{}' \
"${AUTH[@]:-}" \
| tee -a /var/log/jobops-pipeline.log
echo >> /var/log/jobops-pipeline.log
```
```bash
sudo chmod +x /usr/local/bin/jobops-pipeline-run.sh
```
Optional: set `JOBOPS_URL` in roots crontab or in `/etc/environment` if the app is on another host.
**Basic Auth:** When `BASIC_AUTH_USER` and `BASIC_AUTH_PASSWORD` are set in `.env`, all non-GET API calls need Basic auth — use `curl -u user:pass` as above.
---
## 4. Telegram notifications
JobOps does **not** send Telegram directly. Practical options:
### Option A — Pipeline webhook (recommended)
1. In the app: **Settings → Webhooks** (or env `PIPELINE_WEBHOOK_URL` / `WEBHOOK_SECRET`) set a URL that receives JSON when a run **completes or fails**.
2. Point that URL to a **small relay** that translates the JSON into a Telegram `sendMessage` call.
Telegram API:
```text
https://api.telegram.org/bot<BOT_TOKEN>/sendMessage
```
Body (JSON):
```json
{
"chat_id": "<YOUR_CHAT_ID>",
"text": "Pipeline finished: ..."
}
```
You can host the relay on the same VM (Flask/FastAPI/Node, or **n8n** / **Webhook.site** + automation). Keep the **bot token** and **chat id** in env vars, not in the JobOps UI if possible.
Webhook payload shape (sanitized) includes fields like `event`, `pipelineRunId`, `jobsDiscovered`, `jobsProcessed`, `error` — see server code `notify-webhook.ts`.
### Option B — Cron wrapper: poll status, then Telegram
Because `/api/pipeline/run` returns before the run finishes, a simple approach:
1. Cron calls `jobops-pipeline-run.sh` (as above).
2. A **second** script (or same script extended) polls `GET /api/pipeline/status` until `isRunning` is false, then reads `GET /api/pipeline/runs` for the latest run and sends a short message via `curl` to Telegram.
Example **send** (replace token and chat id):
```bash
TELEGRAM_BOT_TOKEN="123456:ABC..."
CHAT_ID="your_numeric_chat_id"
MSG="$(printf 'JobOps pipeline finished. Check dashboard.')"
curl -sS -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \
-H "Content-Type: application/json" \
-d "{\"chat_id\":\"${CHAT_ID}\",\"text\":$(echo "$MSG" | jq -Rs .)}"
```
Get **chat_id**: message your bot, then open `https://api.telegram.org/bot<TOKEN>/getUpdates` and read `message.chat.id`.
### Option C — External automation
Use **n8n**, **Grafana OnCall**, or similar: trigger on schedule → HTTP POST ` /api/pipeline/run` → wait/poll → Telegram node.
---
## 5. Security notes
- Do not commit `.env` or Telegram tokens to Git.
- Prefer **Basic Auth** on the instance if it is reachable from the internet.
- Restrict firewall so only your IP (or VPN) can reach port 3005 if exposed.
---
## 6. Git remotes quick reference
```bash
git remote -v
git push gitea main # your Gitea
git push origin main # upstream GitHub (if you have rights)
```
---
## Related project docs
- Self-hosting: docs site **Self-Hosting** guide (if present in your tree).
- Webhooks: **Settings** documentation for pipeline / job-complete webhooks.
- Optional env: `PIPELINE_WEBHOOK_URL`, `WEBHOOK_SECRET`, `BASIC_AUTH_USER`, `BASIC_AUTH_PASSWORD` in `.env.example`.