diff --git a/handler/routes.go b/handler/routes.go
index d4e0ffb..b4dbdd4 100644
--- a/handler/routes.go
+++ b/handler/routes.go
@@ -389,3 +389,66 @@ func SuggestIPAllocation() echo.HandlerFunc {
return c.JSON(http.StatusOK, suggestedIPs)
}
}
+
+// ApplyServerConfig handler to write config file and restart Wireguard server
+func ApplyServerConfig() echo.HandlerFunc {
+ return func(c echo.Context) error {
+ // initialize database directory
+ dir := "./db"
+ db, err := scribble.New(dir, nil)
+ if err != nil {
+ log.Error("Cannot initialize the database: ", err)
+ }
+
+ // read server information
+ serverInterface := model.ServerInterface{}
+ if err := db.Read("server", "interfaces", &serverInterface); err != nil {
+ log.Error("Cannot fetch server interface config from database: ", err)
+ }
+
+ serverKeyPair := model.ServerKeypair{}
+ if err := db.Read("server", "keypair", &serverKeyPair); err != nil {
+ log.Error("Cannot fetch server key pair from database: ", err)
+ }
+
+ server := model.Server{}
+ server.Interface = &serverInterface
+ server.KeyPair = &serverKeyPair
+
+ // read global settings
+ globalSettings := model.GlobalSetting{}
+ if err := db.Read("server", "global_settings", &globalSettings); err != nil {
+ log.Error("Cannot fetch global settings from database: ", err)
+ }
+
+ // read client information and build a client list
+ records, err := db.ReadAll("clients")
+ if err != nil {
+ log.Error("Cannot fetch clients from database: ", err)
+ }
+
+ clientDataList := []model.ClientData{}
+ for _, f := range records {
+ client := model.Client{}
+ clientData := model.ClientData{}
+
+ // get client info
+ if err := json.Unmarshal([]byte(f), &client); err != nil {
+ log.Error("Cannot decode client json structure: ", err)
+ }
+ clientData.Client = &client
+
+ // create the list of clients and their qrcode data
+ clientDataList = append(clientDataList, clientData)
+ }
+
+ // Write config file
+ err = util.WriteWireGuardServerConfig(server, clientDataList, globalSettings)
+ if err != nil {
+ log.Error("Cannot apply server config: ", err)
+ return c.JSON(http.StatusInternalServerError, jsonHTTPResponse{false, fmt.Sprintf("Cannot apply server config: %v", err)})
+ }
+
+ return c.JSON(http.StatusOK, jsonHTTPResponse{true, "Applied server config successfully"})
+ }
+}
diff --git a/main.go b/main.go
index bcd4056..5adb242 100644
--- a/main.go
+++ b/main.go
@@ -19,5 +19,6 @@ func main() {
app.POST("/global-settings", handler.GlobalSettingSubmit())
app.GET("/api/machine-ips", handler.MachineIPAddresses())
app.GET("/api/suggest-client-ips", handler.SuggestIPAllocation())
+ app.GET("/api/apply-wg-config", handler.ApplyServerConfig())
app.Logger.Fatal(app.Start("127.0.0.1:5000"))
}
diff --git a/model/setting.go b/model/setting.go
index 4d8791b..a316172 100644
--- a/model/setting.go
+++ b/model/setting.go
@@ -10,5 +10,6 @@ type GlobalSetting struct {
DNSServers []string `json:"dns_servers"`
MTU int `json:"mtu,string"`
PersistentKeepalive int `json:"persistent_keepalive,string"`
+ ConfigFilePath string `json:"config_file_path"`
UpdatedAt time.Time `json:"updated_at"`
}
diff --git a/templates/base.html b/templates/base.html
index 28d1705..99322bd 100644
--- a/templates/base.html
+++ b/templates/base.html
@@ -58,9 +58,12 @@
-
+
@@ -169,6 +172,29 @@
+
+
+
+
+
+
Do you want to write config file and restart WireGuard server?
+
+
+
+
+
+
+
+
+
@@ -352,6 +378,27 @@
updateIPAllocationSuggestion();
});
});
+
+ // apply_config_confirm button event
+ $(document).ready(function () {
+ $('#apply_config_confirm').click(function () {
+ $.ajax({
+ cache: false,
+ method: 'GET',
+ url: '/api/apply-wg-config',
+ dataType: 'json',
+ contentType: "application/json",
+ success: function(data) {
+ $('#modal_apply_config').modal('hide');
+ toastr.success('Applied config successfully');
+ },
+ error: function(jqXHR, exception) {
+ var responseJson = jQuery.parseJSON(jqXHR.responseText);
+ toastr.error(responseJson['message']);
+ }
+ });
+ });
+ });
diff --git a/templates/global_settings.html b/templates/global_settings.html
index 59a13c1..e54bc22 100644
--- a/templates/global_settings.html
+++ b/templates/global_settings.html
@@ -55,6 +55,12 @@ Global Settings
name="persistent_keepalive" placeholder="Persistent Keepalive"
value="{{ .globalSettings.PersistentKeepalive }}">
+
+
+
+
@@ -104,7 +110,8 @@ Global Settings
var dns_servers = $("#dns_servers").val().split(",");
var mtu = $("#mtu").val();
var persistent_keepalive = $("#persistent_keepalive").val();
- var data = {"endpoint_address": endpoint_address, "dns_servers": dns_servers, "mtu": mtu, "persistent_keepalive": persistent_keepalive};
+ var config_file_path = $("#config_file_path").val();
+ var data = {"endpoint_address": endpoint_address, "dns_servers": dns_servers, "mtu": mtu, "persistent_keepalive": persistent_keepalive, "config_file_path": config_file_path};
$.ajax({
cache: false,
@@ -173,6 +180,9 @@ Global Settings
persistent_keepalive: {
required: true,
digits: true
+ },
+ config_file_path: {
+ required: true
}
},
messages: {
@@ -184,6 +194,9 @@ Global Settings
persistent_keepalive: {
required: "Please enter a Persistent Keepalive value",
digits: "Persistent keepalive must be an integer"
+ },
+ config_file_path: {
+ required: "Please enter WireGuard config file path"
}
},
errorElement: 'span',
diff --git a/templates/wg.conf b/templates/wg.conf
new file mode 100644
index 0000000..2bb3953
--- /dev/null
+++ b/templates/wg.conf
@@ -0,0 +1,21 @@
+# This file was generated using wireguard-ui (https://github.com/ngoduykhanh/wireguard-ui)
+# Please don't modify it manually, otherwise your change might got replaced.
+
+# Address updated at: {{ .serverConfig.Interface.UpdatedAt }}
+# Private Key updated at: {{ .serverConfig.KeyPair.UpdatedAt }}
+[Interface]
+Address = {{$first :=true}}{{range .serverConfig.Interface.Addresses }}{{if $first}}{{$first = false}}{{else}},{{end}}{{.}}{{end}}
+ListenPort = {{ .serverConfig.Interface.ListenPort }}
+PrivateKey = {{ .serverConfig.KeyPair.PrivateKey }}
+MTU = {{ .globalSettings.MTU }}
+
+{{range .clientDataList}}
+# ID: {{ .Client.ID }}
+# Name: {{ .Client.Name }}
+# Email: {{ .Client.Email }}
+# Created at: {{ .Client.CreatedAt }}
+# Update at: {{ .Client.UpdatedAt }}
+[Peer]
+PublicKey = {{ .Client.PublicKey }}
+AllowedIPs = {{$first :=true}}{{range .Client.AllocatedIPs }}{{if $first}}{{$first = false}}{{else}},{{end}}{{.}}{{end}}
+{{end}}
diff --git a/util/util.go b/util/util.go
index e57d3bc..507db29 100644
--- a/util/util.go
+++ b/util/util.go
@@ -5,7 +5,9 @@ import (
"errors"
"fmt"
"net"
+ "os"
"strings"
+ "text/template"
"time"
externalip "github.com/glendc/go-external-ip"
@@ -308,3 +310,30 @@ func ValidateIPAllocation(serverAddresses []string, ipAllocatedList []string, ip
return true, nil
}
+
+// WriteWireGuardServerConfig to write Wireguard server config. e.g. wg0.conf
+func WriteWireGuardServerConfig(serverConfig model.Server, clientDataList []model.ClientData, globalSettings model.GlobalSetting) error {
+ t, err := template.ParseFiles("templates/wg.conf")
+ if err != nil {
+ return err
+ }
+
+ f, err := os.Create(globalSettings.ConfigFilePath)
+ if err != nil {
+ return err
+ }
+
+ config := map[string]interface{}{
+ "serverConfig": serverConfig,
+ "clientDataList": clientDataList,
+ "globalSettings": globalSettings,
+ }
+
+ err = t.Execute(f, config)
+ if err != nil {
+ return err
+ }
+ f.Close()
+
+ return nil
+}