server-up/docs/netwerken.md
Ramon ea9b1eb668
All checks were successful
Deploy server-up (dev) / deploy (push) Successful in 2m10s
v0.7.80-beta - Volgende-knop, tijdzones, netwerken per groepje, Pangolin
De knop Volgende deed niets. Alpine haalt een boolean-attribuut alleen weg bij
null, undefined of false; het getal 0 zet het juist AAN. Mijn
:disabled="stepMissing().length" gaf bij een ingevuld formulier 0 en zette de
knop dus permanent uit. De logica klopte, de binding niet — met losse logica
niet te vinden, dus er draait nu een test die de echte modal met Alpine in een
DOM rendert en erop klikt.

Tijdzones:
- Nieuwe instelling TIMEZONE, standaard die van de server (TZ, /etc/timezone,
  /etc/localtime). In alle 77 sjablonen stond Europe/Amsterdam hard ingevuld.
- Apps zonder tijdzoneveld krijgen TZ er automatisch bij; die draaiden in UTC.

Poorten:
- _bezette_poorten() telt nu ook mee waar de host zelf op luistert, gelezen uit
  /proc/net/tcp in een hulpcontainer met --network host. Een nginx buiten
  Docker zag Server Up eerder niet.
- GET /api/ports/check geeft vrij/bezet plus een alternatief, en meldt of de
  host echt gecontroleerd kon worden.

Netwerken:
- APP_NETWORKS: meerdere gedeelde bridge-netwerken in plaats van één waar élke
  app aan hing. Per app kies je welke; aanmaken kan vanuit het invulmenu, met
  eigen naam of een voorstel (su-<appnaam>).
- add_shared_network() accepteert een lijst; één naam blijft werken.
- GET /api/networks/<n>/ip-check controleert subnet, bereik, Docker-toewijzing
  en de ARP-tabel van de host (vangt een fysiek apparaat met DHCP-adres) en
  stelt een vrij adres voor.

Pangolin (nieuw, core/pangolin.py):
- Publieke URL per app via een tunnel, zonder poorten open te zetten.
- De API veranderde in 1.9 (resource hing onder een site, staat nu los); beide
  routes worden geprobeerd en bij een fout krijg je beide meldingen.
- API-sleutel is write-only. Getest tegen een nagebouwde API, niet tegen een
  echte server.

Nieuw: docs/pangolin.md; docs/netwerken.md uitgebreid. 2369 tests groen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C7oLCRYzY5ixJ5Sv8Y8EFb
2026-07-28 22:25:38 +02:00

238 lines
9.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Stacks een eigen IP-adres geven (macvlan / ipvlan)
Standaard publiceert een stack poorten op de host: Vaultwarden op `8222`, Mealie
op `9925`, enzovoort. Dat werkt, maar levert op den duur een lange lijst
poortnummers op die je moet onthouden, en twee apps die allebei poort 8080 willen
gaan niet samen.
Met een **macvlan**- of **ipvlan**-netwerk krijgt een stack een eigen IP-adres in
je LAN. De app draait dan gewoon op zijn eigen standaardpoort:
| Zonder | Met eigen IP |
|--------|--------------|
| `http://192.168.1.10:8222` | `http://192.168.1.240` |
| `http://192.168.1.10:9925` | `http://192.168.1.241` |
Je kunt er ook per app op firewallen, en een DNS-naam aan koppelen.
---
## ⚠️ Lees dit eerst: de host bereikt zijn eigen containers niet
Dit is de bekendste valkuil van macvlan. De Docker-host kan **niet** bij een
container die op een macvlan-netwerk draait, en andersom ook niet. Alle andere
apparaten in je netwerk kunnen dat wél.
Draait Server Up op dezelfde machine als de containers, dan zie je dus:
- vanaf je laptop: `http://192.168.1.240` werkt
- vanaf de server zelf: `curl http://192.168.1.240` loopt vast
Heb je dat nodig (bijvoorbeeld voor een healthcheck of een reverse proxy die op
de host draait), maak dan een shim-interface aan op de host:
```bash
# Eenmalig; vervang eth0 en de adressen door die van jouw netwerk.
ip link add shim link eth0 type macvlan mode bridge
ip addr add 192.168.1.239/32 dev shim
ip link set shim up
ip route add 192.168.1.240/28 dev shim
```
Zet dat in een systemd-unit of in `/etc/network/interfaces`, anders is het na een
herstart weg.
**ipvlan (l2)** heeft dit probleem niet op dezelfde manier, maar vereist wel dat
je switch en router er goed mee omgaan. Werkt macvlan niet, probeer dan ipvlan.
---
## Stap 1 — Netwerk aanmaken in Server Up
Ga naar **Instellingen → Netwerken → Netwerk**. Server Up kijkt zelf welk netwerk
je server gebruikt en toont dat bovenaan als voorstel: interface, subnet, gateway
en een vrije IP-range. Eén klik vult het hele formulier.
> Die detectie werkt door heel kort een container te starten die de
> netwerknamespace van de host deelt en daar de routetabel uitleest. Server Up
> zelf zit in een eigen namespace en ziet anders alleen zijn eigen bridge.
Lukt detecteren niet, dan vul je het met de hand in. De vier velden:
| Wat | Voorbeeld | Hoe kom je eraan |
|-----|-----------|------------------|
| Host-interface | `eth0` | `ip -br link` op de server |
| Subnet | `192.168.1.0/24` | Je router; hetzelfde subnet als de server |
| Gateway | `192.168.1.1` | `ip route \| grep default` |
| IP-range | `192.168.1.240/28` | Een blok dat je **buiten je DHCP-bereik** houdt |
### Hoe die vier zich tot elkaar verhouden
Dit is waar het meestal misgaat, dus expliciet:
```
┌─────────────── subnet: 192.168.1.0/24 ───────────────┐
│ │
.1 .20 ──── DHCP ──── .239 .240 ── Docker ── .255
│ │ │ │ │
gateway je laptop, telefoon, einde begin einde
(je router) printer, enz. DHCP IP-range IP-range
```
- **Subnet** — precies hetzelfde als je router gebruikt. Een ander subnet
betekent dat je containers niemand kunnen bereiken.
- **Gateway** — je router, bijna altijd het eerste adres (`.1`). Laat je dit
leeg, dan kunnen de containers wel het LAN op maar niet het internet.
- **IP-range** — het deel dat Docker mag uitdelen. Dit moet **buiten** het
bereik liggen dat je router via DHCP uitgeeft, anders krijgt een container
hetzelfde adres als een apparaat in huis. Het einde van het subnet is meestal
vrij, vandaar `.240/28`.
- **Host-interface** — de netwerkkaart waar het LAN op zit. Niet die van Docker
(`docker0`, `br-…`) en niet wifi.
**Belangrijk:** het instellen van de range in Server Up doet niets aan je router.
Je moet dáár het DHCP-bereik verkleinen, bijvoorbeeld naar `192.168.1.20`
`192.168.1.239`. Doe je dat niet, dan blijven er dubbele adressen mogelijk.
Terwijl je typt controleert Server Up de combinatie en toont hoeveel adressen je
overhoudt (`192.168.1.240/28` → veertien bruikbare adressen, `.241` t/m `.254`).
Klopt er iets niet, dan staat er in gewone taal bij waarom.
### Veelgebruikte ranges
| Subnet | Gateway | Voorstel | Ruimte |
|---|---|---|---|
| `192.168.1.0/24` | `192.168.1.1` | `192.168.1.240/28` | 14 stacks |
| `192.168.0.0/24` | `192.168.0.1` | `192.168.0.240/28` | 14 stacks |
| `10.0.0.0/24` | `10.0.0.1` | `10.0.0.240/28` | 14 stacks |
| `192.168.1.0/24` | `192.168.1.1` | `192.168.1.224/27` | 30 stacks |
Meer nodig? Neem een groter blok: `/27` geeft 30 adressen, `/26` geeft 62. Zorg
dan wel dat je DHCP-bereik navenant kleiner wordt.
## Stap 2 — Wat Server Up ermee doet
Hetzelfde met de hand zou zijn:
```bash
docker network create -d macvlan \
--subnet 192.168.1.0/24 \
--gateway 192.168.1.1 \
--ip-range 192.168.1.240/28 \
-o parent=eth0 \
lan
```
## Stap 3 — Een stack installeren op een eigen IP
Kies in de installatiemodal bij **Netwerk** je netwerk in plaats van "Poorten op
de host". Server Up stelt het eerstvolgende vrije adres voor; je kunt het
overschrijven.
Bij het installeren gebeurt er dit met het compose-bestand:
```yaml
# vóór # ná
services: services:
vaultwarden: vaultwarden:
image: vaultwarden/server image: vaultwarden/server
ports: networks:
- "8222:80" lan:
ipv4_address: 192.168.1.240
networks:
lan:
external: true
```
De poortmapping verdwijnt — die heeft geen functie meer. Vaultwarden luistert op
poort 80 en is bereikbaar op `http://192.168.1.240`.
Bestaat een stack uit meerdere containers, dan krijgt de container die poorten
publiceerde het vaste adres; de rest komt zonder vast adres in hetzelfde netwerk,
zodat ze elkaar op servicenaam blijven vinden.
---
## Adresbeheer
Server Up bewaart het toegekende adres in `.serverup.json` in de stackmap. Zo
blijft het gereserveerd, ook als de stack gestopt is, en krijgt een volgende
installatie het volgende vrije adres voorgesteld.
Wil je het adres van een bestaande stack wijzigen, pas dan het compose-bestand
aan via **compose bewerken** en werk `ipv4_address` bij.
## Verwijderen
Een netwerk kan pas weg als er geen containers meer op draaien. Stop eerst de
betreffende stacks; Server Up weigert het anders met een melding.
## Problemen oplossen
| Symptoom | Oorzaak |
|----------|---------|
| `network ... not found` bij het starten | Netwerk verwijderd terwijl de stack er nog naar verwijst — maak het opnieuw aan |
| Container krijgt geen verbinding | Verkeerde `parent`-interface, of de interface zit in een bond/bridge |
| Adres al in gebruik | Het adres valt binnen je DHCP-bereik; verklein de DHCP-pool of kies een andere range |
| Vanaf de server niet bereikbaar, vanaf laptop wel | Verwacht gedrag — zie de shim-interface bovenaan |
| Werkt niet op WiFi | Klopt: macvlan werkt niet over een draadloze interface |
---
## Gedeelde netwerken tussen apps
Naast een eigen IP-adres is er het gedeelde bridge-netwerk waarop apps elkaar op
containernaam vinden. Tot v0.7.70 was dat er één (`serverup`) en hing élke app
eraan: Vaultwarden kon bij je mediaserver, en andersom.
Nu kies je per app aan welke netwerken hij meedoet, en kun je er bij het
installeren zelf een maken. Laat je de naam leeg, dan wordt er een voorgesteld
(`su-<appnaam>`). Het netwerk verschijnt daarna in de lijst bij elke andere app.
```
Stap 2 — Verbinden
☑ serverup standaard 12 containers
☑ su-media 3 containers
☐ su-beheer 2 containers
[ media ] [+ Netwerk maken]
```
Een app kan aan meerdere netwerken tegelijk hangen — handig voor een reverse
proxy die bij alles moet kunnen.
Verwijderen kan alleen als er geen containers meer aan hangen, en het
standaardnetwerk blijft altijd staan.
---
## Is dit adres nog vrij?
Bij het invullen van een IP-adres controleert Server Up vier dingen:
1. valt het binnen het **subnet** van het netwerk;
2. valt het binnen het ingestelde **bereik** (buiten je DHCP-pool dus);
3. is het al **toegekend aan een container** in dit netwerk of gereserveerd door
een andere stack;
4. heeft de host het adres recent **op het LAN gezien** — dat leest de ARP-tabel
van de host, en vangt een fysiek apparaat met een DHCP-adres.
Klopt er iets niet, dan staat erbij wat en krijg je een vrij adres voorgesteld.
> Punt 4 is geen garantie: een apparaat dat uit staat, staat niet in de
> ARP-tabel. Houd je macvlan-bereik daarom buiten wat je router uitdeelt.
---
## Is deze poort nog vrij?
Poortvelden krijgen automatisch een vrij nummer voorgesteld. Daarbij wordt niet
alleen gekeken naar wat Docker publiceert, maar ook naar wat er **rechtstreeks
op de host luistert** — een nginx of DNS-server buiten Docker zag Server Up
eerder niet, terwijl je er net zo goed mee botst.
Dat laatste gaat via een korte hulpcontainer met `--network host`. Lukt dat
niet, dan meldt het antwoord `host_checked: false`: "vrij" is dan een aanname
op basis van Docker alleen.