New Page
Deployment & Operations Guide
This guide covers deploying and operating the Claw Machine Manager inventory system in various environments, from local testing to production deployment.
Table of Contents
- Prerequisites
- First-Time Deployment
- Moving to Production Server
- Day-to-Day Operations
- Wiping Data & Restarting
- Stopping Services
- When to Rebuild
- Configuration for Production
- Troubleshooting
Prerequisites
Required:
- Docker Engine 20.10+ and Docker Compose v2+
- 2GB+ available RAM
- 5GB+ available disk space
Verify installation:
docker --version # Should show 20.10+
docker compose version # Should show v2+
Network requirements:
- Ports 5432, 8000, and 56421 must be available
- Firewall rules allowing access to port 56421 (frontend) and optionally 8000 (API)
First-Time Deployment
Use these steps when deploying from scratch (fresh installation with no existing data).
Step 1: Navigate to Project Directory
cd /path/to/claw-machine-manager
Step 2: Start All Services
docker compose up -d
This starts three containers:
inventory-db(PostgreSQL 15)inventory-backend(FastAPI)inventory-frontend(Nginx)
Step 3: Wait for Database Health Check
# Check status (wait for "healthy" on db service)
docker compose ps
Expected output:
NAME STATUS
inventory-db Up X seconds (healthy)
inventory-backend Up X seconds
inventory-frontend Up X seconds
⏱️ This usually takes 5-10 seconds.
Step 4: Load Database Schema
docker exec -i inventory-db psql -U inventory_user -d inventory < db/schema.sql
You should see output like:
CREATE TABLE
CREATE TABLE
CREATE FUNCTION
CREATE TRIGGER
...
Step 5: Verify Schema Loaded
docker exec inventory-db psql -U inventory_user -d inventory -c "\dt"
Expected output should show 12 tables:
customers
inventory_balances
items
other_locations
po_line_items
purchase_orders
service_locations
suppliers
transfer_line_items
transfers
warehouse_locations
warehouses
Step 6: Access the Application
Open your browser to:
Frontend: http://localhost:56421
Backend API docs (optional): http://localhost:8000/docs
Moving to Production Server
Follow these steps when deploying to a production server for the first time.
Step 1: Transfer Project Files
Option A: Git Clone (Recommended)
# On production server
git clone <repository-url> /opt/claw-machine-manager
cd /opt/claw-machine-manager
Option B: SCP/RSYNC from Desktop
# From your desktop
rsync -avz --exclude 'db_data' \
/path/to/claw-machine-manager/ \
user@production-server:/opt/claw-machine-manager/
⚠️ Important: Do NOT copy the db_data/ directory or any existing database volumes.
Step 2: Configure for Production
Edit html/config.js and update the API URL:
window.APP_CONFIG = {
API_BASE_URL: 'http://your-server-ip:8000/api'
// Or use domain: 'https://api.yourdomain.com/api'
};
Edit docker-compose.yaml and update CORS origins (line 48):
CORS_ORIGINS: http://your-server-ip:56421,http://your-server-ip:8000,http://localhost:56421
Step 3: Deploy
Follow the same steps as First-Time Deployment above.
Step 4: Configure Firewall
# Allow frontend access
sudo ufw allow 56421/tcp
# Allow API access (if needed for external clients)
sudo ufw allow 8000/tcp
# Verify rules
sudo ufw status
Step 5: Verify External Access
From another machine:
curl http://your-server-ip:56421
curl http://your-server-ip:8000/api/health
Day-to-Day Operations
Starting Services (Normal Operation)
docker compose up -d
Data persists - All inventory, items, and configuration remain intact.
Viewing Logs
All services:
docker compose logs -f
Specific service:
docker compose logs -f backend
docker compose logs -f db
docker compose logs -f frontend
Recent logs only (last 50 lines):
docker compose logs --tail=50 backend
Checking Service Status
docker compose ps
Restarting a Service
Restart backend after code changes:
docker compose restart backend
Restart all services:
docker compose restart
Note: For Python code changes, restart is NOT needed - uvicorn auto-reloads.
Checking Resource Usage
docker stats inventory-backend inventory-db inventory-frontend
Wiping Data & Restarting
Use this when you need to completely reset the database (testing, starting fresh, etc.).
⚠️ WARNING: This Deletes ALL Data
Complete wipe (all data lost):
# Step 1: Stop services and delete volumes
docker compose down -v
# Step 2: Verify volumes removed
docker volume ls | grep claw-machine-manager
# Step 3: Start fresh
docker compose up -d
# Step 4: Wait for healthy database
docker compose ps
# Step 5: Load schema
docker exec -i inventory-db psql -U inventory_user -d inventory < db/schema.sql
# Step 6: Verify
docker exec inventory-db psql -U inventory_user -d inventory -c "\dt"
Alternative: Wipe Without Stopping
If you want to keep containers running:
# Step 1: Drop and recreate database
docker exec inventory-db psql -U inventory_user -d inventory -c "DROP SCHEMA public CASCADE; CREATE SCHEMA public;"
# Step 2: Reload schema
docker exec -i inventory-db psql -U inventory_user -d inventory < db/schema.sql
# Step 3: Restart backend to clear any cached data
docker compose restart backend
Stopping Services
Stop But Keep Data
Recommended for normal shutdown:
docker compose down
This stops and removes containers but preserves the database volume. All data remains intact.
Stop And Delete ALL Data
⚠️ WARNING: This deletes all inventory data permanently:
docker compose down -v
The -v flag removes volumes, including the database. Use only when:
- You want to start completely fresh
- You're done testing and want to clean up
- You've backed up data elsewhere
Stop Single Service
docker compose stop backend
docker compose stop frontend
docker compose stop db # ⚠️ Stops database - all services affected
Start Previously Stopped Service
docker compose start backend
When to Rebuild
The --build flag is only needed for the backend service (the only one with a custom Dockerfile).
You DON'T Need to Rebuild
Most common scenario - changes auto-reload:
| Changed File | Rebuild? | Action |
|---|---|---|
backend/*.py (Python code) |
❌ No | Nothing - auto-reloads |
html/*.html / *.js / *.css |
❌ No | Just refresh browser |
docker-compose.yaml |
❌ No | docker compose up -d |
db/schema.sql |
❌ No | Reload schema manually* |
* Schema reload: See Wiping Data & Restarting
You DO Need to Rebuild
When dependencies or build process changes:
| Changed File | Command |
|---|---|
backend/requirements.txt |
docker compose up -d --build backend |
backend/Dockerfile |
docker compose up -d --build backend |
| Any file copied in Dockerfile | docker compose up -d --build backend |
Rebuild Commands
Rebuild backend only:
docker compose up -d --build backend
Rebuild everything:
docker compose up -d --build
Force complete rebuild (clears Docker cache):
docker compose build --no-cache backend
docker compose up -d
Configuration for Production
Security Considerations
1. Change default database credentials
Edit docker-compose.yaml:
environment:
POSTGRES_DB: inventory
POSTGRES_USER: your_custom_user # Change this
POSTGRES_PASSWORD: your_secure_password # Change this
Also update in backend service:
DATABASE_URL: postgresql://your_custom_user:your_secure_password@db:5432/inventory
2. Restrict database port exposure
For production, remove external database access:
# REMOVE or comment out this section in db service:
# ports:
# - "5432:5432"
Database will only be accessible to backend container (more secure).
3. Configure CORS properly
Only allow your actual frontend domains:
CORS_ORIGINS: https://yourdomain.com,https://www.yourdomain.com
Never use wildcards (*) in production.
Reverse Proxy Setup (Optional)
For production, consider using a reverse proxy (Nginx Proxy Manager, Traefik, etc.):
Example Nginx config:
server {
listen 80;
server_name inventory.yourdomain.com;
location / {
proxy_pass http://your-server-ip:56421;
}
location /api/ {
proxy_pass http://your-server-ip:8000/api/;
}
}
Then update html/config.js:
window.APP_CONFIG = {
API_BASE_URL: '/api' // Relative URL when using reverse proxy
};
Backup Strategy
Backup database (while running):
# Create backup
docker exec inventory-db pg_dump -U inventory_user -d inventory > backup_$(date +%Y%m%d_%H%M%S).sql
# Restore backup (⚠️ overwrites existing data)
docker exec -i inventory-db psql -U inventory_user -d inventory < backup_20250117_120000.sql
Backup everything (while stopped):
docker compose down
tar -czf claw-machine-backup.tar.gz \
docker-compose.yaml \
backend/ \
html/ \
db/ \
nginx.conf
Troubleshooting
Services Won't Start
Check logs:
docker compose logs backend
docker compose logs db
Common issues:
| Symptom | Cause | Solution |
|---|---|---|
port is already allocated |
Port 5432, 8000, or 56421 in use | Stop conflicting service or change ports in docker-compose.yaml |
database not ready |
Database startup slow | Wait 30 seconds and check docker compose ps for "healthy" status |
| Backend crashloop | Missing dependencies | Run docker compose up -d --build backend |
Frontend Shows Blank Page
Check browser console (F12):
| Error | Cause | Solution |
|---|---|---|
Failed to fetch / CORS error |
Backend not accessible or CORS misconfigured | Verify backend URL in html/config.js and CORS_ORIGINS in docker-compose.yaml |
404 Not Found on template files |
Nginx not serving files correctly | Check docker compose logs frontend |
| JavaScript errors | Broken code | Check docker compose logs backend for errors |
Verify configuration:
# Check config.js loaded correctly
curl http://localhost:56421/config.js
# Test API directly
curl http://localhost:8000/api/health
Database Connection Errors
Verify database is running:
docker compose ps db
docker exec inventory-db pg_isready -U inventory_user
Check credentials match:
# In docker-compose.yaml, verify these match:
# - db service: POSTGRES_USER / POSTGRES_PASSWORD
# - backend service: DATABASE_URL
Reset database connection:
docker compose restart backend
Schema Changes Not Applied
Reload schema manually:
docker exec -i inventory-db psql -U inventory_user -d inventory < db/schema.sql
⚠️ This destroys all data. For production, write migration scripts instead.
Inventory Balances Not Updating
Verify trigger exists:
docker exec inventory-db psql -U inventory_user -d inventory -c "\df update_inventory_on_transfer_complete"
Check transfer status:
docker exec inventory-db psql -U inventory_user -d inventory -c "SELECT transfer_id, status FROM transfers ORDER BY created_at DESC LIMIT 5;"
Verify balances table:
docker exec inventory-db psql -U inventory_user -d inventory -c "SELECT * FROM inventory_balances LIMIT 10;"
If trigger is missing, reload schema (see above).
Quick Reference
First-time setup:
docker compose up -d
docker compose ps # Wait for "healthy"
docker exec -i inventory-db psql -U inventory_user -d inventory < db/schema.sql
Normal startup:
docker compose up -d
Stop (keep data):
docker compose down
Wipe and restart:
docker compose down -v
docker compose up -d
# Wait for healthy, then load schema
docker exec -i inventory-db psql -U inventory_user -d inventory < db/schema.sql
View logs:
docker compose logs -f backend
Rebuild after dependency changes:
docker compose up -d --build backend
Access application:
- Frontend: http://localhost:56421
- API docs: http://localhost:8000/docs
Support
For issues or questions:
- Check
docs/status.mdfor current project status - Review
docs/bugs.mdfor known issues - Consult
CLAUDE.mdfor architecture details