Skip to content

Commit fc25b98

Browse files
committed
feat(ci,deploy): add operator-owned AWS cloud deploy path
- Add Dockerfile with multi-stage build and custom entrypoint that materializes secrets into 0600 files and drops environment copies before exec. - Add CloudFormation template for isolated VPC with ECS Fargate task in private subnets behind NAT gateway, per-stack KMS key, scoped Secrets Manager secret, zero-privilege task role, CloudWatch logs/alarms, and desired count 0 by default. - Add container.yml workflow to build and publish container image to GHCR, with cache-to restricted to non-PR runs to prevent PR cache poisoning. - Add publish-template.yml workflow to validate and publish CloudFormation template to public S3 for CloudFormation Quick Create button. - Add .dockerignore to exclude build artifacts and local files from container context. - Add deploy/container-entrypoint.sh to load secrets from environment into temporary files with restricted permissions. - Add deploy/aws/README.md operator runbook covering stack creation, secret configuration, Permit2 approvals, service control, and security boundaries. - Update README.md with Cloud Deploy section and one-click "Launch Stack" button. - Bump version to 0.1.36.
1 parent d015b03 commit fc25b98

12 files changed

Lines changed: 942 additions & 4 deletions

.dockerignore

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
target
2+
.git
3+
.github
4+
*.local.toml
5+
stitch.key
6+
stitch.env
7+
deploy/aws/.terraform
8+
deploy/aws/terraform.tfstate*

.github/workflows/container.yml

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
name: Container
2+
3+
on:
4+
pull_request:
5+
paths:
6+
- '.github/workflows/container.yml'
7+
- 'Cargo.lock'
8+
- 'Cargo.toml'
9+
- 'Dockerfile'
10+
- '.dockerignore'
11+
- 'deploy/container-entrypoint.sh'
12+
- 'src/**'
13+
push:
14+
branches: [main]
15+
paths:
16+
- '.github/workflows/container.yml'
17+
- 'Cargo.lock'
18+
- 'Cargo.toml'
19+
- 'Dockerfile'
20+
- '.dockerignore'
21+
- 'deploy/container-entrypoint.sh'
22+
- 'src/**'
23+
workflow_dispatch:
24+
25+
permissions:
26+
contents: read
27+
packages: write
28+
29+
concurrency:
30+
group: container-${{ github.ref }}
31+
cancel-in-progress: true
32+
33+
jobs:
34+
build:
35+
runs-on: ubuntu-22.04
36+
steps:
37+
- uses: actions/checkout@v6
38+
with:
39+
persist-credentials: false
40+
41+
- uses: docker/setup-buildx-action@v4
42+
43+
- name: Log in to GitHub Container Registry
44+
if: github.event_name != 'pull_request'
45+
uses: docker/login-action@v4
46+
with:
47+
registry: ghcr.io
48+
username: ${{ github.actor }}
49+
password: ${{ secrets.GITHUB_TOKEN }}
50+
51+
- name: Extract Docker metadata
52+
id: meta
53+
uses: docker/metadata-action@v6
54+
with:
55+
images: ghcr.io/textile-protocol/textile-stitch
56+
tags: |
57+
type=sha,prefix=sha-
58+
type=raw,value=latest,enable={{is_default_branch}}
59+
type=ref,event=branch
60+
type=ref,event=pr
61+
62+
- name: Build container image
63+
uses: docker/build-push-action@v6
64+
with:
65+
context: .
66+
push: ${{ github.event_name != 'pull_request' }}
67+
tags: ${{ steps.meta.outputs.tags }}
68+
labels: ${{ steps.meta.outputs.labels }}
69+
cache-from: type=gha
70+
# Only write the shared build cache from trusted (non-PR) runs. A PR can
71+
# run arbitrary code during the build; letting it populate the gha cache
72+
# would let it poison a layer later consumed by the main publish build.
73+
cache-to: ${{ github.event_name != 'pull_request' && 'type=gha,mode=max' || '' }}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
name: Publish CloudFormation Template
2+
3+
# Publishes deploy/aws/cloudformation.yaml to a public S3 URL so the README's
4+
# "Launch Stack" button (CloudFormation Quick Create) has a template to load.
5+
# Quick Create only accepts an S3-hosted templateURL, not a raw GitHub URL.
6+
7+
on:
8+
push:
9+
branches: [main]
10+
paths:
11+
- 'deploy/aws/cloudformation.yaml'
12+
- '.github/workflows/publish-template.yml'
13+
release:
14+
types: [published]
15+
workflow_dispatch:
16+
17+
permissions:
18+
contents: read
19+
id-token: write
20+
21+
concurrency:
22+
group: publish-template
23+
cancel-in-progress: false
24+
25+
env:
26+
AWS_REGION: us-east-1
27+
# The bucket and key the README button points at. The bucket must exist, have
28+
# a policy granting public s3:GetObject on the aws/* prefix, and the role
29+
# below must be allowed to PutObject into it. See deploy/aws/README.md.
30+
TEMPLATE_BUCKET: textile-stitch-deploy
31+
TEMPLATE_KEY: aws/cloudformation.yaml
32+
33+
jobs:
34+
publish:
35+
runs-on: ubuntu-22.04
36+
steps:
37+
- uses: actions/checkout@v6
38+
with:
39+
persist-credentials: false
40+
41+
- name: Configure AWS credentials
42+
uses: aws-actions/configure-aws-credentials@v4
43+
with:
44+
role-to-assume: ${{ secrets.AWS_TEMPLATE_PUBLISH_ROLE }}
45+
aws-region: ${{ env.AWS_REGION }}
46+
47+
- name: Validate template
48+
run: |
49+
aws cloudformation validate-template \
50+
--template-body file://deploy/aws/cloudformation.yaml
51+
52+
- name: Publish template to S3
53+
run: |
54+
# Immutable per-commit copy operators can pin, plus the stable key the
55+
# README's one-click button loads.
56+
aws s3 cp deploy/aws/cloudformation.yaml \
57+
"s3://${TEMPLATE_BUCKET}/aws/cloudformation-${GITHUB_SHA}.yaml" \
58+
--content-type text/yaml
59+
aws s3 cp deploy/aws/cloudformation.yaml \
60+
"s3://${TEMPLATE_BUCKET}/${TEMPLATE_KEY}" \
61+
--content-type text/yaml

.textile-monorepo-source

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
f9b9462490fc2f7ba88dc84952261d076df2c822
1+
38657270963ea9b6ad571f415a99d78809a812ac

.textile-stitch-release-version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0.1.35
1+
0.1.36

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "stitch-bot"
3-
version = "0.1.35"
3+
version = "0.1.36"
44
edition = "2021"
55
description = "Stitch — Textile filler-network operator bot; signs UniswapX limit orders and closes settlement auctions."
66
license = "AGPL-3.0-or-later"

Dockerfile

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
FROM rust:1-bookworm AS builder
2+
3+
WORKDIR /src
4+
COPY Cargo.toml Cargo.lock ./
5+
COPY src ./src
6+
7+
RUN cargo build --locked --release --bin stitch
8+
9+
FROM debian:bookworm-slim
10+
11+
RUN apt-get update \
12+
&& apt-get install -y --no-install-recommends ca-certificates \
13+
&& rm -rf /var/lib/apt/lists/* \
14+
&& useradd --create-home --home-dir /home/stitch --shell /usr/sbin/nologin stitch \
15+
&& mkdir -p /home/stitch/run \
16+
&& chown -R stitch:stitch /home/stitch
17+
18+
COPY --from=builder /src/target/release/stitch /usr/local/bin/stitch
19+
COPY deploy/container-entrypoint.sh /usr/local/bin/stitch-container-entrypoint
20+
21+
RUN chmod 0755 /usr/local/bin/stitch /usr/local/bin/stitch-container-entrypoint
22+
23+
USER stitch
24+
WORKDIR /home/stitch
25+
26+
ENTRYPOINT ["/usr/local/bin/stitch-container-entrypoint"]
27+
CMD ["stitch", "--config", "/home/stitch/run/stitch.toml"]

README.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ Stitch does two jobs for each configured pool by default:
1919
## Contents
2020

2121
- [Quick Start](#quick-start)
22+
- [Cloud Deploy](#cloud-deploy)
2223
- [Manual Install](#manual-install)
2324
- [How It Works](#how-it-works)
2425
- [Requirements](#requirements)
@@ -53,6 +54,23 @@ For the full copyable prompt, open [AI_INSTALL_PROMPT.md](AI_INSTALL_PROMPT.md).
5354
For configuration reference, tuning, and troubleshooting, see
5455
[ADVANCED.md](ADVANCED.md).
5556

57+
## Cloud Deploy
58+
59+
Stitch can run as an operator-owned cloud bot in your own AWS account. The AWS
60+
self-hosting stack in [deploy/aws](deploy/aws/README.md) creates a self-contained
61+
ECS Fargate environment you own and control: one service, one secret, one wallet,
62+
no public ingress. The bot reaches Textile the same way any external operator
63+
does, over the public RPC/API/indexer/subgraph URLs in your `stitch.toml`.
64+
65+
[![Deploy to AWS](https://img.shields.io/badge/Deploy_to-AWS-FF9900?style=for-the-badge&logo=amazonaws&logoColor=white)](https://console.aws.amazon.com/cloudformation/home?region=us-east-1#/stacks/quickcreate?templateURL=https%3A%2F%2Ftextile-stitch-deploy.s3.us-east-1.amazonaws.com%2Faws%2Fcloudformation.yaml&stackName=stitch-operator)
66+
67+
The button opens CloudFormation in your own AWS account with the Stitch stack
68+
prefilled. Sign in, pick your region (it defaults to `us-east-1`), review the
69+
parameters, and create the stack. It comes up stopped by default. Then follow
70+
[deploy/aws](deploy/aws/README.md) to load the wallet secret, run Permit2
71+
approvals, and set the service desired count to `1` when you are ready to run
72+
live.
73+
5674
## Manual Install
5775

5876
Install the latest release:

0 commit comments

Comments
 (0)