restore ability to run the server in a read-only file system (#6098)

This was temporarily lost after the introduction of the native MoQ QUIC
listener.
This commit is contained in:
Alessandro Ros
2026-08-16 16:03:37 +02:00
committed by GitHub
parent 6a40b29538
commit c9f003f247
8 changed files with 66 additions and 56 deletions
+5 -7
View File
@@ -159,13 +159,11 @@ func (cl *CertLoader) Close() {
cl.cert = nil
}
// GetCertificate returns a function that returns the certificate for use in a tls.Config.
func (cl *CertLoader) GetCertificate() func(*tls.ClientHelloInfo) (*tls.Certificate, error) {
return func(_ *tls.ClientHelloInfo) (*tls.Certificate, error) {
cl.certMu.RLock()
defer cl.certMu.RUnlock()
return cl.cert, nil
}
// GetCertificate returns the certificate for use in a tls.Config.
func (cl *CertLoader) GetCertificate(_ *tls.ClientHelloInfo) (*tls.Certificate, error) {
cl.certMu.RLock()
defer cl.certMu.RUnlock()
return cl.cert, nil
}
func (cl *CertLoader) watch() {
+2 -5
View File
@@ -28,10 +28,7 @@ func TestCertReload(t *testing.T) {
require.NoError(t, err)
defer loader.Close()
getCert := loader.GetCertificate()
require.NotNil(t, getCert)
cert, err := getCert(nil)
cert, err := loader.GetCertificate(nil)
require.NoError(t, err)
require.NotNil(t, cert)
require.Equal(t, &testData, cert)
@@ -47,7 +44,7 @@ func TestCertReload(t *testing.T) {
time.Sleep(1 * time.Second)
cert, err = getCert(nil)
cert, err = loader.GetCertificate(nil)
require.NoError(t, err)
require.NotNil(t, cert)
require.Equal(t, &testData, cert)
+22 -13
View File
@@ -43,6 +43,7 @@ type Server struct {
ServerCert string
ServerKey string
AllowAutoCert bool
GetCertificate func(*tls.ClientHelloInfo) (*tls.Certificate, error)
Handler http.Handler
Parent logger.Writer
@@ -64,23 +65,31 @@ func (s *Server) Initialize() error {
var tlsConfig *tls.Config
if s.Encryption {
if s.ServerCert == "" {
return fmt.Errorf("server cert is missing")
}
var getCertificate func(*tls.ClientHelloInfo) (*tls.Certificate, error)
s.loader = &certloader.CertLoader{
CertPath: s.ServerCert,
KeyPath: s.ServerKey,
AllowAuto: s.AllowAutoCert,
Parent: s.Parent,
}
err := s.loader.Initialize()
if err != nil {
return err
if s.GetCertificate != nil {
getCertificate = s.GetCertificate
} else {
if s.ServerCert == "" {
return fmt.Errorf("server cert is missing")
}
s.loader = &certloader.CertLoader{
CertPath: s.ServerCert,
KeyPath: s.ServerKey,
AllowAuto: s.AllowAutoCert,
Parent: s.Parent,
}
err := s.loader.Initialize()
if err != nil {
return err
}
getCertificate = s.loader.GetCertificate
}
tlsConfig = &tls.Config{
GetCertificate: s.loader.GetCertificate(),
GetCertificate: getCertificate,
}
}
+9 -12
View File
@@ -104,8 +104,7 @@ type httpServerParent interface {
type httpServer struct {
http2Address string
http3Address string
serverCert string
serverKey string
getCertificate func(*tls.ClientHelloInfo) (*tls.Certificate, error)
allowOrigins []string
trustedProxies conf.IPNetworks
udpReadBufferSize uint
@@ -125,16 +124,14 @@ func (s *httpServer) initialize() error {
routerHTTP2.Use(s.onRequestHTTPS2)
s.innerHTTP2 = &httpp.Server{
Address: s.http2Address,
AllowOrigins: s.allowOrigins,
ReadTimeout: time.Duration(s.readTimeout),
WriteTimeout: time.Duration(s.writeTimeout),
Encryption: true,
ServerKey: s.serverKey,
ServerCert: s.serverCert,
AllowAutoCert: true,
Handler: routerHTTP2,
Parent: s,
Address: s.http2Address,
AllowOrigins: s.allowOrigins,
ReadTimeout: time.Duration(s.readTimeout),
WriteTimeout: time.Duration(s.writeTimeout),
Encryption: true,
GetCertificate: s.getCertificate,
Handler: routerHTTP2,
Parent: s,
}
err := s.innerHTTP2.Initialize()
if err != nil {
+3 -12
View File
@@ -3,7 +3,6 @@ package moq
import (
"context"
"crypto/tls"
"fmt"
"net"
"os"
"strings"
@@ -29,8 +28,7 @@ type nativeListenerParent interface {
type nativeListener struct {
address string
serverKey string
serverCert string
getCertificate func(*tls.ClientHelloInfo) (*tls.Certificate, error)
udpReadBufferSize uint
parent nativeListenerParent
@@ -65,16 +63,9 @@ func (s *nativeListener) initialize() error {
}
}
cert, err := tls.LoadX509KeyPair(s.serverCert, s.serverKey)
if err != nil {
s.ln.Close()
ctxCancel()
return fmt.Errorf("unable to load TLS keypair for native MoQ QUIC listener: %w", err)
}
tlsConfig := &tls.Config{
Certificates: []tls.Certificate{cert},
NextProtos: supportedMoqtALPNs,
GetCertificate: s.getCertificate,
NextProtos: supportedMoqtALPNs,
}
listener, err := quic.Listen(s.ln, tlsConfig, &quic.Config{
+23 -5
View File
@@ -10,6 +10,7 @@ import (
"github.com/google/uuid"
"github.com/bluenviron/mediamtx/internal/certloader"
"github.com/bluenviron/mediamtx/internal/conf"
"github.com/bluenviron/mediamtx/internal/defs"
"github.com/bluenviron/mediamtx/internal/logger"
@@ -95,6 +96,7 @@ type Server struct {
ctx context.Context
ctxCancel context.CancelFunc
loader *certloader.CertLoader
httpServer *httpServer
nativeListener *nativeListener
sessions map[*session]struct{}
@@ -121,11 +123,22 @@ func (s *Server) Initialize() error {
s.chAPISessionsKick = make(chan serverAPISessionsKickReq)
s.done = make(chan struct{})
s.loader = &certloader.CertLoader{
CertPath: s.ServerCert,
KeyPath: s.ServerKey,
AllowAuto: true,
Parent: s,
}
err := s.loader.Initialize()
if err != nil {
ctxCancel()
return err
}
s.httpServer = &httpServer{
http2Address: s.HTTP2Address,
http3Address: s.HTTP3Address,
serverKey: s.ServerKey,
serverCert: s.ServerCert,
getCertificate: s.loader.GetCertificate,
allowOrigins: s.AllowOrigins,
trustedProxies: s.TrustedProxies,
udpReadBufferSize: s.UDPReadBufferSize,
@@ -134,22 +147,23 @@ func (s *Server) Initialize() error {
pathManager: s.PathManager,
parent: s,
}
err := s.httpServer.initialize()
err = s.httpServer.initialize()
if err != nil {
s.loader.Close()
ctxCancel()
return err
}
s.nativeListener = &nativeListener{
address: s.QUICAddress,
serverKey: s.ServerKey,
serverCert: s.ServerCert,
getCertificate: s.loader.GetCertificate,
udpReadBufferSize: s.UDPReadBufferSize,
parent: s,
}
err = s.nativeListener.initialize()
if err != nil {
s.httpServer.close()
s.loader.Close()
ctxCancel()
return err
}
@@ -268,6 +282,10 @@ outer:
s.httpServer.close()
if s.loader != nil {
s.loader.Close()
}
wg.Wait()
}
+1 -1
View File
@@ -172,7 +172,7 @@ func (s *Server) Initialize() error {
}
net, addr := restrictnetwork.Restrict("tcp", s.Address)
s.ln, err = tlsListen(net, addr, &tls.Config{GetCertificate: s.loader.GetCertificate()})
s.ln, err = tlsListen(net, addr, &tls.Config{GetCertificate: s.loader.GetCertificate})
if err != nil {
return err
}
+1 -1
View File
@@ -166,7 +166,7 @@ func (s *Server) Initialize() error {
return err
}
s.srv.TLSConfig = &tls.Config{GetCertificate: s.loader.GetCertificate()}
s.srv.TLSConfig = &tls.Config{GetCertificate: s.loader.GetCertificate}
}
s.srv.Listen = func(network, address string) (net.Listener, error) {