diff --git a/k8s/cert-manager/certs/production.yaml b/k8s/cert-manager/certs/production.yaml new file mode 100644 index 00000000..e17c1a02 --- /dev/null +++ b/k8s/cert-manager/certs/production.yaml @@ -0,0 +1,13 @@ +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: app-codepod-io +spec: + secretName: app-codepod-io-tls + issuerRef: + name: letsencrypt-production + kind: ClusterIssuer + commonName: "app.codepod.io" + dnsNames: + - "app.codepod.io" diff --git a/k8s/cert-manager/certs/staging.yaml b/k8s/cert-manager/certs/staging.yaml new file mode 100644 index 00000000..cf6bfd6a --- /dev/null +++ b/k8s/cert-manager/certs/staging.yaml @@ -0,0 +1,14 @@ +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: app-codepod-io-staging +spec: + secretName: app-codepod-io-staging-tls + issuerRef: + name: letsencrypt-staging + kind: ClusterIssuer + commonName: "app.codepod.io" + dnsNames: + - "app.codepod.io" + \ No newline at end of file diff --git a/k8s/cert-manager/issuers/letsencrypt-production.yaml b/k8s/cert-manager/issuers/letsencrypt-production.yaml new file mode 100644 index 00000000..e30292e1 --- /dev/null +++ b/k8s/cert-manager/issuers/letsencrypt-production.yaml @@ -0,0 +1,21 @@ +--- +apiVersion: cert-manager.io/v1 +kind: ClusterIssuer +metadata: + name: letsencrypt-production +spec: + acme: + server: https://acme-v02.api.letsencrypt.org/directory + email: lihebi.com@gmail.com + privateKeySecretRef: + name: letsencrypt-production + solvers: + - dns01: + cloudflare: + email: lihebi.com@gmail.com + apiTokenSecretRef: + name: cloudflare-token-secret + key: cloudflare-token + selector: + dnsZones: + - "app.codepod.io" \ No newline at end of file diff --git a/k8s/cert-manager/issuers/letsencrypt-staging.yaml b/k8s/cert-manager/issuers/letsencrypt-staging.yaml new file mode 100644 index 00000000..0fdba068 --- /dev/null +++ b/k8s/cert-manager/issuers/letsencrypt-staging.yaml @@ -0,0 +1,21 @@ +--- +apiVersion: cert-manager.io/v1 +kind: ClusterIssuer +metadata: + name: letsencrypt-staging +spec: + acme: + server: https://acme-staging-v02.api.letsencrypt.org/directory + email: lihebi.com@gmail.com + privateKeySecretRef: + name: letsencrypt-staging + solvers: + - dns01: + cloudflare: + email: lihebi.com@gmail.com + apiTokenSecretRef: + name: cloudflare-token-secret + key: cloudflare-token + selector: + dnsZones: + - "app.codepod.io" \ No newline at end of file diff --git a/k8s/cert-manager/secret-cloudflare.yaml b/k8s/cert-manager/secret-cloudflare.yaml new file mode 100644 index 00000000..a5ff93ea --- /dev/null +++ b/k8s/cert-manager/secret-cloudflare.yaml @@ -0,0 +1,9 @@ +--- +apiVersion: v1 +kind: Secret +metadata: + name: cloudflare-token-secret + namespace: cert-manager +type: Opaque +stringData: + cloudflare-token: diff --git a/k8s/helm-chart/README.md b/k8s/helm-chart/README.md index 9090b551..4cc3786c 100644 --- a/k8s/helm-chart/README.md +++ b/k8s/helm-chart/README.md @@ -2,7 +2,16 @@ ## Prerequist -Also need the secrets: +### Create namespaces + +We need to create one more namespace manually: + + kubectl create ns codepod-staging + kubectl create ns codepod-staging-runtime + +### Apply the secrets + +Need the secrets: ``` apiVersion: v1 @@ -30,11 +39,24 @@ Need to manually apply these secrets: kubectl apply -f secrets.yaml ``` -## Install +### Install longhorn -We need to create one more namespace manually: +Longhorn is needed to dynamically allocate volumes for DB. - kubectl create ns codepod-staging-runtime +### Get SSL certificate (required for prod) + +See `../cert-manager`. Basically: + +1. install cert-manager +2. save cloudflare API token to secrets (to cert-manager ns) +3. define issuers (clusterwise) +4. retrieve certs (into codepod-prod namespace) + +Ref: https://docs.technotim.live/posts/kube-traefik-cert-manager-le/#cert-manager + +End result: the app-codepod-io-tls certificate. + +## Install Install: diff --git a/k8s/helm-chart/templates/ingress.yaml b/k8s/helm-chart/templates/ingress.yaml index 283490d7..06c095c5 100644 --- a/k8s/helm-chart/templates/ingress.yaml +++ b/k8s/helm-chart/templates/ingress.yaml @@ -15,6 +15,12 @@ kind: IngressRoute metadata: name: codepod-ingress spec: + {{- if .Values.ingress.tls }} + entryPoints: + - websecure + tls: + secretName: {{ .Values.ingress.tls.secretName }} + {{- end }} routes: - match: "Host(`{{ .Values.hostname }}`) && PathPrefix(`/`)" kind: Rule @@ -33,3 +39,33 @@ spec: services: - name: codepod-proxy-service port: 4010 + +{{- if .Values.ingress.tls }} +--- +apiVersion: traefik.containo.us/v1alpha1 +kind: Middleware +metadata: + name: redirect-https +spec: + redirectScheme: + scheme: https + permanent: true + +--- +apiVersion: traefik.containo.us/v1alpha1 +kind: IngressRoute +metadata: + name: http-redirect-to-https +spec: + entryPoints: + - web + routes: + - match: "Host(`{{ .Values.hostname }}`)" + kind: Rule + # We need this services clause to make the route valid. + services: + - name: codepod-ui-service + port: 80 + middlewares: + - name: redirect-https +{{- end }} diff --git a/k8s/helm-chart/values.prod.yaml b/k8s/helm-chart/values.prod.yaml index fe5bf7bb..3a451ddd 100644 --- a/k8s/helm-chart/values.prod.yaml +++ b/k8s/helm-chart/values.prod.yaml @@ -1 +1,5 @@ -hostname: "app.codepod.io" \ No newline at end of file +hostname: "app.codepod.io" + +ingress: + tls: + secretName: app-codepod-io-tls \ No newline at end of file