From 49e82d553fee0ec47aee904caa7ab29a42e1da48 Mon Sep 17 00:00:00 2001 From: jtricerolph Date: Tue, 25 Aug 2026 12:22:58 +0000 Subject: [PATCH] Add weather app: deploy_weather(), --only dispatch, full install chain LXC 131 / 10.10.10.131. Generates WEATHER_DB_PASS + WEATHER_SECRET (bearer token for the app's own /api/internal/forecast endpoint). Follows the same deploy_() shape as deploy_tasks(). Co-Authored-By: Claude Sonnet 5 --- install-stack.sh | 179 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 178 insertions(+), 1 deletion(-) diff --git a/install-stack.sh b/install-stack.sh index ffe0ae7..2d5048c 100755 --- a/install-stack.sh +++ b/install-stack.sh @@ -2328,6 +2328,174 @@ ${build_out}" npm_add_location "/kds/" "10.10.10.125" 3080 } +deploy_tasks() { + msg_step "Tasks (LXC 130 · 10.10.10.130)" + + if [[ -z "${TASKS_DB_PASS:-}" ]]; then + TASKS_DB_PASS=$(openssl rand -base64 24 | tr -dc 'a-zA-Z0-9' | head -c 24) + printf '\nTASKS_DB_PASS=%s\n' "$TASKS_DB_PASS" >> "$CREDS_FILE" + msg_ok "Generated TASKS_DB_PASS → ${CREDS_FILE}" + fi + + msg_info "Creating LXC 130" + create_lxc 130 "10.10.10.130" "tasks" 1024 1 + msg_ok "LXC 130 created" + + msg_info "Installing Docker" + install_docker 130 + install_mgmt_key 130 + msg_ok "Docker + SSH ready" + + msg_info "Creating tasks database" + pct exec 100 -- bash -c " + docker exec hotel-manage-postgres psql -U postgres -c \ + \"CREATE USER tasks WITH PASSWORD '${TASKS_DB_PASS}';\" 2>/dev/null || true + docker exec hotel-manage-postgres psql -U postgres -c \ + \"CREATE DATABASE tasks_db OWNER tasks;\" 2>/dev/null || true + docker exec hotel-manage-postgres psql -U postgres -d tasks_db -c \ + \"GRANT ALL ON SCHEMA public TO tasks;\" 2>/dev/null || true + " &>/dev/null + msg_ok "Database tasks_db ready" + + msg_info "Deploying tasks" + deploy_service 130 "tasks" "${REPO_ROOT}/tasks" /opt/tasks + + push_file 130 /opt/tasks/.env <&1"); then + msg_error "docker compose build failed in LXC 130: +${build_out}" + fi + + msg_info "Waiting for tasks" + wait_healthy 130 "http://localhost:3080/tasks/health" \ + && msg_ok "Tasks running at 10.10.10.130:3080" \ + || msg_warn "Tasks may need extra time — check LXC 130" + + msg_info "Seeding tasks 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 ('tasks', 'Tasks', 'Personal task planner — lists, reminders and recurring to-dos', '/tasks', 'ListChecks', '#0d9488', 'Operations', '10.10.10.130', 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 + ('use', 'Use Tasks', 'Create and manage your own lists and tasks', 1), + ('assign', 'Assign Tasks', 'Assign tasks to other users (phase 2)', 2), + ('admin', 'Manage All', 'View and manage every user''s tasks (phase 2)', 3), + ('settings', 'Settings', 'Configure tasks app settings', 4) + ) AS c(slug, name, description, sort_order) + WHERE a.slug = 'tasks' + 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 = 'tasks') + WHERE r.slug = 'staff' AND ac.slug = 'use' + ON CONFLICT DO NOTHING; + " &>/dev/null \ + && msg_ok "tasks seeded into auth DB" \ + || msg_warn "Seed failed — run tasks/seed-app.js manually" + + npm_add_location "/tasks/" "10.10.10.130" 3080 +} + +deploy_weather() { + msg_step "Weather (LXC 131 · 10.10.10.131)" + + if [[ -z "${WEATHER_DB_PASS:-}" ]]; then + WEATHER_DB_PASS=$(openssl rand -base64 24 | tr -dc 'a-zA-Z0-9' | head -c 24) + printf '\nWEATHER_DB_PASS=%s\n' "$WEATHER_DB_PASS" >> "$CREDS_FILE" + msg_ok "Generated WEATHER_DB_PASS → ${CREDS_FILE}" + fi + if [[ -z "${WEATHER_SECRET:-}" ]]; then + WEATHER_SECRET=$(openssl rand -hex 32) + printf '\nWEATHER_SECRET=%s\n' "$WEATHER_SECRET" >> "$CREDS_FILE" + msg_ok "Generated WEATHER_SECRET → ${CREDS_FILE}" + fi + + msg_info "Creating LXC 131" + create_lxc 131 "10.10.10.131" "weather" 1024 1 + msg_ok "LXC 131 created" + + msg_info "Installing Docker" + install_docker 131 + install_mgmt_key 131 + msg_ok "Docker + SSH ready" + + msg_info "Creating weather database" + pct exec 100 -- bash -c " + docker exec hotel-manage-postgres psql -U postgres -c \ + \"CREATE USER weather WITH PASSWORD '${WEATHER_DB_PASS}';\" 2>/dev/null || true + docker exec hotel-manage-postgres psql -U postgres -c \ + \"CREATE DATABASE weather_db OWNER weather;\" 2>/dev/null || true + docker exec hotel-manage-postgres psql -U postgres -d weather_db -c \ + \"GRANT ALL ON SCHEMA public TO weather;\" 2>/dev/null || true + " &>/dev/null + msg_ok "Database weather_db ready" + + msg_info "Deploying weather" + deploy_service 131 "weather" "${REPO_ROOT}/weather" /opt/weather + + push_file 131 /opt/weather/.env <&1"); then + msg_error "docker compose build failed in LXC 131: +${build_out}" + fi + + msg_info "Waiting for weather" + wait_healthy 131 "http://localhost:3080/weather/health" \ + && msg_ok "Weather running at 10.10.10.131:3080" \ + || msg_warn "Weather may need extra time — check LXC 131" + + msg_info "Seeding weather 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 ('weather', 'Weather', 'Reception forecast display — today hourly, next 2 days, 7-day outlook', '/weather/admin', 'CloudSun', '#0ea5e9', 'Hotel', '10.10.10.131', 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 + ('settings', 'Settings', 'View forecast fetch status and trigger a manual refresh', 1) + ) AS c(slug, name, description, sort_order) + WHERE a.slug = 'weather' + ON CONFLICT (app_id, slug) DO NOTHING; + " &>/dev/null \ + && msg_ok "weather seeded into auth DB" \ + || msg_warn "Seed failed — run weather/seed-app.js manually" + + npm_add_location "/weather/" "10.10.10.131" 3080 +} + # ════════════════════════════════════════════════════════════════════════════ # NPM PROXY HOSTS (via API) # ════════════════════════════════════════════════════════════════════════════ @@ -2576,7 +2744,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 reports kitchen kds wages utilities mqtt-broker hvac calendar plant" + VALID="postgres auth portal npm management noticeboard settings cashup hk-planner twin-optimiser room-planner maintenance forecasting rates reports kitchen kds wages utilities mqtt-broker hvac calendar plant tasks weather" [[ -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 @@ -2620,6 +2788,12 @@ if [[ "${1:-}" == "--only" ]]; then "$(openssl rand -base64 24 | tr -dc 'a-zA-Z0-9' | head -c 24)" [[ -z "${CALENDAR_DB_PASS:-}" ]] && _append_secret CALENDAR_DB_PASS \ "$(openssl rand -base64 24 | tr -dc 'a-zA-Z0-9' | head -c 24)" + [[ -z "${TASKS_DB_PASS:-}" ]] && _append_secret TASKS_DB_PASS \ + "$(openssl rand -base64 24 | tr -dc 'a-zA-Z0-9' | head -c 24)" + [[ -z "${WEATHER_DB_PASS:-}" ]] && _append_secret WEATHER_DB_PASS \ + "$(openssl rand -base64 24 | tr -dc 'a-zA-Z0-9' | head -c 24)" + [[ -z "${WEATHER_SECRET:-}" ]] && _append_secret WEATHER_SECRET \ + "$(openssl rand -hex 32)" USE_FORGEJO=true [[ -f /root/.ssh/hotel-manage_deploy.pub ]] \ @@ -2650,6 +2824,8 @@ if [[ "${1:-}" == "--only" ]]; then hvac) deploy_hvac ;; calendar) deploy_calendar ;; plant) deploy_plant ;; + tasks) deploy_tasks ;; + weather) deploy_weather ;; esac exit 0 fi @@ -2685,5 +2861,6 @@ deploy_wages deploy_hvac deploy_calendar deploy_plant +deploy_weather configure_npm_proxy_hosts print_summary