lutece — Scaleway Dedibox VPS (VPS-START-2-S, Paris)
NixOS VPS at 64.31.63.130, installed with nixos-anywhere + disko. Two roles:
- homelab mesh client on
wg0(10.100.0.3), peer of carthage - travel exit node on
wg1(10.101.0.0/24) — full tunnel giving a French IP from abroad, plus access to the homelab
Why no Terraform
Dedibox is on the legacy Online.net platform and has no resources in the
scaleway/scaleway Terraform provider (its scaleway_baremetal_server is
Elastic Metal, a different product). It is scriptable through the dedibox/v1
API (scw dedibox ...), but a VPS on monthly commitment is a pet, ordered once
by hand. The declarative part lives in systems/lutece/.
Hardware facts (verified on the running host)
| Disk | /dev/vda, 30 GB, virtio |
| Firmware | BIOS (GPT + EF02 boot partition, GRUB) |
| CPU / RAM | 2 vCPU / 1.9 GB + 4 GB swapfile |
| IPv4 | 64.31.63.130/24, gw 64.31.63.1 — static, no DHCP |
| IPv6 | 2a11:840:72:1b::/64 via SLAAC; stable address ends :216:3eff:fea8:6cf3 |
The static IPv4 is the important one: a DHCP assumption leaves the box unreachable after reboot. IPv6 is intentionally not pinned — its gateway is the provider router’s link-local address.
Reinstall
nix run github:nix-community/nixos-anywhere -- \
--flake .#lutece --build-on local root@64.31.63.130
Run it from a host whose key is in the VPS’s authorized_keys (set at order
time in the Dedibox console). It must be usable non-interactively, so a
Yubikey/touch key will not do. Keep an IPv4 reachable —
nixos-anywhere has known failures on IPv6-only Scaleway targets
(nix-community/nixos-anywhere#227).
Note the two keys under /etc/wireguard/ are not in the Nix store and do
not survive a reinstall; regenerate them as below.
WireGuard keys (manual, once)
# mesh identity (wg0) — public key goes to globals.machines.lutece.net.vpn.pubkey
umask 077; wg genkey > /etc/wireguard/private.key; wg pubkey < /etc/wireguard/private.key
# travel server identity (wg1) — public key goes into travel client configs
umask 077; wg genkey > /etc/wireguard/travel.key; wg pubkey < /etc/wireguard/travel.key
Travel tunnel
Peers are declared in globals.net.travel.peers (name → travel IP); their
public keys are reused from the machine’s mesh identity in
globals.machines.<name>.net.vpn.pubkey.
Client config, e.g. for hokkaido:
[Interface]
PrivateKey = <the device's existing mesh private key>
Address = 10.101.0.5/32
DNS = 1.1.1.1
MTU = 1340
[Peer]
PublicKey = d28ha+85FlP188kDkCDMX6I8iM20PtbTy6kj0sHvHwo=
Endpoint = travel.sbr.pm:51820
AllowedIPs = 0.0.0.0/0, ::/0
PersistentKeepalive = 25
Only Address changes per device:
| Device | mesh | travel |
|---|---|---|
| hokkaido | 10.100.0.5 |
10.101.0.5/32 |
| osaka (Boox tablet) | 10.100.0.64 |
10.101.0.64/32 |
| suzu | 10.100.0.65 |
10.101.0.65/32 |
| houbeb-makcbook-pro | 10.100.0.71 |
10.101.0.71/32 |
AllowedIPs = 0.0.0.0/0 is what makes it a full tunnel: web traffic exits in
Paris with a French IP, and 10.100.0.0/24 reaches the homelab through
lutece’s wg0.
How the return path works: lutece masquerades 10.101.0.0/24 on
POSTROUTING with no output interface, so homelab hosts see traffic as coming
from 10.100.0.3 and need no route for the travel subnet. That is why adding
this feature required no change to rhea/aion/carthage’s config.
Caveat: this is a hosting IP range, not residential. Geo-restricted services that block datacenter ranges may still refuse it.
Deploy order
- Generate
/etc/wireguard/travel.keyon lutece (above). - Deploy lutece:
nixos-rebuild switch --flake .#lutece --target-host root@64.31.63.130 - Redeploy carthage so it accepts lutece as a mesh peer.
- Add the travel tunnel to the device and test:
curl ifconfig.meshould show64.31.63.130.
Open items
- Root only accepts touch-required keys, so nothing can manage lutece
non-interactively. Add an
aomi-tpmentry forluteceinglobals.ssh.vincentif automation is wanted. - SSH is still public; restrict it to the VPN address once the mesh is up (see
the TODO in
systems/lutece/extra.nix). - Travel peers currently reuse their mesh keypair. Separate keys would be cleaner; it means provisioning a new keypair per device.