📡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. homelab

#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?

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.

  1. 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:


Network layout

My homelab currently consists of three switches and three compute nodes.

network diagram

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:

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:

  1. Create the user

    /user/add group=full comment="The user for the Forgejo Runner" name=forgejorunner password="MyS3cr3tP4ss"
    
  2. 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.

  1. 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-ca
    
  2. Create 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-ca
    
  3. Mark the Mikrotik certificate trusted

    [admin@MikroTik] > /certificate set [find name=mikrotik-ssl] trusted=yes
    
  4. Assign 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.

  1. Download the repository key

    sudo wget -O /usr/share/keyrings/cznic-labs-pkg.gpg https://pkg.labs.nic.cz/gpg
    
  2. Add 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.list
    
  3. Install BIRD3

    sudo apt-get update && sudo apt-get install bird3
    
  4. Make 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;
    };
    };
    }