diff --git a/README.md b/README.md index f64a141..824a64e 100644 --- a/README.md +++ b/README.md @@ -61,6 +61,21 @@ $ docker run \ ekofr/pihole-exporter:latest ``` +If you are running pi-hole behind https, you must both set the `PIHOLE_PROTOCOL` environment variable +as well as include your ssl certificates to the docker image as it does not have any baked in: + +``` +$ docker run \ + -e 'PIHOLE_PROTOCOL=https' \ + -e 'PIHOLE_HOSTNAME=192.168.1.2' \ + -e 'PIHOLE_PASSWORD=mypassword' \ + -e 'INTERVAL=30s' \ + -e 'PORT=9617' \ + -v '/etc/ssl/certs:/etc/ssl/certs:ro' \ + -p 9617:9617 \ + ekofr/pihole-exporter:latest +``` + ### From sources Optionally, you can download and build it from the sources. You have to retrieve the project sources by using one of the following way: diff --git a/config/configuration.go b/config/configuration.go index 75c7972..84ace52 100644 --- a/config/configuration.go +++ b/config/configuration.go @@ -15,6 +15,7 @@ import ( // Config is the exporter CLI configuration. type Config struct { + PIHoleProtocol string `config:"pihole_protocol"` PIHoleHostname string `config:"pihole_hostname"` PIHolePassword string `config:"pihole_password"` PIHoleApiToken string `config:"pihole_api_token"` @@ -24,6 +25,7 @@ type Config struct { func getDefaultConfig() *Config { return &Config{ + PIHoleProtocol: "http", PIHoleHostname: "127.0.0.1", PIHolePassword: "", PIHoleApiToken: "", diff --git a/internal/pihole/client.go b/internal/pihole/client.go index e70ea8f..40ad6e1 100644 --- a/internal/pihole/client.go +++ b/internal/pihole/client.go @@ -7,6 +7,7 @@ import ( "log" "net/http" "net/url" + "os" "strconv" "strings" "time" @@ -15,14 +16,15 @@ import ( ) var ( - loginURLPattern = "http://%s/admin/index.php?login" - statsURLPattern = "http://%s/admin/api.php?summaryRaw&overTimeData&topItems&recentItems&getQueryTypes&getForwardDestinations&getQuerySources&jsonForceObject" + loginURLPattern = "%s://%s/admin/index.php?login" + statsURLPattern = "%s://%s/admin/api.php?summaryRaw&overTimeData&topItems&recentItems&getQueryTypes&getForwardDestinations&getQuerySources&jsonForceObject" ) // Client struct is a PI-Hole client to request an instance of a PI-Hole ad blocker. type Client struct { httpClient http.Client interval time.Duration + protocol string hostname string password string sessionID string @@ -30,8 +32,14 @@ type Client struct { } // NewClient method initializes a new PI-Hole client. -func NewClient(hostname, password, apiToken string, interval time.Duration) *Client { +func NewClient(protocol, hostname, password, apiToken string, interval time.Duration) *Client { + if protocol != "http" && protocol != "https" { + log.Printf("protocol %s is invalid. Must be http or https.", protocol) + os.Exit(1) + } + return &Client{ + protocol: protocol, hostname: hostname, password: password, apiToken: apiToken, @@ -101,7 +109,7 @@ func (c *Client) setMetrics(stats *Stats) { } func (c *Client) getPHPSessionID() (sessionID string) { - loginURL := fmt.Sprintf(loginURLPattern, c.hostname) + loginURL := fmt.Sprintf(loginURLPattern, c.protocol, c.hostname) values := url.Values{"pw": []string{c.password}} req, err := http.NewRequest("POST", loginURL, strings.NewReader(values.Encode())) @@ -130,7 +138,7 @@ func (c *Client) getPHPSessionID() (sessionID string) { func (c *Client) getStatistics() *Stats { var stats Stats - statsURL := fmt.Sprintf(statsURLPattern, c.hostname) + statsURL := fmt.Sprintf(statsURLPattern, c.protocol, c.hostname) if c.isUsingApiToken() { statsURL = fmt.Sprintf("%s&auth=%s", statsURL, c.apiToken) diff --git a/main.go b/main.go index 434083d..1311e59 100644 --- a/main.go +++ b/main.go @@ -26,14 +26,14 @@ func main() { metrics.Init() - initPiHoleClient(conf.PIHoleHostname, conf.PIHolePassword, conf.PIHoleApiToken, conf.Interval) + initPiHoleClient(conf.PIHoleProtocol, conf.PIHoleHostname, conf.PIHolePassword, conf.PIHoleApiToken, conf.Interval) initHttpServer(conf.Port) handleExitSignal() } -func initPiHoleClient(hostname, password, apiToken string, interval time.Duration) { - client := pihole.NewClient(hostname, password, apiToken, interval) +func initPiHoleClient(protocol, hostname, password, apiToken string, interval time.Duration) { + client := pihole.NewClient(protocol, hostname, password, apiToken, interval) go client.Scrape() }