Files
docker-images/python-tools/README.md
T
ajp_anton b9c886a5ea
Build custom container images / build (map[base_image:php:8-fpm-alpine build_args:PHP_VERSION=8 context:php8-pgsql fingerprint_command:{ apk info -v | LC_ALL=C sort; find /usr/local/lib/php/extensions /usr/local/etc/php/conf.d -type f -exec sha256sum {} + | LC_ALL=C sort; } name:ph… (push) Successful in 43s
Build custom container images / build (map[base_image:postgres:18 build_args:PG_VERSION=18 POSTGIS_VERSION=3 VCHORD_VERSION=0.5.3 context:postgres fingerprint_command:{ dpkg-query -W -f='${binary:Package}=${Version}\n' | LC_ALL=C sort; find /usr/lib/postgresql -type f -exec sha256su… (push) Successful in 54s
Build custom container images / build (map[base_image:python:3 build_args:PYTHON_VERSION=3 context:python-tools fingerprint_command:{ dpkg-query -W -f='${binary:Package}=${Version}\n' | LC_ALL=C sort; pip freeze | LC_ALL=C sort; } name:python-tools oci_labels:org.opencontainers.ima… (push) Successful in 1m18s
Restore generic Python tools documentation and tests
2026-08-16 03:17:17 +00:00

5.4 KiB

Python Tools

This image is a Python 3 task runner with ExifTool and a small web control panel for running known, mounted Python maintenance tasks. It starts the control panel with python -m app.

Control Panel

The application discovers direct *.py files in each non-hidden directory under /opt/tasks. Each directory is a task group. Tasks in one group run sequentially; different groups may run concurrently. It records run history and combined output in SQLite under /var/lib/server-maintenance, and supports cancellation of active task process groups.

The image contains application code only. Mount these paths at runtime:

  • /opt/tasks read-only: reviewed task scripts and their input manifests.
  • /opt/credentials read-only: named credential files used by those scripts.
  • /var/lib/server-maintenance: persistent SQLite data, logs, and task state.

Task processes receive a minimal environment. To forward non-secret container settings to tasks, list their names in SERVER_MAINTENANCE_TASK_ENV, separated by commas. This allowlist prevents unrelated container configuration from being exposed to every task; credentials should remain in /opt/credentials.

Tasks are never imported during discovery. Their optional description is the first line of their module docstring. A task must not require stdin or command line arguments, should write useful output, and must return a non-zero exit code on failure.

Task inputs

An optional task-inputs.json beside a group's task files declares the fields for its web forms and its task order. It is parsed as data only and uses version 1:

{
  "version": 1,
  "tasks": {
    "task.py": {
      "inputs": [
        {"name": "identifier", "label": "Identifier", "type": "text", "required": true},
        {"name": "attempts", "label": "Attempts", "type": "integer", "minimum": 1, "maximum": 5, "default": 2},
        {"name": "mode", "label": "Mode", "type": "choice", "options": ["standard", "extended"]},
        {"name": "alerts", "label": "Alerts", "type": "multi_choice", "options": ["email", "webhook"]}
      ]
    }
  }
}

Supported field types are text, integer, date, datetime, choice, multi_choice, and file. Text may also define a regular-expression pattern; integer fields accept minimum, maximum, and step. Choices may use strings or objects with value and label. File fields accept a list of lowercase filename extensions in accept and a byte limit in maximum_bytes. An input can define required and default. Set sensitive to true for a value or upload that must not appear in run history. The form masks sensitive text, the database records [redacted], and the original value is available only through a private execution input file. Tasks listed in the manifest appear in JSON order. A listed task may use {} when it only needs ordering; unlisted scripts appear afterward in alphabetical order. Set wait_for_result to true for a short task whose form should wait for its final success or failure status. This disables the form and warns before leaving the page while the task is running; tasks without it keep the normal queued-run behavior.

For a task with a review-first operation, declare execution with the input field and its review and execution values. The control panel generates the dropdown. A successful review run offers a button that repeats the same saved inputs using the execution value; it does not reuse a stale filesystem snapshot, so the task must still validate its inputs before changing anything.

The server validates every submitted value before a run is queued. It records the validated object in the run database and writes it to a per-run file. Sensitive fields are redacted in the database and use a private 0600 execution file instead. Tasks read the applicable file path from SERVER_MAINTENANCE_INPUT; no user value is appended to the command line. A task without an entry in the manifest gets an empty JSON object. Uploaded files are stored in a private per-run directory; their absolute paths are provided in the input JSON and the files are removed when the task finishes, fails, or is cancelled.

Downloads

Tasks can write downloadable files to the directory named by SERVER_MAINTENANCE_ARTIFACTS. Set download_artifacts to true alongside wait_for_result to start the first artifact download after a successful web run. Run-detail pages also show available downloads. The server deletes an artifact after its HTTP transfer ends; any undownloaded artifact is removed after 24 hours. A browser cannot confirm that a downloaded file was retained on the client device.

Background tasks

An optional background-tasks.json beside a group's task files declares internal recurring scripts. These scripts must live below the group's internal/ directory, are not exposed in the UI, and are launched at most once per configured interval. Their latest output is retained below the persistent state directory rather than being added to normal run history.

{
  "version": 1,
  "tasks": [
    {"id": "poll", "script": "internal/poll.py", "interval_seconds": 60}
  ]
}

compose.example.yaml is suitable for adding the service to an existing Compose stack. Set PYTHON_TOOLS_VOLUME_ROOT to the host directory that will hold state, tasks, and credentials; set SERVER_MAINTENANCE_ALLOWED_PROXY_IPS to the reverse proxy's direct peer address. Keep the application behind an authenticated reverse proxy.