How to Set Up GitHub Actions for Automatic Deployment: A Complete Walkthrough
Imagine pushing code to your main branch and watching your web application go live within seconds, with zero manual steps. That is exactly what GitHub Actions makes possible.
In this guide, we will walk you through configuring GitHub Actions to automatically deploy a web application every time code is pushed. Whether you are deploying to Netlify or your own VPS via SSH, this tutorial has you covered. No prior CI/CD experience required.
What Is GitHub Actions and Why Use It for Deployment?
GitHub Actions is a built-in automation platform provided by GitHub. It lets you define workflows that run in response to events in your repository, such as a push, a pull request, or a scheduled trigger.
Here is why developers love using it for automatic deployment:
- Free for public repositories and generous free minutes for private repos
- Native integration with your GitHub repository (no external service needed)
- Support for environments, secrets, concurrency groups, and protection rules
- A massive marketplace of reusable actions built by the community
- Fine-grained control over when and how deployments happen
Prerequisites
Before we start, make sure you have the following:
- A GitHub account and a repository with your web application code
- A basic understanding of Git (push, pull, branches)
- A deployment target: either a Netlify account or access to a VPS with SSH
- Familiarity with YAML syntax (we will explain the structure as we go)
How GitHub Actions Workflows Work
Every GitHub Actions automation starts with a workflow file. This is a YAML file stored in your repository at:
.github/workflows/your-workflow-name.yml
A workflow file contains the following key components:
| Component | Description |
|---|---|
| name | A human-readable name for the workflow |
| on | The event that triggers the workflow (e.g., push to main) |
| jobs | One or more jobs that run on a virtual machine (runner) |
| steps | Individual commands or actions within a job |
| runs-on | The operating system for the runner (e.g., ubuntu-latest) |
Step-by-Step: Set Up GitHub Actions for Automatic Deployment to Netlify
Netlify is one of the most popular platforms for hosting static sites, JAMstack applications, and frontend projects. Let’s set up a workflow that builds and deploys your site to Netlify on every push to main.
Step 1: Get Your Netlify Credentials
You need two pieces of information from Netlify:
- NETLIFY_AUTH_TOKEN: Go to User Settings > Applications > Personal access tokens in Netlify and generate a new token.
- NETLIFY_SITE_ID: Find this in your Netlify site dashboard under Site configuration > General > Site ID.
Step 2: Store Secrets in Your GitHub Repository
Never hardcode credentials in your workflow files. Instead, store them as GitHub Secrets:
- Go to your repository on GitHub
- Click Settings > Secrets and variables > Actions
- Click New repository secret
- Add
NETLIFY_AUTH_TOKENandNETLIFY_SITE_IDas separate secrets
Step 3: Create the Workflow YAML File
In your repository, create the following file:
.github/workflows/deploy.yml
Paste the following content:
name: Deploy to Netlify
on:
push:
branches:
- main
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install dependencies
run: npm ci
- name: Build the project
run: npm run build
- name: Deploy to Netlify
uses: nwtgck/actions-netlify@v3
with:
publish-dir: './dist'
production-branch: main
production-deploy: true
env:
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }}
Step 4: Push and Watch It Work
- Commit and push the workflow file to your main branch
- Go to the Actions tab in your GitHub repository
- You will see your workflow running automatically
- Once it completes successfully, your site is live on Netlify
That is it. Every future push to main will trigger the same build and deploy process automatically.
Step-by-Step: Set Up GitHub Actions for Automatic Deployment to a VPS via SSH
If you host your application on your own server (a VPS from providers like DigitalOcean, Hetzner, or Linode), you can use GitHub Actions to deploy via SSH.
Step 1: Set Up SSH Key Access
On your local machine, generate an SSH key pair if you do not already have one dedicated to deployments:
ssh-keygen -t ed25519 -C "github-actions-deploy"
Then add the public key to your VPS:
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@your-server-ip
Step 2: Store SSH Credentials as GitHub Secrets
Add the following secrets to your repository (Settings > Secrets and variables > Actions):
- SSH_PRIVATE_KEY: The contents of your private key file
- SSH_HOST: Your server IP address or hostname
- SSH_USER: The username on the server (e.g.,
deployorroot)
Step 3: Create the Workflow YAML File
name: Deploy to VPS
on:
push:
branches:
- main
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install dependencies
run: npm ci
- name: Build the project
run: npm run build
- name: Deploy via SSH
uses: appleboy/ssh-action@v1
with:
host: ${{ secrets.SSH_HOST }}
username: ${{ secrets.SSH_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
cd /var/www/your-app
git pull origin main
npm ci --production
npm run build
pm2 restart your-app
Note: Adjust the script section to match your server setup. If you use Docker, systemd, or another process manager, replace the pm2 restart line accordingly.
Alternative: Upload Build Artifacts via SCP
If you prefer to build on GitHub’s runner and then upload the result, you can use the appleboy/scp-action instead:
- name: Copy files to server
uses: appleboy/scp-action@v1
with:
host: ${{ secrets.SSH_HOST }}
username: ${{ secrets.SSH_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
source: 'dist/*'
target: '/var/www/your-app'
This approach is useful when you do not want to run npm run build on the server itself.
Understanding the Workflow YAML Structure
Let’s break down the key sections of a workflow file so you fully understand what each part does:
Trigger (on)
on:
push:
branches:
- main
This tells GitHub to run the workflow only when code is pushed to the main branch. You can add other triggers like pull_request, schedule, or workflow_dispatch (manual trigger).
Jobs and Runners
jobs:
build-and-deploy:
runs-on: ubuntu-latest
A job runs on a fresh virtual machine. ubuntu-latest is the most common choice, but you can also use windows-latest or macos-latest.
Steps
Steps are executed sequentially within a job. Each step can either:
- Use a pre-built action from the GitHub Marketplace (with the
useskeyword) - Run a shell command directly (with the
runkeyword)
Best Practices for GitHub Actions Deployment Workflows
To keep your deployment pipelines reliable and secure, follow these recommendations:
1. Always Use Secrets for Credentials
Never commit API tokens, SSH keys, or passwords into your repository. Use GitHub Secrets and reference them with ${{ secrets.YOUR_SECRET_NAME }}.
2. Pin Action Versions
Instead of using @latest, pin actions to a specific major version or commit SHA:
uses: actions/checkout@v4
This prevents unexpected breaking changes from affecting your pipeline.
3. Use Concurrency Groups
Prevent multiple deployments from running simultaneously:
concurrency:
group: deployment
cancel-in-progress: true
This ensures that if you push twice in quick succession, the first deployment is cancelled.
4. Add a Build Verification Step
Run tests or linting before the deploy step to catch issues early:
- name: Run tests
run: npm test
5. Use GitHub Environments and Protection Rules
For production deployments, configure environments in your repository settings. You can require manual approvals, limit which branches can deploy, and set environment-specific secrets.
Comparison: Netlify vs. VPS Deployment with GitHub Actions
Not sure which deployment target is right for your project? Here is a quick comparison:
| Feature | Netlify | VPS (SSH) |
|---|---|---|
| Setup complexity | Low | Medium to High |
| Best for | Static sites, JAMstack, SPAs | Full-stack apps, APIs, custom setups |
| Cost | Free tier available | Monthly server cost |
| SSL/CDN included | Yes | Manual setup required |
| Full server control | No | Yes |
| Backend support | Serverless functions only | Full backend support |
Troubleshooting Common Issues
Running into problems? Here are the most common issues developers face when setting up GitHub Actions for deployment:
Workflow Not Triggering
- Make sure the YAML file is in the correct path:
.github/workflows/ - Verify the branch name in the
on.push.branchessection matches exactly (e.g.,mainvs.master) - Check that the YAML syntax is valid (indentation matters)
Build Failing
- Review the logs in the Actions tab for error messages
- Make sure the Node.js version matches what your project requires
- Confirm that
npm ciworks locally with a cleannode_modulesfolder
SSH Connection Refused
- Verify your server allows SSH from external IPs
- Check that the public key is correctly added to
~/.ssh/authorized_keyson the server - Ensure the SSH_PRIVATE_KEY secret includes the full key, including the
BEGINandENDlines
Secrets Not Working
- Secrets are not available in forked repositories by default for security reasons
- Double-check the secret names for typos (they are case-sensitive)
Going Further: Advanced Workflow Ideas
Once you have the basics working, consider enhancing your pipeline:
- Multi-environment deployments: Deploy to staging on push to
developand production on push tomain - Slack or Discord notifications: Get notified when a deployment succeeds or fails
- Docker-based deployments: Build a Docker image, push it to a registry, and pull it on your server
- Database migrations: Run migration scripts as part of the deployment job
- Rollback workflows: Create a manual workflow to redeploy a previous version if something goes wrong
FAQ: GitHub Actions for Automatic Deployment
Can GitHub Actions deploy automatically?
Yes. GitHub Actions can deploy automatically whenever a specific event occurs, such as a push to the main branch, a merged pull request, or even on a scheduled cron job. You define the trigger in the workflow YAML file under the on section.
Is GitHub Actions free to use?
GitHub Actions is free for public repositories. For private repositories, GitHub provides a generous free tier (2,000 minutes per month on the Free plan as of 2026). Paid plans include additional minutes.
How do I set up automatic deployment with Git?
The easiest way is to use GitHub Actions. Create a .github/workflows/deploy.yml file in your repository, define a trigger (such as push to main), add build steps, and include a deployment step using a community action or SSH commands.
Can I deploy to multiple platforms with one workflow?
Yes. You can define multiple jobs within a single workflow file, each targeting a different platform. You can also use conditional logic to deploy to different environments based on the branch.
How do I keep my deployment secrets safe?
Use GitHub Secrets (found in Settings > Secrets and variables > Actions). These are encrypted and only exposed to workflows at runtime. They are never visible in logs.
What if my deployment fails?
GitHub Actions provides detailed logs for every step. Go to the Actions tab, click on the failed run, and inspect the logs. You can also configure notifications to alert you when a workflow fails.
Wrapping Up
Setting up GitHub Actions for automatic deployment is one of the highest-impact improvements you can make to your development workflow. Once configured, you eliminate manual deployment steps, reduce human error, and ship updates faster.
Whether you are deploying a static site to Netlify or a full-stack application to a VPS, the process follows the same pattern: define a trigger, add your build steps, and deploy. Start with the examples in this guide, customize them for your project, and iterate from there.
If you found this guide helpful, explore more developer tutorials and DevOps best practices on pixelatingbits.com.