5.5 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/tasksread-only: reviewed task scripts and their input manifests./opt/credentialsread-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,
"label": "Example Tasks",
"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. label is optional and overrides the group name displayed in the UI.
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
mode selector attached to the submit button. 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.