Hey there! Ready to self-host your Next.js app with Kamal 2.4, AWS ECR, and GitHub Actions? You’re in the right spot! This guide will walk you through everything step by step.
Alright, let’s dive in!
Why Use Kamal for Deployment?
Why bother with Kamal? Simple – it makes life easier and deployments smoother.
- Easy Config: Kamal's YAML-based config is clean and easy to manage.
- Docker Power: Since Kamal works with Docker, you get consistent builds everywhere.
- No Downtime: Rolling deployments mean no more late-night emergency restarts.
- Health Checks: Kamal keeps tabs on your app’s health 24/7.
- Multi-Env: Easily manage staging and production setups.
What You Need Before Starting
Let’s make sure you’re all set before we start:
- AWS account + CLI configured
- Docker installed (know your way around basic commands)
- Kamal 2.4 or later
- Familiarity with GitHub Actions
- A Next.js app ready to rock
Project Structure Breakdown
Here’s a quick peek at how your project should look:
project-root/
|-- .kamal/ # Kamal config
| |-- deploy.yml # Deployment settings
| |-- secrets # Secrets storage
|-- .github/workflows/ # GitHub Actions workflows
| |-- release-deploy.yml # Auto-deployment script
|-- Dockerfile # Docker build instructions
|-- package.json # Dependencies
|-- yarn.lock # Lock file
|-- .env # Local env variables
|-- public/ # Static assets
|-- .next/ # Compiled Next.js build
Example deploy.yml
(Kamal Configuration)
defaults:
service: web-app
image: example/web-app
servers:
web:
- 192.168.1.1
ssh:
user: ubuntu
keys: ["~/.ssh/example-key.pem"]
proxy:
ssl: false
app_port: 3000
host: stagingapp.example.io
healthcheck:
path: /
interval: 3
timeout: 30
registry:
server: 123456789012.dkr.ecr.us-west-1.amazonaws.com
username: AWS
password: <%= %x(aws ecr get-login-password) %>
builder:
arch: amd64
context: .
env:
clear:
NEXT_PUBLIC_APP_BACKEND_URL: https://staging.api.example.io
NEXT_PUBLIC_APP_PUBLIC_IP_API: https://pro.ip-api.com/json/?key=dummykey
-
service
: App name. -
servers
: IP of the server you’re deploying to. -
ssh
: How Kamal connects to your server. -
proxy
: Handles routing and health checks. -
registry
: Stores your Docker images in AWS ECR. -
env
: Environment variables.
Building the Dockerfile
Here’s a lean Dockerfile for production-ready Next.js apps:
FROM node:lts-bookworm-slim AS base
FROM base AS deps
WORKDIR /app
COPY package.json yarn.lock ./
RUN yarn install --frozen-lockfile
ARG NEXT_PUBLIC_APP_BACKEND_URL
ARG NEXT_PUBLIC_APP_PUBLIC_IP_API
ENV NEXT_PUBLIC_APP_BACKEND_URL=$NEXT_PUBLIC_APP_BACKEND_URL
ENV NEXT_PUBLIC_APP_PUBLIC_IP_API=$NEXT_PUBLIC_APP_PUBLIC_IP_API
COPY . .
RUN yarn run build
FROM base AS release
WORKDIR /app
ENV NEXT_TELEMETRY_DISABLED=1
COPY --from=deps /app/node_modules ./node_modules
COPY --from=deps /app/package.json ./package.json
COPY --from=deps /app/.next ./.next
COPY --from=deps /app/public ./public
EXPOSE 3000
CMD ["yarn", "start"]
Automating with GitHub Actions
Time to make deployments automatic! Here’s a GitHub Actions workflow you can use:
name: Release Deploy
on:
release:
types: [published]
permissions:
contents: read
packages: write
id-token: write
env:
ECR_REPOSITORY: example/web-app
jobs:
package:
runs-on: ubuntu-latest
steps:
- name: Checkout Repo
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Create .env file
run: |
if [[ "${{ env.LATEST_TAG }}" == *"-beta"* ]]; then
echo "${{ secrets.STAGING_ENV_FILE }}" > .env
else
echo "${{ secrets.PROD_ENV_FILE }}" > .env
fi
- name: Configure AWS
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }}
aws-region: us-west-1
- name: Login to ECR
uses: aws-actions/amazon-ecr-login@v2
- name: Build & Push Docker Image
uses: docker/build-push-action@v5
with:
context: .
file: ./Dockerfile
platforms: linux/amd64
push: true
tags: |
${{ steps.login-ecr.outputs.registry }}/${{ env.ECR_REPOSITORY }}:${{ github.sha }}
Deploying: Staging vs Production
Staging Deployment
- PR to
develop
branch. - Approve and merge.
- Create a beta release.
Production Deployment
- PR from
develop
tomain
. - Test and merge.
- Create a production release.
Managing Environment Variables
Adding new env variables? Follow this:
- Update
.kamal/secrets
with placeholders. - Push and deploy.
- Replace placeholder with actual value.
- Update GitHub Secrets.
- Redeploy.
Wrapping Up
And there you have it! Kamal 2.4 makes self-hosting Next.js apps on AWS ECR super smooth. With GitHub Actions in the mix, deployments are automated and stress-free. Happy deploying!
Top comments (0)