Streamline Your Next.js Deployment to DigitalOcean: A Hassle-Free Guide with GitHub Actions
Tags: nextjs, githubactions, devops, github
Published: 2024-07-12 15:41:05

Deploying a Next.js application to DigitalOcean can seem daunting, but with the right steps, you can streamline the process and avoid common pitfalls. Follow this comprehensive guide to set up and automate your deployment using GitHub Actions.

### Step-by-Step Deployment

#### 1. Clone the Repository
First, clone your Next.js application repository and switch to the development branch:
```sh
git clone https://<YOUR-PERSONAL-ACCESS-TOKEN>@github.com/yourusername/your-nextjs-app.git
cd your-nextjs-app
git checkout development
```

#### 2. Create a Droplet on DigitalOcean
1. Log in to your DigitalOcean account.
2. Click on **Create Droplet**.
3. Choose **Ubuntu** as the image.
4. Select **Basic** with regular CPU options (2GB Memory / 25GB Disk).
5. Choose **San Francisco** as the region.
6. Under **Authentication**, click on **New SSH Key**.
7. Generate an SSH key if you don't have one:
    ```sh
    ssh-keygen
    ```
8. Copy the content of your `~/.ssh/id_rsa.pub` file and paste it into DigitalOcean.
9. Name the droplet `<give it a name>`.
10. Complete the droplet creation and note the IP address.

#### 3. SSH into the Droplet
Access your droplet securely via SSH:
```sh
ssh root@<your-droplet-IP-address>
```

#### 4. Transfer or Clone the Repository
You can either transfer the frontend folder using `scp` or clone the repository directly in the droplet:
```sh
scp -i ~/.ssh/id_rsa -o IdentitiesOnly=yes -r frontend root@<droplet-ip-address>:/home
# or
git clone https://<YOUR-PERSONAL-ACCESS-TOKEN>@github.com/yourusername/your-nextjs-app.git
```

#### 5. Set Up the Application
Install necessary dependencies and configure Nginx:
```sh
cd your-nextjs-app

# Install Node.js
sudo apt-get install -y nodejs
node -v

# Install Yarn
npm install -g yarn

# Install Nginx
sudo apt-get install -y nginx

# Configure Nginx
sudo nano /etc/nginx/sites-available/frontend-app

# Add the following content to the file
server {
    listen 80;
    server_name YOUR_DROPLET_IP_ADDRESS;

    location / {
        proxy_pass http://localhost:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }
}

# Enable the configuration
sudo ln -s /etc/nginx/sites-available/frontend-app /etc/nginx/sites-enabled/
sudo nginx -t
sudo service nginx restart

# Build and Start the Application
yarn install
yarn build
npm install pm2 -g
pm2 start yarn --name "frontend" -- start
pm2 save
pm2 list
```

#### 6. Configure DNS with Cloudflare
1. Log in to Cloudflare and navigate to your domain.
2. Create a subdomain (e.g., `www.yourdomain.com`) and point it to your droplet's IP address.
3. In DigitalOcean, navigate to **Networking** > **Domains** > **Add Domain**.
4. Add your domain (e.g., `yourdomain.com`), and under the A record, point the subdomain to the droplet's IP address.

#### 7. Update Nginx Configuration
```sh
ssh root@<your-droplet-IP-address>
sudo nano /etc/nginx/sites-available/frontend-app

# Change `server_name` to your domain name
server_name www.yourdomain.com;

# Reload Nginx
sudo nginx -t
sudo service nginx reload
```

#### 8. Obtain an SSL Certificate
Follow the [Certbot instructions](https://certbot.eff.org/lets-encrypt/ubuntufocal-nginx) to install and obtain the certificate, then update the Nginx configuration to use SSL.

### Automate Deployment with GitHub Actions

#### 1. Generate DigitalOcean API Token
1. Log in to DigitalOcean.
2. Navigate to API > Tokens/Keys.
3. Generate a new token and save it.

#### 2. Create GitHub Secrets
1. Navigate to your repository on GitHub.
2. Go to **Settings** > **Secrets and variables** > **Actions** > **New repository secret**.
3. Add the following secrets:
   - `SSH_HOST_FRONTEND`: Droplet IP address
   - `SSH_USERNAME`: `root`
   - `SSH_KEY`: Your SSH private key content (from `~/.ssh/id_rsa`)

#### 3. SSH Key Configuration for GitHub Actions
To save yourself from a headache and waste of time, follow these steps carefully:
1. SSH into the droplet:
    ```sh
    ssh root@<your-droplet-IP-address>
    ```
2. Generate an SSH key:
    ```sh
    ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
    ```
    - Save the key as `~/.ssh/id_rsa`.
3. Add GitHub to known hosts:
    ```sh
    ssh-keyscan -t rsa github.com >> ~/.ssh/known_hosts
    ```
4. Authorize the SSH key:
    ```sh
    cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
    cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys2
    chmod 700 ~/.ssh/authorized_keys && chmod 640 ~/.ssh/authorized_keys2
    ```
5. Display the private key:
    ```sh
    cat ~/.ssh/id_rsa
    ```
6. Copy the key and add it as a GitHub secret (`SSH_KEY`).

#### 4. Create GitHub Actions Workflow
1. Create a `.github/workflows` directory in your repository.
2. Create a file `deploy-frontend.yml` with the following content:
    ```yaml
    name: Deploy Frontend

    on:
      push:
        branches: [ "development" ]
        paths:
          - "<your-application-directory>/**"
      workflow_dispatch:  # Allows you to run this workflow manually from the Actions tab

    jobs:
      build:
        runs-on: ubuntu-latest

        steps:
        - name: Checkout repository
          uses: actions/checkout@v3

        - name: Deploy to DigitalOcean droplet via SSH
          uses: appleboy/ssh-action@v0.1.3
          with:
            host: ${{ secrets.SSH_HOST_FRONTEND }}
            username: ${{ secrets.SSH_USERNAME }}
            key: ${{ secrets.SSH_KEY }}
            script: |
              cd your-nextjs-app
              ls
              git pull
              yarn install
              yarn build

              # Check if PM2 process is running
              if pm2 list | grep -q 'frontend'; then
                # Reload application to ensure zero downtime
                pm2 reload frontend
              else
                # Start the application with PM2 if not already running
                pm2 start yarn --name "frontend" -- start
              fi

              pm2 list
    ```

#### 5. Trigger the Workflow
Make changes in the frontend path and commit to trigger the workflow.

---

### Conclusion

Deploying a Next.js application to DigitalOcean and automating the process with GitHub Actions can save you time and prevent potential deployment headaches. By following this guide, you've set up a robust deployment pipeline that ensures your application is always up-to-date with the latest changes from your development branch. This streamlined process not only enhances your deployment efficiency but also guarantees a reliable and consistent environment for your application. With these steps, you're well on your way to mastering cloud deployment and continuous integration for your Next.js projects. Happy coding!