diff --git a/.github/workflows/chart.yml b/.github/workflows/chart.yml
index 946f71a..11bd74c 100644
--- a/.github/workflows/chart.yml
+++ b/.github/workflows/chart.yml
@@ -10,10 +10,10 @@ name: Chart
on:
pull_request:
branches: [master]
- paths: [deploy/helm]
+ paths: ['deploy/helm/**']
push:
branches: [master]
- paths: [deploy/helm]
+ paths: ['deploy/helm/**']
jobs:
lint-test:
@@ -24,6 +24,14 @@ jobs:
with:
fetch-depth: 0
+ - name: Check docs
+ run: |
+ make helm-docs
+ if ! git diff --exit-code; then
+ echo "error::Documentation is not up to date. Please run helm-docs and commit changes."
+ exit 1
+ fi
+
# ct lint requires Python 3.x to run following packages:
# - yamale (https://github.com/23andMe/Yamale)
# - yamllint (https://github.com/adrienverge/yamllint)
@@ -36,15 +44,9 @@ jobs:
- name: Run chart-testing (lint)
run: ct lint --config ct.yaml
- - name: Check docs
- run: |
- docker run --rm --volume "${PWD}/deploy:/helm-docs" -u "$(id -u)" jnorwood/helm-docs
- if ! git diff --exit-code; then
- echo "error::Documentation is not up to date. Please run helm-docs and commit changes."
- exit 1
- fi
-
- - uses: helm/kind-action@v1
+ - uses: nolar/setup-k3d-k3s@v1
+ with:
+ github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Run chart-testing (install)
run: ct install --config ct.yaml
diff --git a/Makefile b/Makefile
index 7334b32..0b72e16 100644
--- a/Makefile
+++ b/Makefile
@@ -127,4 +127,9 @@ build-docker:
docker build --progress=plain \
--build-arg BUILD_IDENTIFIER=${ENV_BUILD_IDENTIFIER} --build-arg BUILD_VERSION=${ENV_BUILD_VERSION} \
--build-arg TARGETPLATFORM=unknown . \
- -t h44z/wg-portal:local
\ No newline at end of file
+ -t h44z/wg-portal:local
+
+#< helm-docs: Generate the helm chart documentation
+.PHONY: helm-docs
+helm-docs:
+ docker run --rm --volume "${PWD}/deploy:/helm-docs" -u "$$(id -u)" jnorwood/helm-docs -s file
diff --git a/README.md b/README.md
index e9fd180..acc50e9 100644
--- a/README.md
+++ b/README.md
@@ -142,7 +142,8 @@ The following configuration options are available:
| csrf_secret | web | extremely_secret | The CSRF secret. |
| site_title | web | WireGuard Portal | The title that is shown in the web frontend. |
| site_company_name | web | WireGuard Portal | The company name that is shown at the bottom of the web frontend. |
-
+| cert_file | web | | (Optional) Path to the TLS certificate file |
+| key_file | web | | (Optional) Path to the TLS certificate key file |
## Upgrading from V1
diff --git a/deploy/helm/Chart.yaml b/deploy/helm/Chart.yaml
index e17febb..2f2bb87 100644
--- a/deploy/helm/Chart.yaml
+++ b/deploy/helm/Chart.yaml
@@ -16,10 +16,10 @@ annotations:
# This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/)
-version: 0.1.0
+version: 0.2.0
# This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application. Versions are not expected to
# follow Semantic Versioning. They should reflect the version the application is using.
# It is recommended to use it with quotes.
-appVersion: v2.0.0-alpha.2
+appVersion: latest
diff --git a/deploy/helm/README.md b/deploy/helm/README.md
index 59869ef..8cadb51 100644
--- a/deploy/helm/README.md
+++ b/deploy/helm/README.md
@@ -1,6 +1,6 @@
# wg-portal
-  
+  
WireGuard Configuration Portal with LDAP, OAuth, OIDC authentication
@@ -27,90 +27,80 @@ The [Values](#values) section lists the parameters that can be configured during
## Values
-### Parameters
-
-| Key | Type | Default | Description |
-|-----|------|---------|-------------|
-| affinity | object | `{}` | Affinity configuration |
-| args | list | `[]` | Additional pod arguments |
-| command | list | `[]` | Overwrite pod command |
-| dnsPolicy | string | `"ClusterFirst"` | Set DNS policy for the pod. Valid values are `ClusterFirstWithHostNet`, `ClusterFirst`, `Default` or `None`. |
-| env | tpl/list | `[]` | Additional environment variables |
-| envFrom | tpl/list | `[]` | Additional environment variables from a secret or configMap |
-| hostNetwork | string | `false`. | Use the host's network namespace. |
-| image.pullPolicy | string | `"IfNotPresent"` | Image pull policy |
-| image.repository | string | `"ghcr.io/h44z/wg-portal"` | Image repository |
-| image.tag | string | `""` | Overrides the image tag whose default is the chart appVersion |
-| imagePullSecrets | list | `[]` | Image pull secrets |
-| initContainers | tpl/list | `[]` | Pod init containers |
-| nodeSelector | object | `{"kubernetes.io/os":"linux"}` | Node Selector configuration |
-| podAnnotations | tpl/object | `{}` | Extra annotations to add to the pod |
-| podLabels | object | `{}` | Extra labels to add to the pod |
-| podSecurityContext | object | `{}` | Pod Security Context |
-| resources | object | `{}` | Resources requests and limits |
-| restartPolicy | string | `"Always"` | Restart policy for all containers within the pod. Valid values are `Always`, `OnFailure` or `Never`. |
-| revisionHistoryLimit | string | `10` | The number of old ReplicaSets to retain to allow rollback. |
-| securityContext.capabilities.add | list | `["NET_ADMIN"]` | Add capabilities to the container |
-| sidecarContainers | tpl/list | `[]` | Pod sidecar containers |
-| strategy | object | `{"type":"RollingUpdate"}` | Update strategy for the workload Valid values are: `RollingUpdate` or `Recreate` for Deployment, `RollingUpdate` or `OnDelete` for StatefulSet |
-| tolerations | list | `[]` | Tolerations configuration |
-| volumeMounts | tpl/list | `[]` | Additional volumeMounts |
-| volumes | tpl/list | `[]` | Additional volumes |
-| workloadType | string | `"Deployment"` | Workload type - `Deployment` or `StatefulSet` |
-
-### Configuration
-
| Key | Type | Default | Description |
|-----|------|---------|-------------|
+| nameOverride | string | `""` | Partially override resource names (adds suffix) |
+| fullnameOverride | string | `""` | Fully override resource names |
+| extraDeploy | list | `[]` | Array of extra objects to deploy with the release |
| config.advanced | tpl/object | `{}` | Advanced configuration options. |
| config.auth | tpl/object | `{}` | Auth configuration options. |
| config.core | tpl/object | `{}` | Core configuration options.
If external admins in `auth` are not defined and there are no `admin_user` and `admin_password` defined here, the default credentials will be generated. |
| config.database | tpl/object | `{}` | Database configuration options |
| config.mail | tpl/object | `{}` | Mail configuration options |
| config.statistics | tpl/object | `{}` | Statistics configuration options |
-| config.web | tpl/object | `{}` | Web configuration options.
The chart will set `listening_address` automatically from `service.web.port`, and `external_url` from `ingress.host` if enabled. |
-
-### Common
-
-| Key | Type | Default | Description |
-|-----|------|---------|-------------|
-| extraDeploy | list | `[]` | Array of extra objects to deploy with the release |
-| fullnameOverride | string | `""` | Fully override resource names |
-| nameOverride | string | `""` | Partially override resource names (adds suffix) |
-
-### Traffic exposure
-
-| Key | Type | Default | Description |
-|-----|------|---------|-------------|
-| ingress.annotations | object | `{}` | Ingress annotations |
-| ingress.className | string | `""` | Ingress class name |
-| ingress.enabled | bool | `false` | Specifies whether an ingress resource should be created |
-| ingress.host | string | `""` | Ingress host FQDN |
-| ingress.path | string | `"/"` | Ingress path |
-| ingress.pathType | string | `"ImplementationSpecific"` | Ingress path type |
-| ingress.tls | list | `[]` | Ingress TLS configuration |
+| config.web | tpl/object | `{}` | Web configuration options.
`listening_address` will be set automatically from `service.web.port`. `external_url` is required to enable ingress and certificate resources. |
+| revisionHistoryLimit | string | `10` | The number of old ReplicaSets to retain to allow rollback. |
+| workloadType | string | `"Deployment"` | Workload type - `Deployment` or `StatefulSet` |
+| strategy | object | `{"type":"RollingUpdate"}` | Update strategy for the workload Valid values are: `RollingUpdate` or `Recreate` for Deployment, `RollingUpdate` or `OnDelete` for StatefulSet |
+| image.repository | string | `"ghcr.io/h44z/wg-portal"` | Image repository |
+| image.pullPolicy | string | `"IfNotPresent"` | Image pull policy |
+| image.tag | string | `""` | Overrides the image tag whose default is the chart appVersion |
+| imagePullSecrets | list | `[]` | Image pull secrets |
+| podAnnotations | tpl/object | `{}` | Extra annotations to add to the pod |
+| podLabels | object | `{}` | Extra labels to add to the pod |
+| podSecurityContext | object | `{}` | Pod Security Context |
+| securityContext.capabilities.add | list | `["NET_ADMIN"]` | Add capabilities to the container |
+| initContainers | tpl/list | `[]` | Pod init containers |
+| sidecarContainers | tpl/list | `[]` | Pod sidecar containers |
+| dnsPolicy | string | `"ClusterFirst"` | Set DNS policy for the pod. Valid values are `ClusterFirstWithHostNet`, `ClusterFirst`, `Default` or `None`. |
+| restartPolicy | string | `"Always"` | Restart policy for all containers within the pod. Valid values are `Always`, `OnFailure` or `Never`. |
+| hostNetwork | string | `false`. | Use the host's network namespace. |
+| resources | object | `{}` | Resources requests and limits |
+| command | list | `[]` | Overwrite pod command |
+| args | list | `[]` | Additional pod arguments |
+| env | tpl/list | `[]` | Additional environment variables |
+| envFrom | tpl/list | `[]` | Additional environment variables from a secret or configMap |
+| livenessProbe | object | `{}` | Liveness probe configuration |
+| readinessProbe | object | `{}` | Readiness probe configuration |
+| startupProbe | object | `{}` | Startup probe configuration |
+| volumes | tpl/list | `[]` | Additional volumes |
+| volumeMounts | tpl/list | `[]` | Additional volumeMounts |
+| nodeSelector | object | `{"kubernetes.io/os":"linux"}` | Node Selector configuration |
+| tolerations | list | `[]` | Tolerations configuration |
+| affinity | object | `{}` | Affinity configuration |
+| service.mixed.enabled | bool | `false` | Whether to create a single service for the web and wireguard interfaces |
+| service.mixed.type | string | `"LoadBalancer"` | Service type |
| service.web.annotations | object | `{}` | Annotations for the web service |
-| service.web.port | int | `8888` | Web service port Used for the web interface listener |
| service.web.type | string | `"ClusterIP"` | Web service type |
+| service.web.port | int | `8888` | Web service port Used for the web interface listener |
| service.wireguard.annotations | object | `{}` | Annotations for the WireGuard service |
-| service.wireguard.ports | list | `[51820]` | Wireguard service ports. Exposes the WireGuard ports for created interfaces. Lowerest port is selected as start port for the first interface. Increment next port by 1 for each additional interface. |
| service.wireguard.type | string | `"LoadBalancer"` | Wireguard service type |
-
-### Persistence
-
-| Key | Type | Default | Description |
-|-----|------|---------|-------------|
-| persistence.accessMode | string | `"ReadWriteOnce"` | Persistent Volume Access Mode |
-| persistence.annotations | object | `{}` | Persistent Volume Claim annotations |
+| service.wireguard.ports | list | `[51820]` | Wireguard service ports. Exposes the WireGuard ports for created interfaces. Lowerest port is selected as start port for the first interface. Increment next port by 1 for each additional interface. |
+| ingress.enabled | bool | `false` | Specifies whether an ingress resource should be created |
+| ingress.className | string | `""` | Ingress class name |
+| ingress.annotations | object | `{}` | Ingress annotations |
+| ingress.tls | bool | `false` | Ingress TLS configuration. Enable certificate resource or add ingress annotation to create required secret |
+| certificate.enabled | bool | `false` | Specifies whether a certificate resource should be created |
+| certificate.issuer.name | string | `""` | Certificate issuer name |
+| certificate.issuer.kind | string | `""` | Certificate issuer kind (ClusterIssuer or Issuer) |
+| certificate.issuer.group | string | `"cert-manager.io"` | Certificate issuer group |
+| certificate.duration | string | `""` | Optional. [Documentation](https://cert-manager.io/docs/usage/certificate/#creating-certificate-resources) |
+| certificate.renewBefore | string | `""` | Optional. [Documentation](https://cert-manager.io/docs/usage/certificate/#creating-certificate-resources) |
+| certificate.commonName | string | `""` | Optional. [Documentation](https://cert-manager.io/docs/usage/certificate/#creating-certificate-resources) |
+| certificate.emailAddresses | list | `[]` | Optional. [Documentation](https://cert-manager.io/docs/usage/certificate/#creating-certificate-resources) |
+| certificate.ipAddresses | list | `[]` | Optional. [Documentation](https://cert-manager.io/docs/usage/certificate/#creating-certificate-resources) |
+| certificate.keystores | object | `{}` | Optional. [Documentation](https://cert-manager.io/docs/usage/certificate/#creating-certificate-resources) |
+| certificate.privateKey | object | `{}` | Optional. [Documentation](https://cert-manager.io/docs/usage/certificate/#creating-certificate-resources) |
+| certificate.secretTemplate | object | `{}` | Optional. [Documentation](https://cert-manager.io/docs/usage/certificate/#creating-certificate-resources) |
+| certificate.subject | object | `{}` | Optional. [Documentation](https://cert-manager.io/docs/usage/certificate/#creating-certificate-resources) |
+| certificate.uris | list | `[]` | Optional. [Documentation](https://cert-manager.io/docs/usage/certificate/#creating-certificate-resources) |
+| certificate.usages | list | `[]` | Optional. [Documentation](https://cert-manager.io/docs/usage/certificate/#creating-certificate-resources) |
| persistence.enabled | bool | `false` | Specifies whether an persistent volume should be created |
-| persistence.size | string | `"1Gi"` | Persistent Volume size |
+| persistence.annotations | object | `{}` | Persistent Volume Claim annotations |
| persistence.storageClass | string | `""` | Persistent Volume storage class. If undefined (the default) cluster's default provisioner will be used. |
-
-### RBAC
-
-| Key | Type | Default | Description |
-|-----|------|---------|-------------|
+| persistence.accessMode | string | `"ReadWriteOnce"` | Persistent Volume Access Mode |
+| persistence.size | string | `"1Gi"` | Persistent Volume size |
+| serviceAccount.create | bool | `true` | Specifies whether a service account should be created |
| serviceAccount.annotations | object | `{}` | Service account annotations |
| serviceAccount.automount | bool | `false` | Automatically mount a ServiceAccount's API credentials |
-| serviceAccount.create | bool | `true` | Specifies whether a service account should be created |
| serviceAccount.name | string | `""` | The name of the service account to use. If not set and create is true, a name is generated using the fullname template |
diff --git a/deploy/helm/templates/_helpers.tpl b/deploy/helm/templates/_helpers.tpl
index cfeb4cf..a8c9dde 100644
--- a/deploy/helm/templates/_helpers.tpl
+++ b/deploy/helm/templates/_helpers.tpl
@@ -98,3 +98,12 @@ resources:
requests:
storage: {{ .Values.persistence.size | quote }}
{{- end -}}
+
+{{/*
+Define hostname
+*/}}
+{{- define "wg-portal.hostname" -}}
+{{- if .Values.config.web.external_url -}}
+ {{- (urlParse (tpl .Values.config.web.external_url .)).hostname -}}
+{{- end -}}
+{{- end -}}
diff --git a/deploy/helm/templates/_pod.tpl b/deploy/helm/templates/_pod.tpl
index da52f3d..99bd6c2 100644
--- a/deploy/helm/templates/_pod.tpl
+++ b/deploy/helm/templates/_pod.tpl
@@ -7,7 +7,7 @@ metadata:
{{- tpl (toYaml .) $ | nindent 4 }}
{{- end }}
labels:
- {{- include "wg-portal.labels" . | nindent 4 }}
+ {{- include "wg-portal.selectorLabels" . | nindent 4 }}
{{- with .Values.podLabels }}
{{- toYaml . | nindent 4 }}
{{- end }}
@@ -36,7 +36,7 @@ spec:
envFrom: {{- tpl (toYaml .) $ | nindent 8 }}
{{- end }}
ports:
- - name: http
+ - name: web
containerPort: {{ .Values.service.web.port }}
protocol: TCP
{{- range $index, $port := .Values.service.wireguard.ports }}
@@ -65,6 +65,10 @@ spec:
readOnly: true
- name: data
mountPath: /app/data
+ {{- if and .Values.certificate.enabled (include "wg-portal.hostname" .) }}
+ - name: certs
+ mountPath: /app/certs
+ {{- end }}
{{- with .Values.volumeMounts }}
{{- tpl (toYaml .) $ | nindent 8 }}
{{- end }}
@@ -97,6 +101,11 @@ spec:
- name: config
secret:
secretName: {{ include "wg-portal.fullname" . }}
+ {{- if and .Values.certificate.enabled (include "wg-portal.hostname" .) }}
+ - name: certs
+ secret:
+ secretName: {{ include "wg-portal.fullname" . }}-tls
+ {{- end }}
{{- if not .Values.persistence.enabled }}
- name: data
emptyDir: {}
diff --git a/deploy/helm/templates/_service.tpl b/deploy/helm/templates/_service.tpl
new file mode 100644
index 0000000..72234be
--- /dev/null
+++ b/deploy/helm/templates/_service.tpl
@@ -0,0 +1,53 @@
+{{/*
+Define the service template
+{{- include "wg-portal.service" (dict "context" $ "scope" .Values.service. "ports" list "name" "") -}}
+*/}}
+{{- define "wg-portal.service.tpl" -}}
+apiVersion: v1
+kind: Service
+metadata:
+ {{- with .scope.annotations }}
+ annotations: {{- toYaml . | nindent 4 }}
+ {{- end }}
+ labels: {{- include "wg-portal.labels" .context | nindent 4 }}
+ name: {{ include "wg-portal.fullname" .context }}{{ ternary "" (printf "-%s" .name) (empty .name) }}
+spec:
+ {{- with .scope.clusterIP }}
+ clusterIP: {{ . }}
+ {{- end }}
+ {{- with .scope.externalIPs }}
+ externalIPs: {{ toYaml . | nindent 4 }}
+ {{- end }}
+ {{- with .scope.externalName }}
+ externalName: {{ . }}
+ {{- end }}
+ {{- with .scope.externalTrafficPolicy }}
+ externalTrafficPolicy: {{ . }}
+ {{- end }}
+ {{- with .scope.healthCheckNodePort }}
+ healthCheckNodePort: {{ . }}
+ {{- end }}
+ {{- with .scope.loadBalancerIP }}
+ loadBalancerIP: {{ . }}
+ {{- end }}
+ {{- with .scope.loadBalancerSourceRanges }}
+ loadBalancerSourceRanges: {{ toYaml . | nindent 4 }}
+ {{- end }}
+ ports: {{- toYaml .ports | nindent 4 }}
+ {{- with .scope.publishNotReadyAddresses }}
+ publishNotReadyAddresses: {{ . }}
+ {{- end }}
+ {{- with .scope.sessionAffinity }}
+ sessionAffinity: {{ . }}
+ {{- end }}
+ {{- with .scope.sessionAffinityConfig }}
+ sessionAffinityConfig: {{ toYaml . | nindent 4 }}
+ {{- end }}
+ {{- with .scope.topologyKeys }}
+ topologyKeys: {{ toYaml . | nindent 4 }}
+ {{- end }}
+ {{- with .scope.type }}
+ type: {{ . }}
+ {{- end }}
+ selector: {{- include "wg-portal.selectorLabels" .context | nindent 4 }}
+{{- end -}}
diff --git a/deploy/helm/templates/certificate.yaml b/deploy/helm/templates/certificate.yaml
new file mode 100644
index 0000000..03190f3
--- /dev/null
+++ b/deploy/helm/templates/certificate.yaml
@@ -0,0 +1,54 @@
+{{/* https://cert-manager.io/docs/usage/certificate/#creating-certificate-resources */}}
+{{- if and .Values.certificate.enabled (include "wg-portal.hostname" .) -}}
+apiVersion: cert-manager.io/v1
+kind: Certificate
+metadata:
+ name: {{ include "wg-portal.fullname" . }}
+ labels: {{- include "wg-portal.labels" . | nindent 4 }}
+spec:
+ secretName: {{ include "wg-portal.fullname" . }}-tls
+ {{- with .Values.certificate.secretTemplate }}
+ secretTemplate: {{ toYaml . | nindent 4 }}
+ {{- end }}
+ {{- with .Values.certificate.privateKey }}
+ privateKey: {{- toYaml . | nindent 4 }}
+ {{- end }}
+ {{- with .Values.certificate.keystores }}
+ keystores: {{- toYaml . | nindent 4 }}
+ {{- end }}
+ {{- with .Values.certificate.duration }}
+ duration: {{ . }}
+ {{- end }}
+ {{- with .Values.certificate.renewBefore }}
+ renewBefore: {{ . }}
+ {{- end }}
+ {{- with .Values.certificate.usages }}
+ usages: {{- toYaml . | nindent 4 }}
+ {{- end }}
+ {{- with .Values.certificate.subject }}
+ subject: {{- toYaml . | nindent 4 }}
+ {{- end }}
+ {{- with .Values.certificate.commonName }}
+ commonName: {{ . }}
+ {{- end }}
+ dnsNames:
+ - {{ include "wg-portal.hostname" . }}
+ {{- with .Values.certificate.uris }}
+ uris: {{- toYaml . | nindent 4 }}
+ {{- end }}
+ {{- with .Values.certificate.emailAddresses }}
+ emailAddresses: {{- toYaml . | nindent 4 }}
+ {{- end }}
+ {{- with .Values.certificate.ipAddresses }}
+ ipAddresses: {{- toYaml . | nindent 4 }}
+ {{- end }}
+ {{- with .Values.certificate.otherNames }}
+ otherNames: {{- toYaml . | nindent 4 }}
+ {{- end }}
+ issuerRef:
+ {{- with .Values.certificate.issuer.group }}
+ group: {{ . }}
+ {{- end }}
+ kind: {{ .Values.certificate.issuer.kind }}
+ name: {{ .Values.certificate.issuer.name }}
+{{- end -}}
diff --git a/deploy/helm/templates/ingress.yaml b/deploy/helm/templates/ingress.yaml
index 7413c78..be0370e 100644
--- a/deploy/helm/templates/ingress.yaml
+++ b/deploy/helm/templates/ingress.yaml
@@ -1,4 +1,5 @@
-{{- if .Values.ingress.enabled -}}
+{{- $hostname := include "wg-portal.hostname" . -}}
+{{- if and .Values.ingress.enabled $hostname -}}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
@@ -10,38 +11,20 @@ metadata:
spec:
ingressClassName: {{ .Values.ingress.className }}
rules:
- - host: {{ .Values.ingress.host }}
+ - host: {{ $hostname }}
http:
paths:
- - path: /
+ - path: {{ default "/" (urlParse (tpl .Values.config.web.external_url .)).path }}
pathType: {{ default "ImplementationSpecific" .pathType }}
backend:
service:
- name: {{ include "wg-portal.fullname" . }}-web
+ name: {{ include "wg-portal.fullname" . }}
port:
- name: http
- {{- range .Values.ingress.extraHosts }}
- - host: {{ .host | quote }}
- http:
- paths:
- {{- range .paths }}
- - path: {{ .path }}
- pathType: {{ default "ImplementationSpecific" .pathType }}
- backend:
- service:
- name: {{ include "wg-portal.fullname" . }}-web
- port:
- name: http
- {{- end }}
- {{- end }}
+ name: web
{{- if .Values.ingress.tls }}
tls:
- {{- range .Values.ingress.tls }}
- hosts:
- {{- range .hosts }}
- - {{ . | quote }}
- {{- end }}
- secretName: {{ .secretName }}
- {{- end }}
+ - {{ $hostname | quote }}
+ secretName: {{ include "wg-portal.fullname" . }}-tls
{{- end }}
{{- end }}
diff --git a/deploy/helm/templates/secret.yaml b/deploy/helm/templates/secret.yaml
index d8936f5..93d2719 100644
--- a/deploy/helm/templates/secret.yaml
+++ b/deploy/helm/templates/secret.yaml
@@ -32,10 +32,6 @@ stringData:
{{- end }}
web:
listening_address: :{{ .Values.service.web.port }}
- {{- if and .Values.ingress.enabled (not (hasKey .Values.config.web "external_url")) }}
- {{- $proto := ternary "http" "https" (empty .Values.ingress.tls) }}
- external_url: {{ trimSuffix "/" (printf "%s://%s%s" $proto .Values.ingress.host .Values.ingress.path) }}
- {{- end }}
{{- with .Values.config.web }}
{{- tpl (toYaml (omit . "listening_address")) $ | nindent 6 }}
{{- end }}
diff --git a/deploy/helm/templates/service-web.yaml b/deploy/helm/templates/service-web.yaml
deleted file mode 100644
index 531ba70..0000000
--- a/deploy/helm/templates/service-web.yaml
+++ /dev/null
@@ -1,16 +0,0 @@
-apiVersion: v1
-kind: Service
-metadata:
- {{- with .Values.service.web.annotations }}
- annotations: {{- toYaml . | nindent 4 }}
- {{- end }}
- name: {{ include "wg-portal.fullname" . }}-web
- labels: {{- include "wg-portal.labels" . | nindent 4 }}
-spec:
- ports:
- - port: {{ .Values.service.web.port }}
- targetPort: http
- protocol: TCP
- name: http
- selector: {{- include "wg-portal.selectorLabels" . | nindent 4 }}
- type: {{ .Values.service.web.type }}
diff --git a/deploy/helm/templates/service-wireguard.yaml b/deploy/helm/templates/service-wireguard.yaml
deleted file mode 100644
index 3a01cf9..0000000
--- a/deploy/helm/templates/service-wireguard.yaml
+++ /dev/null
@@ -1,27 +0,0 @@
-apiVersion: v1
-kind: Service
-metadata:
- {{- with .Values.service.wireguard.annotations }}
- annotations: {{- toYaml . | nindent 4 }}
- {{- end }}
- name: {{ include "wg-portal.fullname" . }}-wireguard
- labels: {{- include "wg-portal.labels" . | nindent 4 }}
-spec:
- {{- with .Values.service.wireguard.externalTrafficPolicy }}
- externalTrafficPolicy: {{ . }}
- {{- end }}
- {{- with .Values.service.wireguard.loadBalancerSourceRanges }}
- loadBalancerSourceRanges: {{- toYaml . | nindent 4 }}
- {{- end }}
- ports:
- {{- range $index, $port := .Values.service.wireguard.ports }}
- - port: {{ $port }}
- targetPort: wg{{ $index }}
- protocol: UDP
- name: wg{{ $index }}
- {{- end }}
- selector: {{- include "wg-portal.selectorLabels" . | nindent 4 }}
- {{- with .Values.service.wireguard.sessionAffinity }}
- sessionAffinity: {{ . }}
- {{- end }}
- type: {{ .Values.service.wireguard.type }}
diff --git a/deploy/helm/templates/service.yaml b/deploy/helm/templates/service.yaml
new file mode 100644
index 0000000..1b38d3f
--- /dev/null
+++ b/deploy/helm/templates/service.yaml
@@ -0,0 +1,14 @@
+{{- $portsWeb := list (dict "name" "web" "port" .Values.service.web.port "protocol" "TCP" "targetPort" "web") -}}
+{{- $ports := list -}}
+{{- range $idx, $port := .Values.service.wireguard.ports -}}
+{{- $name := printf "wg%d" $idx -}}
+{{- $ports = append $ports (dict "name" $name "port" $port "protocol" "UDP" "targetPort" $name) -}}
+{{- end -}}
+
+{{- if .Values.service.mixed.enabled -}}
+{{ include "wg-portal.service.tpl" (dict "context" . "scope" .Values.service.mixed "ports" (concat $portsWeb $ports)) }}
+{{- else }}
+{{ include "wg-portal.service.tpl" (dict "context" . "scope" .Values.service.web "ports" $portsWeb) }}
+---
+{{ include "wg-portal.service.tpl" (dict "context" . "scope" .Values.service.wireguard "ports" $ports "name" "wireguard") }}
+{{- end -}}
diff --git a/deploy/helm/values.yaml b/deploy/helm/values.yaml
index 142c990..c1d4b90 100644
--- a/deploy/helm/values.yaml
+++ b/deploy/helm/values.yaml
@@ -3,267 +3,202 @@
# Declare variables to be passed into your templates.
# -- Partially override resource names (adds suffix)
-# @section -- Common
nameOverride: ''
# -- Fully override resource names
-# @section -- Common
fullnameOverride: ''
# -- Array of extra objects to deploy with the release
-# @section -- Common
extraDeploy: []
# https://github.com/h44z/wg-portal/blob/master/README.md#configuration-options
config:
# -- (tpl/object) Advanced configuration options.
- # @section -- Configuration
advanced: {}
# -- (tpl/object) Auth configuration options.
- # @section -- Configuration
auth: {}
# -- (tpl/object) Core configuration options.
- # @section -- Configuration
# If external admins in `auth` are not defined and
# there are no `admin_user` and `admin_password` defined here,
# the default credentials will be generated.
core: {}
# -- (tpl/object) Database configuration options
- # @section -- Configuration
database: {}
# -- (tpl/object) Mail configuration options
- # @section -- Configuration
mail: {}
# -- (tpl/object) Statistics configuration options
- # @section -- Configuration
statistics: {}
# -- (tpl/object) Web configuration options.
- # @section -- Configuration
- # The chart will set `listening_address` automatically from `service.web.port`,
- # and `external_url` from `ingress.host` if enabled.
+ # `listening_address` will be set automatically from `service.web.port`.
+ # `external_url` is required to enable ingress and certificate resources.
web: {}
# -- The number of old ReplicaSets to retain to allow rollback.
-# @section -- Parameters
# @default -- `10`
revisionHistoryLimit: ''
# -- Workload type - `Deployment` or `StatefulSet`
-# @section -- Parameters
workloadType: Deployment
# -- Update strategy for the workload
# Valid values are:
# `RollingUpdate` or `Recreate` for Deployment,
# `RollingUpdate` or `OnDelete` for StatefulSet
-# @section -- Parameters
strategy:
type: RollingUpdate
image:
# -- Image repository
- # @section -- Parameters
repository: ghcr.io/h44z/wg-portal
# -- Image pull policy
- # @section -- Parameters
pullPolicy: IfNotPresent
# -- Overrides the image tag whose default is the chart appVersion
- # @section -- Parameters
tag: ''
# -- Image pull secrets
-# @section -- Parameters
imagePullSecrets: []
-
# -- (tpl/object) Extra annotations to add to the pod
-# @section -- Parameters
podAnnotations: {}
-
# -- Extra labels to add to the pod
-# @section -- Parameters
podLabels: {}
-
# -- Pod Security Context
-# @section -- Parameters
podSecurityContext: {}
-
# Container Security Context
securityContext:
capabilities:
# -- Add capabilities to the container
- # @section -- Parameters
add:
- NET_ADMIN
# -- (tpl/list) Pod init containers
-# @section -- Parameters
initContainers: []
# -- (tpl/list) Pod sidecar containers
-# @section -- Parameters
sidecarContainers: []
-
# -- Set DNS policy for the pod.
# Valid values are `ClusterFirstWithHostNet`, `ClusterFirst`, `Default` or `None`.
# @default -- `"ClusterFirst"`
-# @section -- Parameters
dnsPolicy: ''
-
# -- Restart policy for all containers within the pod.
# Valid values are `Always`, `OnFailure` or `Never`.
# @default -- `"Always"`
-# @section -- Parameters
restartPolicy: ''
-
# -- Use the host's network namespace.
# @default -- `false`.
-# @section -- Parameters
hostNetwork: ''
-
# -- Resources requests and limits
-# @section -- Parameters
resources: {}
-
# -- Overwrite pod command
-# @section -- Parameters
command: []
-
# -- Additional pod arguments
-# @section -- Parameters
args: []
-
# -- (tpl/list) Additional environment variables
-# @section -- Parameters
env: []
-
# -- (tpl/list) Additional environment variables from a secret or configMap
-# @section -- Parameters
envFrom: []
-
# -- Liveness probe configuration
-# @ignore
-livenessProbe:
- failureThreshold: 10
- httpGet:
- path: /
- port: http
-
+livenessProbe: {}
# -- Readiness probe configuration
-# @ignore
-readinessProbe:
- httpGet:
- path: /
- port: http
-
+readinessProbe: {}
# -- Startup probe configuration
-# @ignore
-startupProbe:
- initialDelaySeconds: 5
- failureThreshold: 10
- httpGet:
- path: /
- port: http
- scheme: HTTP
-
+startupProbe: {}
# -- (tpl/list) Additional volumes
-# @section -- Parameters
volumes: []
-
# -- (tpl/list) Additional volumeMounts
-# @section -- Parameters
volumeMounts: []
-
# -- Node Selector configuration
-# @section -- Parameters
nodeSelector:
kubernetes.io/os: linux
-
# -- Tolerations configuration
-# @section -- Parameters
tolerations: []
-
# -- Affinity configuration
-# @section -- Parameters
affinity: {}
service:
+ mixed:
+ # -- Whether to create a single service for the web and wireguard interfaces
+ enabled: false
+ # -- Service type
+ type: LoadBalancer
web:
# -- Annotations for the web service
- # @section -- Traffic exposure
annotations: {}
# -- Web service type
- # @section -- Traffic exposure
type: ClusterIP
# -- Web service port
# Used for the web interface listener
- # @section -- Traffic exposure
port: 8888
wireguard:
# -- Annotations for the WireGuard service
- # @section -- Traffic exposure
annotations: {}
# -- Wireguard service type
- # @section -- Traffic exposure
type: LoadBalancer
# -- Wireguard service ports.
# Exposes the WireGuard ports for created interfaces.
# Lowerest port is selected as start port for the first interface.
# Increment next port by 1 for each additional interface.
- # @section -- Traffic exposure
ports:
- 51820
ingress:
# -- Specifies whether an ingress resource should be created
- # @section -- Traffic exposure
enabled: false
# -- Ingress class name
- # @section -- Traffic exposure
className: ''
# -- Ingress annotations
- # @section -- Traffic exposure
- # @section -- Traffic exposure
annotations: {}
- # -- Ingress host FQDN
- # @section -- Traffic exposure
- host: ''
- # -- Ingress path type
- # @section -- Traffic exposure
- pathType: ImplementationSpecific
- # -- Ingress path
- # @section -- Traffic exposure
- path: /
- # -- Ingress TLS configuration
- # @section -- Traffic exposure
- tls: []
- # - secretName: wg-portal-example-tls
- # hosts:
- # - wg-portal.example.local
+ # -- Ingress TLS configuration.
+ # Enable certificate resource or add ingress annotation to create required secret
+ tls: false
+
+certificate:
+ # -- Specifies whether a certificate resource should be created
+ enabled: false
+ issuer:
+ # -- Certificate issuer name
+ name: ''
+ # -- Certificate issuer kind (ClusterIssuer or Issuer)
+ kind: ''
+ # -- Certificate issuer group
+ group: cert-manager.io
+ # -- Optional. [Documentation](https://cert-manager.io/docs/usage/certificate/#creating-certificate-resources)
+ duration: ''
+ # -- Optional. [Documentation](https://cert-manager.io/docs/usage/certificate/#creating-certificate-resources)
+ renewBefore: ''
+ # -- Optional. [Documentation](https://cert-manager.io/docs/usage/certificate/#creating-certificate-resources)
+ commonName: ''
+ # -- Optional. [Documentation](https://cert-manager.io/docs/usage/certificate/#creating-certificate-resources)
+ emailAddresses: []
+ # -- Optional. [Documentation](https://cert-manager.io/docs/usage/certificate/#creating-certificate-resources)
+ ipAddresses: []
+ # -- Optional. [Documentation](https://cert-manager.io/docs/usage/certificate/#creating-certificate-resources)
+ keystores: {}
+ # -- Optional. [Documentation](https://cert-manager.io/docs/usage/certificate/#creating-certificate-resources)
+ privateKey: {}
+ # -- Optional. [Documentation](https://cert-manager.io/docs/usage/certificate/#creating-certificate-resources)
+ secretTemplate: {}
+ # -- Optional. [Documentation](https://cert-manager.io/docs/usage/certificate/#creating-certificate-resources)
+ subject: {}
+ # -- Optional. [Documentation](https://cert-manager.io/docs/usage/certificate/#creating-certificate-resources)
+ uris: []
+ # -- Optional. [Documentation](https://cert-manager.io/docs/usage/certificate/#creating-certificate-resources)
+ usages: []
persistence:
# -- Specifies whether an persistent volume should be created
- # @section -- Persistence
enabled: false
# -- Persistent Volume Claim annotations
- # @section -- Persistence
annotations: {}
# -- Persistent Volume storage class.
# If undefined (the default) cluster's default provisioner will be used.
- # @section -- Persistence
storageClass: ''
# -- Persistent Volume Access Mode
- # @section -- Persistence
accessMode: ReadWriteOnce
# -- Persistent Volume size
- # @section -- Persistence
size: 1Gi
serviceAccount:
# -- Specifies whether a service account should be created
- # @section -- RBAC
create: true
# -- Service account annotations
- # @section -- RBAC
annotations: {}
# -- Automatically mount a ServiceAccount's API credentials
- # @section -- RBAC
automount: false
# -- The name of the service account to use.
# If not set and create is true, a name is generated using the fullname template
- # @section -- RBAC
name: ''
diff --git a/internal/app/api/core/server.go b/internal/app/api/core/server.go
index b9aa3e8..2c1f378 100644
--- a/internal/app/api/core/server.go
+++ b/internal/app/api/core/server.go
@@ -68,8 +68,7 @@ func NewServer(cfg *config.Config, endpoints ...ApiEndpointSetupFunc) (*Server,
c.Writer.Header().Set("X-Served-By", hostname)
c.Next()
}).Use(func(c *gin.Context) {
- var xRequestID string
- xRequestID = uuid(16)
+ xRequestID := uuid(16)
c.Request.Header.Set(RequestIDKey, xRequestID)
c.Set(RequestIDKey, xRequestID)
@@ -106,7 +105,13 @@ func (s *Server) Run(ctx context.Context, listenAddress string) {
srvContext, cancelFn := context.WithCancel(ctx)
go func() {
- if err := srv.ListenAndServe(); err != nil {
+ var err error
+ if s.cfg.Web.CertFile != "" && s.cfg.Web.KeyFile != "" {
+ err = srv.ListenAndServeTLS(s.cfg.Web.CertFile, s.cfg.Web.KeyFile)
+ } else {
+ err = srv.ListenAndServe()
+ }
+ if err != nil {
logrus.Infof("web service on %s exited: %v", listenAddress, err)
cancelFn()
}
diff --git a/internal/config/web.go b/internal/config/web.go
index 5a8ed85..9a7508f 100644
--- a/internal/config/web.go
+++ b/internal/config/web.go
@@ -9,4 +9,6 @@ type WebConfig struct {
CsrfSecret string `yaml:"csrf_secret"`
SiteTitle string `yaml:"site_title"`
SiteCompanyName string `yaml:"site_company_name"`
+ CertFile string `yaml:"cert_file"`
+ KeyFile string `yaml:"key_file"`
}