11package main
22
33import (
4- "errors "
4+ "context "
55 "fmt"
66 "log"
77 "net/http"
88 "os"
9- "path/filepath"
109 "runtime"
1110 "runtime/pprof"
1211
12+ "github.com/PowerDNS/go-tlsconfig"
13+ "github.com/c2h5oh/datasize"
1314 restserver "github.com/restic/rest-server"
15+ "github.com/restic/rest-server/config"
1416 "github.com/spf13/cobra"
1517)
1618
@@ -25,57 +27,37 @@ var cmdRoot = &cobra.Command{
2527 //Version: fmt.Sprintf("rest-server %s compiled with %v on %v/%v\n", version, runtime.Version(), runtime.GOOS, runtime.GOARCH),
2628}
2729
28- var server = restserver.Server {
29- Path : "/tmp/restic" ,
30- Listen : ":8000" ,
31- }
32-
3330var (
34- showVersion bool
35- cpuProfile string
31+ showVersion bool
32+ cpuProfile string
33+ maxSizeBytes uint64
34+ tlsEnabled bool
35+ configFile string
36+ flagConfig = config.Config {}
3637)
3738
3839func init () {
3940 flags := cmdRoot .Flags ()
41+ flags .StringVarP (& configFile , "config" , "c" , configFile , "path to YAML config file" )
4042 flags .StringVar (& cpuProfile , "cpu-profile" , cpuProfile , "write CPU profile to file" )
41- flags .BoolVar (& server .Debug , "debug" , server .Debug , "output debug messages" )
42- flags .StringVar (& server .Listen , "listen" , server .Listen , "listen address" )
43- flags .StringVar (& server . Log , "log" , server . Log , "log HTTP requests in the combined log format" )
44- flags .Int64Var ( & server . MaxRepoSize , "max-size" , server . MaxRepoSize , "the maximum size of the repository in bytes" )
45- flags .StringVar (& server .Path , "path" , server .Path , "data directory" )
46- flags .BoolVar (& server . TLS , "tls" , server .TLS , "turn on TLS support" )
47- flags .StringVar (& server . TLSCert , "tls-cert" , server . TLSCert , "TLS certificate path" )
48- flags .StringVar (& server . TLSKey , "tls-key" , server . TLSKey , "TLS key path" )
49- flags .BoolVar (& server . NoAuth , "no-auth" , server . NoAuth , "disable .htpasswd authentication" )
50- flags .BoolVar (& server .AppendOnly , "append-only" , server .AppendOnly , "enable append only mode" )
51- flags .BoolVar (& server .PrivateRepos , "private-repos" , server .PrivateRepos , "users can only access their private repo" )
52- flags .BoolVar (& server . Prometheus , "prometheus" , server . Prometheus , "enable Prometheus metrics" )
53- flags .BoolVar (& server . Prometheus , "prometheus-no-auth" , server . PrometheusNoAuth , "disable auth for Prometheus /metrics endpoint" )
43+ flags .BoolVar (& flagConfig .Debug , "debug" , flagConfig .Debug , "output debug messages" )
44+ flags .StringVar (& flagConfig .Listen , "listen" , flagConfig .Listen , "listen address" )
45+ flags .StringVar (& flagConfig . AccessLog , "log" , flagConfig . AccessLog , "log HTTP requests in the combined log format" )
46+ flags .Uint64Var ( & maxSizeBytes , "max-size" , uint64 ( flagConfig . Quota . MaxSize ) , "the maximum size of the repository in bytes" )
47+ flags .StringVar (& flagConfig .Path , "path" , flagConfig .Path , "data directory" )
48+ flags .BoolVar (& tlsEnabled , "tls" , flagConfig .TLS . HasCertWithKey () , "turn on TLS support" )
49+ flags .StringVar (& flagConfig . TLS . CertFile , "tls-cert" , flagConfig . TLS . CertFile , "TLS certificate path" )
50+ flags .StringVar (& flagConfig . TLS . KeyFile , "tls-key" , flagConfig . TLS . KeyFile , "TLS key path" )
51+ flags .BoolVar (& flagConfig . Auth . Disabled , "no-auth" , flagConfig . Auth . Disabled , "disable .htpasswd authentication" )
52+ flags .BoolVar (& flagConfig .AppendOnly , "append-only" , flagConfig .AppendOnly , "enable append only mode" )
53+ flags .BoolVar (& flagConfig .PrivateRepos , "private-repos" , flagConfig .PrivateRepos , "users can only access their private repo" )
54+ flags .BoolVar (& flagConfig . Metrics . Enabled , "prometheus" , flagConfig . Metrics . Enabled , "enable Prometheus metrics" )
55+ flags .BoolVar (& flagConfig . Metrics . NoAuth , "prometheus-no-auth" , flagConfig . Metrics . NoAuth , "disable auth for Prometheus /metrics endpoint" )
5456 flags .BoolVarP (& showVersion , "version" , "V" , showVersion , "output version and exit" )
5557}
5658
5759var version = "0.10.0-dev"
5860
59- func tlsSettings () (bool , string , string , error ) {
60- var key , cert string
61- if ! server .TLS && (server .TLSKey != "" || server .TLSCert != "" ) {
62- return false , "" , "" , errors .New ("requires enabled TLS" )
63- } else if ! server .TLS {
64- return false , "" , "" , nil
65- }
66- if server .TLSKey != "" {
67- key = server .TLSKey
68- } else {
69- key = filepath .Join (server .Path , "private_key" )
70- }
71- if server .TLSCert != "" {
72- cert = server .TLSCert
73- } else {
74- cert = filepath .Join (server .Path , "public_key" )
75- }
76- return server .TLS , key , cert , nil
77- }
78-
7961func runRoot (cmd * cobra.Command , args []string ) error {
8062 if showVersion {
8163 fmt .Printf ("rest-server %s compiled with %v on %v/%v\n " , version , runtime .Version (), runtime .GOOS , runtime .GOARCH )
@@ -84,7 +66,26 @@ func runRoot(cmd *cobra.Command, args []string) error {
8466
8567 log .SetFlags (0 )
8668
87- log .Printf ("Data directory: %s" , server .Path )
69+ // Load config
70+ conf := config .Default ()
71+ if configFile != "" {
72+ if err := conf .LoadYAMLFile (configFile ); err != nil {
73+ return err
74+ }
75+ }
76+
77+ // Merge flag config
78+ conf .Quota .MaxSize = datasize .ByteSize (maxSizeBytes )
79+ conf .MergeFlags (flagConfig )
80+ if conf .Debug {
81+ log .Printf ("Effective config:\n %s" , conf .String ())
82+ }
83+ if err := conf .Check (); err != nil {
84+ return err
85+ }
86+ if tlsEnabled && ! conf .TLS .HasCertWithKey () {
87+ return fmt .Errorf ("--tls set, but key and cert not configured" )
88+ }
8889
8990 if cpuProfile != "" {
9091 f , err := os .Create (cpuProfile )
@@ -98,40 +99,51 @@ func runRoot(cmd *cobra.Command, args []string) error {
9899 defer pprof .StopCPUProfile ()
99100 }
100101
101- if server .NoAuth {
102+ log .Printf ("Data directory: %s" , conf .Path )
103+ if conf .Auth .Disabled {
102104 log .Println ("Authentication disabled" )
103105 } else {
104106 log .Println ("Authentication enabled" )
105107 }
106-
107- handler , err := restserver .NewHandler (& server )
108- if err != nil {
109- log .Fatalf ("error: %v" , err )
110- }
111-
112- if server .PrivateRepos {
108+ if conf .PrivateRepos {
113109 log .Println ("Private repositories enabled" )
114110 } else {
115111 log .Println ("Private repositories disabled" )
116112 }
117113
118- enabledTLS , privateKey , publicKey , err := tlsSettings ()
114+ server , err := restserver .NewServer (* conf )
115+ if err != nil {
116+ return err
117+ }
118+ handler , err := restserver .NewHandler (server )
119119 if err != nil {
120120 return err
121121 }
122- if ! enabledTLS {
123- log .Printf ("Starting server on %s\n " , server .Listen )
124- err = http .ListenAndServe (server .Listen , handler )
125- } else {
126122
123+ ctx := context .Background ()
124+ if ! conf .TLS .HasCertWithKey () {
125+ log .Printf ("Starting server on %s\n " , conf .Listen )
126+ return http .ListenAndServe (conf .Listen , handler )
127+ } else {
127128 log .Println ("TLS enabled" )
128- log .Printf ("Private key: %s" , privateKey )
129- log .Printf ("Public key(certificate): %s" , publicKey )
130- log .Printf ("Starting server on %s\n " , server .Listen )
131- err = http .ListenAndServeTLS (server .Listen , publicKey , privateKey , handler )
129+ log .Printf ("Starting server on %s\n " , conf .Listen )
130+ manager , err := tlsconfig .NewManager (ctx , conf .TLS , tlsconfig.Options {
131+ IsServer : true ,
132+ })
133+ if err != nil {
134+ return err
135+ }
136+ tlsConfig , err := manager .TLSConfig ()
137+ if err != nil {
138+ return err
139+ }
140+ hs := http.Server {
141+ Addr : conf .Listen ,
142+ Handler : handler ,
143+ TLSConfig : tlsConfig ,
144+ }
145+ return hs .ListenAndServeTLS ("" , "" ) // Certificates are handled by TLSConfig
132146 }
133-
134- return err
135147}
136148
137149func main () {
0 commit comments