Add environment variables for configuration (#189)

This commit is contained in:
Fin Christensen 2022-04-26 20:35:35 +02:00 committed by GitHub
parent 87b08a8f7c
commit 569eaaee37
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 112 additions and 37 deletions

View file

@ -30,8 +30,41 @@ wireguard interface stats. See the `cap_add` and `network_mode` options on the d
### Environment Variables
| Variable | Description |
|-----------------------------|-----------------------------------------------------------------------------------------------------|
| `SESSION_SECRET` | Used to encrypt the session cookies. Set this to a random value. |
| `WGUI_USERNAME` | The username for the login page. (default `admin`) |
| `WGUI_PASSWORD` | The password for the user on the login page. (default `admin`) |
| `WGUI_ENDPOINT_ADDRESS` | The default endpoint address used in global settings. (default is your public IP address) |
| `WGUI_DNS` | The default DNS servers (comma-separated-list) used in the global settings. (default `1.1.1.1`) |
| `WGUI_MTU` | The default MTU used in global settings. (default `1450`) |
| `WGUI_PERSISTENT_KEEPALIVE` | The default persistent keepalive for WireGuard in global settings. (default `15`) |
| `WGUI_FORWARD_MARK` | The default WireGuard forward mark. (default `0xca6c`) |
| `WGUI_CONFIG_FILE_PATH` | The default WireGuard config file path used in global settings. (default `/etc/wireguard/wg0.conf`) |
Set the `SESSION_SECRET` environment variable to a random value.
#### Defaults for server configuration
These environment variables are used to control the default server settings used when initializing the database.
| Variable | Description |
|-----------------------------------|--------------------------------------------------------------------------------------------------------------------------|
| `WGUI_SERVER_INTERFACE_ADDRESSES` | The default interface addresses (comma-separated-list) for the WireGuard server configuration. (default `10.252.1.0/24`) |
| `WGUI_SERVER_LISTEN_PORT` | The default server listen port. (default `51820`) |
| `WGUI_SERVER_POST_UP_SCRIPT` | The default server post-up script. |
| `WGUI_SERVER_POST_DOWN_SCRIPT` | The default server post-down script. |
#### Defaults for new clients
These environment variables are used to set the defaults used in `New Client` dialog.
| Variable | Description |
|---------------------------------------------|------------------------------------------------------------------------------------------------------------------|
| `WGUI_DEFAULT_CLIENT_ALLOWED_IPS` | Comma-separated-list of CIDRs for the `Allowed IPs` field. (default `0.0.0.0/0`) |
| `WGUI_DEFAULT_CLIENT_EXTRA_ALLOWED_IPS` | Comma-separated-list of CIDRs for the `Extra Allowed IPs` field. (default empty) |
| `WGUI_DEFAULT_CLIENT_USE_SERVER_DNS` | Boolean value [`0`, `f`, `F`, `false`, `False`, `FALSE`, `1`, `t`, `T`, `true`, `True`, `TRUE`] (default `true`) |
| `WGUI_DEFAULT_CLIENT_ENABLE_AFTER_CREATION` | Boolean value [`0`, `f`, `F`, `false`, `False`, `FALSE`, `1`, `t`, `T`, `true`, `True`, `TRUE`] (default `true`) |
#### Email configuration
To use custom `wg.conf` template set the `WG_CONF_TEMPLATE` environment variable to a path to such file. Make sure `wireguard-ui` will be able to work with it - use [default template](templates/wg.conf) for reference.

9
model/client_defaults.go Normal file
View file

@ -0,0 +1,9 @@
package model
// Defaults for creation of new clients used in the templates
type ClientDefaults struct {
AllowedIps []string
ExtraAllowedIps []string
UseServerDNS bool
EnableAfterCreation bool
}

View file

@ -4,6 +4,7 @@ import (
"errors"
"io"
"reflect"
"strings"
"text/template"
rice "github.com/GeertJohan/go.rice"
@ -12,6 +13,7 @@ import (
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
"github.com/labstack/gommon/log"
"github.com/ngoduykhanh/wireguard-ui/util"
)
// TemplateRegistry is a custom html/template renderer for Echo framework
@ -33,6 +35,8 @@ func (t *TemplateRegistry) Render(w io.Writer, name string, data interface{}, c
for k, v := range t.extraData {
data.(map[string]interface{})[k] = v
}
data.(map[string]interface{})["client_defaults"] = util.ClientDefaultsFromEnv()
}
// login page does not need the base layout
@ -85,13 +89,16 @@ func New(tmplBox *rice.Box, extraData map[string]string, secret []byte) *echo.Ec
}
// create template list
funcs := template.FuncMap{
"StringsJoin": strings.Join,
}
templates := make(map[string]*template.Template)
templates["login.html"] = template.Must(template.New("login").Parse(tmplLoginString))
templates["clients.html"] = template.Must(template.New("clients").Parse(tmplBaseString + tmplClientsString))
templates["server.html"] = template.Must(template.New("server").Parse(tmplBaseString + tmplServerString))
templates["global_settings.html"] = template.Must(template.New("global_settings").Parse(tmplBaseString + tmplGlobalSettingsString))
templates["status.html"] = template.Must(template.New("status").Parse(tmplBaseString + tmplStatusString))
templates["wake_on_lan_hosts.html"] = template.Must(template.New("wake_on_lan_hosts").Parse(tmplBaseString + tmplWakeOnLanHostsString))
templates["login.html"] = template.Must(template.New("login").Funcs(funcs).Parse(tmplLoginString))
templates["clients.html"] = template.Must(template.New("clients").Funcs(funcs).Parse(tmplBaseString + tmplClientsString))
templates["server.html"] = template.Must(template.New("server").Funcs(funcs).Parse(tmplBaseString + tmplServerString))
templates["global_settings.html"] = template.Must(template.New("global_settings").Funcs(funcs).Parse(tmplBaseString + tmplGlobalSettingsString))
templates["status.html"] = template.Must(template.New("status").Funcs(funcs).Parse(tmplBaseString + tmplStatusString))
templates["wake_on_lan_hosts.html"] = template.Must(template.New("wake_on_lan_hosts").Funcs(funcs).Parse(tmplBaseString + tmplWakeOnLanHostsString))
e.Logger.SetLevel(log.DEBUG)
e.Pre(middleware.RemoveTrailingSlash())

View file

@ -57,8 +57,10 @@ func (o *JsonDB) Init() error {
// server's interface
if _, err := os.Stat(serverInterfacePath); os.IsNotExist(err) {
serverInterface := new(model.ServerInterface)
serverInterface.Addresses = []string{util.DefaultServerAddress}
serverInterface.ListenPort = util.DefaultServerPort
serverInterface.Addresses = util.LookupEnvOrStrings(util.ServerAddressesEnvVar, []string{util.DefaultServerAddress})
serverInterface.ListenPort = util.LookupEnvOrInt(util.ServerListenPortEnvVar, util.DefaultServerPort)
serverInterface.PostUp = util.LookupEnvOrString(util.ServerPostUpScriptEnvVar, "")
serverInterface.PostDown = util.LookupEnvOrString(util.ServerPostDownScriptEnvVar, "")
serverInterface.UpdatedAt = time.Now().UTC()
o.conn.Write("server", "interfaces", serverInterface)
}
@ -86,12 +88,12 @@ func (o *JsonDB) Init() error {
}
globalSetting := new(model.GlobalSetting)
globalSetting.EndpointAddress = publicInterface.IPAddress
globalSetting.DNSServers = []string{util.DefaultDNS}
globalSetting.MTU = util.DefaultMTU
globalSetting.PersistentKeepalive = util.DefaultPersistentKeepalive
globalSetting.ForwardMark = util.DefaultForwardMark
globalSetting.ConfigFilePath = util.DefaultConfigFilePath
globalSetting.EndpointAddress = util.LookupEnvOrString(util.EndpointAddressEnvVar, publicInterface.IPAddress)
globalSetting.DNSServers = util.LookupEnvOrStrings(util.DNSEnvVar, []string{util.DefaultDNS})
globalSetting.MTU = util.LookupEnvOrInt(util.MTUEnvVar, util.DefaultMTU)
globalSetting.PersistentKeepalive = util.LookupEnvOrInt(util.PersistentKeepaliveEnvVar, util.DefaultPersistentKeepalive)
globalSetting.ForwardMark = util.LookupEnvOrString(util.ForwardMarkEnvVar, util.DefaultForwardMark)
globalSetting.ConfigFilePath = util.LookupEnvOrString(util.ConfigFilePathEnvVar, util.DefaultConfigFilePath)
globalSetting.UpdatedAt = time.Now().UTC()
o.conn.Write("server", "global_settings", globalSetting)
}
@ -99,8 +101,8 @@ func (o *JsonDB) Init() error {
// user info
if _, err := os.Stat(userPath); os.IsNotExist(err) {
user := new(model.User)
user.Username = util.GetCredVar(util.UsernameEnvVar, util.DefaultUsername)
user.Password = util.GetCredVar(util.PasswordEnvVar, util.DefaultPassword)
user.Username = util.LookupEnvOrString(util.UsernameEnvVar, util.DefaultUsername)
user.Password = util.LookupEnvOrString(util.PasswordEnvVar, util.DefaultPassword)
o.conn.Write("server", "users", user)
}

View file

@ -175,7 +175,7 @@
</i>
</label>
<input type="text" data-role="tagsinput" class="form-control" id="client_allowed_ips"
value="0.0.0.0/0">
value="{{ StringsJoin .client_defaults.AllowedIps "," }}">
</div>
<div class="form-group">
<label for="client_extra_allowed_ips" class="control-label">Extra Allowed IPs
@ -184,11 +184,11 @@
client. These addresses will be included in 'AllowedIPs' of WG server config">
</i>
</label>
<input type="text" data-role="tagsinput" class="form-control" id="client_extra_allowed_ips">
<input type="text" data-role="tagsinput" class="form-control" id="client_extra_allowed_ips" value="{{ StringsJoin .client_defaults.ExtraAllowedIps "," }}">
</div>
<div class="form-group">
<div class="icheck-primary d-inline">
<input type="checkbox" id="use_server_dns" checked>
<input type="checkbox" id="use_server_dns" {{ if .client_defaults.UseServerDNS }}checked{{ end }}>
<label for="use_server_dns">
Use server DNS
</label>
@ -196,7 +196,7 @@
</div>
<div class="form-group">
<div class="icheck-primary d-inline">
<input type="checkbox" id="enabled" checked>
<input type="checkbox" id="enabled" {{ if .client_defaults.EnableAfterCreation }}checked{{ end }}>
<label for="enabled">
Enable after creation
</label>

View file

@ -23,17 +23,31 @@ var (
)
const (
DefaultUsername = "admin"
DefaultPassword = "admin"
DefaultServerAddress = "10.252.1.0/24"
DefaultServerPort = 51820
DefaultDNS = "1.1.1.1"
DefaultMTU = 1450
DefaultPersistentKeepalive = 15
DefaultForwardMark = "0xca6c"
DefaultConfigFilePath = "/etc/wireguard/wg0.conf"
UsernameEnvVar = "WGUI_USERNAME"
PasswordEnvVar = "WGUI_PASSWORD"
DefaultUsername = "admin"
DefaultPassword = "admin"
DefaultServerAddress = "10.252.1.0/24"
DefaultServerPort = 51820
DefaultDNS = "1.1.1.1"
DefaultMTU = 1450
DefaultPersistentKeepalive = 15
DefaultForwardMark = "0xca6c"
DefaultConfigFilePath = "/etc/wireguard/wg0.conf"
UsernameEnvVar = "WGUI_USERNAME"
PasswordEnvVar = "WGUI_PASSWORD"
EndpointAddressEnvVar = "WGUI_ENDPOINT_ADDRESS"
DNSEnvVar = "WGUI_DNS"
MTUEnvVar = "WGUI_MTU"
PersistentKeepaliveEnvVar = "WGUI_PERSISTENT_KEEPALIVE"
ForwardMarkEnvVar = "WGUI_FORWARD_MARK"
ConfigFilePathEnvVar = "WGUI_CONFIG_FILE_PATH"
ServerAddressesEnvVar = "WGUI_SERVER_INTERFACE_ADDRESSES"
ServerListenPortEnvVar = "WGUI_SERVER_LISTEN_PORT"
ServerPostUpScriptEnvVar = "WGUI_SERVER_POST_UP_SCRIPT"
ServerPostDownScriptEnvVar = "WGUI_SERVER_POST_DOWN_SCRIPT"
DefaultClientAllowedIpsEnvVar = "WGUI_DEFAULT_CLIENT_ALLOWED_IPS"
DefaultClientExtraAllowedIpsEnvVar = "WGUI_DEFAULT_CLIENT_EXTRA_ALLOWED_IPS"
DefaultClientUseServerDNSEnvVar = "WGUI_DEFAULT_CLIENT_USE_SERVER_DNS"
DefaultClientEnableAfterCreationEnvVar = "WGUI_DEFAULT_CLIENT_ENABLE_AFTER_CREATION"
)
func ParseBasePath(basePath string) string {

View file

@ -77,6 +77,17 @@ func BuildClientConfig(client model.Client, server model.Server, setting model.G
return strConfig
}
// Read the default values for creating a new client from the environment or use sane defaults
func ClientDefaultsFromEnv() model.ClientDefaults {
client_defaults := model.ClientDefaults{}
client_defaults.AllowedIps = LookupEnvOrStrings(DefaultClientAllowedIpsEnvVar, []string{"0.0.0.0/0"})
client_defaults.ExtraAllowedIps = LookupEnvOrStrings(DefaultClientExtraAllowedIpsEnvVar, []string{})
client_defaults.UseServerDNS = LookupEnvOrBool(DefaultClientUseServerDNSEnvVar, true)
client_defaults.EnableAfterCreation = LookupEnvOrBool(DefaultClientEnableAfterCreationEnvVar, true)
return client_defaults
}
// ValidateCIDR to validate a network CIDR
func ValidateCIDR(cidr string) bool {
_, _, err := net.ParseCIDR(cidr)
@ -440,10 +451,9 @@ func LookupEnvOrInt(key string, defaultVal int) int {
return defaultVal
}
// GetCredVar reads value from environment variable or returns fallback
func GetCredVar(key, fallback string) string {
if value, ok := os.LookupEnv(key); ok {
return value
func LookupEnvOrStrings(key string, defaultVal []string) []string {
if val, ok := os.LookupEnv(key); ok {
return strings.Split(val, ",")
}
return fallback
return defaultVal
}