mirror of
https://github.com/ngoduykhanh/wireguard-ui.git
synced 2025-04-19 19:59:13 +03:00
Add Apply Config button to save wireguard config file
This commit is contained in:
parent
ea36311475
commit
7c3cac8084
7 changed files with 177 additions and 2 deletions
|
@ -389,3 +389,66 @@ func SuggestIPAllocation() echo.HandlerFunc {
|
||||||
return c.JSON(http.StatusOK, suggestedIPs)
|
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"})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
1
main.go
1
main.go
|
@ -19,5 +19,6 @@ func main() {
|
||||||
app.POST("/global-settings", handler.GlobalSettingSubmit())
|
app.POST("/global-settings", handler.GlobalSettingSubmit())
|
||||||
app.GET("/api/machine-ips", handler.MachineIPAddresses())
|
app.GET("/api/machine-ips", handler.MachineIPAddresses())
|
||||||
app.GET("/api/suggest-client-ips", handler.SuggestIPAllocation())
|
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"))
|
app.Logger.Fatal(app.Start("127.0.0.1:5000"))
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,5 +10,6 @@ type GlobalSetting struct {
|
||||||
DNSServers []string `json:"dns_servers"`
|
DNSServers []string `json:"dns_servers"`
|
||||||
MTU int `json:"mtu,string"`
|
MTU int `json:"mtu,string"`
|
||||||
PersistentKeepalive int `json:"persistent_keepalive,string"`
|
PersistentKeepalive int `json:"persistent_keepalive,string"`
|
||||||
|
ConfigFilePath string `json:"config_file_path"`
|
||||||
UpdatedAt time.Time `json:"updated_at"`
|
UpdatedAt time.Time `json:"updated_at"`
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,9 +58,12 @@
|
||||||
|
|
||||||
<!-- Right navbar links -->
|
<!-- Right navbar links -->
|
||||||
<div class="navbar-nav ml-auto">
|
<div class="navbar-nav ml-auto">
|
||||||
<button type="button" class="btn btn-outline-primary btn-sm" data-toggle="modal"
|
<button style="margin-left: 0.5em;" type="button" class="btn btn-outline-primary btn-sm" data-toggle="modal"
|
||||||
data-target="#modal_new_client"><i class="nav-icon fas fa-plus"></i> New
|
data-target="#modal_new_client"><i class="nav-icon fas fa-plus"></i> New
|
||||||
Client</button>
|
Client</button>
|
||||||
|
<button style="margin-left: 0.5em;" type="button" class="btn btn-outline-danger btn-sm" data-toggle="modal"
|
||||||
|
data-target="#modal_apply_config"><i class="nav-icon fas fa-check"></i> Apply
|
||||||
|
Config</button>
|
||||||
</nav>
|
</nav>
|
||||||
</nav>
|
</nav>
|
||||||
<!-- /.navbar -->
|
<!-- /.navbar -->
|
||||||
|
@ -169,6 +172,29 @@
|
||||||
</div>
|
</div>
|
||||||
<!-- /.modal -->
|
<!-- /.modal -->
|
||||||
|
|
||||||
|
<div class="modal fade" id="modal_apply_config">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h4 class="modal-title">Apply Config</h4>
|
||||||
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||||
|
<span aria-hidden="true">×</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<p>Do you want to write config file and restart WireGuard server?</p>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer justify-content-between">
|
||||||
|
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
|
||||||
|
<button type="button" class="btn btn-danger" id="apply_config_confirm">Apply</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- /.modal-content -->
|
||||||
|
</div>
|
||||||
|
<!-- /.modal-dialog -->
|
||||||
|
</div>
|
||||||
|
<!-- /.modal -->
|
||||||
|
|
||||||
<!-- Content Wrapper. Contains page content -->
|
<!-- Content Wrapper. Contains page content -->
|
||||||
<div class="content-wrapper">
|
<div class="content-wrapper">
|
||||||
<!-- Content Header (Page header) -->
|
<!-- Content Header (Page header) -->
|
||||||
|
@ -352,6 +378,27 @@
|
||||||
updateIPAllocationSuggestion();
|
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']);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- START: On page script -->
|
<!-- START: On page script -->
|
||||||
|
|
|
@ -55,6 +55,12 @@ Global Settings
|
||||||
name="persistent_keepalive" placeholder="Persistent Keepalive"
|
name="persistent_keepalive" placeholder="Persistent Keepalive"
|
||||||
value="{{ .globalSettings.PersistentKeepalive }}">
|
value="{{ .globalSettings.PersistentKeepalive }}">
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="config_file_path">Wireguard Config File Path</label>
|
||||||
|
<input type="text" class="form-control" id="config_file_path"
|
||||||
|
name="config_file_path" placeholder="E.g. /etc/wireguard/wg0.conf"
|
||||||
|
value="{{ .globalSettings.ConfigFilePath }}">
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- /.card-body -->
|
<!-- /.card-body -->
|
||||||
|
|
||||||
|
@ -104,7 +110,8 @@ Global Settings
|
||||||
var dns_servers = $("#dns_servers").val().split(",");
|
var dns_servers = $("#dns_servers").val().split(",");
|
||||||
var mtu = $("#mtu").val();
|
var mtu = $("#mtu").val();
|
||||||
var persistent_keepalive = $("#persistent_keepalive").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({
|
$.ajax({
|
||||||
cache: false,
|
cache: false,
|
||||||
|
@ -173,6 +180,9 @@ Global Settings
|
||||||
persistent_keepalive: {
|
persistent_keepalive: {
|
||||||
required: true,
|
required: true,
|
||||||
digits: true
|
digits: true
|
||||||
|
},
|
||||||
|
config_file_path: {
|
||||||
|
required: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
messages: {
|
messages: {
|
||||||
|
@ -184,6 +194,9 @@ Global Settings
|
||||||
persistent_keepalive: {
|
persistent_keepalive: {
|
||||||
required: "Please enter a Persistent Keepalive value",
|
required: "Please enter a Persistent Keepalive value",
|
||||||
digits: "Persistent keepalive must be an integer"
|
digits: "Persistent keepalive must be an integer"
|
||||||
|
},
|
||||||
|
config_file_path: {
|
||||||
|
required: "Please enter WireGuard config file path"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
errorElement: 'span',
|
errorElement: 'span',
|
||||||
|
|
21
templates/wg.conf
Normal file
21
templates/wg.conf
Normal file
|
@ -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}}
|
29
util/util.go
29
util/util.go
|
@ -5,7 +5,9 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
"text/template"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
externalip "github.com/glendc/go-external-ip"
|
externalip "github.com/glendc/go-external-ip"
|
||||||
|
@ -308,3 +310,30 @@ func ValidateIPAllocation(serverAddresses []string, ipAllocatedList []string, ip
|
||||||
|
|
||||||
return true, nil
|
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
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue