diff --git a/.github/actions/build-ami/action.yml b/.github/actions/build-ami/action.yml index 2cf3c12597..6f17706988 100644 --- a/.github/actions/build-ami/action.yml +++ b/.github/actions/build-ami/action.yml @@ -18,6 +18,14 @@ inputs: description: 'Prefix for the AMI name' required: false default: 'supabase-postgres' + packer_template: + description: 'Packer template for stage 1 (e.g., amazon-arm64-nix.pkr.hcl)' + required: false + default: 'amazon-arm64-nix.pkr.hcl' + instance_type: + description: 'EC2 instance type for the build' + required: false + default: 'c6g.4xlarge' outputs: stage2_ami_id: @@ -65,7 +73,7 @@ runs: -var "packer-execution-id=${{ env.EXECUTION_ID }}" \ -var "ansible_arguments=-e postgresql_major=${{ inputs.postgres_version }}" \ -var 'ami_regions=${{ inputs.ami_regions }}' \ - amazon-arm64-nix.pkr.hcl + ${{ inputs.packer_template }} - name: Build AMI stage 2 id: build-stage2 @@ -84,4 +92,5 @@ runs: -var "postgres_major_version=${{ inputs.postgres_version }}" \ -var "ami_name=${{ inputs.ami_name_prefix }}" \ -var "git_sha=${{ inputs.git_sha }}" \ + -var "instance_type=${{ inputs.instance_type }}" \ stage2-nix-psql.pkr.hcl diff --git a/.github/workflows/ami-release-nix-single.yml b/.github/workflows/ami-release-nix-single.yml index ff23bddd63..12dbf362e3 100644 --- a/.github/workflows/ami-release-nix-single.yml +++ b/.github/workflows/ami-release-nix-single.yml @@ -12,6 +12,14 @@ on: required: true type: string default: 'main' + arch: + description: 'Architecture to build' + required: true + type: choice + options: + - arm64 + - amd64 + default: arm64 permissions: contents: write @@ -19,7 +27,7 @@ permissions: jobs: build: - runs-on: large-linux-arm + runs-on: ${{ github.event.inputs.arch == 'amd64' && 'blacksmith-2vcpu-ubuntu-2404' || 'large-linux-arm' }} timeout-minutes: 150 steps: @@ -41,6 +49,26 @@ jobs: run: | echo "sha=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT" + - name: Set arch-specific variables + id: arch_vars + run: | + ARCH="${{ github.event.inputs.arch }}" + if [ "$ARCH" = "amd64" ]; then + { + echo "packer_template=amazon-amd64-nix.pkr.hcl" + echo "instance_type=c6i.4xlarge" + echo "ami_name_prefix=supabase-postgres-x86" + echo "version_suffix=-x86" + } >> "$GITHUB_OUTPUT" + else + { + echo "packer_template=amazon-arm64-nix.pkr.hcl" + echo "instance_type=c6g.4xlarge" + echo "ami_name_prefix=supabase-postgres" + echo "version_suffix=" + } >> "$GITHUB_OUTPUT" + fi + - name: Install nix uses: ./.github/actions/nix-install-ephemeral with: @@ -57,6 +85,9 @@ jobs: region: us-east-1 ami_regions: '["us-east-1"]' git_sha: ${{ steps.get_sha.outputs.sha }} + packer_template: ${{ steps.arch_vars.outputs.packer_template }} + instance_type: ${{ steps.arch_vars.outputs.instance_type }} + ami_name_prefix: ${{ steps.arch_vars.outputs.ami_name_prefix }} - name: Grab release version id: process_release_version @@ -83,16 +114,17 @@ jobs: run: | cd ansible ansible-playbook -i localhost \ - -e "ami_release_version=${{ steps.process_release_version.outputs.version }}" \ + -e "ami_release_version=${{ steps.process_release_version.outputs.version }}${{ steps.arch_vars.outputs.version_suffix }}" \ -e "internal_artifacts_bucket=${{ secrets.ARTIFACTS_BUCKET }}" \ -e "postgres_major_version=${{ github.event.inputs.postgres_version }}" \ + -e "arch=${{ github.event.inputs.arch }}" \ manifest-playbook.yml - name: Upload nix flake revision to s3 staging run: | - aws s3 cp /tmp/pg_binaries.tar.gz s3://${{ secrets.ARTIFACTS_BUCKET }}/upgrades/postgres/supabase-postgres-${{ steps.process_release_version.outputs.version }}/20.04.tar.gz - aws s3 cp /tmp/pg_binaries.tar.gz s3://${{ secrets.ARTIFACTS_BUCKET }}/upgrades/postgres/supabase-postgres-${{ steps.process_release_version.outputs.version }}/24.04.tar.gz - aws s3 cp /tmp/pg_binaries.tar.gz s3://${{ secrets.ARTIFACTS_BUCKET }}/upgrades/postgres/supabase-postgres-${{ steps.process_release_version.outputs.version }}/upgrade_bundle.tar.gz + aws s3 cp /tmp/pg_binaries.tar.gz s3://${{ secrets.ARTIFACTS_BUCKET }}/upgrades/postgres/supabase-postgres-${{ steps.process_release_version.outputs.version }}${{ steps.arch_vars.outputs.version_suffix }}/20.04.tar.gz + aws s3 cp /tmp/pg_binaries.tar.gz s3://${{ secrets.ARTIFACTS_BUCKET }}/upgrades/postgres/supabase-postgres-${{ steps.process_release_version.outputs.version }}${{ steps.arch_vars.outputs.version_suffix }}/24.04.tar.gz + aws s3 cp /tmp/pg_binaries.tar.gz s3://${{ secrets.ARTIFACTS_BUCKET }}/upgrades/postgres/supabase-postgres-${{ steps.process_release_version.outputs.version }}${{ steps.arch_vars.outputs.version_suffix }}/upgrade_bundle.tar.gz - name: configure aws credentials - prod uses: aws-actions/configure-aws-credentials@7474bc4690e29a8392af63c5b98e7449536d5c3a # v4.3.1 @@ -104,22 +136,23 @@ jobs: run: | cd ansible ansible-playbook -i localhost \ - -e "ami_release_version=${{ steps.process_release_version.outputs.version }}" \ + -e "ami_release_version=${{ steps.process_release_version.outputs.version }}${{ steps.arch_vars.outputs.version_suffix }}" \ -e "internal_artifacts_bucket=${{ secrets.PROD_ARTIFACTS_BUCKET }}" \ -e "postgres_major_version=${{ github.event.inputs.postgres_version }}" \ + -e "arch=${{ github.event.inputs.arch }}" \ manifest-playbook.yml - name: Upload nix flake revision to s3 prod run: | - aws s3 cp /tmp/pg_binaries.tar.gz s3://${{ secrets.PROD_ARTIFACTS_BUCKET }}/upgrades/postgres/supabase-postgres-${{ steps.process_release_version.outputs.version }}/20.04.tar.gz - aws s3 cp /tmp/pg_binaries.tar.gz s3://${{ secrets.PROD_ARTIFACTS_BUCKET }}/upgrades/postgres/supabase-postgres-${{ steps.process_release_version.outputs.version }}/24.04.tar.gz - aws s3 cp /tmp/pg_binaries.tar.gz s3://${{ secrets.PROD_ARTIFACTS_BUCKET }}/upgrades/postgres/supabase-postgres-${{ steps.process_release_version.outputs.version }}/upgrade_bundle.tar.gz + aws s3 cp /tmp/pg_binaries.tar.gz s3://${{ secrets.PROD_ARTIFACTS_BUCKET }}/upgrades/postgres/supabase-postgres-${{ steps.process_release_version.outputs.version }}${{ steps.arch_vars.outputs.version_suffix }}/20.04.tar.gz + aws s3 cp /tmp/pg_binaries.tar.gz s3://${{ secrets.PROD_ARTIFACTS_BUCKET }}/upgrades/postgres/supabase-postgres-${{ steps.process_release_version.outputs.version }}${{ steps.arch_vars.outputs.version_suffix }}/24.04.tar.gz + aws s3 cp /tmp/pg_binaries.tar.gz s3://${{ secrets.PROD_ARTIFACTS_BUCKET }}/upgrades/postgres/supabase-postgres-${{ steps.process_release_version.outputs.version }}${{ steps.arch_vars.outputs.version_suffix }}/upgrade_bundle.tar.gz - name: Create release uses: softprops/action-gh-release@a06a81a03ee405af7f2048a818ed3f03bbf83c7b # v2.5.0 with: - name: ${{ steps.process_release_version.outputs.version }} - tag_name: ${{ steps.process_release_version.outputs.version }} + name: ${{ steps.process_release_version.outputs.version }}${{ steps.arch_vars.outputs.version_suffix }} + tag_name: ${{ steps.process_release_version.outputs.version }}${{ steps.arch_vars.outputs.version_suffix }} target_commitish: ${{ steps.get_sha.outputs.sha }} - name: Slack Notification on Failure diff --git a/.github/workflows/ami-release-nix.yml b/.github/workflows/ami-release-nix.yml index 728194af84..4249148dca 100644 --- a/.github/workflows/ami-release-nix.yml +++ b/.github/workflows/ami-release-nix.yml @@ -39,9 +39,24 @@ jobs: strategy: matrix: postgres_version: ${{ fromJson(needs.prepare.outputs.postgres_versions) }} - include: - - runner: blacksmith-2vcpu-ubuntu-2404-arm - runs-on: ${{ matrix.runner }} + arch: + - name: arm64 + runner: blacksmith-2vcpu-ubuntu-2404-arm + packer_template: amazon-arm64-nix.pkr.hcl + vars_file: development-arm.vars.pkr.hcl + instance_type: c6g.4xlarge + nix_system: aarch64-linux + ami_name: supabase-postgres + ami_arch_filter: arm64 + - name: amd64 + runner: blacksmith-2vcpu-ubuntu-2404 + packer_template: amazon-amd64-nix.pkr.hcl + vars_file: development-x86.vars.pkr.hcl + instance_type: c6i.4xlarge + nix_system: x86_64-linux + ami_name: supabase-postgres-x86 + ami_arch_filter: x86_64 + runs-on: ${{ matrix.arch.runner }} timeout-minutes: 150 steps: @@ -67,7 +82,7 @@ jobs: - name: Set PostgreSQL version environment variable run: | echo "POSTGRES_MAJOR_VERSION=${{ matrix.postgres_version }}" >> "$GITHUB_ENV" - echo "EXECUTION_ID=${{ github.run_id }}-${{ matrix.postgres_version }}" >> "$GITHUB_ENV" + echo "EXECUTION_ID=${{ github.run_id }}-${{ matrix.postgres_version }}-${{ matrix.arch.name }}" >> "$GITHUB_ENV" - name: Generate common-nix.vars.pkr.hcl run: | @@ -79,9 +94,8 @@ jobs: POSTGRES_MAJOR_VERSION: ${{ env.POSTGRES_MAJOR_VERSION }} run: | GIT_SHA=${{github.sha}} - nix run github:supabase/postgres/${GIT_SHA}#packer -- init amazon-arm64-nix.pkr.hcl - # why is postgresql_major defined here instead of where the _three_ other postgresql_* variables are defined? - nix run github:supabase/postgres/${GIT_SHA}#packer -- build -var "git-head-version=${GIT_SHA}" -var "packer-execution-id=${EXECUTION_ID}" -var-file="development-arm.vars.pkr.hcl" -var-file="common-nix.vars.pkr.hcl" -var "ansible_arguments=-e postgresql_major=${POSTGRES_MAJOR_VERSION}" -var "region=us-east-1" -var 'ami_regions=["us-east-1"]' amazon-arm64-nix.pkr.hcl + nix run github:supabase/postgres/${GIT_SHA}#packer -- init ${{ matrix.arch.packer_template }} + nix run github:supabase/postgres/${GIT_SHA}#packer -- build -var "git-head-version=${GIT_SHA}" -var "packer-execution-id=${EXECUTION_ID}" -var-file="${{ matrix.arch.vars_file }}" -var-file="common-nix.vars.pkr.hcl" -var "ansible_arguments=-e postgresql_major=${POSTGRES_MAJOR_VERSION}" -var "region=us-east-1" -var 'ami_regions=["us-east-1"]' -var "ami_name=${{ matrix.arch.ami_name }}" ${{ matrix.arch.packer_template }} - name: Find stage 1 AMI run: | @@ -98,6 +112,7 @@ jobs: "Name=tag:postgresVersion,Values=${PG_VERSION}-stage1" \ "Name=tag:sourceSha,Values=${GIT_SHA}" \ "Name=state,Values=available" \ + "Name=architecture,Values=${{ matrix.arch.ami_arch_filter }}" \ --query 'Images[0].ImageId' \ --output text) @@ -115,8 +130,7 @@ jobs: run: | GIT_SHA=${{github.sha}} nix run github:supabase/postgres/${GIT_SHA}#packer -- init stage2-nix-psql.pkr.hcl - POSTGRES_MAJOR_VERSION=${{ env.POSTGRES_MAJOR_VERSION }} - nix run github:supabase/postgres/${GIT_SHA}#packer -- build -var "git_sha=${GIT_SHA}" -var "git-head-version=${GIT_SHA}" -var "packer-execution-id=${EXECUTION_ID}" -var "postgres_major_version=${POSTGRES_MAJOR_VERSION}" -var "source_ami=${STAGE1_AMI_ID}" -var-file="development-arm.vars.pkr.hcl" -var-file="common-nix.vars.pkr.hcl" -var "region=us-east-1" stage2-nix-psql.pkr.hcl + nix run github:supabase/postgres/${GIT_SHA}#packer -- build -var "git_sha=${GIT_SHA}" -var "git-head-version=${GIT_SHA}" -var "packer-execution-id=${EXECUTION_ID}" -var "postgres_major_version=${POSTGRES_MAJOR_VERSION}" -var "source_ami=${STAGE1_AMI_ID}" -var-file="${{ matrix.arch.vars_file }}" -var-file="common-nix.vars.pkr.hcl" -var "region=us-east-1" -var "instance_type=${{ matrix.arch.instance_type }}" -var "ami_name=${{ matrix.arch.ami_name }}" stage2-nix-psql.pkr.hcl - name: Grab release version id: process_release_version @@ -125,6 +139,22 @@ jobs: echo "version=$VERSION" >> "$GITHUB_OUTPUT" echo "::notice title=AMI Published::Postgres AMI version: $VERSION" + - name: Set arch-qualified version + id: arch_version + run: | + VERSION="${{ steps.process_release_version.outputs.version }}" + if [ "${{ matrix.arch.name }}" = "amd64" ]; then + { + echo "s3_version=${VERSION}-x86" + echo "release_tag=${VERSION}-x86" + } >> "$GITHUB_OUTPUT" + else + { + echo "s3_version=${VERSION}" + echo "release_tag=${VERSION}" + } >> "$GITHUB_OUTPUT" + fi + - name: Create nix flake revision tarball run: | GIT_SHA=${{github.sha}} @@ -144,16 +174,17 @@ jobs: run: | cd ansible ansible-playbook -i localhost \ - -e "ami_release_version=${{ steps.process_release_version.outputs.version }}" \ + -e "ami_release_version=${{ steps.arch_version.outputs.s3_version }}" \ -e "internal_artifacts_bucket=${{ secrets.ARTIFACTS_BUCKET }}" \ -e "postgres_major_version=${{ matrix.postgres_version }}" \ + -e "arch=${{ matrix.arch.name }}" \ manifest-playbook.yml - name: Upload nix flake revision to s3 staging run: | - aws s3 cp /tmp/pg_binaries.tar.gz s3://${{ secrets.ARTIFACTS_BUCKET }}/upgrades/postgres/supabase-postgres-${{ steps.process_release_version.outputs.version }}/20.04.tar.gz - aws s3 cp /tmp/pg_binaries.tar.gz s3://${{ secrets.ARTIFACTS_BUCKET }}/upgrades/postgres/supabase-postgres-${{ steps.process_release_version.outputs.version }}/24.04.tar.gz - aws s3 cp /tmp/pg_binaries.tar.gz s3://${{ secrets.ARTIFACTS_BUCKET }}/upgrades/postgres/supabase-postgres-${{ steps.process_release_version.outputs.version }}/upgrade_bundle.tar.gz + aws s3 cp /tmp/pg_binaries.tar.gz s3://${{ secrets.ARTIFACTS_BUCKET }}/upgrades/postgres/supabase-postgres-${{ steps.arch_version.outputs.s3_version }}/20.04.tar.gz + aws s3 cp /tmp/pg_binaries.tar.gz s3://${{ secrets.ARTIFACTS_BUCKET }}/upgrades/postgres/supabase-postgres-${{ steps.arch_version.outputs.s3_version }}/24.04.tar.gz + aws s3 cp /tmp/pg_binaries.tar.gz s3://${{ secrets.ARTIFACTS_BUCKET }}/upgrades/postgres/supabase-postgres-${{ steps.arch_version.outputs.s3_version }}/upgrade_bundle.tar.gz - name: configure aws credentials - prod uses: aws-actions/configure-aws-credentials@7474bc4690e29a8392af63c5b98e7449536d5c3a # v4.3.1 @@ -165,16 +196,17 @@ jobs: run: | cd ansible ansible-playbook -i localhost \ - -e "ami_release_version=${{ steps.process_release_version.outputs.version }}" \ + -e "ami_release_version=${{ steps.arch_version.outputs.s3_version }}" \ -e "internal_artifacts_bucket=${{ secrets.PROD_ARTIFACTS_BUCKET }}" \ -e "postgres_major_version=${{ matrix.postgres_version }}" \ + -e "arch=${{ matrix.arch.name }}" \ manifest-playbook.yml - name: Upload nix flake revision to s3 prod run: | - aws s3 cp /tmp/pg_binaries.tar.gz s3://${{ secrets.PROD_ARTIFACTS_BUCKET }}/upgrades/postgres/supabase-postgres-${{ steps.process_release_version.outputs.version }}/20.04.tar.gz - aws s3 cp /tmp/pg_binaries.tar.gz s3://${{ secrets.PROD_ARTIFACTS_BUCKET }}/upgrades/postgres/supabase-postgres-${{ steps.process_release_version.outputs.version }}/24.04.tar.gz - aws s3 cp /tmp/pg_binaries.tar.gz s3://${{ secrets.PROD_ARTIFACTS_BUCKET }}/upgrades/postgres/supabase-postgres-${{ steps.process_release_version.outputs.version }}/upgrade_bundle.tar.gz + aws s3 cp /tmp/pg_binaries.tar.gz s3://${{ secrets.PROD_ARTIFACTS_BUCKET }}/upgrades/postgres/supabase-postgres-${{ steps.arch_version.outputs.s3_version }}/20.04.tar.gz + aws s3 cp /tmp/pg_binaries.tar.gz s3://${{ secrets.PROD_ARTIFACTS_BUCKET }}/upgrades/postgres/supabase-postgres-${{ steps.arch_version.outputs.s3_version }}/24.04.tar.gz + aws s3 cp /tmp/pg_binaries.tar.gz s3://${{ secrets.PROD_ARTIFACTS_BUCKET }}/upgrades/postgres/supabase-postgres-${{ steps.arch_version.outputs.s3_version }}/upgrade_bundle.tar.gz - name: GitHub OIDC Auth uses: aws-actions/configure-aws-credentials@ececac1a45f3b08a01d2dd070d28d111c5fe6722 # v4.1.0 @@ -197,13 +229,13 @@ jobs: VERSION="${{ steps.process_release_version.outputs.version }}" GIT_SHA="${{ github.sha }}" PG_VERSION="${{ matrix.postgres_version }}" - SYSTEM="aarch64-linux" + SYSTEM="${{ matrix.arch.nix_system }}" # Get store path for this build STORE_PATH=$(nix eval --raw ".#psql_${PG_VERSION}/bin.outPath") # Each postgres version gets its own catalog file (no race conditions) - CATALOG_S3="s3://${{ secrets.SHARED_AWS_ARTIFACTS_BUCKET }}/nix-catalog/${GIT_SHA}-psql_${PG_VERSION}.json" + CATALOG_S3="s3://${{ secrets.SHARED_AWS_ARTIFACTS_BUCKET }}/nix-catalog/${GIT_SHA}-psql_${PG_VERSION}-${SYSTEM}.json" # Create catalog JSON for this version jq -n \ @@ -225,12 +257,12 @@ jobs: - name: Create release uses: softprops/action-gh-release@a06a81a03ee405af7f2048a818ed3f03bbf83c7b # v2.5.0 with: - name: ${{ steps.process_release_version.outputs.version }} - tag_name: ${{ steps.process_release_version.outputs.version }} + name: ${{ steps.arch_version.outputs.release_tag }} + tag_name: ${{ steps.arch_version.outputs.release_tag }} target_commitish: ${{github.sha}} - name: Create CLI tag for PG 17 - if: matrix.postgres_version == '17' && github.event_name != 'workflow_dispatch' + if: matrix.postgres_version == '17' && matrix.arch.name == 'arm64' && github.event_name != 'workflow_dispatch' env: GH_TOKEN: ${{ github.token }} run: | @@ -241,6 +273,7 @@ jobs: git push origin "${CLI_TAG}" - name: Trigger pg_upgrade_scripts workflow + if: matrix.arch.name == 'arm64' env: GH_TOKEN: ${{ github.token }} run: | @@ -249,6 +282,7 @@ jobs: -f postgresVersion="${{ steps.process_release_version.outputs.version }}" - name: Trigger pg_upgrade_bin flake version workflow + if: matrix.arch.name == 'arm64' env: GH_TOKEN: ${{ github.token }} run: | diff --git a/amazon-amd64-nix.pkr.hcl b/amazon-amd64-nix.pkr.hcl new file mode 100644 index 0000000000..99136c26c0 --- /dev/null +++ b/amazon-amd64-nix.pkr.hcl @@ -0,0 +1,271 @@ +variable "ami" { + type = string + default = "ubuntu/images/hvm-ssd-gp3/ubuntu-noble-24.04-amd64-server-*" +} + +variable "profile" { + type = string + default = "${env("AWS_PROFILE")}" +} + +variable "ami_name" { + type = string + default = "supabase-postgres" +} + +variable "ami_regions" { + type = list(string) + default = ["ap-southeast-1"] +} + +variable "ansible_arguments" { + type = string + default = "--skip-tags install-postgrest,install-pgbouncer,install-supabase-internal" +} + +variable "region" { + type = string +} + +variable "build-vol" { + type = string + default = "xvdc" +} + +# ccache docker image details +variable "docker_user" { + type = string + default = "" +} + +variable "docker_passwd" { + type = string + default = "" +} + +variable "docker_image" { + type = string + default = "" +} + +variable "docker_image_tag" { + type = string + default = "latest" +} + +locals { + creator = "packer" +} + +variable "postgres-version" { + type = string + default = "" +} + +variable "git-head-version" { + type = string + default = "unknown" +} + +variable "packer-execution-id" { + type = string + default = "unknown" +} + +variable "force-deregister" { + type = bool + default = false +} + +variable "input-hash" { + type = string + default = "" + description = "Content hash of all input sources" +} + +packer { + required_plugins { + amazon = { + source = "github.com/hashicorp/amazon" + version = "~> 1" + } + } +} + +# source block +source "amazon-ebssurrogate" "source" { + profile = "${var.profile}" + ami_name = "${var.ami_name}-${var.postgres-version}-${var.input-hash}-stage-1" + ami_virtualization_type = "hvm" + ami_architecture = "x86_64" + ami_regions = "${var.ami_regions}" + instance_type = "c6i.4xlarge" + region = "${var.region}" + force_deregister = var.force-deregister + + # Increase timeout for instance stop operations to handle large instances + aws_polling { + delay_seconds = 15 + max_attempts = 120 # 120 * 15s = 30 minutes max wait + } + + # Use latest official ubuntu noble ami owned by Canonical. + source_ami_filter { + filters = { + virtualization-type = "hvm" + name = "${var.ami}" + root-device-type = "ebs" + } + owners = [ "099720109477" ] + most_recent = true + } + + ena_support = true + launch_block_device_mappings { + device_name = "/dev/xvdf" + delete_on_termination = true + volume_size = 10 + volume_type = "gp3" + } + + # NOTE: /dev/xvdh is mounted as /data (PostgreSQL data/WAL). The 1 GiB size + # is a minimal default for this AMI; consumers should override this volume + # size at launch. + launch_block_device_mappings { + device_name = "/dev/xvdh" + delete_on_termination = true + volume_size = 1 + volume_type = "gp3" + } + + launch_block_device_mappings { + device_name = "/dev/${var.build-vol}" + delete_on_termination = true + volume_size = 16 + volume_type = "gp2" + omit_from_artifact = true + } + + run_tags = { + creator = "packer" + appType = "postgres" + packerExecutionId = "${var.packer-execution-id}" + } + run_volume_tags = { + creator = "packer" + appType = "postgres" + } + snapshot_tags = { + creator = "packer" + appType = "postgres" + } + tags = { + creator = "packer" + appType = "postgres" + postgresVersion = "${var.postgres-version}-stage1" + sourceSha = "${var.git-head-version}" + inputHash = "${var.input-hash}" + } + + communicator = "ssh" + ssh_pty = true + ssh_username = "ubuntu" + ssh_timeout = "5m" + + ami_root_device { + source_device_name = "/dev/xvdf" + device_name = "/dev/xvda" + delete_on_termination = true + volume_size = 10 + volume_type = "gp2" + } + + associate_public_ip_address = true +} + +# a build block invokes sources and runs provisioning steps on them. +build { + sources = ["source.amazon-ebssurrogate.source"] + + provisioner "file" { + source = "ebssurrogate/files/sources.cfg" + destination = "/tmp/sources.list" + } + + provisioner "file" { + source = "ebssurrogate/files/ebsnvme-id" + destination = "/tmp/ebsnvme-id" + } + + provisioner "file" { + source = "ebssurrogate/files/70-ec2-nvme-devices.rules" + destination = "/tmp/70-ec2-nvme-devices.rules" + } + + provisioner "file" { + source = "ebssurrogate/scripts/chroot-bootstrap-nix.sh" + destination = "/tmp/chroot-bootstrap-nix.sh" + } + + provisioner "file" { + source = "ebssurrogate/files/cloud.cfg" + destination = "/tmp/cloud.cfg" + } + + provisioner "file" { + source = "ebssurrogate/files/vector.timer" + destination = "/tmp/vector.timer" + } + + provisioner "file" { + source = "ebssurrogate/files/apparmor_profiles" + destination = "/tmp" + } + + provisioner "file" { + source = "migrations" + destination = "/tmp" + } + + # Copy ansible playbook + provisioner "shell" { + inline = ["mkdir /tmp/ansible-playbook"] + } + + provisioner "file" { + source = "ansible" + destination = "/tmp/ansible-playbook" + } + + provisioner "file" { + source = "scripts" + destination = "/tmp/ansible-playbook" + } + + provisioner "file" { + source = "ansible/vars.yml" + destination = "/tmp/ansible-playbook/vars.yml" + } + + provisioner "shell" { + environment_vars = [ + "ARGS=${var.ansible_arguments}", + "DOCKER_USER=${var.docker_user}", + "DOCKER_PASSWD=${var.docker_passwd}", + "DOCKER_IMAGE=${var.docker_image}", + "DOCKER_IMAGE_TAG=${var.docker_image_tag}", + "POSTGRES_SUPABASE_VERSION=${var.postgres-version}" + ] + use_env_var_file = true + script = "ebssurrogate/scripts/surrogate-bootstrap-nix.sh" + execute_command = "sudo -S sh -c '. {{.EnvVarFile}} && cd /tmp/ansible-playbook && {{.Path}}'" + start_retry_timeout = "5m" + skip_clean = true + } + + provisioner "file" { + source = "/tmp/ansible.log" + destination = "/tmp/ansible.log" + direction = "download" + } +} diff --git a/ansible/manifest-playbook.yml b/ansible/manifest-playbook.yml index ce02c805c1..9e02d06e9c 100644 --- a/ansible/manifest-playbook.yml +++ b/ansible/manifest-playbook.yml @@ -4,6 +4,13 @@ vars_files: - ./vars.yml + vars: + arch: "{{ arch | default('arm64') }}" + postgrest_binary: "{{ 'ubuntu-aarch64' if arch == 'arm64' else 'linux-static-x86-64' }}" + gotrue_arch: "{{ 'arm64' if arch == 'arm64' else 'x86' }}" + gotrue_checksum: "{{ gotrue_arm_release_checksum if arch == 'arm64' else gotrue_x86_release_checksum }}" + postgrest_checksum: "{{ postgrest_arm_release_checksum if arch == 'arm64' else postgrest_x86_release_checksum }}" + tasks: - name: Write out image manifest action: template src=files/manifest.json dest=./image-manifest-{{ ami_release_version }}.json @@ -17,21 +24,21 @@ # currently, we upload gotrue, adminapi, postgrest - name: gotrue - download commit archive get_url: - url: "https://github.com/supabase/gotrue/releases/download/v{{ gotrue_release }}/auth-v{{ gotrue_release }}-arm64.tar.gz" - dest: /tmp/auth-v{{ gotrue_release }}-arm64.tar.gz - checksum: "{{ gotrue_release_checksum }}" + url: "https://github.com/supabase/gotrue/releases/download/v{{ gotrue_release }}/auth-v{{ gotrue_release }}-{{ gotrue_arch }}.tar.gz" + dest: /tmp/auth-v{{ gotrue_release }}-{{ gotrue_arch }}.tar.gz + checksum: "{{ gotrue_checksum }}" timeout: 60 - name: PostgREST - download ubuntu binary archive (arm) get_url: - url: "https://github.com/PostgREST/postgrest/releases/download/v{{ postgrest_release }}/postgrest-v{{ postgrest_release }}-ubuntu-aarch64.tar.xz" - dest: /tmp/postgrest-{{ postgrest_release }}-arm64.tar.xz - checksum: "{{ postgrest_arm_release_checksum }}" + url: "https://github.com/PostgREST/postgrest/releases/download/v{{ postgrest_release }}/postgrest-v{{ postgrest_release }}-{{ postgrest_binary }}.tar.xz" + dest: /tmp/postgrest-{{ postgrest_release }}-{{ arch }}.tar.xz + checksum: "{{ postgrest_checksum }}" timeout: 60 - name: Download adminapi archive get_url: - url: "https://supabase-public-artifacts-bucket.s3.amazonaws.com/supabase-admin-api/v{{ adminapi_release }}/supabase-admin-api_{{ adminapi_release }}_linux_arm64.tar.gz" + url: "https://supabase-public-artifacts-bucket.s3.amazonaws.com/supabase-admin-api/v{{ adminapi_release }}/supabase-admin-api_{{ adminapi_release }}_linux_{{ arch }}.tar.gz" dest: "/tmp/adminapi.tar.gz" timeout: 90 @@ -43,11 +50,11 @@ - name: adminapi - pack archive shell: | - cd /tmp && tar -cJf supabase-admin-api-{{ adminapi_release }}-arm64.tar.xz supabase-admin-api + cd /tmp && tar -cJf supabase-admin-api-{{ adminapi_release }}-{{ arch }}.tar.xz supabase-admin-api - name: Download admin-mgr archive get_url: - url: "https://supabase-public-artifacts-bucket.s3.amazonaws.com/admin-mgr/v{{ adminmgr_release }}/admin-mgr_{{ adminmgr_release }}_linux_arm64.tar.gz" + url: "https://supabase-public-artifacts-bucket.s3.amazonaws.com/admin-mgr/v{{ adminmgr_release }}/admin-mgr_{{ adminmgr_release }}_linux_{{ arch }}.tar.gz" dest: "/tmp/admin-mgr.tar.gz" timeout: 90 @@ -59,11 +66,11 @@ - name: admin-mgr - pack archive shell: | - cd /tmp && tar -cJf admin-mgr-{{ adminmgr_release }}-arm64.tar.xz admin-mgr + cd /tmp && tar -cJf admin-mgr-{{ adminmgr_release }}-{{ arch }}.tar.xz admin-mgr - name: Download supabase-admin-agent archive get_url: - url: "https://supabase-public-artifacts-bucket.s3.amazonaws.com/supabase-admin-agent/v{{ supabase_admin_agent_release }}/supabase-admin-agent-{{ supabase_admin_agent_release }}-linux-arm64.tar.gz" + url: "https://supabase-public-artifacts-bucket.s3.amazonaws.com/supabase-admin-agent/v{{ supabase_admin_agent_release }}/supabase-admin-agent-{{ supabase_admin_agent_release }}-linux-{{ arch }}.tar.gz" dest: "/tmp/supabase-admin-agent.tar.gz" timeout: 90 @@ -75,19 +82,19 @@ - name: supabase-admin-agent - pack archive shell: | - cd /tmp && tar -cJf supabase-admin-agent-{{ supabase_admin_agent_release }}-arm64.tar.xz supabase-admin-agent-{{ supabase_admin_agent_release }}-linux-arm64 + cd /tmp && tar -cJf supabase-admin-agent-{{ supabase_admin_agent_release }}-{{ arch }}.tar.xz supabase-admin-agent-{{ supabase_admin_agent_release }}-linux-{{ arch }} - name: upload archives shell: | aws s3 cp /tmp/{{ item.file }} s3://{{ internal_artifacts_bucket }}/upgrades/{{ item.service }}/{{ item.file }} with_items: - service: gotrue - file: auth-v{{ gotrue_release }}-arm64.tar.gz + file: auth-v{{ gotrue_release }}-{{ gotrue_arch }}.tar.gz - service: postgrest - file: postgrest-{{ postgrest_release }}-arm64.tar.xz + file: postgrest-{{ postgrest_release }}-{{ arch }}.tar.xz - service: supabase-admin-api - file: supabase-admin-api-{{ adminapi_release }}-arm64.tar.xz + file: supabase-admin-api-{{ adminapi_release }}-{{ arch }}.tar.xz - service: admin-mgr - file: admin-mgr-{{ adminmgr_release }}-arm64.tar.xz + file: admin-mgr-{{ adminmgr_release }}-{{ arch }}.tar.xz - service: supabase-admin-agent - file: supabase-admin-agent-{{ supabase_admin_agent_release }}-arm64.tar.xz + file: supabase-admin-agent-{{ supabase_admin_agent_release }}-{{ arch }}.tar.xz diff --git a/ansible/playbook.yml b/ansible/playbook.yml index fbc3d5d81b..9a868e22e9 100644 --- a/ansible/playbook.yml +++ b/ansible/playbook.yml @@ -233,7 +233,7 @@ become: yes shell: | /bin/bash /tmp/ansible-playbook/ansible/files/supascan_ami.sh /tmp/ansible-playbook/audit-specs/baselines/ami-build - when: stage2_nix and qemu_mode is not defined + when: stage2_nix and qemu_mode is not defined and ansible_architecture != "x86_64" - name: Remove supascan after validation become: yes diff --git a/ansible/tasks/internal/admin-api.yml b/ansible/tasks/internal/admin-api.yml index 1770433e40..0c8e4020e6 100644 --- a/ansible/tasks/internal/admin-api.yml +++ b/ansible/tasks/internal/admin-api.yml @@ -27,9 +27,9 @@ shell: | chmod g+w /etc -- name: Setting arch (x86) +- name: Setting arch (amd64) set_fact: - arch: "x86" + arch: "amd64" when: platform == "amd64" - name: Setting arch (arm) diff --git a/ansible/tasks/internal/supabase-admin-agent.yml b/ansible/tasks/internal/supabase-admin-agent.yml index 0dfc4427ae..9781497f0a 100644 --- a/ansible/tasks/internal/supabase-admin-agent.yml +++ b/ansible/tasks/internal/supabase-admin-agent.yml @@ -31,9 +31,9 @@ dest: /etc/sudoers.d/supabase-admin-agent mode: "0440" -- name: Setting arch (x86) +- name: Setting arch (amd64) set_fact: - arch: "x86" + arch: "amd64" when: platform == "amd64" - name: Setting arch (arm) diff --git a/ansible/tasks/setup-envoy.yml b/ansible/tasks/setup-envoy.yml index 1552393e25..2d32139cc7 100644 --- a/ansible/tasks/setup-envoy.yml +++ b/ansible/tasks/setup-envoy.yml @@ -5,13 +5,13 @@ - name: Envoy - download binary ansible.builtin.get_url: - checksum: "{{ envoy_release_checksum }}" + checksum: "{{ envoy_arm_release_checksum if platform == 'arm64' else envoy_x86_release_checksum }}" dest: '/opt/envoy' group: 'envoy' mode: '0700' owner: 'envoy' # yamllint disable-line rule:line-length - url: "https://github.com/envoyproxy/envoy/releases/download/v{{ envoy_release }}/envoy-{{ envoy_release }}-linux-aarch_64" + url: "https://github.com/envoyproxy/envoy/releases/download/v{{ envoy_release }}/envoy-{{ envoy_release }}-linux-{{ 'aarch_64' if platform == 'arm64' else 'x86_64' }}" - name: Envoy - download hot restarter script ansible.builtin.get_url: diff --git a/ansible/tasks/setup-gotrue.yml b/ansible/tasks/setup-gotrue.yml index 70bbbf85f5..20b599ccc4 100644 --- a/ansible/tasks/setup-gotrue.yml +++ b/ansible/tasks/setup-gotrue.yml @@ -20,7 +20,7 @@ - name: gotrue - download commit archive ansible.builtin.get_url: - checksum: "{{ gotrue_release_checksum }}" + checksum: "{{ gotrue_arm_release_checksum if platform == 'arm64' else gotrue_x86_release_checksum }}" dest: '/tmp/gotrue.tar.gz' url: "https://github.com/supabase/gotrue/releases/download/v{{ gotrue_release }}/auth-v{{ gotrue_release }}-{{ arch }}.tar.gz" diff --git a/ansible/tasks/setup-kong.yml b/ansible/tasks/setup-kong.yml index 22a34897b7..4dfb9d405b 100644 --- a/ansible/tasks/setup-kong.yml +++ b/ansible/tasks/setup-kong.yml @@ -14,9 +14,9 @@ - name: Kong - download deb package get_url: - checksum: "{{ kong_deb_checksum }}" + checksum: "{{ kong_deb_checksum[platform] }}" dest: '/tmp/kong.deb' - url: "https://packages.konghq.com/public/gateway-28/deb/ubuntu/pool/{{ kong_release_target }}/main/k/ko/kong_2.8.1/{{ kong_deb }}" + url: "https://packages.konghq.com/public/gateway-28/deb/ubuntu/pool/{{ kong_release_target }}/main/k/ko/kong_2.8.1/{{ kong_deb[platform] }}" - name: Kong - deb installation ansible.builtin.apt: diff --git a/ansible/tasks/setup-postgrest.yml b/ansible/tasks/setup-postgrest.yml index 13cea264b9..7e5d53839f 100644 --- a/ansible/tasks/setup-postgrest.yml +++ b/ansible/tasks/setup-postgrest.yml @@ -9,6 +9,12 @@ force: true mode: '0644' url: 'https://www.postgresql.org/media/keys/ACCC4CF8.asc' + timeout: 60 + validate_certs: true + register: pgdg_key_download + retries: 6 + delay: 10 + until: pgdg_key_download is succeeded - name: PostgREST - add Postgres PPA main ansible.builtin.apt_repository: @@ -51,7 +57,7 @@ - name: PostgREST - download ubuntu binary archive (arm) ansible.builtin.get_url: - checksum: "{{ postgrest_arm_release_checksum }}" + checksum: "{{ postgrest_arm_release_checksum if platform == 'arm64' else postgrest_x86_release_checksum }}" dest: '/tmp/postgrest.tar.xz' timeout: 60 url: "https://github.com/PostgREST/postgrest/releases/download/v{{ postgrest_release }}/postgrest-v{{ postgrest_release }}-{{ download_binary }}.tar.xz" diff --git a/ansible/vars.yml b/ansible/vars.yml index 1b2f62a4e7..c304b57b38 100644 --- a/ansible/vars.yml +++ b/ansible/vars.yml @@ -10,9 +10,9 @@ postgres_major: # Full version strings for each major version postgres_release: - postgresorioledb-17: "17.6.0.064-orioledb" - postgres17: "17.6.1.107" - postgres15: "15.14.1.107" + postgresorioledb-17: "17.6.0.064-orioledb-x-5" + postgres17: "17.6.1.107-x-5" + postgres15: "15.14.1.107-x-5" # Non Postgres Extensions pgbouncer_release: 1.25.1 @@ -27,6 +27,8 @@ postgrest_x86_release_checksum: sha256:ab5cc7e974d4940447991804588cfb8b3f7b2c57b gotrue_release: 2.188.1 gotrue_release_checksum: sha1:236e8c7bb93e1246b3ff31dbda0fbebe6c3114ca +gotrue_arm_release_checksum: sha1:236e8c7bb93e1246b3ff31dbda0fbebe6c3114ca +gotrue_x86_release_checksum: sha1:b7a6d2c3cb32358710db919f1178569ec19590f0 aws_cli_release: 2.23.11 @@ -38,12 +40,17 @@ golang_version_checksum: amd64: sha256:9ebfcab26801fa4cf0627c6439db7a4da4d3c6766142a3dd83508240e4f21031 envoy_release: 1.28.0 -envoy_release_checksum: sha1:b0a06e9cfb170f1993f369beaa5aa9d7ec679ce5 +envoy_arm_release_checksum: sha256:eb930e32ab5555643e09d11d490e392d0a790c5a80eb0b0ebacb1046bdbb114d +envoy_x86_release_checksum: sha256:2639563ce9bc09b1ee6bd4731760b596c8ed1e474cdd83cc9df9364516e14367 envoy_hot_restarter_release_checksum: sha1:6d43b89d266fb2427a4b51756b649883b0617eda kong_release_target: focal -kong_deb: kong_2.8.1_arm64.deb -kong_deb_checksum: sha1:2086f6ccf8454fe64435252fea4d29d736d7ec61 +kong_deb: + arm64: kong_2.8.1_arm64.deb + amd64: kong_2.8.1_amd64.deb +kong_deb_checksum: + arm64: sha1:2086f6ccf8454fe64435252fea4d29d736d7ec61 + amd64: sha1:7346d558a467f05d9ed63675b59f974300647e9f nginx_release: 1.22.0 nginx_release_checksum: sha1:419efb77b80f165666e2ee406ad8ae9b845aba93 diff --git a/development-x86.vars.pkr.hcl b/development-x86.vars.pkr.hcl new file mode 100644 index 0000000000..9167010cd5 --- /dev/null +++ b/development-x86.vars.pkr.hcl @@ -0,0 +1,5 @@ +arch = "amd64" +ami_regions = ["ap-southeast-1"] +environment = "dev" +instance-type = "c6i.4xlarge" +region = "ap-southeast-1" diff --git a/ebssurrogate/scripts/chroot-bootstrap-nix.sh b/ebssurrogate/scripts/chroot-bootstrap-nix.sh index bb9da1b87f..6447636600 100755 --- a/ebssurrogate/scripts/chroot-bootstrap-nix.sh +++ b/ebssurrogate/scripts/chroot-bootstrap-nix.sh @@ -250,6 +250,11 @@ function update_install_packages { echo "FATAL: Failed to install arm64 boot packages" exit 1 fi + else + if ! apt_install_with_fallback $APT_OPTIONS --yes install initramfs-tools; then + echo "FATAL: Failed to install amd64 boot packages" + exit 1 + fi fi } @@ -308,7 +313,7 @@ function setup_apparmor { cp -rv /tmp/apparmor_profiles/* /etc/apparmor.d/ } -function setup_grub_conf_arm64 { +function setup_grub_conf { cat << EOF > /etc/default/grub GRUB_DEFAULT=0 GRUB_TIMEOUT=0 @@ -320,12 +325,12 @@ EOF # Install GRUB function install_configure_grub { + setup_grub_conf if [ "${ARCH}" = "arm64" ]; then if ! apt_install_with_fallback $APT_OPTIONS --yes install cloud-guest-utils fdisk grub-efi-arm64 efibootmgr; then echo "FATAL: Failed to install grub packages for arm64" exit 1 fi - setup_grub_conf_arm64 rm -rf /etc/grub.d/30_os-prober sleep 1 fi diff --git a/ebssurrogate/scripts/surrogate-bootstrap-nix.sh b/ebssurrogate/scripts/surrogate-bootstrap-nix.sh index ea81bbfd45..564288dce3 100755 --- a/ebssurrogate/scripts/surrogate-bootstrap-nix.sh +++ b/ebssurrogate/scripts/surrogate-bootstrap-nix.sh @@ -226,13 +226,23 @@ function pull_docker { # Create fstab function create_fstab { FMT="%-42s %-11s %-5s %-17s %-5s %s" -cat > "/mnt/etc/fstab" << EOF -$(printf "${FMT}" "# DEVICE UUID" "MOUNTPOINT" "TYPE" "OPTIONS" "DUMP" "FSCK") -$(findmnt -no SOURCE /mnt | xargs blkid -o export | awk -v FMT="${FMT}" '/^UUID=/ { printf(FMT, $0, "/", "ext4", "defaults,discard", "0", "1" ) }') -$(findmnt -no SOURCE /mnt/boot/efi | xargs blkid -o export | awk -v FMT="${FMT}" '/^UUID=/ { printf(FMT, $0, "/boot/efi", "vfat", "umask=0077", "0", "1" ) }') -$(findmnt -no SOURCE /mnt/data | xargs blkid -o export | awk -v FMT="${FMT}" '/^UUID=/ { printf(FMT, $0, "/data", "ext4", "defaults,discard", "0", "2" ) }') -$(printf "$FMT" "/swapfile" "none" "swap" "sw" "0" "0") -EOF + + local ROOT_LINE=$(findmnt -no SOURCE /mnt | xargs blkid -o export | awk -v FMT="${FMT}" '/^UUID=/ { printf(FMT, $0, "/", "ext4", "defaults,discard", "0", "1" ) }') + local DATA_LINE=$(findmnt -no SOURCE /mnt/data | xargs blkid -o export | awk -v FMT="${FMT}" '/^UUID=/ { printf(FMT, $0, "/data", "ext4", "defaults,discard", "0", "2" ) }') + local SWAP_LINE=$(printf "$FMT" "/swapfile" "none" "swap" "sw" "0" "0") + + local EFI_LINE="" + if [ "${ARCH}" = "arm64" ]; then + EFI_LINE=$(findmnt -no SOURCE /mnt/boot/efi | xargs blkid -o export | awk -v FMT="${FMT}" '/^UUID=/ { printf(FMT, $0, "/boot/efi", "vfat", "umask=0077", "0", "1" ) }') + fi + + { + printf "${FMT}\n" "# DEVICE UUID" "MOUNTPOINT" "TYPE" "OPTIONS" "DUMP" "FSCK" + echo "${ROOT_LINE}" + [ -n "${EFI_LINE}" ] && echo "${EFI_LINE}" + echo "${DATA_LINE}" + echo "${SWAP_LINE}" + } > "/mnt/etc/fstab" unset FMT } @@ -247,9 +257,7 @@ function setup_chroot_environment { sed -i "s/REGION/${REGION}/g" /tmp/sources.list cp /tmp/sources.list /mnt/etc/apt/sources.list - if [ "${ARCH}" = "arm64" ]; then - create_fstab - fi + create_fstab # Create mount points and mount the filesystem mkdir -p /mnt/{dev,proc,sys} diff --git a/stage2-nix-psql.pkr.hcl b/stage2-nix-psql.pkr.hcl index 032dd71e52..58e60a2490 100644 --- a/stage2-nix-psql.pkr.hcl +++ b/stage2-nix-psql.pkr.hcl @@ -37,6 +37,11 @@ variable "source_ami" { description = "Source AMI ID from stage 1" } +variable "instance_type" { + type = string + default = "c6g.4xlarge" +} + packer { required_plugins { amazon = { @@ -48,7 +53,7 @@ packer { source "amazon-ebs" "ubuntu" { ami_name = "${var.ami_name}-${var.postgres-version}" - instance_type = "c6g.4xlarge" + instance_type = var.instance_type region = "${var.region}" source_ami = "${var.source_ami}"