Compare commits
4 Commits
1671f9619c
...
2f0b9af67c
| Author | SHA1 | Date | |
|---|---|---|---|
|
2f0b9af67c
|
|||
|
3d0585e0d8
|
|||
|
772bcd441a
|
|||
|
f46833571c
|
@@ -1,85 +0,0 @@
|
|||||||
import { Construct } from "constructs";
|
|
||||||
import { Manifest } from "@cdktf/provider-kubernetes/lib/manifest";
|
|
||||||
import { KubernetesProvider } from "@cdktf/provider-kubernetes/lib/provider";
|
|
||||||
|
|
||||||
export interface CertificateOptions {
|
|
||||||
provider: KubernetesProvider;
|
|
||||||
|
|
||||||
/** Namespace to create the Certificate in */
|
|
||||||
namespace: string;
|
|
||||||
|
|
||||||
/** Required name of the certificate (and CRD name) */
|
|
||||||
name: string;
|
|
||||||
|
|
||||||
/** Secret name for storing the issued TLS cert */
|
|
||||||
secretName: string;
|
|
||||||
|
|
||||||
/** One or more DNS names the certificate should cover */
|
|
||||||
dnsNames: string[];
|
|
||||||
|
|
||||||
/** Reference to the cert-manager issuer */
|
|
||||||
issuerRef: {
|
|
||||||
name: string;
|
|
||||||
kind?: string; // ClusterIssuer or Issuer
|
|
||||||
};
|
|
||||||
|
|
||||||
/** Optional duration (default: cert-manager default) */
|
|
||||||
duration?: string;
|
|
||||||
|
|
||||||
/** Optional renewBefore (default: cert-manager default) */
|
|
||||||
renewBefore?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
class Certificate extends Construct {
|
|
||||||
public readonly manifest: Manifest;
|
|
||||||
|
|
||||||
constructor(scope: Construct, id: string, opts: CertificateOptions) {
|
|
||||||
super(scope, id);
|
|
||||||
|
|
||||||
const manifest: any = {
|
|
||||||
apiVersion: "cert-manager.io/v1",
|
|
||||||
kind: "Certificate",
|
|
||||||
metadata: {
|
|
||||||
name: opts.name,
|
|
||||||
namespace: opts.namespace,
|
|
||||||
},
|
|
||||||
spec: {
|
|
||||||
secretName: opts.secretName,
|
|
||||||
dnsNames: opts.dnsNames,
|
|
||||||
issuerRef: {
|
|
||||||
name: opts.issuerRef.name,
|
|
||||||
kind: opts.issuerRef.kind ?? "ClusterIssuer",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
if (opts.duration) {
|
|
||||||
manifest.spec.duration = opts.duration;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (opts.renewBefore) {
|
|
||||||
manifest.spec.renewBefore = opts.renewBefore;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.manifest = new Manifest(this, id, {
|
|
||||||
provider: opts.provider,
|
|
||||||
manifest,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class CloudflareCertificate extends Certificate {
|
|
||||||
constructor(
|
|
||||||
scope: Construct,
|
|
||||||
id: string,
|
|
||||||
opts: Omit<CertificateOptions, "issuerRef">,
|
|
||||||
) {
|
|
||||||
super(scope, id, {
|
|
||||||
...opts,
|
|
||||||
issuerRef: {
|
|
||||||
name: "cloudflare-issuer",
|
|
||||||
kind: "ClusterIssuer",
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,90 +0,0 @@
|
|||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
kind: ConfigMap
|
|
||||||
metadata:
|
|
||||||
name: cloudflare-domains-config
|
|
||||||
namespace: homelab
|
|
||||||
data:
|
|
||||||
DOMAINS: "auth.dogar.dev"
|
|
||||||
PROXIED: "true"
|
|
||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
kind: ConfigMap
|
|
||||||
metadata:
|
|
||||||
name: cloudflare-domains-config-non-proxied
|
|
||||||
namespace: homelab
|
|
||||||
data:
|
|
||||||
DOMAINS: "dogar.dev,git.dogar.dev,nix.dogar.dev,pip.dogar.dev,npm.dogar.dev"
|
|
||||||
PROXIED: "false"
|
|
||||||
---
|
|
||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
name: cloudflare-ddns
|
|
||||||
namespace: homelab
|
|
||||||
spec:
|
|
||||||
replicas: 1
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
app: cloudflare-ddns
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: cloudflare-ddns
|
|
||||||
spec:
|
|
||||||
nodeSelector:
|
|
||||||
nodepool: worker
|
|
||||||
containers:
|
|
||||||
- name: cloudflare-ddns
|
|
||||||
image: favonia/cloudflare-ddns:latest
|
|
||||||
env:
|
|
||||||
- name: CLOUDFLARE_API_TOKEN
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: cloudflare-token
|
|
||||||
key: token
|
|
||||||
- name: DOMAINS
|
|
||||||
valueFrom:
|
|
||||||
configMapKeyRef:
|
|
||||||
name: cloudflare-domains-config
|
|
||||||
key: DOMAINS
|
|
||||||
- name: UPDATE_TIMEOUT
|
|
||||||
value: "30s"
|
|
||||||
- name: IP6_PROVIDER
|
|
||||||
value: "none"
|
|
||||||
---
|
|
||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
name: cloudflare-ddns-non-proxied
|
|
||||||
namespace: homelab
|
|
||||||
spec:
|
|
||||||
replicas: 1
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
app: cloudflare-ddns
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: cloudflare-ddns
|
|
||||||
spec:
|
|
||||||
nodeSelector:
|
|
||||||
nodepool: worker
|
|
||||||
containers:
|
|
||||||
- name: cloudflare-ddns-non-proxied
|
|
||||||
image: favonia/cloudflare-ddns:latest
|
|
||||||
env:
|
|
||||||
- name: CLOUDFLARE_API_TOKEN
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: cloudflare-token
|
|
||||||
key: token
|
|
||||||
- name: DOMAINS
|
|
||||||
valueFrom:
|
|
||||||
configMapKeyRef:
|
|
||||||
name: cloudflare-domains-config-non-proxied
|
|
||||||
key: DOMAINS
|
|
||||||
- name: UPDATE_TIMEOUT
|
|
||||||
value: "30s"
|
|
||||||
- name: IP6_PROVIDER
|
|
||||||
value: "none"
|
|
||||||
@@ -1,12 +1,11 @@
|
|||||||
import * as fs from "fs";
|
import * as fs from "fs";
|
||||||
|
import * as path from "path";
|
||||||
import { HelmProvider } from "@cdktf/provider-helm/lib/provider";
|
import { HelmProvider } from "@cdktf/provider-helm/lib/provider";
|
||||||
import { Release } from "@cdktf/provider-helm/lib/release";
|
import { Release } from "@cdktf/provider-helm/lib/release";
|
||||||
import { Construct } from "constructs";
|
import { Construct } from "constructs";
|
||||||
import { KubernetesProvider } from "@cdktf/provider-kubernetes/lib/provider";
|
import { KubernetesProvider } from "@cdktf/provider-kubernetes/lib/provider";
|
||||||
import { Manifest } from "@cdktf/provider-kubernetes/lib/manifest";
|
import { Manifest } from "@cdktf/provider-kubernetes/lib/manifest";
|
||||||
|
|
||||||
export { CloudflareCertificate } from "./certificate";
|
|
||||||
|
|
||||||
type CertManagerOptions = {
|
type CertManagerOptions = {
|
||||||
providers: {
|
providers: {
|
||||||
kubernetes: KubernetesProvider;
|
kubernetes: KubernetesProvider;
|
||||||
@@ -34,12 +33,14 @@ export class CertManager extends Construct {
|
|||||||
chart: "cert-manager",
|
chart: "cert-manager",
|
||||||
createNamespace: true,
|
createNamespace: true,
|
||||||
values: [
|
values: [
|
||||||
fs.readFileSync("helm/values/cert-manager.values.yaml", {
|
fs.readFileSync(path.join(__dirname, "values.yaml"), {
|
||||||
encoding: "utf8",
|
encoding: "utf8",
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// "apiVersion=v1,kind=Secret,namespace=default,name=sample"
|
||||||
|
|
||||||
// Self-signed ClusterIssuer for initial CA
|
// Self-signed ClusterIssuer for initial CA
|
||||||
new Manifest(this, "ca-issuer", {
|
new Manifest(this, "ca-issuer", {
|
||||||
provider: kubernetes,
|
provider: kubernetes,
|
||||||
@@ -53,7 +54,9 @@ export class CertManager extends Construct {
|
|||||||
selfSigned: {},
|
selfSigned: {},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
}).importFrom(
|
||||||
|
`apiVersion=${certManagerApiVersion},kind=ClusterIssuer,name=ca-issuer`,
|
||||||
|
);
|
||||||
|
|
||||||
// Self-signed CA Certificate
|
// Self-signed CA Certificate
|
||||||
new Manifest(this, "selfsigned-ca", {
|
new Manifest(this, "selfsigned-ca", {
|
||||||
@@ -80,7 +83,9 @@ export class CertManager extends Construct {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
}).importFrom(
|
||||||
|
`apiVersion=${certManagerApiVersion},kind=Certificate,name=selfsigned-ca,namespace=${options.namespace}`,
|
||||||
|
);
|
||||||
|
|
||||||
// CA-based ClusterIssuer
|
// CA-based ClusterIssuer
|
||||||
new Manifest(this, "cluster-issuer", {
|
new Manifest(this, "cluster-issuer", {
|
||||||
@@ -97,7 +102,9 @@ export class CertManager extends Construct {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
}).importFrom(
|
||||||
|
`apiVersion=${certManagerApiVersion},kind=ClusterIssuer,name=cluster-issuer`,
|
||||||
|
);
|
||||||
|
|
||||||
// Cloudflare ACME ClusterIssuer
|
// Cloudflare ACME ClusterIssuer
|
||||||
new Manifest(this, "cloudflare-issuer", {
|
new Manifest(this, "cloudflare-issuer", {
|
||||||
@@ -130,6 +137,8 @@ export class CertManager extends Construct {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
}).importFrom(
|
||||||
|
`apiVersion=${certManagerApiVersion},kind=ClusterIssuer,name=cloudflare-issuer`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
crds:
|
crds:
|
||||||
enabled: true
|
enabled: true
|
||||||
prometheus:
|
prometheus:
|
||||||
enabled: false
|
enabled: true
|
||||||
webhook:
|
webhook:
|
||||||
timeoutSeconds: 4
|
timeoutSeconds: 4
|
||||||
69
core-services/index.ts
Normal file
69
core-services/index.ts
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
import { HelmProvider } from "@cdktf/provider-helm/lib/provider";
|
||||||
|
import { NamespaceV1 } from "@cdktf/provider-kubernetes/lib/namespace-v1";
|
||||||
|
import { KubernetesProvider } from "@cdktf/provider-kubernetes/lib/provider";
|
||||||
|
import { TerraformOutput, TerraformStack } from "cdktf";
|
||||||
|
import { Construct } from "constructs";
|
||||||
|
import { Longhorn } from "./longhorn";
|
||||||
|
import { MetalLB } from "./metallb";
|
||||||
|
import { Traefik } from "./traefik";
|
||||||
|
import { CertManager } from "./cert-manager";
|
||||||
|
|
||||||
|
export class CoreServices extends TerraformStack {
|
||||||
|
constructor(scope: Construct, id: string) {
|
||||||
|
super(scope, id);
|
||||||
|
|
||||||
|
const kubernetes = new KubernetesProvider(this, "kubernetes", {
|
||||||
|
configPath: "~/.kube/config",
|
||||||
|
});
|
||||||
|
|
||||||
|
const helm = new HelmProvider(this, "helm", {
|
||||||
|
kubernetes: {
|
||||||
|
configPath: "~/.kube/config",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const namespace = "homelab";
|
||||||
|
|
||||||
|
new NamespaceV1(this, "namespace", {
|
||||||
|
provider: kubernetes,
|
||||||
|
metadata: {
|
||||||
|
name: namespace,
|
||||||
|
},
|
||||||
|
}).importFrom("homelab");
|
||||||
|
|
||||||
|
new TerraformOutput(this, "namespace-output", {
|
||||||
|
value: namespace,
|
||||||
|
});
|
||||||
|
|
||||||
|
new Longhorn(this, "longhorn", {
|
||||||
|
name: "longhorn",
|
||||||
|
providers: {
|
||||||
|
kubernetes,
|
||||||
|
helm,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
new MetalLB(this, "metallb", {
|
||||||
|
provider: helm,
|
||||||
|
name: "metallb",
|
||||||
|
namespace: "metallb-system",
|
||||||
|
});
|
||||||
|
|
||||||
|
new Traefik(this, "traefik", {
|
||||||
|
provider: helm,
|
||||||
|
namespace,
|
||||||
|
name: "traefik",
|
||||||
|
});
|
||||||
|
|
||||||
|
new CertManager(this, "cert-manager", {
|
||||||
|
certManagerApiVersion: "cert-manager.io/v1",
|
||||||
|
name: "cert-manager",
|
||||||
|
namespace,
|
||||||
|
version: "1.18.2",
|
||||||
|
providers: {
|
||||||
|
kubernetes,
|
||||||
|
helm,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,9 +1,11 @@
|
|||||||
import * as fs from "fs";
|
import * as fs from "fs";
|
||||||
|
import * as path from "path";
|
||||||
import { HelmProvider } from "@cdktf/provider-helm/lib/provider";
|
import { HelmProvider } from "@cdktf/provider-helm/lib/provider";
|
||||||
import { Release } from "@cdktf/provider-helm/lib/release";
|
import { Release } from "@cdktf/provider-helm/lib/release";
|
||||||
import { Construct } from "constructs";
|
import { Construct } from "constructs";
|
||||||
import { Manifest } from "@cdktf/provider-kubernetes/lib/manifest";
|
import { Manifest } from "@cdktf/provider-kubernetes/lib/manifest";
|
||||||
import { KubernetesProvider } from "@cdktf/provider-kubernetes/lib/provider";
|
import { KubernetesProvider } from "@cdktf/provider-kubernetes/lib/provider";
|
||||||
|
import { IngressRoute } from "../../utils";
|
||||||
|
|
||||||
type LonghornOptions = {
|
type LonghornOptions = {
|
||||||
providers: {
|
providers: {
|
||||||
@@ -28,7 +30,7 @@ export class Longhorn extends Construct {
|
|||||||
chart: "longhorn",
|
chart: "longhorn",
|
||||||
createNamespace: true,
|
createNamespace: true,
|
||||||
values: [
|
values: [
|
||||||
fs.readFileSync("helm/values/longhorn.values.yaml", {
|
fs.readFileSync(path.join(__dirname, "values.yaml"), {
|
||||||
encoding: "utf8",
|
encoding: "utf8",
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
@@ -51,5 +53,16 @@ export class Longhorn extends Construct {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
new IngressRoute(this, "ingress", {
|
||||||
|
provider: kubernetes,
|
||||||
|
name: "longhorn",
|
||||||
|
namespace,
|
||||||
|
serviceName: "longhorn-frontend",
|
||||||
|
servicePort: 80,
|
||||||
|
host: "longhorn.dogar.dev",
|
||||||
|
tlsSecretName: "longhorn-tls",
|
||||||
|
entryPoints: ["websecure"],
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -16,12 +16,4 @@ metrics:
|
|||||||
serviceMonitor:
|
serviceMonitor:
|
||||||
enabled: true
|
enabled: true
|
||||||
ingress:
|
ingress:
|
||||||
enabled: true
|
enabled: false
|
||||||
ingressClassName: traefik
|
|
||||||
host: longhorn.dogar.dev
|
|
||||||
tls: true
|
|
||||||
tlsSecretName: longhorn-tls
|
|
||||||
annotations:
|
|
||||||
cert-manager.io/cluster-issuer: cloudflare-issuer
|
|
||||||
cert-manager.io/acme-challenge-type: dns01
|
|
||||||
cert-manager.io/private-key-size: "4096"
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
grafana:
|
|
||||||
enabled: true
|
|
||||||
ingress:
|
|
||||||
enabled: true
|
|
||||||
ingressClassName: traefik
|
|
||||||
annotations:
|
|
||||||
cert-manager.io/cluster-issuer: cloudflare-issuer
|
|
||||||
cert-manager.io/acme-challenge-type: dns01
|
|
||||||
cert-manager.io/private-key-size: "4096"
|
|
||||||
hosts:
|
|
||||||
- grafana.dogar.dev
|
|
||||||
tls:
|
|
||||||
- secretName: grafana-tls
|
|
||||||
hosts:
|
|
||||||
- grafana.dogar.dev
|
|
||||||
118
main.ts
118
main.ts
@@ -1,88 +1,24 @@
|
|||||||
import * as dotenv from "dotenv";
|
import * as dotenv from "dotenv";
|
||||||
import { cleanEnv, str } from "envalid";
|
import { cleanEnv, str } from "envalid";
|
||||||
import { Construct } from "constructs";
|
import { App, S3Backend, TerraformStack } from "cdktf";
|
||||||
import { App, TerraformStack, LocalBackend, TerraformOutput } from "cdktf";
|
|
||||||
import { HelmProvider } from "@cdktf/provider-helm/lib/provider";
|
|
||||||
import { KubernetesProvider } from "@cdktf/provider-kubernetes/lib/provider";
|
|
||||||
import { NamespaceV1 } from "@cdktf/provider-kubernetes/lib/namespace-v1";
|
|
||||||
|
|
||||||
import { Longhorn } from "./longhorn";
|
|
||||||
import { CertManager } from "./cert-manager";
|
|
||||||
import { Traefik } from "./traefik";
|
|
||||||
import { MetalLB } from "./metallb";
|
|
||||||
import { CacheInfrastructure } from "./cache-infrastructure";
|
import { CacheInfrastructure } from "./cache-infrastructure";
|
||||||
import { UtilityServices } from "./utility-services";
|
import { UtilityServices } from "./utility-services";
|
||||||
import { K8SOperators } from "./k8s-operators";
|
import { K8SOperators } from "./k8s-operators";
|
||||||
|
import { CoreServices } from "./core-services";
|
||||||
|
|
||||||
dotenv.config();
|
dotenv.config();
|
||||||
|
|
||||||
cleanEnv(process.env, {
|
const env = cleanEnv(process.env, {
|
||||||
ACCOUNT_ID: str({ desc: "Cloudflare account id." }),
|
ACCOUNT_ID: str({ desc: "Cloudflare account id." }),
|
||||||
OP_CONNECT_TOKEN: str({ desc: "1Password Connect token." }),
|
OP_CONNECT_TOKEN: str({ desc: "1Password Connect token." }),
|
||||||
|
ACCESS_KEY: str({ desc: "Access key ID for R2 storage." }),
|
||||||
|
SECRET_KEY: str({ desc: "Secret access key for R2 storage." }),
|
||||||
});
|
});
|
||||||
|
|
||||||
class CoreServices extends TerraformStack {
|
const r2Endpoint = `https://${env.ACCOUNT_ID}.r2.cloudflarestorage.com`;
|
||||||
constructor(scope: Construct, id: string) {
|
|
||||||
super(scope, id);
|
|
||||||
|
|
||||||
const kubernetes = new KubernetesProvider(this, "kubernetes", {
|
|
||||||
configPath: "~/.kube/config",
|
|
||||||
});
|
|
||||||
|
|
||||||
const helm = new HelmProvider(this, "helm", {
|
|
||||||
kubernetes: {
|
|
||||||
configPath: "~/.kube/config",
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const namespace = "homelab";
|
|
||||||
|
|
||||||
new NamespaceV1(this, "namespace", {
|
|
||||||
provider: kubernetes,
|
|
||||||
metadata: {
|
|
||||||
name: namespace,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
new TerraformOutput(this, "namespace-output", {
|
|
||||||
value: namespace,
|
|
||||||
});
|
|
||||||
|
|
||||||
new Longhorn(this, "longhorn", {
|
|
||||||
name: "longhorn",
|
|
||||||
providers: {
|
|
||||||
kubernetes,
|
|
||||||
helm,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
new MetalLB(this, "metallb", {
|
|
||||||
provider: helm,
|
|
||||||
name: "metallb",
|
|
||||||
namespace: "metallb-system",
|
|
||||||
});
|
|
||||||
|
|
||||||
new Traefik(this, "traefik", {
|
|
||||||
provider: helm,
|
|
||||||
namespace,
|
|
||||||
name: "traefik",
|
|
||||||
});
|
|
||||||
|
|
||||||
new CertManager(this, "cert-manager", {
|
|
||||||
certManagerApiVersion: "cert-manager.io/v1",
|
|
||||||
name: "cert-manager",
|
|
||||||
namespace,
|
|
||||||
version: "1.18.2",
|
|
||||||
providers: {
|
|
||||||
kubernetes,
|
|
||||||
helm,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const app = new App();
|
const app = new App();
|
||||||
const coreServices = new CoreServices(app, "homelab");
|
const coreServices = new CoreServices(app, "core-services");
|
||||||
|
|
||||||
const k8sOperators = new K8SOperators(app, "k8s-operators");
|
const k8sOperators = new K8SOperators(app, "k8s-operators");
|
||||||
k8sOperators.node.addDependency(coreServices);
|
k8sOperators.node.addDependency(coreServices);
|
||||||
@@ -93,24 +29,30 @@ utilityServices.node.addDependency(k8sOperators);
|
|||||||
const caches = new CacheInfrastructure(app, "cache-infrastructure");
|
const caches = new CacheInfrastructure(app, "cache-infrastructure");
|
||||||
caches.node.addDependency(utilityServices);
|
caches.node.addDependency(utilityServices);
|
||||||
|
|
||||||
new LocalBackend(coreServices, {
|
const deploy: (stack: TerraformStack, key: string) => S3Backend = (
|
||||||
path: "terraform.tfstate",
|
stack,
|
||||||
workspaceDir: ".",
|
key,
|
||||||
|
) =>
|
||||||
|
new S3Backend(stack, {
|
||||||
|
bucket: "terraform-state",
|
||||||
|
key: `${key}/terraform.tfstate`,
|
||||||
|
region: "auto",
|
||||||
|
endpoints: {
|
||||||
|
s3: r2Endpoint,
|
||||||
|
},
|
||||||
|
accessKey: env.ACCESS_KEY,
|
||||||
|
secretKey: env.SECRET_KEY,
|
||||||
|
encrypt: true,
|
||||||
|
usePathStyle: true,
|
||||||
|
skipRegionValidation: true,
|
||||||
|
skipCredentialsValidation: true,
|
||||||
|
skipRequestingAccountId: true,
|
||||||
|
skipS3Checksum: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
new LocalBackend(caches, {
|
deploy(coreServices, "core-services");
|
||||||
path: "terraform.tfstate",
|
deploy(utilityServices, "utility-services");
|
||||||
workspaceDir: "./cachestf",
|
deploy(k8sOperators, "k8s-operators");
|
||||||
});
|
deploy(caches, "cache-infrastructure");
|
||||||
|
|
||||||
new LocalBackend(utilityServices, {
|
|
||||||
path: "terraform.tfstate",
|
|
||||||
workspaceDir: "./utilityservicestf",
|
|
||||||
});
|
|
||||||
|
|
||||||
new LocalBackend(k8sOperators, {
|
|
||||||
path: "terraform.tfstate",
|
|
||||||
workspaceDir: "./k8soperatorstf",
|
|
||||||
});
|
|
||||||
|
|
||||||
app.synth();
|
app.synth();
|
||||||
|
|||||||
@@ -1,452 +0,0 @@
|
|||||||
import { Manifest } from "@cdktf/provider-kubernetes/lib/manifest";
|
|
||||||
import { KubernetesProvider } from "@cdktf/provider-kubernetes/lib/provider";
|
|
||||||
import { Construct } from "constructs";
|
|
||||||
|
|
||||||
type PostgresClusterOptions = {
|
|
||||||
provider: KubernetesProvider;
|
|
||||||
name: string;
|
|
||||||
namespace: string;
|
|
||||||
users: string[];
|
|
||||||
primaryUser: string;
|
|
||||||
initSecretName: string;
|
|
||||||
certManagerApiVersion: string;
|
|
||||||
backupR2EndpointURL: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export class PostgresCluster extends Construct {
|
|
||||||
constructor(scope: Construct, id: string, options: PostgresClusterOptions) {
|
|
||||||
super(scope, id);
|
|
||||||
|
|
||||||
const { provider } = options;
|
|
||||||
|
|
||||||
const destinationPath = "s3://postgres-backups/";
|
|
||||||
const endpointURL = options.backupR2EndpointURL;
|
|
||||||
const barmanStoreName = "r2-postgres-backup-store";
|
|
||||||
const backupServerName = `${options.name}-backup`;
|
|
||||||
|
|
||||||
const barmanConfiguration = {
|
|
||||||
destinationPath,
|
|
||||||
endpointURL,
|
|
||||||
s3Credentials: {
|
|
||||||
accessKeyId: {
|
|
||||||
name: "cloudflare-token",
|
|
||||||
key: "access_key_id",
|
|
||||||
},
|
|
||||||
secretAccessKey: {
|
|
||||||
name: "cloudflare-token",
|
|
||||||
key: "secret_access_key",
|
|
||||||
},
|
|
||||||
region: {
|
|
||||||
name: "cloudflare-token",
|
|
||||||
key: "AWS_REGION",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
wal: {
|
|
||||||
compression: "gzip",
|
|
||||||
},
|
|
||||||
data: {
|
|
||||||
compression: "gzip",
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
new Manifest(this, "r2-backup-store", {
|
|
||||||
provider,
|
|
||||||
manifest: {
|
|
||||||
apiVersion: "barmancloud.cnpg.io/v1",
|
|
||||||
kind: "ObjectStore",
|
|
||||||
metadata: {
|
|
||||||
namespace: options.namespace,
|
|
||||||
name: barmanStoreName,
|
|
||||||
},
|
|
||||||
spec: {
|
|
||||||
retentionPolicy: "15d",
|
|
||||||
configuration: {
|
|
||||||
...barmanConfiguration,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const { certManagerApiVersion } = options;
|
|
||||||
|
|
||||||
const certNames = {
|
|
||||||
server: "postgres-server-cert",
|
|
||||||
client: "postgres-client-cert",
|
|
||||||
};
|
|
||||||
|
|
||||||
const caNames = {
|
|
||||||
server: "postgres-server-ca",
|
|
||||||
client: "postgres-client-ca",
|
|
||||||
};
|
|
||||||
|
|
||||||
// Self-signed issuer for creating CA certificates
|
|
||||||
new Manifest(this, "selfsigned-issuer", {
|
|
||||||
provider,
|
|
||||||
manifest: {
|
|
||||||
apiVersion: certManagerApiVersion,
|
|
||||||
kind: "Issuer",
|
|
||||||
metadata: {
|
|
||||||
name: "selfsigned-issuer",
|
|
||||||
namespace: options.namespace,
|
|
||||||
},
|
|
||||||
spec: {
|
|
||||||
selfSigned: {},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
// Server CA certificate
|
|
||||||
new Manifest(this, "server-ca-cert", {
|
|
||||||
provider,
|
|
||||||
manifest: {
|
|
||||||
apiVersion: certManagerApiVersion,
|
|
||||||
kind: "Certificate",
|
|
||||||
metadata: {
|
|
||||||
name: "server-ca",
|
|
||||||
namespace: options.namespace,
|
|
||||||
},
|
|
||||||
spec: {
|
|
||||||
isCA: true,
|
|
||||||
commonName: caNames.server,
|
|
||||||
secretName: caNames.server,
|
|
||||||
privateKey: {
|
|
||||||
algorithm: "ECDSA",
|
|
||||||
size: 384,
|
|
||||||
},
|
|
||||||
duration: "52560h", // 6 years
|
|
||||||
renewBefore: "8760h", // 1 year before expiration
|
|
||||||
issuerRef: {
|
|
||||||
name: "selfsigned-issuer",
|
|
||||||
kind: "Issuer",
|
|
||||||
group: "cert-manager.io",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
// Issuer using the server CA
|
|
||||||
new Manifest(this, "server-ca-issuer", {
|
|
||||||
provider,
|
|
||||||
manifest: {
|
|
||||||
apiVersion: certManagerApiVersion,
|
|
||||||
kind: "Issuer",
|
|
||||||
metadata: {
|
|
||||||
name: `${caNames.server}-issuer`,
|
|
||||||
namespace: options.namespace,
|
|
||||||
},
|
|
||||||
spec: {
|
|
||||||
ca: {
|
|
||||||
secretName: caNames.server,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
// Server certificate
|
|
||||||
new Manifest(this, "server-cert", {
|
|
||||||
provider,
|
|
||||||
manifest: {
|
|
||||||
apiVersion: certManagerApiVersion,
|
|
||||||
kind: "Certificate",
|
|
||||||
metadata: {
|
|
||||||
name: certNames.server,
|
|
||||||
namespace: options.namespace,
|
|
||||||
},
|
|
||||||
spec: {
|
|
||||||
secretName: certNames.server,
|
|
||||||
usages: ["server auth"],
|
|
||||||
dnsNames: [
|
|
||||||
"postgres-cluster-rw",
|
|
||||||
"postgres-cluster-rw.homelab.svc.cluster.local",
|
|
||||||
"postgres.dogar.dev",
|
|
||||||
],
|
|
||||||
duration: "4380h", // 6 months
|
|
||||||
renewBefore: "720h", // 30 days before expiration
|
|
||||||
issuerRef: {
|
|
||||||
name: `${caNames.server}-issuer`,
|
|
||||||
kind: "Issuer",
|
|
||||||
group: "cert-manager.io",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
// Client CA certificate
|
|
||||||
new Manifest(this, "client-ca", {
|
|
||||||
provider,
|
|
||||||
manifest: {
|
|
||||||
apiVersion: certManagerApiVersion,
|
|
||||||
kind: "Certificate",
|
|
||||||
metadata: {
|
|
||||||
name: "client-ca",
|
|
||||||
namespace: options.namespace,
|
|
||||||
},
|
|
||||||
spec: {
|
|
||||||
isCA: true,
|
|
||||||
commonName: caNames.client,
|
|
||||||
secretName: caNames.client,
|
|
||||||
privateKey: {
|
|
||||||
algorithm: "ECDSA",
|
|
||||||
size: 256,
|
|
||||||
},
|
|
||||||
duration: "52560h", // 6 years
|
|
||||||
renewBefore: "8760h", // 1 year before expiration
|
|
||||||
issuerRef: {
|
|
||||||
name: "selfsigned-issuer",
|
|
||||||
kind: "Issuer",
|
|
||||||
group: "cert-manager.io",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
// Issuer using the client CA
|
|
||||||
new Manifest(this, "client-ca-issuer", {
|
|
||||||
provider,
|
|
||||||
manifest: {
|
|
||||||
apiVersion: certManagerApiVersion,
|
|
||||||
kind: "Issuer",
|
|
||||||
metadata: {
|
|
||||||
name: `${caNames.client}-issuer`,
|
|
||||||
namespace: options.namespace,
|
|
||||||
},
|
|
||||||
spec: {
|
|
||||||
ca: {
|
|
||||||
secretName: caNames.client,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
// Secret for client certificate
|
|
||||||
new Manifest(this, `${certNames.client}-secret`, {
|
|
||||||
provider,
|
|
||||||
manifest: {
|
|
||||||
apiVersion: "v1",
|
|
||||||
kind: "Secret",
|
|
||||||
metadata: {
|
|
||||||
name: certNames.client,
|
|
||||||
namespace: options.namespace,
|
|
||||||
labels: {
|
|
||||||
"cnpg.io/reload": "",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
// Client certificate for streaming replica
|
|
||||||
new Manifest(this, "streaming-replica-cert", {
|
|
||||||
provider,
|
|
||||||
manifest: {
|
|
||||||
apiVersion: certManagerApiVersion,
|
|
||||||
kind: "Certificate",
|
|
||||||
metadata: {
|
|
||||||
name: certNames.client,
|
|
||||||
namespace: options.namespace,
|
|
||||||
},
|
|
||||||
spec: {
|
|
||||||
secretName: certNames.client,
|
|
||||||
usages: ["client auth"],
|
|
||||||
commonName: "streaming_replica",
|
|
||||||
duration: "4380h", // 6 months
|
|
||||||
renewBefore: "720h", // 30 days before expiration
|
|
||||||
issuerRef: {
|
|
||||||
name: "postgres-client-ca-issuer",
|
|
||||||
kind: "Issuer",
|
|
||||||
group: "cert-manager.io",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
// Client certificates for users
|
|
||||||
options.users.forEach(
|
|
||||||
(user) =>
|
|
||||||
new Manifest(this, `${user}-client-cert`, {
|
|
||||||
provider,
|
|
||||||
manifest: {
|
|
||||||
apiVersion: certManagerApiVersion,
|
|
||||||
kind: "Certificate",
|
|
||||||
metadata: {
|
|
||||||
name: `${user}-client-cert`,
|
|
||||||
namespace: options.namespace,
|
|
||||||
},
|
|
||||||
spec: {
|
|
||||||
secretName: `${user}-client-cert`,
|
|
||||||
usages: ["client auth"],
|
|
||||||
commonName: user,
|
|
||||||
duration: "4380h", // 6 months
|
|
||||||
renewBefore: "720h", // 30 days before expiration
|
|
||||||
issuerRef: {
|
|
||||||
name: "postgres-client-ca-issuer",
|
|
||||||
kind: "Issuer",
|
|
||||||
group: "cert-manager.io",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
new Manifest(this, "postgres-cluster", {
|
|
||||||
provider,
|
|
||||||
fieldManager: { forceConflicts: true },
|
|
||||||
manifest: {
|
|
||||||
apiVersion: "postgresql.cnpg.io/v1",
|
|
||||||
kind: "Cluster",
|
|
||||||
metadata: {
|
|
||||||
name: options.name,
|
|
||||||
namespace: options.namespace,
|
|
||||||
},
|
|
||||||
spec: {
|
|
||||||
instances: 3,
|
|
||||||
minSyncReplicas: 1,
|
|
||||||
maxSyncReplicas: 2,
|
|
||||||
primaryUpdateStrategy: "unsupervised",
|
|
||||||
certificates: {
|
|
||||||
serverCASecret: certNames.server,
|
|
||||||
serverTLSSecret: certNames.server,
|
|
||||||
clientCASecret: certNames.client,
|
|
||||||
replicationTLSSecret: certNames.client,
|
|
||||||
},
|
|
||||||
postgresql: {
|
|
||||||
parameters: {
|
|
||||||
archive_mode: "on",
|
|
||||||
archive_timeout: "60min",
|
|
||||||
checkpoint_timeout: "10min",
|
|
||||||
checkpoint_completion_target: "0.7",
|
|
||||||
dynamic_shared_memory_type: "posix",
|
|
||||||
full_page_writes: "on",
|
|
||||||
log_destination: "csvlog",
|
|
||||||
log_directory: "/controller/log",
|
|
||||||
log_filename: "postgres",
|
|
||||||
log_rotation_age: "0",
|
|
||||||
log_rotation_size: "0",
|
|
||||||
log_truncate_on_rotation: "false",
|
|
||||||
logging_collector: "on",
|
|
||||||
max_parallel_workers: "32",
|
|
||||||
max_replication_slots: "32",
|
|
||||||
max_worker_processes: "32",
|
|
||||||
max_slot_wal_keep_size: "256MB",
|
|
||||||
max_wal_size: "512MB",
|
|
||||||
min_wal_size: "128MB",
|
|
||||||
shared_memory_type: "mmap",
|
|
||||||
shared_preload_libraries: "",
|
|
||||||
ssl_max_protocol_version: "TLSv1.3",
|
|
||||||
ssl_min_protocol_version: "TLSv1.3",
|
|
||||||
wal_compression: "on",
|
|
||||||
wal_keep_size: "128MB",
|
|
||||||
wal_level: "replica",
|
|
||||||
wal_log_hints: "on",
|
|
||||||
wal_receiver_timeout: "5s",
|
|
||||||
wal_sender_timeout: "5s",
|
|
||||||
},
|
|
||||||
pg_hba: [
|
|
||||||
`hostssl all ${options.primaryUser} all cert`,
|
|
||||||
"hostssl sameuser all all cert",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
plugins: [
|
|
||||||
{
|
|
||||||
name: "barman-cloud.cloudnative-pg.io",
|
|
||||||
isWALArchiver: true,
|
|
||||||
parameters: {
|
|
||||||
barmanObjectName: barmanStoreName,
|
|
||||||
serverName: backupServerName,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
bootstrap: {
|
|
||||||
recovery: {
|
|
||||||
source: "clusterBackup",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
externalClusters: [
|
|
||||||
{
|
|
||||||
name: "clusterBackup",
|
|
||||||
plugin: {
|
|
||||||
name: "barman-cloud.cloudnative-pg.io",
|
|
||||||
parameters: {
|
|
||||||
barmanObjectName: barmanStoreName,
|
|
||||||
serverName: backupServerName,
|
|
||||||
skipWalArchiveCheck: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
managed: {
|
|
||||||
services: {
|
|
||||||
disabledDefaultServices: ["ro", "r"],
|
|
||||||
additional: [
|
|
||||||
{
|
|
||||||
selectorType: "rw",
|
|
||||||
serviceTemplate: {
|
|
||||||
metadata: {
|
|
||||||
name: "postgres-cluster",
|
|
||||||
superuser: true,
|
|
||||||
annotations: {
|
|
||||||
"external-dns.alpha.kubernetes.io/hostname":
|
|
||||||
"postgres.dogar.dev",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
spec: {
|
|
||||||
type: "LoadBalancer",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
roles: [
|
|
||||||
{
|
|
||||||
name: options.primaryUser,
|
|
||||||
inRoles: ["postgres"],
|
|
||||||
inherit: true,
|
|
||||||
disablePassword: true,
|
|
||||||
createdb: true,
|
|
||||||
createrole: true,
|
|
||||||
login: true,
|
|
||||||
ensure: "present",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
storage: {
|
|
||||||
size: "10Gi",
|
|
||||||
storageClass: "longhorn",
|
|
||||||
},
|
|
||||||
walStorage: {
|
|
||||||
size: "2Gi",
|
|
||||||
storageClass: "longhorn",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
new Manifest(this, "postgres-backup-job", {
|
|
||||||
provider,
|
|
||||||
manifest: {
|
|
||||||
apiVersion: "postgresql.cnpg.io/v1",
|
|
||||||
kind: "ScheduledBackup",
|
|
||||||
metadata: {
|
|
||||||
name: "postgres-cluster",
|
|
||||||
namespace: options.namespace,
|
|
||||||
},
|
|
||||||
spec: {
|
|
||||||
immediate: true,
|
|
||||||
// weekly midnight on Sunday
|
|
||||||
schedule: "* 0 0 * * 0",
|
|
||||||
backupOwnerReference: "self",
|
|
||||||
method: "plugin",
|
|
||||||
pluginConfiguration: {
|
|
||||||
name: "barman-cloud.cloudnative-pg.io",
|
|
||||||
parameters: {
|
|
||||||
barmanObjectName: barmanStoreName,
|
|
||||||
serverName: backupServerName,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
cluster: {
|
|
||||||
name: options.name,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
110
utility-services/dynamic-dns/index.ts
Normal file
110
utility-services/dynamic-dns/index.ts
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
import { Construct } from "constructs";
|
||||||
|
import { KubernetesProvider } from "@cdktf/provider-kubernetes/lib/provider";
|
||||||
|
|
||||||
|
import { OnePasswordSecret } from "../../utils";
|
||||||
|
import { ConfigMapV1 } from "@cdktf/provider-kubernetes/lib/config-map-v1";
|
||||||
|
import { DeploymentV1 } from "@cdktf/provider-kubernetes/lib/deployment-v1";
|
||||||
|
|
||||||
|
type DynamicDNSOptions = {
|
||||||
|
provider: KubernetesProvider;
|
||||||
|
name: string;
|
||||||
|
namespace: string;
|
||||||
|
records: string[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export class DynamicDNS extends Construct {
|
||||||
|
constructor(scope: Construct, id: string, options: DynamicDNSOptions) {
|
||||||
|
super(scope, id);
|
||||||
|
|
||||||
|
const { provider, name, namespace, records } = options;
|
||||||
|
|
||||||
|
new OnePasswordSecret(this, "cloudflare-token", {
|
||||||
|
provider,
|
||||||
|
name: "ddns-cloudflare-token",
|
||||||
|
namespace: options.namespace,
|
||||||
|
itemPath: "vaults/Lab/items/cloudflare",
|
||||||
|
});
|
||||||
|
|
||||||
|
new ConfigMapV1(this, "ddns-configmap", {
|
||||||
|
provider,
|
||||||
|
metadata: {
|
||||||
|
name,
|
||||||
|
namespace,
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
DOMAINS: records.join(","),
|
||||||
|
PROXIED: "false",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
new DeploymentV1(this, "ddns-deployment", {
|
||||||
|
provider,
|
||||||
|
metadata: {
|
||||||
|
name,
|
||||||
|
namespace,
|
||||||
|
},
|
||||||
|
spec: {
|
||||||
|
selector: {
|
||||||
|
matchLabels: {
|
||||||
|
app: name,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
template: {
|
||||||
|
metadata: {
|
||||||
|
labels: {
|
||||||
|
app: name,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
spec: {
|
||||||
|
nodeSelector: {
|
||||||
|
nodepool: "worker",
|
||||||
|
},
|
||||||
|
container: [
|
||||||
|
{
|
||||||
|
name: "ddns-updater",
|
||||||
|
image: "favonia/cloudflare-ddns:latest",
|
||||||
|
env: [
|
||||||
|
{
|
||||||
|
name: "CLOUDFLARE_API_TOKEN",
|
||||||
|
valueFrom: {
|
||||||
|
secretKeyRef: {
|
||||||
|
name: "ddns-cloudflare-token",
|
||||||
|
key: "token",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "DOMAINS",
|
||||||
|
valueFrom: {
|
||||||
|
configMapKeyRef: {
|
||||||
|
name,
|
||||||
|
key: "DOMAINS",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "PROXIED",
|
||||||
|
valueFrom: {
|
||||||
|
configMapKeyRef: {
|
||||||
|
name,
|
||||||
|
key: "PROXIED",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "UPDATE_TIMEOUT",
|
||||||
|
value: "30s",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "IP6_PROVIDER",
|
||||||
|
value: "none",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,14 +1,14 @@
|
|||||||
import * as path from "path";
|
|
||||||
import { DataKubernetesNamespaceV1 } from "@cdktf/provider-kubernetes/lib/data-kubernetes-namespace-v1";
|
import { DataKubernetesNamespaceV1 } from "@cdktf/provider-kubernetes/lib/data-kubernetes-namespace-v1";
|
||||||
import { KubernetesProvider } from "@cdktf/provider-kubernetes/lib/provider";
|
import { KubernetesProvider } from "@cdktf/provider-kubernetes/lib/provider";
|
||||||
import { HelmProvider } from "@cdktf/provider-helm/lib/provider";
|
import { HelmProvider } from "@cdktf/provider-helm/lib/provider";
|
||||||
import { DataTerraformRemoteStateLocal, TerraformStack } from "cdktf";
|
import { DataTerraformRemoteStateS3, TerraformStack } from "cdktf";
|
||||||
import { Construct } from "constructs";
|
import { Construct } from "constructs";
|
||||||
|
|
||||||
import { ValkeyCluster } from "./valkey";
|
import { ValkeyCluster } from "./valkey";
|
||||||
import { GiteaServer } from "./gitea";
|
import { GiteaServer } from "./gitea";
|
||||||
import { AuthentikServer } from "./authentik";
|
import { AuthentikServer } from "./authentik";
|
||||||
import { PostgresCluster } from "./postgres";
|
import { PostgresCluster } from "./postgres";
|
||||||
|
import { DynamicDNS } from "./dynamic-dns";
|
||||||
|
|
||||||
export class UtilityServices extends TerraformStack {
|
export class UtilityServices extends TerraformStack {
|
||||||
constructor(scope: Construct, id: string) {
|
constructor(scope: Construct, id: string) {
|
||||||
@@ -24,16 +24,24 @@ export class UtilityServices extends TerraformStack {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const homelabState = new DataTerraformRemoteStateLocal(
|
const r2Endpoint = `${process.env.ACCOUNT_ID!}.r2.cloudflarestorage.com`;
|
||||||
this,
|
|
||||||
"homelab-state",
|
const homelabState = new DataTerraformRemoteStateS3(this, "homelab-state", {
|
||||||
{
|
usePathStyle: true,
|
||||||
path: path.join(
|
skipRegionValidation: true,
|
||||||
__dirname,
|
skipCredentialsValidation: true,
|
||||||
"../cdktf.out/stacks/homelab/terraform.tfstate",
|
skipRequestingAccountId: true,
|
||||||
),
|
skipS3Checksum: true,
|
||||||
|
encrypt: true,
|
||||||
|
bucket: "terraform-state",
|
||||||
|
key: "core-services/terraform.tfstate",
|
||||||
|
endpoints: {
|
||||||
|
s3: `https://${r2Endpoint}`,
|
||||||
},
|
},
|
||||||
);
|
region: "auto",
|
||||||
|
accessKey: process.env.ACCESS_KEY,
|
||||||
|
secretKey: process.env.SECRET_KEY,
|
||||||
|
});
|
||||||
|
|
||||||
const namespaceName = homelabState.getString("namespace-output");
|
const namespaceName = homelabState.getString("namespace-output");
|
||||||
const namespaceResource = new DataKubernetesNamespaceV1(
|
const namespaceResource = new DataKubernetesNamespaceV1(
|
||||||
@@ -48,7 +56,19 @@ export class UtilityServices extends TerraformStack {
|
|||||||
);
|
);
|
||||||
const namespace = namespaceResource.metadata.name;
|
const namespace = namespaceResource.metadata.name;
|
||||||
|
|
||||||
const r2Endpoint = `${process.env.ACCOUNT_ID!}.r2.cloudflarestorage.com`;
|
new DynamicDNS(this, "dynamic-dns", {
|
||||||
|
provider: kubernetes,
|
||||||
|
namespace,
|
||||||
|
name: "cloudflare-ddns",
|
||||||
|
records: [
|
||||||
|
"dogar.dev",
|
||||||
|
"auth.dogar.dev",
|
||||||
|
"git.dogar.dev",
|
||||||
|
"nix.dogar.dev",
|
||||||
|
"pip.dogar.dev",
|
||||||
|
"npm.dogar.dev",
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
const valkeyCluster = new ValkeyCluster(this, "valkey-cluster", {
|
const valkeyCluster = new ValkeyCluster(this, "valkey-cluster", {
|
||||||
namespace,
|
namespace,
|
||||||
|
|||||||
Reference in New Issue
Block a user