2026-01-29 23:29:32 +01:00
|
|
|
|
# MinApp – Self-hosted .NET Web App (Forgejo CI/CD)
|
|
|
|
|
|
|
|
|
|
|
|
Dette repository indeholder **MinApp**, en ASP.NET Core webapplikation, deployet **DevOps-style** til en Ubuntu-server ved hjælp af:
|
|
|
|
|
|
|
|
|
|
|
|
- Forgejo (Git hosting + CI)
|
|
|
|
|
|
- Forgejo Runner (Docker)
|
|
|
|
|
|
- Caddy (reverse proxy)
|
|
|
|
|
|
- systemd (services)
|
|
|
|
|
|
- **Self-contained .NET publish** (ingen runtime på serveren)
|
|
|
|
|
|
|
|
|
|
|
|
Målet er:
|
|
|
|
|
|
> Push → build → test → deploy til TEST
|
|
|
|
|
|
> Manuel trigger → deploy til PROD
|
|
|
|
|
|
|
|
|
|
|
|
Uden IIS, uden Azure DevOps, uden runtime-rod.
|
|
|
|
|
|
|
2026-01-31 15:41:05 +01:00
|
|
|
|
|
2026-01-29 23:29:32 +01:00
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 🧱 Arkitektur (overblik)
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
Developer PC
|
|
|
|
|
|
│
|
|
|
|
|
|
│ git push
|
|
|
|
|
|
▼
|
|
|
|
|
|
Forgejo (192.168.1.63:3000)
|
|
|
|
|
|
│
|
|
|
|
|
|
│ Actions workflow
|
|
|
|
|
|
▼
|
|
|
|
|
|
Forgejo Runner (Docker)
|
|
|
|
|
|
│
|
|
|
|
|
|
│ dotnet publish (self-contained)
|
|
|
|
|
|
│ rsync + ssh
|
|
|
|
|
|
▼
|
|
|
|
|
|
Ubuntu Webserver (24.04)
|
|
|
|
|
|
├─ systemd service (minapp / minapp-test)
|
|
|
|
|
|
├─ Kestrel (127.0.0.1:5000 / 5001)
|
|
|
|
|
|
└─ Caddy → [http://app.jarjarbinks](http://app.jarjarbinks) / [http://test.jarjarbinks](http://test.jarjarbinks)
|
|
|
|
|
|
|
|
|
|
|
|
````
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 🖥️ Server-setup (kort)
|
|
|
|
|
|
|
|
|
|
|
|
### OS
|
|
|
|
|
|
- Ubuntu **24.04 LTS**
|
|
|
|
|
|
- Arkitektur: **x86_64 / linux-x64**
|
|
|
|
|
|
|
|
|
|
|
|
### Reverse proxy
|
|
|
|
|
|
- **Caddy**
|
|
|
|
|
|
- Port 80/443 → reverse proxy til Kestrel
|
|
|
|
|
|
|
|
|
|
|
|
### App services
|
|
|
|
|
|
- `/opt/minapp/app` (prod)
|
|
|
|
|
|
- `/opt/minapp-test/app` (test)
|
|
|
|
|
|
- Kører som bruger: `minapp`
|
|
|
|
|
|
- Styres via `systemd`
|
|
|
|
|
|
|
|
|
|
|
|
### Vigtigt designvalg
|
|
|
|
|
|
App’en deployes som **self-contained**:
|
|
|
|
|
|
- Ingen .NET runtime installeres på serveren
|
|
|
|
|
|
- CI bygger en Linux-x64 binary
|
|
|
|
|
|
- OS og .NET-versioner er fuldstændig afkoblet
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 🔁 CI/CD Flow (Forgejo Actions)
|
|
|
|
|
|
|
|
|
|
|
|
### Trigger
|
|
|
|
|
|
- `push` til `main` → build + test + deploy til **TEST**
|
|
|
|
|
|
- `workflow_dispatch` → manuel deploy til **PROD**
|
|
|
|
|
|
|
|
|
|
|
|
### Runner
|
|
|
|
|
|
- Kører som Docker runner
|
|
|
|
|
|
- Base image: `node:20-bookworm`
|
|
|
|
|
|
- kræves af Forgejo/GitHub actions (Node)
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## ⚙️ Workflow (`.forgejo/workflows/cicd.yml`)
|
|
|
|
|
|
|
|
|
|
|
|
Nøglepunkter:
|
|
|
|
|
|
|
|
|
|
|
|
```yaml
|
|
|
|
|
|
dotnet publish -c Release \
|
|
|
|
|
|
-r linux-x64 \
|
|
|
|
|
|
--self-contained true \
|
|
|
|
|
|
-o out
|
|
|
|
|
|
````
|
|
|
|
|
|
|
|
|
|
|
|
* Output indeholder en executable: `MinApp`
|
|
|
|
|
|
* Filer kopieres via `rsync` over SSH
|
|
|
|
|
|
* systemd service genstartes efter deploy
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 🔐 Secrets (Forgejo)
|
|
|
|
|
|
|
|
|
|
|
|
Repo → **Settings → Actions → Secrets**
|
|
|
|
|
|
|
|
|
|
|
|
| Navn | Beskrivelse |
|
|
|
|
|
|
| ---------------- | -------------------------------- |
|
|
|
|
|
|
| `DEPLOY_HOST` | Webserver IP (fx `192.168.1.43`) |
|
|
|
|
|
|
| `DEPLOY_USER` | `deploy` |
|
|
|
|
|
|
| `DEPLOY_SSH_KEY` | Private SSH key til deploy |
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 🧑💻 systemd services
|
|
|
|
|
|
|
|
|
|
|
|
### Test
|
|
|
|
|
|
|
|
|
|
|
|
`/etc/systemd/system/minapp-test.service`
|
|
|
|
|
|
|
|
|
|
|
|
```ini
|
|
|
|
|
|
[Service]
|
|
|
|
|
|
WorkingDirectory=/opt/minapp-test/app
|
|
|
|
|
|
ExecStart=/opt/minapp-test/app/MinApp
|
|
|
|
|
|
Environment=ASPNETCORE_URLS=http://127.0.0.1:5001
|
|
|
|
|
|
Environment=ASPNETCORE_ENVIRONMENT=Staging
|
|
|
|
|
|
User=minapp
|
|
|
|
|
|
Restart=always
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### Prod
|
|
|
|
|
|
|
|
|
|
|
|
Samme opsætning, men:
|
|
|
|
|
|
|
|
|
|
|
|
* Port `5000`
|
|
|
|
|
|
* `Production`
|
|
|
|
|
|
* `/opt/minapp/app`
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 🌐 Caddy config
|
|
|
|
|
|
|
|
|
|
|
|
```caddy
|
|
|
|
|
|
http://test.jarjarbinks {
|
|
|
|
|
|
reverse_proxy 127.0.0.1:5001
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
http://app.jarjarbinks {
|
|
|
|
|
|
reverse_proxy 127.0.0.1:5000
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 🧪 Lokale tests på serveren
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
curl http://127.0.0.1:5001
|
|
|
|
|
|
curl http://127.0.0.1:5000
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
Hvis disse virker, vil Caddy også virke.
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 🚀 Deploy-guide
|
|
|
|
|
|
|
|
|
|
|
|
### Deploy til TEST
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
git push origin main
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### Deploy til PROD
|
|
|
|
|
|
|
|
|
|
|
|
* Forgejo → Actions
|
|
|
|
|
|
* Vælg workflow
|
|
|
|
|
|
* **Run workflow**
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 🛠️ Fejlfinding
|
|
|
|
|
|
|
|
|
|
|
|
### Service status
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
sudo systemctl status minapp-test
|
|
|
|
|
|
sudo journalctl -u minapp-test -n 100
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### Runner status
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
sudo systemctl status forgejo-runner
|
|
|
|
|
|
sudo journalctl -u forgejo-runner -n 100
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### Ports
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
ss -lntp | grep 500
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 🧠 Design rationale (why this setup)
|
|
|
|
|
|
|
|
|
|
|
|
* **Self-contained publish**
|
|
|
|
|
|
→ ingen runtime-helvede, nem OS-opgradering
|
|
|
|
|
|
|
|
|
|
|
|
* **systemd fremfor Docker i prod**
|
|
|
|
|
|
→ simpelt, stabilt, nem debugging
|
|
|
|
|
|
|
|
|
|
|
|
* **Caddy fremfor Nginx**
|
|
|
|
|
|
→ minimal config, automatisk TLS senere
|
|
|
|
|
|
|
|
|
|
|
|
* **Forgejo fremfor Azure DevOps**
|
|
|
|
|
|
→ fuld kontrol, ingen cloud-afhængighed
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 📌 Næste mulige skridt
|
|
|
|
|
|
|
|
|
|
|
|
* HTTPS med rigtigt domæne
|
|
|
|
|
|
* Blue/green deploy
|
|
|
|
|
|
* Health checks
|
|
|
|
|
|
* Logs → Loki / Grafana
|
|
|
|
|
|
* Secrets via environment variables
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 👤 Author
|
|
|
|
|
|
|
|
|
|
|
|
Janus
|
|
|
|
|
|
Homelab / self-hosted DevOps setup
|
|
|
|
|
|
|
|
|
|
|
|
|