Skip to main content

Deployment & Operations Guide

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

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

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.md for current project status
  • Review docs/bugs.md for known issues
  • Consult CLAUDE.md for architecture details