Building Rust Applications in AWS CodeBuild
@rawandshaswar|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:
- Use any programming language, including Rust
- Build inside custom Docker environments (e.g., official Rust Docker images or community-maintained ones)
- Or use AWS-managed base images with supported runtimes (Python, Java, Go, Node.js, etc.) and also custom images
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?
-
ARM_CONTAINER – uses AWS Graviton (AArch64) underneath so your crates compile natively.
-
amazonlinux-aarch64-standard:3.0 – latest AL2023-based image with Rust toolchain available via
rustup
. -
BUILD_GENERAL1_MEDIUM – 4 vCPUs / 8 GiB RAM – bump up if you need more horsepower.
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
- Commit & push the workflow.
- In GitHub → Actions you'll see the job waiting for a runner.
- 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.