Add deploy_kitchen (LXC 110) + deploy_kds (LXC 125) functions
- deploy_kitchen: 2 GB RAM, 10 GB disk; creates kitchen_db (shared with kds); FastAPI backend with MSSQL ODBC drivers (~5 min build); seeds 10 caps into auth DB - deploy_kds: 1 GB RAM; connects to kitchen_db (no separate DB — KDS shares schema); slim FastAPI build (httpx only, no MSSQL ODBC); seeds 3 caps + Staff role grants - KITCHEN_DB_PASS added to _append_secret section for --only deploys - Both added to case dispatch and full deploy sequence Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
5c345e47a9
commit
0275641243
1 changed files with 170 additions and 1 deletions
171
install-stack.sh
171
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 <<EOF
|
||||
APP_SLUG=kitchen
|
||||
DATABASE_URL=postgresql://kitchen:${KITCHEN_DB_PASS}@10.10.10.100:5432/kitchen_db
|
||||
CENTRAL_AUTH_SECRET=${CENTRAL_AUTH_SECRET}
|
||||
STACK_INTERNAL_SECRET=${STACK_INTERNAL_SECRET:-}
|
||||
SETTINGS_URL=http://10.10.10.116:3080
|
||||
SETTINGS_SECRET=${SETTINGS_SECRET}
|
||||
AZURE_DI_ENDPOINT=${AZURE_DI_ENDPOINT:-}
|
||||
AZURE_DI_KEY=${AZURE_DI_KEY:-}
|
||||
ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY:-}
|
||||
OFFICE_IP_CHECK=${OFFICE_IP_CHECK:-${OFFICE_IP:-disabled}}
|
||||
VITE_HOTEL_NAME=${SITE_NAME:-Hotel}
|
||||
EOF
|
||||
|
||||
# MSSQL ODBC drivers add ~5 min to the build
|
||||
msg_info "Building kitchen (MSSQL ODBC drivers — takes ~5 min)"
|
||||
local build_out
|
||||
if ! build_out=$(pct exec 110 -- bash -c "cd /opt/kitchen && docker compose up -d --build 2>&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 <<EOF
|
||||
APP_SLUG=kds
|
||||
DATABASE_URL=postgresql://kitchen:${KITCHEN_DB_PASS}@10.10.10.100:5432/kitchen_db
|
||||
CENTRAL_AUTH_SECRET=${CENTRAL_AUTH_SECRET}
|
||||
VITE_HOTEL_NAME=${SITE_NAME:-Hotel}
|
||||
EOF
|
||||
|
||||
local build_out
|
||||
if ! build_out=$(pct exec 125 -- bash -c "cd /opt/kds && docker compose up -d --build 2>&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 <service> (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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue