feat: add deployment script and systemd service #5

Merged
Pertempto merged 11 commits from 0-deployment-script into main 2025-11-21 14:49:57 -05:00
Pertempto commented 2025-11-21 13:25:39 -05:00 (Migrated from github.com)

Summary

  • Add systemd service file for running the backend as a proper service
  • Create deployment script with backup, verification, and rollback capabilities
  • Add deploy recipe to justfile that builds and deploys in one command
  • Add .env.production to .gitignore for security

Changes

Systemd Service (deploy/aptora-extensions.service)

  • Runs as root user (required for port 80)
  • Loads environment from /opt/aptora-extensions/.env
  • Auto-restart on failure with 5-second delay
  • Starts automatically on boot

Deployment Script (deploy/deploy.sh)

  • Takes hostname as command line argument
  • Creates backup of existing binary before deployment
  • Copies binary, environment file, and systemd service to server
  • Sets proper permissions (binary=755, .env=600, owner=root:root)
  • Enables and starts systemd service
  • Verifies deployment with health check
  • Provides rollback instructions if deployment fails

Justfile Integration

  • Added deploy HOST recipe with dependency on build-backend
  • Usage: just deploy <hostname>

Security

  • Added .env.production to .gitignore to prevent committing sensitive credentials

Usage

# Deploy to production server
just deploy aptora-prod.example.com

# Or run script directly
./deploy/deploy.sh aptora-prod.example.com
## Summary - Add systemd service file for running the backend as a proper service - Create deployment script with backup, verification, and rollback capabilities - Add deploy recipe to justfile that builds and deploys in one command - Add .env.production to .gitignore for security ## Changes ### Systemd Service (`deploy/aptora-extensions.service`) - Runs as root user (required for port 80) - Loads environment from `/opt/aptora-extensions/.env` - Auto-restart on failure with 5-second delay - Starts automatically on boot ### Deployment Script (`deploy/deploy.sh`) - Takes hostname as command line argument - Creates backup of existing binary before deployment - Copies binary, environment file, and systemd service to server - Sets proper permissions (binary=755, .env=600, owner=root:root) - Enables and starts systemd service - Verifies deployment with health check - Provides rollback instructions if deployment fails ### Justfile Integration - Added `deploy HOST` recipe with dependency on `build-backend` - Usage: `just deploy <hostname>` ### Security - Added `.env.production` to `.gitignore` to prevent committing sensitive credentials ## Usage ```bash # Deploy to production server just deploy aptora-prod.example.com # Or run script directly ./deploy/deploy.sh aptora-prod.example.com ```
github-actions[bot] commented 2025-11-21 13:28:48 -05:00 (Migrated from github.com)

Changes Requested

  • Run the systemd service as a dedicated unprivileged user and reduce privileges (use User=aptora, Group=aptora, AmbientCapabilities=CAP_NET_BIND_SERVICE, NoNewPrivileges=yes, and add hardening like PrivateTmp=yes). Update deploy/aptora-extensions.service and deploy/deploy.sh to chown files to that user.
  • Harden deploy/deploy.sh: validate local artifacts before uploading, verify remote sudo early, make the file move atomic (use .new + mv), avoid recursive backups of the full directory (use tar or just back up binary + .env), and make health check not assume curl is present (fallback or document requirement).

Summary of Changes

  • Added deploy/aptora-extensions.service systemd unit (runs as root currently).
  • Added deploy/deploy.sh script to copy binary, environment, and unit file to server and start the service.
  • Added deploy/rollback.sh script to restore /opt/aptora-extensions from a backup.
  • Added deploy and rollback recipes to justfile, and build rules for frontend/backend.
  • Added .env.production to .gitignore.

Overall Feedback

  • Negative: The current deployment runs the service as root and performs privileged operations as root on the remote host. This increases risk unnecessarily. The deploy script also assumes local artifacts and remote prerequisites (sudo, curl) exist and uses a full-directory recursive backup which may be heavy or unexpectedly include sensitive data.

  • Positive: The scripts are well structured, use set -euo pipefail, include a clear rollback path and helpful messages, and the justfile integration makes the workflow easy to run. These are solid foundations — with privilege hardening and a few robustness improvements this will be production-ready.

Please address the requested changes and re-request review.

  • @Pertempto
# Changes Requested - Run the systemd service as a dedicated unprivileged user and reduce privileges (use `User=aptora`, `Group=aptora`, `AmbientCapabilities=CAP_NET_BIND_SERVICE`, `NoNewPrivileges=yes`, and add hardening like `PrivateTmp=yes`). Update `deploy/aptora-extensions.service` and `deploy/deploy.sh` to chown files to that user. - Harden `deploy/deploy.sh`: validate local artifacts before uploading, verify remote sudo early, make the file move atomic (use `.new` + `mv`), avoid recursive backups of the full directory (use tar or just back up binary + .env), and make health check not assume `curl` is present (fallback or document requirement). ## Summary of Changes - Added `deploy/aptora-extensions.service` systemd unit (runs as `root` currently). - Added `deploy/deploy.sh` script to copy binary, environment, and unit file to server and start the service. - Added `deploy/rollback.sh` script to restore `/opt/aptora-extensions` from a backup. - Added `deploy` and `rollback` recipes to `justfile`, and build rules for frontend/backend. - Added `.env.production` to `.gitignore`. ## Overall Feedback - Negative: The current deployment runs the service as `root` and performs privileged operations as root on the remote host. This increases risk unnecessarily. The deploy script also assumes local artifacts and remote prerequisites (`sudo`, `curl`) exist and uses a full-directory recursive backup which may be heavy or unexpectedly include sensitive data. - Positive: The scripts are well structured, use `set -euo pipefail`, include a clear rollback path and helpful messages, and the justfile integration makes the workflow easy to run. These are solid foundations — with privilege hardening and a few robustness improvements this will be production-ready. Please address the requested changes and re-request review. - @Pertempto
github-actions[bot] commented 2025-11-21 14:16:53 -05:00 (Migrated from github.com)

deploy/aptora-extensions.service: Do not run the service as root.

  • Change to a dedicated, unprivileged user (e.g. User=aptora) and create that user on the host.
  • Add minimal capabilities instead of full root: AmbientCapabilities=CAP_NET_BIND_SERVICE and NoNewPrivileges=yes.
  • Hardening suggestions: PrivateTmp=yes, ProtectSystem=full (optional but recommended).
  • Update the deploy script to chown files to the dedicated user instead of root:root, or document a strong justification for keeping User=root.

Please update the unit file and deployment steps accordingly. @Pertempto

`deploy/aptora-extensions.service`: Do not run the service as `root`. - Change to a dedicated, unprivileged user (e.g. `User=aptora`) and create that user on the host. - Add minimal capabilities instead of full root: `AmbientCapabilities=CAP_NET_BIND_SERVICE` and `NoNewPrivileges=yes`. - Hardening suggestions: `PrivateTmp=yes`, `ProtectSystem=full` (optional but recommended). - Update the deploy script to chown files to the dedicated user instead of `root:root`, or document a strong justification for keeping `User=root`. Please update the unit file and deployment steps accordingly. @Pertempto
github-actions[bot] commented 2025-11-21 14:22:47 -05:00 (Migrated from github.com)

deploy/deploy.sh: verification/health-check: handle missing curl and make remote check more robust.

Actionable changes:

  • Run a small remote script via SSH that:
    • Runs sudo systemctl is-active aptora-extensions and prints status
    • If active, check for curl and run curl --fail --silent against the configurable health endpoint
    • If curl is missing, fall back to ss -ltnp (or netstat) to confirm a process is listening on :80 and print journalctl -u aptora-extensions -n 50 --no-pager for diagnostics
  • Make health endpoint configurable (not hardcoded to /health) and document default in README or script

This avoids false failures when curl isn't present and provides clearer diagnostics on failure. @Pertempto

`deploy/deploy.sh`: verification/health-check: handle missing `curl` and make remote check more robust. Actionable changes: - Run a small remote script via SSH that: - Runs `sudo systemctl is-active aptora-extensions` and prints status - If active, check for `curl` and run `curl --fail --silent` against the configurable health endpoint - If `curl` is missing, fall back to `ss -ltnp` (or `netstat`) to confirm a process is listening on :80 and print `journalctl -u aptora-extensions -n 50 --no-pager` for diagnostics - Make health endpoint configurable (not hardcoded to `/health`) and document default in README or script This avoids false failures when `curl` isn't present and provides clearer diagnostics on failure. @Pertempto
github-actions[bot] commented 2025-11-21 14:23:19 -05:00 (Migrated from github.com)

deploy/deploy.sh and deploy/rollback.sh: Local artifact checks and early remote sudo validation

Please add these checks before starting SSH/scp operations:

  • Verify local ./aptora-extensions binary exists and is executable. Exit with clear error if missing.
  • Verify local ./.env.production exists. Exit with clear error if missing.
  • Early check that remote sudo works: ssh "$HOST" "sudo -n true" and provide a helpful error instructing the operator to enable passwordless sudo or run the script with a user that can sudo.

These prevent mid-deploy surprises and make failures easier to diagnose. @Pertempto

`deploy/deploy.sh` and `deploy/rollback.sh`: Local artifact checks and early remote sudo validation Please add these checks before starting SSH/scp operations: - Verify local `./aptora-extensions` binary exists and is executable. Exit with clear error if missing. - Verify local `./.env.production` exists. Exit with clear error if missing. - Early check that remote `sudo` works: `ssh "$HOST" "sudo -n true"` and provide a helpful error instructing the operator to enable passwordless sudo or run the script with a user that can sudo. These prevent mid-deploy surprises and make failures easier to diagnose. @Pertempto
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
kwila/office-automations!5
No description provided.