@mtakla/cronops 0.1.1-rc2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +15 -0
- package/README.md +391 -0
- package/config/jobs/example-job1.yaml +17 -0
- package/config/jobs/example-job2.yaml +7 -0
- package/config/jobs/example-job3.yaml +14 -0
- package/config/runner-defaults.yaml +27 -0
- package/config/scripts/example-script.js +1 -0
- package/dist/api/openapi.js +229 -0
- package/dist/api/webapi.js +75 -0
- package/dist/api.js +44 -0
- package/dist/errors/JobError.js +10 -0
- package/dist/handlers/AbstractHandler.js +162 -0
- package/dist/handlers/ExecHandler.js +103 -0
- package/dist/handlers/FileArchiveHandler.js +15 -0
- package/dist/handlers/FileCopyHandler.js +15 -0
- package/dist/handlers/FileDeleteHandler.js +13 -0
- package/dist/handlers/FileMoveHandler.js +16 -0
- package/dist/index.js +17 -0
- package/dist/models/FileHistoryModel.js +45 -0
- package/dist/models/JobModel.js +35 -0
- package/dist/models/JobRunnerContext.js +49 -0
- package/dist/models/JobRunnerResult.js +13 -0
- package/dist/models/JobRunnerSetup.js +105 -0
- package/dist/models/PermissionModel.js +13 -0
- package/dist/server.js +91 -0
- package/dist/tasks/AbstractTask.js +71 -0
- package/dist/tasks/JobLoader.js +73 -0
- package/dist/tasks/JobRunner.js +100 -0
- package/dist/tasks/JobScheduler.js +108 -0
- package/dist/tests/loadtest.js +102 -0
- package/dist/types/Config.types.js +34 -0
- package/dist/types/Options.types.js +19 -0
- package/dist/types/Task.types.js +1 -0
- package/dist/webapi.js +52 -0
- package/package.json +81 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# ISC License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Michael Takla @ nevereven
|
|
4
|
+
|
|
5
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
6
|
+
purpose with or without fee is hereby granted, provided that the above
|
|
7
|
+
copyright notice and this permission notice appear in all copies.
|
|
8
|
+
|
|
9
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
10
|
+
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
11
|
+
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
12
|
+
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
13
|
+
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
14
|
+
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
15
|
+
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,391 @@
|
|
|
1
|
+
# CronOps
|
|
2
|
+
|
|
3
|
+
[](https://github.com/mtakla/cronops/blob/master/LICENSE)
|
|
4
|
+
[](https://img.shields.io/badge/coverage-95%25-green)
|
|
5
|
+
[](https://www.buymeacoffee.com/nevereven)
|
|
6
|
+
|
|
7
|
+
**CronOps** is a lightweight, cron-based file management and system task scheduler for containerized environments. It automates copying, moving, archiving, and cleaning up files across mounted volumes — keeping your storage tidy, enabling seamless file exchange between containerized services, and triggering regular tasks in your development, integration or production environments.
|
|
8
|
+
|
|
9
|
+
> [!WARNING]
|
|
10
|
+
> Early BETA. Not recommended for use in a production environment!
|
|
11
|
+
|
|
12
|
+
## 💡 Why CronOps?
|
|
13
|
+
|
|
14
|
+
In containerized workflows, files often accumulate in volumes: downloads, logs, temporary exports, backups. CronOps acts as your **digital janitor**, running scheduled jobs that:
|
|
15
|
+
|
|
16
|
+
- **Execute** OS commands
|
|
17
|
+
- **Select** files using powerful **glob patterns** and
|
|
18
|
+
- **delete** them on a regular basis
|
|
19
|
+
- **copy** or **move** them to specific target path
|
|
20
|
+
- **archive** them automatically using date/time bases archive name patterns
|
|
21
|
+
- **process** them with OS commands (e.g. awk/sed, curl, untar/unzip, ...)
|
|
22
|
+
- **execute** scripts on them (sh/bash/cmd/powershell/node/lua, ...)
|
|
23
|
+
|
|
24
|
+
All configured via simple, version-controllable ***.yml** based **job definition** files — no coding required.
|
|
25
|
+
|
|
26
|
+
## Top Features
|
|
27
|
+
|
|
28
|
+
- ✅ **Cron-like scheduling** – Flexible job timing using familiar cron syntax
|
|
29
|
+
- ✅ **Glob-based filtering** – Precisely select source files to be processed
|
|
30
|
+
- ✅ **File operations** – Copy, move, delete, or archive files
|
|
31
|
+
- ✅ **Command execution** – Process files with OS commands or custom scripts
|
|
32
|
+
- ✅ **Permission management** – Change uid, gid, and file permissions on processed target files
|
|
33
|
+
- ✅ **Automatic cleanup** – Remove target files after a configurable retention period
|
|
34
|
+
- ✅ **Incremental processing** – Only process changed or new files since last run
|
|
35
|
+
- ✅ **Dry-run mode** – Test jobs and execute scripts safely before applying changes
|
|
36
|
+
- ✅ **Detailed logging** – Detailed job execution logs with stdout/stderr aggregation
|
|
37
|
+
- ✅ **Hot reload** – Change job configs without restarting the service
|
|
38
|
+
- ✅ **Admin API** – Trigger jobs, check status, pause/resume scheduling via secured REST-API
|
|
39
|
+
- ✅ **OpenAPI Web UI** – Interactive API documentation and execution
|
|
40
|
+
- ✅ **Easy setup** – Runs with zero configuration. All config via environment variables
|
|
41
|
+
|
|
42
|
+
## Installation
|
|
43
|
+
|
|
44
|
+
### Install & run with Docker
|
|
45
|
+
|
|
46
|
+
CronOps is built and optimized to run as a Docker container itself:
|
|
47
|
+
|
|
48
|
+
```
|
|
49
|
+
docker run \
|
|
50
|
+
--name cronops \
|
|
51
|
+
-v ./config:/config \
|
|
52
|
+
-v /home/docker/data:/io/source \
|
|
53
|
+
-v /home/docker/archive:/io/target \
|
|
54
|
+
--restart unless-stopped \
|
|
55
|
+
ghcr.io/mtakla/cronops:latest
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
The following docker volumes can be configured:
|
|
59
|
+
|
|
60
|
+
- `/config` : The exposed config directory where job configuration files and scripts are stored
|
|
61
|
+
- `/data/temp` : Temp directory used for dry-run mode simulations
|
|
62
|
+
- `/data/logs` : Directory where job logs and file history are stored
|
|
63
|
+
- `/io/source` : Primary source directory (CROPS_SOURCE_ROOT), referenced as `$1` in source paths
|
|
64
|
+
- `/io/target` : Primary target directory (CROPS_TARGET_ROOT), referenced as `$1` in target paths
|
|
65
|
+
- `/io/source2` : Secondary source directory (CROPS_SOURCE_2_ROOT), referenced as `$2` in source paths
|
|
66
|
+
- `/io/target2` : Secondary target directory (CROPS_TARGET_2_ROOT), referenced as `$2` in target paths
|
|
67
|
+
- `/io/source3` : Third source directory (CROPS_SOURCE_2_ROOT), referenced as `$2` in source paths
|
|
68
|
+
- `/io/target3` : Third target directory (CROPS_TARGET_2_ROOT), referenced as `$2` in target paths
|
|
69
|
+
|
|
70
|
+
### Install & run with Docker compose
|
|
71
|
+
|
|
72
|
+
Create the following `compose.yaml` file:
|
|
73
|
+
|
|
74
|
+
```yaml
|
|
75
|
+
services:
|
|
76
|
+
cronops:
|
|
77
|
+
image: ghcr.io/mtakla/cronops:latest
|
|
78
|
+
container_name: cronops
|
|
79
|
+
restart: unless-stopped
|
|
80
|
+
volumes:
|
|
81
|
+
- /home/docker/data:/io/source
|
|
82
|
+
- /home/docker/archive:/io/target
|
|
83
|
+
- ./config:/config
|
|
84
|
+
- ./temp:/data/temp
|
|
85
|
+
- ./logs:/data/logs
|
|
86
|
+
environment:
|
|
87
|
+
CROPS_API_KEY: 54bad6e77cf8cbc3c65ca76d127138d50e63adc29fb14450f1d60f2693b8676c # <-- change me!
|
|
88
|
+
TZ: Europe/UTC
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
In same directory, type `docker compose up -d` to install and start the cronops service.
|
|
92
|
+
|
|
93
|
+
To check if the server is running, just action:
|
|
94
|
+
|
|
95
|
+
```sh
|
|
96
|
+
docker logs -f cronops
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
After your first start you should see the following output:
|
|
100
|
+
```text
|
|
101
|
+
____ ___
|
|
102
|
+
/ ___| _ __ ___ _ __ / _ \ _ __ ___
|
|
103
|
+
| | | '__|/ _ \ | '_ \ | | | || '_ \ / __|
|
|
104
|
+
| |___ | | | (_) || | | || |_| || |_) |\__ \
|
|
105
|
+
\____||_| \___/ |_| |_| \___/ | .__/ |___/
|
|
106
|
+
|_|
|
|
107
|
+
|
|
108
|
+
☰ CronOps v0.1.1-rc2.4 »Omnia coniuncta sunt«
|
|
109
|
+
Monitoring job configs in /config/workspace/cronops/config/jobs ...
|
|
110
|
+
|
|
111
|
+
Web API enabled. HTTP Server is listening on port 8118 ...
|
|
112
|
+
⎆ API endpoint http://127.0.0.1:8118/api (secured)
|
|
113
|
+
⎆ OpenAPI docs http://127.0.0.1:8118/docs
|
|
114
|
+
⎆ Health check http://127.0.0.1:8118/health
|
|
115
|
+
|
|
116
|
+
Job config loaded (1 active job)
|
|
117
|
+
🕔 [example-job3] scheduled (*/5 * * * *)
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Now you can add your job configuration files to the `./config/jobs/` directory. Each YAML file in this directory can contain one or more job definitions. Details, see below.
|
|
121
|
+
|
|
122
|
+
> [!NOTE]
|
|
123
|
+
> You do not need to restart the server after changing job files. The server identifies any changes and will hot reload the configuration. If a job configuration is invalid, an appropriate message will appear in the docker logs and the specific job will not be scheduled.
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
### Updating using Docker compose
|
|
127
|
+
|
|
128
|
+
When using docker compose, to update to the latest version of CronOps, just type
|
|
129
|
+
|
|
130
|
+
```sh
|
|
131
|
+
docker compose pull && docker compose up -d
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
in the same directoy where `compose.yaml` has been created.
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
### Install & run in server environment
|
|
139
|
+
|
|
140
|
+
This requires [node.js](https://nodejs.org/) (v24 ++) to be installed on your server.
|
|
141
|
+
|
|
142
|
+
First step is to create an empty app directory with a `.env` file that contains your configuration settings, e.g.:
|
|
143
|
+
|
|
144
|
+
```ini
|
|
145
|
+
NODE_ENV=production
|
|
146
|
+
CROPS_SOURCE_ROOT=/var/lib/docker/volumes # change as you like
|
|
147
|
+
CROPS_TARGET_ROOT=/var/opt/backups # change as you like
|
|
148
|
+
CROPS_CONFIG_DIR=/home/cronops/config # optional. Default is ./config
|
|
149
|
+
CROPS_LOG_DIR=/home/cronops/logs # optional. Default is ~/.cronops
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
To install and start CronOps, type in bash shell:
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
npx dotenvx run -- npx @mtakla/cronops &> /var/log/cronops.log
|
|
156
|
+
```
|
|
157
|
+
This will ...
|
|
158
|
+
|
|
159
|
+
- download the latest version of cronops (and dotenvx)
|
|
160
|
+
- load the environment settings defined in the `.env` file
|
|
161
|
+
- start the cronops service with the loaded environment settings
|
|
162
|
+
- create jobs directory in `/home/cronops/config/jobs` if it doesn't exist
|
|
163
|
+
- switch to idle mode as no active jobs are configured
|
|
164
|
+
|
|
165
|
+
You can add job configuration files to `/home/cronops/config/jobs/` directory. Each YAML file in this directory defines a job. The server will hot reload when job files are added, modified, or removed.
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
## Configuration
|
|
169
|
+
|
|
170
|
+
The CronOps service can be configured with the following environment variables:
|
|
171
|
+
|
|
172
|
+
| ENV | Description | Docker defaults |
|
|
173
|
+
| --------------------- | ------------------------------------------------------------------------------ | --------------- |
|
|
174
|
+
| `CROPS_SOURCE_ROOT` | Path to primary source directory | `/io/source` |
|
|
175
|
+
| `CROPS_TARGET_ROOT` | Path to primary target directory | `/io/target` |
|
|
176
|
+
| `CROPS_SOURCE_2_ROOT` | Path to secondary source directory | `/io/source2` |
|
|
177
|
+
| `CROPS_TARGET_2_ROOT` | Path to secondary target directory | `/io/target2` |
|
|
178
|
+
| `CROPS_SOURCE_3_ROOT` | Path to tertiary source directory | `/io/source3` |
|
|
179
|
+
| `CROPS_TARGET_3_ROOT` | Path to tertiary target directory | `/io/target3` |
|
|
180
|
+
| `CROPS_CONFIG_DIR` | Path to the config directory where job files are located | `/config` |
|
|
181
|
+
| `CROPS_TEMP_DIR` | Path to temporary folder used for dry-run mode | `/data/temp` |
|
|
182
|
+
| `CROPS_LOG_DIR` | Path to directory where job logs and file history are stored | `/data/logs` |
|
|
183
|
+
| `CROPS_HOST` | Host address for the Admin API server | `0.0.0.0` |
|
|
184
|
+
| `CROPS_PORT` | Port for the Admin API server | `8083` |
|
|
185
|
+
| `CROPS_EXEC_SHELL` | (*Optional*) Default shell for `exec` actions. Can be `false`, `true`, or path | `false` |
|
|
186
|
+
| `CROPS_API_KEY` | (*Optional*) API key for securing the Admin API endpoints | - |
|
|
187
|
+
| `CROPS_BASE_URL` | (*Optional*) Base URL for admin API and OpenAPI docs | - |
|
|
188
|
+
| `TZ` | (*Optional*) Timezone for cron scheduling (standard timezone format) | `UTC` |
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
## Job Configuration
|
|
192
|
+
|
|
193
|
+
Jobs are configured as YAML files in the `CROPS_CONFIG_DIR/jobs` directory. Each YAML file can contain one or more job definitions. .
|
|
194
|
+
|
|
195
|
+
Example job config `./config/jobs/example.yaml`
|
|
196
|
+
|
|
197
|
+
```yaml
|
|
198
|
+
action: move # exec|call|copy|move|delete|archive
|
|
199
|
+
cron: "*/5 * * * * *"
|
|
200
|
+
source:
|
|
201
|
+
dir: $1/nzbget/config/data/download
|
|
202
|
+
includes:
|
|
203
|
+
- "**/*.mp4"
|
|
204
|
+
target:
|
|
205
|
+
dir: $1/filegator/micha/downloads
|
|
206
|
+
permissions:
|
|
207
|
+
owner: "1000:1000"
|
|
208
|
+
file_mode: "444"
|
|
209
|
+
dir_mode: "711"
|
|
210
|
+
retention: 12h
|
|
211
|
+
dry_run: true
|
|
212
|
+
enabled: false
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
> [!NOTE]
|
|
216
|
+
You can change the job configuration at any time and the server will hot reload and schedule the new job configuration.
|
|
217
|
+
Be aware that once the job config has been changed, active running tasks will be terminated and the job will be rescheduled
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
### Job Actions
|
|
221
|
+
|
|
222
|
+
CronOps supports 5 different job actions:
|
|
223
|
+
|
|
224
|
+
#### File based actions
|
|
225
|
+
|
|
226
|
+
- **`copy`** - Copy files from source to target directory while preserving originals
|
|
227
|
+
- **`move`** - Move files from source to target directory (removes originals after successful copy)
|
|
228
|
+
- **`delete`** - Delete files matching the source patterns
|
|
229
|
+
- **`archive`** - Create a compressed tar.gz archive of matched files in the target directory
|
|
230
|
+
|
|
231
|
+
#### Command execution action
|
|
232
|
+
|
|
233
|
+
- **`exec`** - Execute a command or script. Use with `command`, `args`, `shell`, and `env` properties
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
> [!TIP]
|
|
237
|
+
> **Path References**: Use `$1`, `$2`, or `$3` in job paths to reference configured root directories.
|
|
238
|
+
> For source paths, these map to `CROPS_SOURCE_ROOT`, `CROPS_SOURCE_2_ROOT`, and `CROPS_SOURCE_3_ROOT`.
|
|
239
|
+
> For target paths, they map to `CROPS_TARGET_ROOT`, `CROPS_TARGET_2_ROOT`, and `CROPS_TARGET_3_ROOT`.
|
|
240
|
+
|
|
241
|
+
### Job Configuration examples
|
|
242
|
+
|
|
243
|
+
#### Copy Files with Pattern Matching
|
|
244
|
+
|
|
245
|
+
```yaml
|
|
246
|
+
action: copy
|
|
247
|
+
cron: "0 2 * * *" # Daily at 2 AM
|
|
248
|
+
source:
|
|
249
|
+
dir: $1/downloads
|
|
250
|
+
includes:
|
|
251
|
+
- "**/*.pdf"
|
|
252
|
+
- "**/*.doc"
|
|
253
|
+
excludes:
|
|
254
|
+
- "**/*.tmp"
|
|
255
|
+
target:
|
|
256
|
+
dir: $1/archive/documents
|
|
257
|
+
permissions:
|
|
258
|
+
owner: "1000:1000"
|
|
259
|
+
file_mode: "644"
|
|
260
|
+
dir_mode: "755"
|
|
261
|
+
retention: "30d"
|
|
262
|
+
enabled: true
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
#### Create an archive
|
|
266
|
+
|
|
267
|
+
```yaml
|
|
268
|
+
action: archive
|
|
269
|
+
cron: "0 0 * * 0" # Weekly on Sunday at midnight
|
|
270
|
+
source:
|
|
271
|
+
dir: $1/logs
|
|
272
|
+
includes:
|
|
273
|
+
- "**/*.log"
|
|
274
|
+
excludes:
|
|
275
|
+
- ".git/**"
|
|
276
|
+
- "node_modules/**"
|
|
277
|
+
target:
|
|
278
|
+
dir: $1/backups
|
|
279
|
+
archive_name: "logs-{{yyyy-MM-dd}}.tgz"
|
|
280
|
+
enabled: true
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
#### Execute Custom Command
|
|
284
|
+
|
|
285
|
+
```yaml
|
|
286
|
+
action: exec
|
|
287
|
+
cron: "*/15 * * * *" # Every 15 minutes
|
|
288
|
+
command: "node"
|
|
289
|
+
args:
|
|
290
|
+
- "--experimental-vm-modules"
|
|
291
|
+
- "{scriptDir}/cleanup.js"
|
|
292
|
+
env:
|
|
293
|
+
LOG_LEVEL: "info"
|
|
294
|
+
API_TOKEN: "secret123"
|
|
295
|
+
enabled: true
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
### Command execution parameters
|
|
299
|
+
|
|
300
|
+
For jobs of action type `exec`, you can use dynamic parameters in your `command`, `args` or custom `env` entries that will be resolved before the system command is executed:
|
|
301
|
+
|
|
302
|
+
| Parameter | Description |
|
|
303
|
+
| ------------- | ---------------------------------------------------------------- |
|
|
304
|
+
| `{jobId}` | job identifier |
|
|
305
|
+
| `{sourceDir}` | absolute path to the job source directory |
|
|
306
|
+
| `{targetDir}` | absolute path to the job target directory (or CROPS_TARGET_ROOT) |
|
|
307
|
+
| `{scriptDir}` | absolute path to the configured script directory |
|
|
308
|
+
| `{tempDir}` | absolute path to the configured temp directory |
|
|
309
|
+
| `{logDir}` | absolute path to the configured log directory |
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
If the exec action is configured to run on selected `source` files:
|
|
313
|
+
|
|
314
|
+
| Parameter | Description |
|
|
315
|
+
| ------------ | ---------------------------------------------------------------------------- |
|
|
316
|
+
| `{file}` | absolute path to the processed file, e.g. `/io/source/foo/bar.txt` |
|
|
317
|
+
| `{fileDir}` | absolute path to the parent dir of the processed file, e.g. `/io/source/foo` |
|
|
318
|
+
| `{fileName}` | name of the processed file, e.g. `bar.txt` |
|
|
319
|
+
| `{fileBase}` | base name of the processed file without extension, e.g. `bar` |
|
|
320
|
+
| `{fileExt}` | extension of the processed file, e.g. `.txt` |
|
|
321
|
+
|
|
322
|
+
### Command execution ENV defaults
|
|
323
|
+
|
|
324
|
+
For jobs of action type `exec` the following environment variables are available by default when the os command is executed.
|
|
325
|
+
|
|
326
|
+
| Parameter | Description |
|
|
327
|
+
| ------------------ | ---------------------------------------------------------------- |
|
|
328
|
+
| `CROPS_JOB_ID` | job identifier |
|
|
329
|
+
| `CROPS_SOURCE_DIR` | absolute path to the job source directory |
|
|
330
|
+
| `CROPS_TARGET_DIR` | absolute path to the job target directory (or CROPS_TARGET_ROOT) |
|
|
331
|
+
| `CROPS_SCRIPT_DIR` | absolute path to the configured script directory |
|
|
332
|
+
| `CROPS_TEMP_DIR` | absolute path to the configured temp directory |
|
|
333
|
+
| `CROPS_LOG_DIR` | absolute path to the configured log directory |
|
|
334
|
+
| `CROPS_DRY_RUN` | "true", if dry_run mode is enabled |
|
|
335
|
+
| `CROPS_VERBOSE` | "true", if dry_run mode is enabled |
|
|
336
|
+
|
|
337
|
+
|
|
338
|
+
If the exec action is configured to run on selected `source` files:
|
|
339
|
+
|
|
340
|
+
| Parameter | Description |
|
|
341
|
+
| ----------------- | ----------------------------------------------------------------------------------- |
|
|
342
|
+
| `CROPS_FILE` | absolute path to the processed source file, e.g. `/io/source/foo/bar.txt` |
|
|
343
|
+
| `CROPS_FILE_DIR` | absolute path to the parent dir of the processed source file, e.g. `/io/source/foo` |
|
|
344
|
+
| `CROPS_FILE_NAME` | file name of the processed source file, e.g. `bar.txt` |
|
|
345
|
+
| `CROPS_FILE_BASE` | base name of the processed source file without extension, e.g. `bar` |
|
|
346
|
+
| `CROPS_FILE_EXT` | extension of the processed source file, e.g. `.txt` |
|
|
347
|
+
|
|
348
|
+
|
|
349
|
+
|
|
350
|
+
### Job properties
|
|
351
|
+
|
|
352
|
+
| Property | Description |
|
|
353
|
+
| ------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
354
|
+
| `action` | **Required**. The action to perform. One of: `exec`, `call`, `copy`, `move`, `delete`, `archive` |
|
|
355
|
+
| `cron` | (*Optional*) Cron-like scheduling string, e.g., `*/2 * * * *`. See [node-cron](https://nodecron.com/cron-syntax.html) documentation for details. If omitted, job runs once. |
|
|
356
|
+
| `command` | (*For `exec`/`call` actions*) Command to execute, e.g., `"node"`, `"/bin/bash"` |
|
|
357
|
+
| `shell` | (*Optional*) Shell to use for command execution. Can be `true` (use default shell) or a path to a shell binary |
|
|
358
|
+
| `args` | (*Optional*) Array of command arguments for `exec`/`call` actions |
|
|
359
|
+
| `env` | (*Optional*) Environment variables to pass to the command. Object with uppercase keys and string values |
|
|
360
|
+
| `source.dir` | Source directory path. Can be absolute or use `$1` (CROPS_SOURCE_ROOT), `$2` (CROPS_SOURCE_2_ROOT), or `$3` (CROPS_SOURCE_3_ROOT), e.g., `"$1/downloads"` |
|
|
361
|
+
| `source.includes` | (*Optional*) Array of glob patterns to include files, relative to `source.dir`. Default: `["**/*"]` |
|
|
362
|
+
| `source.excludes` | (*Optional*) Array of glob patterns to exclude files from processing |
|
|
363
|
+
| `target.dir` | Target directory path. Can be absolute or use `$1` (CROPS_TARGET_ROOT), `$2` (CROPS_TARGET_2_ROOT), or `$3` (CROPS_TARGET_3_ROOT) |
|
|
364
|
+
| `target.archive_name` | (*For `archive` action*) Archive file name pattern with date placeholders, e.g., `"backup-{{yyyy-MM-dd}}.tgz"` |
|
|
365
|
+
| `target.permissions.owner` | (*Optional*) Change user/group ownership to `"uid:gid"` for all target files. Default: process owner unless `PUID` or `PGID` environment is set |
|
|
366
|
+
| `target.permissions.file_mode` | (*Optional*) Change file permissions using octal (e.g., `"644"`) or symbolic mode (e.g., `"ugo+r"`). Default: "660" |
|
|
367
|
+
| `target.permissions.dir_mode` | (*Optional*) Change directory permissions using octal (e.g., `"755"`) or symbolic mode (e.g., `"ugo+rx"`). Default: "770" |
|
|
368
|
+
| `target.retention` | (*Optional*) Time period after which target files will be deleted, e.g., `"10d"`, `"12h"`. Uses [ms](https://www.npmjs.com/package/ms) format. Default: files are kept |
|
|
369
|
+
| `dry_run` | (*Optional*) If `true`, simulate the operation without making actual changes. Source files are never modified in dry-run mode. Default: `false` |
|
|
370
|
+
| `verbose` | (*Optional*) Enable verbose logging for this job. Default: `false` |
|
|
371
|
+
| `enabled` | (*Optional*) If `false`, the job will not be scheduled. Default: `true` |
|
|
372
|
+
|
|
373
|
+
|
|
374
|
+
|
|
375
|
+
## Security considerations & Trouble shooting
|
|
376
|
+
|
|
377
|
+
> [!NOTE]
|
|
378
|
+
> It is strongly advised against accessing or modifying the data directly on the host system within Docker's internal volume storage path (typically `/var/lib/docker/volumes/`).
|
|
379
|
+
|
|
380
|
+
> [!WARNING]
|
|
381
|
+
> **Hazardous Misconfiguration**
|
|
382
|
+
>
|
|
383
|
+
> If your CronOps docker container is running with Root Privileges and the persistent volumes (source/target directories) are mounted to critical system directories of the hosting operating system (e.g., `/etc`, `/var`, etc.), this creates an extremely high **security risk**:
|
|
384
|
+
>
|
|
385
|
+
> - **System File Overwrite**: The container can access, modify, or delete crucial files and directories on the host machine via the exposed volume paths.
|
|
386
|
+
> - **Host System Damage**: If the volume mounts are not correctly configured (e.g., if a Bind Mount unintentionally exposes the wrong host directory), the root user inside the container can potentially modify or delete system-critical data on the host.
|
|
387
|
+
|
|
388
|
+
|
|
389
|
+
## License
|
|
390
|
+
|
|
391
|
+
CronOps is under [ISC License](https://github.com/mtakla/cronops/blob/master/LICENSE). Made with ❤ in EU
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
action: copy # exec | copy | move | delete | archive
|
|
2
|
+
cron: "*/5 * * * * *"
|
|
3
|
+
source:
|
|
4
|
+
dir: /src
|
|
5
|
+
includes:
|
|
6
|
+
- "**/*.ts"
|
|
7
|
+
excludes:
|
|
8
|
+
- "**/*test.ts"
|
|
9
|
+
target:
|
|
10
|
+
dir: $1/build/example/backup
|
|
11
|
+
permissions:
|
|
12
|
+
owner: "1000:1000"
|
|
13
|
+
file_mode: "664"
|
|
14
|
+
dir_mode: "774"
|
|
15
|
+
retention: "10d"
|
|
16
|
+
verbose: false
|
|
17
|
+
enabled: false
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# THIS FILE MAY BE OBSOLETE!
|
|
2
|
+
# WHY? Use env vars for config
|
|
3
|
+
# - CROPS_SOURCE_EXCLUDES: "[**/*~, **/*~]"
|
|
4
|
+
# - CROPS_EXEC_ENVIRONMENT: "[CI_API_TOKEN:'10f23f2efasdfsevrew']"
|
|
5
|
+
# - CROPS_EXEC_SHELL: "/bin/bash"
|
|
6
|
+
# - CROPS_DEFAULT_ARCHIVE_NAME
|
|
7
|
+
|
|
8
|
+
# Altenatively:
|
|
9
|
+
# - any environment will be routed to the sub process
|
|
10
|
+
# - CROPS_EXEC_APPLY_PARENT_ENVIRONMENT
|
|
11
|
+
#
|
|
12
|
+
# Notes:
|
|
13
|
+
# - Needs a server restart if changes to this file are made
|
|
14
|
+
useShell: false
|
|
15
|
+
environment:
|
|
16
|
+
- CI_API_TOKEN=""
|
|
17
|
+
source:
|
|
18
|
+
excludes:
|
|
19
|
+
- "**/*~"
|
|
20
|
+
- "**/*.git"
|
|
21
|
+
- "**/*.svn"
|
|
22
|
+
- "**/*.part"
|
|
23
|
+
- "**/*.download"
|
|
24
|
+
- "**/*.crdownload"
|
|
25
|
+
- "**/*.tmp"
|
|
26
|
+
target:
|
|
27
|
+
archive_name: "backup-{{yyyy-MM-dd_HH-mm}}.tgz"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
console.log("To the moon!");
|