Garage serves all three buckets and both apps, and a last comparison found nothing in MinIO that Garage lacks. Drop the MinIO service, its bootstrap and its root credentials from the deploy, and let compose remove the leftover containers. The storage_minio_data volume is left on the host. All images can be pulled again, so the deploy goes back to failing on a pull error. Document Garage in the README and SECRETS, including the key format and how the existing secrets map to it, and swap the MinIO client in the flake for awscli and rclone. Assisted-by: Claude:fable-5-2
This commit is contained in:
parent
bdfc028ca1
commit
e9388c0b0d
6 changed files with 74 additions and 231 deletions
|
|
@ -1,148 +0,0 @@
|
|||
#!/bin/sh
|
||||
# Idempotent MinIO bootstrap: bucket + per-app service account scoped to that
|
||||
# bucket. Re-running just refreshes the policy and resets the access key.
|
||||
set -eu
|
||||
|
||||
mc alias set local http://minio:9000 "${MINIO_ROOT_USER}" "${MINIO_ROOT_PASSWORD}"
|
||||
|
||||
ensure_bucket() {
|
||||
bucket="$1"
|
||||
if ! mc ls "local/${bucket}" >/dev/null 2>&1; then
|
||||
mc mb "local/${bucket}"
|
||||
fi
|
||||
mc anonymous set none "local/${bucket}" >/dev/null
|
||||
}
|
||||
|
||||
write_policy() {
|
||||
name="$1"
|
||||
bucket="$2"
|
||||
cat > "/tmp/${name}.json" <<EOF
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Action": ["s3:ListBucket", "s3:GetBucketLocation"],
|
||||
"Resource": ["arn:aws:s3:::${bucket}"]
|
||||
},
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Action": ["s3:GetObject", "s3:PutObject", "s3:DeleteObject"],
|
||||
"Resource": ["arn:aws:s3:::${bucket}/*"]
|
||||
}
|
||||
]
|
||||
}
|
||||
EOF
|
||||
mc admin policy create local "${name}" "/tmp/${name}.json" 2>/dev/null \
|
||||
|| mc admin policy update local "${name}" "/tmp/${name}.json"
|
||||
}
|
||||
|
||||
# Read-only on one prefix of a bucket.
|
||||
write_ro_prefix_policy() {
|
||||
name="$1"
|
||||
bucket="$2"
|
||||
prefix="$3"
|
||||
cat > "/tmp/${name}.json" <<EOF
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Action": ["s3:GetObject"],
|
||||
"Resource": ["arn:aws:s3:::${bucket}/${prefix}*"]
|
||||
}
|
||||
]
|
||||
}
|
||||
EOF
|
||||
mc admin policy create local "${name}" "/tmp/${name}.json" 2>/dev/null \
|
||||
|| mc admin policy update local "${name}" "/tmp/${name}.json"
|
||||
}
|
||||
|
||||
# World-readable by object key; no anonymous listing or writes.
|
||||
ensure_public_bucket() {
|
||||
bucket="$1"
|
||||
if ! mc ls "local/${bucket}" >/dev/null 2>&1; then
|
||||
mc mb "local/${bucket}"
|
||||
fi
|
||||
cat > "/tmp/${bucket}-anonymous.json" <<EOF
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Principal": {"AWS": ["*"]},
|
||||
"Action": ["s3:GetObject"],
|
||||
"Resource": ["arn:aws:s3:::${bucket}/*"]
|
||||
}
|
||||
]
|
||||
}
|
||||
EOF
|
||||
mc anonymous set-json "/tmp/${bucket}-anonymous.json" "local/${bucket}" >/dev/null
|
||||
}
|
||||
|
||||
# Put and delete only: the holder can publish and retract, not read or list.
|
||||
write_upload_policy() {
|
||||
name="$1"
|
||||
bucket="$2"
|
||||
cat > "/tmp/${name}.json" <<EOF
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Action": ["s3:PutObject", "s3:DeleteObject"],
|
||||
"Resource": ["arn:aws:s3:::${bucket}/*"]
|
||||
}
|
||||
]
|
||||
}
|
||||
EOF
|
||||
mc admin policy create local "${name}" "/tmp/${name}.json" 2>/dev/null \
|
||||
|| mc admin policy update local "${name}" "/tmp/${name}.json"
|
||||
}
|
||||
|
||||
# $3: one or more policy names, space-separated.
|
||||
ensure_user() {
|
||||
access="$1"
|
||||
secret="$2"
|
||||
policies="$3"
|
||||
if mc admin user info local "${access}" >/dev/null 2>&1; then
|
||||
# Rotate secret to match desired state.
|
||||
mc admin user remove local "${access}" >/dev/null
|
||||
fi
|
||||
mc admin user add local "${access}" "${secret}"
|
||||
# shellcheck disable=SC2086 # word-split the policy list on purpose
|
||||
mc admin policy attach local ${policies} --user "${access}" 2>/dev/null || true
|
||||
}
|
||||
|
||||
ensure_bucket "asxpio-invoices"
|
||||
write_policy "asxpio-invoices-rw" "asxpio-invoices"
|
||||
|
||||
# Datacenter bingo photos: uploaded and resized by asxpio's admin, served by
|
||||
# datacenterbingo. Keys keep their bingo/ prefix, so DB rows stay valid.
|
||||
ensure_bucket "datacenterbingo-photos"
|
||||
write_policy "datacenterbingo-photos-rw" "datacenterbingo-photos"
|
||||
write_ro_prefix_policy "datacenterbingo-photos-ro" "datacenterbingo-photos" ""
|
||||
|
||||
ensure_user "${ASXPIO_S3_ACCESS_KEY}" "${ASXPIO_S3_SECRET_KEY}" "asxpio-invoices-rw datacenterbingo-photos-rw"
|
||||
|
||||
if [ -n "${BINGO_S3_ACCESS_KEY:-}" ] && [ -n "${BINGO_S3_SECRET_KEY:-}" ]; then
|
||||
ensure_user "${BINGO_S3_ACCESS_KEY}" "${BINGO_S3_SECRET_KEY}" "datacenterbingo-photos-ro"
|
||||
else
|
||||
echo "minio-init: BINGO_S3_* unset, skipping bingo user"
|
||||
fi
|
||||
|
||||
# Files shared by link: https://s3.asxp.io/public/<key>. Everything in this
|
||||
# bucket is readable by anyone who knows the key.
|
||||
ensure_public_bucket "public"
|
||||
write_upload_policy "public-upload" "public"
|
||||
|
||||
if [ -n "${PUBLIC_S3_ACCESS_KEY:-}" ] && [ -n "${PUBLIC_S3_SECRET_KEY:-}" ]; then
|
||||
ensure_user "${PUBLIC_S3_ACCESS_KEY}" "${PUBLIC_S3_SECRET_KEY}" "public-upload"
|
||||
else
|
||||
echo "minio-init: PUBLIC_S3_* unset, skipping public uploader"
|
||||
fi
|
||||
|
||||
# Leftover from before the photos had their own bucket.
|
||||
mc admin policy remove local "asxpio-invoices-bingo-ro" >/dev/null 2>&1 || true
|
||||
|
||||
echo "minio-init: done"
|
||||
Loading…
Add table
Add a link
Reference in a new issue