feat: initial KosmoConnect platform v0.1
Includes: - Backend services: ingestion (:8001), weather API (:8002), gateway (:8003), billing (:8004) with BTCPay integration - Shared asyncpg pool, TimescaleDB hypertable, Redis, Mosquitto MQTT - React frontend: Dashboard (MapLibre) and Messaging (chat UI) - Bridge daemon for Pi + Meshtastic (Serial/TCP T-Deck support) - Production Docker Compose, Nginx reverse proxy, ops scripts - DEPLOY.md with step-by-step deployment guide
This commit is contained in:
314
DEPLOY.md
Normal file
314
DEPLOY.md
Normal file
@@ -0,0 +1,314 @@
|
||||
# KosmoConnect Deployment Guide
|
||||
|
||||
This document walks you through deploying the entire KosmoConnect stack: cloud backend, web frontends, Raspberry Pi bridge daemon, and T-Deck integration.
|
||||
|
||||
---
|
||||
|
||||
## 1. Prerequisites
|
||||
|
||||
### Cloud Server (VPS or bare metal)
|
||||
- **OS**: Ubuntu 22.04 LTS or Debian 12 recommended
|
||||
- **RAM**: 2GB minimum, 4GB recommended
|
||||
- **Ports**: 22 (SSH), 80 (HTTP), 443 (HTTPS), 1883 (MQTT — can be restricted)
|
||||
- **Domain**: Optional but strongly recommended (e.g., `kosmo.example.com`)
|
||||
|
||||
### Raspberry Pi (Bridge Node)
|
||||
- **Model**: Pi 3B+ or Pi 4
|
||||
- **OS**: Raspberry Pi OS Lite (64-bit)
|
||||
- **Peripherals**: Reliable power supply, internet (WiFi or Ethernet)
|
||||
- **Meshtastic device**: T-Deck (WiFi mode) or T-Beam (USB)
|
||||
|
||||
### Local Development Machine
|
||||
- Docker & Docker Compose
|
||||
- Node.js 20+ and npm
|
||||
- Python 3.13+ (for testing)
|
||||
|
||||
---
|
||||
|
||||
## 2. Cloud Backend Deployment
|
||||
|
||||
### 2.1 Prepare the Server
|
||||
|
||||
```bash
|
||||
# On your server
|
||||
sudo apt update && sudo apt upgrade -y
|
||||
sudo apt install -y git docker.io docker-compose nginx certbot python3-certbot-nginx
|
||||
sudo usermod -aG docker $USER
|
||||
# Log out and back in for group changes to take effect
|
||||
```
|
||||
|
||||
### 2.2 Clone the Repository
|
||||
|
||||
```bash
|
||||
git clone https://your-repo/kosmo-connect.git
|
||||
cd kosmo-connect
|
||||
```
|
||||
|
||||
### 2.3 Configure Environment
|
||||
|
||||
```bash
|
||||
cd backend
|
||||
cp .env.prod.example .env
|
||||
nano .env
|
||||
```
|
||||
|
||||
Fill in:
|
||||
- `POSTGRES_PASSWORD` — strong random password
|
||||
- `BTCPAY_API_KEY`, `BTCPAY_STORE_ID`, `WEBHOOK_SECRET` — from your BTCPay Server
|
||||
|
||||
### 2.4 Build Web Frontends
|
||||
|
||||
```bash
|
||||
cd ../web
|
||||
./build.sh
|
||||
```
|
||||
|
||||
This produces:
|
||||
- `web/dashboard/dist/`
|
||||
- `web/messaging/dist/`
|
||||
|
||||
### 2.5 Start Backend Services
|
||||
|
||||
```bash
|
||||
cd ../backend
|
||||
docker-compose -f docker-compose.prod.yml up -d --build
|
||||
```
|
||||
|
||||
Services will be available on localhost ports inside the server:
|
||||
- API: `127.0.0.1:8002`
|
||||
- Ingestion: `127.0.0.1:8001`
|
||||
- Gateway: `127.0.0.1:8003`
|
||||
- Billing: `127.0.0.1:8004`
|
||||
- MQTT: `127.0.0.1:1883` (only locally exposed by default)
|
||||
|
||||
Nginx serves the static frontends on port 80 and proxies `/api` to the correct service.
|
||||
|
||||
### 2.6 Seed the Database (First Time Only)
|
||||
|
||||
```bash
|
||||
# Seed test users for dev / early testing
|
||||
docker-compose -f docker-compose.prod.yml exec -T timescaledb \
|
||||
psql -U kosmo -d kosmoconnect < migrations/002_seed_test_users.sql
|
||||
```
|
||||
|
||||
### 2.7 Configure SSL (Recommended)
|
||||
|
||||
If you have a domain pointing to the server:
|
||||
|
||||
```bash
|
||||
sudo certbot --nginx -d kosmo.example.com
|
||||
```
|
||||
|
||||
Update `backend/nginx.conf` to use HTTPS and redirect HTTP to HTTPS. Then reload nginx:
|
||||
|
||||
```bash
|
||||
docker-compose -f docker-compose.prod.yml restart nginx
|
||||
```
|
||||
|
||||
### 2.8 Open MQTT to the Bridge (If Needed)
|
||||
|
||||
By default, Mosquitto only listens on `127.0.0.1:1883`. If your Pi bridge needs to connect over the internet, you have two options:
|
||||
|
||||
**Option A: VPN / WireGuard** (recommended for security)
|
||||
- Run a WireGuard server on the cloud host
|
||||
- Connect the Pi as a peer
|
||||
- The Pi can then reach Mosquitto at `mosquitto:1883` internally
|
||||
|
||||
**Option B: Public MQTT with Authentication**
|
||||
- Change the Mosquitto port binding in `docker-compose.prod.yml` to `0.0.0.0:1883`
|
||||
- Enable TLS on Mosquitto and require username/password
|
||||
- Update `mosquitto.conf` with authentication
|
||||
|
||||
---
|
||||
|
||||
## 3. Raspberry Pi Bridge Deployment
|
||||
|
||||
### 3.1 Prepare the Pi
|
||||
|
||||
```bash
|
||||
# On the Pi
|
||||
sudo apt update
|
||||
sudo apt install -y python3-venv python3-pip git rsync
|
||||
```
|
||||
|
||||
### 3.2 Deploy from Your Dev Machine
|
||||
|
||||
```bash
|
||||
cd firmware/infrastructure-node/bridge-daemon
|
||||
./deploy-pi.sh 192.168.1.50 pi
|
||||
```
|
||||
|
||||
This copies the daemon to `/opt/kosmo-bridge` and installs the systemd service.
|
||||
|
||||
### 3.3 Configure the Bridge
|
||||
|
||||
Edit the service to point to your cloud MQTT broker:
|
||||
|
||||
```bash
|
||||
ssh pi@192.168.1.50
|
||||
sudo systemctl edit --full kosmo-bridge
|
||||
```
|
||||
|
||||
Example for **T-Deck over WiFi**:
|
||||
|
||||
```ini
|
||||
[Service]
|
||||
Environment="PYTHONUNBUFFERED=1"
|
||||
Environment="MQTT_HOST=kosmo.example.com"
|
||||
Environment="MQTT_PORT=1883"
|
||||
Environment="MESHTASTIC_HOST=192.168.1.45"
|
||||
Environment="MESHTASTIC_TCP_PORT=4403"
|
||||
Environment="GATEWAY_NODE_ID=!yourgateway01"
|
||||
```
|
||||
|
||||
Or for **USB T-Beam**:
|
||||
|
||||
```ini
|
||||
Environment="MQTT_HOST=kosmo.example.com"
|
||||
Environment="MQTT_PORT=1883"
|
||||
Environment="MESHTASTIC_DEVICE=/dev/ttyUSB0"
|
||||
Environment="GATEWAY_NODE_ID=!yourgateway01"
|
||||
```
|
||||
|
||||
### 3.4 Start and Monitor
|
||||
|
||||
```bash
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl restart kosmo-bridge
|
||||
sudo journalctl -u kosmo-bridge -f
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. T-Deck WiFi Setup
|
||||
|
||||
### 4.1 Enable WiFi on the T-Deck
|
||||
|
||||
Using the Meshtastic app on your phone or the Python CLI:
|
||||
|
||||
```bash
|
||||
meshtastic --host <t-deck-ip> --set wifi_ssid "YourNetwork" --set wifi_psk "YourPassword"
|
||||
```
|
||||
|
||||
Or via the device menu if the T-Deck firmware supports on-screen WiFi config.
|
||||
|
||||
### 4.2 Find the T-Deck IP
|
||||
|
||||
Check your router's DHCP table, or scan the network:
|
||||
|
||||
```bash
|
||||
nmap -p 4403 192.168.1.0/24
|
||||
```
|
||||
|
||||
You should see an open port `4403` on the T-Deck's IP.
|
||||
|
||||
### 4.3 Test Mesh Connectivity
|
||||
|
||||
Send a text message from another Meshtastic node. You should see it appear in the cloud logs:
|
||||
|
||||
```bash
|
||||
# On the cloud server
|
||||
docker-compose -f docker-compose.prod.yml logs -f gateway
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. BTCPay Server Webhook Configuration
|
||||
|
||||
1. Log in to `https://pay.cqre.net`
|
||||
2. Go to your store → **Webhooks** → **Create Webhook**
|
||||
3. Payload URL:
|
||||
```
|
||||
https://kosmo.example.com/api/v1/billing/webhooks/btcpay
|
||||
```
|
||||
4. Select events:
|
||||
- `Invoice created`
|
||||
- `Invoice settled`
|
||||
- `Invoice expired`
|
||||
- `Invoice invalid`
|
||||
5. Save and copy the **Webhook Secret**
|
||||
6. Paste it into your cloud server's `.env` as `WEBHOOK_SECRET`
|
||||
7. Restart billing:
|
||||
```bash
|
||||
cd backend
|
||||
docker-compose -f docker-compose.prod.yml restart billing
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. Post-Deployment Checklist
|
||||
|
||||
| Check | Command / Test |
|
||||
|-------|----------------|
|
||||
| Dashboard loads | Open `https://kosmo.example.com/` in browser |
|
||||
| Messaging client loads | Open `https://kosmo.example.com/messaging` |
|
||||
| API healthy | `curl https://kosmo.example.com/api/v1/weather/latest` |
|
||||
| Gateway healthy | `curl https://kosmo.example.com/api/v1/messages/conversations -H "X-User-ID: ..."` |
|
||||
| Billing healthy | `curl https://kosmo.example.com/api/v1/billing/invoices -H "X-User-ID: ..."` |
|
||||
| MQTT reachable from Pi | `nc -vz kosmo.example.com 1883` (or via VPN) |
|
||||
| Bridge daemon running | `ssh pi@... "sudo systemctl status kosmo-bridge"` |
|
||||
| Mesh messages flow | Send text from T-Deck, check gateway logs |
|
||||
| Web-to-mesh works | Send message from browser, receive on T-Deck |
|
||||
| BTCPay webhook works | Create invoice, pay it, verify subscription activates |
|
||||
|
||||
---
|
||||
|
||||
## 7. Updating After Deployment
|
||||
|
||||
### Update Backend
|
||||
|
||||
```bash
|
||||
cd kosmo-connect/backend
|
||||
git pull
|
||||
docker-compose -f docker-compose.prod.yml up -d --build
|
||||
```
|
||||
|
||||
### Update Web Frontends
|
||||
|
||||
```bash
|
||||
cd kosmo-connect/web
|
||||
./build.sh
|
||||
cd ../backend
|
||||
docker-compose -f docker-compose.prod.yml restart nginx
|
||||
```
|
||||
|
||||
### Update Bridge Daemon on Pi
|
||||
|
||||
```bash
|
||||
cd kosmo-connect/firmware/infrastructure-node/bridge-daemon
|
||||
./deploy-pi.sh 192.168.1.50 pi
|
||||
ssh pi@192.168.1.50 "sudo systemctl restart kosmo-bridge"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 8. Troubleshooting
|
||||
|
||||
### Dashboard shows no nodes
|
||||
- Verify ingestion service is running
|
||||
- Check that `simulate-bridge.py` or a real bridge is publishing to MQTT
|
||||
- Inspect ingestion logs: `docker-compose -f docker-compose.prod.yml logs ingestion`
|
||||
|
||||
### T-Deck not reachable over TCP
|
||||
- Ensure T-Deck and Pi are on the same WiFi network
|
||||
- Verify port 4403 is open: `nmap -p 4403 <t-deck-ip>`
|
||||
- Try restarting the T-Deck
|
||||
|
||||
### Bridge daemon cannot connect to MQTT
|
||||
- If using VPN, verify WireGuard tunnel is up (`wg show`)
|
||||
- If exposing MQTT publicly, confirm firewall rules allow port 1883
|
||||
- Check Mosquitto logs: `docker-compose -f docker-compose.prod.yml logs mosquitto`
|
||||
|
||||
### Messages send but T-Deck never receives them
|
||||
- Confirm the target `node_id` matches exactly (case-sensitive, includes `!`)
|
||||
- Check gateway logs for outbound publishes
|
||||
- Check bridge daemon logs for MQTT subscription hits
|
||||
|
||||
### BTCPay webhook not triggering subscriptions
|
||||
- Verify `WEBHOOK_SECRET` matches BTCPay exactly
|
||||
- Test webhook manually with a simulated payload
|
||||
- Check billing logs for signature verification errors
|
||||
|
||||
---
|
||||
|
||||
*"Through openness, we preserve. Through preservation, we evolve. Through evolution, we return."*
|
||||
Reference in New Issue
Block a user