All checks were successful
Deploy server-up (dev) / deploy (push) Successful in 2m10s
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
238 lines
9.3 KiB
Markdown
238 lines
9.3 KiB
Markdown
# 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.
|