diff --git a/deploy/helm/README.md b/deploy/helm/README.md
index 658b90e..12c9cf5 100644
--- a/deploy/helm/README.md
+++ b/deploy/helm/README.md
@@ -27,97 +27,97 @@ The [Values](#values) section lists the parameters that can be configured during
## Values
-| 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](https://wgportal.org/latest/documentation/configuration/overview/#advanced) options. |
-| config.auth | tpl/object | `{}` | [Auth configuration](https://wgportal.org/latest/documentation/configuration/overview/#auth) options. |
-| config.core | tpl/object | `{}` | [Core configuration](https://wgportal.org/latest/documentation/configuration/overview/#core) options.
If external admins in `auth` are defined and there are no `admin_user` and `admin_password` defined here, the default admin account will be disabled. |
-| config.database | tpl/object | `{}` | [Database configuration](https://wgportal.org/latest/documentation/configuration/overview/#database) options |
-| config.mail | tpl/object | `{}` | [Mail configuration](https://wgportal.org/latest/documentation/configuration/overview/#mail) options |
-| config.statistics | tpl/object | `{}` | [Statistics configuration](https://wgportal.org/latest/documentation/configuration/overview/#statistics) options |
-| config.web | tpl/object | `{}` | [Web configuration](https://wgportal.org/latest/documentation/configuration/overview/#web) 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.type | string | `"ClusterIP"` | Web service type |
-| service.web.port | int | `8888` | Web service port Used for the web interface listener |
-| service.web.appProtocol | string | `"http"` | Web service appProtocol. Will be auto set to `https` if certificate is enabled. |
-| service.wireguard.annotations | object | `{}` | Annotations for the WireGuard service |
-| service.wireguard.type | string | `"LoadBalancer"` | Wireguard service type |
-| 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.metrics.port | int | `8787` | |
-| 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. If enabled, certificate will be used for the web. |
-| 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.annotations | object | `{}` | Persistent Volume Claim annotations |
-| persistence.storageClass | string | `""` | Persistent Volume storage class. If undefined (the default) cluster's default provisioner will be used. |
-| 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.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 |
-| monitoring.enabled | bool | `false` | Enable Prometheus monitoring. |
-| monitoring.apiVersion | string | `"monitoring.coreos.com/v1"` | API version of the Prometheus resource. Use `azmonitoring.coreos.com/v1` for Azure Managed Prometheus. |
-| monitoring.kind | string | `"PodMonitor"` | Kind of the Prometheus resource. Could be `PodMonitor` or `ServiceMonitor`. |
-| monitoring.labels | object | `{}` | Resource labels. |
-| monitoring.annotations | object | `{}` | Resource annotations. |
-| monitoring.interval | string | `1m` | Interval at which metrics should be scraped. If not specified `config.statistics.data_collection_interval` interval is used. |
-| monitoring.metricRelabelings | list | `[]` | Relabelings to samples before ingestion. |
-| monitoring.relabelings | list | `[]` | Relabelings to samples before scraping. |
-| monitoring.scrapeTimeout | string | `""` | Timeout after which the scrape is ended If not specified, the Prometheus global scrape interval is used. |
-| monitoring.jobLabel | string | `""` | The label to use to retrieve the job name from. |
-| monitoring.podTargetLabels | object | `{}` | Transfers labels on the Kubernetes Pod onto the target. |
-| monitoring.dashboard.enabled | bool | `false` | Enable Grafana dashboard. |
-| monitoring.dashboard.annotations | object | `{}` | Annotations for the dashboard ConfigMap. |
-| monitoring.dashboard.labels | object | `{}` | Additional labels for the dashboard ConfigMap. |
-| monitoring.dashboard.namespace | string | `""` | Dashboard ConfigMap namespace Overrides the namespace for the dashboard ConfigMap. |
+| 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](https://wgportal.org/latest/documentation/configuration/overview/#advanced) options. |
+| config.auth | tpl/object | `{}` | [Auth configuration](https://wgportal.org/latest/documentation/configuration/overview/#auth) options. |
+| config.core | tpl/object | `{}` | [Core configuration](https://wgportal.org/latest/documentation/configuration/overview/#core) options.
If external admins in `auth` are defined and there are no `admin_user` and `admin_password` defined here, the default admin account will be disabled. |
+| config.database | tpl/object | `{}` | [Database configuration](https://wgportal.org/latest/documentation/configuration/overview/#database) options |
+| config.mail | tpl/object | `{}` | [Mail configuration](https://wgportal.org/latest/documentation/configuration/overview/#mail) options |
+| config.statistics | tpl/object | `{}` | [Statistics configuration](https://wgportal.org/latest/documentation/configuration/overview/#statistics) options |
+| config.web | tpl/object | `{}` | [Web configuration](https://wgportal.org/latest/documentation/configuration/overview/#web) 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.type | string | `"ClusterIP"` | Web service type |
+| service.web.port | int | `8888` | Web service port Used for the web interface listener |
+| service.web.appProtocol | string | `"http"` | Web service appProtocol. Will be auto set to `https` if certificate is enabled. |
+| service.wireguard.annotations | object | `{}` | Annotations for the WireGuard service |
+| service.wireguard.type | string | `"LoadBalancer"` | Wireguard service type |
+| 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.metrics.port | int | `8787` | |
+| 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. If enabled, certificate will be used for the web. |
+| 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.annotations | object | `{}` | Persistent Volume Claim annotations |
+| persistence.storageClass | string | `""` | Persistent Volume storage class. If undefined (the default) cluster's default provisioner will be used. |
+| 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.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 |
+| monitoring.enabled | bool | `false` | Enable Prometheus monitoring. |
+| monitoring.apiVersion | string | `"monitoring.coreos.com/v1"` | API version of the Prometheus resource. Use `azmonitoring.coreos.com/v1` for Azure Managed Prometheus. |
+| monitoring.kind | string | `"PodMonitor"` | Kind of the Prometheus resource. Could be `PodMonitor` or `ServiceMonitor`. |
+| monitoring.labels | object | `{}` | Resource labels. |
+| monitoring.annotations | object | `{}` | Resource annotations. |
+| monitoring.interval | string | `1m` | Interval at which metrics should be scraped. If not specified `config.statistics.data_collection_interval` interval is used. |
+| monitoring.metricRelabelings | list | `[]` | Relabelings to samples before ingestion. |
+| monitoring.relabelings | list | `[]` | Relabelings to samples before scraping. |
+| monitoring.scrapeTimeout | string | `""` | Timeout after which the scrape is ended If not specified, the Prometheus global scrape interval is used. |
+| monitoring.jobLabel | string | `""` | The label to use to retrieve the job name from. |
+| monitoring.podTargetLabels | object | `{}` | Transfers labels on the Kubernetes Pod onto the target. |
+| monitoring.dashboard.enabled | bool | `false` | Enable Grafana dashboard. |
+| monitoring.dashboard.annotations | object | `{}` | Annotations for the dashboard ConfigMap. |
+| monitoring.dashboard.labels | object | `{}` | Additional labels for the dashboard ConfigMap. |
+| monitoring.dashboard.namespace | string | `""` | Dashboard ConfigMap namespace Overrides the namespace for the dashboard ConfigMap. |
diff --git a/docs/documentation/configuration/examples.md b/docs/documentation/configuration/examples.md
index 31671ab..bf008ad 100644
--- a/docs/documentation/configuration/examples.md
+++ b/docs/documentation/configuration/examples.md
@@ -6,6 +6,7 @@ Below are some sample YAML configurations demonstrating how to override some def
core:
admin_user: test@example.com
admin_password: password
+ admin_api_token: super-s3cr3t-api-token-or-a-UUID
import_existing: false
create_default_peer: true
self_provisioning_allowed: true
diff --git a/docs/documentation/configuration/overview.md b/docs/documentation/configuration/overview.md
index 8ba9b64..a890f33 100644
--- a/docs/documentation/configuration/overview.md
+++ b/docs/documentation/configuration/overview.md
@@ -111,6 +111,10 @@ More advanced options are found in the subsequent `Advanced` section.
- **Default:** `wgportal`
- **Description:** The administrator password. The default password of `wgportal` should be changed immediately.
+### `admin_api_token`
+- **Default:** *(empty)*
+- **Description:** An API token for the admin user. If a token is provided, the REST API can be accessed using this token. If empty, the API is initially disabled for the admin user.
+
### `editable_keys`
- **Default:** `true`
- **Description:** Allow editing of WireGuard key-pairs directly in the UI.
diff --git a/internal/app/app.go b/internal/app/app.go
index 84e6ff2..11f41ab 100644
--- a/internal/app/app.go
+++ b/internal/app/app.go
@@ -127,7 +127,7 @@ func (a *App) createDefaultUser(ctx context.Context) error {
}
now := time.Now()
- admin, err := a.CreateUser(ctx, &domain.User{
+ defaultAdmin := &domain.User{
BaseModel: domain.BaseModel{
CreatedBy: domain.CtxSystemAdminId,
UpdatedBy: domain.CtxSystemAdminId,
@@ -150,7 +150,16 @@ func (a *App) createDefaultUser(ctx context.Context) error {
Locked: nil,
LockedReason: "",
LinkedPeerCount: 0,
- })
+ }
+ if a.Config.Core.AdminApiToken != "" {
+ if len(a.Config.Core.AdminApiToken) < 18 {
+ logrus.Warnf("[SECURITY WARNING] admin API token is too short, should be at least 18 characters long")
+ }
+ defaultAdmin.ApiToken = a.Config.Core.AdminApiToken
+ defaultAdmin.ApiTokenCreated = &now
+ }
+
+ admin, err := a.CreateUser(ctx, defaultAdmin)
if err != nil {
return err
}
diff --git a/internal/config/config.go b/internal/config/config.go
index c2bd83b..bf2f837 100644
--- a/internal/config/config.go
+++ b/internal/config/config.go
@@ -16,6 +16,7 @@ type Config struct {
// AdminUser defines the default administrator account that will be created
AdminUser string `yaml:"admin_user"`
AdminPassword string `yaml:"admin_password"`
+ AdminApiToken string `yaml:"admin_api_token"` // if set, the API access is enabled automatically
EditableKeys bool `yaml:"editable_keys"`
CreateDefaultPeer bool `yaml:"create_default_peer"`
@@ -94,6 +95,7 @@ func defaultConfig() *Config {
cfg.Core.AdminUser = "admin@wgportal.local"
cfg.Core.AdminPassword = "wgportal"
+ cfg.Core.AdminApiToken = "" // by default, the API access is disabled
cfg.Core.ImportExisting = true
cfg.Core.RestoreState = true
cfg.Core.CreateDefaultPeer = false