How to deploy a Next.JS app to S3 with GitLabCI

Cris Pintea

Cris Pintea

This article will provide an example of GitLabCI deploy script for a statically rendered Next.JS App on AWS S3.

Set up your S3 bucket

Head over to AWS, select S3 and then create a bucket. While creating your bucket make sure you deselect “Block all public access”.

After you’ve created your bucket you’ll need to do two things.

Configure the bucket policy

Find the Permissions tab of your S3 bucket, and scroll down to the bucket policy. You can use the following.

    "Version": "2012-10-17",
    "Statement": [
            "Sid": "PublicReadGetObject",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::YOUR_BUCKET_NAME/*"

Configure Static Website Hosting

Head over to the Properties tab of your S3 bucket and find the “Static website hosting” wizard. You’ll get a link here, this will be your website’s public link.

GitLabCI pipeline


You’ll need to create an IAM user with write access to your S3 bucket. Then add the API key and secret for this user as environment variables to your GitLab project, from the settings.

The names for the environment variables should be AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY as shown in the screenshot below.

.gitlab-ci.yml file

Here’s a .gitlab-ci.yml file that works out of the box for projects created using create-next-app.


  - build
  - deploy

  image: node:alpine
  stage: build
  - npm i
  - npm run export
    expire_in: 30 days
      - out
  - master

  image: python:latest
  stage: deploy
  - pip install awscli
  - aws s3 cp ./out/ s3://$S3_BUCKET_NAME/ --recursive --include "*"
  - master


That’s all. Now push to git and watch the pipeline upload all the files to S3 automagically!

If you want to use your own domain, you’ll need to add a Cloudfront layer in front of the S3 bucket, and point your DNS to the Cloudfront endpoint.

If you liked this article, you might like my others too. Subscribe to my newsletter!

Do you know how to handle token refreshing automatically with axios?

Leave a comment

Leave a Reply

Your email address will not be published. Required fields are marked *