📡My first network connectivity
I am setting up an IPv6-only homelab with Forgejo, OpenTofu + Terragrunt, MikroTik switches, and BIRD3 OSPFv3 routing.
A Forgejo runner operates inside the homelab and configures the network using Infrastructure-as-Code.
The entire IoC configuration is publicly available on Codeberg.

#IPv6 #Homelab #Forgejo #OpenSource #MikroTik #OSPF #OpenTofu #Terragrunt #BIRD #Automation
Getting Started with Forgejo
I set up a Forgejo runner inside my homelab network so the runner can configure the switches and nodes directly. In theory, this isn’t strictly necessary because everything runs on IPv6 without NAT; with proper firewall rules, internet-originating traffic could reach the homelab as well.
My configuration is public on Codeberg:
Repository: myOpenstackCluster (https://codeberg.org/mpiscaer/myOpenstackCluster)
Why Codeberg?
- 🇪🇺Based in Europe
- 🫶Non-profit
- 🌐Full IPv6 support
I followed the official installation guide: https://forgejo.org/docs/next/admin/actions/runner-installation/
Because this runner is IPv6-only, I made a few adjustments.
- Forgejo Configuration
In config.yml, I enabled:
enable_ipv6: true
2. Docker Configuration
{
"ipv6": true,
"experimental": true,
"ip6tables": true,
"fixed-cidr-v6": "fd00:d0ca:1::/64",
"default-address-pools": [
{ "base": "172.17.0.0/16", "size": 24 },
{ "base": "fd00:d0ca:2::/104", "size": 112 }
],
"registry-mirrors": [
"https://registry.ipv6.docker.com"
]
}
This configuration:
- Enables IPv6 networking
- Provides an IPv6 address pool for containers
- Uses Docker Hub’s IPv6 registry mirror
Network layout
My homelab currently consists of three switches and three compute nodes.
Switch Configuration
Now that the Forgejo runner is operational, I can continue setting up the network. The long-term goal is to use BGP unnumbered, but that requires more preparation. For now, I’m starting with an IPv6-only OSPF setup, which avoids assigning global IPv6 addresses to every link and keeps early configuration simpler.
The plan is to use OpenTofu with Terragrunt to manage switch configuration as Infrastructure as Code.
Before Terragrunt can manage the switches, I need a minimal bootstrap configuration:
- Create a user
- Create TLS certificates
- Enable HTTPS and the API
Now that the runner is running I can continue with the network setup. The goal of the Lab is to have a Unnumbered bgp setup. Currently for now it is to complex/new. So we start with a IPv6 only OSPF setup, the advantages is that you don't need to setup a IPv6 global adress range on every interface, this makes the setup easier. For now it is harder to figure out how it all works.
We will use OpenTofu and Terragrunt to configure the switches.
We start the setup with some basic setup so that the IoC(Intrastructure as Code) can connect to it.
We will enable the following:
- Create a user
- Create a certificate for the TLS
- Enable the TLS webserver
Create the user
/user/add group=full comment="The user for the Forgejo Runner" name=forgejorunner password="MyS3cr3tP4ss"Enable the API and HTTPS Using this guide: https://www.shellhacks.com/mikrotik-enabling-https-for-webfig-api/
This generates certificates and enables the API over TLS. Terragrunt will later replace this configuration.
Create the CA
[admin@MikroTik] > /certificate add name=root-ca-template \ common-name=root-ca \ days-valid=99999 \ key-size=2048 \ key-usage=crl-sign,key-cert-sign [admin@MikroTik] > /certificate sign root-ca-template name=root-caCreate the MikroTik certificate
[admin@MikroTik] > /certificate add name=mikrotik-ssl-template \ common-name=mikrotik-ssl \ days-valid=99999 \ key-size=2048 [admin@MikroTik] > /certificate sign mikrotik-ssl-template name=mikrotik-ssl ca=root-caMark the Mikrotik certificate trusted
[admin@MikroTik] > /certificate set [find name=mikrotik-ssl] trusted=yesAssign the certificate to www-ssl and api-ssl
[admin@MikroTik] > /ip service set www-ssl certificate=mikrotik-ssl disabled=no [admin@MikroTik] > /ip service set api-ssl certificate=mikrotik-ssl disabled=no
Terragrunt
OpenTofu (a Terraform fork) will manage the MikroTik configuration.
I found a useful example here:
https://github.com/mirceanton/mikrotik-terraform.git
I adapted parts of it:
* router-base module
* MikroTik provider code
* Additional modules for IPv6 addressing, OSPF setup, and SSH key configuration
🖥️node setup
For now, the three nodes are configured manually. Eventually they will be managed through Ansible and integrated into the overall IaC workflow.
The nodes receive their IPv6 addresses via Router Advertisements. Using Netplan, I configured a static IPv6 address on each loopback interface. This loopback address will be propagated via OSPF.
BIRD3 Installation and Configuration
To install BIRD3, I followed the instructions from: https://pkg.labs.nic.cz/doc/?project=bird.
Download the repository key
sudo wget -O /usr/share/keyrings/cznic-labs-pkg.gpg https://pkg.labs.nic.cz/gpgAdd the APT repository
echo "deb [signed-by=/usr/share/keyrings/cznic-labs-pkg.gpg] https://pkg.labs.nic.cz/bird3 jammy main" | sudo tee /etc/apt/sources.list.d/cznic-labs-bird3.listInstall BIRD3
sudo apt-get update && sudo apt-get install bird3Make the bird configuration
# ========================================================= # GLOBAL SETTINGS # ========================================================= # router id 172.17.40.12; # # ========================================================= # KERNEL ROUTING # ========================================================= protocol kernel { persist; learn; ipv6 { import all; # Accept routes from kernel export all; # Install BIRD-learned routes into kernel }; } # # ========================================================= # DEVICE PROTOCOL # ========================================================= protocol device { scan time 5; } # # ========================================================= # DIRECT (CONNECTED) ROUTES # ========================================================= protocol direct { ipv6; interface "lo", "enP4p65s0", "enP2p33s0"; } # # ========================================================= # OSPFv3 (IPv6) # ========================================================= protocol ospf v3 ospf6 { ipv6 { import all; export where source = RTS_DEVICE; # Only advertise connected routes }; area 0 { # Uplink / LAN interfaces interface "enP4p65s0" { hello 10; retransmit 5; cost 10; }; interface "enP2p33s0" { hello 10; retransmit 5; cost 10; }; }; }