installer: create headscale user resource
diff --git a/core/headscale/main.go b/core/headscale/main.go
index b9dbc22..1ca4f6b 100644
--- a/core/headscale/main.go
+++ b/core/headscale/main.go
@@ -20,19 +20,16 @@
// TODO(gio): ingress-private user name must be configurable
const defaultACLs = `
{
- "hosts": {
- "private-network": "10.1.0.0/24",
- },
"autoApprovers": {
"routes": {
- "private-network": ["private-network-proxy@{{ .Domain }}"],
+ "10.1.0.0/24": ["private-network-proxy@{{ .Domain }}"],
},
},
"acls": [
{ // Everyone can access ingress-private service
"action": "accept",
"src": ["*"],
- "dst": ["private-network:*"],
+ "dst": ["10.1.0.0/24:*"],
},
],
}
diff --git a/core/installer/app.go b/core/installer/app.go
index 3210667..4935169 100644
--- a/core/installer/app.go
+++ b/core/installer/app.go
@@ -102,6 +102,7 @@
CreateCertificateIssuerPrivate(valuesTmpls, tmpls),
CreateAppCoreAuth(valuesTmpls, tmpls),
CreateAppHeadscale(valuesTmpls, tmpls),
+ CreateAppHeadscaleUser(valuesTmpls, tmpls),
CreateAppTailscaleProxy(valuesTmpls, tmpls),
CreateMetallbIPAddressPool(valuesTmpls, tmpls),
CreateEnvManager(valuesTmpls, tmpls),
@@ -383,6 +384,22 @@
}
}
+func CreateAppHeadscaleUser(fs embed.FS, tmpls *template.Template) App {
+ schema, err := fs.ReadFile("values-tmpl/headscale-user.jsonschema")
+ if err != nil {
+ panic(err)
+ }
+ return App{
+ "headscale-user",
+ []string{"app-headscale"},
+ []*template.Template{
+ tmpls.Lookup("headscale-user.yaml"),
+ },
+ string(schema),
+ tmpls.Lookup("headscale-user.md"),
+ }
+}
+
func CreateAppTailscaleProxy(fs embed.FS, tmpls *template.Template) App {
schema, err := fs.ReadFile("values-tmpl/tailscale-proxy.jsonschema")
if err != nil {
diff --git a/core/installer/values-tmpl/headscale-user.jsonschema b/core/installer/values-tmpl/headscale-user.jsonschema
new file mode 100644
index 0000000..e4884a6
--- /dev/null
+++ b/core/installer/values-tmpl/headscale-user.jsonschema
@@ -0,0 +1,14 @@
+{
+ "type": "object",
+ "properties": {
+ "Username": { "type": "string" },
+ "PreAuthKey": {
+ "type": "object",
+ "properties": {
+ "Enabled": { "type": "boolean" }
+ },
+ "additionalProperties": false
+ }
+ },
+ "additionalProperties": false
+}
diff --git a/core/installer/values-tmpl/headscale-user.md b/core/installer/values-tmpl/headscale-user.md
new file mode 100644
index 0000000..7246082
--- /dev/null
+++ b/core/installer/values-tmpl/headscale-user.md
@@ -0,0 +1 @@
+Creates Headscale user resource
diff --git a/core/installer/values-tmpl/headscale-user.yaml b/core/installer/values-tmpl/headscale-user.yaml
new file mode 100644
index 0000000..0eca8d0
--- /dev/null
+++ b/core/installer/values-tmpl/headscale-user.yaml
@@ -0,0 +1,20 @@
+apiVersion: helm.toolkit.fluxcd.io/v2beta1
+kind: HelmRelease
+metadata:
+ name: user-{{ .Values.Username }}
+ namespace: {{ .Release.Namespace }}
+spec:
+ chart:
+ spec:
+ chart: charts/headscale-user
+ sourceRef:
+ kind: GitRepository
+ name: pcloud
+ namespace: {{ .Global.Id }}
+ interval: 1m0s
+ values:
+ username: {{ .Values.Username }}
+ headscaleApiAddress: http://headscale-api.{{ .Global.Id }}-app-headscale.svc.cluster.local
+ preAuthKey:
+ enabled: {{ .Values.PreAuthKey.Enabled }}
+ secretName: {{ .Values.Username }}-headscale-preauthkey
diff --git a/core/installer/values-tmpl/tailscale-proxy.yaml b/core/installer/values-tmpl/tailscale-proxy.yaml
index 1774f1e..904f850 100644
--- a/core/installer/values-tmpl/tailscale-proxy.yaml
+++ b/core/installer/values-tmpl/tailscale-proxy.yaml
@@ -16,7 +16,7 @@
namespace: {{ .Global.Id }}
interval: 1m0s
values:
- hostname: {{ .Global.Id }}-{{ .Values.HostnameSuffix }}
+ hostname: {{ .Values.Hostname}}
apiServer: http://headscale-api.{{ .Global.Id }}-app-headscale.svc.cluster.local
loginServer: https://headscale.{{ .Global.Domain }} # TODO(gio): take headscale subdomain from configuration
ipSubnet: {{ .Values.IPSubnet }}
diff --git a/core/installer/welcome/create-admin-account.html b/core/installer/welcome/create-admin-account.html
index 5f6efd2..2b22074 100644
--- a/core/installer/welcome/create-admin-account.html
+++ b/core/installer/welcome/create-admin-account.html
@@ -36,7 +36,7 @@
aria-label="Secret Token"
required
/>
- <button type="submit" class="contrast">Create Account</button>
+ <button type="submit">Create Account</button>
</form>
</main>
</body>
diff --git a/core/installer/welcome/env.go b/core/installer/welcome/env.go
index 4e74181..3d3e332 100644
--- a/core/installer/welcome/env.go
+++ b/core/installer/welcome/env.go
@@ -556,9 +556,9 @@
return err
}
if err := appManager.Install(*app, nsGen, emptySuffixGen, map[string]any{
- "Username": "private-network-proxy",
- "IPSubnet": "10.1.0.0/24",
- "HostnameSuffix": "private-network-proxy",
+ "Hostname": "private-network-proxy",
+ "Username": "private-network-proxy",
+ "IPSubnet": "10.1.0.0/24",
}); err != nil {
return err
}
diff --git a/core/installer/welcome/welcome.go b/core/installer/welcome/welcome.go
index 2517a6f..e13ec3a 100644
--- a/core/installer/welcome/welcome.go
+++ b/core/installer/welcome/welcome.go
@@ -93,7 +93,11 @@
}
func (s *Server) createAdminAccount(w http.ResponseWriter, r *http.Request) {
- var req createAccountReq
+ req, err := extractReq(r)
+ if err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
// TODO(giolekva): accounts-ui create user req
{
config, err := s.repo.ReadConfig()
@@ -127,19 +131,20 @@
}
}
{
- app, err := appsRepo.Find("tailscale-proxy")
+ app, err := appsRepo.Find("headscale-user")
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
if err := appManager.Install(*app, nsGen, suffixGen, map[string]any{
"Username": req.Username,
- "IPSubnet": "10.1.0.0/24", // TODO(giolekva): this should be taken from the config generated during new env creation
+ "PreAuthKey": map[string]any{
+ "Enabled": false,
+ },
}); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
- // TODO(giolekva): headscale accept routes
}
}
if _, err := w.Write([]byte("OK")); err != nil {