Vorschau

/tutorial-cicd-deployment-setup.md

# CI/CD Deployment Setup — Raspberry Pi + GitHub Actions + Router + DynDNS

This guide explains step by step how to set up **automatic deployment (CI/CD)** for a website running on a Raspberry Pi.

After setup, the following happens automatically whenever code is pushed to the `main` branch:

1. GitHub starts the workflow
2. Connects to the Raspberry Pi via SSH
3. Switches to the project directory
4. Runs `deploy.sh`
5. Rebuilds / updates the website

---

# Requirements

You need:

* Raspberry Pi with SSH enabled
* GitHub repository
* DynDNS service (e.g. No-IP or DuckDNS)
* Router with port forwarding (example: FRITZ!Box)
* SSH port accessible from the internet
* SSH key authentication configured
* Project directory already exists on the Raspberry Pi

Example project path:

```bash
/home/username/project-folder/app-folder
```

or

```bash
~/project-folder/app-folder
```

---

# Step 1 — Configure DynDNS

Open your router interface:

```text
Internet → Port Sharing / DynDNS
```

Enter:

## Domain name

```text
example.ddns.net
```

## Username

```text
DynDNS username
```

## Password

```text
DynDNS password
```

Optional (if provider is not selectable):

```text
https://dynupdate.no-ip.com/nic/update?hostname=<domain>&myip=<ipaddr>
```

⚠️ Important:

Domain name must **NOT** be:

```text
192.168.x.x
```

and **NOT**:

```text
fritz.box
```

Instead always use:

```text
example.ddns.net
```

---

# Step 2 — Enable SSH on Raspberry Pi

Check SSH status:

```bash
sudo systemctl status ssh
```

If necessary:

```bash
sudo systemctl enable ssh
sudo systemctl start ssh
```

---

# Step 3 — Configure SSH Port Forwarding on Router

Open router menu:

```text
Internet → Port Sharing / Port Forwarding
```

Configure forwarding:

## External port

```text
SSH port (e.g. 22 or custom external port)
```

## Internal port

```text
22
```

## Target device

```text
Raspberry Pi
```

---

# Step 4 — Test SSH Connection from Outside

Test connection:

```bash
ssh -p PORT [email protected]
```

If this works → network configuration is correct ✅

---

# Step 5 — Generate SSH Key for GitHub Actions

Generate key:

```bash
ssh-keygen -t ed25519 -C "github-actions-deploy"
```

This creates:

```text
id_ed25519
id_ed25519.pub
```

---

# Step 6 — Add Public Key to Raspberry Pi

On Raspberry Pi:

```bash
mkdir -p ~/.ssh
chmod 700 ~/.ssh
cat id_ed25519.pub >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
```

Test connection:

```bash
ssh -i id_ed25519 -p PORT [email protected]
```

---

# Step 7 — Create GitHub Secrets

Open repository:

```text
Settings → Secrets and variables → Actions
```

Create the following secrets:

## PI_HOST

```text
example.ddns.net
```

⚠️ Important — NOT:

```text
https://example.ddns.net
ssh://example.ddns.net
example.ddns.net:22
```

Only:

```text
example.ddns.net
```

---

## PI_PORT

```text
22
```

(or your custom SSH port)

---

## PI_USERNAME

```text
username
```

---

## PI_SSH_KEY

Paste the full content of:

```text
id_ed25519
```

Including:

```text
-----BEGIN OPENSSH PRIVATE KEY-----
```

through:

```text
-----END OPENSSH PRIVATE KEY-----
```

🚫 Do NOT paste:

```text
.pub file
```

---

# Step 8 — Create deploy.sh

File location:

```bash
~/project-folder/app-folder/deploy.sh
```

Example script:

```bash
#!/bin/bash

set -e

cd ~/project-folder

git pull origin main

cd ~/project-folder/app-folder

npm install
npm run build
```

Make executable:

```bash
chmod +x ~/project-folder/app-folder/deploy.sh
```

---

# Step 9 — Create GitHub Workflow

File:

```text
.github/workflows/deploy.yml
```

Content:

```yaml
name: Deploy to Raspberry Pi

on:
  push:
    branches:
      - main

jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v5

      - uses: appleboy/[email protected]
        with:
          host: ${{ secrets.PI_HOST }}
          username: ${{ secrets.PI_USERNAME }}
          key: ${{ secrets.PI_SSH_KEY }}
          port: ${{ secrets.PI_PORT }}
          script: |
            cd ~/project-folder/app-folder
            ./deploy.sh
```

---

# Step 10 — Test Deployment

Run:

```bash
git add .
git commit -m "test deployment"
git push origin main
```

Then open:

```text
GitHub → Actions
```

Workflow should start automatically.

---

# Common Issues

## Wrong project path

Incorrect:

```bash
/project-folder/app-folder
```

Correct:

```bash
~/project-folder/app-folder
```

---

## Incorrect PI_HOST value

Incorrect:

```text
https://domain
```

Correct:

```text
domain
```

---

## SSH port not forwarded

Website reachable ≠ SSH reachable

SSH requires its own port forwarding rule.

---

## Wrong SSH key stored

GitHub requires:

```text
private key
```

NOT:

```text
.pub
```

---

# Deployment Flow (Automatic)

Push to main:

```bash
git push origin main
```

GitHub:

```text
workflow starts
```

SSH connection:

```text
Raspberry Pi
```

Script execution:

```text
deploy.sh
```

Website:

```text
updated automatically
```

---

# Result

CI/CD now runs automatically via:

```text
GitHub Actions
→ SSH
→ Raspberry Pi
→ deploy.sh
```

No manual server login required anymore.