diff --git a/contour/resources/default_gateway.yaml b/contour/resources/default_gateway.yaml index 4876d4a..91284a5 100644 --- a/contour/resources/default_gateway.yaml +++ b/contour/resources/default_gateway.yaml @@ -17,6 +17,14 @@ spec: - kind: TCPRoute namespaces: from: All + - name: snips-ssh + protocol: TCP + port: 2222 + allowedRoutes: + kinds: + - kind: TCPRoute + namespaces: + from: All - name: http protocol: HTTP port: 80 diff --git a/fider/resources/deployment.yaml b/fider/resources/deployment.yaml index c7096a9..ea053d2 100644 --- a/fider/resources/deployment.yaml +++ b/fider/resources/deployment.yaml @@ -16,6 +16,7 @@ spec: containers: - name: fider image: docker.io/getfider/fider:stable + imagePullPolicy: Always ports: - containerPort: 3000 protocol: TCP diff --git a/snips/config/.env b/snips/config/.env new file mode 100644 index 0000000..5da691d --- /dev/null +++ b/snips/config/.env @@ -0,0 +1,6 @@ +SNIPS_DB_FILEPATH=/data/snips.db +SNIPS_SSH_HOSTKEYPATH=/etc/snips/snips +SNIPS_SSH_AUTHORIZEDKEYSPATH=/etc/snips/authorized_keys +SNIPS_HTTP_EXTERNAL=https://snips.icb4dc0.de +SNIPS_SSH_EXTERNAL=ssh://snips.icb4dc0.de:2222 +SNIPS_ENABLEGUESSER=true \ No newline at end of file diff --git a/snips/config/litestream.yml b/snips/config/litestream.yml new file mode 100644 index 0000000..6dada72 --- /dev/null +++ b/snips/config/litestream.yml @@ -0,0 +1,12 @@ +addr: ":9090" + +dbs: + - path: /data/snips.db + replicas: + - type: s3 + endpoint: https://2df513adaee2eeae12106af900bed297.r2.cloudflarestorage.com + bucket: backup + path: snips + region: us-east-1 + retention: 72h + snapshot-interval: 1h \ No newline at end of file diff --git a/snips/config/secrets.enc.yml b/snips/config/secrets.enc.yml new file mode 100644 index 0000000..947218e --- /dev/null +++ b/snips/config/secrets.enc.yml @@ -0,0 +1,40 @@ +apiVersion: v1 +kind: Secret +metadata: + name: snips-secrets +stringData: + hmackey: ENC[AES256_GCM,data:Srvw37mEYlKUGZ0ep+CBXQQ0xubkcg8ab6jJ1VK2oUC2nFDnC6oExJuoZRUlwCFfahdfju6iB8JyD9dWmWV+Hx1Kq/TlyPQREYol8XIJdqkwv7xe5CO825cU5Zirx/7650WiZpwz9kz7LG6U5HPcvlEv/AZT/wJZMGGOqdogy5E=,iv:P3OEEuuLaBLCq2Rstvhj9xThUYiOr6AUKV2b0EiPiKg=,tag:QFUgQKEsOcbEfATKeYIv1A==,type:str] + authorized_keys: ENC[AES256_GCM,data:vWIUncU3s1XUz+opHZNuNviwecQMTFP2QNIY29LnSZgrGkLb/ws/D8DrNixCgEiqMlU0V7ut58rdIaklNfQ0zc8N95DeIqdbnZora0gQ+xfrmDNMVXfgMdDzEEhKQto1yFqj75MjEsfC9riZxKoGP5tx3qjkXPqfH4tNvx+3Cwtb8m8GQukR5fq9D2K43Qb12yk0rDrEnZ3S0okBbPgmrkfCqKTv+8HrvEiuqvPIRun5Nu5lLHJKtNmfNbmfzzv8eyGJUW9CFM+2qmIIscpGeh3Est1MIk/ubSO7c2iEPMxNcmil7ZmDVJ5dU/9QTgr4M27crS8agWQ8953WJ7pNnbDHFWpTfWsnEhiK4tp4gR3EeQiFHOvdaxa32uDWi1rSBRWQzt7lK6U7fIZ4Gagi0eieogbt++HWuM3zXT+QmLwyRfA3sy4UazUazkyr+WH6ea6F3awaRQEe2og29Ghaepc21cniarZDYZcaAMMKLRqmVFL+WY3+M9YwyTeUZGvyyXHI4DB9UM//Ik1/UxK27d+tHnLpYjOsKbTmxTovi897BFUKOOajYy4YCkK/qLPSEgzm1CVReh7VhX7url/lRSx6/5421zvlx+yKmRIVcD0Hbp2xRkIso8iMRhC6tPDr2uhapyeidcv7GKOLnuSHoqEcse4HqLbnVMSGfbVBUdf9vGfOE8KEjx2bPnZPECUjPlwXgRoJ3lRfpKSJl1V3fJj3/cjwh1fUdnQa+g2D+B6MkR9lOha3pD9Aufv5iTAiNbBEgKBN8+UVZjU5chy2plkRDm3dfrccVAtfwmH3YItkDLSfKFDMRyBB6WZpwo7N9viBqQHy75bq2TJEWY7wou5+tkx9NZOQ1KTELpiedhUwK8RNU+KiIBF2/CikSeJ+5/syoo8zqyOzQ01lRPWywo/3TcUlh6JVRx6xintAkfjqRJ8/huKu8UsAZ0Jh5HXrQacpB+wWGdo52hae5DadMmf6trXxZA==,iv:FTydQ7piJuTYkhgzEImD3RWF6AwWUBkXcEFisykNlSM=,tag:FSu7srqamA4F6dtwLysRgQ==,type:str] + snips: ENC[AES256_GCM,data:qM3fmKclXaf2ebI2vz6qTFNuk2HzOO5rYHqU0M7ugffI/damdMpAbTrOe3sa8+A11RMcKWYBEABOjfGesH8f7HJj4kO6cTJ3dSQwA2c7A2NiSLLEhjARBTx7rW57eNGp2nmUCwk2LFZWSTaRyaYhZtWtj6+7Zlt/2Se/zZSuguBNZqc1erOkkErMfRGjUggMu0FhQHiwIt7isofBbBO460sx6EiDsZFGYqJLSptKfQr5FusBBRHNj2vgtki7qLowr5saS3rf+0zGT5OV0CFWMKunX2dAwoquwNWaYdLGH1Yc1E25ofoivBA0i9JLpfdwvsku3WwNxioBeIolW0YqaaDg6XFqWIXW7UAzN2bdTVHq1ln0SFpvXt4ihkYciFlLg5FAO1lAhz/rRA5XBRCDPYU44oo6KsDjnBIOsXSTkqS02cSIiKVgbMqzUChqR2mQD6pfNvpbOZ7IHiPrT4O0oD8W5S12oJnofViZj+4/B/cbf0ZsvVTGo3dmBp0moChv7Sli,iv:cHUL5DJGs8F/cQS1lTFYZUS23TP272XJ0uc8gjRDJSs=,tag:vYy8VUb9rjne2fQVs0TjWQ==,type:str] + snips.pub: ENC[AES256_GCM,data:09R5K9p5QmsBPAdM2/rDZpUja4+t2yaeqYPLQI0JkErRlF/nvdv1GbFqoOmeDL3VYejiguAevAfV+vbOgub95JF6lAH6XQSNCPVCaA+W5b588RyDZ/HAxmb/Lxwxmxb8A1L3,iv:Qa9eYBoGAGjYfwcgClGolhijnWFV/ekRr7OvLyPZFGU=,tag:GWsA3mk1pU2fKLZfattvnw==,type:str] + r2-access-key: ENC[AES256_GCM,data:eJK3BRpEdJDfShlNeUV2BAL6FDs082SsueO6gnQ+Uyk=,iv:bGPbyngp4yCxudHbRUToR8FoFWGYBKpMfg9imbcTxO8=,tag:BUEoS0o4QqCWz8AxSM7x6Q==,type:str] + r2-secret-key: ENC[AES256_GCM,data:aFRc3BO1ue4tITSDmce2Pndzqx/1fD0RnL4u+KPt52VkjtQ65WfI9LOoC4bw9OtIjNBP6iyK0SpdqMmBFEtWVg==,iv:/IEaWqgQ/eNFfxA5If5D92hDaek3DHHdVHTnsyrEfYc=,tag:HPWWp8d3TOH6US0ITIFcRg==,type:str] +sops: + kms: [] + gcp_kms: [] + azure_kv: [] + hc_vault: [] + age: + - recipient: age18e0w4jn03n66qwg8h3rjstz7g5zx2vhvz28aterkfkfetrxtpuysftp6we + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB6ZjM1Y0M1TnBlNHd2eFda + cDlqVmt5bCt2WmJ4TXhyR2J2eEFYRGVQR21zCmMvQWpsMWJIVW9IL2xZUWF1MnJn + djRnMmRFMnNEOHI5ZUMwYWtJL3Y0ZWcKLS0tIHlCRFhtV0xkTVI5SUZaT1ZoMnhu + cGVNNVpQU2JRVFVjUjRlamtteXhpd2MK7T3aBSFPit5ulg3FU49vXfvO4q2S2VQl + nb0f+QW8nyKcl1PSsquUM3G7PAg9lLxWlDnwXRxsaZQ0WUuTF0NBwQ== + -----END AGE ENCRYPTED FILE----- + - recipient: age1yssdnqk90tn6zzggmwt70krndw04yfk9hwzdac3wsgfxmttngd7q89qzjr + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBpNGFERlp1a0ZIMXVjVEFN + ems2VnV2TlZhRlBJcnMrWlhLRDV4cTVqNUhVCkREMm5BRVVrK1NJeWRpWlJCNmJl + UXh6OVhVdXNnTm5lTnlsWnVkbnpQY2cKLS0tIFlQY0VuSklLOU1aN2R4eHNEZ25J + TElVdVRyM05nRjJYMWFCL29YZyt4TjgK56s837z/U6dswH2ZSQH3PA3aJ7blAa0F + sX8koiFtwkVcnrHvdPvKqitKLot7C3fu9BRZkFfcdi4tYh1vAeKS9w== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2024-03-06T19:44:14Z" + mac: ENC[AES256_GCM,data:BwnqY1C0PCNPOoUidMvOsyjAiTnCiqktfrgPnbwsdKlFZUElccbCn9pF+e03lAjUU6f9vZ7TaEi9pcgLZ6dMIG7/FQN95XLeEyBfzbYqO0bkAdFxlZmQLX4zzrKkb8wC4kFwRz2m0HSd3+CT7W3SPdqNWGNrnsFKKip4F61Akgw=,iv:dCI+9pObu3EvtJFj/zGWYmGPqjprbZEEmMB4pJCVfk0=,tag:9TvUtXve7qfJ6u8lIluyIg==,type:str] + pgp: [] + unencrypted_regex: ^(apiVersion|metadata|kind|type)$ + version: 3.8.1 diff --git a/snips/kustomization.yaml b/snips/kustomization.yaml new file mode 100644 index 0000000..a9922c3 --- /dev/null +++ b/snips/kustomization.yaml @@ -0,0 +1,35 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +namespace: snips + +images: + - name: snips + newName: ghcr.io/robherley/snips.sh + newTag: v0.3.2 + - name: litestream + newName: litestream/litestream + newTag: "0.3" + +labels: +- includeSelectors: true + pairs: + app.kubernetes.io/instance: icb4dc0de + app.kubernetes.io/managed-by: kustomize + +resources: + - resources/namespace.yaml + - resources/statefulset.yaml + - resources/service.yaml + - resources/routes.yaml + +configMapGenerator: + - name: snips-config + envs: + - config/.env + - name: litestream-config + files: + - config/litestream.yml + +generators: + - ./secret-generator.yaml \ No newline at end of file diff --git a/snips/resources/namespace.yaml b/snips/resources/namespace.yaml new file mode 100644 index 0000000..8ac9590 --- /dev/null +++ b/snips/resources/namespace.yaml @@ -0,0 +1,7 @@ +--- +apiVersion: v1 +kind: Namespace +metadata: + name: snips + labels: + prometheus: default \ No newline at end of file diff --git a/snips/resources/routes.yaml b/snips/resources/routes.yaml new file mode 100644 index 0000000..ecc78d6 --- /dev/null +++ b/snips/resources/routes.yaml @@ -0,0 +1,48 @@ +--- +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: snips-http +spec: + parentRefs: + - name: contour + sectionName: http + namespace: projectcontour + hostnames: + - snips.icb4dc0.de + rules: + - filters: + - type: RequestRedirect + requestRedirect: + scheme: https + statusCode: 301 +--- +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: snips-https +spec: + parentRefs: + - name: contour + sectionName: https + namespace: projectcontour + hostnames: + - snips.icb4dc0.de + rules: + - backendRefs: + - name: snips + port: 8080 +--- +apiVersion: gateway.networking.k8s.io/v1alpha2 +kind: TCPRoute +metadata: + name: snips-ssh +spec: + parentRefs: + - name: contour + sectionName: snips-ssh + namespace: projectcontour + rules: + - backendRefs: + - name: snips + port: 2222 \ No newline at end of file diff --git a/snips/resources/service.yaml b/snips/resources/service.yaml new file mode 100644 index 0000000..0a9f20e --- /dev/null +++ b/snips/resources/service.yaml @@ -0,0 +1,17 @@ +--- +apiVersion: v1 +kind: Service +metadata: + name: snips +spec: + selector: + app.kubernetes.io/name: snips + ports: + - name: http + protocol: TCP + port: 8080 + targetPort: 8080 + - name: ssh + protocol: TCP + port: 2222 + targetPort: 2222 \ No newline at end of file diff --git a/snips/resources/statefulset.yaml b/snips/resources/statefulset.yaml new file mode 100644 index 0000000..b356f64 --- /dev/null +++ b/snips/resources/statefulset.yaml @@ -0,0 +1,150 @@ +--- +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: snips +spec: + replicas: 1 + serviceName: snips + selector: + matchLabels: + app.kubernetes.io/name: snips + template: + metadata: + labels: + app.kubernetes.io/name: snips + spec: + initContainers: + - name: init-litestream + image: litestream + args: ['restore', '-if-db-not-exists', '-if-replica-exists', '/data/snips.db'] + volumeMounts: + - name: data + mountPath: /data + - name: litestream-config + mountPath: /etc/litestream.yml + subPath: litestream.yml + env: + - name: LITESTREAM_ACCESS_KEY_ID + valueFrom: + secretKeyRef: + name: snips-secrets + key: r2-access-key + - name: LITESTREAM_SECRET_ACCESS_KEY + valueFrom: + secretKeyRef: + name: snips-secrets + key: r2-secret-key + containers: + - name: snips + image: snips + envFrom: + - configMapRef: + name: snips-config + env: + - name: SNIPS_HMACKEY + valueFrom: + secretKeyRef: + name: snips-secrets + key: hmackey + ports: + - containerPort: 8080 + protocol: TCP + name: http + - containerPort: 2222 + protocol: TCP + name: ssh + livenessProbe: + tcpSocket: + port: 2222 + initialDelaySeconds: 5 + periodSeconds: 5 + readinessProbe: + tcpSocket: + port: 2222 + initialDelaySeconds: 5 + periodSeconds: 5 + resources: + limits: + cpu: 100m + memory: 200Mi + requests: + cpu: 50m + memory: 50Mi + volumeMounts: + - name: snips-secrets + readOnly: true + mountPath: /etc/snips + - name: data + mountPath: /data + - name: litestream + image: litestream + args: ['replicate'] + volumeMounts: + - name: data + mountPath: /data + - name: litestream-config + mountPath: /etc/litestream.yml + subPath: litestream.yml + env: + - name: LITESTREAM_ACCESS_KEY_ID + valueFrom: + secretKeyRef: + name: snips-secrets + key: r2-access-key + - name: LITESTREAM_SECRET_ACCESS_KEY + valueFrom: + secretKeyRef: + name: snips-secrets + key: r2-secret-key + readinessProbe: + httpGet: + path: /metrics + port: 9090 + initialDelaySeconds: 5 + periodSeconds: 5 + livenessProbe: + httpGet: + path: /metrics + port: 9090 + initialDelaySeconds: 5 + periodSeconds: 5 + ports: + - name: metrics + containerPort: 9090 + affinity: + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + podAffinityTerm: + labelSelector: + matchExpressions: + - key: app.kubernetes.io/name + operator: In + values: + - snips + topologyKey: topology.kubernetes.io/zone + volumes: + - name: snips-secrets + secret: + secretName: snips-secrets + items: + - key: authorized_keys + path: authorized_keys + - key: snips + path: snips + - key: snips.pub + path: snips.pub + - name: litestream-config + configMap: + name: litestream-config + volumeClaimTemplates: + - metadata: + name: data + spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + storageClassName: r2 \ No newline at end of file diff --git a/snips/secret-generator.yaml b/snips/secret-generator.yaml new file mode 100644 index 0000000..6d9c2df --- /dev/null +++ b/snips/secret-generator.yaml @@ -0,0 +1,11 @@ +apiVersion: viaduct.ai/v1 +kind: ksops +metadata: + # Specify a name + name: snips-secret-generator + annotations: + config.kubernetes.io/function: | + exec: + path: ksops +files: + - config/secrets.enc.yml \ No newline at end of file