Deploying Next Js website on VPS using build from GitHub Actions
โ 2 years ago | ๐ 7 min read
In this article we build our Next Js app using Github Actions and then use the build files from github actions to deploy our app in our own VPS (Virtual Private Server). Also, since we are using GitHub actions we can trigger builds on activities on our repositories like Pull, Push, Tags etc.
When our Next Js app gets large it becomes resource intensive (specially on memory) to build and sometimes Operating System may kill the build process. However, running the production build is not so much memory intensive. So, we want to use GitHub actions for build process and want to host the files built for production in our own Linux Server.
If the memory in our VPS starts getting insufficient memory then we may have following alternative approaches instead of this one.
- Increasing Memory: This obviously comes with a cost.
- Building locally: In this approach you may have to push your build files to Version Control which may not be desirable.
Next Js Part
If you are trying this from scratch you can build a new Next Js app following this link. Either existing or new app, it must build using command npm run build
.
VPS Part
We need to setup few things for first time in VPS in order for things to work when we setup our CI/CD process
- First make sure that node and npm are installed in our system
- pm2 is a node js based tool for running things in background. In this tutorial we are using pm2 for running our Next Js server.
- Clone our app in your server using
git clone
- Now we need to start our next server to build and serve our Next Js app using commands
npm install npm run build pm2 start npm --name app-name -- start
Replace app-name with your own desired name. This should start our Next Js server at port 3000(if using default port) which we can verify using
curl localhost:3000
It should spit out HTML of our page.
If you are unable to build due to low memory (which is the point of this tutorial) at this early stage also then you can just skip above commands and run the last pm2 command after we setup GitHub actions to build and sync the build files.
GitHub Actions part
We now create a YAML file in our project at path .github/workflows/deploy.yml
. Lets look at whole deployment file then break it down to understand what's going on.
name: Deploy Next App on: push: branches: [main] jobs: build: runs-on: ubuntu-latest strategy: matrix: node-version: [16.x] env: SSH_KEY: ${{secrets.SSH_KEY}} steps: - uses: actions/checkout@master - name: Use Node.js ${{ matrix.node-version }} uses: actions/setup-node@v2 with: node-version: ${{ matrix.node-version }} cache: "npm" - run: npm i - run: npm run build - run: mkdir ~/.ssh - run: echo "$SSH_KEY" >> ~/.ssh/github-action - run: chmod 400 ~/.ssh/github-action - run: echo -e "Host vps\n\tUser root\n\tHostname 11.000.000.111\n\tIdentityFile ~/.ssh/github-action\n\tStrictHostKeyChecking No" >> ~/.ssh/config - run: rsync -re ssh ./.next/ vps:/home/root/app-name/.next - run: ssh vps "pm2 restart app-name"
Defining name and trigger
name: Deploy Next App on: push: branches: [main]
here we are giving name to our deployment app and triggering it on each push on main branch. Second lets setup our build enviroment
build: runs-on: ubuntu-latest strategy: matrix: node-version: [16.x] env: SSH_KEY: ${{secrets.SSH_KEY}}
Here, we are defining our build host environment with ubuntu as our Host OS and node version 16. Also, we are setting up SSH_KEY environment variable. We are using GitHub Secrets to provide value for SSH_KEY environment variable. To know more about GitHub secrets you can visit here.
Also, how to get value for SSH_KEY secret?
We can use ssh-keygen
command in terminal(or in GitBash in case of Windows) and give filename as github-actions. After this we should have two files named github-actions
as private key and github-actions.pub
as public key. Now to make sure that our github-actions instance will have permission to sent build files to our server we paste contents of private file to secrets of repository in GitHub with name SSH_KEY
. The content of public key goes to list of authorized keys in the server usually in file ~/.ssh/authorized_keys
with this done lets move to the build part
- uses: actions/checkout@master - name: Use Node.js ${{ matrix.node-version }} uses: actions/setup-node@v2 with: node-version: ${{ matrix.node-version }} cache: "npm" - run: npm i - run: npm run build
here we are just setting up node and then run npm commands for build. Finally to deploying
- run: mkdir ~/.ssh - run: echo "$SSH_KEY" >> ~/.ssh/github-action - run: chmod 400 ~/.ssh/github-action - run: echo -e "Host vps\n\tUser root\n\tHostname 11.000.000.111\n\tIdentityFile ~/.ssh/github-action\n\tStrictHostKeyChecking No" >> ~/.ssh/config - run: rsync -re ssh ./.next/ vps:/home/root/app-name/.next - run: ssh vps "pm2 restart app-name"
in first three line we put our private key in place with appropriate permissions. then we add entry for host in config file. You have to replace root
with your username and 11.000.000.11
with your own host name. After the ssh setup in place we use rsync utility to sync our .next folder to our app directory in our server. At last, we need to restart our pm2 instance in our server to reflect our changes. This command may not work if the instance is not rinning yet and you may have to start it with pm2 start npm --name app-name -- start
We have successfully deployed our Next js site using GitHub Actions for the build. Our website should be up and running at localhost:3000
and should update on push to main
branch.
Share this on