docs: replace Unraid stub with verified working install settings from production server
This commit is contained in:
128
README.md
128
README.md
@@ -27,14 +27,6 @@ docker run -d --name cpas-tracker \
|
|||||||
# http://localhost:3001
|
# http://localhost:3001
|
||||||
```
|
```
|
||||||
|
|
||||||
## Export for Unraid
|
|
||||||
|
|
||||||
```bash
|
|
||||||
docker save cpas-tracker | gzip > cpas-tracker.tar.gz
|
|
||||||
```
|
|
||||||
|
|
||||||
Then follow README_UNRAID_INSTALL.md.
|
|
||||||
|
|
||||||
## Update After Code Changes
|
## Update After Code Changes
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
@@ -45,6 +37,82 @@ docker run -d --name cpas-tracker -p 3001:3001 -v cpas-data:/data cpas-tracker
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## Deploying on Unraid
|
||||||
|
|
||||||
|
### Step 1 — Build and export the image on your dev machine
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker build -t cpas:latest .
|
||||||
|
docker save cpas:latest | gzip > cpas-latest.tar.gz
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 2 — Load the image on Unraid
|
||||||
|
|
||||||
|
Transfer `cpas-latest.tar.gz` to your Unraid server, then load it via the Unraid terminal:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker load < /path/to/cpas-latest.tar.gz
|
||||||
|
```
|
||||||
|
|
||||||
|
Confirm the image is present:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker images | grep cpas
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 3 — Create the appdata directory
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mkdir -p /mnt/user/appdata/cpas/db
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 4 — Run the container
|
||||||
|
|
||||||
|
This is the verified working `docker run` command for Unraid (bridge networking with static IP):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker run \
|
||||||
|
-d \
|
||||||
|
--name='cpas' \
|
||||||
|
--net='br0' \
|
||||||
|
--ip='10.2.0.14' \
|
||||||
|
--pids-limit 2048 \
|
||||||
|
-e TZ="America/Chicago" \
|
||||||
|
-e HOST_OS="Unraid" \
|
||||||
|
-e HOST_HOSTNAME="ALPHA" \
|
||||||
|
-e HOST_CONTAINERNAME="cpas" \
|
||||||
|
-e 'PORT'='3001' \
|
||||||
|
-e 'DB_PATH'='/data/cpas.db' \
|
||||||
|
-l net.unraid.docker.managed=dockerman \
|
||||||
|
-l net.unraid.docker.webui='http://[IP]:[PORT:3001]' \
|
||||||
|
-v '/mnt/user/appdata/cpas/db':'/data':'rw' \
|
||||||
|
cpas:latest
|
||||||
|
```
|
||||||
|
|
||||||
|
Access the app at `http://10.2.0.14:3001` (or whatever static IP you assigned).
|
||||||
|
|
||||||
|
### Key settings explained
|
||||||
|
|
||||||
|
| Setting | Value | Notes |
|
||||||
|
|---------|-------|-------|
|
||||||
|
| `--net` | `br0` | Unraid custom bridge network — gives the container its own LAN IP |
|
||||||
|
| `--ip` | `10.2.0.14` | Static IP on your LAN — adjust to match your subnet |
|
||||||
|
| `--pids-limit` | `2048` | Required — Puppeteer/Chromium spawns many processes for PDF generation; default Unraid limit is too low and will cause PDF failures |
|
||||||
|
| `PORT` | `3001` | Express listen port inside the container |
|
||||||
|
| `DB_PATH` | `/data/cpas.db` | SQLite database path inside the container |
|
||||||
|
| Volume | `/mnt/user/appdata/cpas/db` → `/data` | Persists the database across container restarts and rebuilds |
|
||||||
|
|
||||||
|
### Updating on Unraid
|
||||||
|
|
||||||
|
1. Build and export the new image on your dev machine (Step 1 above)
|
||||||
|
2. Load it on Unraid: `docker load < cpas-latest.tar.gz`
|
||||||
|
3. Stop and remove the old container: `docker stop cpas && docker rm cpas`
|
||||||
|
4. Re-run the `docker run` command from Step 4 — the volume mount preserves all data
|
||||||
|
|
||||||
|
> **Note:** The `--pids-limit 2048` flag is critical. Without it, Chromium hits Unraid's default PID limit and PDF generation silently fails or crashes the container.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
### Company Dashboard
|
### Company Dashboard
|
||||||
@@ -143,16 +211,16 @@ Scores are computed over a **rolling 90-day window** (negated violations exclude
|
|||||||
|
|
||||||
```
|
```
|
||||||
cpas/
|
cpas/
|
||||||
├── Dockerfile # Multi-stage: builds React + runs Express w/ Chromium
|
├── Dockerfile # Multi-stage: builds React + runs Express w/ Chromium
|
||||||
├── .dockerignore
|
├── .dockerignore
|
||||||
├── package.json # Backend (Express) deps
|
├── package.json # Backend (Express) deps
|
||||||
├── server.js # API + static file server
|
├── server.js # API + static file server
|
||||||
├── db/
|
├── db/
|
||||||
│ ├── schema.sql # Tables + 90-day active score view
|
│ ├── schema.sql # Tables + 90-day active score view
|
||||||
│ └── database.js # SQLite connection (better-sqlite3) + auto-migrations
|
│ └── database.js # SQLite connection (better-sqlite3) + auto-migrations
|
||||||
├── pdf/
|
├── pdf/
|
||||||
│ └── generator.js # Puppeteer PDF generation
|
│ └── generator.js # Puppeteer PDF generation
|
||||||
└── client/ # React frontend (Vite)
|
└── client/ # React frontend (Vite)
|
||||||
├── package.json
|
├── package.json
|
||||||
├── vite.config.js
|
├── vite.config.js
|
||||||
├── index.html
|
├── index.html
|
||||||
@@ -160,23 +228,23 @@ cpas/
|
|||||||
├── main.jsx
|
├── main.jsx
|
||||||
├── App.jsx
|
├── App.jsx
|
||||||
├── data/
|
├── data/
|
||||||
│ └── violations.js # All CPAS violation definitions + groups
|
│ └── violations.js # All CPAS violation definitions + groups
|
||||||
├── hooks/
|
├── hooks/
|
||||||
│ └── useEmployeeIntelligence.js # Score + history hook
|
│ └── useEmployeeIntelligence.js # Score + history hook
|
||||||
└── components/
|
└── components/
|
||||||
├── CpasBadge.jsx # Tier badge + color logic
|
├── CpasBadge.jsx # Tier badge + color logic
|
||||||
├── TierWarning.jsx # Pre-submit tier crossing alert
|
├── TierWarning.jsx # Pre-submit tier crossing alert
|
||||||
├── Dashboard.jsx # Company-wide leaderboard + audit log trigger
|
├── Dashboard.jsx # Company-wide leaderboard + audit log trigger
|
||||||
├── ViolationForm.jsx # Violation entry form
|
├── ViolationForm.jsx # Violation entry form
|
||||||
├── EmployeeModal.jsx # Employee profile + history modal
|
├── EmployeeModal.jsx # Employee profile + history modal
|
||||||
├── EditEmployeeModal.jsx # Employee edit + merge duplicate
|
├── EditEmployeeModal.jsx # Employee edit + merge duplicate
|
||||||
├── AmendViolationModal.jsx # Non-scoring field amendment + diff history
|
├── AmendViolationModal.jsx # Non-scoring field amendment + diff history
|
||||||
├── AuditLog.jsx # Filterable audit log panel
|
├── AuditLog.jsx # Filterable audit log panel
|
||||||
├── NegateModal.jsx # Negate/resolve violation dialog
|
├── NegateModal.jsx # Negate/resolve violation dialog
|
||||||
├── ViolationHistory.jsx # Violation list component
|
├── ViolationHistory.jsx # Violation list component
|
||||||
├── ExpirationTimeline.jsx # Per-violation 90-day roll-off countdown
|
├── ExpirationTimeline.jsx # Per-violation 90-day roll-off countdown
|
||||||
├── EmployeeNotes.jsx # Inline notes editor with quick-add HR tags
|
├── EmployeeNotes.jsx # Inline notes editor with quick-add HR tags
|
||||||
└── ReadmeModal.jsx # In-app admin documentation panel
|
└── ReadmeModal.jsx # In-app admin documentation panel
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
Reference in New Issue
Block a user