Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion .github/workflows/docker-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,16 @@ jobs:
variant:
- name: standard
nix_target: cdk-mintd-static
dockerfile: Dockerfile.static
tag_suffix: ""
- name: ldk-node
nix_target: cdk-mintd-ldk-static
dockerfile: Dockerfile.static
tag_suffix: "-ldk-node"
- name: hardened
nix_target: cdk-mintd-static
dockerfile: Dockerfile.hardened
tag_suffix: "-hardened"
runs-on: ${{ matrix.arch.runner }}
timeout-minutes: 120
permissions:
Expand Down Expand Up @@ -66,7 +72,7 @@ jobs:
nix build .#${{ matrix.variant.nix_target }} -L
mkdir -p ./docker-build
cp -f ./result/bin/* ./docker-build/cdk-mintd
cp Dockerfile.static ./docker-build/Dockerfile
cp ${{ matrix.variant.dockerfile }} ./docker-build/Dockerfile

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
Expand Down Expand Up @@ -118,6 +124,8 @@ jobs:
tag_suffix: ""
- name: ldk-node
tag_suffix: "-ldk-node"
- name: hardened
tag_suffix: "-hardened"

steps:
- name: Login to Docker Hub
Expand Down
29 changes: 29 additions & 0 deletions Dockerfile.hardened
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# syntax=docker/dockerfile:1.7

FROM alpine:3.21 AS rootfs

RUN apk add --no-cache ca-certificates && \
mkdir -p /data && \
chown 10001:10001 /data

FROM scratch

LABEL org.opencontainers.image.title="CDK Mintd Hardened" \
org.opencontainers.image.description="Shell-less CDK mintd image with a static binary and scratch runtime"

COPY --from=rootfs /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
COPY --from=rootfs --chown=10001:10001 /data /data
COPY --chown=0:0 --chmod=0555 cdk-mintd /usr/local/bin/cdk-mintd

ENV CDK_MINTD_WORK_DIR=/data \
HOME=/data \
SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt \
SQLITE_TMPDIR=/data \
TMPDIR=/data
Comment on lines +21 to +22

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't we want to create /tmp too and point SQLITE_TMPDIR and TMPDIR there?

Mixing data files and temp files together sounds bad.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you are right. We probably don't have to create the directory at all.
I'm going to update this. Thanks.


WORKDIR /data
USER 10001:10001
VOLUME ["/data"]
EXPOSE 8085 9000

ENTRYPOINT ["/usr/local/bin/cdk-mintd"]
47 changes: 47 additions & 0 deletions crates/cdk-mintd/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,53 @@ docker-compose --profile ldk-node up

- **`cashubtc/mintd:latest`** - Standard mint with default features
- **`cashubtc/mintd-ldk-node:latest`** - Mint with LDK Node support
- **`cashubtc/mintd:latest-hardened`** - Shell-less standard mint image built from `scratch`

### Hardened Image

The hardened image is built from `scratch` and contains only the static `cdk-mintd`
binary, CA certificates, and `/data`. It has no `/bin/sh`, `curl`, `tar`, package
manager, or debug tools. The image runs as UID/GID `10001:10001` and defaults the
CDK work directory to `/data`.

Run it with a read-only root filesystem and a writable `/data` mount:

```bash
docker run --rm \
--read-only \
--user 10001:10001 \
--cap-drop ALL \
--security-opt no-new-privileges:true \
--mount type=volume,src=cdk_mintd_data,dst=/data \
-p 8085:8085 \
-e CDK_MINTD_URL=https://example.com \
-e CDK_MINTD_LN_BACKEND=fakewallet \
-e CDK_MINTD_LISTEN_HOST=0.0.0.0 \
-e CDK_MINTD_LISTEN_PORT=8085 \
-e CDK_MINTD_DATABASE=sqlite \
-e CDK_MINTD_CACHE_BACKEND=memory \
cashubtc/mintd:latest-hardened
```

Or use the Compose file that applies the same runtime hardening:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new hardened-image README section points users to docker-compose -f docker-compose.hardened.yaml up, but this PR only adds Dockerfile.hardened and no docker-compose.hardened.yaml exists in the repository. Users following the documented Compose workflow will hit a missing-file error. Please either add the referenced Compose file with the runtime hardening settings described here, or remove/adjust this paragraph.


```bash
docker-compose -f docker-compose.hardened.yaml up
```

The Dockerfile expects a prebuilt Linux static binary named `cdk-mintd` in the
build context. This matches the release workflow. For a local Linux build with
Nix:

```bash
nix build .#cdk-mintd-static
mkdir -p docker-build
cp ./result/bin/* ./docker-build/cdk-mintd
cp Dockerfile.hardened ./docker-build/Dockerfile
docker build --platform linux/arm64 -t cashubtc/mintd:local-hardened ./docker-build
```

For amd64, use `--platform linux/amd64` and build the matching static binary.

### Configuration via Environment Variables

Expand Down