Let's deploy a static Next.js app to an S3 Bucket. I will use Yandex Object Storage (an S3-compatible service by Yandex). But it could be any S3 service and any "static" web app (Vite React, bare HTML, etc.); the process will be very similar.
Create Next.js App
bun create next-app
Check everything works as expected by running the dev server:
bun run dev
Now we need to change the next.config.ts to:
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
/* config options here */
// cacheComponents: true,
// partialPrefetching: true,
output: 'export',
distDir: 'dist',
trailingSlash: true
};
export default nextConfig;
We enabled the static export by setting output: 'export'. Also, the output folder was changed to dist (instead of out by default). We also need trailingSlash: true to make the Next.js routes work without the server (change links from /me -> /me/ and emit /me.html -> /me/index.html). Please see the docs for more details.
Let's build the app:
bun run build
The dist folder should appear.
Yandex Cloud Console
Open the Yandex Cloud Console.
Go to the Object Storage.
Create a new bucket (set Read objects -> For all).
Click the bucket you created. Go to Settings -> Website -> turn on Hosting. Set the Home page and Error page values and click Save.
Now our bucket is ready. 🎉
Deployment Script
Let's write a script to automate our deployment process. First, to be able to upload files to the bucket, we need a static key.
Create a Service Account and Assign Roles
- Navigate to Identity and Access Management -> Service accounts.
- Click
Create service account, name it (for example, s3-copy-sa), and clickCreate. - Assign the
storage.editorrole to the service account so it can manage and upload objects to your bucket.
Create the Static Access Key
- In the Service accounts list, select your newly created service account.
- In the top panel, click
Create new keyand selectCreate static access key. - Add a description (optional) and click
Create. - Important: Copy and save the Key ID and the Secret Key immediately. You will not be able to view the secret key again once you close the window.
Create the secrets/.env.deploy file:
export BUCKET_NAME=your-bucket-name
export AWS_ACCESS_KEY_ID=your-access-key-id
export AWS_SECRET_ACCESS_KEY=your-access-key
export AWS_DEFAULT_REGION=ru-central1
export AWS_ENDPOINT_URL=https://storage.yandexcloud.net/
Add secrets/* to .gitignore so your secrets will never be committed to your git repository.
Create Script
Create the scripts/deploy.sh file:
source ./secrets/.env.deploy
dist_folder="dist"
is_dist_exists=0
if [ -d $dist_folder ]; then
is_dist_exists=1
fi
should_rebuild=1
if [ $is_dist_exists -ne 0 ]; then
echo ""
read -p " 🚧 The \"$dist_folder\" (build) folder already exists. Rebuild the project? (y/n): " confirm
if [ "$confirm" == "n" ]; then
should_rebuild=0
fi
fi
if [ $should_rebuild == 1 ]; then
echo ""
echo " 🏗️ building..."
echo ""
bun run build
build_status=$?
else
build_status=0
fi
if [ $build_status -ne 0 ]; then
echo ""
echo " 🚨 Build failed!"
echo ""
exit $build_status
fi
echo ""
read -p " 🛳️ Deploy to production? (y/n): " confirm
if [ "$confirm" != "y" ]; then
echo " 🚫 Deploy canceled."
echo ""
exit 1
fi
echo ""
echo " ☕"
echo ""
echo ""
echo " Backup old files..."
echo ""
(aws s3 --recursive mv s3://$BUCKET_NAME/ "s3://$BUCKET_NAME.backup/$(date +%Y-%m-%d_%H-%M-%S)/")
echo ""
echo "Copying new files..."
echo ""
(aws s3 --recursive cp $dist_folder s3://$BUCKET_NAME/)
unset BUCKET_NAME
unset AWS_ACCESS_KEY_ID
unset AWS_SECRET_ACCESS_KEY
unset AWS_DEFAULT_REGION
unset AWS_ENDPOINT_URL
echo ""
echo " 🚀 Done!"
echo ""
This script will check if the dist folder exists. Ask whether we need to rebuild the project. Back up the old deployment to the BACKET_NAME.backup bucket. And upload the current build to the BUCKET_NAME bucket.
Please create the BUCKET_NAME.backup bucket. For example, if your bucket name is static-app, then create the static-app.backup bucket.
Also, install the aws-cli command-line tool. We will need it to manipulate our buckets. See the docs for more info.
curl -fsSL https://awscli.amazonaws.com/v2/install.sh | bash
Make it Live
Let's allow our script to be executed:
chmod +x scripts/deploy.sh
And now we are ready to run it:
./scripts/deploy.sh
After the script finishes, we should see our build files inside the bucket.
Go to the Settings tab -> Website and click the Link (https://your-bucket-name.website.yandexcloud.net).
Congratulations, the app is live now! 🥳
Credits
Photo by Sixteen Miles Out on Unsplash.
Top comments (0)