v2

sidebar_position: 7

Ops Toolbox

Purpose: Reference for operational scripts in deployment/ec2/scripts/
Status: Active
Last Updated: April 2026

ops.sh is a lightweight operational toolbox for day-to-day EC2 host management. It complements the heavier install.sh (full infra install) and deploy.sh (full code deploy) by offering targeted, safe subcommands with automatic backups.


When to Use Which Script

Task Script
First-time server setup provision.sh
Full infra install/refresh (nginx + workers) install.sh
Code deployment (code + assets + migrations) deploy.sh or ops.sh deploy
Resync one or more nginx configs with backup ops.sh resync nginx
Provision or renew TLS certs for specific apps ops.sh ssl
Rollback to a previous git ref rollback.sh
Toggle maintenance mode maintenance.sh
Install command aliases install-aliases.sh

Command Aliases (Optional)

For convenience, you can install system-wide command aliases that allow you to run ops scripts from anywhere without typing full paths:

# Install aliases (creates symlinks in /usr/local/bin)
sudo /var/www/loreax/deployment/ec2/scripts/install-aliases.sh

# Available aliases after installation:
loreax-ops <command>           # ops.sh wrapper
loreax-deploy [options]        # deploy.sh wrapper
loreax-rollback [options]      # rollback.sh wrapper
loreax-maintenance <on|off>    # maintenance.sh wrapper

Benefits:

  • Run commands from any directory
  • Shorter, memorable command names
  • Consistent loreax-* namespace

Uninstall:

sudo /var/www/loreax/deployment/ec2/scripts/install-aliases.sh --uninstall

Note: The provision.sh script automatically installs these aliases during first-time server setup.


Usage

# Without aliases
bash deployment/ec2/scripts/ops.sh <command> [subcommand] [options]

# With aliases installed
loreax-ops <command> [subcommand] [options]

Run with --help for a summary at any level.


Commands

deploy

Manually trigger a full deployment when CI/CD fails or for direct server deployments.

Usage:

# Deploy current branch (fast-forward to origin)
loreax-ops deploy

# Deploy specific branch, tag, or commit
loreax-ops deploy --ref=master
loreax-ops deploy --ref=v1.2.3
loreax-ops deploy --ref=abc1234

# Skip build steps (when only config changed)
loreax-ops deploy --skip-build

# Skip infrastructure sync (nginx + systemd)
loreax-ops deploy --skip-infra

# Combine options
loreax-ops deploy --ref=hotfix/payment-bug --skip-infra

What it does:

  1. Pulls the specified git ref (or fast-forwards current branch)
  2. Syncs nginx configs and systemd units (unless --skip-infra)
  3. Runs composer install and bun run build (unless --skip-build)
  4. Generates OpenAPI specification
  5. Runs database migrations
  6. Caches config, routes, events, and views
  7. Reloads PHP-FPM and Horizon

When to use:

  • CI/CD pipeline fails but code is ready
  • Emergency hotfix deployment
  • Testing deployment process on staging
  • Manual deployment during initial setup

resync nginx

Resyncs nginx site configs from the repo working tree into /etc/nginx/sites-available/, with an automatic timestamped backup before overwriting.

# Resync all configs
bash deployment/ec2/scripts/ops.sh resync nginx --all

# Resync specific apps (comma-separated)
bash deployment/ec2/scripts/ops.sh resync nginx --app=api
bash deployment/ec2/scripts/ops.sh resync nginx --app=dev,admin
bash deployment/ec2/scripts/ops.sh resync nginx --app=api,dev,admin

App names map to conf files by prefix match (apiapi.loreax.bervant.co.ke.conf):

App name Conf file
api api.loreax.bervant.co.ke.conf
admin admin.loreax.bervant.co.ke.conf
dev dev.loreax.bervant.co.ke.conf

What it does for each conf:

  1. Backs up the current /etc/nginx/sites-available/<conf><conf>.bak.<YYYYMMDD_HHMMSS>
  2. Installs the new conf from deployment/ec2/nginx/<conf> (mode 644)
  3. Ensures the symlink in /etc/nginx/sites-enabled/ exists
  4. Runs nginx -t to validate the full nginx config
  5. If validation passes: reloads nginx (systemctl reload nginx)
  6. If validation fails: exits with an error — nginx is not reloaded and backups remain for manual recovery

Recovering from a bad config:

# Find the backup
ls /etc/nginx/sites-available/*.bak.*

# Restore it
sudo cp /etc/nginx/sites-available/api.loreax.bervant.co.ke.conf.bak.20260501_143022 \
        /etc/nginx/sites-available/api.loreax.bervant.co.ke.conf

# Verify and reload
sudo nginx -t && sudo systemctl reload nginx

ssl

Provisions (or renews) Let's Encrypt TLS certificates via certbot's --nginx plugin. Always performs a resync nginx first so certbot operates on the latest config from the repo.

Prerequisite: certbot and the nginx plugin must be installed.

# Install certbot if not present
sudo apt-get install -y certbot python3-certbot-nginx

Usage:

# Provision certs for all three surfaces
bash deployment/ec2/scripts/ops.sh ssl --all

# Provision certs for specific apps only
bash deployment/ec2/scripts/ops.sh ssl --app=api
bash deployment/ec2/scripts/ops.sh ssl --app=api,dev,admin

# Use a custom email for the Let's Encrypt account (default: admin@loreax.bervant.co.ke)
bash deployment/ec2/scripts/ops.sh ssl --all --email=ops@yourdomain.com

What it does:

  1. Resolves conf files for the selected apps (same --all / --app= logic as resync nginx)
  2. Backs up and resyncs the selected confs from the repo working tree
  3. Validates with nginx -t and reloads nginx — stops here if validation fails
  4. Reads the server_name directive from each installed conf to determine the hostname
  5. Runs certbot --nginx --non-interactive --agree-tos -d <host1> [-d <host2> ...]
  6. certbot patches the installed confs in-place, uncommenting the SSL listen 443 and certificate lines that are already present in the repo configs

After running:

The installed nginx confs will have their SSL blocks activated by certbot. These changes are in /etc/nginx/sites-available/ — they are not reflected back into the repo. The repo confs intentionally keep the SSL lines commented out so they work on HTTP-only environments (local, fresh provisions) without modification.

Renewal:

certbot auto-renewal runs via a system timer. Verify it is active:

sudo systemctl status certbot.timer

# Force a dry-run renewal to confirm it would succeed
sudo certbot renew --dry-run

Provisioning order matters: DNS A-records for all target hostnames must resolve to this server before running ssl. certbot performs an HTTP-01 challenge over port 80.

# Verify DNS before running ssl
dig +short api.loreax.bervant.co.ke
dig +short admin.loreax.bervant.co.ke
dig +short dev.loreax.bervant.co.ke
# All three should return 35.178.52.158

Source

deployment/ec2/scripts/ops.sh — requires bash, nginx, sudo, and (for ssl) certbot with the nginx plugin.