{"id":13820921,"url":"https://github.com/travisghansen/kubernetes-pfsense-controller","last_synced_at":"2025-07-30T05:32:48.125Z","repository":{"id":51713362,"uuid":"148936576","full_name":"travisghansen/kubernetes-pfsense-controller","owner":"travisghansen","description":"Integrate Kubernetes and pfSense","archived":false,"fork":false,"pushed_at":"2023-04-15T19:14:45.000Z","size":168,"stargazers_count":204,"open_issues_count":4,"forks_count":22,"subscribers_count":18,"default_branch":"master","last_synced_at":"2025-04-09T23:16:39.143Z","etag":null,"topics":["api","client","cluster","controller","dns","firewall","haproxy","haproxy-configuration","ingress","ingress-controller","ingress-dns","k8s","kubernetes","load-balancer","metallb","pfsense","php"],"latest_commit_sha":null,"homepage":null,"language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/travisghansen.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-09-15T20:14:20.000Z","updated_at":"2025-03-15T09:26:26.000Z","dependencies_parsed_at":"2024-05-28T19:37:30.417Z","dependency_job_id":null,"html_url":"https://github.com/travisghansen/kubernetes-pfsense-controller","commit_stats":{"total_commits":72,"total_committers":5,"mean_commits":14.4,"dds":0.05555555555555558,"last_synced_commit":"c4fe0964918d10b8188dc99afe7664e5efb8b13b"},"previous_names":[],"tags_count":33,"template":false,"template_full_name":null,"purl":"pkg:github/travisghansen/kubernetes-pfsense-controller","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/travisghansen%2Fkubernetes-pfsense-controller","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/travisghansen%2Fkubernetes-pfsense-controller/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/travisghansen%2Fkubernetes-pfsense-controller/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/travisghansen%2Fkubernetes-pfsense-controller/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/travisghansen","download_url":"https://codeload.github.com/travisghansen/kubernetes-pfsense-controller/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/travisghansen%2Fkubernetes-pfsense-controller/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":267815187,"owners_count":24148356,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-30T02:00:09.044Z","response_time":70,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api","client","cluster","controller","dns","firewall","haproxy","haproxy-configuration","ingress","ingress-controller","ingress-dns","k8s","kubernetes","load-balancer","metallb","pfsense","php"],"created_at":"2024-08-04T08:01:11.670Z","updated_at":"2025-07-30T05:32:48.070Z","avatar_url":"https://github.com/travisghansen.png","language":"PHP","funding_links":[],"categories":["PHP","Operators vs Controllers"],"sub_categories":["Networking"],"readme":"![Image](https://img.shields.io/docker/pulls/travisghansen/kubernetes-pfsense-controller.svg)\n![Image](https://img.shields.io/github/actions/workflow/status/travisghansen/kubernetes-pfsense-controller/main.yml?branch=master\u0026style=flat-square)\n\n# Intro\n[kubernetes-pfsense-controller (kpc)](https://github.com/travisghansen/kubernetes-pfsense-controller) works hard to keep\n[pfSense](https://www.pfsense.org/) and [Kubernetes](https://kubernetes.io/) in sync and harmony.  The primary focus is\nto facilitate a first-class Kubernetes cluster by integrating and/or implementing features that generally do not come\nwith bare-metal installation(s).\n\nThis is generally achieved using the standard Kubernetes API along with the xmlrpc API for pfSense.  Speaking broadly\nthe Kubernetes API is `watch`ed and appropriate updates are sent to pfSense (`config.xml`) via xmlrpc calls along with\nappropriate reload/restart/update/sync actions to apply changes.\n\nPlease note, this controller is not designed to run multiple instances simultaneously (ie: do NOT crank up the replicas).\n\nDisclaimer: this is new software bound to have bugs.  Please make a backup before using it as it may eat your\nconfiguration.  Having said that, all known code paths appear to be solid and working without issue.  If you find a bug,\nplease report it! \n\nUpdated disclaimer: this software is no longer very new, but is still bound to have bugs. Continue to make backups as\nappropriate :) Having said that, it's been used for multiple years now on several systems and has yet to do anything\nevil.\n\n# Installation\n\nVarious files are available in the `deploy` directory of the project, alter to your needs and `kubectl apply`.\n\nAlternatively, a helm repository is provided for convenience:\n\n```\nhelm repo add kubernetes-pfsense-controller https://travisghansen.github.io/kubernetes-pfsense-controller-chart/\nhelm repo update\n\n# create your own values.yaml file and edit as appropriate\n# https://github.com/travisghansen/kubernetes-pfsense-controller-chart/blob/master/stable/kubernetes-pfsense-controller/values.yaml\nhelm upgrade \\\n--install \\\n--create-namespace \\\n--namespace kpc \\\n--values values.yaml \\\nkpc-primary \\\nkubernetes-pfsense-controller/kubernetes-pfsense-controller\n```\n\n## Support Matrix\n\nGenerally speaking `kpc` tracks the most recent versions of both kubernetes and pfSense. Having said that reasonable\nattempts will be made to support older versions of both.\n\n`kpc` currently works with any `2.4+` (known working up to `2.5.2`) version of pfSense and probably very old kubernetes\nversions (known working up to `1.22`).\n\n# Plugins\nThe controller is comprised of several plugins that are enabled/disabled/configured via a Kubernetes ConfigMap.  Details\nabout each plugin follows below.\n\n## metallb\n[MetalLB](https://metallb.universe.tf/) implements `LoadBalancer` type `Service`s in Kubernetes.  This is done via any\ncombination of Layer2 or BGP type configurations.  Layer2 requires no integration with pfSense, however, if you want to\nleverage the BGP implementation you need a BGP server along with neighbor configuration.  `kpc` *dynamically* updates\nbgp neighbors for you in pfSense by continually monitoring cluster `Node`s.\n\nWhile this plugin is *named* `metallb` it does not **require** MetalLB to be installed or in use. It can be used with\n`kube-vip` or any other service that requires BGP peers/neighbors.\n\nThe plugin assumes you've already installed openbgp or frr and configured it as well as created a `group` to use with\nMetalLB.\n\n```yaml\n      metallb:\n        enabled: true\n        nodeLabelSelector:\n        nodeFieldSelector:\n        # pick 1 implementation\n        # bgp-implementation: openbgp\n        bgp-implementation: frr\n        options:\n          frr:\n            template:\n              peergroup: metallb\n\n          openbgp:\n            template:\n              md5sigkey:\n              md5sigpass:\n              groupname: metallb\n              row:\n                - parameters: announce all\n                  parmvalue:\n```\n\n## haproxy-declarative\n`haproxy-declarative` plugin allows you to declaratively create HAProxy frontend/backend definitions as `ConfigMap`\nresources in the cluster.  When declaring backends however, the pool of servers can/will be dynamically created/updated\nbased on cluster nodes.  See [declarative-example.yaml](examples/declarative-example.yaml) for an example.\n\n```yaml\n      haproxy-declarative:\n        enabled: true\n```\n\n## haproxy-ingress-proxy\n`haproxy-ingress-proxy` plugin allows you to mirror cluster ingress rules handled by an ingress controller to HAProxy\nrunning on pfSense.  If you run pfSense on the network edge with non-cluster services already running, you now can\ndynamically inject new rules to route traffic into your cluster while simultaneously running non-cluster services.\n\nTo achieve this goal, new 'shared' HAProxy frontends are created and attached to an **existing** HAProxy frontend.  Each\ncreated frontend should also set an existing backend.  Note that existing frontend(s)/backend(s) can be created manually\nor using the `haproxy-declarative` plugin.\n\nWhen creating the parent frontend(s) please note that the selected type should be `http / https(offloading)` to fully\nsupport the feature. If type `ssl / https(TCP mode)` is selected (`SSL Offloading` may be selected or not in the\n`External address` table) `sni` is used for routing logic and **CANNOT** support path-based logic which implies a 1:1\nmapping between `host` entries and backing `service`s. Type `tcp` will not work and any `Ingress` resources that would\nbe bound to a frontend of this type are ignored.\n\nCombined with `haproxy-declarative` you can create a dynamic backend service (ie: your ingress controller) and\nsubsequently dynamic frontend services based off of cluster ingresses.  This is generally helpful when you cannot or do\nnot for whatever reason create wildcard frontend(s) to handle incoming traffic in HAProxy on pfSense.\n\nOptionally, on the ingress resources you can set the following annotations: `haproxy-ingress-proxy.pfsense.org/frontend`\nand `haproxy-ingress-proxy.pfsense.org/backend` to respectively set the frontend and backend to override the defaults.\n\nIn advanced scenarios it is possible to provide a template definition of the shared frontend using the\n`haproxy-ingress-proxy.pfsense.org/frontendDefinitionTemplate` annotation (see\nhttps://github.com/travisghansen/kubernetes-pfsense-controller/issues/19#issuecomment-1416576678).\n\n```yaml\n      haproxy-ingress-proxy:\n        enabled: true\n        ingressLabelSelector:\n        ingressFieldSelector:\n        # works in conjunction with the ingress annotation 'haproxy-ingress-proxy.pfsense.org/enabled'\n        # if defaultEnabled is empty or true, you can disable specific ingresses by setting the annotation to false\n        # if defaultEnabled is false, you can enable specific ingresses by setting the annotation to true\n        defaultEnabled: true\n        # can optionally be comma-separated list if you want the same ingress to be served by multiple frontends\n        defaultFrontend: http-80\n        defaultBackend: traefik\n        #allowedHostRegex: \"/.*/\"\n```\n\n## DNS Helpers\n`kpc` provides various options to manage DNS entries in pfSense based on cluster state.  Note that these options can be\nused in place of or in conjunction with [external-dns](https://github.com/kubernetes-incubator/external-dns) to support\npowerful setups/combinations.\n\n### pfsense-dns-services\n`pfsense-dns-services` watches for services of type `LoadBalancer` that have the annotation `dns.pfsense.org/hostname`\nwith the value of the desired hostname (optionally you may specifiy a comma-separated list of hostnames).  `kpc` will\ncreate the DNS entry in unbound/dnsmasq.  Note that to actually get  an IP on these services you'll likely need\n`MetalLB` deployed in the cluster (regardless of the `metallb` plugin running or not).\n\n```yaml\n      pfsense-dns-services:\n        enabled: true\n        serviceLabelSelector:\n        serviceFieldSelector:\n        #allowedHostRegex: \"/.*/\"\n        dnsBackends:\n          dnsmasq:\n            enabled: true\n          unbound:\n            enabled: true\n```\n\n### pfsense-dns-ingresses\n`pfsense-dns-ingresses` watches ingresses and automatically creates DNS entries in unbound/dnsmasq. This requires proper\nsupport from the ingress controller to set IPs on the ingress resources.\n\n```yaml\n      pfsense-dns-ingresses:\n        enabled: true\n        ingressLabelSelector:\n        ingressFieldSelector:\n        # works in conjunction with the ingress annotation 'dns.pfsense.org/enabled'\n        # if defaultEnabled is empty or true, you can disable specific ingresses by setting the annotation to false\n        # if defaultEnabled is false, you can enable specific ingresses by setting the annotation to true\n        defaultEnabled: true\n        #allowedHostRegex: \"/.*/\"\n        dnsBackends:\n          dnsmasq:\n            enabled: true\n          unbound:\n            enabled: true\n```\n\n### pfsense-dns-haproxy-ingress-proxy\n`pfsense-dns-haproxy-ingress-proxy` monitors the HAProxy rules created by the `haproxy-ingress-proxy` plugin and creates\nhost aliases for each entry.  To do so you create an arbitrary host in unbound/dnsmasq (something like\n`\u003cfrontend name\u003e.k8s`) and bind that host to the frontend through the config option `frontends.\u003cfrontend name\u003e`.  Any\nproxy rules created for that frontend will now automatically get added as aliases to the configured `hostname`.  Make\nsure the static `hostname` created in your DNS service of choice points to the/an IP bound to the corresponding\n`frontend`.\n\n```yaml\n      pfsense-dns-haproxy-ingress-proxy:\n        enabled: true\n        # NOTE: this regex is in *addition* to the regex applied to the haproxy-ingress-proxy plugin\n        #allowedHostRegex: \"/.*/\"\n        dnsBackends:\n          dnsmasq:\n            enabled: true\n          unbound:\n            enabled: true\n        frontends:\n          http-80:\n            hostname: http-80.k8s\n          primary_frontend_name2:\n            hostname: primary_frontend_name2.k8s\n```\n\n# Notes\n`regex` parameters are passed through php's `preg_match()` method, you can test your syntax using that.  Also note that\nif you want to specify a regex ending (`$`), you must escape it in yaml as 2 `$`\n(ie: `#allowedHostRegex: \"/.example.com$$/\"`).\n\n`kpc` stores it's stateful data in the cluster as a ConfigMap (kube-system.kubernetes-pfsense-controller-store by\ndefault).  You can review the data there to gain understanding into what the controller is managing.\n\nYou may need/want to bump up the `webConfigurator` setting for `Max Processes` to ensure enough simultaneous connections\ncan be established.  Each `kpc` instance will only require 1 process (ie: access to the API is serialized by `kpc`).\n\n## Links\n * https://medium.com/@ipuustin/using-metallb-as-kubernetes-load-balancer-with-ubiquiti-edgerouter-7ff680e9dca3\n * https://miek.nl/2017/december/16/a-k8s-lb-using-arp/\n\n# TODO\n 1. base64 advanced fields (haproxy)\n 1. taint haproxy config so it shows 'apply' button in interface?\n 1. _index and id management\n 1. ssl certs name/serial\n 1. build docker images\n 1. create manifests\n 1. ensure pfsync items are pushed as appropriate\n 1. perform config rollbacks when appropriate?\n 1. validate configuration(s) to ensure proper schema\n\n# Development\n\n## check store values\n\n```\nkubectl -n kube-system get configmaps kubernetes-pfsense-controller-store -o json | jq -crM '.data.\"haproxy-declarative\"' | jq .\nkubectl -n kube-system get configmaps kubernetes-pfsense-controller-store -o json | jq -crM '.data.\"metallb\"' | jq .\n...\n```\n\n## HAProxy\nXML config structure (note that `ha_backends` is actually frontends...it's badly named):\n```yaml\nhaproxy\n   ha_backends\n     item\n     item\n     ...\n   ha_pools\n     item\n       ha_servers\n         item\n         item\n         ...\n     item\n     ...\n```\n\n### Links\n * https://github.com/pfsense/FreeBSD-ports/blob/devel/net/pfSense-pkg-haproxy-devel/files/usr/local/pkg/haproxy/haproxy.inc\n\n## Links\n * https://github.com/pfsense/pfsense/blob/master/src/usr/local/www/xmlrpc.php\n * https://clouddocs.f5.com/products/connectors/k8s-bigip-ctlr/v1.5/\n * https://github.com/schematicon/validator-php\n * https://kubernetes.io/docs/concepts/overview/working-with-objects/kubernetes-objects/\n * https://kubernetes.io/docs/concepts/overview/working-with-objects/field-selectors/\n * https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/\n * https://github.com/MacFJA/PharBuilder\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftravisghansen%2Fkubernetes-pfsense-controller","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftravisghansen%2Fkubernetes-pfsense-controller","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftravisghansen%2Fkubernetes-pfsense-controller/lists"}