August 20, 2026 · v1.4.21
v1.4.21 is a CloudFormation and Aurora correctness release. CloudFormation change sets stop reporting an invalid status that broke the CDK, a replacement of a custom-named resource is refused instead of silently destroying data, and SES configuration sets provision. RDS Aurora global databases and replicated readers survive Stop/Start and validate engine versions across every write path. Around that, S3 gains correct conditional deletes and multipart composite checksums, IoT adds a native mTLS MQTT listener on port 8883, and API Gateway routes on the resource+method pair the way AWS does.
cryptography package is installed (IOT_MTLS_ENABLED=0 to disable, IOT_MTLS_PORT to move it) — with the broker certificate served at GET /_ministack/iot/ca.pem. A client certificate is optional: a device presenting none is served under MINISTACK_ACCOUNT_ID like an unsigned WebSocket upgrade, and an unknown or non-ACTIVE certificate is refused with a 0x05 CONNACK. Contributed by @iot-rocket.MINISTACK_RDS_PG_CLUSTER_REPLICATION, StopDBCluster now stops the reader containers alongside the writer and StartDBCluster revives each reader by re-cloning from the writer; the same revival runs on a MiniStack restart, so a persisted reader comes back as a real hot standby instead of being demoted to a writer alias. Contributed by @kiran01bm.AWS::SES::ConfigurationSet and AWS::SES::ConfigurationSetEventDestination. A template carrying an SES configuration set failed with Unsupported resource type; both resource types now provision (registered in the classic and v2 SES stores, Ref returns the set name, the event destination round-trips), CloudFormation-provisioning fidelity only. Contributed by @ryan-bennett.{proxy+} elsewhere in the tree as it does on AWS, and only an exact resource+method match keeps the request; routing precedes authorization. Supersedes the 1.4.16 change that answered a methodless resource 403. Contributed by @iot-rocket.ExecuteChangeSet wrote the invalid EXECUTE_COMPLETE into Status, breaking the CDK's Status == CREATE_COMPLETE gate. Status now stays CREATE_COMPLETE while ExecutionStatus tracks the deployment outcome; a no-change set ends FAILED, a missing set returns ChangeSetNotFound (404), a duplicate name is AlreadyExistsException, deleting a stack removes its change sets, and a direct UpdateStack marks pending sets OBSOLETE. Reported by @iot-rocket.TableName) executed the replacement and dropped the table's rows; it now fails and rolls back to UPDATE_ROLLBACK_COMPLETE with the message real CloudFormation uses, leaving the resource and its data intact. Reported by @iot-rocket.ModifyDBInstance, ModifyDBCluster, CreateGlobalCluster and ModifyGlobalCluster stored engine versions the catalog does not advertise; all paths now reject them (InvalidParameterCombination / Cannot find upgrade target … on the modify paths), ModifyGlobalCluster propagates an accepted version to every member, and a member moved to a different major than its global is refused. Contributed by @kiran01bm.StopDBCluster and StartDBCluster are now limited to sole-member global databases (InvalidDBClusterStateFault), deleting a primary's last instance preserves compute other global members still need, and a successful recreate resets stale MySQL replica state before re-linking replication. Contributed by @kiran01bm.arn:aws:states:::<service>:<action> integration MiniStack does not implement echoed its input back as SUCCEEDED, so a state machine whose side effect never ran still reported success; it now fails with States.Runtime. Reported by @iwasakar.DeleteObject with If-Match on a key that is not there now returns 204, and If-Match: * is honored as an existence check — it holds against any present object and returns 412 PreconditionFailed when the key is absent — rather than being compared as a literal ETag. Contributed by @gaul.CreateMultipartUpload records the checksum algorithm, UploadPart validates and echoes each part's checksum, and completion builds the AWS composite (<digest>-<parts>, the digest of the parts' digests) read back as COMPOSITE; a mismatch is BadDigest. Contributed by @gaul.docker pull ministackorg/ministack:1.4.21 docker run -d -p 4566:4566 ministackorg/ministack:1.4.21
Or pin in compose.yaml:
services:
ministack:
image: ministackorg/ministack:1.4.21
ports:
- "4566:4566"
Issues and PRs welcome on GitHub. Discussion on r/ministack.