mirror of
https://github.com/goauthentik/authentik
synced 2026-04-25 17:15:26 +02:00
root: allow listening on multiple IPs (#20930)
This commit is contained in:
committed by
GitHub
parent
545b1e8f19
commit
4dfdf9afa3
@@ -32,12 +32,18 @@ postgresql:
|
||||
# host: replica1.example.com
|
||||
|
||||
listen:
|
||||
http: 0.0.0.0:9000
|
||||
https: 0.0.0.0:9443
|
||||
ldap: 0.0.0.0:3389
|
||||
ldaps: 0.0.0.0:6636
|
||||
radius: 0.0.0.0:1812
|
||||
metrics: 0.0.0.0:9300
|
||||
http:
|
||||
- "[::]:9000"
|
||||
https:
|
||||
- "[::]:9443"
|
||||
ldap:
|
||||
- "[::]:3389"
|
||||
ldaps:
|
||||
- "[::]:6636"
|
||||
radius:
|
||||
- "[::]:1812"
|
||||
metrics:
|
||||
- "[::]:9300"
|
||||
debug: 0.0.0.0:9900
|
||||
debug_py: 0.0.0.0:9901
|
||||
trusted_proxy_cidrs:
|
||||
|
||||
@@ -224,7 +224,10 @@ class WorkerHealthcheckMiddleware(Middleware):
|
||||
thread: HTTPServerThread | None
|
||||
|
||||
def __init__(self):
|
||||
host, _, port = CONFIG.get("listen.http").rpartition(":")
|
||||
listen = CONFIG.get("listen.http", ["[::]:9000"])
|
||||
if isinstance(listen, str):
|
||||
listen = listen.split(",")
|
||||
host, _, port = listen[0].rpartition(":")
|
||||
|
||||
try:
|
||||
port = int(port)
|
||||
@@ -323,7 +326,10 @@ class MetricsMiddleware(BaseMetricsMiddleware):
|
||||
return []
|
||||
|
||||
def after_worker_boot(self, broker: Broker, worker: Worker):
|
||||
addr, _, port = CONFIG.get("listen.metrics").rpartition(":")
|
||||
listen = CONFIG.get("listen.metrics", ["[::]:9300"])
|
||||
if isinstance(listen, str):
|
||||
listen = listen.split(",")
|
||||
addr, _, port = listen[0].rpartition(":")
|
||||
|
||||
try:
|
||||
port = int(port)
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
@@ -12,7 +14,8 @@ import (
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
"goauthentik.io/internal/config"
|
||||
"goauthentik.io/internal/utils/web"
|
||||
utils "goauthentik.io/internal/utils/web"
|
||||
"goauthentik.io/internal/web"
|
||||
)
|
||||
|
||||
var workerPidFile = path.Join(os.TempDir(), "authentik-worker.pid")
|
||||
@@ -44,9 +47,15 @@ func init() {
|
||||
|
||||
func checkServer() int {
|
||||
h := &http.Client{
|
||||
Transport: web.NewUserAgentTransport("goauthentik.io/healthcheck", http.DefaultTransport),
|
||||
Transport: utils.NewUserAgentTransport("goauthentik.io/healthcheck",
|
||||
&http.Transport{
|
||||
DialContext: func(_ context.Context, _, _ string) (net.Conn, error) {
|
||||
return net.Dial("unix", path.Join(os.TempDir(), web.SocketName))
|
||||
},
|
||||
},
|
||||
),
|
||||
}
|
||||
url := fmt.Sprintf("http://%s%s-/health/live/", config.Get().Listen.HTTP, config.Get().Web.Path)
|
||||
url := fmt.Sprintf("http://localhost%s-/health/live/", config.Get().Web.Path)
|
||||
res, err := h.Head(url)
|
||||
if err != nil {
|
||||
log.WithError(err).Warning("failed to send healthcheck request")
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/getsentry/sentry-go"
|
||||
@@ -51,9 +52,10 @@ var rootCmd = &cobra.Command{
|
||||
ex := common.Init()
|
||||
defer common.Defer()
|
||||
|
||||
u, err := url.Parse(fmt.Sprintf("http://%s%s", config.Get().Listen.HTTP, config.Get().Web.Path))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
u := url.URL{
|
||||
Scheme: "unix",
|
||||
Host: fmt.Sprintf("%s/%s", os.TempDir(), web.SocketName),
|
||||
Path: config.Get().Web.Path,
|
||||
}
|
||||
|
||||
ws := web.NewWebServer()
|
||||
@@ -70,13 +72,13 @@ var rootCmd = &cobra.Command{
|
||||
},
|
||||
}
|
||||
|
||||
func attemptProxyStart(ws *web.WebServer, u *url.URL) {
|
||||
func attemptProxyStart(ws *web.WebServer, u url.URL) {
|
||||
maxTries := 100
|
||||
attempt := 0
|
||||
l := log.WithField("logger", "authentik.server")
|
||||
for {
|
||||
l.Debug("attempting to init outpost")
|
||||
ac := ak.NewAPIController(*u, config.Get().SecretKey)
|
||||
ac := ak.NewAPIController(u, config.Get().SecretKey)
|
||||
if ac == nil {
|
||||
attempt += 1
|
||||
time.Sleep(1 * time.Second)
|
||||
|
||||
@@ -50,12 +50,12 @@ type PostgreSQLConfig struct {
|
||||
}
|
||||
|
||||
type ListenConfig struct {
|
||||
HTTP string `yaml:"http" env:"HTTP, overwrite"`
|
||||
HTTPS string `yaml:"https" env:"HTTPS, overwrite"`
|
||||
LDAP string `yaml:"ldap" env:"LDAP, overwrite"`
|
||||
LDAPS string `yaml:"ldaps" env:"LDAPS, overwrite"`
|
||||
Radius string `yaml:"radius" env:"RADIUS, overwrite"`
|
||||
Metrics string `yaml:"metrics" env:"METRICS, overwrite"`
|
||||
HTTP []string `yaml:"http" env:"HTTP, overwrite"`
|
||||
HTTPS []string `yaml:"https" env:"HTTPS, overwrite"`
|
||||
LDAP []string `yaml:"ldap" env:"LDAP, overwrite"`
|
||||
LDAPS []string `yaml:"ldaps" env:"LDAPS, overwrite"`
|
||||
Radius []string `yaml:"radius" env:"RADIUS, overwrite"`
|
||||
Metrics []string `yaml:"metrics" env:"METRICS, overwrite"`
|
||||
Debug string `yaml:"debug" env:"DEBUG, overwrite"`
|
||||
TrustedProxyCIDRs []string `yaml:"trusted_proxy_cidrs" env:"TRUSTED_PROXY_CIDRS, overwrite"`
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"crypto/fips140"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
@@ -54,19 +55,44 @@ type APIController struct {
|
||||
// NewAPIController initialise new API Controller instance from URL and API token
|
||||
func NewAPIController(akURL url.URL, token string) *APIController {
|
||||
rsp := sentry.StartSpan(context.Background(), "authentik.outposts.init")
|
||||
log := log.WithField("logger", "authentik.outpost.ak-api-controller")
|
||||
|
||||
originalAkURL := akURL
|
||||
var client http.Client
|
||||
if akURL.Scheme == "unix" {
|
||||
log.WithField("host", akURL.Host).WithField("path", akURL.Path).Debug("using unix socket")
|
||||
socketPath := akURL.Host
|
||||
client = http.Client{
|
||||
Transport: web.NewUserAgentTransport(
|
||||
constants.UserAgentOutpost(),
|
||||
web.NewTracingTransport(
|
||||
rsp.Context(),
|
||||
&http.Transport{
|
||||
DialContext: func(_ context.Context, _, _ string) (net.Conn, error) {
|
||||
return net.Dial("unix", socketPath)
|
||||
},
|
||||
},
|
||||
),
|
||||
),
|
||||
}
|
||||
akURL.Scheme = "http"
|
||||
akURL.Host = "localhost"
|
||||
} else {
|
||||
client = http.Client{
|
||||
Transport: web.NewUserAgentTransport(
|
||||
constants.UserAgentOutpost(),
|
||||
web.NewTracingTransport(
|
||||
rsp.Context(),
|
||||
GetTLSTransport(),
|
||||
),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
apiConfig := api.NewConfiguration()
|
||||
apiConfig.Host = akURL.Host
|
||||
apiConfig.Scheme = akURL.Scheme
|
||||
apiConfig.HTTPClient = &http.Client{
|
||||
Transport: web.NewUserAgentTransport(
|
||||
constants.UserAgentOutpost(),
|
||||
web.NewTracingTransport(
|
||||
rsp.Context(),
|
||||
GetTLSTransport(),
|
||||
),
|
||||
),
|
||||
}
|
||||
apiConfig.HTTPClient = &client
|
||||
apiConfig.Servers = api.ServerConfigurations{
|
||||
{
|
||||
URL: fmt.Sprintf("%sapi/v3", akURL.Path),
|
||||
@@ -77,8 +103,6 @@ func NewAPIController(akURL url.URL, token string) *APIController {
|
||||
// create the API client, with the transport
|
||||
apiClient := api.NewAPIClient(apiConfig)
|
||||
|
||||
log := log.WithField("logger", "authentik.outpost.ak-api-controller")
|
||||
|
||||
// Because we don't know the outpost UUID, we simply do a list and pick the first
|
||||
// The service account this token belongs to should only have access to a single outpost
|
||||
outposts, _ := retry.DoWithData[*api.PaginatedOutpostList](
|
||||
@@ -124,7 +148,7 @@ func NewAPIController(akURL url.URL, token string) *APIController {
|
||||
}
|
||||
ac.logger.WithField("embedded", ac.IsEmbedded()).Info("Outpost mode")
|
||||
ac.logger.WithField("offset", ac.reloadOffset.String()).Debug("HA Reload offset")
|
||||
err = ac.initEvent(akURL, outpost.Pk)
|
||||
err = ac.initEvent(originalAkURL, outpost.Pk)
|
||||
if err != nil {
|
||||
go ac.recentEvents()
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"maps"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
@@ -45,9 +46,19 @@ func (ac *APIController) initEvent(akURL url.URL, outpostUUID string) error {
|
||||
dialer := websocket.Dialer{
|
||||
Proxy: http.ProxyFromEnvironment,
|
||||
HandshakeTimeout: 10 * time.Second,
|
||||
TLSClientConfig: &tls.Config{
|
||||
}
|
||||
if akURL.Scheme == "unix" {
|
||||
ac.logger.WithField("host", akURL.Host).WithField("path", akURL.Path).Debug("websocket is using unix connection")
|
||||
socketPath := akURL.Host
|
||||
dialer.NetDialContext = func(ctx context.Context, _, _ string) (net.Conn, error) {
|
||||
return (&net.Dialer{}).DialContext(ctx, "unix", socketPath)
|
||||
}
|
||||
akURL.Scheme = "http"
|
||||
akURL.Host = "localhost"
|
||||
} else {
|
||||
dialer.TLSClientConfig = &tls.Config{
|
||||
InsecureSkipVerify: config.Get().AuthentikInsecure,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
wsu := ac.getWebsocketURL(akURL, outpostUUID, query).String()
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
package healthcheck
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"context"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
"goauthentik.io/internal/config"
|
||||
"goauthentik.io/internal/outpost/ak"
|
||||
"goauthentik.io/internal/utils/web"
|
||||
)
|
||||
|
||||
@@ -21,9 +24,15 @@ var Command = &cobra.Command{
|
||||
|
||||
func check() int {
|
||||
h := &http.Client{
|
||||
Transport: web.NewUserAgentTransport("goauthentik.io/healthcheck", http.DefaultTransport),
|
||||
Transport: web.NewUserAgentTransport("goauthentik.io/healthcheck",
|
||||
&http.Transport{
|
||||
DialContext: func(_ context.Context, _, _ string) (net.Conn, error) {
|
||||
return net.Dial("unix", path.Join(os.TempDir(), ak.MetricsSocketName))
|
||||
},
|
||||
},
|
||||
),
|
||||
}
|
||||
url := fmt.Sprintf("http://%s/outpost.goauthentik.io/ping", config.Get().Listen.Metrics)
|
||||
url := "http://localhost/outpost.goauthentik.io/ping"
|
||||
res, err := h.Head(url)
|
||||
if err != nil {
|
||||
log.WithError(err).Warning("failed to send healthcheck request")
|
||||
|
||||
@@ -1,12 +1,22 @@
|
||||
package ak
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promauto"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"goauthentik.io/internal/utils/sentry"
|
||||
"goauthentik.io/internal/utils/unix"
|
||||
)
|
||||
|
||||
var (
|
||||
OutpostInfo = promauto.NewGaugeVec(prometheus.GaugeOpts{
|
||||
MetricsSocketName = "authentik-metrics.sock"
|
||||
OutpostInfo = promauto.NewGaugeVec(prometheus.GaugeOpts{
|
||||
Name: "authentik_outpost_info",
|
||||
Help: "Outpost info",
|
||||
}, []string{"outpost_name", "outpost_type", "uuid", "version", "build"})
|
||||
@@ -19,3 +29,43 @@ var (
|
||||
Help: "Connection status",
|
||||
}, []string{"outpost_name", "outpost_type", "uuid"})
|
||||
)
|
||||
|
||||
func MetricsRouter() *mux.Router {
|
||||
m := mux.NewRouter()
|
||||
m.Use(sentry.SentryNoSampleMiddleware)
|
||||
m.HandleFunc("/outpost.goauthentik.io/ping", func(rw http.ResponseWriter, r *http.Request) {
|
||||
rw.WriteHeader(204)
|
||||
})
|
||||
m.Path("/metrics").Handler(promhttp.Handler())
|
||||
return m
|
||||
}
|
||||
|
||||
func RunMetricsServer(listen string, router *mux.Router) {
|
||||
l := log.WithField("logger", "authentik.outpost.metrics").WithField("listen", listen)
|
||||
l.Info("Starting Metrics server")
|
||||
err := http.ListenAndServe(listen, router)
|
||||
if err != nil {
|
||||
l.WithError(err).Warning("Failed to start metrics listener")
|
||||
}
|
||||
}
|
||||
|
||||
func RunMetricsUnix(router *mux.Router) {
|
||||
socketPath := path.Join(os.TempDir(), MetricsSocketName)
|
||||
l := log.WithField("logger", "authentik.outpost.metrics").WithField("listen", socketPath)
|
||||
ln, err := unix.Listen(socketPath)
|
||||
if err != nil {
|
||||
l.WithError(err).Warning("failed to listen")
|
||||
return
|
||||
}
|
||||
defer func() {
|
||||
err := ln.Close()
|
||||
if err != nil {
|
||||
l.WithError(err).Warning("failed to close listener")
|
||||
}
|
||||
}()
|
||||
l.WithField("listen", socketPath).Info("Starting Metrics server")
|
||||
err = http.Serve(ln, router)
|
||||
if err != nil {
|
||||
l.WithError(err).Warning("Failed to start metrics listener")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@ import (
|
||||
"goauthentik.io/internal/config"
|
||||
"goauthentik.io/internal/crypto"
|
||||
"goauthentik.io/internal/outpost/ak"
|
||||
"goauthentik.io/internal/outpost/ldap/metrics"
|
||||
"goauthentik.io/internal/utils"
|
||||
|
||||
"beryju.io/ldap"
|
||||
@@ -63,9 +62,7 @@ func (ls *LDAPServer) Type() string {
|
||||
return "ldap"
|
||||
}
|
||||
|
||||
func (ls *LDAPServer) StartLDAPServer() error {
|
||||
listen := config.Get().Listen.LDAP
|
||||
|
||||
func (ls *LDAPServer) StartLDAPServer(listen string) error {
|
||||
ln, err := net.Listen("tcp", listen)
|
||||
if err != nil {
|
||||
ls.log.WithField("listen", listen).WithError(err).Warning("Failed to listen (SSL)")
|
||||
@@ -89,26 +86,40 @@ func (ls *LDAPServer) StartLDAPServer() error {
|
||||
}
|
||||
|
||||
func (ls *LDAPServer) Start() error {
|
||||
listenLdap := config.Get().Listen.LDAP
|
||||
listenLdaps := config.Get().Listen.LDAPS
|
||||
listenMetrics := config.Get().Listen.Metrics
|
||||
metricsRouter := ak.MetricsRouter()
|
||||
wg := sync.WaitGroup{}
|
||||
wg.Add(3)
|
||||
wg.Add(len(listenLdap) + len(listenLdaps) + 1 + len(listenMetrics))
|
||||
for _, listen := range listenLdap {
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
err := ls.StartLDAPServer(listen)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}()
|
||||
}
|
||||
for _, listen := range listenLdaps {
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
err := ls.StartLDAPTLSServer(listen)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}()
|
||||
}
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
metrics.RunServer()
|
||||
}()
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
err := ls.StartLDAPServer()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}()
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
err := ls.StartLDAPTLSServer()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
ak.RunMetricsUnix(metricsRouter)
|
||||
}()
|
||||
for _, listen := range listenMetrics {
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
ak.RunMetricsServer(listen, metricsRouter)
|
||||
}()
|
||||
}
|
||||
wg.Wait()
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ import (
|
||||
"net"
|
||||
|
||||
"github.com/pires/go-proxyproto"
|
||||
"goauthentik.io/internal/config"
|
||||
"goauthentik.io/internal/utils"
|
||||
)
|
||||
|
||||
@@ -37,8 +36,7 @@ func (ls *LDAPServer) getCertificates(info *tls.ClientHelloInfo) (*tls.Certifica
|
||||
return ls.defaultCert, nil
|
||||
}
|
||||
|
||||
func (ls *LDAPServer) StartLDAPTLSServer() error {
|
||||
listen := config.Get().Listen.LDAPS
|
||||
func (ls *LDAPServer) StartLDAPTLSServer(listen string) error {
|
||||
tlsConfig := utils.GetTLSConfig()
|
||||
tlsConfig.GetCertificate = ls.getCertificates
|
||||
|
||||
|
||||
@@ -1,16 +1,8 @@
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"goauthentik.io/internal/config"
|
||||
"goauthentik.io/internal/utils/sentry"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promauto"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -23,19 +15,3 @@ var (
|
||||
Help: "Total number of rejected requests",
|
||||
}, []string{"outpost_name", "type", "reason", "app"})
|
||||
)
|
||||
|
||||
func RunServer() {
|
||||
m := mux.NewRouter()
|
||||
l := log.WithField("logger", "authentik.outpost.metrics")
|
||||
m.Use(sentry.SentryNoSampleMiddleware)
|
||||
m.HandleFunc("/outpost.goauthentik.io/ping", func(rw http.ResponseWriter, r *http.Request) {
|
||||
rw.WriteHeader(204)
|
||||
})
|
||||
m.Path("/metrics").Handler(promhttp.Handler())
|
||||
listen := config.Get().Listen.Metrics
|
||||
l.WithField("listen", listen).Info("Starting Metrics server")
|
||||
err := http.ListenAndServe(listen, m)
|
||||
if err != nil {
|
||||
l.WithError(err).Warning("Failed to start metrics listener")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,8 @@
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"goauthentik.io/internal/config"
|
||||
"goauthentik.io/internal/utils/sentry"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promauto"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -23,19 +15,3 @@ var (
|
||||
Help: "Proxy upstream response latencies in seconds",
|
||||
}, []string{"outpost_name", "method", "scheme", "host", "upstream_host"})
|
||||
)
|
||||
|
||||
func RunServer() {
|
||||
m := mux.NewRouter()
|
||||
l := log.WithField("logger", "authentik.outpost.metrics")
|
||||
m.Use(sentry.SentryNoSampleMiddleware)
|
||||
m.HandleFunc("/outpost.goauthentik.io/ping", func(rw http.ResponseWriter, r *http.Request) {
|
||||
rw.WriteHeader(204)
|
||||
})
|
||||
m.Path("/metrics").Handler(promhttp.Handler())
|
||||
listen := config.Get().Listen.Metrics
|
||||
l.WithField("listen", listen).Info("Starting Metrics server")
|
||||
err := http.ListenAndServe(listen, m)
|
||||
if err != nil {
|
||||
l.WithError(err).Warning("Failed to start metrics listener")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@ import (
|
||||
"goauthentik.io/internal/crypto"
|
||||
"goauthentik.io/internal/outpost/ak"
|
||||
"goauthentik.io/internal/outpost/proxyv2/application"
|
||||
"goauthentik.io/internal/outpost/proxyv2/metrics"
|
||||
"goauthentik.io/internal/utils"
|
||||
sentryutils "goauthentik.io/internal/utils/sentry"
|
||||
"goauthentik.io/internal/utils/web"
|
||||
@@ -127,11 +126,10 @@ func (ps *ProxyServer) getCertificates(info *tls.ClientHelloInfo) (*tls.Certific
|
||||
}
|
||||
|
||||
// ServeHTTP constructs a net.Listener and starts handling HTTP requests
|
||||
func (ps *ProxyServer) ServeHTTP() {
|
||||
listenAddress := config.Get().Listen.HTTP
|
||||
listener, err := net.Listen("tcp", listenAddress)
|
||||
func (ps *ProxyServer) ServeHTTP(listen string) {
|
||||
listener, err := net.Listen("tcp", listen)
|
||||
if err != nil {
|
||||
ps.log.WithField("listen", listenAddress).WithError(err).Warning("Failed to listen")
|
||||
ps.log.WithField("listen", listen).WithError(err).Warning("Failed to listen")
|
||||
return
|
||||
}
|
||||
proxyListener := &proxyproto.Listener{Listener: listener, ConnPolicy: utils.GetProxyConnectionPolicy()}
|
||||
@@ -142,18 +140,17 @@ func (ps *ProxyServer) ServeHTTP() {
|
||||
}
|
||||
}()
|
||||
|
||||
ps.log.WithField("listen", listenAddress).Info("Starting HTTP server")
|
||||
ps.log.WithField("listen", listen).Info("Starting HTTP server")
|
||||
ps.serve(proxyListener)
|
||||
ps.log.WithField("listen", listenAddress).Info("Stopping HTTP server")
|
||||
ps.log.WithField("listen", listen).Info("Stopping HTTP server")
|
||||
}
|
||||
|
||||
// ServeHTTPS constructs a net.Listener and starts handling HTTPS requests
|
||||
func (ps *ProxyServer) ServeHTTPS() {
|
||||
listenAddress := config.Get().Listen.HTTPS
|
||||
func (ps *ProxyServer) ServeHTTPS(listen string) {
|
||||
tlsConfig := utils.GetTLSConfig()
|
||||
tlsConfig.GetCertificate = ps.getCertificates
|
||||
|
||||
ln, err := net.Listen("tcp", listenAddress)
|
||||
ln, err := net.Listen("tcp", listen)
|
||||
if err != nil {
|
||||
ps.log.WithError(err).Warning("Failed to listen (TLS)")
|
||||
return
|
||||
@@ -167,26 +164,40 @@ func (ps *ProxyServer) ServeHTTPS() {
|
||||
}()
|
||||
|
||||
tlsListener := tls.NewListener(proxyListener, tlsConfig)
|
||||
ps.log.WithField("listen", listenAddress).Info("Starting HTTPS server")
|
||||
ps.log.WithField("listen", listen).Info("Starting HTTPS server")
|
||||
ps.serve(tlsListener)
|
||||
ps.log.WithField("listen", listenAddress).Info("Stopping HTTPS server")
|
||||
ps.log.WithField("listen", listen).Info("Stopping HTTPS server")
|
||||
}
|
||||
|
||||
func (ps *ProxyServer) Start() error {
|
||||
listenHttp := config.Get().Listen.HTTP
|
||||
listenHttps := config.Get().Listen.HTTPS
|
||||
listenMetrics := config.Get().Listen.Metrics
|
||||
metricsRouter := ak.MetricsRouter()
|
||||
wg := sync.WaitGroup{}
|
||||
wg.Add(3)
|
||||
wg.Add(len(listenHttp) + len(listenHttps) + 1 + len(listenMetrics))
|
||||
for _, listen := range listenHttp {
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
ps.ServeHTTP(listen)
|
||||
}()
|
||||
}
|
||||
for _, listen := range listenHttps {
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
ps.ServeHTTPS(listen)
|
||||
}()
|
||||
}
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
ps.ServeHTTP()
|
||||
}()
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
ps.ServeHTTPS()
|
||||
}()
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
metrics.RunServer()
|
||||
ak.RunMetricsUnix(metricsRouter)
|
||||
}()
|
||||
for _, listen := range listenMetrics {
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
ak.RunMetricsServer(listen, metricsRouter)
|
||||
}()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"goauthentik.io/internal/config"
|
||||
"goauthentik.io/internal/utils/sentry"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
)
|
||||
|
||||
func RunServer() {
|
||||
m := mux.NewRouter()
|
||||
l := log.WithField("logger", "authentik.outpost.metrics")
|
||||
m.Use(sentry.SentryNoSampleMiddleware)
|
||||
m.HandleFunc("/outpost.goauthentik.io/ping", func(rw http.ResponseWriter, r *http.Request) {
|
||||
rw.WriteHeader(204)
|
||||
})
|
||||
m.Path("/metrics").Handler(promhttp.Handler())
|
||||
listen := config.Get().Listen.Metrics
|
||||
l.WithField("listen", listen).Info("Starting Metrics server")
|
||||
err := http.ListenAndServe(listen, m)
|
||||
if err != nil {
|
||||
l.WithError(err).Warning("Failed to start metrics listener")
|
||||
}
|
||||
}
|
||||
@@ -9,9 +9,9 @@ import (
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/wwt/guac"
|
||||
|
||||
"goauthentik.io/internal/config"
|
||||
"goauthentik.io/internal/outpost/ak"
|
||||
"goauthentik.io/internal/outpost/rac/connection"
|
||||
"goauthentik.io/internal/outpost/rac/metrics"
|
||||
)
|
||||
|
||||
type RACServer struct {
|
||||
@@ -92,12 +92,10 @@ func (rs *RACServer) wsHandler(ctx context.Context, msg ak.Event) error {
|
||||
}
|
||||
|
||||
func (rs *RACServer) Start() error {
|
||||
listenMetrics := config.Get().Listen.Metrics
|
||||
metricsRouter := ak.MetricsRouter()
|
||||
wg := sync.WaitGroup{}
|
||||
wg.Add(2)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
metrics.RunServer()
|
||||
}()
|
||||
wg.Add(1 + 1 + len(listenMetrics))
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
err := rs.startGuac()
|
||||
@@ -105,6 +103,16 @@ func (rs *RACServer) Start() error {
|
||||
panic(err)
|
||||
}
|
||||
}()
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
ak.RunMetricsUnix(metricsRouter)
|
||||
}()
|
||||
for _, listen := range listenMetrics {
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
ak.RunMetricsServer(listen, metricsRouter)
|
||||
}()
|
||||
}
|
||||
wg.Wait()
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1,16 +1,8 @@
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"goauthentik.io/internal/config"
|
||||
"goauthentik.io/internal/utils/sentry"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promauto"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -23,19 +15,3 @@ var (
|
||||
Help: "Total number of rejected requests",
|
||||
}, []string{"outpost_name", "reason", "app"})
|
||||
)
|
||||
|
||||
func RunServer() {
|
||||
m := mux.NewRouter()
|
||||
l := log.WithField("logger", "authentik.outpost.metrics")
|
||||
m.Use(sentry.SentryNoSampleMiddleware)
|
||||
m.HandleFunc("/outpost.goauthentik.io/ping", func(rw http.ResponseWriter, r *http.Request) {
|
||||
rw.WriteHeader(204)
|
||||
})
|
||||
m.Path("/metrics").Handler(promhttp.Handler())
|
||||
listen := config.Get().Listen.Metrics
|
||||
l.WithField("listen", listen).Info("Starting Metrics server")
|
||||
err := http.ListenAndServe(listen, m)
|
||||
if err != nil {
|
||||
l.WithError(err).Warning("Failed to start metrics listener")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
log "github.com/sirupsen/logrus"
|
||||
"goauthentik.io/internal/config"
|
||||
"goauthentik.io/internal/outpost/ak"
|
||||
"goauthentik.io/internal/outpost/radius/metrics"
|
||||
"golang.org/x/sync/errgroup"
|
||||
|
||||
"layeh.com/radius"
|
||||
)
|
||||
@@ -30,7 +30,7 @@ type ProviderInstance struct {
|
||||
}
|
||||
|
||||
type RadiusServer struct {
|
||||
s radius.PacketServer
|
||||
s []*radius.PacketServer
|
||||
log *log.Entry
|
||||
ac *ak.APIController
|
||||
cryptoStore *ak.CryptoStore
|
||||
@@ -45,10 +45,13 @@ func NewServer(ac *ak.APIController) ak.Outpost {
|
||||
providers: map[int32]*ProviderInstance{},
|
||||
cryptoStore: ak.NewCryptoStore(ac.Client.CryptoAPI),
|
||||
}
|
||||
rs.s = radius.PacketServer{
|
||||
Handler: rs,
|
||||
SecretSource: rs,
|
||||
Addr: config.Get().Listen.Radius,
|
||||
listenRadius := config.Get().Listen.Radius
|
||||
for _, listen := range listenRadius {
|
||||
rs.s = append(rs.s, &radius.PacketServer{
|
||||
Handler: rs,
|
||||
SecretSource: rs,
|
||||
Addr: listen,
|
||||
})
|
||||
}
|
||||
return rs
|
||||
}
|
||||
@@ -95,29 +98,44 @@ func (rs *RadiusServer) RADIUSSecret(ctx context.Context, remoteAddr net.Addr) (
|
||||
}
|
||||
|
||||
func (rs *RadiusServer) Start() error {
|
||||
listenMetrics := config.Get().Listen.Metrics
|
||||
metricsRouter := ak.MetricsRouter()
|
||||
wg := sync.WaitGroup{}
|
||||
wg.Add(2)
|
||||
wg.Add(len(rs.s) + 1 + len(listenMetrics))
|
||||
for _, s := range rs.s {
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
rs.log.WithField("listen", s.Addr).Info("Starting radius server")
|
||||
err := s.ListenAndServe()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}()
|
||||
}
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
metrics.RunServer()
|
||||
}()
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
rs.log.WithField("listen", rs.s.Addr).Info("Starting radius server")
|
||||
err := rs.s.ListenAndServe()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
ak.RunMetricsUnix(metricsRouter)
|
||||
}()
|
||||
for _, listen := range listenMetrics {
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
ak.RunMetricsServer(listen, metricsRouter)
|
||||
}()
|
||||
}
|
||||
wg.Wait()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (rs *RadiusServer) Stop() error {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
err := rs.s.Shutdown(ctx)
|
||||
errs := new(errgroup.Group)
|
||||
for _, s := range rs.s {
|
||||
errs.Go(func() error {
|
||||
return s.Shutdown(ctx)
|
||||
})
|
||||
}
|
||||
cancel()
|
||||
return err
|
||||
return errs.Wait()
|
||||
}
|
||||
|
||||
func (rs *RadiusServer) TimerFlowCacheExpiry(context.Context) {}
|
||||
|
||||
43
internal/utils/unix/unix.go
Normal file
43
internal/utils/unix/unix.go
Normal file
@@ -0,0 +1,43 @@
|
||||
package unix
|
||||
|
||||
import (
|
||||
"net"
|
||||
)
|
||||
|
||||
type Listener struct {
|
||||
*net.UnixListener
|
||||
}
|
||||
|
||||
type Conn struct {
|
||||
net.Conn
|
||||
}
|
||||
|
||||
func Listen(path string) (*Listener, error) {
|
||||
addr, err := net.ResolveUnixAddr("unix", path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ln, err := net.ListenUnix("unix", addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Listener{
|
||||
ln,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (l *Listener) Accept() (net.Conn, error) {
|
||||
c, err := l.UnixListener.Accept()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Conn{c}, nil
|
||||
}
|
||||
|
||||
func (c *Conn) LocalAddr() net.Addr {
|
||||
return &net.TCPAddr{IP: net.IPv6loopback, Port: 0}
|
||||
}
|
||||
|
||||
func (c *Conn) RemoteAddr() net.Addr {
|
||||
return &net.TCPAddr{IP: net.IPv6loopback, Port: 0}
|
||||
}
|
||||
@@ -19,7 +19,7 @@ var Requests = promauto.NewHistogramVec(prometheus.HistogramOpts{
|
||||
Help: "API request latencies in seconds",
|
||||
}, []string{"dest"})
|
||||
|
||||
func (ws *WebServer) runMetricsServer() {
|
||||
func (ws *WebServer) runMetricsServer(listen string) {
|
||||
l := log.WithField("logger", "authentik.router.metrics")
|
||||
|
||||
m := mux.NewRouter()
|
||||
@@ -49,10 +49,10 @@ func (ws *WebServer) runMetricsServer() {
|
||||
return
|
||||
}
|
||||
})
|
||||
l.WithField("listen", config.Get().Listen.Metrics).Info("Starting Metrics server")
|
||||
err := http.ListenAndServe(config.Get().Listen.Metrics, m)
|
||||
l.WithField("listen", listen).Info("Starting Metrics server")
|
||||
err := http.ListenAndServe(listen, m)
|
||||
if err != nil {
|
||||
l.WithError(err).Warning("Failed to start metrics server")
|
||||
}
|
||||
l.WithField("listen", config.Get().Listen.Metrics).Info("Stopping Metrics server")
|
||||
l.WithField("listen", listen).Info("Stopping Metrics server")
|
||||
}
|
||||
|
||||
@@ -21,17 +21,18 @@ import (
|
||||
"goauthentik.io/internal/config"
|
||||
"goauthentik.io/internal/constants"
|
||||
"goauthentik.io/internal/gounicorn"
|
||||
"goauthentik.io/internal/outpost/ak"
|
||||
"goauthentik.io/internal/outpost/proxyv2"
|
||||
"goauthentik.io/internal/utils"
|
||||
"goauthentik.io/internal/utils/unix"
|
||||
"goauthentik.io/internal/utils/web"
|
||||
"goauthentik.io/internal/web/brand_tls"
|
||||
)
|
||||
|
||||
const (
|
||||
SocketName = "authentik.sock"
|
||||
IPCKeyFile = "authentik-core-ipc.key"
|
||||
MetricsKeyFile = "authentik-core-metrics.key"
|
||||
UnixSocketName = "authentik-core.sock"
|
||||
CoreSocketName = "authentik-core.sock"
|
||||
)
|
||||
|
||||
type WebServer struct {
|
||||
@@ -64,7 +65,7 @@ func NewWebServer() *WebServer {
|
||||
loggingHandler.Use(web.NewLoggingHandler(l, nil))
|
||||
|
||||
tmp := os.TempDir()
|
||||
socketPath := path.Join(tmp, UnixSocketName)
|
||||
socketPath := path.Join(tmp, CoreSocketName)
|
||||
|
||||
// create http client to talk to backend, normal client if we're in debug more
|
||||
// and a client that connects to our socket when in non debug mode
|
||||
@@ -140,7 +141,8 @@ func (ws *WebServer) prepareKeys() {
|
||||
func (ws *WebServer) Start() {
|
||||
ws.prepareKeys()
|
||||
|
||||
u, err := url.Parse(fmt.Sprintf("http://%s%s", config.Get().Listen.HTTP, config.Get().Web.Path))
|
||||
socketPath := path.Join(os.TempDir(), SocketName)
|
||||
u, err := url.Parse(fmt.Sprintf("http://localhost%s", config.Get().Web.Path))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@@ -150,7 +152,11 @@ func (ws *WebServer) Start() {
|
||||
apiConfig.HTTPClient = &http.Client{
|
||||
Transport: web.NewUserAgentTransport(
|
||||
constants.UserAgentIPC(),
|
||||
ak.GetTLSTransport(),
|
||||
&http.Transport{
|
||||
DialContext: func(_ context.Context, _, _ string) (net.Conn, error) {
|
||||
return net.Dial("unix", socketPath)
|
||||
},
|
||||
},
|
||||
),
|
||||
}
|
||||
apiConfig.Servers = api.ServerConfigurations{
|
||||
@@ -171,10 +177,18 @@ func (ws *WebServer) Start() {
|
||||
go tw.Start()
|
||||
})
|
||||
|
||||
go ws.runMetricsServer()
|
||||
for _, listen := range config.Get().Listen.Metrics {
|
||||
go ws.runMetricsServer(listen)
|
||||
}
|
||||
go ws.attemptStartBackend()
|
||||
go ws.listenPlain()
|
||||
go ws.listenTLS()
|
||||
_ = os.Remove(socketPath)
|
||||
go ws.listenUnix(socketPath)
|
||||
for _, listen := range config.Get().Listen.HTTP {
|
||||
go ws.listenPlain(listen)
|
||||
}
|
||||
for _, listen := range config.Get().Listen.HTTPS {
|
||||
go ws.listenTLS(listen)
|
||||
}
|
||||
}
|
||||
|
||||
func (ws *WebServer) attemptStartBackend() {
|
||||
@@ -225,23 +239,41 @@ func (ws *WebServer) Shutdown() {
|
||||
ws.stop <- struct{}{}
|
||||
}
|
||||
|
||||
func (ws *WebServer) listenPlain() {
|
||||
ln, err := net.Listen("tcp", config.Get().Listen.HTTP)
|
||||
func (ws *WebServer) listenUnix(listen string) {
|
||||
ln, err := unix.Listen(listen)
|
||||
if err != nil {
|
||||
ws.log.WithError(err).Warning("failed to listen")
|
||||
ws.log.WithField("listen", listen).WithError(err).Warning("failed to listen")
|
||||
return
|
||||
}
|
||||
defer func() {
|
||||
err := ln.Close()
|
||||
if err != nil {
|
||||
ws.log.WithField("listen", listen).WithError(err).Warning("failed to close listener")
|
||||
}
|
||||
}()
|
||||
|
||||
ws.log.WithField("listen", listen).Info("Starting HTTP server")
|
||||
ws.serve(ln)
|
||||
ws.log.WithField("listen", listen).Info("Stopping HTTP server")
|
||||
}
|
||||
|
||||
func (ws *WebServer) listenPlain(listen string) {
|
||||
ln, err := net.Listen("tcp", listen)
|
||||
if err != nil {
|
||||
ws.log.WithField("listen", listen).WithError(err).Warning("failed to listen")
|
||||
return
|
||||
}
|
||||
proxyListener := &proxyproto.Listener{Listener: ln, ConnPolicy: utils.GetProxyConnectionPolicy()}
|
||||
defer func() {
|
||||
err := proxyListener.Close()
|
||||
if err != nil {
|
||||
ws.log.WithError(err).Warning("failed to close proxy listener")
|
||||
ws.log.WithField("listen", listen).WithError(err).Warning("failed to close proxy listener")
|
||||
}
|
||||
}()
|
||||
|
||||
ws.log.WithField("listen", config.Get().Listen.HTTP).Info("Starting HTTP server")
|
||||
ws.log.WithField("listen", listen).Info("Starting HTTP server")
|
||||
ws.serve(proxyListener)
|
||||
ws.log.WithField("listen", config.Get().Listen.HTTP).Info("Stopping HTTP server")
|
||||
ws.log.WithField("listen", listen).Info("Stopping HTTP server")
|
||||
}
|
||||
|
||||
func (ws *WebServer) serve(listener net.Listener) {
|
||||
|
||||
@@ -6,7 +6,6 @@ import (
|
||||
|
||||
"github.com/pires/go-proxyproto"
|
||||
|
||||
"goauthentik.io/internal/config"
|
||||
"goauthentik.io/internal/crypto"
|
||||
"goauthentik.io/internal/utils"
|
||||
"goauthentik.io/internal/utils/web"
|
||||
@@ -48,13 +47,13 @@ func (ws *WebServer) GetCertificate() func(ch *tls.ClientHelloInfo) (*tls.Config
|
||||
}
|
||||
|
||||
// ServeHTTPS constructs a net.Listener and starts handling HTTPS requests
|
||||
func (ws *WebServer) listenTLS() {
|
||||
func (ws *WebServer) listenTLS(listen string) {
|
||||
tlsConfig := utils.GetTLSConfig()
|
||||
tlsConfig.GetConfigForClient = ws.GetCertificate()
|
||||
|
||||
ln, err := net.Listen("tcp", config.Get().Listen.HTTPS)
|
||||
ln, err := net.Listen("tcp", listen)
|
||||
if err != nil {
|
||||
ws.log.WithError(err).Warning("failed to listen (TLS)")
|
||||
ws.log.WithField("listen", listen).WithError(err).Warning("failed to listen (TLS)")
|
||||
return
|
||||
}
|
||||
proxyListener := &proxyproto.Listener{
|
||||
@@ -71,7 +70,7 @@ func (ws *WebServer) listenTLS() {
|
||||
}()
|
||||
|
||||
tlsListener := tls.NewListener(proxyListener, tlsConfig)
|
||||
ws.log.WithField("listen", config.Get().Listen.HTTPS).Info("Starting HTTPS server")
|
||||
ws.log.WithField("listen", listen).Info("Starting HTTPS server")
|
||||
ws.serve(tlsListener)
|
||||
ws.log.WithField("listen", config.Get().Listen.HTTPS).Info("Stopping HTTPS server")
|
||||
ws.log.WithField("listen", listen).Info("Stopping HTTPS server")
|
||||
}
|
||||
|
||||
@@ -237,43 +237,43 @@ Defaults to `seconds=60`.
|
||||
|
||||
##### `AUTHENTIK_LISTEN__HTTP`
|
||||
|
||||
Listening address:port for HTTP.
|
||||
List of comma-separated `address:port` values for HTTP.
|
||||
|
||||
Applies to the Server, the Worker, and Proxy outposts.
|
||||
|
||||
Defaults to `0.0.0.0:9000`.
|
||||
Defaults to `[::]:9000`.
|
||||
|
||||
##### `AUTHENTIK_LISTEN__HTTPS`
|
||||
|
||||
Listening address:port for HTTPS.
|
||||
List of comma-separated `address:port` values for HTTPS.
|
||||
|
||||
Applies to the Server and Proxy outposts.
|
||||
|
||||
Defaults to `0.0.0.0:9443`.
|
||||
Defaults to `[::]:9443`.
|
||||
|
||||
##### `AUTHENTIK_LISTEN__LDAP`
|
||||
|
||||
Listening address:port for LDAP.
|
||||
List of comma-separated `address:port` values for LDAP.
|
||||
|
||||
Applies to LDAP outposts.
|
||||
|
||||
Defaults to `0.0.0.0:3389`.
|
||||
Defaults to `[::]:3389`.
|
||||
|
||||
##### `AUTHENTIK_LISTEN__LDAPS`
|
||||
|
||||
Listening address:port for LDAPS.
|
||||
List of comma-separated `address:port` values for LDAPS.
|
||||
|
||||
Applies to LDAP outposts.
|
||||
|
||||
Defaults to `0.0.0.0:6636`.
|
||||
Defaults to `[::]:6636`.
|
||||
|
||||
##### `AUTHENTIK_LISTEN__METRICS`
|
||||
|
||||
Listening address:port for Prometheus metrics.
|
||||
List of comma-separated `address:port` values for Prometheus metrics.
|
||||
|
||||
Applies to all.
|
||||
|
||||
Defaults to `0.0.0.0:9300`.
|
||||
Defaults to `[::]:9300`.
|
||||
|
||||
##### `AUTHENTIK_LISTEN__DEBUG`
|
||||
|
||||
|
||||
@@ -6,7 +6,11 @@ draft: true
|
||||
|
||||
## Highlights
|
||||
|
||||
<!-- ## Breaking changes -->
|
||||
## Breaking changes
|
||||
|
||||
### Listening on multiple IPs
|
||||
|
||||
For advanced use cases, authentik now supports setting listening settings to a comma-separated list of IPs. With this change, the default IP we listen on changed from `0.0.0.0` to `[::]` to better match ecosystem standards. Some IPv4-only environments might need to adapt those settings.
|
||||
|
||||
## New features and improvements
|
||||
|
||||
|
||||
Reference in New Issue
Block a user