Rawand Ahmed Shaswar

Building Rust Applications in AWS CodeBuild

Jul 5, 2025 (2w ago)42 views

A few days ago, I tried my best to use GitHub Actions' self-hosted runners to build a Rust application for an ARM-based EC2 instance, It was known to me a few hours later that, GitHub does not provide ARM-based self-hosted runners for private repositories, and I had to find a way to build my Rust application for ARM64 architecture.

So I decided to use AWS CodeBuild, a fully managed continuous integration service that compiles source code, runs tests, and produces software packages. Aside from the deep integration with AWS services, it also supports Docker images, which means you can use any Docker image as a build environment.

For me personally, I wanted to use the official Amazon Linux ARM image. And I used it to build both backend and engine repo's of my Retrack App project.

CodeBuild is a direct alternative to GitHub Actions

You can build virtually anything on CodeBuild—similar to GitHub Actions—if you're comfortable in AWS. Setting up a build pipeline is straightforward. You can:

Is it expensive?

AWS CodeBuild is a pay-as-you-go service, which means you only pay for the build time you use. The cost depends on the type of build environment you choose and the duration of the build.

Tier Specs Price (Linux)
general1.small 2 vCPU, 3 GB memory $0.005 / minute
general1.medium 4 vCPU, 7 GB memory ~$0.01 / minute
general1.large 8 vCPU, 15 GB memory ~$0.02 / minute

1. Getting Started

First, let's set a enviroment variable called GH_TOKEN. With this we can begin importing GitHub credentials into CodeBuild so it can listen for workflow jobs.

export GH_TOKEN=your_github_token

Next, we will import it into CodeBuild Credentials:

aws codebuild import-source-credentials \
  --server-type GITHUB \
  --auth-type PERSONAL_ACCESS_TOKEN \
  --token "$GH_TOKEN"

Only needed once per AWS account/region.

2. Create an IAM service role for CodeBuild

# Create a role for CodeBuild to assume
cat <<'EOF' > codebuild-trust.json
{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": {"Service": "codebuild.amazonaws.com"},
    "Action": "sts:AssumeRole"
  }]
}
EOF

# Create the role
aws iam create-role \
  --role-name CodeBuildRustArmRole \
  --assume-role-policy-document file://codebuild-trust.json

# Give the role broad build permissions (fine-tune later!)
aws iam attach-role-policy \
  --role-name CodeBuildRustArmRole \
  --policy-arn arn:aws:iam::aws:policy/AWSCodeBuildDeveloperAccess

# Export the role arn for use
export ROLE_ARN=$(aws iam get-role --role-name "$ROLE_NAME" \
                 --query 'Role.Arn' --output text)

Now we are ready to create a CodeBuild project that uses this role.

3. Create the CodeBuild project

First, we need a few variables to work with this carefully:

ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
PROJECT_NAME="rust-arm-runner" # Name of the CodeBuild project
GITHUB_REPO="https://github.com/<your-username>/<your-repo>.git"
ROLE_ARN="arn:aws:iam::$ACCOUNT_ID:role/CodeBuildRustArmRole"

Next, we can create the CodeBuild project:

aws codebuild create-project \
  --name "$PROJECT_NAME" \
  --description "ARM GitHub Actions runner for Rust builds" \
  --source "type=GITHUB,location=$GITHUB_REPO,buildspec=" \
  --artifacts "type=NO_ARTIFACTS" \
  --environment "type=ARM_CONTAINER,image=aws/codebuild/amazonlinux-aarch64-standard:3.0,computeType=BUILD_GENERAL1_MEDIUM" \
  --service-role "$ROLE_ARN" \
  --tags name=lang,value=rust

Why these flags?

4. Turn the project into a GitHub Actions runner

A runner project listens only for WORKFLOW_JOB_QUEUED events – we add a webhook filter for that.

aws codebuild create-webhook \
  --project-name "$PROJECT_NAME" \
  --filter-groups '[ [ {"type":"EVENT","pattern":"WORKFLOW_JOB_QUEUED"} ] ]'

Confirm if it's created by running:

aws codebuild batch-get-projects --names $PROJECT_NAME --query "projects[0].webhook"

Should show filterGroups with WORKFLOW_JOB_QUEUED.

5. Creating a workflow file:

Create a file called .github/workflows/ci.yml and add it to your repo:

name: Rust CI (AWS CodeBuild – ARM)

on:
  push:
    branches: ["main"]
  pull_request:
    branches: ["main"]

jobs:
  build:
    runs-on: codebuild-rust-arm-runner-${{ github.run_id }}-${{ github.run_attempt }}
    steps:
      - uses: actions/checkout@v4
      - name: Set up Rust (stable)
        uses: dtolnay/rust-toolchain@stable
      - name: Build & test
        run: |
          cargo build --verbose --release
          cargo test --verbose

Key bit → the runs-on label must start with codebuild-$PROJECT_NAME-.
The convention above keeps the project name plus adds GitHub's run metadata so multiple jobs don't collide.

6. Test the pipeline

  1. Commit & push the workflow.
  2. In GitHub → Actions you'll see the job waiting for a runner.
  3. In the AWS Console → CodeBuild → builds, you should see a new build spin up, compile your Rust crate on ARM and report back.

Cleanup

# 1 Delete the runner project (removes the webhook automatically)
aws codebuild delete-project --name "$PROJECT_NAME"

# 2 Remove the GitHub PAT stored in this account/region (optional but recommended)
#   – list tokens first, then delete the ARN that points to GITHUB
CREDS_ARN=$(aws codebuild list-source-credentials --query 'sourceCredentialsInfos[?serverType==`GITHUB`].arn' --output text)
if [ -n "$CREDS_ARN" ]; then
  aws codebuild delete-source-credentials --arn "$CREDS_ARN"
fi

# 3 Detach any managed policies attached to the role and delete the role
for ARN in $(aws iam list-attached-role-policies \
              --role-name CodeBuildRustArmRole \
              --query 'AttachedPolicies[].PolicyArn' --output text); do
  aws iam detach-role-policy --role-name CodeBuildRustArmRole --policy-arn "$ARN"
done

# Remove any inline policies just in case
for POLICY in $(aws iam list-role-policies --role-name CodeBuildRustArmRole --query 'PolicyNames[]' --output text); do
  aws iam delete-role-policy --role-name CodeBuildRustArmRole --policy-name "$POLICY"
done

# Finally, delete the role
aws iam delete-role --role-name CodeBuildRustArmRole

Running this above leaves zero AWS resources in your account related to this demo.

References