{"id":20394837,"url":"https://github.com/tnolet/haproxy-rest","last_synced_at":"2025-04-12T12:13:06.836Z","repository":{"id":20119372,"uuid":"23389224","full_name":"tnolet/haproxy-rest","owner":"tnolet","description":"REST interface for HAproxy written in GO","archived":false,"fork":false,"pushed_at":"2015-12-21T17:49:51.000Z","size":20412,"stargazers_count":77,"open_issues_count":2,"forks_count":19,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-04-12T12:13:00.321Z","etag":null,"topics":["go","haproxy"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tnolet.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-08-27T12:41:57.000Z","updated_at":"2023-08-18T11:50:06.000Z","dependencies_parsed_at":"2022-08-31T05:21:27.734Z","dependency_job_id":null,"html_url":"https://github.com/tnolet/haproxy-rest","commit_stats":null,"previous_names":[],"tags_count":19,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tnolet%2Fhaproxy-rest","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tnolet%2Fhaproxy-rest/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tnolet%2Fhaproxy-rest/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tnolet%2Fhaproxy-rest/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tnolet","download_url":"https://codeload.github.com/tnolet/haproxy-rest/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248565082,"owners_count":21125418,"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","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":["go","haproxy"],"created_at":"2024-11-15T03:54:27.772Z","updated_at":"2025-04-12T12:13:06.817Z","avatar_url":"https://github.com/tnolet.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# HAproxy-rest - DEPRECATED\n\n\u003e This repo is no longer maintained. Haproxy-rest is surpassed by [Vamp Router](https://github.com/magneticio/vamp-router)\n\nHAproxy-rest started as a REST interface for HAproxy. Now it's much more. Features are:\n\n-   Update the config through REST or through Zookeeper\n-   Run in full load balancer mode, or simple local proxy mode\n-   Adjust server weight\n-   Get statistics on frontends, backends and servers\n-   Stream statistics to Kafka\n-   Set ACL's *(experimental)*\n-   Set HTTP \u0026 TCP Spike limiting *(experimental)*\n\n\n*Important* : Currently, HAproxy-rest does NOT check validity of the HAproxy command, ACLs and configs submitted to it.\nSubmitting a config where a frontend references a non-existing backend will be accepted by the REST api but crash HAproxy.\n\n## Installing: the easy Docker way\n\nStart up an instance with all defaults and bind it to the local network interface\n\n    $ docker run --net=host tnolet/haproxy-rest\n\n    2014-11-20 21:04:31 INFO   ==\u003e Starting in Load Balancer mode \u003c==\n    2014-11-20 21:04:31 WARN  Unable to load persistent config from disk\n    2014-11-20 21:04:31 WARN  Loading example config\n    2014-11-20 21:04:31 INFO  Pid file exists, proceeding with startup...\n    2014-11-20 21:04:31 INFO  HaproxyReload: 30300\n    2014-11-20 21:04:31 INFO  Starting REST server\n    [GIN-debug] POST  /v1/backend/:name/servers/:server/weight/:weight --\u003e main.func·003 (4 handlers)\n    [GIN-debug] POST  /v1/frontend/:name/acls/:acl/:pattern --\u003e main.func·004 (4 handlers)\n    [GIN-debug] GET   /v1/frontend/:name/acls   --\u003e main.func·005 (4 handlers)\n    [GIN-debug] GET   /v1/stats                 --\u003e main.func·006 (4 handlers)\n    [GIN-debug] GET   /v1/stats/backend         --\u003e main.func·007 (4 handlers)\n    [GIN-debug] GET   /v1/stats/frontend        --\u003e main.func·008 (4 handlers)\n    [GIN-debug] GET   /v1/stats/server          --\u003e main.func·009 (4 handlers)\n    [GIN-debug] GET   /v1/config                --\u003e main.func·010 (4 handlers)\n    [GIN-debug] POST  /v1/config                --\u003e main.func·011 (4 handlers)\n    [GIN-debug] GET   /v1/info                  --\u003e main.func·012 (4 handlers)\n    [GIN-debug] Listening and serving HTTP on 0.0.0.0:10001\n    \nThe default ports are:\n\n    10001      REST Api (for config, stats etc)  \n    1988       built-in Haproxy stats\n    \n## Changing ports\n\nYou could change the REST api port by adding the `-port` flag\n\n    $ docker run --net=host tnolet/haproxy-rest -port=1234\n\nOr by exporting an environment variable `PORT0`. When deploying with Marathon 0.7.0, this is done automatically\n     \n     $ export PORT0=12345\n     $ docker run --net=host tnolet/haproxy-rest\n\n## Getting statistics\n\nStatistics are published in two different ways: straight from the REST interface and as Kafka topics\n\n### Stats via REST\n     \nGrab some stats from the `/stats` endpoint. Notice the IP address. This is [boot2docker](https://github.com/boot2docker/boot2docker)'s address on my Macbook. I'm using [httpie](https://github.com/jakubroztocil/httpie) instead of curl.\n\n    $ http http://192.168.59.103:10001/v1/stats\n    HTTP/1.1 200 OK\n    \n    [\n        {\n            \"act\": \"\", \n            \"bck\": \"\", \n            \"bin\": \"3572\", \n            \"bout\": \"145426\", \n            \"check_code\": \"\", \n            \"check_duration\": \"\", \n            \"check_status\": \"\", \n            \"chkdown\": \"\", \n            \"chkfail\": \"\", \n            \"cli_abrt\": \"\", \n            ...\n            \nValid endpoints are `stats/frontend`, `stats/backend` and `stats/server`. The `/stats` endpoint gives you all of them\nin one go.\n\n### Stats via Kafka\n\nStatistics are also published as Kafka topics. Configure a Kafka endpoint using the `-kakfaHost` and `-kafkaPort` flags.\nStats are published as the following topic:\n\n- loadbalancer.all\n\nThe messages on that topic are json strings, where the \"name\" key indicates what metric type from which proxy\n you are dealing with, i.e.:\n\n    {\n     \"name\": \"testbe.test_be_1.rate\",   # The rate for server test_be_1 for proxy testbe\n     \"value\": \"2\",                      # The value of the metric\n     \"timestamp\": 1413546338            # The timestamp in Unix epoch\n    }\n    {\n     \"name\": \"testbe.test_be_1.rate_lim\",\n     \"value\": \"12\",\n     \"timestamp\": 1413546338\n    }\n    { \"name\": \"testbe.test_be_1.rate_max\",\n     \"value\": \"30\",\n     \"timestamp\": 1413546338\n    }\n\n__Note:__ currently, not all Haproxy metric types are sent to Kafka. At this moment, the list is hardcoded as a `wantedMetrics` slice:\n    \n    wantedMetrics  := []string{ \"Scur\", \"Qcur\",\"Smax\",\"Slim\",\"Weight\",\"Qtime\",\"Ctime\",\"Rtime\",\"Ttime\",\"Req_rate\",\"Req_rate_max\",\"Req_tot\",\"Rate\",\"Rate_lim\",\"Rate_max\" }\n\nFor an explanation of the metric types, please read [this](http://cbonte.github.io/haproxy-dconv/configuration-1.5.html#9.1)            \n### Updating the configuration via REST\n\nPost a configuration. You can use the example file `resources/config_example.json`\n\n    $ http POST http://192.168.59.103:10001/v1/config \u003c resources/config_example.json \n    HTTP/1.1 200 OK\n     \n    Ok\n    \nUpdate the weight of some backend server\n\n    $ http POST http://192.168.59.103:10001/v1/backend/testbe/servers/test_be_1/weight/20\n    HTTP/1.1 200 OK\n    \n    Ok\n\n### Running as local proxy + Zookeeper\n\nAt [magnetic.io](http://magnetic.io), we use Haproxy-rest running in local proxy mode for simple service discovery.\nWhen you start HAproxy-rest with `-mode=localproxy`, only very simple binds are set up between two host:port pairs.\nNo frontends, no backends, no ACL's, no nothing.  \n\n__Note:__ local proxy mode requires a Zookeeper ensemble to function: local proxy only gets its config from a Zookeeper\nnode.  \n\nHaproxy-rest will watch for changes to the key: `/magnetic/localproxy`. You can set your own namespace using the `-zooConKey` flag.  The `/localproxy` part is hardcoded.\nTo this node you need to publish a full configuration in JSON format. Starting up a localproxy using Zookeeper\nlooks like this:  \n\n    -mode=localproxy -zooConString=10.161.63.88:2181,10.189.106.106:2181,10.5.99.23:2181\n    \nThis will result in config similar to the following JSON. Notice the `frontends` and `backends` are empty.\nThere is just a simple array of services that bind a port to an endpoint.\n\n    {\n        frontends: [ ],\n        backends: [ ],\n        services: [\n            {\n                name: \"vrn-development-service-4d7a24cd\",\n                bindPort: 22500,\n                endPoint: \"10.224.236.38\",\n                mode: \"tcp\"\n            }\n        ]\n    }\n    \n## Setting Frontends\n\nThe frontend is the basic listening port or unix socket. Here's an example of a basic HTTP frontend:\n\n    {\n        \"name\" : \"test_fe_1\",\n        \"bindPort\" : 8000,\n        \"bindIp\" : \"0.0.0.0\",\n        \"defaultBackend\" : \"testbe1\",\n        \"mode\" : \"http\",\n        \"options\" : {\n            \"httpClose\" :  true\n    }\n\nYou can also setup the frontend to listen on Unix sockets. _Note_: you have to explicitly declare the protocol\ncoming over the socket. On this example we declare the Haproxy specific `proxy` protocol.\n\n    {\n        \"name\" : \"test_fe_1\",\n        \"mode\" : \"http\",\n        \"defaultBackend\" : \"testbe2\",\n        \"unixSock\" : \"/tmp/vamp_testbe2_1.sock\",\n        \"sockProtocol\" : \"accept-proxy\"\n    }\n    \n### Setting ACL's\n    \nYou can set ACLs as part of a frontend's configuration and use these ACLs to route traffic to different backends.\nThe example below will route all Internet Explorer users to a different backend. You can update this on the fly\nwithout loosing sessions or causing errors due to Haproxy's smart restart mechanisms.\n\n    {\n        \"frontends\" : [\n            {\n                \"name\" : \"test_fe_1\",                               # declare a frontend\n                ...                                                 # some stuff left out for brevity\n                \"acls\" : [\n                    {\n                        \"name\" : \"uses_msie\",                       # set an ACL by giving it a name and some pattern. \n                        \"backend\" : \"testbe2\",                      # set the backend to send traffic to\n                        \"pattern\" : \"hdr_sub(user-agent) MSIE\"      # This pattern matches all HTTP requests that have\n                    }                                               # \"MSIE\" in their User-Agent header                 \n\n                ]\n            }\n        ]\n    }\n\n### Rate / Spike limiting \n\nYou can set limits on specific connection rates for HTTP and TCP traffic. This comes in handy if you want to protect\nyourself from abusive users or other spikes. The rates are calculated over a specific time range. The example below\ntracks the TCP connection rate over 30 seconds. If more than 200 new connections are made in this time period, the \nclient receives an 503 error and goes into a \"cooldown\" period for 60 seconds (`expiryTime`)\n\n    {\n        \"frontends\" : [\n            {\n                \"name\" : \"test_fe_1\",\n                ... \n                \"httpSpikeLimit\" : {\n                    \"sampleTime\" : \"30s\",\n                    \"expiryTime\" : \"60s\",\n                    \"rate\" : 50\n                },\n                \"tcpSpikeLimit\" : {\n                    \"sampleTime\" : \"30s\",\n                    \"expiryTime\" : \"60s\",\n                    \"rate\" : 200\n            }\n    }\n\nNote: the time format used, i.e. `30s`, is the default Haproxy time format. More details [here](http://cbonte.github.io/haproxy-dconv/configuration-1.5.html#2.2)\n\n## Setting Backends and servers\n\n\nMore info to follow. _Note_: You can point servers to standard IP + port pairs or to Unix sockets.\nHere are some examples:\n\n    {  \"backends\" : [\n    \n            {\n                \"name\" : \"testbe1\",\n                \"mode\" : \"http\",\n                \"servers\" : [\n                    {\n                        \"name\" : \"test_be1_1\",\n                        \"host\" : \"192.168.59.103\",\n                        \"port\" : 8081,\n                        \"weight\" : 100,\n                        \"maxconn\" : 1000,\n                        \"check\" : false,\n                        \"checkInterval\" : 10\n                        },\n                    {\n                        \"name\" : \"test_be1_2\",\n                        \"host\" : \"192.168.59.103\",\n                        \"port\" : 8082,\n                        \"weight\" : 100,\n                        \"maxconn\" : 1000,\n                        \"check\" : false,\n                        \"checkInterval\" : 10\n                    }\n                ],\n                \"proxyMode\" : false\n            }\n        ]\n    }\n    \n    \nAnd with proxy mode set to true:\n\n    { \n        \"backends\" : \n            [\n                {\n                    \"name\" : \"testbe2\",\n                    \"mode\" : \"http\",\n                    \"servers\" : [\n                        {\n                            \"name\" : \"test_be2_1\",\n                            \"unixSock\" : \"/tmp/vamp_testbe2_1.sock\",\n                            \"weight\" : 100\n                        }\n                    ],\n                    \"proxyMode\" : true,\n                    \"options\" : {}\n                }\n            ]\n    }\n\n\n \n### Startup Flags \u0026 Options\n\n    -binary=\"/usr/local/bin/haproxy\"                           Path to the HAproxy binary\n    -kafkaHost=\"localhost\"                                     The hostname or ip address of the Kafka host\n    -kafkaPort=9092                                            The port of the Kafka host\n    -kafkaSwitch=\"off\"                                         Switch whether to enable Kafka streaming\n    -lbConfigFile=\"resources/haproxy_new.cfg\"                  Location of the target HAproxy config file\n    -lbTemplate=\"resources/haproxy_cfg.template\"               Template file to build HAproxy load balancer config\n    -mode=\"loadbalancer\"                                       Switch for \"loadbalancer\" or \"localproxy\" mode\n    -pidFile=\"resources/haproxy-private.pid\"                   Location of the HAproxy PID file\n    -port=10001                                                Port/IP to use for the REST interface. Overrides $PORT0 env variable\n    -proxyConfigFile=\"resources/haproxy_localproxy_new.cfg\"    Location of the target HAproxy localproxy config\n    -proxyTemplate=\"resources/haproxy_localproxy_cfg.template\" Template file to build HAproxy local proxy config\n    -zooConKey=\"magnetic\"                                      Zookeeper root key\n    -zooConString=\"localhost\"                                  A zookeeper ensemble connection string\n    \nfor example, this would start up haproxy-rest on port 12345\n\n    $ ./haproxy-rest -port=12345  \nand this would start up haproxy-rest with kafka streaming enabled\n\n    $ ./haproxy-rest -mode=loadbalancer -kafkaSwitch=on -kafkaHost=10.161.63.88\n    \n### Installing: the harder custom build way\n\nInstall HAproxy 1.5 or greater in whatever way you like. Just make sure the `haproxy` executable is in your `PATH`. For Ubuntu, use:\n\n\n    $ add-apt-repository ppa:vbernat/haproxy-1.5 -y  \n    $ apt-get update -y  \n    $ apt-get install -y haproxy  \n\n\nClone this repo \n\n    git clone https://github.com/tnolet/haproxy-rest \n\nCD into the directory just created and startup haproxy\n\nOSX:\n\n    $ cd haproxy-rest\n    $ haproxy -f resources/haproxy_init.cfg -p resources/haproxy-private.pid -st $(\u003cresources/haproxy-private.pid)\n\nUbuntu\n\n    $ cd haproxy-rest      \n    $ haproxy -f resources/haproxy_init.cfg -p resources/haproxy-private.pid -sf $(cat resources/haproxy-private.pid)\n\n    \nBuild the program and run it. \n \n    $ go build\n    $ ./haproxy-rest\n\nIf you're on Mac OSX or Windows and want to compile for Linux (which is probably the OS \nyou're using to run HAproxy), you need to cross compile. \nFor this, go to your Go `src` directory, i.e.\n\n    $ cd /usr/local/Cellar/go/1.3.1\n\nCompile the compiler with the correct arguments for OS and ARC\n\n    $ GOOS=linux GOARCH=386 CGO_ENABLED=0 ./make.bash --no-clean\n\nCompile the application\n\n    $ GOOS=windows GOARCH=386 go build \n    \n\n## Inspiration\n\nPart of Haproxy-rest is inspired by [haproxy-config](https://github.com/jbuchbinder/haproxy-config) and\n[consul-haproxy](https://github.com/hashicorp/consul-haproxy). It is not a straight fork or clone of either of these,\nbut parts are borrowed.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftnolet%2Fhaproxy-rest","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftnolet%2Fhaproxy-rest","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftnolet%2Fhaproxy-rest/lists"}