Added wireguard service in container
This commit is contained in:
		
							parent
							
								
									f43c59c043
								
							
						
					
					
						commit
						a13b78b1f5
					
				
							
								
								
									
										27
									
								
								Dockerfile
								
								
								
								
							
							
						
						
									
										27
									
								
								Dockerfile
								
								
								
								
							|  | @ -13,11 +13,8 @@ RUN apk add --update --no-cache ${BUILD_DEPENDENCIES} | |||
| 
 | ||||
| WORKDIR /build | ||||
| 
 | ||||
| # Add dependencies | ||||
| COPY go.mod /build | ||||
| COPY go.sum /build | ||||
| COPY package.json /build | ||||
| COPY yarn.lock /build | ||||
| # Add sources | ||||
| COPY . /build | ||||
| 
 | ||||
| # Prepare assets | ||||
| RUN yarn install --pure-lockfile --production && \ | ||||
|  | @ -42,34 +39,30 @@ RUN mkdir -p assets/plugins && \ | |||
|     /build/node_modules/jquery-tags-input/ \ | ||||
|     assets/plugins/ | ||||
| 
 | ||||
| # Move custom assets | ||||
| RUN cp -r /build/custom/ assets/ | ||||
| 
 | ||||
| # Get go modules and build tool | ||||
| RUN go mod download && \ | ||||
|     go get github.com/GeertJohan/go.rice/rice | ||||
| 
 | ||||
| # Add sources | ||||
| COPY . /build | ||||
| 
 | ||||
| # Move custom assets | ||||
| RUN cp -r /build/custom/ assets/ | ||||
| 
 | ||||
| # Build | ||||
| RUN rice embed-go && \ | ||||
|     CGO_ENABLED=0 GOOS=${TARGETOS} GOARCH=${TARGETARCH} go build -a -o wg-ui . | ||||
| 
 | ||||
| # Release stage | ||||
| FROM alpine:3.11 | ||||
| FROM ubuntu:22.04 | ||||
| ENV TZ=Europe/Minsk | ||||
| ENV DEBIAN_FRONTEND=noninteractive | ||||
| 
 | ||||
| RUN addgroup -S wgui && \ | ||||
|     adduser -S -D -G wgui wgui | ||||
| 
 | ||||
| RUN apk --no-cache add ca-certificates | ||||
| RUN apt-get update && apt upgrade -y && apt-get install -y wireguard wireguard-tools iptables iproute2 | ||||
| 
 | ||||
| WORKDIR /app | ||||
| 
 | ||||
| RUN mkdir -p db | ||||
| 
 | ||||
| # Copy binary files | ||||
| COPY --from=builder --chown=wgui:wgui /build/wg-ui /app | ||||
| COPY --from=builder /build/wg-ui /app | ||||
| 
 | ||||
| RUN chmod +x wg-ui | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										69
									
								
								README.md
								
								
								
								
							
							
						
						
									
										69
									
								
								README.md
								
								
								
								
							|  | @ -9,6 +9,9 @@ A web user interface to manage your WireGuard setup. | |||
| - Authentication | ||||
| - Manage extra client's information (name, email, etc) | ||||
| - Retrieve configs using QR code / file | ||||
| - start wireguard interface / rules | ||||
| - stop wireguard interface / rules | ||||
| - restart wireguard interface / rules | ||||
| 
 | ||||
| ## Run WireGuard-UI | ||||
| 
 | ||||
|  | @ -100,72 +103,6 @@ EMAIL_FROM_ADDRESS: the sender's email address | |||
| EMAIL_FROM_NAME: the sender's name | ||||
| ``` | ||||
| 
 | ||||
| ## 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: | ||||
| 
 | ||||
| ### systemd | ||||
| 
 | ||||
| Create /etc/systemd/system/wgui.service | ||||
| 
 | ||||
| ``` | ||||
| [Unit] | ||||
| Description=Restart WireGuard | ||||
| After=network.target | ||||
| 
 | ||||
| [Service] | ||||
| Type=oneshot | ||||
| ExecStart=/usr/bin/systemctl restart wg-quick@wg0.service | ||||
| 
 | ||||
| [Install] | ||||
| RequiredBy=wgui.path | ||||
| ``` | ||||
| 
 | ||||
| Create /etc/systemd/system/wgui.path | ||||
| 
 | ||||
| ``` | ||||
| [Unit] | ||||
| Description=Watch /etc/wireguard/wg0.conf for changes | ||||
| 
 | ||||
| [Path] | ||||
| PathModified=/etc/wireguard/wg0.conf | ||||
| 
 | ||||
| [Install] | ||||
| WantedBy=multi-user.target | ||||
| ``` | ||||
| 
 | ||||
| Apply it | ||||
| 
 | ||||
| ``` | ||||
| systemctl enable wgui.{path,service} | ||||
| systemctl start wgui.{path,service} | ||||
| ``` | ||||
| 
 | ||||
| ### openrc | ||||
| 
 | ||||
| Create and `chmod +x` /usr/local/bin/wgui | ||||
| ``` | ||||
| #!/bin/sh | ||||
| wg-quick down wg0 | ||||
| wg-quick up wg0 | ||||
| ``` | ||||
| 
 | ||||
| Create and `chmod +x` /etc/init.d/wgui | ||||
| ``` | ||||
| #!/sbin/openrc-run | ||||
| 
 | ||||
| command=/sbin/inotifyd | ||||
| command_args="/usr/local/bin/wgui /etc/wireguard/wg0.conf:w" | ||||
| pidfile=/run/${RC_SVCNAME}.pid | ||||
| command_background=yes | ||||
| ``` | ||||
| 
 | ||||
| Apply it | ||||
| 
 | ||||
| ``` | ||||
| rc-service wgui start | ||||
| rc-update add wgui default | ||||
| ``` | ||||
| 
 | ||||
| ## Build | ||||
| 
 | ||||
| ### Build docker image | ||||
|  |  | |||
|  | @ -686,6 +686,82 @@ func SuggestIPAllocation(db store.IStore) echo.HandlerFunc { | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| // Restart Wireguard Server handler to stop Wireguard server
 | ||||
| func RestartServer(db store.IStore, tmplBox *rice.Box) echo.HandlerFunc { | ||||
| 	return func(c echo.Context) error { | ||||
| 
 | ||||
| 		settings, err := db.GetGlobalSettings() | ||||
| 		if err != nil { | ||||
| 			log.Error("Cannot get global settings: ", err) | ||||
| 			return c.JSON(http.StatusInternalServerError, jsonHTTPResponse{false, "Cannot get global settings"}) | ||||
| 		} | ||||
| 
 | ||||
| 		// Stop Server
 | ||||
| 		err = util.StopWireGuardServer(settings) | ||||
| 		if err != nil { | ||||
| 			log.Error("Cannot stop server: ", err) | ||||
| 			return c.JSON(http.StatusInternalServerError, jsonHTTPResponse{ | ||||
| 				false, fmt.Sprintf("Cannot stop server: %v", err), | ||||
| 			}) | ||||
| 		} | ||||
| 
 | ||||
| 		// Start Server
 | ||||
| 		err = util.StartWireGuardServer(settings) | ||||
| 		if err != nil { | ||||
| 			log.Error("Cannot start server: ", err) | ||||
| 			return c.JSON(http.StatusInternalServerError, jsonHTTPResponse{ | ||||
| 				false, fmt.Sprintf("Cannot start server: %v", err), | ||||
| 			}) | ||||
| 		} | ||||
| 
 | ||||
| 		return c.JSON(http.StatusOK, jsonHTTPResponse{true, "Restarted Wireguard Server successfully"}) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // Stop Wireguard Server handler to stop Wireguard server
 | ||||
| func StopServer(db store.IStore, tmplBox *rice.Box) echo.HandlerFunc { | ||||
| 	return func(c echo.Context) error { | ||||
| 
 | ||||
| 		settings, err := db.GetGlobalSettings() | ||||
| 		if err != nil { | ||||
| 			log.Error("Cannot get global settings: ", err) | ||||
| 			return c.JSON(http.StatusInternalServerError, jsonHTTPResponse{false, "Cannot get global settings"}) | ||||
| 		} | ||||
| 
 | ||||
| 		// Stop Server
 | ||||
| 		err = util.StopWireGuardServer(settings) | ||||
| 		if err != nil { | ||||
| 			log.Error("Cannot stop server: ", err) | ||||
| 			return c.JSON(http.StatusInternalServerError, jsonHTTPResponse{ | ||||
| 				false, fmt.Sprintf("Cannot stop server: %v", err), | ||||
| 			}) | ||||
| 		} | ||||
| 		return c.JSON(http.StatusOK, jsonHTTPResponse{true, "Stopped Wireguard Server successfully"}) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // Start Wireguard Server handler to start Wireguard server
 | ||||
| func StartServer(db store.IStore, tmplBox *rice.Box) echo.HandlerFunc { | ||||
| 	return func(c echo.Context) error { | ||||
| 
 | ||||
| 		settings, err := db.GetGlobalSettings() | ||||
| 		if err != nil { | ||||
| 			log.Error("Cannot get global settings: ", err) | ||||
| 			return c.JSON(http.StatusInternalServerError, jsonHTTPResponse{false, "Cannot get global settings"}) | ||||
| 		} | ||||
| 
 | ||||
| 		// Start Server
 | ||||
| 		err = util.StartWireGuardServer(settings) | ||||
| 		if err != nil { | ||||
| 			log.Error("Cannot start server: ", err) | ||||
| 			return c.JSON(http.StatusInternalServerError, jsonHTTPResponse{ | ||||
| 				false, fmt.Sprintf("Cannot start server: %v", err), | ||||
| 			}) | ||||
| 		} | ||||
| 		return c.JSON(http.StatusOK, jsonHTTPResponse{true, "Started Wireguard Server successfully"}) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // ApplyServerConfig handler to write config file and restart Wireguard server
 | ||||
| func ApplyServerConfig(db store.IStore, tmplBox *rice.Box) echo.HandlerFunc { | ||||
| 	return func(c echo.Context) error { | ||||
|  |  | |||
							
								
								
									
										6
									
								
								main.go
								
								
								
								
							
							
						
						
									
										6
									
								
								main.go
								
								
								
								
							|  | @ -17,7 +17,7 @@ import ( | |||
| 
 | ||||
| var ( | ||||
| 	// command-line banner information
 | ||||
| 	appVersion = "development" | ||||
| 	appVersion = "development-2" | ||||
| 	gitCommit  = "N/A" | ||||
| 	gitRef     = "N/A" | ||||
| 	buildTime  = fmt.Sprintf(time.Now().UTC().Format("01-02-2006 15:04:05")) | ||||
|  | @ -97,6 +97,7 @@ func init() { | |||
| 	//fmt.Println("Session secret\t:", util.SessionSecret)
 | ||||
| 	fmt.Println("Custom wg.conf\t:", util.WgConfTemplate) | ||||
| 	fmt.Println("Base path\t:", util.BasePath + "/") | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| func main() { | ||||
|  | @ -154,6 +155,9 @@ func main() { | |||
| 	app.GET(util.BasePath + "/api/machine-ips", handler.MachineIPAddresses(), handler.ValidSession) | ||||
| 	app.GET(util.BasePath + "/api/suggest-client-ips", handler.SuggestIPAllocation(db), handler.ValidSession) | ||||
| 	app.GET(util.BasePath + "/api/apply-wg-config", handler.ApplyServerConfig(db, tmplBox), handler.ValidSession) | ||||
| 	app.GET(util.BasePath + "/api/start-wg", handler.StartServer(db, tmplBox), handler.ValidSession) | ||||
| 	app.GET(util.BasePath + "/api/stop-wg", handler.StopServer(db, tmplBox), handler.ValidSession) | ||||
| 	app.GET(util.BasePath + "/api/restart-wg", handler.RestartServer(db, tmplBox), handler.ValidSession) | ||||
| 	app.GET(util.BasePath + "/wake_on_lan_hosts", handler.GetWakeOnLanHosts(db), handler.ValidSession) | ||||
| 	app.POST(util.BasePath + "/wake_on_lan_host", handler.SaveWakeOnLanHost(db), handler.ValidSession) | ||||
| 	app.DELETE(util.BasePath + "/wake_on_lan_host/:mac_address", handler.DeleteWakeOnHost(db), handler.ValidSession) | ||||
|  |  | |||
|  | @ -64,6 +64,12 @@ | |||
|                 <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> | ||||
|                 <button id="start-wg" style="margin-left: 0.5em;" type="button" | ||||
|                         class="btn btn-outline-success btn-sm"><i class="nav-icon fa fa-play"></i> Start</button> | ||||
|                 <button id="stop-wg" style="margin-left: 0.5em;" type="button" | ||||
|                         class="btn btn-outline-danger btn-sm"><i class="nav-icon fa fa-stop"></i> Stop</button> | ||||
|                 <button id="restart-wg" style="margin-left: 0.5em;" type="button" | ||||
|                         class="btn btn-outline-success btn-sm"><i class="nav-icon fa fa-retweet"></i> Restart</button> | ||||
|                 {{if .baseData.CurrentUser}} | ||||
|                 <button onclick="location.href='{{.basePath}}/logout';" style="margin-left: 0.5em;" type="button" | ||||
|                     class="btn btn-outline-danger btn-sm"><i class="nav-icon fas fa-sign-out-alt"></i> Logout</button> | ||||
|  | @ -246,7 +252,7 @@ | |||
|                         </button> | ||||
|                     </div> | ||||
|                     <div class="modal-body"> | ||||
|                         <p>Do you want to write config file and restart WireGuard server?</p> | ||||
|                         <p>Do you want to write config file?</p> | ||||
|                     </div> | ||||
|                     <div class="modal-footer justify-content-between"> | ||||
|                         <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button> | ||||
|  | @ -489,6 +495,66 @@ | |||
|             }); | ||||
|         }); | ||||
| 
 | ||||
|         // restart wireguard button event | ||||
|         $(document).ready(function () { | ||||
|             $("#restart-wg").click(function () { | ||||
|                 $.ajax({ | ||||
|                     cache: false, | ||||
|                     method: 'GET', | ||||
|                     url: '{{.basePath}}/api/restart-wg', | ||||
|                     dataType: 'json', | ||||
|                     contentType: "application/json", | ||||
|                     success: function(data) { | ||||
|                         toastr.success('Wireguard restart successfully'); | ||||
|                     }, | ||||
|                     error: function(jqXHR, exception) { | ||||
|                         const responseJson = jQuery.parseJSON(jqXHR.responseText); | ||||
|                         toastr.error(responseJson['message']); | ||||
|                     } | ||||
|                 }); | ||||
|             }); | ||||
|         }); | ||||
| 
 | ||||
|         // stop wireguard button event | ||||
|         $(document).ready(function () { | ||||
|             $("#stop-wg").click(function () { | ||||
|                 $.ajax({ | ||||
|                     cache: false, | ||||
|                     method: 'GET', | ||||
|                     url: '{{.basePath}}/api/stop-wg', | ||||
|                     dataType: 'json', | ||||
|                     contentType: "application/json", | ||||
|                     success: function(data) { | ||||
|                         toastr.success('Wireguard stopped successfully'); | ||||
|                     }, | ||||
|                     error: function(jqXHR, exception) { | ||||
|                         const responseJson = jQuery.parseJSON(jqXHR.responseText); | ||||
|                         toastr.error(responseJson['message']); | ||||
|                     } | ||||
|                 }); | ||||
|             }); | ||||
|         }); | ||||
| 
 | ||||
|         // start wireguard button event | ||||
|         $(document).ready(function () { | ||||
|             $("#start-wg").click(function () { | ||||
|                 $.ajax({ | ||||
|                     cache: false, | ||||
|                     method: 'GET', | ||||
|                     url: '{{.basePath}}/api/start-wg', | ||||
|                     dataType: 'json', | ||||
|                     contentType: "application/json", | ||||
|                     success: function(data) { | ||||
|                         toastr.success('Wireguard started successfully'); | ||||
|                     }, | ||||
|                     error: function(jqXHR, exception) { | ||||
|                         const responseJson = jQuery.parseJSON(jqXHR.responseText); | ||||
|                         toastr.error(responseJson['message']); | ||||
|                     } | ||||
|                 }); | ||||
|             }); | ||||
|         }); | ||||
| 
 | ||||
|         // apply_config_confirm button event | ||||
|         $(document).ready(function () { | ||||
|             $("#apply_config_confirm").click(function () { | ||||
|  |  | |||
							
								
								
									
										47
									
								
								util/util.go
								
								
								
								
							
							
						
						
									
										47
									
								
								util/util.go
								
								
								
								
							|  | @ -7,6 +7,7 @@ import ( | |||
| 	"io/ioutil" | ||||
| 	"net" | ||||
| 	"os" | ||||
| 	"os/exec" | ||||
| 	"strconv" | ||||
| 	"strings" | ||||
| 	"text/template" | ||||
|  | @ -375,6 +376,52 @@ func ValidateIPAllocation(serverAddresses []string, ipAllocatedList []string, ip | |||
| 	return true, nil | ||||
| } | ||||
| 
 | ||||
| // StopWireguard Server to stop Wireguard server with config. e.g. wg0.conf
 | ||||
| func StopWireGuardServer(globalSettings model.GlobalSetting) error { | ||||
| 
 | ||||
|     app := "wg-quick" | ||||
| 
 | ||||
|     arg0 := "down" | ||||
|     arg1 := globalSettings.ConfigFilePath | ||||
| 
 | ||||
| 
 | ||||
|     cmd := exec.Command(app, arg0, arg1) | ||||
|     stdout, err := cmd.Output() | ||||
| 
 | ||||
|     if err != nil { | ||||
|         fmt.Println(err.Error()) | ||||
|         return err | ||||
|     } | ||||
| 
 | ||||
|     // Print the output
 | ||||
|     fmt.Println(string(stdout)) | ||||
| 
 | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // StartWireguard Server to start Wireguard server with config. e.g. wg0.conf
 | ||||
| func StartWireGuardServer(globalSettings model.GlobalSetting) error { | ||||
| 
 | ||||
|     app := "wg-quick" | ||||
| 
 | ||||
|     arg0 := "up" | ||||
|     arg1 := globalSettings.ConfigFilePath | ||||
| 
 | ||||
| 
 | ||||
|     cmd := exec.Command(app, arg0, arg1) | ||||
|     stdout, err := cmd.Output() | ||||
| 
 | ||||
|     if err != nil { | ||||
|         fmt.Println(err.Error()) | ||||
|         return err | ||||
|     } | ||||
| 
 | ||||
|     // Print the output
 | ||||
|     fmt.Println(string(stdout)) | ||||
| 
 | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // WriteWireGuardServerConfig to write Wireguard server config. e.g. wg0.conf
 | ||||
| func WriteWireGuardServerConfig(tmplBox *rice.Box, serverConfig model.Server, clientDataList []model.ClientData, globalSettings model.GlobalSetting) error { | ||||
| 	var tmplWireguardConf string | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue