Read and Process Local Machine Files Using Bind Mounts
For the complete documentation index, see llms.txt. For a full content snapshot, see llms-full.txt. Append.mdto anykestra.io/docs/*URL for plain Markdown.
Access locally stored files on your machine inside Kestra workflows.
In Kestra, you can access files stored on your local machine from within your flows. This is useful when you have a directory of files to process or scripts to execute without needing to copy them into Kestra.
Setting up Kestra with Docker
If you’re running Kestra with Docker, you’ll need to create a bind mount to a local directory on your machine so that Kestra can access those files inside the container.
In your Docker Compose file, add the absolute path of the local directory and define its mount point inside the container.
In this example, the local path /Users/username/Documents/files is mounted to /files inside the container using - /Users/username/Documents/files:/files.
Add this under the volumes section of your Docker Compose file:
... kestra: image: kestra/kestra:latest pull_policy: always user: "root" command: server standalone volumes: - kestra-data:/app/storage - /var/run/docker.sock:/var/run/docker.sock - /tmp/kestra-wd:/tmp/kestra-wd - /Users/username/Documents/files:/files...You can now access any files or directories within /Users/username/Documents/files from inside Kestra under the /files path.
Accessing files inside Script tasks
By default, a Script task runs inside a Docker Task Runner. To access local files, change the Task Runner type to Process, so it runs as a subprocess on your Kestra instance:
id: processnamespace: company.team
tasks: - id: hello type: io.kestra.plugin.scripts.shell.Commands taskRunner: type: io.kestra.plugin.core.runner.Process commands: - cat /files/myfile.txtBatch-uploading files with local.Uploads
io.kestra.plugin.fs.local.Uploads writes multiple Kestra internal storage files to a directory on the local filesystem in a single task. It mirrors the Uploads task available on the FTP, FTPS, SFTP, and SMB backends.
Configure allowed paths
Both local.Upload (single file) and local.Uploads (batch) require the destination directory to be listed in the plugin’s allowed-paths configuration. Add the following to your kestra.yml:
kestra: plugins: configurations: - type: io.kestra.plugin.fs.local.Uploads values: allowed-paths: - /data/uploads - type: io.kestra.plugin.fs.local.Upload values: allowed-paths: - /data/uploadsWithout this, any write to /data/uploads is rejected with a SecurityException even if the path is bind-mounted into the container.
Upload a list of files
Pass a list of Kestra internal storage URIs to from. Each file is written to the to directory using its original filename.
The flow below runs a data ingestion job that produces run logs and SQL migration scripts, then archives the logs to a local directory:
id: archive_pipeline_logsnamespace: company.team
tasks: - id: run_pipeline type: io.kestra.plugin.scripts.shell.Commands taskRunner: type: io.kestra.plugin.core.runner.Process outputFiles: - "*.log" - "*.sql" commands: - echo "ingested 1024 rows" > ingest.log - echo "0 errors" > errors.log - echo "ALTER TABLE orders ADD COLUMN status TEXT;" > schema.sql - echo "INSERT INTO orders VALUES (1, 'pending');" > seed.sql
- id: upload_logs type: io.kestra.plugin.fs.local.Uploads from: - "{{ outputs.run_pipeline.outputFiles['ingest.log'] }}" - "{{ outputs.run_pipeline.outputFiles['errors.log'] }}" to: /data/uploads/logsUpload with custom destination filenames
To rename files at the destination, pass a map of destinationFilename: sourceURI pairs instead of a list. This is useful for versioning — for example, tagging migration scripts with a version prefix before archiving them.
In the flow above, replace the upload_logs task with:
- id: upload_migrations type: io.kestra.plugin.fs.local.Uploads from: v1_schema.sql: "{{ outputs.run_pipeline.outputFiles['schema.sql'] }}" v1_seed.sql: "{{ outputs.run_pipeline.outputFiles['seed.sql'] }}" to: /data/uploads/migrationsFilter by regular expression
Use regExp to upload only files whose internal storage URI matches a pattern. Files that do not match are skipped.
When a task produces a mixed set of outputs, regExp lets you route file types to separate destinations without splitting the upstream task. In the flow above, replace the upload_logs task with:
- id: upload_sql_only type: io.kestra.plugin.fs.local.Uploads from: - "{{ outputs.run_pipeline.outputFiles['ingest.log'] }}" - "{{ outputs.run_pipeline.outputFiles['errors.log'] }}" - "{{ outputs.run_pipeline.outputFiles['schema.sql'] }}" - "{{ outputs.run_pipeline.outputFiles['seed.sql'] }}" regExp: ".*\\.sql$" to: /data/uploads/migrationsAdditional properties
| Property | Default | Description |
|---|---|---|
maxFiles | 25 | Upper bound on how many files are written. Excess files are dropped with a warning. |
overwrite | true | When false, the task fails if a destination file already exists. |
Was this page helpful?