Moved v3 code from NginxProxyManager/nginx-proxy-manager-3 to NginxProxyManager/nginx-proxy-manager
This commit is contained in:
28
backend/internal/config/args.go
Normal file
28
backend/internal/config/args.go
Normal file
@ -0,0 +1,28 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/alexflint/go-arg"
|
||||
)
|
||||
|
||||
// ArgConfig is the settings for passing arguments to the command
|
||||
type ArgConfig struct {
|
||||
Version bool `arg:"-v" help:"print version and exit"`
|
||||
}
|
||||
|
||||
var (
|
||||
appArguments ArgConfig
|
||||
)
|
||||
|
||||
// InitArgs will parse arg vars
|
||||
func InitArgs(version, commit *string) {
|
||||
// nolint: errcheck, gosec
|
||||
arg.MustParse(&appArguments)
|
||||
|
||||
if appArguments.Version {
|
||||
fmt.Printf("v%s (%s)\n", *version, *commit)
|
||||
os.Exit(0)
|
||||
}
|
||||
}
|
79
backend/internal/config/config.go
Normal file
79
backend/internal/config/config.go
Normal file
@ -0,0 +1,79 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
golog "log"
|
||||
"runtime"
|
||||
|
||||
"npm/internal/logger"
|
||||
|
||||
"github.com/getsentry/sentry-go"
|
||||
"github.com/vrischmann/envconfig"
|
||||
)
|
||||
|
||||
// Init will parse environment variables into the Env struct
|
||||
func Init(version, commit, sentryDSN *string) {
|
||||
// ErrorReporting is enabled until we load the status of it from the DB later
|
||||
ErrorReporting = true
|
||||
|
||||
Version = *version
|
||||
Commit = *commit
|
||||
|
||||
if err := envconfig.InitWithPrefix(&Configuration, "NPM"); err != nil {
|
||||
fmt.Printf("%+v\n", err)
|
||||
}
|
||||
|
||||
initLogger(*sentryDSN)
|
||||
logger.Info("Build Version: %s (%s)", Version, Commit)
|
||||
createDataFolders()
|
||||
loadKeys()
|
||||
}
|
||||
|
||||
// Init initialises the Log object and return it
|
||||
func initLogger(sentryDSN string) {
|
||||
// this removes timestamp prefixes from logs
|
||||
golog.SetFlags(0)
|
||||
|
||||
switch Configuration.Log.Level {
|
||||
case "debug":
|
||||
logLevel = logger.DebugLevel
|
||||
case "warn":
|
||||
logLevel = logger.WarnLevel
|
||||
case "error":
|
||||
logLevel = logger.ErrorLevel
|
||||
default:
|
||||
logLevel = logger.InfoLevel
|
||||
}
|
||||
|
||||
err := logger.Configure(&logger.Config{
|
||||
LogThreshold: logLevel,
|
||||
Formatter: Configuration.Log.Format,
|
||||
SentryConfig: sentry.ClientOptions{
|
||||
// This is the jc21 NginxProxyManager Sentry project,
|
||||
// errors will be reported here (if error reporting is enable)
|
||||
// and this project is private. No personal information should
|
||||
// be sent in any error messages, only stacktraces.
|
||||
Dsn: sentryDSN,
|
||||
Release: Commit,
|
||||
Dist: Version,
|
||||
Environment: fmt.Sprintf("%s-%s", runtime.GOOS, runtime.GOARCH),
|
||||
},
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
logger.Error("LoggerConfigurationError", err)
|
||||
}
|
||||
}
|
||||
|
||||
// GetLogLevel returns the logger const level
|
||||
func GetLogLevel() logger.Level {
|
||||
return logLevel
|
||||
}
|
||||
|
||||
func isError(errorClass string, err error) bool {
|
||||
if err != nil {
|
||||
logger.Error(errorClass, err)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
34
backend/internal/config/folders.go
Normal file
34
backend/internal/config/folders.go
Normal file
@ -0,0 +1,34 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"npm/internal/logger"
|
||||
"os"
|
||||
)
|
||||
|
||||
// createDataFolders will recursively create these folders within the
|
||||
// data folder defined in configuration.
|
||||
func createDataFolders() {
|
||||
folders := []string{
|
||||
"access",
|
||||
"certificates",
|
||||
"logs",
|
||||
// Acme.sh:
|
||||
Configuration.Acmesh.GetWellknown(),
|
||||
// Nginx:
|
||||
"nginx/hosts",
|
||||
"nginx/streams",
|
||||
"nginx/temp",
|
||||
}
|
||||
|
||||
for _, folder := range folders {
|
||||
path := folder
|
||||
if path[0:1] != "/" {
|
||||
path = fmt.Sprintf("%s/%s", Configuration.DataFolder, folder)
|
||||
}
|
||||
logger.Debug("Creating folder: %s", path)
|
||||
if err := os.MkdirAll(path, os.ModePerm); err != nil {
|
||||
logger.Error("CreateDataFolderError", err)
|
||||
}
|
||||
}
|
||||
}
|
112
backend/internal/config/keys.go
Normal file
112
backend/internal/config/keys.go
Normal file
@ -0,0 +1,112 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"encoding/asn1"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
"npm/internal/logger"
|
||||
)
|
||||
|
||||
var keysFolder string
|
||||
var publicKeyFile string
|
||||
var privateKeyFile string
|
||||
|
||||
func loadKeys() {
|
||||
// check if keys folder exists in data folder
|
||||
keysFolder = fmt.Sprintf("%s/keys", Configuration.DataFolder)
|
||||
publicKeyFile = fmt.Sprintf("%s/public.key", keysFolder)
|
||||
privateKeyFile = fmt.Sprintf("%s/private.key", keysFolder)
|
||||
|
||||
if _, err := os.Stat(keysFolder); os.IsNotExist(err) {
|
||||
// nolint:errcheck,gosec
|
||||
os.Mkdir(keysFolder, 0700)
|
||||
}
|
||||
|
||||
// check if keys exist on disk
|
||||
_, publicKeyErr := os.Stat(publicKeyFile)
|
||||
_, privateKeyErr := os.Stat(privateKeyFile)
|
||||
|
||||
// generate keys if either one doesn't exist
|
||||
if os.IsNotExist(publicKeyErr) || os.IsNotExist(privateKeyErr) {
|
||||
generateKeys()
|
||||
saveKeys()
|
||||
}
|
||||
|
||||
// Load keys from disk
|
||||
// nolint:gosec
|
||||
publicKeyBytes, publicKeyBytesErr := ioutil.ReadFile(publicKeyFile)
|
||||
// nolint:gosec
|
||||
privateKeyBytes, privateKeyBytesErr := ioutil.ReadFile(privateKeyFile)
|
||||
PublicKey = string(publicKeyBytes)
|
||||
PrivateKey = string(privateKeyBytes)
|
||||
|
||||
if isError("PublicKeyReadError", publicKeyBytesErr) || isError("PrivateKeyReadError", privateKeyBytesErr) || PublicKey == "" || PrivateKey == "" {
|
||||
logger.Warn("There was an error loading keys, proceeding to generate new RSA keys")
|
||||
generateKeys()
|
||||
saveKeys()
|
||||
}
|
||||
}
|
||||
|
||||
func generateKeys() {
|
||||
reader := rand.Reader
|
||||
bitSize := 4096
|
||||
|
||||
key, err := rsa.GenerateKey(reader, bitSize)
|
||||
if isError("RSAGenerateError", err) {
|
||||
return
|
||||
}
|
||||
|
||||
privateKey := &pem.Block{
|
||||
Type: "PRIVATE KEY",
|
||||
Bytes: x509.MarshalPKCS1PrivateKey(key),
|
||||
}
|
||||
|
||||
privateKeyBuffer := new(bytes.Buffer)
|
||||
err = pem.Encode(privateKeyBuffer, privateKey)
|
||||
if isError("PrivatePEMEncodeError", err) {
|
||||
return
|
||||
}
|
||||
|
||||
asn1Bytes, err2 := asn1.Marshal(key.PublicKey)
|
||||
if isError("RSAMarshalError", err2) {
|
||||
return
|
||||
}
|
||||
|
||||
publicKey := &pem.Block{
|
||||
Type: "PUBLIC KEY",
|
||||
Bytes: asn1Bytes,
|
||||
}
|
||||
|
||||
publicKeyBuffer := new(bytes.Buffer)
|
||||
err = pem.Encode(publicKeyBuffer, publicKey)
|
||||
if isError("PublicPEMEncodeError", err) {
|
||||
return
|
||||
}
|
||||
|
||||
PublicKey = publicKeyBuffer.String()
|
||||
PrivateKey = privateKeyBuffer.String()
|
||||
logger.Info("Generated new RSA keys")
|
||||
}
|
||||
|
||||
func saveKeys() {
|
||||
err := ioutil.WriteFile(publicKeyFile, []byte(PublicKey), 0600)
|
||||
if err != nil {
|
||||
logger.Error("PublicKeyWriteError", err)
|
||||
} else {
|
||||
logger.Info("Saved Public Key: %s", publicKeyFile)
|
||||
}
|
||||
|
||||
err = ioutil.WriteFile(privateKeyFile, []byte(PrivateKey), 0600)
|
||||
if err != nil {
|
||||
logger.Error("PrivateKeyWriteError", err)
|
||||
} else {
|
||||
logger.Info("Saved Private Key: %s", privateKeyFile)
|
||||
}
|
||||
}
|
49
backend/internal/config/vars.go
Normal file
49
backend/internal/config/vars.go
Normal file
@ -0,0 +1,49 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"npm/internal/logger"
|
||||
)
|
||||
|
||||
// Version is the version set by ldflags
|
||||
var Version string
|
||||
|
||||
// Commit is the git commit set by ldflags
|
||||
var Commit string
|
||||
|
||||
// IsSetup defines whether we have an admin user or not
|
||||
var IsSetup bool
|
||||
|
||||
// ErrorReporting defines whether we will send errors to Sentry
|
||||
var ErrorReporting bool
|
||||
|
||||
// PublicKey is the public key
|
||||
var PublicKey string
|
||||
|
||||
// PrivateKey is the private key
|
||||
var PrivateKey string
|
||||
|
||||
var logLevel logger.Level
|
||||
|
||||
type log struct {
|
||||
Level string `json:"level" envconfig:"optional,default=info"`
|
||||
Format string `json:"format" envconfig:"optional,default=nice"`
|
||||
}
|
||||
|
||||
type acmesh struct {
|
||||
Home string `json:"home" envconfig:"optional,default=/data/.acme.sh"`
|
||||
ConfigHome string `json:"config_home" envconfig:"optional,default=/data/.acme.sh/config"`
|
||||
CertHome string `json:"cert_home" envconfig:"optional,default=/data/.acme.sh/certs"`
|
||||
}
|
||||
|
||||
// Configuration is the main configuration object
|
||||
var Configuration struct {
|
||||
DataFolder string `json:"data_folder" envconfig:"optional,default=/data"`
|
||||
Acmesh acmesh `json:"acmesh"`
|
||||
Log log `json:"log"`
|
||||
}
|
||||
|
||||
// GetWellknown returns the well known path
|
||||
func (a *acmesh) GetWellknown() string {
|
||||
return fmt.Sprintf("%s/.well-known", a.Home)
|
||||
}
|
Reference in New Issue
Block a user