@@ -2,8 +2,8 @@ package runner
2
2
3
3
import (
4
4
"context"
5
- "crypto/tls"
6
5
"fmt"
6
+ "log"
7
7
"net"
8
8
"net/http"
9
9
"os"
@@ -13,6 +13,7 @@ import (
13
13
"time"
14
14
15
15
"github.com/gotify/server/v2/config"
16
+ "golang.org/x/crypto/acme"
16
17
"golang.org/x/crypto/acme/autocert"
17
18
)
18
19
@@ -31,6 +32,8 @@ func Run(router http.Handler, conf *config.Configuration) error {
31
32
if conf .Server .SSL .Enabled {
32
33
if conf .Server .SSL .LetsEncrypt .Enabled {
33
34
applyLetsEncrypt (s , conf )
35
+ } else if conf .Server .SSL .CertFile != "" && conf .Server .SSL .CertKey != "" {
36
+ log .Fatalf ("CertFile and CertKey must be set to use HTTPS when LetsEncrypt is disabled, please set GOTIFY_SERVER_SSL_CERTFILE and GOTIFY_SERVER_SSL_CERTKEY" )
34
37
}
35
38
36
39
httpsListener , err := startListening ("TLS connection" , conf .Server .SSL .ListenAddr , conf .Server .SSL .Port , conf .Server .KeepAlivePeriodSeconds )
@@ -94,12 +97,43 @@ func getNetworkAndAddr(listenAddr string, port int) (string, string) {
94
97
return "tcp" , fmt .Sprintf ("%s:%d" , listenAddr , port )
95
98
}
96
99
100
+ type LoggingRoundTripper struct {
101
+ RoundTripper http.RoundTripper
102
+ }
103
+
104
+ func (l * LoggingRoundTripper ) RoundTrip (r * http.Request ) (resp * http.Response , err error ) {
105
+ log .Printf ("Let's Encrypt Client Request: %s %s\n " , r .Method , r .URL .String ())
106
+ resp , err = l .RoundTripper .RoundTrip (r )
107
+ if resp .StatusCode == 429 {
108
+ log .Printf ("Let's Encrypt Client Rate Limited: Retry-After %s on %s %s\n " , resp .Header .Get ("Retry-After" ), r .Method , r .URL .String ())
109
+ } else if resp .StatusCode >= 400 {
110
+ log .Printf ("Let's Encrypt Client Request Failed: Unexpected status code %d on %s %s\n " , resp .StatusCode , r .Method , r .URL .String ())
111
+ } else if err != nil {
112
+ log .Printf ("Let's Encrypt Client Request Failed: %s on %s %s\n " , err .Error (), r .Method , r .URL .String ())
113
+ }
114
+ return
115
+ }
116
+
97
117
func applyLetsEncrypt (s * http.Server , conf * config.Configuration ) {
118
+ httpClient := http .DefaultClient
119
+ httpClient .Transport = & LoggingRoundTripper {RoundTripper : http .DefaultTransport }
120
+ httpClient .Timeout = 60 * time .Second
121
+
122
+ acmeClient := & acme.Client {
123
+ HTTPClient : httpClient ,
124
+ DirectoryURL : conf .Server .SSL .LetsEncrypt .DirectoryURL ,
125
+ }
98
126
certManager := autocert.Manager {
99
- Prompt : func (tosURL string ) bool { return conf .Server .SSL .LetsEncrypt .AcceptTOS },
127
+ Client : acmeClient ,
128
+ Prompt : func (tosURL string ) bool {
129
+ if ! conf .Server .SSL .LetsEncrypt .AcceptTOS {
130
+ log .Fatalf ("Let's Encrypt TOS must be accepted to use Let's Encrypt, please acknowledge TOS at %s and set GOTIFY_SERVER_SSL_LETSENCRYPT_ACCEPTTOS=true" , tosURL )
131
+ }
132
+ return true
133
+ },
100
134
HostPolicy : autocert .HostWhitelist (conf .Server .SSL .LetsEncrypt .Hosts ... ),
101
135
Cache : autocert .DirCache (conf .Server .SSL .LetsEncrypt .Cache ),
102
136
}
103
137
s .Handler = certManager .HTTPHandler (s .Handler )
104
- s .TLSConfig = & tls. Config { GetCertificate : certManager .GetCertificate }
138
+ s .TLSConfig = certManager .TLSConfig ()
105
139
}
0 commit comments