กำลังดำเนินการแปล
เอกสารนี้แสดงเป็นภาษาอังกฤษชั่วคราว ขณะกำลังจัดเตรียมเนื้อหาฉบับแปลภาษาไทย
Deployment Troubleshooting and Operations
Use this reference to diagnose operational errors, perform database health checks, and maintain long-term system stability.
พร้อมใช้งานแล้ว. ตรวจสอบล่าสุดเมื่อ: 26 October 2026.
Automated Readiness Health Check
Aqiled includes a dedicated readiness health check at /health/ready (SingleSchoolReadinessHealthCheck.cs).
curl -i http://127.0.0.1:5216/health/ready
Response Codes
HTTP 200 OK(Healthy): Database is connected, PostgreSQL 18 is validated, migrations are applied, and the school identity matches the deployment configuration.HTTP 503 Service Unavailable(Unhealthy): One or more dependencies failed startup checks. Inspect systemd logs for details:sudo journalctl -u school-api -n 50 --no-pager
Startup Validation Errors
1. PostgreSQL Version Incompatibility
- Error:
InvalidOperationException: DefaultConnection uses PostgreSQL 16.x. School.Api requires PostgreSQL 18.x. - Cause: The database server is running an older major version. Aqiled pins PostgreSQL 18.x for modern exclusion constraints and RLS capabilities.
- Solution: Upgrade your database to PostgreSQL 18 using the official PGDG repository.
2. Dedicated School Identity Mismatch
- Error:
InvalidOperationException: Dedicated school identity does not match deployment configuration. - Cause: The
Deployment:SchoolTenantIdin/etc/school/api.envdoes not match the UUID in thedeploymentidentitytable, or multiple schools exist in the database. - Solution:
- Inspect the marker in PostgreSQL:
SELECT schoolid FROM deploymentidentity WHERE id = 1; - Ensure
/etc/school/api.envhas the exact matching UUID:Deployment__SchoolTenantId=<MATCHING_UUID> - Never delete the marker or switch
Deployment:Modeback toMultiTenantto bypass this check.
- Inspect the marker in PostgreSQL:
3. Database Role & Row-Level Security Violations
- Error:
InvalidOperationException: DefaultConnection must use a restricted role subject to tenant row security. - Cause:
DefaultConnectionwas configured with a superuser account, or an account withBYPASSRLSor table ownership. - Solution:
Verify your connection strings in
/etc/school/api.env:DefaultConnectionmust useschool_app(NOBYPASSRLS).AdminConnectionmust useschool_admin(BYPASSRLS).- Neither connection may connect as the
postgressuperuser.
4. Missing Tenant RLS Policy
- Error:
InvalidOperationException: A tenant table is missing its row security policy; apply and review the AppDb migration. - Cause: A database table containing
tenantidis missing theschool_tenant_guardsecurity policy. - Solution: Re-run the AppDbContext migration bundle using the
school_migratoruser.
Networking & Runtime Issues
5. SignalR WebSocket Reconnect Loops
- Symptom: Parent notices, live chat, and attendance updates constantly fail with WebSocket connection errors in the browser console.
- Cause: Reverse proxy is stripping
UpgradeandConnectionheaders or using HTTP/1.0. - Solution:
Verify Nginx configuration includes:
proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade";
6. Front-End API Calls Failing with 404
- Symptom: The login page renders, but clicking submit fails or sends requests to external domains.
- Cause: The front-end was built with standard
npm run buildinstead ofnpm run build:dedicated. - Solution:
Rebuild front-end assets with:
cd front-end npm run build:dedicated sudo cp -r dist/dedicated/* /opt/school/web/current/
7. Background Jobs Triggering at the Wrong Hour
- Symptom: Daily Quran Hifz revision digests or data retention jobs fire during the school day rather than overnight.
- Cause: The host OS timezone is set to UTC, while the school operates in a different timezone (e.g. UTC+7).
- Solution:
- Set server timezone:
sudo timedatectl set-timezone Asia/Bangkok. - In the Aqiled School Admin dashboard, verify the school's configured timezone under System Settings.
- Set server timezone:
Maintenance & Backups
Automated Daily Backup
Create a daily backup script at /usr/local/sbin/school-backup:
#!/usr/bin/env bash
set -euo pipefail
BACKUP_DIR="/var/backups/school"
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="${BACKUP_DIR}/school_db_${DATE}.dump"
# Dump database using pg_dump custom format
sudo -u postgres pg_dump -Fc -d school_db > "${BACKUP_FILE}"
# Retain backups for 14 days
find "${BACKUP_DIR}" -type f -name "*.dump" -mtime +14 -delete
Make executable and schedule in cron:
sudo chmod +x /usr/local/sbin/school-backup
# Add to /etc/cron.d/school-backup:
# 0 2 * * * root /usr/local/sbin/school-backup
