@highstate/library 0.20.0 → 0.25.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/dist/highstate.library.msgpack +0 -0
  2. package/dist/index.js +4260 -3948
  3. package/package.json +12 -12
  4. package/src/abbreviations.ts +2 -0
  5. package/src/apps/index.ts +1 -0
  6. package/src/apps/vault.ts +374 -0
  7. package/src/common/access-point.ts +150 -4
  8. package/src/common/filter.ts +40 -0
  9. package/src/common/index.ts +1 -0
  10. package/src/common/server.ts +131 -1
  11. package/src/databases/etcd.ts +12 -4
  12. package/src/databases/index.ts +1 -0
  13. package/src/databases/minio.ts +19 -0
  14. package/src/databases/mongodb.ts +12 -4
  15. package/src/databases/mysql.ts +12 -4
  16. package/src/databases/postgresql.ts +12 -4
  17. package/src/databases/rustfs.ts +169 -0
  18. package/src/dns.ts +3 -3
  19. package/src/index.ts +3 -0
  20. package/src/k3s.ts +129 -3
  21. package/src/k8s/apps/envoy-gateway.ts +50 -0
  22. package/src/k8s/apps/etcd.ts +1 -1
  23. package/src/k8s/apps/grafana.ts +1 -1
  24. package/src/k8s/apps/index.ts +4 -0
  25. package/src/k8s/apps/mariadb.ts +1 -1
  26. package/src/k8s/apps/matrix-stack.ts +2 -1
  27. package/src/k8s/apps/minio.ts +2 -2
  28. package/src/k8s/apps/mongodb.ts +1 -1
  29. package/src/k8s/apps/postgresql.ts +1 -1
  30. package/src/k8s/apps/rustfs.ts +119 -0
  31. package/src/k8s/apps/shared.ts +16 -1
  32. package/src/k8s/apps/signoz.ts +32 -0
  33. package/src/k8s/apps/traefik.ts +5 -5
  34. package/src/k8s/apps/valkey.ts +1 -1
  35. package/src/k8s/apps/vault.ts +113 -0
  36. package/src/k8s/apps/vaultwarden.ts +31 -2
  37. package/src/k8s/apps/workload.ts +12 -14
  38. package/src/k8s/cert-manager.ts +44 -2
  39. package/src/k8s/cilium.ts +3 -16
  40. package/src/k8s/coredns.ts +62 -0
  41. package/src/k8s/gateway.ts +25 -0
  42. package/src/k8s/index.ts +1 -0
  43. package/src/k8s/scheduling.ts +87 -0
  44. package/src/k8s/service-args.ts +109 -0
  45. package/src/k8s/shared.ts +26 -0
  46. package/src/k8s/workload.ts +21 -0
  47. package/src/netaminity.ts +950 -0
  48. package/src/network/address-space.ts +14 -0
  49. package/src/network/endpoint.ts +12 -1
  50. package/src/network/index.ts +1 -0
  51. package/src/network/network.ts +58 -0
  52. package/src/restic.ts +2 -1
  53. package/src/ssh.ts +27 -0
  54. package/src/third-party/gcp.ts +427 -0
  55. package/src/third-party/index.ts +1 -0
  56. package/src/third-party/yandex.ts +194 -1
  57. package/src/tls.ts +135 -6
  58. package/src/utils.ts +16 -1
  59. package/src/wireguard.ts +273 -4
  60. package/LICENSE +0 -21
  61. package/dist/index.js.map +0 -1
package/src/k3s.ts CHANGED
@@ -1,5 +1,7 @@
1
- import { defineUnit, z } from "@highstate/contract"
1
+ import { defineEntity, defineUnit, type EntityValue, secretSchema, z } from "@highstate/contract"
2
+ import { serverEntity } from "./common"
2
3
  import { clusterInputs, clusterOutputs } from "./k8s/shared"
4
+ import { l4EndpointEntity } from "./network"
3
5
 
4
6
  export const packagedComponents = [
5
7
  "coredns",
@@ -22,6 +24,48 @@ export const componentSchema = z.enum([...packagedComponents, ...internalCompone
22
24
 
23
25
  export const cniSchema = z.enum(["none", "flannel"])
24
26
 
27
+ export const clusterEntity = defineEntity({
28
+ type: "k3s.cluster.v1",
29
+
30
+ includes: {
31
+ /**
32
+ * The API endpoint workers should use to join the cluster.
33
+ *
34
+ * This is the public endpoint when the cluster has one, otherwise the first master endpoint.
35
+ */
36
+ bootstrapEndpoint: l4EndpointEntity,
37
+ },
38
+
39
+ schema: z.object({
40
+ /**
41
+ * The cluster name.
42
+ */
43
+ name: z.string(),
44
+
45
+ /**
46
+ * The agent token workers should use to join the cluster.
47
+ */
48
+ agentToken: secretSchema(z.string()),
49
+
50
+ /**
51
+ * The shared K3s agent configuration for workers joining the cluster.
52
+ */
53
+ agentConfig: z.record(z.string(), z.unknown()),
54
+
55
+ /**
56
+ * The registry configuration workers should use when joining the cluster.
57
+ */
58
+ registries: z.record(z.string(), z.unknown()),
59
+ }),
60
+
61
+ meta: {
62
+ color: "#326CE5",
63
+ title: "K3s Cluster",
64
+ icon: "devicon:k3s",
65
+ iconColor: "#326CE5",
66
+ },
67
+ })
68
+
25
69
  /**
26
70
  * The K3s cluster created on top of the server.
27
71
  */
@@ -78,8 +122,28 @@ export const cluster = defineUnit({
78
122
  registries: z.record(z.string(), z.unknown()).optional(),
79
123
  },
80
124
 
81
- inputs: clusterInputs,
82
- outputs: clusterOutputs,
125
+ inputs: {
126
+ ...clusterInputs,
127
+
128
+ /**
129
+ * The public API endpoint to expose for cluster access.
130
+ *
131
+ * If specified, it will be used for the kubeconfig, Kubernetes provider, cluster entity, and TLS SANs.
132
+ * Node bootstrap still uses the first master endpoint.
133
+ */
134
+ publicEndpoint: {
135
+ entity: l4EndpointEntity,
136
+ required: false,
137
+ },
138
+ },
139
+ outputs: {
140
+ ...clusterOutputs,
141
+
142
+ /**
143
+ * The K3s cluster join information for provisioning additional workers.
144
+ */
145
+ cluster: clusterEntity,
146
+ },
83
147
 
84
148
  meta: {
85
149
  title: "K3s Cluster",
@@ -93,3 +157,65 @@ export const cluster = defineUnit({
93
157
  path: "cluster",
94
158
  },
95
159
  })
160
+
161
+ /**
162
+ * The group of K3s worker nodes joined to an existing K3s cluster.
163
+ */
164
+ export const workerGroup = defineUnit({
165
+ type: "k3s.worker-group.v1",
166
+
167
+ args: {
168
+ /**
169
+ * The K3s configuration to pass to each worker in the group.
170
+ *
171
+ * See: https://docs.k3s.io/installation/configuration
172
+ */
173
+ config: z.record(z.string(), z.unknown()).optional(),
174
+
175
+ /**
176
+ * The map of configuration per each worker in the group, where the key is the hostname of the node.
177
+ *
178
+ * Note: if multiple nodes have the same hostname, the configuration will be applied to all of them.
179
+ */
180
+ nodeConfig: z.record(z.string(), z.record(z.string(), z.unknown())).optional(),
181
+ },
182
+
183
+ inputs: {
184
+ /**
185
+ * The K3s cluster join information.
186
+ */
187
+ cluster: clusterEntity,
188
+
189
+ /**
190
+ * The worker servers in the group to join to the cluster.
191
+ */
192
+ workers: {
193
+ entity: serverEntity,
194
+ multiple: true,
195
+ },
196
+ },
197
+
198
+ outputs: {
199
+ /**
200
+ * The worker servers in the group joined to the cluster.
201
+ */
202
+ workers: {
203
+ entity: serverEntity,
204
+ multiple: true,
205
+ },
206
+ },
207
+
208
+ meta: {
209
+ title: "K3s Worker Group",
210
+ category: "k3s",
211
+ icon: "devicon:k3s",
212
+ secondaryIcon: "mdi:server",
213
+ },
214
+
215
+ source: {
216
+ package: "@highstate/k3s",
217
+ path: "worker-group",
218
+ },
219
+ })
220
+
221
+ export type Cluster = EntityValue<typeof clusterEntity>
@@ -0,0 +1,50 @@
1
+ import { defineUnit, z } from "@highstate/contract"
2
+ import { pick } from "remeda"
3
+ import { gatewayEntity } from "../../common"
4
+ import { appName, sharedArgs, sharedInputs, source } from "./shared"
5
+
6
+ /**
7
+ * The Envoy Gateway controller and gateway implementation.
8
+ */
9
+ export const envoyGateway = defineUnit({
10
+ type: "k8s.apps.envoy-gateway.v1",
11
+
12
+ args: {
13
+ ...appName("envoy-gateway"),
14
+ ...pick(sharedArgs, ["external", "replicas", "values", "patches", "service", "scheduling"]),
15
+
16
+ /**
17
+ * The name of the GatewayClass to configure for Gateway API resources.
18
+ *
19
+ * Defaults to "envoy-gateway".
20
+ */
21
+ className: z.string().default("envoy-gateway"),
22
+
23
+ /**
24
+ * The Gateway API controller name for Envoy Gateway.
25
+ */
26
+ controllerName: z.string().default("gateway.envoyproxy.io/gatewayclass-controller"),
27
+
28
+ /**
29
+ * Whether to install CRDs bundled with the Envoy Gateway Helm chart.
30
+ */
31
+ installCrds: z.boolean().default(true),
32
+ },
33
+
34
+ inputs: {
35
+ ...pick(sharedInputs, ["k8sCluster"]),
36
+ },
37
+
38
+ outputs: {
39
+ gateway: gatewayEntity,
40
+ },
41
+
42
+ meta: {
43
+ title: "Envoy Gateway",
44
+ icon: "simple-icons:envoyproxy",
45
+ iconColor: "#AC6199",
46
+ category: "Network",
47
+ },
48
+
49
+ source: source("envoy-gateway"),
50
+ })
@@ -18,7 +18,7 @@ export const etcd = defineUnit({
18
18
 
19
19
  args: {
20
20
  ...appName("etcd"),
21
- ...pick(sharedArgs, ["external"]),
21
+ ...pick(sharedArgs, ["external", "values", "patches", "service", "scheduling"]),
22
22
  },
23
23
 
24
24
  secrets: {
@@ -11,7 +11,7 @@ export const grafana = defineUnit({
11
11
 
12
12
  args: {
13
13
  ...appName("grafana"),
14
- ...pick(sharedArgs, ["fqdn"]),
14
+ ...pick(sharedArgs, ["fqdn", "values", "patches", "service", "scheduling"]),
15
15
 
16
16
  /**
17
17
  * The list of plugins to install on Grafana.
@@ -1,4 +1,5 @@
1
1
  export * from "./code-server"
2
+ export * from "./envoy-gateway"
2
3
  export * from "./etcd"
3
4
  export * from "./grafana"
4
5
  export * from "./grocy"
@@ -11,6 +12,7 @@ export * from "./portal"
11
12
  export * from "./postgresql"
12
13
  export * from "./refluxdb"
13
14
  export * from "./remnawave"
15
+ export * from "./rustfs"
14
16
  export {
15
17
  appName,
16
18
  optionalSharedArgs,
@@ -19,11 +21,13 @@ export {
19
21
  sharedInputs,
20
22
  sharedSecrets,
21
23
  } from "./shared"
24
+ export * from "./signoz"
22
25
  export * from "./syncthing"
23
26
  // export * from "./zitadel"
24
27
  // export * from "./gitea"
25
28
  export * from "./traefik"
26
29
  export * from "./valkey"
30
+ export * from "./vault"
27
31
  export * from "./vaultwarden"
28
32
  export * from "./wg-feed-server"
29
33
  export * from "./workload"
@@ -19,7 +19,7 @@ export const mariadb = defineUnit({
19
19
 
20
20
  args: {
21
21
  ...appName("mariadb"),
22
- ...pick(sharedArgs, ["external"]),
22
+ ...pick(sharedArgs, ["external", "values", "patches", "service", "scheduling"]),
23
23
  },
24
24
 
25
25
  secrets: {
@@ -1,7 +1,7 @@
1
1
  import { defineUnit, z } from "@highstate/contract"
2
2
  import { pick } from "remeda"
3
3
  import { postgresql } from "../../databases"
4
- import { appName, sharedInputs, source } from "./shared"
4
+ import { appName, sharedArgs, sharedInputs, source } from "./shared"
5
5
 
6
6
  /**
7
7
  * The Matrix stack deployed on Kubernetes.
@@ -11,6 +11,7 @@ export const matrixStack = defineUnit({
11
11
 
12
12
  args: {
13
13
  ...appName("matrix-stack"),
14
+ ...pick(sharedArgs, ["values", "patches", "service"]),
14
15
 
15
16
  /**
16
17
  * The base domain for the Matrix stack services.
@@ -20,8 +20,8 @@ export const minio = defineUnit({
20
20
 
21
21
  args: {
22
22
  ...appName("minio"),
23
- ...pick(optionalSharedArgs, ["fqdn"]),
24
- ...pick(sharedArgs, ["external"]),
23
+ ...pick(optionalSharedArgs, ["fqdn", "namespace"]),
24
+ ...pick(sharedArgs, ["external", "values", "patches", "service", "scheduling"]),
25
25
 
26
26
  /**
27
27
  * The FQDN of the MinIO console.
@@ -19,7 +19,7 @@ export const mongodb = defineUnit({
19
19
 
20
20
  args: {
21
21
  ...appName("mongodb"),
22
- ...pick(sharedArgs, ["external"]),
22
+ ...pick(sharedArgs, ["external", "values", "patches", "service", "scheduling"]),
23
23
  },
24
24
 
25
25
  secrets: {
@@ -19,7 +19,7 @@ export const postgresql = defineUnit({
19
19
 
20
20
  args: {
21
21
  ...appName("postgresql"),
22
- ...pick(sharedArgs, ["namespace", "external"]),
22
+ ...pick(sharedArgs, ["namespace", "external", "values", "patches", "service", "scheduling"]),
23
23
  },
24
24
 
25
25
  secrets: {
@@ -0,0 +1,119 @@
1
+ import { defineUnit, z } from "@highstate/contract"
2
+ import { pick } from "remeda"
3
+ import { connectionEntity } from "../../databases/rustfs"
4
+ import { workloadEntity } from "../workload"
5
+ import {
6
+ appName,
7
+ optionalSharedArgs,
8
+ optionalSharedInputs,
9
+ sharedArgs,
10
+ sharedInputs,
11
+ sharedSecrets,
12
+ source,
13
+ } from "./shared"
14
+
15
+ /**
16
+ * The RustFS S3-compatible object storage deployed on Kubernetes.
17
+ */
18
+ export const rustfs = defineUnit({
19
+ type: "k8s.apps.rustfs.v1",
20
+
21
+ args: {
22
+ ...appName("rustfs"),
23
+ ...pick(optionalSharedArgs, ["fqdn", "namespace"]),
24
+ ...pick(sharedArgs, ["external", "values", "patches", "service", "scheduling"]),
25
+
26
+ /**
27
+ * The deployment topology to use.
28
+ *
29
+ * Standalone mode deploys one pod with one data volume.
30
+ * Distributed mode deploys an erasure-coded StatefulSet across multiple pods and volumes.
31
+ */
32
+ mode: z.enum(["standalone", "distributed"]).default("distributed"),
33
+
34
+ /**
35
+ * The FQDN of the RustFS console.
36
+ *
37
+ * If not provided, the console will only be available inside the cluster.
38
+ */
39
+ consoleFqdn: z.string().optional(),
40
+
41
+ /**
42
+ * The number of nodes in a distributed deployment.
43
+ *
44
+ * Ignored in standalone mode.
45
+ */
46
+ replicas: z.number().int().min(2).default(4),
47
+
48
+ /**
49
+ * The number of data volumes attached to each distributed node.
50
+ *
51
+ * Ignored in standalone mode.
52
+ */
53
+ drivesPerNode: z.number().int().min(1).default(4),
54
+
55
+ /**
56
+ * Whether to bypass RustFS validation that each data volume uses a distinct physical disk.
57
+ *
58
+ * This sets `RUSTFS_UNSAFE_BYPASS_DISK_CHECK=true` and must only be used for local testing or CI.
59
+ * Enabling it in production can cause correlated data loss because multiple erasure-coded drives
60
+ * may actually share one physical device.
61
+ */
62
+ unsafeBypassDiskCheck: z.boolean().default(false),
63
+
64
+ /**
65
+ * Whether distributed RustFS pods may share Kubernetes nodes.
66
+ *
67
+ * By default, RustFS requires each replica to run on a different node for failure isolation.
68
+ * Enable this when the Kubernetes cluster has fewer eligible nodes than RustFS replicas.
69
+ * Pods will still prefer separate nodes, but the scheduler may place multiple replicas on one node.
70
+ * This reduces fault tolerance because one node failure can make multiple RustFS replicas unavailable.
71
+ *
72
+ * Ignored in standalone mode.
73
+ */
74
+ allowLessNodes: z.boolean().default(false),
75
+
76
+ /**
77
+ * The Kubernetes StorageClass used for RustFS volumes.
78
+ */
79
+ storageClass: z.string().default("local-path"),
80
+
81
+ /**
82
+ * The requested capacity of each data volume.
83
+ */
84
+ dataStorageSize: z.string().default("100Gi"),
85
+
86
+ /**
87
+ * The requested capacity of each log volume.
88
+ */
89
+ logStorageSize: z.string().default("1Gi"),
90
+
91
+ /**
92
+ * The S3 region reported by RustFS.
93
+ */
94
+ region: z.string().default("us-east-1"),
95
+ },
96
+
97
+ secrets: {
98
+ ...pick(sharedSecrets, ["adminPassword", "backupKey"]),
99
+ },
100
+
101
+ inputs: {
102
+ ...pick(sharedInputs, ["k8sCluster"]),
103
+ ...pick(optionalSharedInputs, ["accessPoint", "resticRepo"]),
104
+ },
105
+
106
+ outputs: {
107
+ connection: connectionEntity,
108
+ workload: workloadEntity,
109
+ },
110
+
111
+ meta: {
112
+ title: "RustFS",
113
+ icon: "simple-icons:rust",
114
+ secondaryIcon: "mdi:bucket",
115
+ category: "Databases",
116
+ },
117
+
118
+ source: source("rustfs"),
119
+ })
@@ -16,7 +16,18 @@ import { etcd, mongodb, mysql, postgresql, redis } from "../../databases"
16
16
  import { providerEntity } from "../../dns"
17
17
  import { repositoryEntity } from "../../restic"
18
18
  import { namespaceEntity, persistentVolumeClaimEntity } from "../resources"
19
- import { clusterEntity } from "../shared"
19
+ import { clusterEntity, helmExtensionArgs, schedulingArg, serviceArg } from "../shared"
20
+
21
+ export {
22
+ helmExtensionArgs,
23
+ type JsonPatchOperation,
24
+ jsonPatchOperationSchema,
25
+ type Scheduling,
26
+ type ServiceArgs,
27
+ schedulingArg,
28
+ schedulingSchema,
29
+ serviceArg,
30
+ } from "../shared"
20
31
 
21
32
  export const sharedArgs = $args({
22
33
  /**
@@ -47,6 +58,10 @@ export const sharedArgs = $args({
47
58
  * If not provided, defaults to the appName.
48
59
  */
49
60
  namespace: z.string().optional(),
61
+
62
+ ...helmExtensionArgs,
63
+ ...serviceArg,
64
+ ...schedulingArg,
50
65
  })
51
66
 
52
67
  type ToOptionalArgs<T extends Record<string, FullComponentArgumentOptions>> = Simplify<{
@@ -0,0 +1,32 @@
1
+ import { defineUnit } from "@highstate/contract"
2
+ import { pick } from "remeda"
3
+ import { serviceEntity } from "../service"
4
+ import { appName, sharedArgs, sharedInputs, source } from "./shared"
5
+
6
+ /**
7
+ * SigNoz deployed on Kubernetes.
8
+ */
9
+ export const signoz = defineUnit({
10
+ type: "k8s.apps.signoz.v1",
11
+
12
+ args: {
13
+ ...appName("signoz"),
14
+ ...pick(sharedArgs, ["fqdn", "namespace", "values", "patches", "service", "scheduling"]),
15
+ },
16
+
17
+ inputs: {
18
+ ...pick(sharedInputs, ["k8sCluster", "accessPoint", "postgresql"]),
19
+ },
20
+
21
+ outputs: {
22
+ service: serviceEntity,
23
+ },
24
+
25
+ meta: {
26
+ title: "SigNoz",
27
+ icon: "selfhst:signoz",
28
+ category: "Observability",
29
+ },
30
+
31
+ source: source("signoz"),
32
+ })
@@ -13,7 +13,7 @@ export const traefik = defineUnit({
13
13
 
14
14
  args: {
15
15
  ...appName("traefik"),
16
- ...pick(sharedArgs, ["external", "replicas"]),
16
+ ...pick(sharedArgs, ["external", "replicas", "values", "patches", "service", "scheduling"]),
17
17
 
18
18
  /**
19
19
  * The name of the class to configure for ingress and gateway resources.
@@ -23,14 +23,14 @@ export const traefik = defineUnit({
23
23
  className: z.string().default("traefik"),
24
24
 
25
25
  /**
26
- * The node selector to apply to all Traefik pods.
26
+ * Whether to create and enable reconciliation for Traefik CRDs.
27
27
  */
28
- nodeSelector: z.record(z.string(), z.string()).default({}),
28
+ enableTraefikCrds: z.boolean().default(true),
29
29
 
30
30
  /**
31
- * Whether to create and enable reconciliation for Traefik CRDs.
31
+ * Whether to install CRDs bundled with the Traefik Helm chart.
32
32
  */
33
- enableTraefikCrds: z.boolean().default(true),
33
+ installCrds: z.boolean().default(true),
34
34
 
35
35
  /**
36
36
  * Whether to enable reconciliation for Ingress resources and create ingress class.
@@ -19,7 +19,7 @@ export const valkey = defineUnit({
19
19
 
20
20
  args: {
21
21
  ...appName("valkey"),
22
- ...pick(sharedArgs, ["external"]),
22
+ ...pick(sharedArgs, ["external", "values", "patches", "service", "scheduling"]),
23
23
  },
24
24
 
25
25
  secrets: {
@@ -0,0 +1,113 @@
1
+ import { defineUnit, z } from "@highstate/contract"
2
+ import { pick } from "remeda"
3
+ import { connectionEntity } from "../../apps/vault"
4
+ import { s3 } from "../../databases"
5
+ import { statefulSetEntity } from "../workload"
6
+ import {
7
+ appName,
8
+ optionalSharedInputs,
9
+ sharedArgs,
10
+ sharedInputs,
11
+ sharedSecrets,
12
+ source,
13
+ } from "./shared"
14
+
15
+ /**
16
+ * The HashiCorp Vault deployed on Kubernetes using the official Helm chart.
17
+ */
18
+ export const vault = defineUnit({
19
+ type: "k8s.apps.vault.v1",
20
+
21
+ args: {
22
+ ...appName("vault"),
23
+ ...pick(sharedArgs, [
24
+ "fqdn",
25
+ "external",
26
+ "namespace",
27
+ "values",
28
+ "patches",
29
+ "service",
30
+ "scheduling",
31
+ ]),
32
+
33
+ /**
34
+ * The storage backend to use for Vault.
35
+ *
36
+ * The options are:
37
+ * - `file`: uses a persistent volume claim and supports restic backups (default);
38
+ * - `s3`: uses an external S3-compatible bucket; expects `s3Bucket` input.
39
+ */
40
+ backend: z.enum(["file", "s3"]).default("file"),
41
+
42
+ /**
43
+ * The automatic Vault initialization configuration.
44
+ */
45
+ autoInit: z
46
+ .object({
47
+ /**
48
+ * Whether to initialize Vault automatically using the Vault CLI.
49
+ */
50
+ enabled: z.boolean().default(true),
51
+
52
+ /**
53
+ * The number of unseal key shares to create.
54
+ */
55
+ shares: z.number().int().positive().default(1),
56
+
57
+ /**
58
+ * The number of unseal key shares required to unseal Vault.
59
+ */
60
+ threshold: z.number().int().positive().default(1),
61
+ })
62
+ .refine(autoInit => autoInit.threshold <= autoInit.shares, {
63
+ message: "threshold must be less than or equal to shares",
64
+ path: ["threshold"],
65
+ })
66
+ .default({
67
+ enabled: true,
68
+ shares: 1,
69
+ threshold: 1,
70
+ }),
71
+ },
72
+
73
+ secrets: {
74
+ ...pick(sharedSecrets, ["backupKey"]),
75
+
76
+ /**
77
+ * The root token returned by `vault operator init`.
78
+ */
79
+ rootToken: z.string().optional(),
80
+
81
+ /**
82
+ * The unseal key shares returned by `vault operator init`.
83
+ */
84
+ unsealKeys: z.string().array().meta({ complex: true }).optional(),
85
+ },
86
+
87
+ inputs: {
88
+ ...pick(sharedInputs, ["k8sCluster", "accessPoint"]),
89
+
90
+ /**
91
+ * When `backend` is `s3`, supply an existing S3 bucket connection (see `s3.bucketEntity`).
92
+ */
93
+ s3Bucket: {
94
+ entity: s3.bucketEntity,
95
+ required: false, // only required if backend is s3, will validate presence later
96
+ },
97
+
98
+ ...pick(optionalSharedInputs, ["resticRepo", "volume"]),
99
+ },
100
+
101
+ outputs: {
102
+ connection: connectionEntity,
103
+ statefulSet: statefulSetEntity,
104
+ },
105
+
106
+ meta: {
107
+ title: "Vault",
108
+ icon: "simple-icons:vault",
109
+ category: "Security",
110
+ },
111
+
112
+ source: source("vault"),
113
+ })
@@ -1,6 +1,13 @@
1
- import { defineUnit } from "@highstate/contract"
1
+ import { defineUnit, z } from "@highstate/contract"
2
2
  import { pick } from "remeda"
3
- import { appName, sharedArgs, sharedInputs, source } from "./shared"
3
+ import {
4
+ appName,
5
+ optionalSharedInputs,
6
+ sharedArgs,
7
+ sharedInputs,
8
+ sharedSecrets,
9
+ source,
10
+ } from "./shared"
4
11
 
5
12
  /**
6
13
  * The Vaultwarden password manager deployed on Kubernetes.
@@ -11,10 +18,32 @@ export const vaultwarden = defineUnit({
11
18
  args: {
12
19
  ...appName("vaultwarden"),
13
20
  ...pick(sharedArgs, ["fqdn"]),
21
+
22
+ /**
23
+ * Whether signup is allowed for the Vaultwarden instance. Defaults to `false` for security reasons.
24
+ */
25
+ allowSignup: z.boolean().default(false),
26
+
27
+ /**
28
+ * Whether admin panel is enabled. Defaults to `true`.
29
+ */
30
+ enableAdminPanel: z.boolean().default(true),
31
+ },
32
+
33
+ secrets: {
34
+ /**
35
+ * The admin token for the Vaulwarden instance.
36
+ *
37
+ * Will be automatically generated if `enableAdminPanel` is `true`.
38
+ */
39
+ adminToken: z.string().optional(),
40
+
41
+ ...pick(sharedSecrets, ["backupKey"]),
14
42
  },
15
43
 
16
44
  inputs: {
17
45
  ...pick(sharedInputs, ["k8sCluster", "accessPoint", "mysql"]),
46
+ ...pick(optionalSharedInputs, ["resticRepo"]),
18
47
  },
19
48
 
20
49
  meta: {