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.