Compare commits

...

5 Commits

Author SHA1 Message Date
Christoph Haas
a95fe42efe fix ci and docker build 2020-12-17 16:23:55 +01:00
Christoph Haas
262e8e2047 fix a few bugs, add instructions for raspberry pi 2020-12-17 16:10:05 +01:00
Christoph Haas
edd09a9e13 fix newlines in template 2020-12-17 14:01:03 +01:00
Christoph Haas
814f57d357 fix newlines in template 2020-12-17 13:47:46 +01:00
Christoph Haas
793c2fc27e remove unnecessary script and css files 2020-12-02 19:26:18 +01:00
21 changed files with 115 additions and 38610 deletions

View File

@@ -8,10 +8,17 @@ IMAGE=h44z/wg-portal
.PHONY: all test clean phony
all: dep test build
all: dep build
build: dep $(addprefix $(BUILDDIR)/,$(BINARIES))
build: dep $(addsuffix -amd64,$(addprefix $(BUILDDIR)/,$(BINARIES)))
cp -r assets $(BUILDDIR)
cp scripts/wg-portal.service $(BUILDDIR)
cp scripts/wg-portal.env $(BUILDDIR)
build-cross-plat: dep build $(addsuffix -arm,$(addprefix $(BUILDDIR)/,$(BINARIES))) $(addsuffix -arm64,$(addprefix $(BUILDDIR)/,$(BINARIES)))
cp -r assets $(BUILDDIR)
cp scripts/wg-portal.service $(BUILDDIR)
cp scripts/wg-portal.env $(BUILDDIR)
dep:
$(GOCMD) mod download
@@ -43,5 +50,13 @@ docker-build:
docker-push:
docker push $(IMAGE)
$(BUILDDIR)/%: cmd/%/main.go dep phony
$(GOCMD) build -o $@ $<
$(BUILDDIR)/%-amd64: cmd/%/main.go dep phony
GOOS=linux GOARCH=amd64 $(GOCMD) build -o $@ $<
# On arch-linux install aarch64-linux-gnu-gcc to crosscompile for arm64
$(BUILDDIR)/%-arm64: cmd/%/main.go dep phony
CGO_ENABLED=1 CC=aarch64-linux-gnu-gcc GOOS=linux GOARCH=arm64 $(GOCMD) build -ldflags "-linkmode external -extldflags -static" -o $@ $<
# On arch-linux install arm-linux-gnueabihf-gcc to crosscompile for arm
$(BUILDDIR)/%-arm: cmd/%/main.go dep phony
CGO_ENABLED=1 CC=arm-linux-gnueabihf-gcc GOOS=linux GOARCH=arm GOARM=7 $(GOCMD) build -ldflags "-linkmode external -extldflags -static" -o $@ $<

44
README-RASPBERRYPI.md Normal file
View File

@@ -0,0 +1,44 @@
# WireGuard Portal on Raspberry Pi
This readme only contains a detailed explanation of how to setup the WireGuard Portal service on a raspberry pi (>= 3).
## Setup
You can download prebuild binaries from the [release page](https://github.com/h44z/wg-portal/releases). If you want to build the binary yourself,
use the following instructions:
### Building
This section describes how to build the WireGuard Portal code.
To compile the final binary, use the Makefile provided in the repository.
As WireGuard Portal is written in Go, **golang >= 1.14** must be installed prior to building.
```
make build-cross-plat
```
The compiled binary and all necessary assets will be located in the dist folder.
### Service setup
- Copy the contents from the dist folder (or from the downloaded zip file) to `/opt/wg-portal`. You can choose a different path as well, but make sure to update the systemd service file accordingly.
- Update the provided systemd `wg-portal.service` file:
- Make sure that the binary matches the system architecture.
- There are three pre-build binaries available: wg-portal-**amd64**, wg-portal-**arm64** and wg-portal-**arm**.
- For a raspberry pi use the arm binary if you are using armv7l architecture. If armv8 is used, the arm64 version should work.
- Make sure that the paths to the binary and the working directory are set correctly (defaults to /opt/wg-portal/wg-portal-amd64):
- ConditionPathExists
- WorkingDirectory
- ExecStart
- EnvironmentFile
- Update environment variables in the `wg-portal.env` file to fit your needs
- Link the system service file to the correct folder:
- `sudo ln -s /opt/wg-portal/wg-portal.service /etc/systemd/system/wg-portal.service`
- Reload the systemctl daemon:
- `sudo systemctl daemon-reload`
### Manage the service
Once the service has been setup, you can simply manage the service using `systemctl`:
- Enable on startup: `systemctl enable wg-portal.service`
- Start: `systemctl start wg-portal.service`
- Stop: `systemctl stop wg-portal.service`
- Status: `systemctl status wg-portal.service`

View File

@@ -34,7 +34,7 @@ will only be available in combination with LDAP.
### Docker
The easiest way to run WireGuard Portal is using the provided docker image.
Docker compose snippet, used for demo server
Docker compose snippet with sample values:
```
version: '3.6'
services:
@@ -74,9 +74,13 @@ For a standalone application, use the Makefile provided in the repository to bui
```
make
# To build for arm architecture as well use:
make build-cross-plat
```
The compiled binary and all necessary assets will be located in the dist folder.
A detailed description for using this software with a raspberry pi can be found in the [README-RASPBERRYPI.md](README-RASPBERRYPI.md).
## What is out of scope

View File

@@ -1,209 +0,0 @@
/*!
* bootstrap-tokenfield
* https://github.com/sliptree/bootstrap-tokenfield
* Copyright 2013-2014 Sliptree and other contributors; Licensed MIT
*/
@-webkit-keyframes 'blink' {
0% {
border-color: #ededed;
}
100% {
border-color: #b94a48;
}
}
@-moz-keyframes 'blink' {
0% {
border-color: #ededed;
}
100% {
border-color: #b94a48;
}
}
@keyframes 'blink' {
0% {
border-color: #ededed;
}
100% {
border-color: #b94a48;
}
}
.tokenfield {
height: auto;
min-height: 34px;
padding-bottom: 0px;
}
.tokenfield.focus {
border-color: #66afe9;
outline: 0;
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px rgba(102, 175, 233, 0.6);
box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px rgba(102, 175, 233, 0.6);
}
.tokenfield .token {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
border-radius: 3px;
display: inline-block;
border: 1px solid #d9d9d9;
background-color: #ededed;
white-space: nowrap;
margin: -1px 5px 5px 0;
height: 22px;
vertical-align: top;
cursor: default;
}
.tokenfield .token:hover {
border-color: #b9b9b9;
}
.tokenfield .token.active {
border-color: #52a8ec;
border-color: rgba(82, 168, 236, 0.8);
}
.tokenfield .token.duplicate {
border-color: #ebccd1;
-webkit-animation-name: blink;
animation-name: blink;
-webkit-animation-duration: 0.1s;
animation-duration: 0.1s;
-webkit-animation-direction: normal;
animation-direction: normal;
-webkit-animation-timing-function: ease;
animation-timing-function: ease;
-webkit-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
.tokenfield .token.invalid {
background: none;
border: 1px solid transparent;
-webkit-border-radius: 0;
-moz-border-radius: 0;
border-radius: 0;
border-bottom: 1px dotted #d9534f;
}
.tokenfield .token.invalid.active {
background: #ededed;
border: 1px solid #ededed;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
border-radius: 3px;
}
.tokenfield .token .token-label {
display: inline-block;
overflow: hidden;
text-overflow: ellipsis;
padding-left: 4px;
vertical-align: top;
}
.tokenfield .token .close {
font-family: Arial;
display: inline-block;
line-height: 100%;
font-size: 1.1em;
line-height: 1.49em;
margin-left: 5px;
float: none;
height: 100%;
vertical-align: top;
padding-right: 4px;
}
.tokenfield .token-input {
background: none;
width: 60px;
min-width: 60px;
border: 0;
height: 20px;
padding: 0;
margin-bottom: 6px;
-webkit-box-shadow: none;
box-shadow: none;
}
.tokenfield .token-input:focus {
border-color: transparent;
outline: 0;
/* IE6-9 */
-webkit-box-shadow: none;
box-shadow: none;
}
.tokenfield.disabled {
cursor: not-allowed;
background-color: #eeeeee;
}
.tokenfield.disabled .token-input {
cursor: not-allowed;
}
.tokenfield.disabled .token:hover {
cursor: not-allowed;
border-color: #d9d9d9;
}
.tokenfield.disabled .token:hover .close {
cursor: not-allowed;
opacity: 0.2;
filter: alpha(opacity=20);
}
.has-warning .tokenfield.focus {
border-color: #66512c;
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b;
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b;
}
.has-error .tokenfield.focus {
border-color: #843534;
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483;
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483;
}
.has-success .tokenfield.focus {
border-color: #2b542c;
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168;
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168;
}
.tokenfield.input-sm,
.input-group-sm .tokenfield {
min-height: 30px;
padding-bottom: 0px;
}
.input-group-sm .token,
.tokenfield.input-sm .token {
height: 20px;
margin-bottom: 4px;
}
.input-group-sm .token-input,
.tokenfield.input-sm .token-input {
height: 18px;
margin-bottom: 5px;
}
.tokenfield.input-lg,
.input-group-lg .tokenfield {
min-height: 45px;
padding-bottom: 4px;
}
.input-group-lg .token,
.tokenfield.input-lg .token {
height: 25px;
}
.input-group-lg .token-label,
.tokenfield.input-lg .token-label {
line-height: 23px;
}
.input-group-lg .token .close,
.tokenfield.input-lg .token .close {
line-height: 1.3em;
}
.input-group-lg .token-input,
.tokenfield.input-lg .token-input {
height: 23px;
line-height: 23px;
margin-bottom: 6px;
vertical-align: top;
}
.tokenfield.rtl {
direction: rtl;
text-align: right;
}
.tokenfield.rtl .token {
margin: -1px 0 5px 5px;
}
.tokenfield.rtl .token .token-label {
padding-left: 0px;
padding-right: 4px;
}

10150
assets/css/bootstrap.css vendored

File diff suppressed because it is too large Load Diff

1312
assets/css/jquery-ui.css vendored

File diff suppressed because it is too large Load Diff

View File

@@ -1,141 +0,0 @@
/*!
* bootstrap-tokenfield
* https://github.com/sliptree/bootstrap-tokenfield
* Copyright 2013-2014 Sliptree and other contributors; Licensed MIT
*/
/* General Typeahead styling, from http://jsfiddle.net/ragulka/Dy9au/1/ */
.twitter-typeahead {
width: 100%;
position: relative;
vertical-align: top;
}
.twitter-typeahead .tt-input,
.twitter-typeahead .tt-hint {
margin: 0;
width: 100%;
vertical-align: middle;
background-color: #ffffff;
}
.twitter-typeahead .tt-hint {
color: #999999;
z-index: 1;
border: 1px solid transparent;
}
.twitter-typeahead .tt-input {
color: #555555;
z-index: 2;
}
.twitter-typeahead .tt-input,
.twitter-typeahead .tt-hint {
height: 34px;
padding: 6px 12px;
font-size: 14px;
line-height: 1.428571429;
}
.twitter-typeahead .input-sm.tt-input,
.twitter-typeahead .hint-sm.tt-hint {
border-radius: 3px;
}
.twitter-typeahead .input-lg.tt-input,
.twitter-typeahead .hint-lg.tt-hint {
border-radius: 6px;
}
.input-group .twitter-typeahead:first-child .tt-input,
.input-group .twitter-typeahead:first-child .tt-hint {
border-radius: 4px 0 0 4px !important;
}
.input-group .twitter-typeahead:last-child .tt-input,
.input-group .twitter-typeahead:last-child .tt-hint {
border-radius: 0 4px 4px 0 !important;
}
.input-group.input-group-sm .twitter-typeahead:first-child .tt-input,
.input-group.input-group-sm .twitter-typeahead:first-child .tt-hint {
border-radius: 3px 0 0 3px !important;
}
.input-group.input-group-sm .twitter-typeahead:last-child .tt-input,
.input-group.input-group-sm .twitter-typeahead:last-child .tt-hint {
border-radius: 0 3px 3px 0 !important;
}
.input-sm.tt-input,
.hint-sm.tt-hint,
.input-group.input-group-sm .tt-input,
.input-group.input-group-sm .tt-hint {
height: 30px;
padding: 5px 10px;
font-size: 12px;
line-height: 1.5;
}
.input-group.input-group-lg .twitter-typeahead:first-child .tt-input,
.input-group.input-group-lg .twitter-typeahead:first-child .tt-hint {
border-radius: 6px 0 0 6px !important;
}
.input-group.input-group-lg .twitter-typeahead:last-child .tt-input,
.input-group.input-group-lg .twitter-typeahead:last-child .tt-hint {
border-radius: 0 6px 6px 0 !important;
}
.input-lg.tt-input,
.hint-lg.tt-hint,
.input-group.input-group-lg .tt-input,
.input-group.input-group-lg .tt-hint {
height: 45px;
padding: 10px 16px;
font-size: 18px;
line-height: 1.33;
}
.tt-dropdown-menu {
width: 100%;
min-width: 160px;
margin-top: 2px;
padding: 5px 0;
background-color: #ffffff;
border: 1px solid #ccc;
border: 1px solid rgba(0, 0, 0, 0.15);
*border-right-width: 2px;
*border-bottom-width: 2px;
border-radius: 6px;
-webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
-webkit-background-clip: padding-box;
-moz-background-clip: padding;
background-clip: padding-box;
}
.tt-suggestion {
display: block;
padding: 3px 20px;
}
.tt-suggestion.tt-cursor {
color: #262626;
background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);
}
.tt-suggestion.tt-cursor a {
color: #ffffff;
}
.tt-suggestion p {
margin: 0;
}
/* Tokenfield-specific Typeahead styling */
.tokenfield .twitter-typeahead {
width: auto;
}
.tokenfield .twitter-typeahead .tt-hint {
padding: 0;
height: 20px;
}
.tokenfield.input-sm .twitter-typeahead .tt-input,
.tokenfield.input-sm .twitter-typeahead .tt-hint {
height: 18px;
font-size: 12px;
line-height: 1.5;
}
.tokenfield.input-lg .twitter-typeahead .tt-input,
.tokenfield.input-lg .twitter-typeahead .tt-hint {
height: 23px;
font-size: 18px;
line-height: 1.33;
}
.tokenfield .twitter-typeahead .tt-suggestions {
font-size: 14px;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

18706
assets/js/jquery-ui.js vendored

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -91,7 +91,7 @@
<button type="submit" class="btn btn-primary">Save</button>
<a href="/admin" class="btn btn-secondary">Cancel</a>
<a href="/admin/applyglobals" class="btn btn-dark float-right">Apply Allowed IP's to clients</a>
<a href="/admin/device/applyglobals" class="btn btn-dark float-right">Apply Allowed IP's to clients</a>
</form>
</div>
{{template "prt_footer.html" .}}

View File

@@ -100,7 +100,7 @@
<th class="column-top" width="280" style="font-size:0pt; line-height:0pt; padding:0; margin:0; font-weight:normal; vertical-align:top;">
<table width="100%" border="0" cellspacing="0" cellpadding="0">
<tr>
{{if not .Client.LdapUser}}
{{if .Client.LdapUser}}
<td class="h4 pb20" style="color:#000000; font-family:'Muli', Arial,sans-serif; font-size:20px; line-height:28px; text-align:left; padding-bottom:20px;">Hello {{.Client.LdapUser.Firstname}} {{.Client.LdapUser.Lastname}}</td>
{{else}}
<td class="h4 pb20" style="color:#000000; font-family:'Muli', Arial,sans-serif; font-size:20px; line-height:28px; text-align:left; padding-bottom:20px;">Hello</td>

View File

@@ -48,7 +48,6 @@
<script src="/js/jquery.min.js"></script>
<script src="/js/bootstrap.bundle.min.js"></script>
<script src="/js/jquery.easing.js"></script>
<script src="/js/jquery.fancybox.min.js"></script>
<script src="/js/custom.js"></script>
</body>

View File

@@ -73,6 +73,15 @@ func (s *Server) PostAdminEditInterface(c *gin.Context) {
return
}
// Update WireGuard config file
err = s.WriteWireGuardConfigFile()
if err != nil {
_ = s.updateFormInSession(c, formDevice)
s.setFlashMessage(c, "Failed to update wireguard config-file: "+err.Error(), "danger")
c.Redirect(http.StatusSeeOther, "/admin/device/edit?formerr=update")
return
}
s.setFlashMessage(c, "Changes applied successfully!", "success")
s.setFlashMessage(c, "WireGuard must be restarted to apply ip changes.", "warning")
c.Redirect(http.StatusSeeOther, "/admin/device/edit")

View File

@@ -5,35 +5,35 @@ var (
[Interface]
Address = {{ .Client.IPsStr }}
PrivateKey = {{ .Client.PrivateKey }}
{{if .Server.DNSStr -}}
{{- if .Server.DNSStr}}
DNS = {{ .Server.DNSStr }}
{{- end}}
{{- if ne .Server.Mtu 0 -}}
{{- if ne .Server.Mtu 0}}
MTU = {{.Server.Mtu}}
{{- end}}
[Peer]
PublicKey = {{ .Server.PublicKey }}
{{- if .Client.PresharedKey -}}
{{- if .Client.PresharedKey}}
PresharedKey = {{ .Client.PresharedKey }}
{{- end -}}
{{- end}}
AllowedIPs = {{ .Client.AllowedIPsStr }}
Endpoint = {{ .Server.Endpoint }}
{{if and (ne .Server.PersistentKeepalive 0) (not .Client.IgnorePersistentKeepalive) -}}
{{- if and (ne .Server.PersistentKeepalive 0) (not .Client.IgnorePersistentKeepalive)}}
PersistentKeepalive = {{.Server.PersistentKeepalive}}
{{- end}}
`
DeviceCfgTpl = `# AUTOGENERATED FILE - DO NOT EDIT
# Updated: {{ .Server.UpdatedAt }} / Created: {{ .Server.CreatedAt }}
[Interface]
{{- range .Server.IPs }}
{{- range .Server.IPs}}
Address = {{ . }}
{{- end}}
ListenPort = {{ .Server.ListenPort }}
PrivateKey = {{ .Server.PrivateKey }}
{{- if ne .Server.Mtu 0 -}}
{{- if ne .Server.Mtu 0}}
MTU = {{.Server.Mtu}}
{{- end -}}
{{- end}}
PreUp = {{ .Server.PreUp }}
PostUp = {{ .Server.PostUp }}
PreDown = {{ .Server.PreDown }}
@@ -44,9 +44,9 @@ PostDown = {{ .Server.PostDown }}
# {{.Identifier}} / {{.Email}} / Updated: {{.UpdatedAt}} / Created: {{.CreatedAt}}
[Peer]
PublicKey = {{ .PublicKey }}
{{- if .PresharedKey -}}
{{- if .PresharedKey}}
PresharedKey = {{ .PresharedKey }}
{{- end -}}
{{- end}}
AllowedIPs = {{ StringsJoin .IPs ", " }}
{{- end}}
{{end}}`

6
scripts/wg-portal.env Normal file
View File

@@ -0,0 +1,6 @@
LISTENING_ADDRESS=:8080
EXTERNAL_URL=https://vpn.company.com
WEBSITE_TITLE=WireGuard VPN
COMPANY_NAME=Your Company Name
ADMIN_USER=admin
ADMIN_PASS=supersecret

19
scripts/wg-portal.service Normal file
View File

@@ -0,0 +1,19 @@
[Unit]
Description=WireGuard Portal
ConditionPathExists=/opt/wg-portal/wg-portal-amd64
After=network.target
[Service]
Type=simple
User=root
Group=root
Restart=on-failure
RestartSec=10
WorkingDirectory=/opt/wg-portal
ExecStart=/opt/wg-portal/wg-portal-amd64
EnvironmentFile=/opt/wg-portal/wg-portal.env
[Install]
WantedBy=multi-user.target