Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP]: Added MySQL as a datastore #165

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 72 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ wireguard interface stats. See the `cap_add` and `network_mode` options on the d

Set the `SESSION_SECRET` environment variable to a random value.

In order to sent the wireguard configuration to clients via email, set the following environment variables:
In order to send the wireguard configuration to clients via email, set the following environment variables:

- using SendGrid API

Expand All @@ -55,6 +55,22 @@ EMAIL_FROM_ADDRESS: the sender's email address
EMAIL_FROM_NAME: the sender's name
```

In order to connect to a database, set the following environment
variables:

```
DB_TYPE
DB_HOST
DB_PORT
DB_DATABASE
DB_USERNAME
DB_PASSWORD
DB_TLS: the TLS option
```

For details on the values that these variables should be set to, see the
section for your desired database.

### Using binary file

Download the binary file from the release and run it with command:
Expand All @@ -63,6 +79,61 @@ Download the binary file from the release and run it with command:
./wireguard-ui
```

## Databases

By default, all the data for the application is stored in JSON files in
the `./db` directory. By using the `--db-type` command line option or by
setting the `DB_TYPE` environment variable, you can choose to use a
different backend. Note: for some backends, other options may need to be
set.

Backend options:

| Value | Database | Other options |
| ----- | -------- | ------------- |
| jsondb | JSON files in `./db` | None |
| mysql | MySQL or MariaDB server | `DB_HOST` `DB_PORT` `DB_DATABASE` `DB_USERNAME` `DB_PASSWORD` `DB_TLS` |

### JSONDB

When using the JSONDB database, all of the data is stored in separate
JSON files in the `./db` directory. This is the default database and no
special configuration is required.

### MySQL

In order to use a MySQL or MariaDB server, you will first have to set
the `DB_TYPE` environment variable to `mysql`. You should then specify
the hostname or IP address of the database server using `DB_HOST` as
well as the port on which the database server is listening, if it is
different from the default of `3306`. `DB_DATABASE` is the name of the
database that WireGuard-UI is to use. Please ensure that the database is
empty before you start WireGuard-UI for the first time otherwise the
tables will not be initialized properly. `DB_USERNAME` and `DB_PASSWORD`
should contain the login details for a user with the following
permissions for the database:

* SELECT
* INSERT
* UPDATE
* DELETE
* CREATE
* ALTER

`DB_TLS` sets the TLS configuration for the database connection. It
defaults to `false` and can be one of the following values:

| Option | Description |
| ------ | ----------- |
| false | Never use TLS (default) |
| true | Enable TLS / SSL encrypted connection to the server |
| prefered | Use TLS when advertised by the server |
| skip-verify | Use TLS, but don't check against a CA |

After you have set these options, you should be able to start the
WireGuard-UI server. The server will then initialize the database and
insert the default configuration. If this process is interrupted, you
will have to empty the database and restart the initialization.
## Auto restart WireGuard daemon
WireGuard-UI only takes care of configuration generation. You can use systemd to watch for the changes and restart the service. Following is an example:

Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ require (
github.com/GeertJohan/go.rice v1.0.0
github.com/glendc/go-external-ip v0.0.0-20170425150139-139229dcdddd
github.com/go-playground/universal-translator v0.17.0 // indirect
github.com/go-sql-driver/mysql v1.6.0
github.com/gorilla/sessions v1.2.0
github.com/jcelliott/lumber v0.0.0-20160324203708-dd349441af25 // indirect
github.com/labstack/echo-contrib v0.9.0
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8c
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no=
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
Expand Down
6 changes: 3 additions & 3 deletions handler/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ func NewClient(db store.IStore) echo.HandlerFunc {
}

// validate the input Allocation IPs
allocatedIPs, err := util.GetAllocatedIPs("")
allocatedIPs, err := util.GetAllocatedIPs(db, "")
check, err := util.ValidateIPAllocation(server.Interface.Addresses, allocatedIPs, client.AllocatedIPs)
if !check {
return c.JSON(http.StatusBadRequest, jsonHTTPResponse{false, fmt.Sprintf("%s", err)})
Expand Down Expand Up @@ -268,7 +268,7 @@ func UpdateClient(db store.IStore) echo.HandlerFunc {
}
client := *clientData.Client
// validate the input Allocation IPs
allocatedIPs, err := util.GetAllocatedIPs(client.ID)
allocatedIPs, err := util.GetAllocatedIPs(db, client.ID)
check, err := util.ValidateIPAllocation(server.Interface.Addresses, allocatedIPs, _client.AllocatedIPs)
if !check {
return c.JSON(http.StatusBadRequest, jsonHTTPResponse{false, fmt.Sprintf("%s", err)})
Expand Down Expand Up @@ -624,7 +624,7 @@ func SuggestIPAllocation(db store.IStore) echo.HandlerFunc {
// we take the first available ip address from
// each server's network addresses.
suggestedIPs := make([]string, 0)
allocatedIPs, err := util.GetAllocatedIPs("")
allocatedIPs, err := util.GetAllocatedIPs(db, "")
if err != nil {
log.Error("Cannot suggest ip allocation. Failed to get list of allocated ip addresses: ", err)
return c.JSON(http.StatusInternalServerError, jsonHTTPResponse{
Expand Down
48 changes: 41 additions & 7 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ import (
"github.com/ngoduykhanh/wireguard-ui/emailer"
"github.com/ngoduykhanh/wireguard-ui/handler"
"github.com/ngoduykhanh/wireguard-ui/router"
"github.com/ngoduykhanh/wireguard-ui/store"
"github.com/ngoduykhanh/wireguard-ui/store/jsondb"
"github.com/ngoduykhanh/wireguard-ui/store/mysqldb"
"github.com/ngoduykhanh/wireguard-ui/util"
)

Expand All @@ -35,6 +37,13 @@ var (
flagEmailFrom string
flagEmailFromName string = "WireGuard UI"
flagSessionSecret string
flagDBType string = "jsondb"
flagDBHost string = "localhost"
flagDBPort int = 3306
flagDBDatabase string = "wireguard-ui"
flagDBUsername string
flagDBPassword string
flagDBTLS string = "false"
)

const (
Expand All @@ -61,6 +70,13 @@ func init() {
flag.StringVar(&flagEmailFrom, "email-from", util.LookupEnvOrString("EMAIL_FROM_ADDRESS", flagEmailFrom), "'From' email address.")
flag.StringVar(&flagEmailFromName, "email-from-name", util.LookupEnvOrString("EMAIL_FROM_NAME", flagEmailFromName), "'From' email name.")
flag.StringVar(&flagSessionSecret, "session-secret", util.LookupEnvOrString("SESSION_SECRET", flagSessionSecret), "The key used to encrypt session cookies.")
flag.StringVar(&flagDBType, "db-type", util.LookupEnvOrString("DB_TYPE", flagDBType), "Type of database to use. [jsondb, mysql]")
flag.StringVar(&flagDBHost, "db-host", util.LookupEnvOrString("DB_HOST", flagDBHost), "Database host")
flag.IntVar(&flagDBPort, "db-port", util.LookupEnvOrInt("DB_PORT", flagDBPort), "Database port")
flag.StringVar(&flagDBDatabase, "db-database", util.LookupEnvOrString("DB_DATABASE", flagDBDatabase), "Database name")
flag.StringVar(&flagDBUsername, "db-username", util.LookupEnvOrString("DB_USERNAME", flagDBUsername), "Database username")
flag.StringVar(&flagDBPassword, "db-password", util.LookupEnvOrString("DB_PASSWORD", flagDBPassword), "Database password")
flag.StringVar(&flagDBTLS, "db-tls", util.LookupEnvOrString("DB_TLS", flagDBTLS), "TLS mode. [true, false, skip-verify, preferred]")
flag.Parse()

// update runtime config
Expand All @@ -76,6 +92,13 @@ func init() {
util.EmailFrom = flagEmailFrom
util.EmailFromName = flagEmailFromName
util.SessionSecret = []byte(flagSessionSecret)
util.DBType = flagDBType
util.DBHost = flagDBHost
util.DBPort = flagDBPort
util.DBDatabase = flagDBDatabase
util.DBUsername = flagDBUsername
util.DBPassword = flagDBPassword
util.DBTLS = flagDBTLS

// print app information
fmt.Println("Wireguard UI")
Expand All @@ -89,18 +112,12 @@ func init() {
//fmt.Println("Sendgrid key\t:", util.SendgridApiKey)
fmt.Println("Email from\t:", util.EmailFrom)
fmt.Println("Email from name\t:", util.EmailFromName)
fmt.Println("Datastore\t:", util.DBType)
//fmt.Println("Session secret\t:", util.SessionSecret)

}

func main() {
db, err := jsondb.New("./db")
if err != nil {
panic(err)
}
if err := db.Init(); err != nil {
panic(err)
}
// set app extra data
extraData := make(map[string]string)
extraData["appVersion"] = appVersion
Expand All @@ -111,6 +128,23 @@ func main() {
// rice file server for assets. "assets" is the folder where the files come from.
assetHandler := http.FileServer(rice.MustFindBox("assets").HTTPBox())

// Configure database
var db store.IStore
var err error
switch util.DBType {
case "jsondb":
db, err = jsondb.New("./db")
case "mysql":
db, err = mysqldb.New(util.DBUsername, util.DBPassword, util.DBHost, util.DBPort, util.DBDatabase, util.DBTLS, tmplBox)
}

if err != nil {
panic(err)
}
if err := db.Init(); err != nil {
panic(err)
}

// register routes
app := router.New(tmplBox, extraData, util.SessionSecret)

Expand Down
Loading