From ec8ce94082488258d951f16a606ff70d75d4af32 Mon Sep 17 00:00:00 2001 From: Nick Beckley Date: Fri, 10 Jul 2026 18:43:13 +0000 Subject: [PATCH] Add PlotDirector development deployment --- config/README.md | 4 +- config/nginx/README.md | 6 + config/nginx/plotdirector-dev.conf | 30 ++++ config/systemd/plotdirector-dev.service | 21 +++ docs/ARCHITECTURE.md | 51 ++++-- docs/BUILD-LOG.md | 57 +++++++ docs/REBUILD-GUIDE.md | 45 ++++- install/README.md | 7 + install/phases/50-plotdirector-dev.sh | 218 ++++++++++++++++++++++++ install/phases/README.md | 13 ++ 10 files changed, 435 insertions(+), 17 deletions(-) create mode 100644 config/nginx/plotdirector-dev.conf create mode 100644 config/systemd/plotdirector-dev.service create mode 100755 install/phases/50-plotdirector-dev.sh diff --git a/config/README.md b/config/README.md index a5b8ebc..7b5b746 100644 --- a/config/README.md +++ b/config/README.md @@ -41,7 +41,9 @@ Additional service directories may be added when those services are implemented. `config/sql-server/` contains the version-controlled Docker Compose definition and safe example environment file for the SQL Server container. The live environment file is stored outside the repository at `/etc/atlas/sql-server.env`. -`config/nginx/` contains the temporary Atlas default HTTP site configuration. Live nginx configuration is deployed under `/etc/nginx/`. +`config/nginx/` contains the temporary Atlas default HTTP site configuration and the PlotDirector development reverse-proxy configuration. Live nginx configuration is deployed under `/etc/nginx/`. + +`config/systemd/` contains source-controlled systemd unit templates. `plotdirector-dev.service` is deployed to `/etc/systemd/system/plotdirector-dev.service`. ## Security Considerations diff --git a/config/nginx/README.md b/config/nginx/README.md index fa5a89c..61d0e95 100644 --- a/config/nginx/README.md +++ b/config/nginx/README.md @@ -4,6 +4,8 @@ This directory contains version-controlled nginx configuration for Atlas. `atlas-default.conf` is the temporary default HTTP site. It serves a small static status page from `/var/www/atlas` and exposes `/health` for local validation. +`plotdirector-dev.conf` proxies `dev.plotdirector.com` to PlotDirector on `http://127.0.0.1:5050` and provides a lightweight `/health` endpoint. It is intentionally HTTP-only until the TLS phase. + Deployment locations: - Source configuration: `config/nginx/atlas-default.conf` @@ -11,5 +13,9 @@ Deployment locations: - Enabled site: `/etc/nginx/sites-enabled/atlas-default.conf` - Static content: `/var/www/atlas` - Health check: `/health` +- PlotDirector source configuration: `config/nginx/plotdirector-dev.conf` +- PlotDirector live configuration: `/etc/nginx/sites-available/plotdirector-dev.conf` +- PlotDirector enabled site: `/etc/nginx/sites-enabled/plotdirector-dev.conf` +- PlotDirector hostname: `dev.plotdirector.com` Do not store TLS private keys, live certificates, secrets, or PlotDirector-specific proxy credentials here. diff --git a/config/nginx/plotdirector-dev.conf b/config/nginx/plotdirector-dev.conf new file mode 100644 index 0000000..030b087 --- /dev/null +++ b/config/nginx/plotdirector-dev.conf @@ -0,0 +1,30 @@ +server { + listen 80; + listen [::]:80; + + server_name dev.plotdirector.com; + + access_log /var/log/nginx/plotdirector-dev-access.log; + error_log /var/log/nginx/plotdirector-dev-error.log; + + client_max_body_size 100m; + + location = /health { + add_header Content-Type text/plain; + return 200 "ok\n"; + } + + location / { + proxy_pass http://127.0.0.1:5050; + proxy_http_version 1.1; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_read_timeout 120s; + proxy_send_timeout 120s; + proxy_connect_timeout 30s; + } +} diff --git a/config/systemd/plotdirector-dev.service b/config/systemd/plotdirector-dev.service new file mode 100644 index 0000000..5de6ba6 --- /dev/null +++ b/config/systemd/plotdirector-dev.service @@ -0,0 +1,21 @@ +[Unit] +Description=PlotDirector development web application +After=network-online.target docker.service +Wants=network-online.target +Requires=docker.service + +[Service] +Type=simple +User=plotdirector +Group=plotdirector +WorkingDirectory=/srv/apps/plotdirector-dev/current +EnvironmentFile=/etc/plotdirector/plotdirector.env +ExecStart=/usr/bin/dotnet /srv/apps/plotdirector-dev/current/PlotLine.dll +Restart=on-failure +RestartSec=10 +SyslogIdentifier=plotdirector-dev +NoNewPrivileges=true +PrivateTmp=true + +[Install] +WantedBy=multi-user.target diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index c406932..d6f57fa 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -23,6 +23,8 @@ Atlas is a single physical development server. - Development volume: SSD mounted at `/srv` - Repository root: `/srv/repos` - Infrastructure repository: `/srv/repos/AI-Development-Server` +- PlotDirector source repository: `/srv/repos/PlotDirector` +- PlotDirector development deployment: `/srv/apps/plotdirector-dev/current` The intended model separates operating system state, SQL data, and development data. This supports rebuild and recovery by reducing reliance on the OS volume for mutable project data. @@ -80,20 +82,32 @@ Atlas is intended to support: Only components verified during implementation should be recorded as installed. -### Intended PlotDirector Deployment Topology +### PlotDirector Development Deployment Topology -PlotDirector deployment topology is not yet established. +PlotDirector is deployed for development from the `onboarding` branch. -Current assumptions: +- Repository: `git@git.catherinelynwood.com:nick/PlotDirector.git` +- Source path: `/srv/repos/PlotDirector` +- Entry project: `PlotLine/PlotLine.csproj` +- Target framework: `net10.0` +- Output assembly: `PlotLine.dll` +- Published path: `/srv/apps/plotdirector-dev/current` +- Uploads path: `/srv/apps/plotdirector-dev/uploads` +- Runtime environment file: `/etc/plotdirector/plotdirector.env` +- Service account: `plotdirector` +- systemd service: `plotdirector-dev` +- Kestrel endpoint: `http://127.0.0.1:5050` +- nginx hostname: `dev.plotdirector.com` +- Development database: `PlotDirector_Development` +- SQL login: `plotdirector_dev` -- Source repositories should live under `/srv/repos`. -- Build artefacts should be generated outside this infrastructure repository. -- Deployed applications should be separated from source repositories. -- SQL data should use `/sql` once SQL Server paths are confirmed. -- nginx may act as the reverse proxy if the application is exposed over HTTP or HTTPS. -- Docker may host one or more services if containerisation is adopted. +Windows LAN clients can test the development site with this hosts-file entry: -Specific PlotDirector service names, ports, deployment paths, database names, and rollback procedures are `TODO: Confirm during the relevant implementation phase.` +```text +192.168.10.10 dev.plotdirector.com +``` + +SMTP, Stripe, and OpenAI are intentionally unconfigured in the Atlas development runtime unless explicitly provided through protected runtime configuration. ### Role of nginx @@ -105,8 +119,10 @@ nginx is installed from the standard Ubuntu 26.04 repositories and currently ser - Version-controlled source: `config/nginx/atlas-default.conf` - Static site root: `/var/www/atlas` - Health endpoint: `http://192.168.10.10/health` +- PlotDirector development proxy source: `config/nginx/plotdirector-dev.conf` +- PlotDirector development hostname: `dev.plotdirector.com` -HTTPS, TLS certificates, and PlotDirector reverse-proxy configuration are not configured yet. +HTTPS and TLS certificates are not configured yet. ### Role of SQL Server @@ -141,6 +157,10 @@ The intended storage and responsibility model is: - Source repositories: `/srv/repos` - Infrastructure repository: `/srv/repos/AI-Development-Server` +- PlotDirector source repository: `/srv/repos/PlotDirector` +- PlotDirector published application: `/srv/apps/plotdirector-dev/current` +- PlotDirector runtime configuration: `/etc/plotdirector/plotdirector.env` +- PlotDirector uploads: `/srv/apps/plotdirector-dev/uploads` - Installer logs: `/var/log/atlas/install/` - Discovery and validation reports: `/var/log/atlas/reports/` - Future installer state and markers: `/var/lib/atlas/` @@ -163,6 +183,7 @@ Known trust boundaries: - Repository content versus live secret-bearing configuration. - SQL data on `/sql` versus source and scripts on `/srv`. - Future public-facing application traffic through nginx, if enabled. +- PlotDirector Kestrel listens only on loopback and is reached through nginx. Unresolved trust-boundary details: @@ -188,9 +209,10 @@ flowchart TB Scripts[Future operational scripts
scripts/] Tests[Future smoke tests
tests/] SQL[(SQL data volume
/sql)] - Deploy[Future deployed applications] - Nginx[nginx reverse proxy] + Deploy[PlotDirector dev deployment
/srv/apps/plotdirector-dev/current] + Nginx[nginx reverse proxy
dev.plotdirector.com] Docker[Docker runtime] + SqlContainer[SQL Server container
atlas-sql-server] end Repo --> Install @@ -198,7 +220,8 @@ flowchart TB Repo --> Scripts Repo --> Tests Source --> Deploy - Deploy --> SQL + Deploy --> SqlContainer + SqlContainer --> SQL Nginx --> Deploy Docker --> Deploy ``` diff --git a/docs/BUILD-LOG.md b/docs/BUILD-LOG.md index e758add..259a0d0 100644 --- a/docs/BUILD-LOG.md +++ b/docs/BUILD-LOG.md @@ -10,6 +10,63 @@ This file records chronological Atlas build and infrastructure milestones. Do no ### Phase +Phase 2 PlotDirector development deployment. + +### Objective + +Build and run the PlotDirector `onboarding` branch on Atlas behind nginx using the local SQL Server container. + +### Changes + +- Cloned PlotDirector at `/srv/repos/PlotDirector` from `git@git.catherinelynwood.com:nick/PlotDirector.git`. +- Confirmed branch `onboarding` tracks `origin/onboarding`. +- Built `PlotLine/PlotLine.csproj` targeting `net10.0`. +- Created runtime configuration at `/etc/plotdirector/plotdirector.env`. +- Created SQL database `PlotDirector_Development`. +- Created SQL login `plotdirector_dev`. +- Applied numbered SQL scripts `001` through `131`; `Stripe_Price_IDs_Prod.sql` was not run. +- Published the application to `/srv/apps/plotdirector-dev/current`. +- Added systemd unit template `config/systemd/plotdirector-dev.service`. +- Added nginx proxy configuration `config/nginx/plotdirector-dev.conf`. +- Added deployment phase `install/phases/50-plotdirector-dev.sh`. + +### Validation + +- `dotnet restore` passed. +- `dotnet build --configuration Release` passed with zero warnings. +- `dotnet publish --configuration Release` passed. +- `plotdirector-dev` systemd service started and listened on `127.0.0.1:5050`. +- nginx proxied `dev.plotdirector.com` to Kestrel. +- `/health` returned HTTP 200 from nginx. +- The development database contained the expected schema after script application. + +### Problems + +- SQL script execution required `sqlcmd -I` from script `076` onward so `QUOTED_IDENTIFIER` was enabled. +- `/srv` was `0700`, which prevented the non-root service account from traversing to `/srv/apps`. Atlas now grants execute-only traversal on `/srv`. +- The repository contains legacy hard-coded connection strings. They were not copied into Atlas runtime configuration. + +### Decisions + +- Run the application as the non-root `plotdirector` service account. +- Keep Kestrel bound to `127.0.0.1:5050`. +- Use nginx hostname `dev.plotdirector.com` for LAN development. +- Leave SMTP, Stripe, and OpenAI unconfigured for smoke testing. + +### Git Commit + +Not yet committed. + +### Operator + +Codex. + +### Date + +2026-07-10 + +### Phase + Phase 2 nginx and firewall baseline. ### Objective diff --git a/docs/REBUILD-GUIDE.md b/docs/REBUILD-GUIDE.md index f0ac66a..01399b5 100644 --- a/docs/REBUILD-GUIDE.md +++ b/docs/REBUILD-GUIDE.md @@ -12,6 +12,7 @@ This guide describes the planned rebuild path for Atlas. At Phase 1, the reposit - Docker installation script: present. - SQL Server container installation script: present. - nginx installation script: present. +- PlotDirector development deployment script: present. - Other component installation scripts: not yet created. - Configuration templates: not yet created. - Operational scripts: not yet created. @@ -121,8 +122,12 @@ Planned bootstrap flow: 9. Run `install/phases/20-sql-server.sh` after Docker is available. 10. Run `install/phases/40-nginx.sh`. 11. Apply the UFW baseline rules. -12. Run additional ordered installation scripts from `install/phases/` when they exist. -13. Run smoke tests from `tests/` when they exist. +12. Clone PlotDirector to `/srv/repos/PlotDirector` on branch `onboarding`. +13. Create protected PlotDirector runtime configuration at `/etc/plotdirector/plotdirector.env`. +14. Initialise the `PlotDirector_Development` database using the numbered SQL scripts. +15. Run `install/phases/50-plotdirector-dev.sh`. +16. Run additional ordered installation scripts from `install/phases/` when they exist. +17. Run smoke tests from `tests/` when they exist. Bootstrap command sequence is `TODO: Confirm during the relevant implementation phase.` @@ -135,6 +140,7 @@ install/phases/10-dotnet.sh install/phases/20-sql-server.sh install/phases/30-docker.sh install/phases/40-nginx.sh +install/phases/50-plotdirector-dev.sh ``` Current Docker and SQL Server commands: @@ -172,6 +178,41 @@ Current firewall inspection command: sudo ufw status numbered ``` +Current PlotDirector development deployment command: + +```bash +install/phases/50-plotdirector-dev.sh +``` + +PlotDirector runtime details: + +- Source repository: `/srv/repos/PlotDirector` +- Required branch: `onboarding` +- Entry project: `PlotLine/PlotLine.csproj` +- Published path: `/srv/apps/plotdirector-dev/current` +- Runtime environment file: `/etc/plotdirector/plotdirector.env` +- Service: `plotdirector-dev` +- Kestrel endpoint: `http://127.0.0.1:5050` +- nginx hostname: `dev.plotdirector.com` +- Database: `PlotDirector_Development` +- SQL login: `plotdirector_dev` + +Use this Windows hosts-file entry for LAN testing: + +```text +192.168.10.10 dev.plotdirector.com +``` + +PlotDirector validation commands: + +```bash +systemctl is-active plotdirector-dev +journalctl -u plotdirector-dev --no-pager -n 100 +curl --noproxy '*' -fsS http://127.0.0.1:5050/ >/dev/null +curl --noproxy '*' -fsS -H 'Host: dev.plotdirector.com' http://127.0.0.1/ >/dev/null +sudo nginx -t +``` + Installation scripts must: - Be idempotent. diff --git a/install/README.md b/install/README.md index 21419e8..2f37cb3 100644 --- a/install/README.md +++ b/install/README.md @@ -55,6 +55,7 @@ install/phases/10-dotnet.sh install/phases/20-sql-server.sh install/phases/30-docker.sh install/phases/40-nginx.sh +install/phases/50-plotdirector-dev.sh ``` The .NET installer installs only the required .NET SDK packages and verifies them with `dotnet --list-sdks`. @@ -70,11 +71,17 @@ Docker is installed from Docker's official signed Ubuntu APT repository. SQL Ser nginx is installed from Ubuntu repositories and serves the temporary Atlas status site until PlotDirector routing is configured. +PlotDirector development deployment uses `/srv/repos/PlotDirector` on branch `onboarding`, publishes `PlotLine.dll` to `/srv/apps/plotdirector-dev/current`, runs as the `plotdirector` service account, and is proxied by nginx as `dev.plotdirector.com`. + +The PlotDirector runtime environment file is `/etc/plotdirector/plotdirector.env`. It contains secrets and must never be committed. + Runtime output belongs outside the repository: - `/var/log/atlas/install/` - `/var/log/atlas/reports/` - `/var/lib/atlas/` +- `/srv/apps/plotdirector-dev/current` +- `/srv/apps/plotdirector-dev/uploads` ## Security Considerations diff --git a/install/phases/50-plotdirector-dev.sh b/install/phases/50-plotdirector-dev.sh new file mode 100755 index 0000000..a990484 --- /dev/null +++ b/install/phases/50-plotdirector-dev.sh @@ -0,0 +1,218 @@ +#!/usr/bin/env bash +set -Eeuo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +INSTALL_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)" +REPO_ROOT="$(cd "${INSTALL_DIR}/.." && pwd)" + +# shellcheck source=install/lib/common.sh +source "${INSTALL_DIR}/lib/common.sh" +# shellcheck source=install/lib/logging.sh +source "${INSTALL_DIR}/lib/logging.sh" +# shellcheck source=install/lib/files.sh +source "${INSTALL_DIR}/lib/files.sh" + +atlas_set_script_name "50-plotdirector-dev.sh" +atlas_install_error_trap + +APP_REPO="/srv/repos/PlotDirector" +APP_BRANCH="onboarding" +APP_PROJECT="${APP_REPO}/PlotLine/PlotLine.csproj" +PUBLISH_DIR="/srv/apps/plotdirector-dev/current" +UPLOADS_DIR="/srv/apps/plotdirector-dev/uploads" +ENV_FILE="/etc/plotdirector/plotdirector.env" +SERVICE_USER="plotdirector" +SERVICE_NAME="plotdirector-dev" +SYSTEMD_SOURCE="${REPO_ROOT}/config/systemd/plotdirector-dev.service" +SYSTEMD_DEST="/etc/systemd/system/plotdirector-dev.service" +NGINX_SOURCE="${REPO_ROOT}/config/nginx/plotdirector-dev.conf" +NGINX_DEST="/etc/nginx/sites-available/plotdirector-dev.conf" +NGINX_LINK="/etc/nginx/sites-enabled/plotdirector-dev.conf" +NGINX_BACKUP_DIR="/etc/nginx/atlas-backups" +ALLOW_DIRTY=0 + +usage() { + cat <<'USAGE' +Usage: install/phases/50-plotdirector-dev.sh [options] + +Publish and run the PlotDirector onboarding branch as the Atlas development +instance behind nginx. This script does not modify PlotDirector source, +create Git commits, or store secrets. + +Prerequisites: + - /srv/repos/PlotDirector exists on branch onboarding. + - /etc/plotdirector/plotdirector.env exists and contains runtime settings. + - The PlotDirector development database has already been initialised. + +Options: + --help Show this help text. + --version Show script/framework version. + --dry-run Show intended actions without making changes. + --verbose Print additional diagnostic output. + --allow-dirty Permit deployment from a dirty PlotDirector working tree. + +USAGE +} + +while [[ "$#" -gt 0 ]]; do + case "$1" in + --help) + usage + exit "${ATLAS_EXIT_OK}" + ;; + --version) + atlas_print_version + exit "${ATLAS_EXIT_OK}" + ;; + --dry-run) + atlas_enable_dry_run + ;; + --verbose) + atlas_enable_verbose + ;; + --allow-dirty) + ALLOW_DIRTY=1 + ;; + *) + atlas_usage_error "Unknown option: $1" + exit "${ATLAS_EXIT_USAGE}" + ;; + esac + shift +done + +require_prerequisites() { + atlas_require_command git + atlas_require_command dotnet + atlas_require_command curl + atlas_require_sudo_noninteractive || { + atlas_log_error "Passwordless non-interactive sudo is required" + exit "${ATLAS_EXIT_PREREQ}" + } + + if [[ ! -d "${APP_REPO}/.git" ]]; then + atlas_log_error "PlotDirector repository not found at ${APP_REPO}" + exit "${ATLAS_EXIT_PREREQ}" + fi + + local current_branch + current_branch="$(git -C "$APP_REPO" branch --show-current)" + if [[ "$current_branch" != "$APP_BRANCH" ]]; then + atlas_log_error "Expected ${APP_REPO} to be on ${APP_BRANCH}; found ${current_branch}" + exit "${ATLAS_EXIT_UNSAFE}" + fi + + if [[ "$ALLOW_DIRTY" != "1" ]] && [[ -n "$(git -C "$APP_REPO" status --porcelain)" ]]; then + atlas_log_error "PlotDirector working tree is dirty. Use --allow-dirty only for deliberate local deployments." + exit "${ATLAS_EXIT_UNSAFE}" + fi + + if ! sudo -n test -f "$ENV_FILE"; then + atlas_log_error "Runtime environment file is missing: ${ENV_FILE}" + exit "${ATLAS_EXIT_PREREQ}" + fi +} + +ensure_runtime_user_and_dirs() { + if atlas_is_dry_run; then + atlas_log_info "Dry-run mode: would ensure ${SERVICE_USER} user and deployment directories" + return 0 + fi + + if ! id "$SERVICE_USER" >/dev/null 2>&1; then + sudo -n useradd --system --home-dir /srv/apps/plotdirector-dev --shell /usr/sbin/nologin --create-home "$SERVICE_USER" + fi + + sudo -n install -d -m 0750 -o "$SERVICE_USER" -g "$SERVICE_USER" /srv/apps/plotdirector-dev "$PUBLISH_DIR" "$UPLOADS_DIR" + local srv_mode + srv_mode="$(stat -c '%a' /srv)" + if (( (8#$srv_mode & 0001) == 0 )); then + sudo -n chmod o+x /srv + fi + sudo -n chown root:"$SERVICE_USER" /etc/plotdirector + sudo -n chmod 0750 /etc/plotdirector + sudo -n chown root:"$SERVICE_USER" "$ENV_FILE" + sudo -n chmod 0640 "$ENV_FILE" +} + +publish_application() { + if atlas_is_dry_run; then + atlas_log_info "Dry-run mode: would restore and publish ${APP_PROJECT} to ${PUBLISH_DIR}" + return 0 + fi + + local publish_tmp + publish_tmp="$(mktemp -d)" + dotnet restore "$APP_PROJECT" + dotnet publish "$APP_PROJECT" --configuration Release --output "$publish_tmp" + sudo -n rsync -a --delete "${publish_tmp}/" "${PUBLISH_DIR}/" + sudo -n chown -R "${SERVICE_USER}:${SERVICE_USER}" "$PUBLISH_DIR" "$UPLOADS_DIR" + sudo -n find "$PUBLISH_DIR" -type d -exec chmod 0750 {} + + sudo -n find "$PUBLISH_DIR" -type f -exec chmod 0640 {} + + rm -rf "$publish_tmp" +} + +deploy_systemd_unit() { + if atlas_is_dry_run; then + atlas_log_info "Dry-run mode: would deploy ${SYSTEMD_DEST}" + atlas_log_info "Dry-run mode: would enable ${SERVICE_NAME}" + return 0 + fi + + if [[ -f "$SYSTEMD_DEST" ]] && cmp -s "$SYSTEMD_SOURCE" "$SYSTEMD_DEST"; then + atlas_log_ok "No change required for ${SYSTEMD_DEST}" + else + sudo -n install -m 0644 -o root -g root "$SYSTEMD_SOURCE" "$SYSTEMD_DEST" + atlas_log_ok "Updated ${SYSTEMD_DEST}" + fi + sudo -n systemctl daemon-reload + sudo -n systemctl enable "$SERVICE_NAME" +} + +deploy_nginx_site() { + if atlas_is_dry_run; then + atlas_log_info "Dry-run mode: would deploy nginx site ${NGINX_DEST}" + return 0 + fi + + sudo -n install -d -m 0755 /etc/nginx/sites-available /etc/nginx/sites-enabled + sudo -n install -d -m 0750 "$NGINX_BACKUP_DIR" + sudo -n nginx -t + sudo -n install -m 0644 "$NGINX_SOURCE" "$NGINX_DEST" + sudo -n ln -sfn "$NGINX_DEST" "$NGINX_LINK" + sudo -n nginx -t +} + +restart_and_verify() { + if atlas_is_dry_run; then + atlas_log_info "Dry-run mode: would restart ${SERVICE_NAME}, reload nginx, and verify HTTP responses" + return 0 + fi + + sudo -n systemctl restart "$SERVICE_NAME" + + local attempt + for attempt in {1..30}; do + if curl -fsS http://127.0.0.1:5050/ >/dev/null 2>&1; then + break + fi + sleep 2 + done + + curl -fsS http://127.0.0.1:5050/ >/dev/null + sudo -n nginx -t + sudo -n systemctl reload nginx + curl -fsS -H "Host: dev.plotdirector.com" http://127.0.0.1/health >/dev/null + atlas_log_ok "PlotDirector development deployment verified" +} + +main() { + require_prerequisites + ensure_runtime_user_and_dirs + publish_application + deploy_systemd_unit + deploy_nginx_site + restart_and_verify +} + +main diff --git a/install/phases/README.md b/install/phases/README.md index b2dc3b7..e7d6a06 100644 --- a/install/phases/README.md +++ b/install/phases/README.md @@ -24,6 +24,7 @@ Each phase must source the shared framework under `install/lib/`, support dry-ru - `20-sql-server.sh`: deploys SQL Server 2025 Developer using Microsoft's official container image. - `30-docker.sh`: installs Docker Engine from Docker's official Ubuntu APT repository. - `40-nginx.sh`: installs nginx and deploys the temporary Atlas status site. +- `50-plotdirector-dev.sh`: publishes and restarts the PlotDirector development instance from `/srv/repos/PlotDirector`. Installed SDKs after the current Phase 2 run: @@ -36,3 +37,15 @@ Current SQL Server deployment: - Digest: `sha256:698682bab57c02c42bc0aa274b158aeb242d8e9104149a7489628d5535805816` - Container: `atlas-sql-server` - Compose project: `atlas-sql` + +Current PlotDirector development deployment: + +- Repository: `/srv/repos/PlotDirector` +- Branch: `onboarding` +- Entry project: `PlotLine/PlotLine.csproj` +- Target framework: `net10.0` +- Assembly: `PlotLine.dll` +- Published path: `/srv/apps/plotdirector-dev/current` +- Service: `plotdirector-dev` +- nginx hostname: `dev.plotdirector.com` +- Database: `PlotDirector_Development`