--- a/t/run
+++ b/t/run
@@ -15,7 +15,9 @@
 use strict;
 use IO::Socket::INET6;
 use Test::More qw/no_plan/;
-use Conf::Libconfig 1.0.3;
+use FindBin;
+use lib "$FindBin::Bin/";
+use FakeLibconfig;
 use Getopt::Long;
 
 # --cover: request test coverage analysis (not implemented)
@@ -42,7 +44,7 @@
 ################################################################################
 sub get_conf {
     my ($filename) = @_;
-    my $conf = new Conf::Libconfig;
+    my $conf = new FakeLibconfig;
     $conf->read_file($filename) or die "$filename: $!";
     return $conf;
 }
--- /dev/null
+++ b/t/FakeLibconfig.pm
@@ -0,0 +1,233 @@
+# Fake Conf::Libconfig style wrapper
+
+package FakeLibconfig;
+
+=head1 NAME
+
+FakeLibconfig - This is a fake implementation of Conf::Libconfig;
+
+=head1 SYNOPSIS
+
+This Debian specific patch avoids us needing Conf::Libconfig.
+
+=head1 DESCRIPTION
+
+
+=cut
+
+use v5.36;
+use strictures 2;
+use Mouse;
+use namespace::clean;
+use IO::File;
+use IO::Socket::INET;
+use List::Util   qw(none);
+use Scalar::Util qw(looks_like_number);
+use builtin      qw(true false is_bool);
+use Carp         qw(confess);
+
+use Parse::RecDescent;
+
+my @used_ports = ();
+
+# Note that this isn't a complete libconfig parser; it's just good enough for our purposes.
+my $parser = Parse::RecDescent->new(<<'EOF');
+parse: <skip: qr{(?xs:
+          (?: \s+                       # Whitespace
+          |   \# [^\n]* \n?             # End of line comment
+          )
+       )*}>
+       configuration
+       { $item[2] }
+
+configuration : setting(s?) {my %res; for my $i (@{$item[1]}) {%res = (%res,%{$i}) }; \%res}
+
+name :	/[a-zA-Z][a-zA-Z_0-9-]*/ { $item[1]; }
+
+boolean : /true|false/i {$item[1] =~ /true/i; }
+string :	/"[^"]*"/ { $item[1] =~ s/^"//; $item[1] =~ s/"$//; $item[1] }
+integer :	/[-+]?[0-9]+/ { bless \int($item[1]), $item[0]; }
+integer64 :	/[-+]?[0-9]+L(L)?/ { bless \int($item[1]), $item[0]; }
+bin :	/0[bB]([01]){1,32}/ { $item[1]; }
+bin64 :	/0[bB]([01]){1,64}L(L)?/ { $item[1]; }
+oct :	/0[oOqQ]([0-7]){1,10}/ { $item[1]; }
+oct64 :	/0[oOqQ]([0-7]){1,21}L(L)?/ { $item[1] }
+hex :	/0[xX]([0-9A-Fa-f]){1,8}/ { $item[1] }
+hex64 :	/0[xX]([0-9A-Fa-f]){1,16}L(L)?/ { $item[1] }
+float :	/([-+]?[0-9]*\\.[0-9]*(e[-+]?[0-9]+)?)|([-+]([0-9]+)(\\.[0-9]*)?[eE][-+]?[0-9]+)/i { float($item[1]) }
+scalar_value : boolean {$item[1]} | integer {$item[1]} | integer64 | bin | bin64 | oct | oct64 | hex | hex64 | float | string {$item[1]}
+
+list : "(" value ("," value {$item[2]})(s?) /,?/ ")" { [ $item[2], @{$item[3]} ] }
+group : "{" setting(s?) "}" { my %res; for my $s (@{$item[2]}) {%res = (%res,%{$s})}; \%res; }
+value : scalar_value {$item[1]} | list  { $item[1] } |group { $item[1] } | array {$item[1]}
+array : "[" scalar_value ("," scalar_value {$item[2]})(s?) /,?/ "]" { [ $item[2],@{$item[3]} ] }
+
+setting : name ':' value ';' { my %f = ($item[1] => $item[3]); \%f }
+
+EOF
+
+has 'config_values' => ( is => 'rw' );
+has 'cfg_file'      => ( is => 'rw', isa => 'Str' );
+
+=over
+
+=item read_file
+
+Read a libconfig-style configuration file in, setting cfg_file. As a
+hacky side-effect, change all ports to random ports which are
+currently not being listened on and write to the config file.
+
+=cut
+
+sub read_file {
+    my ( $self, $filename ) = @_;
+
+    # read in the configuration file
+    $self->cfg_file($filename);
+
+    # actually read in the file
+    my $fh = IO::File->new( $self->cfg_file, 'r' )
+      or die "Unable to open $self->cfg_file for reading:$!";
+
+    local $/;
+    my $file = <$fh>;
+    $fh->close();
+
+    my $config = $parser->parse($file);
+
+    # change all of the ports to be un-occupied ports
+    for my $section (qw(listen protocols)) {
+        if ( not exists $config->{$section} ) {
+            next;
+        }
+        for my $element ( @{ $config->{$section} } ) {
+            if ( exists $element->{port} ) {
+                $element->{port} = get_unused_port();
+            }
+            if (exists $element->{host} and $element->{host} eq "ip4-localhost") {
+                $element->{host} = "127.0.0.1";
+            }
+        }
+    }
+
+    $self->config_values($config);
+
+    $self->write_file( $self->cfg_file );
+
+}
+
+sub format_value {
+    my ($value) = @_;
+    my $ret = "";
+    if ( ref($value) eq 'ARRAY' ) {
+        my @braces = ( '[', ']' );
+        my $ending = ",";
+        if ( @{$value} ) {
+            if ( ref( $value->[0] ) eq 'HASH' ) {
+                @braces = ( "\n(\n", "\n)" );
+                $ending .= "\n";
+            }
+        }
+        $ret .= $braces[0];
+        for my $i ( 0 .. $#{$value} ) {
+            my $v = $value->[$i];
+            $ret .= format_value($v);
+            if ( $i < $#{$value} ) {
+                $ret .= $ending;
+            }
+        }
+        $ret .= $braces[1];
+    }
+    elsif ( ref($value) eq 'HASH' ) {    # it's a hash, output it.
+        $ret .= "{";
+        while ( my ( $k, $v ) = each %{$value} ) {
+            $ret .= format_key_value( $k, $v, 0 );
+        }
+        $ret .= "}";
+    }
+    elsif ( is_bool($value) ) {          # it's a bool
+        $ret .= $value ? "true" : "false";
+    }
+    elsif ( ref($value) =~ /integer/ ) {    # it's a number
+        $ret .= ${$value};
+    }
+    elsif ( not defined $value ) {
+        confess "Value not defined, cannot format.";
+    }
+    else {                                   # it's a string
+        $ret .= qq{"$value"};
+    }
+    return $ret;
+}
+
+sub format_key_value {
+    my ( $key, $value, $newline ) = @_;
+
+    my $ret = "";
+    if ( not defined $newline ) {
+        $newline = 1;
+    }
+
+    $ret .= "${key}: " . format_value($value) . ";";
+    if ($newline) {
+        $ret .= "\n";
+    }
+    else {
+        $ret .= " ";
+    }
+    return $ret;
+}
+
+sub write_file {
+    my ( $self, $filename ) = @_;
+
+    my $fh = IO::File->new( $filename, 'w' );
+    for my $key ( keys %{ $self->config_values } ) {
+        my $value = $self->config_values->{$key};
+        print {$fh} format_key_value( $key, $value );
+    }
+    $fh->close();
+}
+
+sub value {
+    my ( $self, $key ) = @_;
+    if ( not exists $self->config_values->{$key} ) {
+        use Data::Dumper;
+        print STDERR Dumper( $self->config_values );
+        die "Missing key '$key' in config";
+    }
+    return $self->config_values->{$key};
+}
+
+sub lookup_value {
+    my ( $self, $key ) = @_;
+    my $val = $self->value($key);
+    if (ref($val) =~ /integer/) {
+        return ${$val};
+    }
+    return $val;
+}
+
+sub get_unused_port {
+    for my $attempt ( 0 .. 9 ) {
+        my $sock = IO::Socket::INET->new(
+            Listen    => 1,
+            LocalAddr => 'localhost',
+            ReuseAddr => 1,
+        );
+        my $port = $sock->sockport();
+        $sock->shutdown(2);
+        if ( none { $port == $_ } @used_ports ) {
+            push @used_ports, $port;
+            return $port;
+        }
+    }
+    die "Unable to find an unused port after 10 tries";
+
+}
+
+=back
+
+=cut
+
+1;
--- /dev/null
+++ b/t/test_libfakeconfig.pm
@@ -0,0 +1,46 @@
+
+use Test::More;
+use strictures 2;
+use lib qw(.);
+use IO::File;
+use FakeLibconfig;
+use v5.36;
+use builtin    qw(true);
+
+
+plan tests => 8;
+
+my $conf = FakeLibconfig->new();
+
+my $fh = IO::File->new('temp.cfg','w');
+print {$fh} <<'EOF';
+an_integer: 1;
+a_bool: true;
+listen:
+(
+{ port: "80";},
+{ port: "80";},
+);
+EOF
+$fh->close();
+$conf->read_file('temp.cfg');
+
+# validate that an integer is parsed correctly
+ok($conf->lookup_value('an_integer') eq 1,"Integer returns 1");
+# validate that a boolean is parsed correctly
+ok($conf->lookup_value('a_bool') eq true,"Bool returns true");
+# validate that the ports have changed
+ok($conf->lookup_value('listen')->[0]{'port'} ne 80,"Port is no longer 80");
+my $old_port = $conf->lookup_value('listen')->[0]{'port'};
+
+# reread the file in
+$conf->read_file('temp.cfg');
+
+# validate that an integer is parsed correctly
+ok($conf->lookup_value('an_integer') eq 1,"Integer returns 1");
+# validate that a boolean is parsed correctly
+ok($conf->lookup_value('a_bool') eq true,"Bool returns true");
+# validate that the ports have changed
+ok(defined $conf->lookup_value('listen')->[0]{'port'},"Port is defined");
+ok($conf->lookup_value('listen')->[0]{'port'} ne 80,"Port is no longer 80");
+ok($conf->lookup_value('listen')->[0]{'port'} ne $old_port,"Port is no longer the old port");
