Add PlotDirector development deployment

This commit is contained in:
Nick Beckley 2026-07-10 18:43:13 +00:00
parent 4dafddf8e5
commit ec8ce94082
10 changed files with 435 additions and 17 deletions

View File

@ -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/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 ## Security Considerations

View File

@ -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. `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: Deployment locations:
- Source configuration: `config/nginx/atlas-default.conf` - Source configuration: `config/nginx/atlas-default.conf`
@ -11,5 +13,9 @@ Deployment locations:
- Enabled site: `/etc/nginx/sites-enabled/atlas-default.conf` - Enabled site: `/etc/nginx/sites-enabled/atlas-default.conf`
- Static content: `/var/www/atlas` - Static content: `/var/www/atlas`
- Health check: `/health` - 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. Do not store TLS private keys, live certificates, secrets, or PlotDirector-specific proxy credentials here.

View File

@ -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;
}
}

View File

@ -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

View File

@ -23,6 +23,8 @@ Atlas is a single physical development server.
- Development volume: SSD mounted at `/srv` - Development volume: SSD mounted at `/srv`
- Repository root: `/srv/repos` - Repository root: `/srv/repos`
- Infrastructure repository: `/srv/repos/AI-Development-Server` - 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. 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. 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`. Windows LAN clients can test the development site with this hosts-file entry:
- 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.
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 ### 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` - Version-controlled source: `config/nginx/atlas-default.conf`
- Static site root: `/var/www/atlas` - Static site root: `/var/www/atlas`
- Health endpoint: `http://192.168.10.10/health` - 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 ### Role of SQL Server
@ -141,6 +157,10 @@ The intended storage and responsibility model is:
- Source repositories: `/srv/repos` - Source repositories: `/srv/repos`
- Infrastructure repository: `/srv/repos/AI-Development-Server` - 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/` - Installer logs: `/var/log/atlas/install/`
- Discovery and validation reports: `/var/log/atlas/reports/` - Discovery and validation reports: `/var/log/atlas/reports/`
- Future installer state and markers: `/var/lib/atlas/` - Future installer state and markers: `/var/lib/atlas/`
@ -163,6 +183,7 @@ Known trust boundaries:
- Repository content versus live secret-bearing configuration. - Repository content versus live secret-bearing configuration.
- SQL data on `/sql` versus source and scripts on `/srv`. - SQL data on `/sql` versus source and scripts on `/srv`.
- Future public-facing application traffic through nginx, if enabled. - Future public-facing application traffic through nginx, if enabled.
- PlotDirector Kestrel listens only on loopback and is reached through nginx.
Unresolved trust-boundary details: Unresolved trust-boundary details:
@ -188,9 +209,10 @@ flowchart TB
Scripts[Future operational scripts<br>scripts/] Scripts[Future operational scripts<br>scripts/]
Tests[Future smoke tests<br>tests/] Tests[Future smoke tests<br>tests/]
SQL[(SQL data volume<br>/sql)] SQL[(SQL data volume<br>/sql)]
Deploy[Future deployed applications] Deploy[PlotDirector dev deployment<br>/srv/apps/plotdirector-dev/current]
Nginx[nginx reverse proxy] Nginx[nginx reverse proxy<br>dev.plotdirector.com]
Docker[Docker runtime] Docker[Docker runtime]
SqlContainer[SQL Server container<br>atlas-sql-server]
end end
Repo --> Install Repo --> Install
@ -198,7 +220,8 @@ flowchart TB
Repo --> Scripts Repo --> Scripts
Repo --> Tests Repo --> Tests
Source --> Deploy Source --> Deploy
Deploy --> SQL Deploy --> SqlContainer
SqlContainer --> SQL
Nginx --> Deploy Nginx --> Deploy
Docker --> Deploy Docker --> Deploy
``` ```

View File

@ -10,6 +10,63 @@ This file records chronological Atlas build and infrastructure milestones. Do no
### Phase ### 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. Phase 2 nginx and firewall baseline.
### Objective ### Objective

View File

@ -12,6 +12,7 @@ This guide describes the planned rebuild path for Atlas. At Phase 1, the reposit
- Docker installation script: present. - Docker installation script: present.
- SQL Server container installation script: present. - SQL Server container installation script: present.
- nginx installation script: present. - nginx installation script: present.
- PlotDirector development deployment script: present.
- Other component installation scripts: not yet created. - Other component installation scripts: not yet created.
- Configuration templates: not yet created. - Configuration templates: not yet created.
- Operational scripts: 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. 9. Run `install/phases/20-sql-server.sh` after Docker is available.
10. Run `install/phases/40-nginx.sh`. 10. Run `install/phases/40-nginx.sh`.
11. Apply the UFW baseline rules. 11. Apply the UFW baseline rules.
12. Run additional ordered installation scripts from `install/phases/` when they exist. 12. Clone PlotDirector to `/srv/repos/PlotDirector` on branch `onboarding`.
13. Run smoke tests from `tests/` when they exist. 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.` 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/20-sql-server.sh
install/phases/30-docker.sh install/phases/30-docker.sh
install/phases/40-nginx.sh install/phases/40-nginx.sh
install/phases/50-plotdirector-dev.sh
``` ```
Current Docker and SQL Server commands: Current Docker and SQL Server commands:
@ -172,6 +178,41 @@ Current firewall inspection command:
sudo ufw status numbered 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: Installation scripts must:
- Be idempotent. - Be idempotent.

View File

@ -55,6 +55,7 @@ install/phases/10-dotnet.sh
install/phases/20-sql-server.sh install/phases/20-sql-server.sh
install/phases/30-docker.sh install/phases/30-docker.sh
install/phases/40-nginx.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`. 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. 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: Runtime output belongs outside the repository:
- `/var/log/atlas/install/` - `/var/log/atlas/install/`
- `/var/log/atlas/reports/` - `/var/log/atlas/reports/`
- `/var/lib/atlas/` - `/var/lib/atlas/`
- `/srv/apps/plotdirector-dev/current`
- `/srv/apps/plotdirector-dev/uploads`
## Security Considerations ## Security Considerations

View File

@ -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

View File

@ -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. - `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. - `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. - `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: Installed SDKs after the current Phase 2 run:
@ -36,3 +37,15 @@ Current SQL Server deployment:
- Digest: `sha256:698682bab57c02c42bc0aa274b158aeb242d8e9104149a7489628d5535805816` - Digest: `sha256:698682bab57c02c42bc0aa274b158aeb242d8e9104149a7489628d5535805816`
- Container: `atlas-sql-server` - Container: `atlas-sql-server`
- Compose project: `atlas-sql` - 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`