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
132 changes: 132 additions & 0 deletions .github/workflows/build-base-images.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
name: Build Base AMIs

on:
workflow_dispatch:
inputs:
region:
description: "AWS region for AMI builds. Defaults to AWS_REGION secret."
required: false
type: string
default: ""
ami_prefix:
description: "AMI name prefix"
required: true
type: string
default: dash-network-base
arch:
description: "Architecture(s) to build"
required: true
type: choice
options:
- both
- amd64
- arm64
default: both
schedule:
# Refresh base AMIs weekly so new deploys can use recent Ubuntu/package updates.
- cron: '20 4 * * 0'

permissions:
contents: read

jobs:
build:
name: Build Dash Network base AMIs
runs-on: ubuntu-22.04
timeout-minutes: 120
concurrency:
group: build-base-amis-${{ inputs.region || 'scheduled' }}
cancel-in-progress: false

env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_SESSION_TOKEN: ${{ secrets.AWS_SESSION_TOKEN }}
AWS_REGION: ${{ inputs.region || secrets.AWS_REGION }}
AWS_DEFAULT_REGION: ${{ inputs.region || secrets.AWS_REGION }}
AMI_PREFIX: ${{ inputs.ami_prefix || 'dash-network-base' }}
AMI_ARCH: ${{ inputs.arch || 'both' }}
ANSIBLE_HOST_KEY_CHECKING: "false"

steps:
- name: Checkout dash-network-deploy
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5
with:
persist-credentials: false

- name: Set up Packer
uses: hashicorp/setup-packer@1aa358be5cf73883762b302a3a03abd66e75b232

- name: Install controller dependencies
run: |
sudo apt-get update
sudo apt-get install -y python3-pip python3-netaddr jq
python3 -m pip install --upgrade pip
python3 -m pip install ansible-core==2.16.3 jmespath

- name: Validate AWS configuration
run: |
test -n "$AWS_ACCESS_KEY_ID"
test -n "$AWS_SECRET_ACCESS_KEY"
test -n "$AWS_REGION"
aws sts get-caller-identity --output json >/dev/null

- name: Initialize and validate Packer template
run: |
packer init packer/dash-network-base.pkr.hcl
packer fmt -check packer/dash-network-base.pkr.hcl
packer validate \
-var "region=${AWS_REGION}" \
-var "ami_prefix=${AMI_PREFIX}" \
packer/dash-network-base.pkr.hcl

- name: Build base AMIs
run: |
args=(--region="${AWS_REGION}" --ami-prefix="${AMI_PREFIX}")
case "$AMI_ARCH" in
both) ;;
amd64|arm64) args+=(--only="$AMI_ARCH") ;;
*)
echo "Unsupported arch: $AMI_ARCH" >&2
exit 1
;;
esac

./bin/build-base-image "${args[@]}"

- name: Summarize latest base AMIs
run: |
{
echo "## Latest base AMIs"
echo
echo "Region: \`${AWS_REGION}\`"
echo
echo "| Architecture | AMI ID | Name | Created |"
echo "| --- | --- | --- | --- |"
for arch in amd64 arm64; do
if [[ "$AMI_ARCH" != "both" && "$AMI_ARCH" != "$arch" ]]; then
continue
fi

image_json=$(aws ec2 describe-images \
--owners self \
--filters \
"Name=tag:Project,Values=dash-network-deploy" \
"Name=tag:Architecture,Values=${arch}" \
"Name=name,Values=${AMI_PREFIX}-${arch}-*" \
--query 'sort_by(Images, &CreationDate)[-1]' \
--output json)

image_id=$(jq -r '.ImageId // ""' <<< "$image_json")
name=$(jq -r '.Name // ""' <<< "$image_json")
created=$(jq -r '.CreationDate // ""' <<< "$image_json")

if [[ -z "$image_id" ]]; then
echo "| ${arch} | not found | | |"
else
echo "| ${arch} | \`${image_id}\` | \`${name}\` | ${created} |"
fi
done
echo
echo "Set these in a network tfvars file as \`base_ami_amd64_id\` and \`base_ami_arm64_id\` when you want a deploy to adopt them."
} >> "$GITHUB_STEP_SUMMARY"
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Ansible
/ansible/*.retry
/ansible/deploy.yml.pre-*

# Node.JS
node_modules
Expand All @@ -10,6 +11,9 @@ node_modules
# Terraform
/terraform/aws/.terraform

# Local run logs
/logs/

# Jet Brains
.idea

Expand Down
39 changes: 38 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ Dash Core developers to assist in Dash Platform development.
## Installation

1. [Install Docker](https://docs.docker.com/install/)
2. Download tool:
2. [Install Packer](https://developer.hashicorp.com/packer/install) if you plan to build pre-baked base AMIs.
3. Download tool:

Using `wget`:

Expand Down Expand Up @@ -78,6 +79,13 @@ dash-network deploy <network_name>

You may pass the `--only-infrastructure` or `--only-provisioning` option to target either infrastructure or software provisioning workflows.

For faster updates to an existing deployment, pass `--fast`. Fast mode skips Docker
image updates, final Docker cleanup, and slow observability/logging setup such as
CloudWatch Agent, Elastic/logs, filebeat, metricbeat, metrics, and status
dashboards. It also polls masternode sync more frequently while preserving the
same maximum wait time, and keeps the registration block generator running
through collateral/protx/spork waits instead of restarting it for each wait.

To destroy an available Dash Network, use the `destroy` command:

```bash
Expand Down Expand Up @@ -208,3 +216,32 @@ aws route53 create-hosted-zone --name networks.domain.tld --caller-reference 123
```

Please note the values of these, as they will be needed in the network config files.

## Pre-baked base AMIs

Deployments can use architecture-specific base AMIs with common host setup already installed. This avoids repeating the slow, identical bootstrap work on every deploy.

Build both AMIs with Packer:

```bash
bin/build-base-image --profile=<aws-profile> --region=us-west-2
```

The `Build Base AMIs` GitHub Actions workflow also refreshes these AMIs weekly and can be run manually for a specific region, prefix, or architecture. It uses the same AWS repository secrets as the deploy workflows: `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, optional `AWS_SESSION_TOKEN`, and `AWS_REGION`.

Then set the generated AMI IDs in the network tfvars:

```hcl
base_ami_amd64_id = "ami-..."
base_ami_arm64_id = "ami-..."
```

When provisioning instances launched from those AMIs, skip the baked common setup:

```bash
./bin/deploy -p --prebaked-common-setup <network_name>
```

The baked image includes swap, common packages, Python/pip Docker dependencies, Docker, Docker daemon options, and Eternal Terminal. Per-host runtime configuration still runs during deploy, including hostnames, `/etc/hosts`, CloudWatch Agent configuration, VPN, logs, metrics, and node-specific Dash services.

Changing AMI IDs does not replace existing instances automatically because Terraform ignores AMI drift for instance resources. Recreate or taint instances to adopt a new base image.
Loading