Skip to main content

SUM Platform CLI: single control plane for site lifecycle management

Project description

SUM CLI (v3.3)

PyPI

The SUM CLI is the single control plane for deploying and managing SUM Platform client sites on staging and production servers.

Install

pip install sum-cli
sum-platform --version

With Gitea Support

If using Gitea instead of GitHub for repository hosting:

pip install sum-cli[gitea]

Initial Setup

Before using the CLI, configure your infrastructure settings:

sudo sum-platform setup

This interactive command creates /etc/sum/config.yml with your staging/production server settings.

Commands

Command Description Requires Sudo
setup Configure infrastructure settings Yes
init Create new site at /srv/sum/<name>/ Yes
update Pull updates, migrate, restart No (staging)
backup PostgreSQL backup via pgBackRest No
restore Point-in-time database restore No
destroy Tear down a site and all its infrastructure Yes
monitor Check backup health, send alerts No
promote Deploy staging site to production No
check Validate project setup No
theme Theme management (list, check, update) No
themes List themes (deprecated, use theme list) No

Theme Management

The theme command group provides tools for managing themes in existing projects.

Listing Themes

# List local themes (from themes/ directory or SUM_THEME_PATH)
sum-platform theme list

# List remote themes from sum-themes repository
sum-platform theme list --remote

Checking for Updates

# Compare current theme version against latest available
cd /path/to/project
sum-platform theme check

Viewing Available Versions

# Show all available versions for a theme
sum-platform theme versions theme_a

Updating Themes

# Update to latest version
cd /path/to/project
sum-platform theme update

# Update to specific version
sum-platform theme update --version 1.2.0

# Allow downgrade to older version
sum-platform theme update --version 1.0.0 --allow-downgrade

# Force reinstall even if at target version
sum-platform theme update --force

Theme updates are atomic with automatic rollback on failure. The lockfile at .sum/theme.json tracks version history.

Site Directory Structure

Each site lives at /srv/sum/<slug>/:

/srv/sum/<slug>/
├── app/          # Django project (git checkout)
├── venv/         # Python virtualenv
├── static/       # collectstatic output
├── media/        # User uploads
└── backups/      # Database backups

Ownership

The CLI runs as root (sudo sum-platform init). After setup, fix_site_ownership() sets the final permissions:

Directory Owner Group Why
app/ deploy www-data Gunicorn reads code; deploy user runs git pulls
static/ deploy www-data collectstatic writes here; Caddy serves directly
media/ deploy www-data Django writes uploads here; Caddy serves directly
venv/ root root Security — prevents application code from modifying its own runtime
backups/ root root Security — prevents application code from accessing/tampering with backups

The deploy user runs gunicorn, owns application files, and is a member of www-data. It has no sudo access. Configured in /etc/sum/config.yml under defaults.deploy_user.

Operations on site files (app/, static/, media/) should run as the deploy user:

sudo -u deploy /srv/sum/mysite/venv/bin/python /srv/sum/mysite/app/manage.py migrate
sudo -u deploy /srv/sum/mysite/venv/bin/python /srv/sum/mysite/app/manage.py collectstatic

Operations on venv/ and backups/ require root.

Creating Sites

With GitHub

sudo sum-platform init acme --git-provider github --git-org acme-corp

With Gitea

sudo sum-platform init acme --git-provider gitea --git-org clients \
  --gitea-url https://gitea.agency.com

With Gitea (Custom SSH Port)

sudo sum-platform init acme --git-provider gitea --git-org clients \
  --gitea-url https://gitea.agency.com --gitea-ssh-port 2222

Without Git

sudo sum-platform init acme --no-git

Additional Init Options

sudo sum-platform init acme --git-provider github --git-org acme-corp \
  --theme theme_a \
  --profile sage-stone \
  --content-path /path/to/custom/content

# Skip systemd service installation
sudo sum-platform init acme --no-git --skip-systemd

# Skip Caddy reverse proxy configuration
sudo sum-platform init acme --no-git --skip-caddy

# Set custom Django superuser username (default: admin)
sudo sum-platform init acme --no-git --superuser myuser

Dev / Testing (Unreleased sum-core)

By default, init installs sum-core from a pinned git tag in the boilerplate requirements.txt. To test with unreleased changes, use one of these overrides (listed in priority order):

SUM_CORE_SOURCE environment variable — raw pip requirement line, always takes priority:

SUM_CORE_SOURCE="-e /path/to/local/core" sudo sum-platform init acme --no-git
SUM_CORE_SOURCE="sum-core==0.8.0" sudo sum-platform init acme --no-git

--dev flag — editable install from the monorepo using an absolute path (must run from within the monorepo):

cd /path/to/sum-platform
sudo sum-platform init acme --dev --no-git

--core-ref flag — install from a specific git branch or tag:

sudo sum-platform init acme --core-ref develop --no-git
sudo sum-platform init acme --core-ref feature/my-branch --no-git

--dev and --core-ref are mutually exclusive. SUM_CORE_SOURCE silently overrides both.

Destroying Sites

WARNING: The destroy command is irreversible. It permanently removes a site and all its infrastructure.

destroy reverses everything created by init, tearing down resources in safe order:

  1. Stop and disable the systemd service
  2. Remove the systemd service file and reload daemon
  3. Drop the PostgreSQL cluster (and deallocate port)
  4. Remove pgBackRest stanza config and backup cron
  5. Remove the Caddy site config and reload
  6. Remove the site directory (/srv/sum/<slug>/)

Usage

# Interactive — prompts you to type the site slug to confirm
sudo sum-platform destroy acme

# Skip confirmation prompts (for automation/scripts)
sudo sum-platform destroy acme --force

# Also permanently delete remote backup data
sudo sum-platform destroy acme --purge-backups

Options

Option Description
--force Skip all confirmation prompts
--purge-backups Also delete remote backup data via pgBackRest stanza-delete. IRREVERSIBLE.

Safety Features

  • Slug confirmation: You must type the exact site slug to proceed. A mismatch aborts the operation.
  • Double confirmation for backups: When --purge-backups is used, you must also type DELETE BACKUPS to confirm.
  • Path safety check: The command refuses to remove directory paths that don't contain the site slug or are too shallow (prevents accidental deletion of system directories).
  • Non-fatal warnings: If individual teardown steps fail (e.g., service already stopped), the command continues and reports warnings rather than aborting.
  • Requires root: The command escalates to root privileges automatically.

Recommended: Back Up Before Destroying

# Create a full backup first
sum-platform backup acme --type=full

# Then destroy (without --purge-backups to keep remote backups)
sudo sum-platform destroy acme

Validating Sites

The check command validates that a project is correctly set up and ready to run.

Usage

# Run from inside a project directory
cd /srv/sum/acme/app && sum-platform check

# Or specify a project name (resolves under clients/ directory)
sum-platform check acme

Checks Performed

Check What It Validates
Virtualenv Virtual environment exists with required packages (django, wagtail)
Credentials .env.local exists (created during init with superuser credentials)
Database All migrations applied (manage.py migrate --check)
Homepage Homepage is set as the default site root page
Theme compiled CSS Compiled CSS exists at theme/active/static/<slug>/css/main.css and is >5KB
Theme slug match Theme slug in .sum/theme.json matches theme/active/theme.json
Required env vars All keys from .env.example are set in .env or environment
sum_core import sum_core package is importable in the project's Python environment

Example Output

[OK] Virtualenv: Virtualenv exists with required packages
[OK] Credentials: .env.local found
[OK] Database: Migrations up to date
[OK] Homepage: Homepage set as site root
[OK] Theme compiled CSS: /srv/sum/acme/app/theme/active/static/theme_a/css/main.css
[OK] Theme slug match: theme_a
[OK] Required env vars: Required env vars present
[OK] sum_core import: sum_core importable

✅ All checks passed

Failed checks show remediation hints:

[FAIL] Virtualenv: Package 'django' not installed
       → Run 'pip install -r requirements.txt'
[FAIL] Database: Pending migrations
       → Run 'python manage.py migrate'

The command exits with code 0 on success or 1 if any check fails.

Managing Sites

# Update a deployed site (pull, migrate, restart)
sum-platform update acme

# Update production site
sum-platform update acme --target prod

# Update without running migrations
sum-platform update acme --skip-migrations

# Backup database (PostgreSQL via pgBackRest)
sum-platform backup acme --type full

# Validate project setup
sum-platform check acme

# List available themes
sum-platform theme list

# List remote themes with latest versions
sum-platform theme list --remote

# Check for theme updates in a project
cd /srv/sum/acme && sum-platform theme check

# Update theme to latest version
cd /srv/sum/acme && sum-platform theme update

Promoting to Production

The promote command deploys a working staging site to a production server with a custom domain. It requires a git-enabled site (created without --no-git).

sum-platform promote acme --domain acme-client.com

Options:

Option Required Description
--domain Yes Production domain for the site (e.g., acme-client.com)

What promote does (11 steps):

  1. Backs up the staging database
  2. Copies the backup to the production server via scp
  3. Provisions production infrastructure (database, user, directories, .env)
  4. Clones the site repository on production (HTTPS with token, falls back to SSH)
  5. Creates a virtualenv and installs dependencies
  6. Restores the database from backup
  7. Syncs media files from staging via rsync
  8. Runs Django migrations and collectstatic
  9. Installs and enables systemd service
  10. Configures Caddy reverse proxy
  11. Starts the service and verifies health

After completion, the command prints the production URL and reminds you to configure DNS.

Prerequisites:

  • The staging site must exist and have a git repository
  • SSH access to the production server must be configured in /etc/sum/config.yml
  • The production.ssh_host setting must be set in system config

Backup and Recovery

# Create differential backup
sum-platform backup acme

# Create full backup
sum-platform backup acme --type=full

# List available backups
sum-platform backup acme --list

# List restore points with details
sum-platform restore acme --list

# Restore to specific point in time
sum-platform restore acme --time "2024-01-15 14:30:00"

# Restore to latest backup
sum-platform restore acme --latest

# Clean up pre-restore data after verifying restore
sum-platform restore acme --latest --cleanup

# Skip confirmation prompt (useful for automation)
sum-platform restore acme --latest --confirm

Backup Monitoring

The monitor command checks backup freshness and sends email alerts for stale backups.

# Check all sites, send alerts for problems
sum-platform monitor

# Check without sending alerts
sum-platform monitor --no-alerts

# Verbose output (show all sites)
sum-platform monitor -v

Cron Setup

Add to crontab for hourly monitoring:

0 * * * * /usr/local/bin/sum-platform monitor

Alerts are sent when:

  • Backup is older than 48 hours
  • Backup status file is missing

Configuration

Global Config (/etc/sum/config.yml)

Infrastructure settings only. Created via sum-platform setup.

agency:
  name: Your Agency Name

staging:
  server: staging.example.com
  domain_pattern: "{slug}.staging.example.com"
  base_dir: /srv/sum

production:
  server: prod.example.com
  ssh_host: 10.0.0.1
  base_dir: /srv/sum

templates:
  dir: /opt/your-ops/infra
  systemd: systemd/sum-site-gunicorn.service.template
  caddy: caddy/Caddyfile.template

defaults:
  theme: theme_a
  seed_profile: starter
  deploy_user: deploy
  postgres_port: 5432

backups:
  storage_box:
    host: u123456.your-storagebox.de
    user: u123456
    fingerprint: SHA256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    port: 23
    ssh_key: /etc/sum/backup-key
    base_path: /backups
  retention:
    full_backups: 2
    diff_backups: 7
  alerts:
    email: alerts@agency.com

Site Config (/srv/sum/<site>/.sum/config.yml)

Per-site configuration. Auto-created when you run init.

GitHub site:

site:
  slug: acme
  theme: theme_a
  created: 2026-02-03T14:30:00Z

git:
  provider: github
  org: acme-corp

Gitea site:

site:
  slug: acme
  theme: theme_a
  created: 2026-02-03T14:30:00Z

git:
  provider: gitea
  org: clients
  url: https://gitea.agency.com
  ssh_port: 2222
  token_env: GITEA_TOKEN

No-git site:

site:
  slug: acme
  theme: theme_a
  created: 2026-02-03T14:30:00Z

git: null

Git Provider Setup

GitHub

Requires the GitHub CLI (gh) to be installed and authenticated:

gh auth login

Gitea

Set the API token environment variable:

export GITEA_TOKEN=your-token-here

Or use a custom environment variable name:

sudo sum-platform init acme --git-provider gitea --git-org clients \
  --gitea-url https://gitea.agency.com --gitea-token-env MY_GITEA_TOKEN

Common Workflows

Set Up a New Client Site

# 1. Create the site with git integration
sudo sum-platform init acme --git-provider github --git-org acme-corp

# 2. Validate the setup
sum-platform check acme

# 3. Visit the staging URL shown in init output

Update sum_core on a Deployed Site

# 1. Create a backup before updating
sum-platform backup acme --type=full

# 2. Pull latest code and apply updates
sum-platform update acme

# 3. Verify the site is working
sum-platform check acme

Recover from Backup

# 1. List available restore points
sum-platform restore acme --list

# 2. Restore to the latest backup
sum-platform restore acme --latest

# 3. Verify the restored site
sum-platform check acme

# 4. Clean up pre-restore data once verified
sum-platform restore acme --latest --cleanup

Promote a Staging Site to Production

# 1. Verify the staging site is ready
sum-platform check acme

# 2. Create a full backup before promoting
sum-platform backup acme --type=full

# 3. Promote to production with a custom domain
sum-platform promote acme --domain acme-client.com

# 4. Configure DNS to point to the production server

Destroy a Site Safely

# 1. Create a final backup (in case you need it later)
sum-platform backup acme --type=full

# 2. Destroy the site (keeps remote backups by default)
sudo sum-platform destroy acme

# 3. To also purge remote backup data (irreversible)
sudo sum-platform destroy acme --purge-backups

Troubleshooting

"Database configuration required" error

The .env file is missing or incomplete.

cp .env.example .env
# Edit .env with your database credentials
make db-up && make dev-reset

check reports "sum_core import" failure

The sum_core package is not installed in the site's virtualenv.

cd /srv/sum/acme
source venv/bin/activate
pip install sum-core

destroy warns "Could not stop service"

The systemd service may already be stopped or never created (e.g., if --skip-systemd was used during init). This warning is non-fatal — the command continues removing other resources.

promote fails with "Cannot promote without git repository"

The staging site was created with --no-git. Promote requires a git repository to clone on the production server. Re-create the site with a git provider.

init fails with permission errors

The init command requires root. Run with sudo:

sudo sum-platform init acme --no-git

Backup/restore fails with pgBackRest errors

Ensure pgBackRest is installed and the stanza is initialized:

# Check pgBackRest info for the site
sudo -u postgres pgbackrest --stanza=acme info

If the stanza doesn't exist, it was likely not created during init. Re-running init is the safest fix.

Development Install (monorepo)

pip install -e ./cli

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

sum_cli-3.3.0.tar.gz (207.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

sum_cli-3.3.0-py3-none-any.whl (158.5 kB view details)

Uploaded Python 3

File details

Details for the file sum_cli-3.3.0.tar.gz.

File metadata

  • Download URL: sum_cli-3.3.0.tar.gz
  • Upload date:
  • Size: 207.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for sum_cli-3.3.0.tar.gz
Algorithm Hash digest
SHA256 2847d8370f4f3fdf5c8603eb7ab0b956c456a9f5fbcca541fcd54921431e1048
MD5 36438170d41604b112a495b28c475cb9
BLAKE2b-256 0e0a1f6e05e9e94214b15e9451af6054d8738c6213d33e9f9bcb381dccb90c6a

See more details on using hashes here.

File details

Details for the file sum_cli-3.3.0-py3-none-any.whl.

File metadata

  • Download URL: sum_cli-3.3.0-py3-none-any.whl
  • Upload date:
  • Size: 158.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for sum_cli-3.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 f8be01a104c6737335be6d437c3f5bdcc5dd60c720ede8b88ed4835b8bf58b70
MD5 4bd892e71537d799983050b7b48c9ea9
BLAKE2b-256 d24edfcdd32f51edf30dc33a7d2286a22bbaa5de94c2688f20f353be40d0d01a

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page