diff --git a/frontend/src/components/StdDataDisplay/StdTable.vue b/frontend/src/components/StdDataDisplay/StdTable.vue
index f7611d4e..1d64e96b 100644
--- a/frontend/src/components/StdDataDisplay/StdTable.vue
+++ b/frontend/src/components/StdDataDisplay/StdTable.vue
@@ -525,7 +525,7 @@ function initSortable() {
:okText="$gettext('OK')"
:title="$gettext('Are you sure you want to delete?')"
@confirm="destroy(record[rowKey])">
- Delete
+ {{ $gettext('Delete') }}
diff --git a/frontend/src/views/dashboard/DashBoard.vue b/frontend/src/views/dashboard/DashBoard.vue
index c535270f..e2487c20 100644
--- a/frontend/src/views/dashboard/DashBoard.vue
+++ b/frontend/src/views/dashboard/DashBoard.vue
@@ -164,7 +164,7 @@ function wsOnMessage(m: { data: any }) {
{{ $gettext('CPU:') + ' ' }}
- {{ cpu_info[0]?.modelName }}
+ {{ cpu_info[0]?.modelName || 'core' }}
{{ (cpu_info[0]?.mhz / 1000).toFixed(2) + 'GHz' }}
* {{ cpu_info.length }}
@@ -303,10 +303,6 @@ function wsOnMessage(m: { data: any }) {
}
}
-.os-platform {
- text-transform: capitalize;
-}
-
.load-avg-describe {
@media (max-width: 1600px) and (min-width: 1200px) {
display: none;
diff --git a/frontend/src/views/domain/DomainEdit.vue b/frontend/src/views/domain/DomainEdit.vue
index 6d9fe629..564a7ddb 100644
--- a/frontend/src/views/domain/DomainEdit.vue
+++ b/frontend/src/views/domain/DomainEdit.vue
@@ -25,7 +25,7 @@ watch(route, () => {
const update = ref(0)
const ngx_config = reactive({
- filename: '',
+ name: '',
upstreams: [],
servers: []
})
diff --git a/frontend/src/views/domain/cert/Cert.vue b/frontend/src/views/domain/cert/Cert.vue
index d32c51cd..f559432d 100644
--- a/frontend/src/views/domain/cert/Cert.vue
+++ b/frontend/src/views/domain/cert/Cert.vue
@@ -7,7 +7,7 @@ import ChangeCert from '@/views/domain/cert/ChangeCert.vue'
const {$gettext} = useGettext()
-const props = defineProps(['directivesMap', 'current_server_directives', 'enabled', 'cert_info'])
+const props = defineProps(['config_name', 'directivesMap', 'current_server_directives', 'enabled', 'cert_info'])
const emit = defineEmits(['callback', 'update:enabled'])
@@ -38,6 +38,7 @@ const enabled = computed({
import {useGettext} from 'vue3-gettext'
-import {computed, h, nextTick, onMounted, ref, VNode, watch} from 'vue'
+import {computed, nextTick, ref, watch} from 'vue'
import {message} from 'ant-design-vue'
import domain from '@/api/domain'
import websocket from '@/lib/websocket'
@@ -8,7 +8,7 @@ import Template from '@/views/template/Template.vue'
const {$gettext, interpolate} = useGettext()
-const props = defineProps(['directivesMap', 'current_server_directives', 'enabled'])
+const props = defineProps(['config_name', 'directivesMap', 'current_server_directives', 'enabled'])
const emit = defineEmits(['changeEnabled', 'callback', 'update:enabled'])
@@ -50,7 +50,7 @@ function job() {
})
}
}).then(() => {
- issue_cert(name.value, callback)
+ issue_cert(props.config_name, name.value, callback)
})
}
@@ -61,13 +61,13 @@ function callback(ssl_certificate: string, ssl_certificate_key: string) {
function change_auto_cert(r: boolean) {
if (r) {
- domain.add_auto_cert(name.value).then(() => {
+ domain.add_auto_cert(props.config_name).then(() => {
message.success(interpolate($gettext('Auto-renewal enabled for %{name}'), {name: name.value}))
}).catch(e => {
message.error(e.message ?? interpolate($gettext('Enable auto-renewal failed for %{name}'), {name: name.value}))
})
} else {
- domain.remove_auto_cert(name.value).then(() => {
+ domain.remove_auto_cert(props.config_name).then(() => {
message.success(interpolate($gettext('Auto-renewal disabled for %{name}'), {name: name.value}))
}).catch(e => {
message.error(e.message ?? interpolate($gettext('Disable auto-renewal failed for %{name}'), {name: name.value}))
@@ -86,7 +86,7 @@ function log(msg: string) {
(logContainer.value as any as Element).scroll({top: 320, left: 0, behavior: 'smooth'})
}
-const issue_cert = async (server_name: string, callback: Function) => {
+const issue_cert = async (config_name: string, server_name: string, callback: Function) => {
progressStatus.value = 'active'
modalClosable.value = false
modalVisible.value = true
@@ -95,7 +95,7 @@ const issue_cert = async (server_name: string, callback: Function) => {
log($gettext('Getting the certificate, please wait...'))
- const ws = websocket('/api/cert/issue', false)
+ const ws = websocket(`/api/domain/${config_name}/cert`, false)
ws.onopen = () => {
ws.send(JSON.stringify({
diff --git a/frontend/src/views/domain/ngx_conf/NgxConfigEditor.vue b/frontend/src/views/domain/ngx_conf/NgxConfigEditor.vue
index 1447162e..ef950c8c 100644
--- a/frontend/src/views/domain/ngx_conf/NgxConfigEditor.vue
+++ b/frontend/src/views/domain/ngx_conf/NgxConfigEditor.vue
@@ -168,6 +168,7 @@ watch(current_server_index, () => {
= nginx.Warn {
- c.JSON(http.StatusInternalServerError, gin.H{
- "message": output,
- "error": "nginx_config_syntax_error",
- })
- return
- }
+ enabledConfigFilePath = nginx.GetConfPath("sites-enabled", name)
+ if helper.FileExists(enabledConfigFilePath) {
+ // Test nginx configuration
+ output := nginx.TestConf()
+ if nginx.GetLogLevel(output) >= nginx.Warn {
+ c.JSON(http.StatusInternalServerError, gin.H{
+ "message": output,
+ "error": "nginx_config_syntax_error",
+ })
+ return
+ }
- output = nginx.Reload()
+ output = nginx.Reload()
- if nginx.GetLogLevel(output) >= nginx.Warn {
- c.JSON(http.StatusInternalServerError, gin.H{
- "message": output,
- })
- return
- }
- }
+ if nginx.GetLogLevel(output) >= nginx.Warn {
+ c.JSON(http.StatusInternalServerError, gin.H{
+ "message": output,
+ })
+ return
+ }
+ }
- GetDomain(c)
+ GetDomain(c)
}
func EnableDomain(c *gin.Context) {
- configFilePath := nginx.GetConfPath("sites-available", c.Param("name"))
- enabledConfigFilePath := nginx.GetConfPath("sites-enabled", c.Param("name"))
+ configFilePath := nginx.GetConfPath("sites-available", c.Param("name"))
+ enabledConfigFilePath := nginx.GetConfPath("sites-enabled", c.Param("name"))
- _, err := os.Stat(configFilePath)
+ _, err := os.Stat(configFilePath)
- if err != nil {
- ErrHandler(c, err)
- return
- }
+ if err != nil {
+ ErrHandler(c, err)
+ return
+ }
- if _, err = os.Stat(enabledConfigFilePath); os.IsNotExist(err) {
- err = os.Symlink(configFilePath, enabledConfigFilePath)
+ if _, err = os.Stat(enabledConfigFilePath); os.IsNotExist(err) {
+ err = os.Symlink(configFilePath, enabledConfigFilePath)
- if err != nil {
- ErrHandler(c, err)
- return
- }
- }
+ if err != nil {
+ ErrHandler(c, err)
+ return
+ }
+ }
- // Test nginx config, if not pass then disable the site.
- output := nginx.TestConf()
+ // Test nginx config, if not pass then disable the site.
+ output := nginx.TestConf()
- if nginx.GetLogLevel(output) >= nginx.Warn {
- _ = os.Remove(enabledConfigFilePath)
- c.JSON(http.StatusInternalServerError, gin.H{
- "message": output,
- })
- return
- }
+ if nginx.GetLogLevel(output) >= nginx.Warn {
+ _ = os.Remove(enabledConfigFilePath)
+ c.JSON(http.StatusInternalServerError, gin.H{
+ "message": output,
+ })
+ return
+ }
- output = nginx.Reload()
+ output = nginx.Reload()
- if nginx.GetLogLevel(output) >= nginx.Warn {
- c.JSON(http.StatusInternalServerError, gin.H{
- "message": output,
- })
- return
- }
+ if nginx.GetLogLevel(output) >= nginx.Warn {
+ c.JSON(http.StatusInternalServerError, gin.H{
+ "message": output,
+ })
+ return
+ }
- c.JSON(http.StatusOK, gin.H{
- "message": "ok",
- })
+ c.JSON(http.StatusOK, gin.H{
+ "message": "ok",
+ })
}
func DisableDomain(c *gin.Context) {
- enabledConfigFilePath := nginx.GetConfPath("sites-enabled", c.Param("name"))
+ enabledConfigFilePath := nginx.GetConfPath("sites-enabled", c.Param("name"))
- _, err := os.Stat(enabledConfigFilePath)
+ _, err := os.Stat(enabledConfigFilePath)
- if err != nil {
- ErrHandler(c, err)
- return
- }
+ if err != nil {
+ ErrHandler(c, err)
+ return
+ }
- err = os.Remove(enabledConfigFilePath)
+ err = os.Remove(enabledConfigFilePath)
- if err != nil {
- ErrHandler(c, err)
- return
- }
+ if err != nil {
+ ErrHandler(c, err)
+ return
+ }
- // delete auto cert record
- certModel := model.Cert{Domain: c.Param("name")}
- err = certModel.Remove()
- if err != nil {
- ErrHandler(c, err)
- return
- }
+ // delete auto cert record
+ certModel := model.Cert{Filename: c.Param("name")}
+ err = certModel.Remove()
+ if err != nil {
+ ErrHandler(c, err)
+ return
+ }
- output := nginx.Reload()
+ output := nginx.Reload()
- if nginx.GetLogLevel(output) >= nginx.Warn {
- c.JSON(http.StatusInternalServerError, gin.H{
- "message": output,
- })
- return
- }
+ if nginx.GetLogLevel(output) >= nginx.Warn {
+ c.JSON(http.StatusInternalServerError, gin.H{
+ "message": output,
+ })
+ return
+ }
- c.JSON(http.StatusOK, gin.H{
- "message": "ok",
- })
+ c.JSON(http.StatusOK, gin.H{
+ "message": "ok",
+ })
}
func DeleteDomain(c *gin.Context) {
- var err error
- name := c.Param("name")
- availablePath := nginx.GetConfPath("sites-available", name)
- enabledPath := nginx.GetConfPath("sites-enabled", name)
+ var err error
+ name := c.Param("name")
+ availablePath := nginx.GetConfPath("sites-available", name)
+ enabledPath := nginx.GetConfPath("sites-enabled", name)
- if _, err = os.Stat(availablePath); os.IsNotExist(err) {
- c.JSON(http.StatusNotFound, gin.H{
- "message": "site not found",
- })
- return
- }
+ if _, err = os.Stat(availablePath); os.IsNotExist(err) {
+ c.JSON(http.StatusNotFound, gin.H{
+ "message": "site not found",
+ })
+ return
+ }
- if _, err = os.Stat(enabledPath); err == nil {
- c.JSON(http.StatusNotAcceptable, gin.H{
- "message": "site is enabled",
- })
- return
- }
+ if _, err = os.Stat(enabledPath); err == nil {
+ c.JSON(http.StatusNotAcceptable, gin.H{
+ "message": "site is enabled",
+ })
+ return
+ }
- certModel := model.Cert{Domain: name}
- _ = certModel.Remove()
+ certModel := model.Cert{Filename: name}
+ _ = certModel.Remove()
- err = os.Remove(availablePath)
+ err = os.Remove(availablePath)
- if err != nil {
- ErrHandler(c, err)
- return
- }
+ if err != nil {
+ ErrHandler(c, err)
+ return
+ }
- c.JSON(http.StatusOK, gin.H{
- "message": "ok",
- })
+ c.JSON(http.StatusOK, gin.H{
+ "message": "ok",
+ })
}
func AddDomainToAutoCert(c *gin.Context) {
- domain := c.Param("domain")
- domain = strings.ReplaceAll(domain, " ", "_")
- certModel, err := model.FirstOrCreateCert(domain)
+ name := c.Param("name")
+ certModel, err := model.FirstOrCreateCert(name)
- if err != nil {
- ErrHandler(c, err)
- return
- }
+ if err != nil {
+ ErrHandler(c, err)
+ return
+ }
- err = certModel.Updates(&model.Cert{
- AutoCert: model.AutoCertEnabled,
- })
+ err = certModel.Updates(&model.Cert{
+ AutoCert: model.AutoCertEnabled,
+ })
- if err != nil {
- ErrHandler(c, err)
- return
- }
+ if err != nil {
+ ErrHandler(c, err)
+ return
+ }
- c.JSON(http.StatusOK, certModel)
+ c.JSON(http.StatusOK, certModel)
}
func RemoveDomainFromAutoCert(c *gin.Context) {
- domain := c.Param("domain")
- domain = strings.ReplaceAll(domain, " ", "_")
- certModel := model.Cert{
- Domain: domain,
- }
+ name := c.Param("name")
+ certModel := model.Cert{
+ Filename: name,
+ }
- err := certModel.Updates(&model.Cert{
- AutoCert: model.AutoCertDisabled,
- })
+ err := certModel.Updates(&model.Cert{
+ AutoCert: model.AutoCertDisabled,
+ })
- if err != nil {
- ErrHandler(c, err)
- return
- }
- c.JSON(http.StatusOK, nil)
+ if err != nil {
+ ErrHandler(c, err)
+ return
+ }
+ c.JSON(http.StatusOK, nil)
}
func DuplicateSite(c *gin.Context) {
- name := c.Param("name")
+ name := c.Param("name")
- var json struct {
- Name string `json:"name" binding:"required"`
- }
+ var json struct {
+ Name string `json:"name" binding:"required"`
+ }
- if !BindAndValid(c, &json) {
- return
- }
+ if !BindAndValid(c, &json) {
+ return
+ }
- src := nginx.GetConfPath("sites-available", name)
- dst := nginx.GetConfPath("sites-available", json.Name)
+ src := nginx.GetConfPath("sites-available", name)
+ dst := nginx.GetConfPath("sites-available", json.Name)
- if helper.FileExists(dst) {
- c.JSON(http.StatusNotAcceptable, gin.H{
- "message": "File exists",
- })
- return
- }
+ if helper.FileExists(dst) {
+ c.JSON(http.StatusNotAcceptable, gin.H{
+ "message": "File exists",
+ })
+ return
+ }
- _, err := helper.CopyFile(src, dst)
+ _, err := helper.CopyFile(src, dst)
- if err != nil {
- ErrHandler(c, err)
- return
- }
+ if err != nil {
+ ErrHandler(c, err)
+ return
+ }
- c.JSON(http.StatusOK, gin.H{
- "dst": dst,
- })
+ c.JSON(http.StatusOK, gin.H{
+ "dst": dst,
+ })
}
diff --git a/server/model/cert.go b/server/model/cert.go
index ece89584..c3b1ef0d 100644
--- a/server/model/cert.go
+++ b/server/model/cert.go
@@ -2,6 +2,7 @@ package model
import (
"github.com/0xJacky/Nginx-UI/server/pkg/nginx"
+ "github.com/lib/pq"
"os"
)
@@ -10,28 +11,35 @@ const (
AutoCertDisabled = -1
)
+type CertDomains []string
+
type Cert struct {
Model
- Name string `json:"name"`
- Domain string `json:"domain"`
- SSLCertificatePath string `json:"ssl_certificate_path"`
- SSLCertificateKeyPath string `json:"ssl_certificate_key_path"`
- AutoCert int `json:"auto_cert"`
+ Name string `json:"name"`
+ Domains pq.StringArray `json:"domains" gorm:"type:text[]"`
+ Filename string `json:"filename"`
+ SSLCertificatePath string `json:"ssl_certificate_path"`
+ SSLCertificateKeyPath string `json:"ssl_certificate_key_path"`
+ AutoCert int `json:"auto_cert"`
}
-func FirstCert(domain string) (c Cert, err error) {
+func FirstCert(confName string) (c Cert, err error) {
err = db.First(&c, &Cert{
- Domain: domain,
+ Filename: confName,
}).Error
return
}
-func FirstOrCreateCert(domain string) (c Cert, err error) {
- err = db.FirstOrCreate(&c, &Cert{Domain: domain}).Error
+func FirstOrCreateCert(confName string) (c Cert, err error) {
+ err = db.FirstOrCreate(&c, &Cert{Filename: confName}).Error
return
}
+func (c *Cert) Insert() error {
+ return db.Create(c).Error
+}
+
func GetAutoCertList() (c []Cert) {
var t []Cert
db.Where("auto_cert", AutoCertEnabled).Find(&t)
@@ -49,7 +57,7 @@ func GetAutoCertList() (c []Cert) {
}
for _, v := range t {
- if enabledConfigMap[v.Domain] == true {
+ if enabledConfigMap[v.Filename] == true {
c = append(c, v)
}
}
@@ -76,9 +84,9 @@ func FirstCertByID(id int) (c Cert, err error) {
}
func (c *Cert) Updates(n *Cert) error {
- return db.Model(c).Updates(n).Error
+ return db.Model(&Cert{}).Where("filename", c.Filename).Updates(n).Error
}
func (c *Cert) Remove() error {
- return db.Where("domain", c.Domain).Delete(c).Error
+ return db.Where("filename", c.Filename).Delete(c).Error
}
diff --git a/server/pkg/cert/auto_cert.go b/server/pkg/cert/auto_cert.go
index 9d5e0804..2a991558 100644
--- a/server/pkg/cert/auto_cert.go
+++ b/server/pkg/cert/auto_cert.go
@@ -3,7 +3,6 @@ package cert
import (
"github.com/0xJacky/Nginx-UI/server/model"
"log"
- "strings"
"time"
)
@@ -19,7 +18,7 @@ func handleIssueCertLogChan(logChan chan string) {
}
}
-func AutoCert() {
+func AutoObtain() {
defer func() {
if err := recover(); err != nil {
log.Println("[AutoCert] Recover", err)
@@ -27,19 +26,12 @@ func AutoCert() {
}()
log.Println("[AutoCert] Start")
autoCertList := model.GetAutoCertList()
- for i := range autoCertList {
- domain := autoCertList[i].Domain
-
- certModel, err := model.FirstCert(domain)
-
- if err != nil {
- log.Println("[AutoCert] Error get certificate from database", err)
- continue
- }
+ for _, certModel := range autoCertList {
+ confName := certModel.Filename
if certModel.SSLCertificatePath == "" {
log.Println("[AutoCert] Error ssl_certificate_path is empty, " +
- "try to reopen auto-cert for this domain:" + domain)
+ "try to reopen auto-cert for this config:" + confName)
continue
}
@@ -49,16 +41,17 @@ func AutoCert() {
// Get certificate info error, ignore this domain
continue
}
- // before 1 mo
- if time.Now().Before(cert.NotBefore.AddDate(0, 1, 0)) {
+ // every week
+ if time.Now().Sub(cert.NotBefore).Hours()/24 < 7 {
continue
}
+ //
// after 1 mo, reissue certificate
logChan := make(chan string, 1)
errChan := make(chan error, 1)
// support SAN certification
- go IssueCert(strings.Split(domain, "_"), logChan, errChan)
+ go IssueCert(certModel.Domains, logChan, errChan)
go handleIssueCertLogChan(logChan)
@@ -69,4 +62,5 @@ func AutoCert() {
close(logChan)
}
+ log.Println("[AutoCert] End")
}
diff --git a/server/pkg/cert/cert.go b/server/pkg/cert/cert.go
index 7979c52d..ff7c9f50 100644
--- a/server/pkg/cert/cert.go
+++ b/server/pkg/cert/cert.go
@@ -1,148 +1,155 @@
package cert
import (
- "crypto"
- "crypto/ecdsa"
- "crypto/elliptic"
- "crypto/rand"
- "github.com/0xJacky/Nginx-UI/server/pkg/nginx"
- "github.com/0xJacky/Nginx-UI/server/settings"
- "github.com/go-acme/lego/v4/certcrypto"
- "github.com/go-acme/lego/v4/certificate"
- "github.com/go-acme/lego/v4/challenge/http01"
- "github.com/go-acme/lego/v4/lego"
- "github.com/go-acme/lego/v4/registration"
- "github.com/pkg/errors"
- "log"
- "os"
- "path/filepath"
- "strings"
+ "crypto"
+ "crypto/ecdsa"
+ "crypto/elliptic"
+ "crypto/rand"
+ "crypto/tls"
+ "github.com/0xJacky/Nginx-UI/server/pkg/nginx"
+ "github.com/0xJacky/Nginx-UI/server/settings"
+ "github.com/go-acme/lego/v4/certcrypto"
+ "github.com/go-acme/lego/v4/certificate"
+ "github.com/go-acme/lego/v4/challenge/http01"
+ "github.com/go-acme/lego/v4/lego"
+ "github.com/go-acme/lego/v4/registration"
+ "github.com/pkg/errors"
+ "log"
+ "net/http"
+ "os"
+ "path/filepath"
+ "strings"
)
// MyUser You'll need a user or account type that implements acme.User
type MyUser struct {
- Email string
- Registration *registration.Resource
- key crypto.PrivateKey
+ Email string
+ Registration *registration.Resource
+ key crypto.PrivateKey
}
func (u *MyUser) GetEmail() string {
- return u.Email
+ return u.Email
}
func (u *MyUser) GetRegistration() *registration.Resource {
- return u.Registration
+ return u.Registration
}
func (u *MyUser) GetPrivateKey() crypto.PrivateKey {
- return u.key
+ return u.key
}
func IssueCert(domain []string, logChan chan string, errChan chan error) {
- defer func() {
- if err := recover(); err != nil {
- log.Println("Issue Cert recover", err)
- }
- }()
+ defer func() {
+ if err := recover(); err != nil {
+ log.Println("Issue Cert recover", err)
+ }
+ }()
- // Create a user. New accounts need an email and private key to start.
- logChan <- "Generating private key for registering account"
- privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
- if err != nil {
- errChan <- errors.Wrap(err, "issue cert generate key error")
- return
- }
+ // Create a user. New accounts need an email and private key to start.
+ logChan <- "Generating private key for registering account"
+ privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
+ if err != nil {
+ errChan <- errors.Wrap(err, "issue cert generate key error")
+ return
+ }
- logChan <- "Preparing lego configurations"
- myUser := MyUser{
- Email: settings.ServerSettings.Email,
- key: privateKey,
- }
+ logChan <- "Preparing lego configurations"
+ myUser := MyUser{
+ Email: settings.ServerSettings.Email,
+ key: privateKey,
+ }
- config := lego.NewConfig(&myUser)
+ config := lego.NewConfig(&myUser)
- if settings.ServerSettings.Demo {
- config.CADirURL = "https://acme-staging-v02.api.letsencrypt.org/directory"
- }
+ if settings.ServerSettings.Demo {
+ config.CADirURL = "https://acme-staging-v02.api.letsencrypt.org/directory"
+ }
- if settings.ServerSettings.CADir != "" {
- config.CADirURL = settings.ServerSettings.CADir
- }
+ if settings.ServerSettings.CADir != "" {
+ config.CADirURL = settings.ServerSettings.CADir
+ if config.HTTPClient != nil {
+ config.HTTPClient.Transport = &http.Transport{
+ TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
+ }
+ }
+ }
- config.Certificate.KeyType = certcrypto.RSA2048
+ config.Certificate.KeyType = certcrypto.RSA2048
- logChan <- "Creating client facilitates communication with the CA server"
- // A client facilitates communication with the CA server.
- client, err := lego.NewClient(config)
- if err != nil {
- errChan <- errors.Wrap(err, "issue cert new client error")
- return
- }
+ logChan <- "Creating client facilitates communication with the CA server"
+ // A client facilitates communication with the CA server.
+ client, err := lego.NewClient(config)
+ if err != nil {
+ errChan <- errors.Wrap(err, "issue cert new client error")
+ return
+ }
- logChan <- "Using HTTP01 challenge provider"
- err = client.Challenge.SetHTTP01Provider(
- http01.NewProviderServer("",
- settings.ServerSettings.HTTPChallengePort,
- ),
- )
+ logChan <- "Using HTTP01 challenge provider"
+ err = client.Challenge.SetHTTP01Provider(
+ http01.NewProviderServer("",
+ settings.ServerSettings.HTTPChallengePort,
+ ),
+ )
- if err != nil {
- errChan <- errors.Wrap(err, "issue cert challenge fail")
- return
- }
+ if err != nil {
+ errChan <- errors.Wrap(err, "issue cert challenge fail")
+ return
+ }
- // New users will need to register
- logChan <- "Registering user"
- reg, err := client.Registration.Register(registration.RegisterOptions{TermsOfServiceAgreed: true})
- if err != nil {
- errChan <- errors.Wrap(err, "issue cert register fail")
- return
- }
- myUser.Registration = reg
+ // New users will need to register
+ logChan <- "Registering user"
+ reg, err := client.Registration.Register(registration.RegisterOptions{TermsOfServiceAgreed: true})
+ if err != nil {
+ errChan <- errors.Wrap(err, "issue cert register fail")
+ return
+ }
+ myUser.Registration = reg
- request := certificate.ObtainRequest{
- Domains: domain,
- Bundle: true,
- }
+ request := certificate.ObtainRequest{
+ Domains: domain,
+ Bundle: true,
+ }
- logChan <- "Obtaining certificate"
- certificates, err := client.Certificate.Obtain(request)
- if err != nil {
- errChan <- errors.Wrap(err, "issue cert fail to obtain")
- return
- }
- name := strings.Join(domain, "_")
- saveDir := nginx.GetConfPath("ssl/" + name)
- if _, err = os.Stat(saveDir); os.IsNotExist(err) {
- err = os.MkdirAll(saveDir, 0755)
- if err != nil {
- errChan <- errors.Wrap(err, "issue cert fail to create")
- return
- }
- }
+ logChan <- "Obtaining certificate"
+ certificates, err := client.Certificate.Obtain(request)
+ if err != nil {
+ errChan <- errors.Wrap(err, "issue cert fail to obtain")
+ return
+ }
+ name := strings.Join(domain, "_")
+ saveDir := nginx.GetConfPath("ssl/" + name)
+ if _, err = os.Stat(saveDir); os.IsNotExist(err) {
+ err = os.MkdirAll(saveDir, 0755)
+ if err != nil {
+ errChan <- errors.Wrap(err, "issue cert fail to create")
+ return
+ }
+ }
- // Each certificate comes back with the cert bytes, the bytes of the client's
- // private key, and a certificate URL. SAVE THESE TO DISK.
- logChan <- "Writing certificate to disk"
- err = os.WriteFile(filepath.Join(saveDir, "fullchain.cer"),
- certificates.Certificate, 0644)
+ // Each certificate comes back with the cert bytes, the bytes of the client's
+ // private key, and a certificate URL. SAVE THESE TO DISK.
+ logChan <- "Writing certificate to disk"
+ err = os.WriteFile(filepath.Join(saveDir, "fullchain.cer"),
+ certificates.Certificate, 0644)
- if err != nil {
- errChan <- errors.Wrap(err, "error issue cert write fullchain.cer")
- return
- }
+ if err != nil {
+ errChan <- errors.Wrap(err, "error issue cert write fullchain.cer")
+ return
+ }
- logChan <- "Writing certificate private key to disk"
- err = os.WriteFile(filepath.Join(saveDir, "private.key"),
- certificates.PrivateKey, 0644)
+ logChan <- "Writing certificate private key to disk"
+ err = os.WriteFile(filepath.Join(saveDir, "private.key"),
+ certificates.PrivateKey, 0644)
- if err != nil {
- errChan <- errors.Wrap(err, "error issue cert write key")
- return
- }
+ if err != nil {
+ errChan <- errors.Wrap(err, "error issue cert write key")
+ return
+ }
- close(errChan)
- logChan <- "Reloading nginx"
+ close(errChan)
+ logChan <- "Reloading nginx"
- nginx.Reload()
+ nginx.Reload()
- logChan <- "Finished"
+ logChan <- "Finished"
}
diff --git a/server/pkg/nginx/type.go b/server/pkg/nginx/type.go
index cf803e06..c436c350 100644
--- a/server/pkg/nginx/type.go
+++ b/server/pkg/nginx/type.go
@@ -1,61 +1,64 @@
package nginx
import (
- "github.com/tufanbarisyildirim/gonginx"
- "strings"
+ "github.com/tufanbarisyildirim/gonginx"
+ "path"
+ "strings"
)
type NgxConfig struct {
- FileName string `json:"file_name"`
- Upstreams []*NgxUpstream `json:"upstreams"`
- Servers []*NgxServer `json:"servers"`
- Custom string `json:"custom"`
- c *gonginx.Config
+ FileName string `json:"file_name"`
+ Name string `json:"name"`
+ Upstreams []*NgxUpstream `json:"upstreams"`
+ Servers []*NgxServer `json:"servers"`
+ Custom string `json:"custom"`
+ c *gonginx.Config
}
type NgxServer struct {
- Directives []*NgxDirective `json:"directives"`
- Locations []*NgxLocation `json:"locations"`
- Comments string `json:"comments"`
+ Directives []*NgxDirective `json:"directives"`
+ Locations []*NgxLocation `json:"locations"`
+ Comments string `json:"comments"`
}
type NgxUpstream struct {
- Name string `json:"name"`
- Directives []*NgxDirective `json:"directives"`
- Comments string `json:"comments"`
+ Name string `json:"name"`
+ Directives []*NgxDirective `json:"directives"`
+ Comments string `json:"comments"`
}
type NgxDirective struct {
- Directive string `json:"directive"`
- Params string `json:"params"`
- Comments string `json:"comments"`
+ Directive string `json:"directive"`
+ Params string `json:"params"`
+ Comments string `json:"comments"`
}
type NgxLocation struct {
- Path string `json:"path"`
- Content string `json:"content"`
- Comments string `json:"comments"`
+ Path string `json:"path"`
+ Content string `json:"content"`
+ Comments string `json:"comments"`
}
func (d *NgxDirective) Orig() string {
- return d.Directive + " " + d.Params
+ return d.Directive + " " + d.Params
}
func (d *NgxDirective) TrimParams() {
- d.Params = strings.TrimRight(strings.TrimSpace(d.Params), ";")
- return
+ d.Params = strings.TrimRight(strings.TrimSpace(d.Params), ";")
+ return
}
func NewNgxServer() *NgxServer {
- return &NgxServer{
- Locations: make([]*NgxLocation, 0),
- Directives: make([]*NgxDirective, 0),
- }
+ return &NgxServer{
+ Locations: make([]*NgxLocation, 0),
+ Directives: make([]*NgxDirective, 0),
+ }
}
func NewNgxConfig(filename string) *NgxConfig {
- return &NgxConfig{
- FileName: filename,
- Upstreams: make([]*NgxUpstream, 0),
- }
+ return &NgxConfig{
+ FileName: filename,
+ Upstreams: make([]*NgxUpstream, 0),
+ Name: path.Base(filename),
+ }
}
diff --git a/server/router/routers.go b/server/router/routers.go
index 834b2afc..51a98845 100644
--- a/server/router/routers.go
+++ b/server/router/routers.go
@@ -76,6 +76,7 @@ func InitRouter() *gin.Engine {
g.DELETE("domain/:name", api.DeleteDomain)
// duplicate site
g.POST("domain/:name/duplicate", api.DuplicateSite)
+ g.GET("domain/:name/cert", api.IssueCert)
g.GET("configs", api.GetConfigs)
g.GET("config/*name", api.GetConfig)
@@ -90,17 +91,15 @@ func InitRouter() *gin.Engine {
g.GET("template/blocks", api.GetTemplateBlockList)
g.GET("template/block/:name", api.GetTemplateBlock)
- g.GET("cert/issue", api.IssueCert)
-
g.GET("certs", api.GetCertList)
g.GET("cert/:id", api.GetCert)
g.POST("cert", api.AddCert)
g.POST("cert/:id", api.ModifyCert)
g.DELETE("cert/:id", api.RemoveCert)
// Add domain to auto-renew cert list
- g.POST("auto_cert/:domain", api.AddDomainToAutoCert)
+ g.POST("auto_cert/:name", api.AddDomainToAutoCert)
// Delete domain from auto-renew cert list
- g.DELETE("auto_cert/:domain", api.RemoveDomainFromAutoCert)
+ g.DELETE("auto_cert/:name", api.RemoveDomainFromAutoCert)
// pty
g.GET("pty", api.Pty)