Switch code, scripts and docs to English; drop plan.md references
This commit is contained in:
1 parent
76f1ad7825
commit
c4c7ca2ee4
15 files changed
+532
-540
No files matched your search
+87
-90
@@ -1,122 +1,120 @@
|
||||
# Deployment
|
||||
|
||||
Wie ein neuer Stand der Website auf Unraid landet. Aktueller Stand:
|
||||
**Handbetrieb** — Image lokal bauen, in die Gitea-Registry pushen, auf Unraid
|
||||
ziehen. Die Automatisierung per Gitea Actions (plan.md Schritt 10) kommt später.
|
||||
How a new version of the website ends up on Unraid. Current state:
|
||||
**manual** — build the image locally, push it to the Gitea registry, pull it on
|
||||
Unraid. Automation via Gitea Actions comes later.
|
||||
|
||||
> **Test- vs. Produktivbetrieb.** Solange die Domain noch nicht umgezogen ist und
|
||||
> NPM nicht davorsteht, läuft der Container mit einem Port-Mapping und ist im
|
||||
> lokalen Netz direkt erreichbar (`http://<unraid>:5000`). Im Produktivbetrieb
|
||||
> entfällt das Mapping — dann ist nur NPM der Weg zum Container (plan.md AE-4,
|
||||
> Abschnitt 8). Die beiden compose-Varianten sind unten getrennt beschrieben.
|
||||
> **Test vs. production.** As long as the domain has not moved yet and NPM is not
|
||||
> in front of it, the container runs with a port mapping and is directly reachable
|
||||
> on the local network (`http://<unraid>:5000`). In production the mapping is gone
|
||||
> — then NPM is the only path to the container. The two compose variants are
|
||||
> described separately below.
|
||||
|
||||
---
|
||||
|
||||
## Voraussetzungen (einmalig)
|
||||
## Prerequisites (one-time)
|
||||
|
||||
### Gitea-Registry-Token
|
||||
### Gitea registry token
|
||||
|
||||
Der Push in die Registry braucht ein Gitea-Zugriffstoken mit **Paket-Schreibrecht**
|
||||
(`package: Read and Write`) — **nicht** das Kontopasswort.
|
||||
The push to the registry needs a Gitea access token with **package write
|
||||
permission** (`package: Read and Write`) — **not** the account password.
|
||||
|
||||
1. Gitea → oben rechts Profilbild → **Settings** → **Applications**.
|
||||
2. Abschnitt **Manage Access Tokens**: Name vergeben (z.B. `registry-push`).
|
||||
3. Unter **Select scopes**: `package` auf **Read and Write** stellen.
|
||||
4. **Generate Token** klicken, Zeichenkette **sofort kopieren** (nur einmal
|
||||
sichtbar).
|
||||
1. Gitea → top right profile picture → **Settings** → **Applications**.
|
||||
2. **Manage Access Tokens** section: assign a name (e.g. `registry-push`).
|
||||
3. Under **Select scopes**: set `package` to **Read and Write**.
|
||||
4. Click **Generate Token**, **copy the string immediately** (shown only once).
|
||||
|
||||
> **Token ist ein Geheimnis.** Niemals in Git, Chats, Screenshots oder Tickets
|
||||
> im Klartext ablegen. Wird eins doch einmal sichtbar: in Gitea **löschen** und
|
||||
> neu erzeugen. Ein `package`-Token erlaubt das Hochladen beliebiger Images in
|
||||
> die Registry.
|
||||
> **The token is a secret.** Never store it in plain text in Git, chats,
|
||||
> screenshots, or tickets. If one does become visible: **delete** it in Gitea and
|
||||
> generate a new one. A `package` token allows uploading arbitrary images to the
|
||||
> registry.
|
||||
|
||||
Der Docker-Login speichert das Token danach lokal, sodass es nur einmal
|
||||
eingegeben werden muss.
|
||||
The Docker login then stores the token locally, so it only has to be entered once.
|
||||
|
||||
---
|
||||
|
||||
## Arbeitsweise: Branches, nie direkt auf main
|
||||
## Way of working: branches, never directly on main
|
||||
|
||||
`main` ist der **veröffentlichte** Stand — nur daraus wird `:latest` gebaut, und
|
||||
nur `:latest` zieht Unraid. Deshalb wird nie direkt auf `main` committet:
|
||||
`main` is the **published** state — only `:latest` is built from it, and only
|
||||
`:latest` is pulled by Unraid. That is why we never commit directly to `main`:
|
||||
|
||||
1. Feature-Branch anlegen: `git switch -c <bereich>/<kurz>` (z.B.
|
||||
1. Create a feature branch: `git switch -c <area>/<short>` (e.g.
|
||||
`deployment/sha-tagging`, `content/pipeline`).
|
||||
2. Dort committen, Branch pushen: `git push -u origin <branch>`.
|
||||
3. In Gitea einen **Pull Request** gegen `main` öffnen und dort mergen.
|
||||
4. Erst danach aus `main` das Release-Image bauen (unten).
|
||||
2. Commit there, push the branch: `git push -u origin <branch>`.
|
||||
3. Open a **Pull Request** against `main` in Gitea and merge it there.
|
||||
4. Only then build the release image from `main` (below).
|
||||
|
||||
**Dev-Images bleiben lokal.** Zum Ausprobieren auf dem eigenen Rechner:
|
||||
**Dev images stay local.** For trying things out on your own machine:
|
||||
|
||||
```bash
|
||||
scripts/dev-build.sh # baut elternbeirat-web:dev-<branch>, pusht NICHTS
|
||||
scripts/dev-build.sh # builds elternbeirat-web:dev-<branch>, pushes NOTHING
|
||||
```
|
||||
|
||||
So kann ein Entwicklungsstand nie versehentlich als `:latest` in der Registry
|
||||
landen.
|
||||
This way a development state can never accidentally land in the registry as
|
||||
`:latest`.
|
||||
|
||||
## Neuen Stand ausrollen (Handbetrieb)
|
||||
## Rolling out a new version (manual)
|
||||
|
||||
Voraussetzung: einmalig an der Registry angemeldet (siehe unten). Dann, **auf
|
||||
main** und mit sauberem Arbeitsverzeichnis:
|
||||
Prerequisite: logged in to the registry once (see below). Then, **on main** and
|
||||
with a clean working directory:
|
||||
|
||||
```bash
|
||||
scripts/release.sh
|
||||
```
|
||||
|
||||
Das Skript baut das Image, taggt es mit `:latest` **und** dem Commit-Kurz-SHA
|
||||
(für Rollback) und pusht beide. Es **bricht ab**, wenn du nicht auf `main` bist
|
||||
oder uncommittete Änderungen hast, und warnt bei ungepushten Commits.
|
||||
The script builds the image, tags it with `:latest` **and** the short commit SHA
|
||||
(for rollback), and pushes both. It **aborts** if you are not on `main` or have
|
||||
uncommitted changes, and warns about unpushed commits.
|
||||
|
||||
> Der Image-Pfad `gitea.anticarnist.de/tom/elternbeirat` ist **kleingeschrieben**
|
||||
> — Container-Registries verlangen das im Pfad, obwohl Benutzer (`Tom`) und Repo
|
||||
> (`Elternbeirat`) großgeschrieben sind.
|
||||
> The image path `gitea.anticarnist.de/tom/elternbeirat` is **lowercase** —
|
||||
> container registries require that in the path, even though the user (`Tom`) and
|
||||
> the repo (`Elternbeirat`) are capitalized.
|
||||
|
||||
### Unraid einmalig an der Registry anmelden
|
||||
### Logging Unraid in to the registry once
|
||||
|
||||
Das Image ist **privat**, deshalb muss Unraid sich einmal anmelden, bevor es
|
||||
ziehen kann. Das **Compose Manager Plus**-Plugin hat dafür kein UI-Feld — der
|
||||
Login läuft über das Unraid-Terminal (`>_`-Symbol oben rechts in der
|
||||
Weboberfläche, Prompt `root@Cube:~#`):
|
||||
The image is **private**, so Unraid has to log in once before it can pull. The
|
||||
**Compose Manager Plus** plugin has no UI field for this — the login runs through
|
||||
the Unraid terminal (`>_` symbol at the top right of the web interface, prompt
|
||||
`root@Cube:~#`):
|
||||
|
||||
```bash
|
||||
docker login gitea.anticarnist.de
|
||||
# Username: Tom
|
||||
# Password: <package-Token>
|
||||
# Password: <package token>
|
||||
```
|
||||
|
||||
Der Login bleibt gespeichert; er muss nur wiederholt werden, wenn das Token
|
||||
wechselt. Zwei erfahrungsgemäße Stolpersteine:
|
||||
The login stays stored; it only has to be repeated when the token changes. Two
|
||||
pitfalls learned from experience:
|
||||
|
||||
- **Nicht mit PowerShell/Laptop verwechseln.** Der Login muss im *Unraid*-Terminal
|
||||
passieren (`root@Cube`), nicht in der Windows-PowerShell (`PS C:\`). Der Laptop
|
||||
braucht den Login nur zum *Pushen*, Unraid zum *Ziehen*.
|
||||
- **Falscher Username bleibt hängen.** Meldet der Login „Stored credentials
|
||||
invalid or expired" und fragt *nicht* nach dem Namen, erst `docker logout
|
||||
gitea.anticarnist.de`, dann neu einloggen — sonst wird versehentlich ein
|
||||
Nonsens-Username gespeichert.
|
||||
- **Klartext-Warnung.** Docker speichert das Token unverschlüsselt in
|
||||
`/root/.docker/config.json`. Auf dem eigenen Server für den Anfang okay.
|
||||
*Später sauberer:* einen Credential-Helper einrichten (→ offener Punkt unten).
|
||||
- **Don't confuse it with PowerShell/laptop.** The login has to happen in the
|
||||
*Unraid* terminal (`root@Cube`), not in Windows PowerShell (`PS C:\`). The laptop
|
||||
needs the login only to *push*, Unraid to *pull*.
|
||||
- **A wrong username gets stuck.** If the login reports "Stored credentials
|
||||
invalid or expired" and does *not* ask for the name, first `docker logout
|
||||
gitea.anticarnist.de`, then log in again — otherwise a nonsense username gets
|
||||
stored by accident.
|
||||
- **Plain-text warning.** Docker stores the token unencrypted in
|
||||
`/root/.docker/config.json`. On your own server, okay for a start.
|
||||
*Cleaner later:* set up a credential helper (→ open item below).
|
||||
|
||||
### Auf Unraid neu ziehen und starten
|
||||
### Pull and start again on Unraid
|
||||
|
||||
Im **Compose Manager Plus**-Plugin (Unraid-Weboberfläche):
|
||||
In the **Compose Manager Plus** plugin (Unraid web interface):
|
||||
|
||||
- Reiter **Docker** → Abschnitt **Compose** → Stack **elternbeirat** →
|
||||
**Compose Down**, dann **Compose Up** (oder „Pull" + „Up", je nach
|
||||
Plugin-Version), damit die neue `:latest` gezogen wird.
|
||||
- **Docker** tab → **Compose** section → stack **elternbeirat** →
|
||||
**Compose Down**, then **Compose Up** (or "Pull" + "Up", depending on the plugin
|
||||
version), so that the new `:latest` is pulled.
|
||||
|
||||
> `docker compose up` zieht ein `:latest` **nicht** automatisch neu, wenn schon
|
||||
> ein gleichnamiges Image lokal liegt. Im Zweifel vorher explizit „Pull".
|
||||
> `docker compose up` does **not** automatically re-pull a `:latest` if an image of
|
||||
> the same name is already present locally. When in doubt, explicitly "Pull" first.
|
||||
|
||||
---
|
||||
|
||||
## compose-Varianten
|
||||
## compose variants
|
||||
|
||||
### Test (jetzt: ohne NPM, direkt im LAN erreichbar)
|
||||
### Test (now: without NPM, directly reachable on the LAN)
|
||||
|
||||
Liegt im Repo als `compose.yaml`. Zieht das Registry-Image und mappt Port
|
||||
Present in the repo as `compose.yaml`. Pulls the registry image and maps port
|
||||
**5000 → 8080**:
|
||||
|
||||
```yaml
|
||||
@@ -129,15 +127,14 @@ services:
|
||||
ASPNETCORE_URLS: http://+:8080
|
||||
TZ: Europe/Berlin
|
||||
ports:
|
||||
- "5000:8080" # TEST-Zugang, im Produktivbetrieb entfernen
|
||||
- "5000:8080" # TEST access, remove in production
|
||||
```
|
||||
|
||||
Erreichbar unter `http://<unraid>:5000`.
|
||||
Reachable at `http://<unraid>:5000`.
|
||||
|
||||
### Produktiv (später: nur über NPM)
|
||||
### Production (later: only via NPM)
|
||||
|
||||
Kein `ports:`-Block, stattdessen das externe NPM-Docker-Netz (plan.md
|
||||
Abschnitt 8):
|
||||
No `ports:` block, instead the external NPM Docker network:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
@@ -159,27 +156,27 @@ networks:
|
||||
|
||||
## Rollback
|
||||
|
||||
`scripts/release.sh` taggt jeden Release zusätzlich mit dem Commit-Kurz-SHA, der
|
||||
sich — anders als das wandernde `:latest` — nie verschiebt. Zum Zurückrollen in
|
||||
der Unraid-`compose.yaml` `:latest` durch `:<sha>` des letzten funktionierenden
|
||||
Stands ersetzen und neu hochfahren:
|
||||
`scripts/release.sh` additionally tags each release with the short commit SHA,
|
||||
which — unlike the moving `:latest` — never shifts. To roll back, replace
|
||||
`:latest` in the Unraid `compose.yaml` with the `:<sha>` of the last working state
|
||||
and bring it back up:
|
||||
|
||||
```yaml
|
||||
image: gitea.anticarnist.de/tom/elternbeirat:99dd052 # statt :latest
|
||||
```
|
||||
|
||||
Welche SHA-Tags in der Registry liegen, zeigt Gitea unter
|
||||
Which SHA tags are in the registry is shown by Gitea under
|
||||
`Tom/-/packages` → `elternbeirat`.
|
||||
|
||||
---
|
||||
|
||||
## Offene Automatisierung (später, plan.md Schritt 10)
|
||||
## Open automation (later)
|
||||
|
||||
- `.gitea/workflows/deploy.yml`: auf Push nach `main` bauen und pushen.
|
||||
- Zwei bekannte Stolpersteine: der `act_runner` braucht Docker-Socket-Zugriff;
|
||||
die Registry braucht das `write:package`-Token, nicht das Login-Passwort.
|
||||
- Redeploy per Watchtower **label-scoped**, sonst aktualisiert er den ganzen
|
||||
Home-Lab-Bestand.
|
||||
- **Registry-Token auf Unraid verschlüsseln:** aktuell liegt es im Klartext in
|
||||
`/root/.docker/config.json`. Später einen Credential-Helper einrichten, damit
|
||||
die Klartext-Warnung von `docker login` verschwindet.
|
||||
- `.gitea/workflows/deploy.yml`: build and push on push to `main`.
|
||||
- Two known pitfalls: the `act_runner` needs Docker socket access; the registry
|
||||
needs the `write:package` token, not the login password.
|
||||
- Redeploy via Watchtower **label-scoped**, otherwise it updates the entire
|
||||
home-lab inventory.
|
||||
- **Encrypt the registry token on Unraid:** currently it sits in plain text in
|
||||
`/root/.docker/config.json`. Set up a credential helper later, so that the
|
||||
plain-text warning from `docker login` disappears.
|
||||
Reference in new issue
Block a user