All checks were successful
Deploy to Server / deploy (push) Successful in 41s
149 lines
4.2 KiB
Markdown
149 lines
4.2 KiB
Markdown
# Train-ID
|
|
|
|
Simple Node/Express app to identify and inventory model trains from photos using OpenAI Vision, store results in MySQL, and export PDFs/XLSX.
|
|
|
|
## Requirements
|
|
- Node.js 20+ and npm
|
|
- MySQL 8+
|
|
- OpenAI API key
|
|
|
|
## Environment variables
|
|
Create a `.env` in the project root on the server:
|
|
|
|
```
|
|
PORT=3000
|
|
# OpenAI
|
|
OPENAI_API_KEY=sk-...
|
|
# or alternative variable name also supported by code:
|
|
# openapi_key=sk-...
|
|
|
|
# MySQL connection
|
|
db_ip=127.0.0.1
|
|
db_port=3306
|
|
db_user=trainid
|
|
db_pass=changeme
|
|
db_name=trainid
|
|
```
|
|
|
|
## Local development
|
|
```
|
|
npm install
|
|
npm run build
|
|
npm start
|
|
# or for auto-reload on TypeScript build changes:
|
|
npm run dev
|
|
```
|
|
Visit `http://localhost:3000`.
|
|
|
|
## API overview
|
|
- POST `/api/upload` with `multipart/form-data` field `image` → analyzes photo, inserts record
|
|
- GET `/api/items` → list items (optional `?q=` to search model/SKU)
|
|
- GET `/api/items/:id/pdf` → generate/download PDF for one item
|
|
- GET `/api/export/xlsx` → download XLSX export of inventory with embedded thumbnails
|
|
- DELETE `/api/items/:id` → delete one
|
|
- DELETE `/api/items` → wipe all
|
|
|
|
## Debian 13 (Trixie) LXC install
|
|
These steps assume a fresh Debian 13 LXC and deployment directory `/opt/Train-ID` with a system user `deployuser` that has passwordless sudo for service management.
|
|
|
|
1) Base packages and Node.js
|
|
```
|
|
sudo apt update
|
|
sudo apt install -y curl ca-certificates gnupg build-essential pkg-config
|
|
# Node 20 using Nodesource or Debian repo (choose one). Nodesource example:
|
|
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
|
|
sudo apt install -y nodejs
|
|
node -v && npm -v
|
|
```
|
|
|
|
2) MySQL server (or connect to external MySQL)
|
|
```
|
|
sudo apt install -y mariadb-server mariadb-client
|
|
sudo systemctl enable --now mariadb
|
|
sudo mysql -e "CREATE DATABASE IF NOT EXISTS trainid CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
|
|
sudo mysql -e "CREATE USER IF NOT EXISTS 'trainid'@'%' IDENTIFIED BY 'changeme';"
|
|
sudo mysql -e "GRANT ALL PRIVILEGES ON trainid.* TO 'trainid'@'%'; FLUSH PRIVILEGES;"
|
|
```
|
|
If using external MySQL, skip install and set `db_ip` etc. in `.env`.
|
|
|
|
3) App checkout and build
|
|
```
|
|
sudo mkdir -p /opt/Train-ID
|
|
sudo chown $USER:$USER /opt/Train-ID
|
|
git clone https://git.hudsonriggs.systems/HRiggs/Train-ID.git /opt/Train-ID
|
|
cd /opt/Train-ID
|
|
cp .env.example .env || true # if you keep a template in the future
|
|
# create .env as per above
|
|
npm ci || npm install
|
|
npm run build
|
|
```
|
|
|
|
4) Systemd service
|
|
Create `/etc/systemd/system/train-id.service`:
|
|
```
|
|
[Unit]
|
|
Description=Train-ID API
|
|
After=network.target
|
|
|
|
[Service]
|
|
Type=simple
|
|
WorkingDirectory=/opt/Train-ID
|
|
EnvironmentFile=/opt/Train-ID/.env
|
|
ExecStart=/usr/bin/node /opt/Train-ID/dist/server.js
|
|
Restart=always
|
|
RestartSec=5
|
|
User=www-data
|
|
Group=www-data
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
```
|
|
Then enable and start:
|
|
```
|
|
sudo systemctl daemon-reload
|
|
sudo systemctl enable --now train-id
|
|
sudo systemctl status train-id --no-pager
|
|
```
|
|
|
|
5) Reverse proxy (optional, for port 80/443)
|
|
Example Nginx site (`/etc/nginx/sites-available/train-id`):
|
|
```
|
|
server {
|
|
listen 80;
|
|
server_name _;
|
|
location / {
|
|
proxy_pass http://127.0.0.1:3000;
|
|
proxy_set_header Host $host;
|
|
proxy_set_header X-Real-IP $remote_addr;
|
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
proxy_set_header X-Forwarded-Proto $scheme;
|
|
}
|
|
}
|
|
```
|
|
Enable and reload:
|
|
```
|
|
sudo apt install -y nginx
|
|
sudo ln -s /etc/nginx/sites-available/train-id /etc/nginx/sites-enabled/train-id
|
|
sudo nginx -t && sudo systemctl reload nginx
|
|
```
|
|
|
|
## CI/CD deploy
|
|
The repo includes `.gitea/workflows/deploy.yaml` which, on push to `main`, SSHes to `192.168.30.114`, pulls latest, installs dependencies, builds, and restarts the `train-id` service. Set `DEPLOY_KEY` in repository secrets to a private SSH key authorized for `deployuser@192.168.30.114`.
|
|
|
|
If your service name or directory differ, update `SERVICE`/`APP_DIR` in the workflow accordingly.
|
|
|
|
```
|
|
apt update
|
|
apt install -y sudo
|
|
|
|
SYSCTL_PATH=$(command -v systemctl) # usually /bin/systemctl or /usr/bin/systemctl
|
|
cat >/etc/sudoers.d/train-id <<EOF
|
|
deployuser ALL=(root) NOPASSWD: ${SYSCTL_PATH} restart train-id, ${SYSCTL_PATH} restart train-id.service
|
|
EOF
|
|
chmod 440 /etc/sudoers.d/train-id
|
|
visudo -cf /etc/sudoers.d/train-id
|
|
|
|
sudo -n systemctl restart train-id
|
|
```
|
|
|