nrp-s3
Skill4 starsChanged 15 days agoBSD-3-ClauseView on GitHub
Manage S3 object storage on the NRP (National Research Platform) Nautilus cluster, which uses Ceph S3 (not AWS). Covers public vs internal endpoints, rclone usage, bucket creation, public-read policies, CORS configuration, credential handling, and syncing to source.coop. Use when working with S3 buckets on NRP Nautilus, uploading or downloading data, configuring bucket access, or syncing datasets to source.coop.
In this repository18 other files it gives its agents.
- boettiger-lab-stackSkill
- cng-datasetsSkill
- disclose-tool-useSkill
- duckdb-spatialSkill
- gdal-spatialSkill
- github-app-authSkill
- github-rulesetsSkill
- html-figuresSkill
- human-communication-consentSkill
- k8s-never-force-deleteSkill
- nrp-kubernetesSkill
- oci-artifactsSkill
- pod-resourcesSkill
- python-envSkill
- reproducible-reportsSkill
- stacked-pr-squash-mergeSkill
- stac-navigationSkill
- writing-voiceSkill
The file
We split this skill into the rules it gives an agent
3 rules. About 0 are common, 1 is distinctive, and 2 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈1
Distinctive · estimate
This author's own choices. Worth a look.
2
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 26
Always use path-style URLs (not virtual-hosted):
- Very specific: line 32
Never use <bucket>.s3-west.nrp-nautilus.io — it won't work.
- Very specific: line 127
If no rc alias exists yet for the Ceph endpoint, create one from rclone's stored creds (silently, to avoid leaking them into chat logs):
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
NRP S3 Storage
The NRP Nautilus cluster provides S3-compatible object storage powered by Ceph (Rook). This is not AWS S3 — it has its own endpoints, credential system, and quirks.
Two Endpoints
| Endpoint | URL | Use |
| Public | s3-west.nrp-nautilus.io | External access, browsers, public data URLs |
| Internal | rook-ceph-rgw-nautiluss3.rook | Inside k8s pods (faster, no TLS overhead) |
The internal endpoint handles high-concurrency workloads well (DuckDB parallel reads, many pod threads). The public endpoint throttles with 503 SlowDown errors under concurrent load — always use the internal endpoint for heavy parallel reads inside the cluster.
Public URL format
Always use path-style URLs (not virtual-hosted):
https://s3-west.nrp-nautilus.io/<bucket>/<path>Never use <bucket>.s3-west.nrp-nautilus.io — it won't work.
Credentials
Kubernetes secrets
Two secrets are pre-configured in the biodiversity namespace:
aws— ContainsAWS_ACCESS_KEY_IDandAWS_SECRET_ACCESS_KEYrclone-config— Contains a complete rclone configuration (includesnrpandsourceremotes)
env:
- name: AWS_ACCESS_KEY_ID
valueFrom:
secretKeyRef: { name: aws, key: AWS_ACCESS_KEY_ID }
- name: AWS_SECRET_ACCESS_KEY
valueFrom:
secretKeyRef: { name: aws, key: AWS_SECRET_ACCESS_KEY }
volumes:
- name: rclone-config
secret:
secretName: rclone-config
volumeMounts:
- name: rclone-config
mountPath: /root/.config/rclone
readOnly: trueLocal credentials
Default to rclone for everything it can do. Rclone is configured with an nrp remote and reads its own config — no credential handling needed from you. Use rclone mkdir, rclone copy, rclone sync, rclone lsf, rclone cat, rclone size, rclone purge, etc. directly.
The AWS CLI is only needed for operations rclone doesn't support (bucket policies, CORS). Do not try to extract rclone credentials to feed aws-cli — a PreToolUse hook blocks rclone config show|dump, and parsing ~/.config/rclone/rclone.conf via python/awk is the same anti-pattern in a costume. If you genuinely need aws-cli, ask the user to set AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY in their environment, or ask them to run the aws-cli command themselves with ! prefix.
CRITICAL: NEVER run rclone config show, rclone config dump, cat ~/.config/rclone/rclone.conf, or any command that emits credentials to stdout. Credentials shown in chat logs force immediate key rotation.
Environment Variables for K8s Pods
env:
- name: AWS_ACCESS_KEY_ID
valueFrom:
secretKeyRef: { name: aws, key: AWS_ACCESS_KEY_ID }
- name: AWS_SECRET_ACCESS_KEY
valueFrom:
secretKeyRef: { name: aws, key: AWS_SECRET_ACCESS_KEY }
- name: AWS_S3_ENDPOINT
value: "rook-ceph-rgw-nautiluss3.rook"
- name: AWS_HTTPS
value: "false" # Internal endpoint is plain HTTP
- name: AWS_VIRTUAL_HOSTING
value: "FALSE" # Path-style URLs requiredTool-Specific Endpoint Notes
DuckDB (see duckdb-spatial skill for secret syntax):
- External:
ENDPOINT 's3-west.nrp-nautilus.io',USE_SSL 'TRUE' - Inside pods:
ENDPOINT 'rook-ceph-rgw-nautiluss3.rook',USE_SSL 'FALSE',REGION 'us-east-1' - For public (anonymous) access: empty
KEY_IDandSECRETwork
GDAL/OGR (see gdal-spatial skill for VSI prefix syntax):
- External: use
/vsicurl/https://s3-west.nrp-nautilus.io/... - Inside pods: use
/vsis3/...with the env vars above
Rclone
The remote is named nrp. Inside k8s pods, the config is mounted from rclone-config secret — no additional setup needed.
Ceph S3 (and other non-AWS endpoints like minio) require two non-default options in rclone.conf:
provider = Other
force_path_style = trueWithout these, rclone uses virtual-hosted URLs which Ceph does not support.
Bucket Management
Creating a bucket
rclone mkdir nrp:<bucket-name>Setting public read access
Easiest path: the rc CLI (Rust S3 client, like MinIO's mc).
rc bucket anonymous set download <alias>/<bucket-name>If no rc alias exists yet for the Ceph endpoint, create one from rclone's stored creds (silently, to avoid leaking them into chat logs):
eval "$(python3 -c "
import configparser
c = configparser.ConfigParser()
c.read('$HOME/.config/rclone/rclone.conf')
s = c['nrp']
ep = s.get('endpoint','')
if ep and not ep.startswith('http'): ep = 'https://' + ep
print('K=' + s['access_key_id'])
print('S=' + s['secret_access_key'])
print('E=' + ep)
")"
rc alias set <alias> "$E" "$K" "$S"Note: the existing rc alias named nrp may point to a different (rustfs) endpoint — use a distinct name like ceph to avoid clobbering it.
Fallback (if rc is unavailable and AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY are already exported in the shell):
aws s3api put-bucket-policy \
--bucket <bucket-name> \
--endpoint-url https://s3-west.nrp-nautilus.io \
--policy '{"Version":"2012-10-17","Statement":[
{"Effect":"Allow","Principal":{"AWS":["*"]},
"Action":["s3:GetBucketLocation","s3:ListBucket"],
"Resource":["arn:aws:s3:::<bucket-name>"]},
{"Effect":"Allow","Principal":{"AWS":["*"]},
"Action":["s3:GetObject"],
"Resource":["arn:aws:s3:::<bucket-name>/*"]}
]}'Setting CORS (required for browser access to PMTiles, etc.)
aws s3api put-bucket-cors \
--bucket <bucket-name> \
--endpoint-url https://s3-west.nrp-nautilus.io \
--cors-configuration '{
"CORSRules": [{
"AllowedOrigins": ["*"],
"AllowedMethods": ["GET", "HEAD"],
"AllowedHeaders": ["*"],
"ExposeHeaders": ["ETag", "Content-Length", "Content-Type", "Accept-Ranges", "Content-Range"],
"MaxAgeSeconds": 3600
}]
}'Verifying configuration
aws s3api get-bucket-policy --bucket <bucket-name> --endpoint-url https://s3-west.nrp-nautilus.io
aws s3api get-bucket-cors --bucket <bucket-name> --endpoint-url https://s3-west.nrp-nautilus.ioStandard Bucket Layout
<bucket>/
├── raw/ # Source/original data (uploaded once)
├── <dataset>.parquet # Cloud-optimized GeoParquet
├── <dataset>.pmtiles # Vector tiles for web maps
├── <dataset>/
│ └── hex/
│ └── h0={cell}/data_0.parquet # H3 hex-indexed, hive-partitioned
├── README.md # Data dictionary and usage docs
└── stac-collection.json # STAC metadataSyncing to Source.coop
Source.coop mirrors processed datasets for broader public access using the source rclone remote (pre-configured in rclone-config secret). Run large syncs as k8s jobs, not from a local machine.
Common Pitfalls
- Virtual-hosted URLs — Always use path-style:
https://s3-west.nrp-nautilus.io/<bucket>/... - Public endpoint inside pods — Use the internal endpoint for all S3 ops inside the cluster
- High concurrency on public endpoint — Causes 503 SlowDown; use the internal endpoint
- Forgetting CORS — Required for browser-based tools (PMTiles, map viewers)
- HTTPS on internal endpoint — Internal is HTTP; set
AWS_HTTPS=false - Hardcoding credentials — Always use k8s secrets
- New buckets are private — Must explicitly set public read policy
- Syncing large data locally — Always use a k8s job for large transfers to source.coop
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

