diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..289f553 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +tmp/ +pkg/secrets/ diff --git a/.sops.yaml b/.sops.yaml new file mode 100644 index 0000000..6647330 --- /dev/null +++ b/.sops.yaml @@ -0,0 +1,5 @@ +creation_rules: + - path_regex: \.yaml$ + encrypted_regex: ^(data|stringData)$ + age: >- + age1pq1sv3sp559cz4uvdynlfp3j9kr4kur56q655385d86aqrqraz8hejmrfqfwf6qrduzua3t7gap67rk0tenyj3nqu33fqana0zeugvr8y2xrgr33th48pja57wzvk9hscyg5jg9rxwk3y7dpkqmtvfkuhg6gz7xepkegu5wuxdegv2gxvk9027skh7wrjpawfdr59d6azmcwpa8ez46zv0ynkfu6xdxceqrwkxphw3wc2m6e22vxzyzzmxkqmj8qa49q5pfyveezf33varg2uvmchujrff5twfrrn4mmhwpry44p2hf5akwvuwvwdqczcd6hlghqm9fh9rlv9v27gz9u07qvvpmwyyt8z643z9zflat6lwjvpl6zmcrw4776hpqkvsyd09gwh530gvtg7qmnfky8ef8xtxpjdqskw95tydqv9n86gunwt8zf3km9g4lpjgynpgxu79nzkds39axygs982q7xeft7u5rw9vyr2hk0y3c589s9r9qtr3usy3uw4sygs56dgllwufnhmqe7zlqvf5wk73z3fl59xrw3pgys50eectrjqvzkukmtrzkjt4mdv6y35s0xefmjvsdlumg85rxyt283g4gf96yn2d6p92ue329xt6x3xxfs2p4xqw33w90qqdt9enjdxcd2tppcr9c8hxf3s2p6m4sdr5rc0r4c384ysm5f4exa63f3vpnzwy6qk2v7ymmfv3yyfwg9fgc28h2yym3xsp8y6a457zer8tk2ndmz4pu3g2wrcggg9zze4xs2vyhsf5umqykzfeptquqp3nqgplejsuemnxpuc7qvuk8t5fdn9c5rgrkuqtmxq4cv4y88lgz4tnmqdda6azsa2krupkgrksqpg0uk6lscezk86cka5hecrg9v7742uarqevlqytxv37jgf2ueyaxcccqzfzvxt3jet6kergarq2mvvdgt8x8m8n5n9qye5e2d2jw2z3n96a8d6sh0gfxzf8mk4gm7d60pa7r7tmk59ggch55s8w5p9lwpunvspdg73theqrsd9cykzkf93f95l9yw5g8ex595cxe6xy9tw67msej2vmntsad0v8tsc642kthwft6v0thelt8vktzc4e3azqjrkzkyhyyn9q2yuetx34yr65u27xvdpdrhl352rluaj2g32yxkum30sj845wx2vwqez4ztveva7g5j884d6l0rylkwz4f8jdexnnmehdxn2t759utazhnsx48984cxmncnd6cr8fpjvv4ugzefs44x0w6kyy7nzml7w2jsdgjs43k5mlent5sqqckmnpvr4y9s828t7d55jcjxfydgj2exqert9r4m7myqwehgdxgzsgmceu7uat4rpjfrag0x0gyewk7xgdyvvqp3cj44v0u24e73q47gqrma0c6n7djsrmyctv9vfr579s594ss5heg87aq08j8u6g5cs3xthtz7ckhkw0pz3h5vv06r9psrp63ggdrdq9jzrtp6vfl34dgw33nt4efyh7rrpl9psfwp6yn8rcv7acew0cecjqr6gd0s2wtt6996aapj82epyzvksenc9ew5j2xn9umh6y7jt0xsq9xz5e6v4r8xjmykapckgmq56awux29xzupu35gr9qv5crfkqzhe53dpczj930hwvrldqaq2z3g7e3tu92jqcl88ka43zxdkvwym4qacjsztl7gtv5v0juy9q0ctfd4l672wu2ps3vtypyzcpm2jyxvy093aqzpsfua2h6rycahupnxj8qstc3r0flhwx7l4vgw6vnzptvs98yp2spnqwr5y27xgu64nzdkj3pk5vdkrwuyyg78wthd3eh9qk7pzn6fl47ccrevundlq4lwlsjr7fm929cvxdp8dmyz8t45mapjvzk37yf2s7mddp0lpxzal739e5py082sq3c5wchkzc84cl4w diff --git a/README.md b/README.md index d19f7fd..ad657e9 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,25 @@ The GitOps controller is running in a constant loop and always matches the Git s flux vs ArgoCD Flux is more CLI Driven ArgoCD has a richer GUI +## Dev dependencies +- AGE +- SOPS +- Go Toolchain + +## Secrets +Some secrets are written a Go files, they must be decrypted first. +Once decrypted they show up at `./pkg/secrets/..`. Note that they are referenced in `./cmd/secrets/main.go`. + ## Flux Prerequisites: - Kubernetes Cluster -Github (giea, etc) personal access token + +### Managing secrets with SOPS +First step to manage secrets in Flux with SOPS, is to add the secret-key to Kubernetes and make it accessible to the flux system. + +To decrypt secrets use: +```sh +sops --decrypt +``` +There must be an environment variable named `SOPS_AGE_KEY_FILE` that contains the path of the AGE key text file. diff --git a/apps/hydra/linkding/deployment.yaml b/apps/hydra/linkding/deployment.yaml index bcf5d7e..dd3ca40 100644 --- a/apps/hydra/linkding/deployment.yaml +++ b/apps/hydra/linkding/deployment.yaml @@ -19,6 +19,16 @@ spec: - env: - name: LD_CSRF_TRUSTED_ORIGINS value: https://link.danicos.me + - name: LD_SUPERUSER_NAME + valueFrom: + secretKeyRef: + key: supe_user_name + name: linkding + - name: LD_SUPERUSER_PASSWORD + valueFrom: + secretKeyRef: + key: supe_user_password + name: linkding image: sissbruecker/linkding:1.45.0 name: linkding ports: diff --git a/apps/hydra/secrets/linkding.yaml b/apps/hydra/secrets/linkding.yaml new file mode 100644 index 0000000..e6c6a6a --- /dev/null +++ b/apps/hydra/secrets/linkding.yaml @@ -0,0 +1,54 @@ +apiVersion: v1 +kind: Secret +metadata: + name: linkding + namespace: linkding +stringData: + supe_user_name: ENC[AES256_GCM,data:ksT268LhGr4oMajHODGVnEw=,iv:6MNfGQdAJysxySogJIAujqCBzA/UTBqy2tAmAz15FQY=,tag:fXiDattDh0ldXvdlwiGsSg==,type:str] + supe_user_password: ENC[AES256_GCM,data:llPaiDegtQO0DzVyts854jA7a6lp7fkKluDCLN3AxTjca5YX/0jr9v+nbUM=,iv:H/vHd+aFnHXTK3idSBEeRdl/O1QAZH4ddzTfrZgYIgM=,tag:bg6p4xEtwhs7e3tB82x+jQ==,type:str] +sops: + age: + - recipient: age1pq1sv3sp559cz4uvdynlfp3j9kr4kur56q655385d86aqrqraz8hejmrfqfwf6qrduzua3t7gap67rk0tenyj3nqu33fqana0zeugvr8y2xrgr33th48pja57wzvk9hscyg5jg9rxwk3y7dpkqmtvfkuhg6gz7xepkegu5wuxdegv2gxvk9027skh7wrjpawfdr59d6azmcwpa8ez46zv0ynkfu6xdxceqrwkxphw3wc2m6e22vxzyzzmxkqmj8qa49q5pfyveezf33varg2uvmchujrff5twfrrn4mmhwpry44p2hf5akwvuwvwdqczcd6hlghqm9fh9rlv9v27gz9u07qvvpmwyyt8z643z9zflat6lwjvpl6zmcrw4776hpqkvsyd09gwh530gvtg7qmnfky8ef8xtxpjdqskw95tydqv9n86gunwt8zf3km9g4lpjgynpgxu79nzkds39axygs982q7xeft7u5rw9vyr2hk0y3c589s9r9qtr3usy3uw4sygs56dgllwufnhmqe7zlqvf5wk73z3fl59xrw3pgys50eectrjqvzkukmtrzkjt4mdv6y35s0xefmjvsdlumg85rxyt283g4gf96yn2d6p92ue329xt6x3xxfs2p4xqw33w90qqdt9enjdxcd2tppcr9c8hxf3s2p6m4sdr5rc0r4c384ysm5f4exa63f3vpnzwy6qk2v7ymmfv3yyfwg9fgc28h2yym3xsp8y6a457zer8tk2ndmz4pu3g2wrcggg9zze4xs2vyhsf5umqykzfeptquqp3nqgplejsuemnxpuc7qvuk8t5fdn9c5rgrkuqtmxq4cv4y88lgz4tnmqdda6azsa2krupkgrksqpg0uk6lscezk86cka5hecrg9v7742uarqevlqytxv37jgf2ueyaxcccqzfzvxt3jet6kergarq2mvvdgt8x8m8n5n9qye5e2d2jw2z3n96a8d6sh0gfxzf8mk4gm7d60pa7r7tmk59ggch55s8w5p9lwpunvspdg73theqrsd9cykzkf93f95l9yw5g8ex595cxe6xy9tw67msej2vmntsad0v8tsc642kthwft6v0thelt8vktzc4e3azqjrkzkyhyyn9q2yuetx34yr65u27xvdpdrhl352rluaj2g32yxkum30sj845wx2vwqez4ztveva7g5j884d6l0rylkwz4f8jdexnnmehdxn2t759utazhnsx48984cxmncnd6cr8fpjvv4ugzefs44x0w6kyy7nzml7w2jsdgjs43k5mlent5sqqckmnpvr4y9s828t7d55jcjxfydgj2exqert9r4m7myqwehgdxgzsgmceu7uat4rpjfrag0x0gyewk7xgdyvvqp3cj44v0u24e73q47gqrma0c6n7djsrmyctv9vfr579s594ss5heg87aq08j8u6g5cs3xthtz7ckhkw0pz3h5vv06r9psrp63ggdrdq9jzrtp6vfl34dgw33nt4efyh7rrpl9psfwp6yn8rcv7acew0cecjqr6gd0s2wtt6996aapj82epyzvksenc9ew5j2xn9umh6y7jt0xsq9xz5e6v4r8xjmykapckgmq56awux29xzupu35gr9qv5crfkqzhe53dpczj930hwvrldqaq2z3g7e3tu92jqcl88ka43zxdkvwym4qacjsztl7gtv5v0juy9q0ctfd4l672wu2ps3vtypyzcpm2jyxvy093aqzpsfua2h6rycahupnxj8qstc3r0flhwx7l4vgw6vnzptvs98yp2spnqwr5y27xgu64nzdkj3pk5vdkrwuyyg78wthd3eh9qk7pzn6fl47ccrevundlq4lwlsjr7fm929cvxdp8dmyz8t45mapjvzk37yf2s7mddp0lpxzal739e5py082sq3c5wchkzc84cl4w + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IG1sa2VtNzY4eDI1NTE5IHZIVTI2OVlO + d291TTlYN3JFbm9oY0ViVWNuOWpiNzh6UjVvVnFkQ1RLQmFmdlNJaDRBRGN6MWVL + emllSVExelArWE4zNmtnS0RYQlU1UkZvUXRWVlgrdnhjNHBVV1dNY0lyMm1KRDBY + cHlTVGtZbkJtUlhjQk1LMFh3UGtwRVlsK3dpM0JWOEQvWGlidmcrTUlleEZOTlhJ + dFBYa2pLZVVpdDdjcDlRbjFZc1A4OTRvNHowcGR4NUIxNEVtREMyVEZiWGJXZXNy + eHA0SHptbEFEUHBDcUxGbTZwTUZFMENpOW1HWnl1clYwNjlVRm9pMFM2bytFbEFP + NFZmdTNOaVQxNlZVb1NwY2R6L2JKVVVyS3I3dVdNc3RJYWdJcklCcTFDRWZrWW4x + dHJyczVGcTVKVUV2dHZzWnNObXNSTnBqbE1SdjdMZ1NhVDRmblFkanlZQVhvRjIr + Y0VEZGxsSGVHWFhXUUQwNm5kQ1Buak8vYkYyMC95elB0Vm16M1d6U1V0NzRTOGlw + OTd1MjBIVGo1TkljRUJDbVJDTzJ0dzNBeDBISnBydUQzNlpkdVl2dHJSYW1TanVj + UFlnZis3MWtqNVhiY3FWTkVOc2dydm9BNXQwYXArMzBOcWcyTlZoRDRiR0J4Sk9w + K2FZNklpUHh6RGpVaVIvVGlkeXkxV2tBeEtoN1FRV0Rpc21xS0c3Zy9zdWRvWDVj + SVcwM2x5VnNYRGlFUk1zeGY0NEh4bG1MS2oyNTlIZG5UOE00NVBDWjlZa0pDaW1S + QlBOejQxSW9HMFNid2FRdjdVRmluMWhGQUVoR2RjbUlEbFF5eXhmVFkvaUc0cTA4 + MDNlWFBLOFR3TUdsSGlVSXY3SnhhZk4xbUR5cEVpS0pOeERrRnVPeWZpSy9hNGtB + bUhPTExxdmpKdFdkL3U0c0tCZXZhQzNrUWNlMitQb0N1ZXpZQ011SkNkTzZNUEta + aDU4aFZKdmhHR2xLanBGRWk0M3dycGlrb1NZUUNkU25mTzFCTkdjaUlZb3U2MDdN + NkFoZDVuOHBmWU42WTU1TTBMWktPRTBjajRWcmhMaUhnSWZvcTBiWStpY2RKVGpi + L0NoZmZmOVVkOU53aTYrSGMwV0FKWlJTWkFQSHJCSW1qbi9xM0hLSFhpRWVQK0Rq + bnVIbFY0NVJXK2ZRNWsxVnlSTzBpMmJhNUcwMlUyK0FKZkd2ZGZ0MHZQOWRTeHgv + RnhrdUxhSXhCYmtMcGh2UmdFYXlFSllqZnF3YnZLS3V6WjVDeElYdUpKZTY5bmF5 + K3ZoTVpUUm5TQzhlbllBV0hiTE4zbWpjc2hEMWozNGp3Zi9MOWNPNXd2c0ZOUlVt + T0pYKzRGeGJCb2N5S3kwRUNrdDNxREkrRDRFSWVMV1hYSFo2NzNLK2o2TVlNbGtI + WjBYcFZBdVlEMEtpQW1DQnZBcCtrOGlDRC8yMlZSY2t3eGdxakYzQU96UFlVZkFM + QmFmMzMwNWVkUDdRR0o0RkQzYnNmU2EvZG1iazQwbTArNDRBb3FIcGEwbVhjajZT + eXo2MThqbEFPKzkrUHpSd2hpYUR3NjZzMkE3ZmozdHJycGoxL0FjbmtGQzNOeWFE + UnZHR3F4SkV1V1htclFOZFVjZzh3VUJleWVUbDI3a1dYMld5cUttVTBoR3F1SFUv + ZTN1dmgvVU5YWnFmbnM3djA3a0VEWVdlNWoyaDgwOVlsUXpWVStVUE5PVENDaUpD + SE5wUno2dS8reFJ0ZXdLUTMySU9DV0o5RGNyanBzbFRWTUZPbU4wOVk0MGxHOHRr + ek5sVHZjTXJkWVpoQVFxOXMyMUQ4a01TL0RoeHFYZ3VlQXdxNzZhaWNuTGk3ZmVH + OFVUaXVmNUIvaXN2QUFUVktycGdGMjN0REMvL0h4d0RBMHVhL0lwUEV0Y0Z0Y2dy + VjFkdVFXeTJ5WStzRm5OeFIyM1VsV2RqY0tMSzRuQ3ZTdFltdzFxcWNpeDVmdwpN + aWFSUlYrUGhBZHc3QjRWdWlSY0xENWcrUHVzMlROWEFKQmRMU1dDcXZnCi0tLSBs + SGU1WGU2Z0lXNXZtWUlyeS91TlNiVFJPbmw3YkF1V0xFZERqMWRiYzNvCoM/4Yxa + 2CVMQrIHVcDHgJS5zjtAGU1oJ+V6uagff94KmvhoxutLDZVzMOI4RXJLqX9dhbto + y34d5A/e6B8EskY= + -----END AGE ENCRYPTED FILE----- + lastmodified: "2026-04-20T23:41:39Z" + mac: ENC[AES256_GCM,data:p0Q4Jgx+qmk3ipmdO49zZJN9Te1lJ8g+WCtRcJmvG1jq0BUxmi4tLt4Ir1u+caK0U1wpLxd0mxkI/b41Wlke5vcd+462nR3GINhGFL0QGWyHv25PmWvWnHIMvxyRA9MmMPmIHQpG/JDUWShriNmKGQwUU2BqW4u53y6M2NguMag=,iv:8BQLnW2ZBzRXawyxcAE4SGpYFx+g+OBt5sxQbsx24AM=,tag:Gj5nIJqCHwfTSU5tvjBGIQ==,type:str] + encrypted_regex: ^(data|stringData)$ + version: 3.12.2 diff --git a/clusters/hydra/apps.yaml b/clusters/hydra/apps.yaml index 694c806..1570503 100644 --- a/clusters/hydra/apps.yaml +++ b/clusters/hydra/apps.yaml @@ -4,6 +4,10 @@ metadata: name: apps namespace: flux-system spec: + decryption: + provider: sops + secretRef: + name: sops-age interval: 10m0s path: ./apps/hydra prune: true diff --git a/main.go b/cmd/apps/main.go similarity index 89% rename from main.go rename to cmd/apps/main.go index abde345..26454e8 100644 --- a/main.go +++ b/cmd/apps/main.go @@ -19,10 +19,10 @@ func main() { err := flux_stack.MarshalYamlFlat(root.FLUX_CLUSTER_HYDRA_PATH) assertNoErr(err) - hydraApps := map[string]stack.Stack{ + hydra_apps := map[string]stack.Stack{ "linkding": linkding.Stack(), } - for name, s := range hydraApps { + for name, s := range hydra_apps { fmt.Printf("STACK: %s\n", name) err = s.MarshalYaml(root.FLUX_APPS_HYDRA_PATH) assertNoErr(err) diff --git a/cmd/secrets/main.go b/cmd/secrets/main.go new file mode 100644 index 0000000..5edc81e --- /dev/null +++ b/cmd/secrets/main.go @@ -0,0 +1,22 @@ +package main + +import ( + "fmt" + "os" + + "danicos.dev/daniel/homelab/pkg/root" + "danicos.dev/daniel/homelab/pkg/secrets" +) + +func main() { + secrets_stack := secrets.Stack() + err := secrets_stack.MarshalYaml(root.TMP_FOLDER) + assertNoErr(err) +} + +func assertNoErr(err error) { + if err != nil { + fmt.Println(err.Error()) + os.Exit(1) + } +} diff --git a/magefiles/magefile.go b/magefiles/magefile.go index 226c3b2..d3fc39d 100644 --- a/magefiles/magefile.go +++ b/magefiles/magefile.go @@ -20,17 +20,27 @@ var Aliases = map[string]any{ func init() { Env := map[string]string{ - "LINUX_ADMIN": "arch", - "CLUSTER_NAME": root.HYDRA_CLUSTER, - "CLUSTER_HOST": root.HYDRA_HOSTNAME, - "GITEA_HOST": root.GITEA_HOST, + "LINUX_ADMIN": "arch", + "CLUSTER_NAME": root.HYDRA_CLUSTER, + "CLUSTER_HOST": root.HYDRA_HOSTNAME, + "GITEA_HOST": root.GITEA_HOST, + "GO_SECRETS": root.GO_SECRETS_FOLDER, + "ENC_SECRETS_PATH": root.GO_ENC_SECRETS_FOLDER, + "HYDRA_PATH": root.FLUX_APPS_HYDRA_PATH, + "SECRETS_FOLDER": root.SECRETS_FOLDER, + "HYDRA_SECRETS_PATH": root.FLUX_APPS_SECRETS_HYDRA_PATH, } r = target.NewRunner(Env, nil) } func Build() error { - t := target.NewA("go", "run", ".") - return r.RunV("run", t) + t := target.NewA("go", "run", "./cmd/apps/main.go") + return r.RunV("Build apps", t) +} + +func Build_secrets() error { + t := target.NewA("go", "run", "./cmd/secrets/main.go") + return r.RunV("Build secrets", t) } func InstallK3S() error { @@ -47,3 +57,15 @@ func InstallFlux() error { t := target.New("./scripts/install_flux.sh") return r.RunV("Install Flux", t) } + +// Uploads AGE Key to flux as a Kubernetes secret +func Enc_flux() error { + t := target.New("./scripts/encrypt_flux.sh") + return r.RunV("Upload key to flux", t) +} + +// Encrypt and decrypt Go files that contain secrets. +func Enc_Dec(opt string) error { + t := target.NewA("./scripts/enc_dec_go.sh", opt) + return r.RunV("Enc or Dec Go secrets", t) +} diff --git a/pkg/enc/linkding.go.age b/pkg/enc/linkding.go.age new file mode 100644 index 0000000..2357fcc Binary files /dev/null and b/pkg/enc/linkding.go.age differ diff --git a/pkg/enc/secrets.go.age b/pkg/enc/secrets.go.age new file mode 100644 index 0000000..cc4c877 --- /dev/null +++ b/pkg/enc/secrets.go.age @@ -0,0 +1,5 @@ +age-encryption.org/v1 +-> mlkem768x25519 cYiJfHWipORzmkN1ltuNeQ+kEmMNZsQO8WGYRNgc5Gzd33AbnzswSzfDC16dfA5xLlu9397QgmSfgRxG6xD8e7N/MFLSUZRX16wVdV6Dl7GpOF/m/0fOwhSpdKKEJKW8NrwR/Ju6CSfzKtgPGL5qsRoWBSdgOLdkA+6W3DlUwfxHArVaJMNYvHP4E5XGnaVAzFUNYkTpGgJgTBATWP8C0M2kpEARMsTNjXgDPmgvjsvk/Xo5H81S6RiqmxdHIt9gN3y/rjNlOwRFAKk3uHxzzfbW5zGRZAisy4RPRdT9G121xWJmajnFGM9bEJcalbwI6N9w8A48oJfRgOGo0ecLCBEnkEq2OHamKzEZMj6CDgByvZL49BycJQpJ9ijNykZBnCgUPaM4SsqTj9affd2gxsLNHcvLNTmN/vUqkKQXD9bllnwyJ0Pz7t5Lg/tbfDfILCzgcgWGY8KtHDjHV1OTNdoROdrW+aEI95mpqtnkT1gzzcVTZ3ozD3Glkzm8sPBwGjhpARNRpI96eeBUnpgN8dYXpQlV3Gqxl5TEsdBkiVOtII0OaQeg/iW8eh2FTU8/Dg8xjWsyen2abhImROt4TnIvqGmhesLdKguyWa/miAh8flr4CazWpB5Pk2kD+DXUIWsEQCyaZMTZRhuGIBpbguyRbOyx2rCxWWTCevTwl99TQdI1nfu8dfR9jB+DhrTnak7rwLJej0D2jD0iQQ4J1KCNP4knQfR86ujVT4A5J6uU4giA7Hu9np/+JXmZjOl0rethtaq035a405a4uBbNAPn9lzefOC2yULMxM0P8GCWbezr3k9chFCNS9bsMZh/FdgtY7kJxqJOW75zlgm/6pos0Bj45/zFwOyM71y30dOgc7Ex51cKeHRBtYtgsItrNVwkM0DfCH9VU6GgRzMVCq4RrnUT0o3xARfIFaEL3zZD/KoarhMaINEva88tvbf+zm2lDZoW1EsrT2dGKEJzMqZdqC0NjJwOrGHJwh6wy1cRdtEZrGR8zzyAfYAW0XqgfHMljJ5QRgRbqBpqrGthP+3r5fdyWA+5z2Z4cWV2nBSpV0FlPVgxGRnxNMG1zgpeBt8JdAkftgat1AvCZzgSIw1jQJP+Win5DRewK+qzBBIdkPYYawwLPOO6aeG0ahwge0pMQY17F96Y3tw5mi5fHmh+/ms7yG6CJ/4WxdxgbvX2kUpUckT5ZLoAVLn9fAm5Jg4XVyj0z1anTKD8Gjyabaogfk8bHeNZByjo7qbEYHpf/apBFEbg0vgoC85JtmiqfpegTLhHuEaux/V0xCgIfNPHPiYOTQs3Ij//8ALWn3ZBbCg2pZ4I6y0wKtI46vcuVHThy8vWL992a7v601WyfPuB2ZAYpcAy0KU3cEJTQ1Jcc5nqTpT01nVJ3MZLQ5D1Zll+l8WtPYLgTlAEc+qulXReT/Z64clLAdJrdn4wwjBAs5S2RcWWF1CKDG9HJfKFiLA/qeTJDthUYbUQt/FBZew +TIif8yenxheEYQcu8isoeyPZ4GUTSjgR/0UOALrhBo4 +--- ahXiHd/RR2JyVd0AB0/4LC5QBkPbfmuXj77awnvz/eQ +gNfL oɒ:R^9^0SJ&N%x ٥,'4!\<ӖI=D̴R]r:dp%ϴxhw-pGֺhyTLNI]j$ t1%G8Ǝ/_U?i,ΑOhnESr>٨dzί_+6u:61gnĀ9eOH * \ No newline at end of file diff --git a/pkg/flux/flux.go b/pkg/flux/flux.go index f0d2ce2..a57f4d2 100644 --- a/pkg/flux/flux.go +++ b/pkg/flux/flux.go @@ -7,6 +7,7 @@ import ( "danicos.dev/daniel/go-kube/pkg/stack" "danicos.dev/daniel/homelab/pkg/root" kz "github.com/fluxcd/kustomize-controller/api/v1" + flux_meta "github.com/fluxcd/pkg/apis/meta" meta "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -28,6 +29,12 @@ func Apps() kz.Kustomization { retryInteval := durMin(1) timeout := durMin(5) spec := kz.KustomizationSpec{ + Decryption: &kz.Decryption{ + Provider: root.FLUX_DECRYPTION_PROVIDER, + SecretRef: &flux_meta.LocalObjectReference{ + Name: "sops-age", + }, + }, Interval: durMin(10), RetryInterval: &retryInteval, Timeout: &timeout, diff --git a/pkg/linkding/linkding.go b/pkg/linkding/linkding.go index 26d2068..353229a 100644 --- a/pkg/linkding/linkding.go +++ b/pkg/linkding/linkding.go @@ -8,6 +8,16 @@ import ( core "k8s.io/api/core/v1" ) +var Secret = struct { + Name string + SuperUserKey string + SuperUserPasswordKey string +}{ + Name: root.Linkding.Name, + SuperUserKey: "supe_user_name", + SuperUserPasswordKey: "supe_user_password", +} + var meta kube.Metadata var Namespace = kube.Namespace("linkding") var srv core.Service @@ -36,6 +46,10 @@ func deployment() apps.Deployment { envMapping := map[string]string{ "LD_CSRF_TRUSTED_ORIGINS": "https://link.danicos.me", } + secretMapping := map[string]string{ + "LD_SUPERUSER_NAME": Secret.SuperUserKey, + "LD_SUPERUSER_PASSWORD": Secret.SuperUserPasswordKey, + } pod_spec := core.PodSpec{ SecurityContext: &core.PodSecurityContext{ RunAsUser: &root.Linkding.SecurityContextID, @@ -47,7 +61,7 @@ func deployment() apps.Deployment { Name: root.Linkding.Name, Image: root.Linkding.Image, SecurityContext: root.ContainerSecurityContext, - Env: kube.NewEnvVar(envMapping), + Env: kube.NewEnvVarWithSecret(envMapping, secretMapping, Secret.Name), Ports: []core.ContainerPort{{ ContainerPort: root.Linkding.Port, }}, @@ -64,4 +78,4 @@ func deployment() apps.Deployment { return kube.NewDeployment(meta, pod_spec) } -// kubectl --kubeconfig ~/.kube/hydra -n linkding exec -it linking-67f686679d-2tfrk -- python manage.py createsuperuser --username=daniel --email=danicosme@pm.me +// kubectl -n linkding exec -it linking-67f686679d-2tfrk -- python manage.py createsuperuser --username=daniel --email=danicosme@pm.me diff --git a/pkg/root/root.go b/pkg/root/root.go index 8959ae2..a970023 100644 --- a/pkg/root/root.go +++ b/pkg/root/root.go @@ -5,15 +5,21 @@ import ( ) const ( - HYDRA_CLUSTER = "hydra" - HYDRA_HOSTNAME = "hydra-0" // VPN Host - GITEA_HOST = "danicos.dev" + HYDRA_CLUSTER = "hydra" + HYDRA_HOSTNAME = "hydra-0" // VPN Host + GITEA_HOST = "danicos.dev" + TMP_FOLDER = "./tmp" + SECRETS_FOLDER = TMP_FOLDER + "/secrets" + GO_SECRETS_FOLDER = "./pkg/secrets" + GO_ENC_SECRETS_FOLDER = "./pkg/enc" ) const ( - FLUX_NAMESPACE = "flux-system" - FLUX_APPS_HYDRA_PATH = "./apps/" + HYDRA_CLUSTER - FLUX_CLUSTER_HYDRA_PATH = "./clusters/" + HYDRA_CLUSTER + FLUX_NAMESPACE = "flux-system" + FLUX_APPS_HYDRA_PATH = "./apps/" + HYDRA_CLUSTER + FLUX_APPS_SECRETS_HYDRA_PATH = "./apps/" + HYDRA_CLUSTER + "/secrets" + FLUX_CLUSTER_HYDRA_PATH = "./clusters/" + HYDRA_CLUSTER + FLUX_DECRYPTION_PROVIDER = "sops" ) var ( diff --git a/scripts/create_flux_secret.sh b/scripts/create_flux_secret.sh new file mode 100755 index 0000000..fcd6bb5 --- /dev/null +++ b/scripts/create_flux_secret.sh @@ -0,0 +1,13 @@ +#!/bin/sh + +set -eu + +if [ -z "${AGE_KEY}" ]; then + echo "unbound variable" +fi +if [ ! -f "${AGE_KEY}" ]; then + echo "Error: ${AGE_KEY} file does not exist" + exit 1 +fi + +cat $AGE_KEY | kubectl --kubeconfig ~/.kube/hydra create secret generic sops-age --namespace=flux-system --from-file=age.agekey=/dev/stdin diff --git a/scripts/enc_dec_go.sh b/scripts/enc_dec_go.sh new file mode 100755 index 0000000..980afd9 --- /dev/null +++ b/scripts/enc_dec_go.sh @@ -0,0 +1,35 @@ +#!/bin/sh + +set -eu + +if [ -z "${AGE_KEY}" ]; then + echo "unbound variable" +fi +if [ ! -f "${AGE_KEY}" ]; then + echo "Error: ${AGE_KEY} file does not exist" + exit 1 +fi + +mkdir -p $ENC_SECRETS_PATH +if [ "$1" = "enc" ]; then + for FILE in $GO_SECRETS/*; do + FILENAME="${FILE##*/}" + age --encrypt \ + --output $ENC_SECRETS_PATH/$FILENAME.age \ + --identity $AGE_KEY \ + $FILE + done +elif [ "$1" = "dec" ]; then + mkdir -p $GO_SECRETS + for FILE in $ENC_SECRETS_PATH/*; do + FILENAME="${FILE##*/}" # Cut the directories path + FILENAME="${FILENAME%.age}" # Cut the .age + echo $GO_SECRETS/$FILENAME + age --decrypt \ + --identity $AGE_KEY \ + $FILE > $GO_SECRETS/$FILENAME + done +else + echo "Error: Invalid argument. Use 'enc' or 'dec'." >&2 + exit 1 +fi diff --git a/scripts/encrypt_flux.sh b/scripts/encrypt_flux.sh new file mode 100755 index 0000000..591c0ba --- /dev/null +++ b/scripts/encrypt_flux.sh @@ -0,0 +1,24 @@ +#!/bin/sh + +set -eu + +if [ -z "${AGE_KEY}" ]; then + echo "unbound variable" +fi +if [ ! -f "${AGE_KEY}" ]; then + echo "Error: ${AGE_KEY} file does not exist" + exit 1 +fi + +PUBLIC_KEY=$(age-keygen -y $AGE_KEY) + +SECRETS_ENC_PATH=$HYDRA_SECRETS_PATH +mkdir -p $SECRETS_ENC_PATH +for FILE in $SECRETS_FOLDER/*; do + sops --encrypt --in-place $FILE + + FILENAME="${FILE##*/}" + DEST=$SECRETS_ENC_PATH/$FILENAME + echo Moving encrypted file to $DEST + mv $FILE $DEST +done diff --git a/scripts/get_kubeconfig.sh b/scripts/get_kubeconfig.sh index 614156c..f8f5acf 100755 --- a/scripts/get_kubeconfig.sh +++ b/scripts/get_kubeconfig.sh @@ -1,6 +1,6 @@ #!/bin/sh -set -euo pipefail +set -eu echo CLUSTER NAME: $CLUSTER_NAME echo HOST: $CLUSTER_HOST diff --git a/scripts/install_flux.sh b/scripts/install_flux.sh index cc96d77..52e9e4c 100755 --- a/scripts/install_flux.sh +++ b/scripts/install_flux.sh @@ -1,6 +1,6 @@ #!/bin/sh -set -euo pipefail +set -eu echo CLUSTER NAME: $CLUSTER_NAME diff --git a/scripts/install_k3s.sh b/scripts/install_k3s.sh index 560cf87..4d1891b 100755 --- a/scripts/install_k3s.sh +++ b/scripts/install_k3s.sh @@ -1,6 +1,6 @@ #!/bin/sh -set -euo pipefail +set -eu echo HOST: $CLUSTER_HOST echo USER: $LINUX_ADMIN