diff --git a/html/cgi-bin/haproxy.cgi b/html/cgi-bin/haproxy.cgi
new file mode 100644
index 000000000..dbc42ce28
--- /dev/null
+++ b/html/cgi-bin/haproxy.cgi
@@ -0,0 +1,289 @@
+#!/usr/bin/perl
+###############################################################################
+# #
+# IPFire.org - A linux based firewall #
+# Copyright (C) 2007-2023 IPFire Team #
+# Copyright (C) 2024 BPFire #
+# #
+# This program is free software: you can redistribute it and/or modify #
+# it under the terms of the GNU General Public License as published by #
+# the Free Software Foundation, either version 3 of the License, or #
+# (at your option) any later version. #
+# #
+# This program is distributed in the hope that it will be useful, #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
+# GNU General Public License for more details. #
+# #
+# You should have received a copy of the GNU General Public License #
+# along with this program. If not, see . #
+# #
+###############################################################################
+
+use strict;
+use experimental 'smartmatch';
+
+# enable only the following on debugging purpose
+#use warnings;
+#use CGI::Carp 'fatalsToBrowser';
+
+require '/var/ipfire/general-functions.pl';
+require "${General::swroot}/lang.pl";
+require "${General::swroot}/header.pl";
+#workaround to suppress a warning when a variable is used only once
+my @dummy = ( ${Header::colouryellow} );
+undef (@dummy);
+
+our %hasettings=();
+our %netsettings=();
+my %mainsettings=();
+my %timesettings=();
+my $setting = "${General::swroot}/haproxy/settings";
+my $configsetting = "${General::swroot}/haproxy/config";
+my $loxilbipfile = "${General::swroot}/loxilb/ipconfigfile";
+ # because we need commas in the some data
+my $errormessage = '';
+#remove 'ENABLE_HA' from '/var/ipfire/haproxy/settings' as it could affect haproxy running state
+my @nosaved=('ENABLE_HAPROXY');
+my %color = ();
+
+$hasettings{'ENABLE_HAPROXY'} = 'off';
+
+&Header::showhttpheaders();
+my @MODE= ('tcp', 'http');
+
+#Settings1 for the first screen box
+$hasettings{"mode"} = '';
+$hasettings{"bind"} = '';
+
+# Read Ipcop settings
+&General::readhash("${General::swroot}/ethernet/settings", \%netsettings);
+&General::readhash("${General::swroot}/main/settings", \%mainsettings);
+&General::readhash("/srv/web/ipfire/html/themes/ipfire/include/colors.txt", \%color);
+
+#Get GUI values
+&Header::getcgihash(\%hasettings);
+
+if ($hasettings{'ACTION'} eq $Lang::tr{'enable'})
+{
+ #remove @nosaved from $hasettings before writehash to 'configsettings' file since 'configsetting' is only for haproxy running state
+ my @nosaved = ("mode", "bind", "ENABLE_HAPROXY");
+ map (delete ($hasettings{$_}) ,(@nosaved));
+ &General::writehash("$configsetting", \%hasettings);
+ if ($hasettings{'ENABLE_HAPROXY'} eq 'on') {
+ &General::system('/usr/bin/touch', "${General::swroot}/haproxy/enable_ha");
+ &General::system('/usr/local/bin/haproxyctrl', 'start');
+ } else {
+ &General::system('/usr/local/bin/haproxyctrl', 'stop');
+ unlink "${General::swroot}/haproxy/enable_ha";
+ }
+}
+
+# Check Settings1 first because they are needed by &buildconf
+if ($hasettings{'ACTION'} eq $Lang::tr{'save'}) {
+
+ if ($hasettings{"mode"} eq '') {
+ $errormessage = "mode" . " is $Lang::tr{'required field'}";
+ goto ERROR;
+ }
+ if ($hasettings{"bind"} eq '') {
+ $errormessage = "bind" . " is $Lang::tr{'required field'}";
+ goto ERROR;
+ }
+
+ map (delete ($hasettings{$_}) ,@nosaved,'ACTION','KEY1','KEY2','q'); # Must not be saved
+ &General::writehash($setting, \%hasettings); # Save good settings
+ $hasettings{'ACTION'} = $Lang::tr{'save'}; # create an 'ACTION'
+ map ($hasettings{$_} = '',@nosaved,'KEY1','KEY2'); # and reinit vars to empty
+ &buildconf;
+ ERROR:
+}
+
+if ($hasettings{'ACTION'} eq '' ) { # First launch from GUI
+
+ $hasettings{"mode"} = '';
+ $hasettings{"bind"} = '';
+}
+
+### START PAGE ###
+&Header::openpage($Lang::tr{'haproxy configuration'}, 1, $Header::extraHead);
+&Header::openbigbox('100%', 'left', '', $errormessage);
+
+if ($errormessage) {
+ &Header::openbox('100%', 'left', $Lang::tr{'error messages'});
+ print "$errormessage \n";
+ &Header::closebox();
+}
+
+# Read configuration file.
+&General::readhash("$configsetting", \%hasettings);
+
+# Checkbox pre-selection.
+my $checked;
+if ($hasettings{'ENABLE_HA'} eq "on") {
+ $checked = "checked='checked'";
+}
+
+my $sactive = "