None of the approaches above work on a CI/CD pipeline, in my case Azure GitHub Actions. The fundamental problem is that the build executes in the cloud and doesn't have access to production environment variables. Normally in Azure, you put sensitive env variables in the Environment section of the Web App config, but this simply doesn't work for a NextJS app because the environment variables are bound at build time. So you need to provide the sensitive environment variables (API keys and so on) to the build process of the pipeline. You could of course check in your env.production file, but this completely defeats security. If your sensitive env variables are in the code base they are, by definition, no longer sensitive.
The way to do this is to add the env variables to the build script. So for my GitHub actions it looks like this...
- name: npm install, build, and test
run: |
npm install
npm run build --if-present
npm run test --if-present
env:
NEXT_PUBLIC_SECRET_API_KEY: abc-xxxxxxxxxxx
But wait! The GitHub action script is checked into the code repository!
Indeed. This is not good enough. So take this the final mile we need to use GitHub secrets. So create a production environment for the repo and add the API key to it. Now the build script looks like this...
jobs:
build:
runs-on: ubuntu-latest
environment: production # add this to select the environment
permissions:
contents: read #This is required for actions/checkout
steps:
- uses: actions/checkout@v4
- name: Set up Node.js version
uses: actions/setup-node@v3
with:
node-version: '20.x'
- name: npm install, build, and test
run: |
npm install
npm run build --if-present
npm run test --if-present
env:
NEXT_PUBLIC_SECRET_API_KEY: ${{ secrets.NEXT_PUBLIC_SECRET_API_KEY }}
Now you are fully protected and your production API key will be available in production.
.envfile at the same level aspackage.json? Not quite sure what else can help.