make CLI configurable

This commit is contained in:
m5r
2024-07-26 12:16:23 +02:00
parent c3220327e1
commit c7989fa736
15 changed files with 468 additions and 251 deletions

111
cmd/root.go Normal file
View File

@ -0,0 +1,111 @@
package cmd
import (
"fmt"
"net/mail"
"net/url"
"strings"
"time"
"github.com/asaskevich/govalidator"
"github.com/go-acme/lego/v4/lego"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"local-ip.sh/certs"
"local-ip.sh/http"
"local-ip.sh/utils"
"local-ip.sh/xip"
)
var command = &cobra.Command{
Use: "local-ip.sh",
PreRun: func(cmd *cobra.Command, args []string) {
viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_"))
viper.SetEnvPrefix("XIP")
viper.AutomaticEnv()
email := viper.GetString("Email")
_, err := mail.ParseAddress(email)
if err != nil {
utils.Logger.Fatal().Err(err).Msg("Invalid email address")
}
domain := viper.GetString("Domain")
if !govalidator.IsDNSName(domain) {
utils.Logger.Fatal().Err(err).Msg("Invalid domain")
}
nameservers := strings.Split(viper.GetString("nameservers"), ",")
for _, ns := range nameservers {
if !govalidator.IsIPv4(ns) {
utils.Logger.Fatal().Err(err).Str("ns", ns).Msg("Invalid name server")
}
}
viper.Set("NameServers", nameservers)
staging := viper.GetBool("staging")
var caDir string
if staging {
caDir = lego.LEDirectoryStaging
} else {
caDir = lego.LEDirectoryProduction
}
viper.Set("CADirURL", caDir)
parsedCaDirUrl, _ := url.Parse(caDir)
caDirHostname := parsedCaDirUrl.Hostname()
viper.Set("AccountFilePath", fmt.Sprintf("./.lego/accounts/%s/%s/account.json", caDirHostname, email))
viper.Set("KeyFilePath", fmt.Sprintf("./.lego/accounts/%s/%s/keys/%s.key", caDirHostname, email, email))
utils.InitConfig()
},
Run: func(cmd *cobra.Command, args []string) {
n := xip.NewXip()
go func() {
// try to obtain certificates once the DNS server is accepting requests
account := certs.LoadAccount()
certsClient := certs.NewCertsClient(n, account)
time.Sleep(5 * time.Second)
certsClient.RequestCertificates()
for {
// afterwards, try to renew certificates once a day
time.Sleep(24 * time.Hour)
certsClient.RequestCertificates()
}
}()
go http.ServeHttp()
n.StartServer()
},
}
func Execute() {
command.Flags().Uint("dns-port", 53, "Port for the DNS server")
viper.BindPFlag("dns-port", command.Flags().Lookup("dns-port"))
command.Flags().Uint("http-port", 80, "Port for the HTTP server")
viper.BindPFlag("http-port", command.Flags().Lookup("http-port"))
command.Flags().Uint("https-port", 443, "Port for the HTTPS server")
viper.BindPFlag("https-port", command.Flags().Lookup("https-port"))
command.Flags().Bool("staging", false, "Enable to use the Let's Encrypt staging environment to obtain certificates")
viper.BindPFlag("staging", command.Flags().Lookup("staging"))
command.Flags().String("domain", "", "Root domain (required)")
viper.BindPFlag("domain", command.Flags().Lookup("domain"))
command.Flags().String("email", "", "ACME account email address (required)")
viper.BindPFlag("email", command.Flags().Lookup("email"))
command.Flags().String("nameservers", "", "List of nameservers separated by commas (required)")
viper.BindPFlag("nameservers", command.Flags().Lookup("nameservers"))
if err := command.Execute(); err != nil {
utils.Logger.Fatal().Err(err).Msg("Failed to run local-ip.sh")
}
}