diff --git a/install-stack.sh b/install-stack.sh index 4df54bc..b56948a 100755 --- a/install-stack.sh +++ b/install-stack.sh @@ -1503,6 +1503,169 @@ ${build_out}" npm_add_location "/reports/" "10.10.10.122" 3080 } +deploy_kitchen() { + msg_step "Kitchen (LXC 110 · 10.10.10.110)" + + if [[ -z "${KITCHEN_DB_PASS:-}" ]]; then + KITCHEN_DB_PASS=$(openssl rand -base64 24 | tr -dc 'a-zA-Z0-9' | head -c 24) + printf '\nKITCHEN_DB_PASS=%s\n' "$KITCHEN_DB_PASS" >> "$CREDS_FILE" + msg_ok "Generated KITCHEN_DB_PASS → ${CREDS_FILE}" + fi + + # 2 GB RAM — FastAPI + MSSQL ODBC drivers + Azure DI OCR + msg_info "Creating LXC 110 (2 GB RAM)" + create_lxc 110 "10.10.10.110" "kitchen" 2048 2 + pct resize 110 rootfs 10G &>/dev/null || true + msg_ok "LXC 110 created" + + msg_info "Installing Docker" + install_docker 110 + install_mgmt_key 110 + msg_ok "Docker + SSH ready" + + msg_info "Creating kitchen_db (shared by kitchen and kds)" + pct exec 100 -- bash -c " + docker exec hotel-manage-postgres psql -U postgres -c \ + \"CREATE USER kitchen WITH PASSWORD '${KITCHEN_DB_PASS}';\" 2>/dev/null || true + docker exec hotel-manage-postgres psql -U postgres -c \ + \"CREATE DATABASE kitchen_db OWNER kitchen;\" 2>/dev/null || true + docker exec hotel-manage-postgres psql -U postgres -d kitchen_db -c \ + \"GRANT ALL ON SCHEMA public TO kitchen;\" 2>/dev/null || true + " &>/dev/null + msg_ok "Database kitchen_db ready (schema applied by Python backend on first start)" + + msg_info "Deploying kitchen" + deploy_service 110 "kitchen" "${REPO_ROOT}/kitchen" /opt/kitchen + + # AZURE_DI_ENDPOINT and AZURE_DI_KEY are for the OCR invoice upload pipeline. + # ANTHROPIC_API_KEY enables the LLM integration (allergen / flag analysis). + # Leave blank to disable optional integrations; they can be added post-deploy via .env. + push_file 110 /opt/kitchen/.env <&1"); then + msg_error "docker compose build failed in LXC 110: +${build_out}" + fi + + msg_info "Waiting for kitchen" + wait_healthy 110 "http://localhost:3080/kitchen/health" 200 \ + && msg_ok "Kitchen running at 10.10.10.110:3080" \ + || msg_warn "Kitchen may need extra time — check LXC 110 logs" + + msg_info "Seeding kitchen into auth DB" + pct exec 100 -- docker exec hotel-manage-postgres psql -U postgres -d auth_db -c " + INSERT INTO apps (slug, name, description, base_path, icon, theme_color, category, internal_host, internal_port) + VALUES ('kitchen', 'Kitchen', 'Invoice/GP, recipes, menus and kitchen management', '/kitchen', 'ChefHat', '#0d9488', 'Kitchen', '10.10.10.110', 3080) + ON CONFLICT (slug) DO UPDATE SET + name=EXCLUDED.name, description=EXCLUDED.description, base_path=EXCLUDED.base_path, + icon=EXCLUDED.icon, theme_color=EXCLUDED.theme_color, category=EXCLUDED.category, + internal_host=EXCLUDED.internal_host, internal_port=EXCLUDED.internal_port; + INSERT INTO app_capabilities (app_id, slug, name, description, sort_order) + SELECT a.id, c.slug, c.name, c.description, c.sort_order + FROM apps a, (VALUES + ('view', 'View app', 'Access the kitchen app and dashboard', 1), + ('invoices', 'View invoices', 'View invoice list, details and search', 2), + ('invoices_manage', 'Manage invoices', 'Upload, edit, approve and delete invoices', 3), + ('disputes', 'Disputes', 'Open, manage and resolve invoice disputes', 4), + ('logbook', 'Wastage logbook', 'Record and view wastage logbook entries', 5), + ('orders', 'Purchase orders', 'Create and manage purchase orders', 6), + ('recipes', 'Recipes', 'View and edit recipes, ingredients and allergens', 7), + ('menus', 'Menus', 'Build, edit and publish menus and dishes', 8), + ('manage_flags', 'Manage flags', 'Review and dismiss food compliance and allergen flags', 9), + ('settings', 'Manage settings', 'App settings: integrations, API keys, SambaPOS config', 10) + ) AS c(slug, name, description, sort_order) + WHERE a.slug = 'kitchen' + ON CONFLICT (app_id, slug) DO NOTHING; + " &>/dev/null \ + && msg_ok "kitchen seeded into auth DB" \ + || msg_warn "Seed failed — run auth db.js manually" + + npm_add_location "/kitchen/" "10.10.10.110" 3080 +} + +deploy_kds() { + msg_step "KDS (LXC 125 · 10.10.10.125)" + + # KDS uses kitchen_db (shared schema). KITCHEN_DB_PASS must exist (deploy_kitchen first). + if [[ -z "${KITCHEN_DB_PASS:-}" ]]; then + msg_error "KITCHEN_DB_PASS not set — deploy kitchen first, or add it to ${CREDS_FILE}" + fi + + msg_info "Creating LXC 125" + create_lxc 125 "10.10.10.125" "kds" 1024 1 + msg_ok "LXC 125 created" + + msg_info "Installing Docker" + install_docker 125 + install_mgmt_key 125 + msg_ok "Docker + SSH ready" + + msg_info "Deploying kds" + deploy_service 125 "kds" "${REPO_ROOT}/kds" /opt/kds + + push_file 125 /opt/kds/.env <&1"); then + msg_error "docker compose build failed in LXC 125: +${build_out}" + fi + + msg_info "Waiting for kds" + wait_healthy 125 "http://localhost:3080/kds/health" 200 \ + && msg_ok "KDS running at 10.10.10.125:3080" \ + || msg_warn "KDS may need extra time — check LXC 125 logs" + + msg_info "Seeding kds into auth DB" + pct exec 100 -- docker exec hotel-manage-postgres psql -U postgres -d auth_db -c " + INSERT INTO apps (slug, name, description, base_path, icon, theme_color, category, internal_host, internal_port) + VALUES ('kds', 'Kitchen Display', 'SambaPOS ticket feed and course flow display', '/kds', 'Monitor', '#0d9488', 'Kitchen', '10.10.10.125', 3080) + ON CONFLICT (slug) DO UPDATE SET + name=EXCLUDED.name, description=EXCLUDED.description, base_path=EXCLUDED.base_path, + icon=EXCLUDED.icon, theme_color=EXCLUDED.theme_color, category=EXCLUDED.category, + internal_host=EXCLUDED.internal_host, internal_port=EXCLUDED.internal_port; + INSERT INTO app_capabilities (app_id, slug, name, description, sort_order) + SELECT a.id, c.slug, c.name, c.description, c.sort_order + FROM apps a, (VALUES + ('view', 'View board', 'View the KDS ticket board', 1), + ('manage', 'Manage courses', 'Call away, mark sent and clear courses on live tickets', 2), + ('settings', 'Manage settings', 'KDS timer thresholds, SambaPOS GraphQL config', 3) + ) AS c(slug, name, description, sort_order) + WHERE a.slug = 'kds' + ON CONFLICT (app_id, slug) DO NOTHING; + INSERT INTO role_capabilities (role_id, capability_id) + SELECT r.id, ac.id FROM roles r + JOIN app_capabilities ac ON ac.app_id = (SELECT id FROM apps WHERE slug = 'kds') + WHERE r.slug = 'staff' AND ac.slug IN ('view', 'manage') + AND NOT EXISTS (SELECT 1 FROM role_capabilities rc WHERE rc.role_id = r.id AND rc.capability_id = ac.id) + ON CONFLICT DO NOTHING; + " &>/dev/null \ + && msg_ok "kds seeded into auth DB" \ + || msg_warn "Seed failed — run auth db.js manually" + + npm_add_location "/kds/" "10.10.10.125" 3080 +} + # ════════════════════════════════════════════════════════════════════════════ # NPM PROXY HOSTS (via API) # ════════════════════════════════════════════════════════════════════════════ @@ -1751,7 +1914,7 @@ SUMMARY # Sources existing credentials and redeploys just the named service. if [[ "${1:-}" == "--only" ]]; then ONLY="${2:-}" - VALID="postgres auth portal npm management noticeboard settings cashup hk-planner twin-optimiser room-planner maintenance forecasting rates" + VALID="postgres auth portal npm management noticeboard settings cashup hk-planner twin-optimiser room-planner maintenance forecasting rates reports kitchen kds" [[ -z "$ONLY" ]] && msg_error "Usage: install-stack.sh --only (one of: ${VALID})" grep -qw "$ONLY" <<< "$VALID" || msg_error "Unknown service '${ONLY}'. Valid: ${VALID}" CREDS_FILE=/root/hotel-manage-credentials.txt @@ -1781,6 +1944,8 @@ if [[ "${1:-}" == "--only" ]]; then "$(openssl rand -base64 24 | tr -dc 'a-zA-Z0-9' | head -c 24)" [[ -z "${REPORTS_DB_PASS:-}" ]] && _append_secret REPORTS_DB_PASS \ "$(openssl rand -base64 24 | tr -dc 'a-zA-Z0-9' | head -c 24)" + [[ -z "${KITCHEN_DB_PASS:-}" ]] && _append_secret KITCHEN_DB_PASS \ + "$(openssl rand -base64 24 | tr -dc 'a-zA-Z0-9' | head -c 24)" USE_FORGEJO=true [[ -f /root/.ssh/hotel-manage_deploy.pub ]] \ @@ -1803,6 +1968,8 @@ if [[ "${1:-}" == "--only" ]]; then forecasting) deploy_forecasting ;; rates) deploy_rates ;; reports) deploy_reports ;; + kitchen) deploy_kitchen ;; + kds) deploy_kds ;; esac exit 0 fi @@ -1828,5 +1995,7 @@ deploy_maintenance deploy_forecasting deploy_rates deploy_reports +deploy_kitchen +deploy_kds configure_npm_proxy_hosts print_summary